diff --git a/.arcconfig b/.arcconfig deleted file mode 100644 index e200298f603e5..0000000000000 --- a/.arcconfig +++ /dev/null @@ -1,8 +0,0 @@ -{ - "phabricator.uri" : "https://reviews.llvm.org/", - "repository.callsign" : "G", - "conduit_uri" : "https://reviews.llvm.org/", - "base": "git:HEAD^", - "arc.land.onto.default": "main", - "arc.land.onto": ["main"] -} diff --git a/.arclint b/.arclint deleted file mode 100644 index 27d838eb153f2..0000000000000 --- a/.arclint +++ /dev/null @@ -1,15 +0,0 @@ -{ - "linters": { - "clang-format": { - "type": "script-and-regex", - "script-and-regex.script": "bash utils/arcanist/clang-format.sh", - "script-and-regex.regex": "/^(?P[[:alpha:]]+)\n(?P[^\n]+)\n(====|(?P\\d),(?P\\d)\n(?P.*)>>>>\n(?P.*)<<<<\n)$/s", - "include": [ - "(\\.(cc|cpp|h)$)" - ], - "exclude": [ - "(^clang/test/)" - ] - } - } -} diff --git a/.clang-tidy b/.clang-tidy index 4e1cb114f43b2..9cece0de812b8 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/new-prs-labeler.yml b/.github/new-prs-labeler.yml index 8ed976fbdddc6..9a580c6d6984e 100644 --- a/.github/new-prs-labeler.yml +++ b/.github/new-prs-labeler.yml @@ -869,6 +869,9 @@ backend:SystemZ: third-party:unittests: - third-party/unittests/** +third-party:benchmark: + - third-party/benchmark/** + llvm:binary-utilities: - llvm/docs/CommandGuide/llvm-* - llvm/include/llvm/BinaryFormat/** diff --git a/.github/workflows/build-ci-container.yml b/.github/workflows/build-ci-container.yml index 3f2bf57eb8508..28fc7de2ee065 100644 --- a/.github/workflows/build-ci-container.yml +++ b/.github/workflows/build-ci-container.yml @@ -77,14 +77,18 @@ jobs: cp ./.github/workflows/containers/github-action-ci/storage.conf ~/.config/containers/storage.conf podman info + # Download the container image into /mnt/podman rather than + # $GITHUB_WORKSPACE to avoid space limitations on the default drive + # and use the permissions setup for /mnt/podman. - name: Download stage1-toolchain uses: actions/download-artifact@v4 with: name: stage1-toolchain + path: /mnt/podman - name: Load stage1-toolchain run: | - podman load -i stage1-toolchain.tar + podman load -i /mnt/podman/stage1-toolchain.tar - name: Build Container working-directory: ./.github/workflows/containers/github-action-ci/ diff --git a/.github/workflows/containers/github-action-ci/stage2.Dockerfile b/.github/workflows/containers/github-action-ci/stage2.Dockerfile index e1a06cb68a589..0ca0da87734c4 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/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h index a177178769e45..c170fa6397cc9 100644 --- a/bolt/include/bolt/Core/BinaryFunction.h +++ b/bolt/include/bolt/Core/BinaryFunction.h @@ -2056,6 +2056,14 @@ class BinaryFunction { /// Returns false if disassembly failed. Error disassemble(); + /// An external interface to register a branch while the function is in + /// disassembled state. Allows to make custom modifications to the + /// disassembler. E.g., a pre-CFG pass can add an instruction and register + /// a branch that will later be used during the CFG construction. + /// + /// Return a label at the branch destination. + MCSymbol *registerBranch(uint64_t Src, uint64_t Dst); + Error handlePCRelOperand(MCInst &Instruction, uint64_t Address, uint64_t Size); diff --git a/bolt/include/bolt/Core/ParallelUtilities.h b/bolt/include/bolt/Core/ParallelUtilities.h index 7d3af47757bce..e7b35a79acc78 100644 --- a/bolt/include/bolt/Core/ParallelUtilities.h +++ b/bolt/include/bolt/Core/ParallelUtilities.h @@ -18,6 +18,7 @@ #include "bolt/Core/MCPlusBuilder.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/ThreadPool.h" using namespace llvm; @@ -28,8 +29,6 @@ extern cl::opt TaskCount; } // namespace opts namespace llvm { -class ThreadPool; - namespace bolt { class BinaryContext; class BinaryFunction; @@ -50,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/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp index 00df42c11e223..ce4dd29f542b0 100644 --- a/bolt/lib/Core/BinaryFunction.cpp +++ b/bolt/lib/Core/BinaryFunction.cpp @@ -1445,6 +1445,16 @@ Error BinaryFunction::disassemble() { return Error::success(); } +MCSymbol *BinaryFunction::registerBranch(uint64_t Src, uint64_t Dst) { + assert(CurrentState == State::Disassembled && + "Cannot register branch unless function is in disassembled state."); + assert(containsAddress(Src) && containsAddress(Dst) && + "Cannot register external branch."); + MCSymbol *Target = getOrCreateLocalLabel(Dst); + TakenBranches.emplace_back(Src - getAddress(), Dst - getAddress()); + return Target; +} + bool BinaryFunction::scanExternalRefs() { bool Success = true; bool DisassemblyFailed = false; @@ -1759,13 +1769,6 @@ void BinaryFunction::postProcessJumpTables() { } } } - - // Remove duplicates branches. We can get a bunch of them from jump tables. - // Without doing jump table value profiling we don't have use for extra - // (duplicate) branches. - llvm::sort(TakenBranches); - auto NewEnd = std::unique(TakenBranches.begin(), TakenBranches.end()); - TakenBranches.erase(NewEnd, TakenBranches.end()); } bool BinaryFunction::validateExternallyReferencedOffsets() { @@ -2128,6 +2131,13 @@ Error BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) { // e.g. exit(3), etc. Otherwise we'll see a false fall-through // blocks. + // Remove duplicates branches. We can get a bunch of them from jump tables. + // Without doing jump table value profiling we don't have a use for extra + // (duplicate) branches. + llvm::sort(TakenBranches); + auto NewEnd = std::unique(TakenBranches.begin(), TakenBranches.end()); + TakenBranches.erase(NewEnd, TakenBranches.end()); + for (std::pair &Branch : TakenBranches) { LLVM_DEBUG(dbgs() << "registering branch [0x" << Twine::utohexstr(Branch.first) << "] -> [0x" diff --git a/bolt/lib/Core/ParallelUtilities.cpp b/bolt/lib/Core/ParallelUtilities.cpp index 1a28bc4346ecd..5f5e96e0e7881 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/Core/Relocation.cpp b/bolt/lib/Core/Relocation.cpp index ded497f3c0611..cbf95a7db08b5 100644 --- a/bolt/lib/Core/Relocation.cpp +++ b/bolt/lib/Core/Relocation.cpp @@ -381,6 +381,14 @@ static uint64_t encodeValueAArch64(uint64_t Type, uint64_t Value, uint64_t PC) { // OP 1001_01 goes in bits 31:26 of BL. Value = ((Value >> 2) & 0x3ffffff) | 0x94000000ULL; break; + case ELF::R_AARCH64_JUMP26: + Value -= PC; + assert(isInt<28>(Value) && + "only PC +/- 128MB is allowed for direct branch"); + // Immediate goes in bits 25:0 of B. + // OP 0001_01 goes in bits 31:26 of B. + Value = ((Value >> 2) & 0x3ffffff) | 0x14000000ULL; + break; } return Value; } diff --git a/bolt/lib/Passes/IdenticalCodeFolding.cpp b/bolt/lib/Passes/IdenticalCodeFolding.cpp index 9f8d82b05ccf4..87eba10354a37 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 ca9d24245ceb1..85c2397dcc5b2 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 0d7dc1070ce75..a78397199972c 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,28 @@ 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)); + 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 +144,19 @@ 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; + /// 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,9 +166,6 @@ 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(); @@ -174,6 +194,12 @@ class LinuxKernelRewriter final : public MetadataRewriter { Error readStaticCalls(); Error rewriteStaticCalls(); + Error readExceptionTable(); + Error rewriteExceptionTable(); + + /// Paravirtual instruction patch sites. + Error readParaInstructions(); + /// Mark instructions referenced by kernel metadata. Error markInstructions(); @@ -192,6 +218,12 @@ class LinuxKernelRewriter final : public MetadataRewriter { if (Error E = readStaticCalls()) return E; + if (Error E = readExceptionTable()) + return E; + + if (Error E = readParaInstructions()) + return E; + return Error::success(); } @@ -203,6 +235,11 @@ class LinuxKernelRewriter final : public MetadataRewriter { } 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,7 +286,6 @@ void LinuxKernelRewriter::insertLKMarker(uint64_t PC, uint64_t SectionOffset, } void LinuxKernelRewriter::processLKSections() { - processLKExTable(); processLKPCIFixup(); processLKKSymtab(); processLKKSymtab(true); @@ -257,69 +293,6 @@ void LinuxKernelRewriter::processLKSections() { 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 @@ -943,6 +916,187 @@ 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"); + + ++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"); + + ++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(); +} + } // namespace std::unique_ptr diff --git a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp index c1c09c70ab01d..9efb428a6e1ba 100644 --- a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp +++ b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp @@ -1629,6 +1629,9 @@ class AArch64MCPlusBuilder : public MCPlusBuilder { uint64_t RelType; if (Fixup.getKind() == MCFixupKind(AArch64::fixup_aarch64_pcrel_call26)) RelType = ELF::R_AARCH64_CALL26; + else if (Fixup.getKind() == + MCFixupKind(AArch64::fixup_aarch64_pcrel_branch26)) + RelType = ELF::R_AARCH64_JUMP26; else if (FKI.Flags & MCFixupKindInfo::FKF_IsPCRel) { switch (FKI.TargetSize) { default: diff --git a/bolt/test/X86/linux-exceptions.s b/bolt/test/X86/linux-exceptions.s new file mode 100644 index 0000000000000..20b8c965f853a --- /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 0000000000000..4bdfde5fb7f24 --- /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/tools/merge-fdata/merge-fdata.cpp b/bolt/tools/merge-fdata/merge-fdata.cpp index c6dfd3cfdc56d..f2ac5ad4492ee 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/bolt/unittests/Core/BinaryContext.cpp b/bolt/unittests/Core/BinaryContext.cpp index 94ee65e63a1dc..08619eccdd75a 100644 --- a/bolt/unittests/Core/BinaryContext.cpp +++ b/bolt/unittests/Core/BinaryContext.cpp @@ -104,6 +104,49 @@ TEST_P(BinaryContextTester, FlushPendingRelocCALL26) { EXPECT_FALSE(memcmp(Func2Call, &Vect[12], 4)) << "Wrong forward call value\n"; } +TEST_P(BinaryContextTester, FlushPendingRelocJUMP26) { + if (GetParam() != Triple::aarch64) + GTEST_SKIP(); + + // This test checks that encodeValueAArch64 used by flushPendingRelocations + // returns correctly encoded values for R_AARCH64_JUMP26 relocation for both + // backward and forward branches. + // + // The offsets layout is: + // 4: func1 + // 8: b func1 + // 12: b func2 + // 16: func2 + + const uint64_t Size = 20; + char *Data = new char[Size]; + BinarySection &BS = BC->registerOrUpdateSection( + ".text", ELF::SHT_PROGBITS, ELF::SHF_EXECINSTR | ELF::SHF_ALLOC, + (uint8_t *)Data, Size, 4); + MCSymbol *RelSymbol1 = BC->getOrCreateGlobalSymbol(4, "Func1"); + ASSERT_TRUE(RelSymbol1); + BS.addRelocation(8, RelSymbol1, ELF::R_AARCH64_JUMP26, 0, 0, true); + MCSymbol *RelSymbol2 = BC->getOrCreateGlobalSymbol(16, "Func2"); + ASSERT_TRUE(RelSymbol2); + BS.addRelocation(12, RelSymbol2, ELF::R_AARCH64_JUMP26, 0, 0, true); + + std::error_code EC; + SmallVector Vect(Size); + raw_svector_ostream OS(Vect); + + BS.flushPendingRelocations(OS, [&](const MCSymbol *S) { + return S == RelSymbol1 ? 4 : S == RelSymbol2 ? 16 : 0; + }); + + const uint8_t Func1Call[4] = {255, 255, 255, 23}; + const uint8_t Func2Call[4] = {1, 0, 0, 20}; + + EXPECT_FALSE(memcmp(Func1Call, &Vect[8], 4)) + << "Wrong backward branch value\n"; + EXPECT_FALSE(memcmp(Func2Call, &Vect[12], 4)) + << "Wrong forward branch value\n"; +} + #endif TEST_P(BinaryContextTester, BaseAddress) { diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp index 22bdb5de22d87..21b581fa6df2e 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 b2d0efecc2069..298b02e77cb0a 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/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp index a8a23b045f80b..e518a64abc52e 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 @@ class BugproneModule : public ClangTidyModule { "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 1cd6fb207d762..638fba03a4358 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 0000000000000..6175fcdfd229c --- /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 0000000000000..785116218f468 --- /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 05012c7df6a97..b4bf85c912c3c 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp @@ -33,98 +33,98 @@ AST_MATCHER_P(FunctionDecl, isInstantiatedFrom, Matcher, 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;" @@ -133,36 +133,36 @@ UnusedReturnValueCheck::UnusedReturnValueCheck(llvm::StringRef Name, "::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)), + anyOf(isInstantiatedFrom(matchers::matchesAnyListedName( + CheckedFunctions)), returns(hasCanonicalType(hasDeclaration( namedDecl(matchers::matchesAnyListedName( CheckedReturnTypes))))))))) diff --git a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.h b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.h index ab2cc691b894f..d65a567e1c468 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.h @@ -29,14 +29,14 @@ class UnusedReturnValueCheck : public ClangTidyCheck { } 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 c5b6b541096ca..b91ad0f182295 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 c633683570f74..87fd8adf99708 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/google/ExplicitConstructorCheck.cpp b/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp index 34d49af9f81e2..6f26de9881357 100644 --- a/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/ExplicitConstructorCheck.cpp @@ -79,8 +79,10 @@ static bool isStdInitializerList(QualType Type) { } void ExplicitConstructorCheck::check(const MatchFinder::MatchResult &Result) { - constexpr char WarningMessage[] = + constexpr char NoExpressionWarningMessage[] = "%0 must be marked explicit to avoid unintentional implicit conversions"; + constexpr char WithExpressionWarningMessage[] = + "%0 explicit expression evaluates to 'false'"; if (const auto *Conversion = Result.Nodes.getNodeAs("conversion")) { @@ -91,7 +93,7 @@ void ExplicitConstructorCheck::check(const MatchFinder::MatchResult &Result) { // gmock to define matchers). if (Loc.isMacroID()) return; - diag(Loc, WarningMessage) + diag(Loc, NoExpressionWarningMessage) << Conversion << FixItHint::CreateInsertion(Loc, "explicit "); return; } @@ -101,9 +103,11 @@ void ExplicitConstructorCheck::check(const MatchFinder::MatchResult &Result) { Ctor->getMinRequiredArguments() > 1) return; + const ExplicitSpecifier ExplicitSpec = Ctor->getExplicitSpecifier(); + bool TakesInitializerList = isStdInitializerList( Ctor->getParamDecl(0)->getType().getNonReferenceType()); - if (Ctor->isExplicit() && + if (ExplicitSpec.isExplicit() && (Ctor->isCopyOrMoveConstructor() || TakesInitializerList)) { auto IsKwExplicit = [](const Token &Tok) { return Tok.is(tok::raw_identifier) && @@ -130,18 +134,31 @@ void ExplicitConstructorCheck::check(const MatchFinder::MatchResult &Result) { return; } - if (Ctor->isExplicit() || Ctor->isCopyOrMoveConstructor() || + if (ExplicitSpec.isExplicit() || Ctor->isCopyOrMoveConstructor() || TakesInitializerList) return; - bool SingleArgument = + // Don't complain about explicit(false) or dependent expressions + const Expr *ExplicitExpr = ExplicitSpec.getExpr(); + if (ExplicitExpr) { + ExplicitExpr = ExplicitExpr->IgnoreImplicit(); + if (isa(ExplicitExpr) || + ExplicitExpr->isInstantiationDependent()) + return; + } + + const bool SingleArgument = Ctor->getNumParams() == 1 && !Ctor->getParamDecl(0)->isParameterPack(); SourceLocation Loc = Ctor->getLocation(); - diag(Loc, WarningMessage) + auto Diag = + diag(Loc, ExplicitExpr ? WithExpressionWarningMessage + : NoExpressionWarningMessage) << (SingleArgument ? "single-argument constructors" - : "constructors that are callable with a single argument") - << FixItHint::CreateInsertion(Loc, "explicit "); + : "constructors that are callable with a single argument"); + + if (!ExplicitExpr) + Diag << FixItHint::CreateInsertion(Loc, "explicit "); } } // namespace clang::tidy::google diff --git a/clang-tools-extra/clang-tidy/hicpp/IgnoredRemoveResultCheck.cpp b/clang-tools-extra/clang-tidy/hicpp/IgnoredRemoveResultCheck.cpp index 3410559d435f6..8020f8cd06251 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/modernize/CMakeLists.txt b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt index 28ca52f46943a..6852db6c2ee31 100644 --- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt @@ -31,6 +31,7 @@ add_clang_library(clangTidyModernizeModule UseBoolLiteralsCheck.cpp UseConstraintsCheck.cpp UseDefaultMemberInitCheck.cpp + UseDesignatedInitializersCheck.cpp UseEmplaceCheck.cpp UseEqualsDefaultCheck.cpp UseEqualsDeleteCheck.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp index 654f4bd0c6ba4..e96cf274f58cf 100644 --- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp @@ -32,6 +32,7 @@ #include "UseBoolLiteralsCheck.h" #include "UseConstraintsCheck.h" #include "UseDefaultMemberInitCheck.h" +#include "UseDesignatedInitializersCheck.h" #include "UseEmplaceCheck.h" #include "UseEqualsDefaultCheck.h" #include "UseEqualsDeleteCheck.h" @@ -68,6 +69,8 @@ class ModernizeModule : public ClangTidyModule { CheckFactories.registerCheck("modernize-make-shared"); CheckFactories.registerCheck("modernize-make-unique"); CheckFactories.registerCheck("modernize-pass-by-value"); + CheckFactories.registerCheck( + "modernize-use-designated-initializers"); CheckFactories.registerCheck( "modernize-use-starts-ends-with"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp new file mode 100644 index 0000000000000..ebc5338d0a7bf --- /dev/null +++ b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp @@ -0,0 +1,184 @@ +//===--- UseDesignatedInitializersCheck.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 "UseDesignatedInitializersCheck.h" +#include "../utils/DesignatedInitializers.h" +#include "clang/AST/APValue.h" +#include "clang/AST/Decl.h" +#include "clang/AST/Expr.h" +#include "clang/AST/Stmt.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/ASTMatchers/ASTMatchersMacros.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Lex/Lexer.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::modernize { + +static constexpr char IgnoreSingleElementAggregatesName[] = + "IgnoreSingleElementAggregates"; +static constexpr bool IgnoreSingleElementAggregatesDefault = true; + +static constexpr char RestrictToPODTypesName[] = "RestrictToPODTypes"; +static constexpr bool RestrictToPODTypesDefault = false; + +static constexpr char IgnoreMacrosName[] = "IgnoreMacros"; +static constexpr bool IgnoreMacrosDefault = true; + +namespace { + +struct Designators { + + Designators(const InitListExpr *InitList) : InitList(InitList) { + assert(InitList->isSyntacticForm()); + }; + + unsigned size() { return getCached().size(); } + + std::optional operator[](const SourceLocation &Location) { + const auto &Designators = getCached(); + const auto Result = Designators.find(Location); + if (Result == Designators.end()) + return {}; + const llvm::StringRef Designator = Result->getSecond(); + return (Designator.front() == '.' ? Designator.substr(1) : Designator) + .trim("\0"); // Trim NULL characters appearing on Windows in the + // name. + } + +private: + using LocationToNameMap = llvm::DenseMap; + + std::optional CachedDesignators; + const InitListExpr *InitList; + + LocationToNameMap &getCached() { + return CachedDesignators ? *CachedDesignators + : CachedDesignators.emplace( + utils::getUnwrittenDesignators(InitList)); + } +}; + +unsigned getNumberOfDesignated(const InitListExpr *SyntacticInitList) { + return llvm::count_if(*SyntacticInitList, [](auto *InitExpr) { + return isa(InitExpr); + }); +} + +AST_MATCHER(CXXRecordDecl, isAggregate) { return Node.isAggregate(); } + +AST_MATCHER(CXXRecordDecl, isPOD) { return Node.isPOD(); } + +AST_MATCHER(InitListExpr, isFullyDesignated) { + if (const InitListExpr *SyntacticForm = + Node.isSyntacticForm() ? &Node : Node.getSyntacticForm()) + return getNumberOfDesignated(SyntacticForm) == SyntacticForm->getNumInits(); + return true; +} + +AST_MATCHER(InitListExpr, hasMoreThanOneElement) { + return Node.getNumInits() > 1; +} + +} // namespace + +UseDesignatedInitializersCheck::UseDesignatedInitializersCheck( + StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), IgnoreSingleElementAggregates(Options.get( + IgnoreSingleElementAggregatesName, + IgnoreSingleElementAggregatesDefault)), + RestrictToPODTypes( + Options.get(RestrictToPODTypesName, RestrictToPODTypesDefault)), + IgnoreMacros( + Options.getLocalOrGlobal(IgnoreMacrosName, IgnoreMacrosDefault)) {} + +void UseDesignatedInitializersCheck::registerMatchers(MatchFinder *Finder) { + const auto HasBaseWithFields = + hasAnyBase(hasType(cxxRecordDecl(has(fieldDecl())))); + Finder->addMatcher( + initListExpr( + hasType(cxxRecordDecl(RestrictToPODTypes ? isPOD() : isAggregate(), + unless(HasBaseWithFields)) + .bind("type")), + IgnoreSingleElementAggregates ? hasMoreThanOneElement() : anything(), + unless(isFullyDesignated())) + .bind("init"), + this); +} + +void UseDesignatedInitializersCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *InitList = Result.Nodes.getNodeAs("init"); + const auto *Type = Result.Nodes.getNodeAs("type"); + if (!Type || !InitList) + return; + const auto *SyntacticInitList = InitList->getSyntacticForm(); + if (!SyntacticInitList) + return; + Designators Designators{SyntacticInitList}; + const unsigned NumberOfDesignated = getNumberOfDesignated(SyntacticInitList); + if (SyntacticInitList->getNumInits() - NumberOfDesignated > + Designators.size()) + return; + + // If the whole initializer list is un-designated, issue only one warning and + // a single fix-it for the whole expression. + if (0 == NumberOfDesignated) { + if (IgnoreMacros && InitList->getBeginLoc().isMacroID()) + return; + { + DiagnosticBuilder Diag = + diag(InitList->getLBraceLoc(), + "use designated initializer list to initialize %0"); + Diag << Type << InitList->getSourceRange(); + for (const Stmt *InitExpr : *SyntacticInitList) { + const auto Designator = Designators[InitExpr->getBeginLoc()]; + if (Designator && !Designator->empty()) + Diag << FixItHint::CreateInsertion(InitExpr->getBeginLoc(), + ("." + *Designator + "=").str()); + } + } + diag(Type->getBeginLoc(), "aggregate type is defined here", + DiagnosticIDs::Note); + return; + } + + // In case that only a few elements are un-designated (not all as before), the + // check offers dedicated issues and fix-its for each of them. + for (const auto *InitExpr : *SyntacticInitList) { + if (isa(InitExpr)) + continue; + if (IgnoreMacros && InitExpr->getBeginLoc().isMacroID()) + continue; + const auto Designator = Designators[InitExpr->getBeginLoc()]; + if (!Designator || Designator->empty()) { + // There should always be a designator. If there's unexpectedly none, we + // at least report a generic diagnostic. + diag(InitExpr->getBeginLoc(), "use designated init expression") + << InitExpr->getSourceRange(); + } else { + diag(InitExpr->getBeginLoc(), + "use designated init expression to initialize field '%0'") + << InitExpr->getSourceRange() << *Designator + << FixItHint::CreateInsertion(InitExpr->getBeginLoc(), + ("." + *Designator + "=").str()); + } + } +} + +void UseDesignatedInitializersCheck::storeOptions( + ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, IgnoreSingleElementAggregatesName, + IgnoreSingleElementAggregates); + Options.store(Opts, RestrictToPODTypesName, RestrictToPODTypes); + Options.store(Opts, IgnoreMacrosName, IgnoreMacros); +} + +} // namespace clang::tidy::modernize diff --git a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.h b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.h new file mode 100644 index 0000000000000..0a496f51b9576 --- /dev/null +++ b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.h @@ -0,0 +1,40 @@ +//===--- UseDesignatedInitializersCheck.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_MODERNIZE_USEDESIGNATEDINITIALIZERSCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USEDESIGNATEDINITIALIZERSCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::modernize { + +/// Finds initializer lists for aggregate type that could be +/// written as designated initializers instead. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/modernize/use-designated-initializers.html +class UseDesignatedInitializersCheck : public ClangTidyCheck { +public: + UseDesignatedInitializersCheck(StringRef Name, ClangTidyContext *Context); + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + + std::optional getCheckTraversalKind() const override { + return TK_IgnoreUnlessSpelledInSource; + } + +private: + bool IgnoreSingleElementAggregates; + bool RestrictToPODTypes; + bool IgnoreMacros; +}; + +} // namespace clang::tidy::modernize + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USEDESIGNATEDINITIALIZERSCHECK_H diff --git a/clang-tools-extra/clang-tidy/utils/CMakeLists.txt b/clang-tools-extra/clang-tidy/utils/CMakeLists.txt index 88638d4acd556..f0160fa9df748 100644 --- a/clang-tools-extra/clang-tidy/utils/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/utils/CMakeLists.txt @@ -7,6 +7,7 @@ add_clang_library(clangTidyUtils Aliasing.cpp ASTUtils.cpp DeclRefExprUtils.cpp + DesignatedInitializers.cpp ExceptionAnalyzer.cpp ExceptionSpecAnalyzer.cpp ExprSequence.cpp diff --git a/clang-tools-extra/clang-tidy/utils/DesignatedInitializers.cpp b/clang-tools-extra/clang-tidy/utils/DesignatedInitializers.cpp new file mode 100644 index 0000000000000..6faeb7a0b76e1 --- /dev/null +++ b/clang-tools-extra/clang-tidy/utils/DesignatedInitializers.cpp @@ -0,0 +1,195 @@ +//===--- DesignatedInitializers.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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file provides utilities for designated initializers. +/// +//===----------------------------------------------------------------------===// + +#include "DesignatedInitializers.h" +#include "clang/AST/DeclCXX.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/ScopeExit.h" + +namespace clang::tidy::utils { + +namespace { + +/// Returns true if Name is reserved, like _Foo or __Vector_base. +static inline bool isReservedName(llvm::StringRef Name) { + // This doesn't catch all cases, but the most common. + return Name.size() >= 2 && Name[0] == '_' && + (isUppercase(Name[1]) || Name[1] == '_'); +} + +// Helper class to iterate over the designator names of an aggregate type. +// +// For an array type, yields [0], [1], [2]... +// For aggregate classes, yields null for each base, then .field1, .field2, +// ... +class AggregateDesignatorNames { +public: + AggregateDesignatorNames(QualType T) { + if (!T.isNull()) { + T = T.getCanonicalType(); + if (T->isArrayType()) { + IsArray = true; + Valid = true; + return; + } + if (const RecordDecl *RD = T->getAsRecordDecl()) { + Valid = true; + FieldsIt = RD->field_begin(); + FieldsEnd = RD->field_end(); + if (const auto *CRD = llvm::dyn_cast(RD)) { + BasesIt = CRD->bases_begin(); + BasesEnd = CRD->bases_end(); + Valid = CRD->isAggregate(); + } + OneField = Valid && BasesIt == BasesEnd && FieldsIt != FieldsEnd && + std::next(FieldsIt) == FieldsEnd; + } + } + } + // Returns false if the type was not an aggregate. + operator bool() { return Valid; } + // Advance to the next element in the aggregate. + void next() { + if (IsArray) + ++Index; + else if (BasesIt != BasesEnd) + ++BasesIt; + else if (FieldsIt != FieldsEnd) + ++FieldsIt; + } + // Print the designator to Out. + // Returns false if we could not produce a designator for this element. + bool append(std::string &Out, bool ForSubobject) { + if (IsArray) { + Out.push_back('['); + Out.append(std::to_string(Index)); + Out.push_back(']'); + return true; + } + if (BasesIt != BasesEnd) + return false; // Bases can't be designated. Should we make one up? + if (FieldsIt != FieldsEnd) { + llvm::StringRef FieldName; + if (const IdentifierInfo *II = FieldsIt->getIdentifier()) + FieldName = II->getName(); + + // For certain objects, their subobjects may be named directly. + if (ForSubobject && + (FieldsIt->isAnonymousStructOrUnion() || + // std::array x = {1,2,3}. Designators not strictly valid! + (OneField && isReservedName(FieldName)))) + return true; + + if (!FieldName.empty() && !isReservedName(FieldName)) { + Out.push_back('.'); + Out.append(FieldName.begin(), FieldName.end()); + return true; + } + return false; + } + return false; + } + +private: + bool Valid = false; + bool IsArray = false; + bool OneField = false; // e.g. std::array { T __elements[N]; } + unsigned Index = 0; + CXXRecordDecl::base_class_const_iterator BasesIt; + CXXRecordDecl::base_class_const_iterator BasesEnd; + RecordDecl::field_iterator FieldsIt; + RecordDecl::field_iterator FieldsEnd; +}; + +// Collect designator labels describing the elements of an init list. +// +// This function contributes the designators of some (sub)object, which is +// represented by the semantic InitListExpr Sem. +// This includes any nested subobjects, but *only* if they are part of the +// same original syntactic init list (due to brace elision). In other words, +// it may descend into subobjects but not written init-lists. +// +// For example: struct Outer { Inner a,b; }; struct Inner { int x, y; } +// Outer o{{1, 2}, 3}; +// This function will be called with Sem = { {1, 2}, {3, ImplicitValue} } +// It should generate designators '.a:' and '.b.x:'. +// '.a:' is produced directly without recursing into the written sublist. +// (The written sublist will have a separate collectDesignators() call later). +// Recursion with Prefix='.b' and Sem = {3, ImplicitValue} produces '.b.x:'. +void collectDesignators(const InitListExpr *Sem, + llvm::DenseMap &Out, + const llvm::DenseSet &NestedBraces, + std::string &Prefix) { + if (!Sem || Sem->isTransparent()) + return; + assert(Sem->isSemanticForm()); + + // The elements of the semantic form all correspond to direct subobjects of + // the aggregate type. `Fields` iterates over these subobject names. + AggregateDesignatorNames Fields(Sem->getType()); + if (!Fields) + return; + for (const Expr *Init : Sem->inits()) { + auto Next = llvm::make_scope_exit([&, Size(Prefix.size())] { + Fields.next(); // Always advance to the next subobject name. + Prefix.resize(Size); // Erase any designator we appended. + }); + // Skip for a broken initializer or if it is a "hole" in a subobject that + // was not explicitly initialized. + if (!Init || llvm::isa(Init)) + continue; + + const auto *BraceElidedSubobject = llvm::dyn_cast(Init); + if (BraceElidedSubobject && + NestedBraces.contains(BraceElidedSubobject->getLBraceLoc())) + BraceElidedSubobject = nullptr; // there were braces! + + if (!Fields.append(Prefix, BraceElidedSubobject != nullptr)) + continue; // no designator available for this subobject + if (BraceElidedSubobject) { + // If the braces were elided, this aggregate subobject is initialized + // inline in the same syntactic list. + // Descend into the semantic list describing the subobject. + // (NestedBraces are still correct, they're from the same syntactic + // list). + collectDesignators(BraceElidedSubobject, Out, NestedBraces, Prefix); + continue; + } + Out.try_emplace(Init->getBeginLoc(), Prefix); + } +} + +} // namespace + +llvm::DenseMap +getUnwrittenDesignators(const InitListExpr *Syn) { + assert(Syn->isSyntacticForm()); + + // collectDesignators needs to know which InitListExprs in the semantic tree + // were actually written, but InitListExpr::isExplicit() lies. + // Instead, record where braces of sub-init-lists occur in the syntactic form. + llvm::DenseSet NestedBraces; + for (const Expr *Init : Syn->inits()) + if (auto *Nested = llvm::dyn_cast(Init)) + NestedBraces.insert(Nested->getLBraceLoc()); + + // Traverse the semantic form to find the designators. + // We use their SourceLocation to correlate with the syntactic form later. + llvm::DenseMap Designators; + std::string EmptyPrefix; + collectDesignators(Syn->isSemanticForm() ? Syn : Syn->getSemanticForm(), + Designators, NestedBraces, EmptyPrefix); + return Designators; +} + +} // namespace clang::tidy::utils diff --git a/clang-tools-extra/clang-tidy/utils/DesignatedInitializers.h b/clang-tools-extra/clang-tidy/utils/DesignatedInitializers.h new file mode 100644 index 0000000000000..a6cb2963faf72 --- /dev/null +++ b/clang-tools-extra/clang-tidy/utils/DesignatedInitializers.h @@ -0,0 +1,42 @@ +//===--- DesignatedInitializers.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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file provides utilities for designated initializers. +/// +//===----------------------------------------------------------------------===// + +#include "clang/AST/Expr.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/DenseMap.h" + +namespace clang::tidy::utils { + +/// Get designators describing the elements of a (syntactic) init list. +/// +/// Given for example the type +/// \code +/// struct S { int i, j; }; +/// \endcode +/// and the definition +/// \code +/// S s{1, 2}; +/// \endcode +/// calling `getUnwrittenDesignators` for the initializer list expression +/// `{1, 2}` would produce the map `{loc(1): ".i", loc(2): ".j"}`. +/// +/// It does not produce designators for any explicitly-written nested lists, +/// e.g. `{1, .j=2}` would only return `{loc(1): ".i"}`. +/// +/// It also considers structs with fields of record types like +/// `struct T { S s; };`. In this case, there would be designators of the +/// form `.s.i` and `.s.j` in the returned map. +llvm::DenseMap +getUnwrittenDesignators(const clang::InitListExpr *Syn); + +} // namespace clang::tidy::utils diff --git a/clang-tools-extra/clangd/CMakeLists.txt b/clang-tools-extra/clangd/CMakeLists.txt index 3911fb6c6c746..f49704157880d 100644 --- a/clang-tools-extra/clangd/CMakeLists.txt +++ b/clang-tools-extra/clangd/CMakeLists.txt @@ -182,6 +182,7 @@ target_link_libraries(clangDaemon clangIncludeCleaner clangPseudo clangTidy + clangTidyUtils clangdSupport ) diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp index 3f9fd01281942..2907e3ba3c303 100644 --- a/clang-tools-extra/clangd/ClangdServer.cpp +++ b/clang-tools-extra/clangd/ClangdServer.cpp @@ -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); 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); }; diff --git a/clang-tools-extra/clangd/FindSymbols.cpp b/clang-tools-extra/clangd/FindSymbols.cpp index 5b3e46a7b4dc1..5244a4e893769 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/HeuristicResolver.cpp b/clang-tools-extra/clangd/HeuristicResolver.cpp index 3c147b6b582bf..26d54200eeffd 100644 --- a/clang-tools-extra/clangd/HeuristicResolver.cpp +++ b/clang-tools-extra/clangd/HeuristicResolver.cpp @@ -16,6 +16,80 @@ namespace clang { namespace clangd { +namespace { + +// Helper class for implementing HeuristicResolver. +// Unlike HeuristicResolver which is a long-lived class, +// a new instance of this class is created for every external +// call into a HeuristicResolver operation. That allows this +// class to store state that's local to such a top-level call, +// particularly "recursion protection sets" that keep track of +// nodes that have already been seen to avoid infinite recursion. +class HeuristicResolverImpl { +public: + HeuristicResolverImpl(ASTContext &Ctx) : Ctx(Ctx) {} + + // These functions match the public interface of HeuristicResolver + // (but aren't const since they may modify the recursion protection sets). + std::vector + resolveMemberExpr(const CXXDependentScopeMemberExpr *ME); + std::vector + resolveDeclRefExpr(const DependentScopeDeclRefExpr *RE); + std::vector resolveTypeOfCallExpr(const CallExpr *CE); + std::vector resolveCalleeOfCallExpr(const CallExpr *CE); + std::vector + resolveUsingValueDecl(const UnresolvedUsingValueDecl *UUVD); + std::vector + resolveDependentNameType(const DependentNameType *DNT); + std::vector resolveTemplateSpecializationType( + const DependentTemplateSpecializationType *DTST); + const Type *resolveNestedNameSpecifierToType(const NestedNameSpecifier *NNS); + const Type *getPointeeType(const Type *T); + +private: + ASTContext &Ctx; + + // Recursion protection sets + llvm::SmallSet SeenDependentNameTypes; + + // Given a tag-decl type and a member name, heuristically resolve the + // name to one or more declarations. + // The current heuristic is simply to look up the name in the primary + // template. This is a heuristic because the template could potentially + // have specializations that declare different members. + // Multiple declarations could be returned if the name is overloaded + // (e.g. an overloaded method in the primary template). + // This heuristic will give the desired answer in many cases, e.g. + // for a call to vector::size(). + std::vector + resolveDependentMember(const Type *T, DeclarationName Name, + llvm::function_ref Filter); + + // Try to heuristically resolve the type of a possibly-dependent expression + // `E`. + const Type *resolveExprToType(const Expr *E); + std::vector resolveExprToDecls(const Expr *E); + + // Helper function for HeuristicResolver::resolveDependentMember() + // which takes a possibly-dependent type `T` and heuristically + // resolves it to a CXXRecordDecl in which we can try name lookup. + CXXRecordDecl *resolveTypeToRecordDecl(const Type *T); + + // This is a reimplementation of CXXRecordDecl::lookupDependentName() + // so that the implementation can call into other HeuristicResolver helpers. + // FIXME: Once HeuristicResolver is upstreamed to the clang libraries + // (https://github.com/clangd/clangd/discussions/1662), + // CXXRecordDecl::lookupDepenedentName() can be removed, and its call sites + // can be modified to benefit from the more comprehensive heuristics offered + // by HeuristicResolver instead. + std::vector + lookupDependentName(CXXRecordDecl *RD, DeclarationName Name, + llvm::function_ref Filter); + bool findOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, + DeclarationName Name); +}; + // Convenience lambdas for use as the 'Filter' parameter of // HeuristicResolver::resolveDependentMember(). const auto NoFilter = [](const NamedDecl *D) { return true; }; @@ -31,8 +105,6 @@ const auto TemplateFilter = [](const NamedDecl *D) { return isa(D); }; -namespace { - const Type *resolveDeclsToType(const std::vector &Decls, ASTContext &Ctx) { if (Decls.size() != 1) // Names an overload set -- just bail. @@ -46,12 +118,10 @@ const Type *resolveDeclsToType(const std::vector &Decls, return nullptr; } -} // namespace - // Helper function for HeuristicResolver::resolveDependentMember() // which takes a possibly-dependent type `T` and heuristically // resolves it to a CXXRecordDecl in which we can try name lookup. -CXXRecordDecl *HeuristicResolver::resolveTypeToRecordDecl(const Type *T) const { +CXXRecordDecl *HeuristicResolverImpl::resolveTypeToRecordDecl(const Type *T) { assert(T); // Unwrap type sugar such as type aliases. @@ -84,7 +154,7 @@ CXXRecordDecl *HeuristicResolver::resolveTypeToRecordDecl(const Type *T) const { return TD->getTemplatedDecl(); } -const Type *HeuristicResolver::getPointeeType(const Type *T) const { +const Type *HeuristicResolverImpl::getPointeeType(const Type *T) { if (!T) return nullptr; @@ -117,8 +187,8 @@ const Type *HeuristicResolver::getPointeeType(const Type *T) const { return FirstArg.getAsType().getTypePtrOrNull(); } -std::vector HeuristicResolver::resolveMemberExpr( - const CXXDependentScopeMemberExpr *ME) const { +std::vector HeuristicResolverImpl::resolveMemberExpr( + const CXXDependentScopeMemberExpr *ME) { // If the expression has a qualifier, try resolving the member inside the // qualifier's type. // Note that we cannot use a NonStaticFilter in either case, for a couple @@ -164,14 +234,14 @@ std::vector HeuristicResolver::resolveMemberExpr( return resolveDependentMember(BaseType, ME->getMember(), NoFilter); } -std::vector HeuristicResolver::resolveDeclRefExpr( - const DependentScopeDeclRefExpr *RE) const { +std::vector +HeuristicResolverImpl::resolveDeclRefExpr(const DependentScopeDeclRefExpr *RE) { return resolveDependentMember(RE->getQualifier()->getAsType(), RE->getDeclName(), StaticFilter); } std::vector -HeuristicResolver::resolveTypeOfCallExpr(const CallExpr *CE) const { +HeuristicResolverImpl::resolveTypeOfCallExpr(const CallExpr *CE) { const auto *CalleeType = resolveExprToType(CE->getCallee()); if (!CalleeType) return {}; @@ -187,7 +257,7 @@ HeuristicResolver::resolveTypeOfCallExpr(const CallExpr *CE) const { } std::vector -HeuristicResolver::resolveCalleeOfCallExpr(const CallExpr *CE) const { +HeuristicResolverImpl::resolveCalleeOfCallExpr(const CallExpr *CE) { if (const auto *ND = dyn_cast_or_null(CE->getCalleeDecl())) { return {ND}; } @@ -195,29 +265,31 @@ HeuristicResolver::resolveCalleeOfCallExpr(const CallExpr *CE) const { return resolveExprToDecls(CE->getCallee()); } -std::vector HeuristicResolver::resolveUsingValueDecl( - const UnresolvedUsingValueDecl *UUVD) const { +std::vector HeuristicResolverImpl::resolveUsingValueDecl( + const UnresolvedUsingValueDecl *UUVD) { return resolveDependentMember(UUVD->getQualifier()->getAsType(), UUVD->getNameInfo().getName(), ValueFilter); } -std::vector HeuristicResolver::resolveDependentNameType( - const DependentNameType *DNT) const { +std::vector +HeuristicResolverImpl::resolveDependentNameType(const DependentNameType *DNT) { + if (auto [_, inserted] = SeenDependentNameTypes.insert(DNT); !inserted) + return {}; return resolveDependentMember( resolveNestedNameSpecifierToType(DNT->getQualifier()), DNT->getIdentifier(), TypeFilter); } std::vector -HeuristicResolver::resolveTemplateSpecializationType( - const DependentTemplateSpecializationType *DTST) const { +HeuristicResolverImpl::resolveTemplateSpecializationType( + const DependentTemplateSpecializationType *DTST) { return resolveDependentMember( resolveNestedNameSpecifierToType(DTST->getQualifier()), DTST->getIdentifier(), TemplateFilter); } std::vector -HeuristicResolver::resolveExprToDecls(const Expr *E) const { +HeuristicResolverImpl::resolveExprToDecls(const Expr *E) { if (const auto *ME = dyn_cast(E)) { return resolveMemberExpr(ME); } @@ -236,7 +308,7 @@ HeuristicResolver::resolveExprToDecls(const Expr *E) const { return {}; } -const Type *HeuristicResolver::resolveExprToType(const Expr *E) const { +const Type *HeuristicResolverImpl::resolveExprToType(const Expr *E) { std::vector Decls = resolveExprToDecls(E); if (!Decls.empty()) return resolveDeclsToType(Decls, Ctx); @@ -244,8 +316,8 @@ const Type *HeuristicResolver::resolveExprToType(const Expr *E) const { return E->getType().getTypePtr(); } -const Type *HeuristicResolver::resolveNestedNameSpecifierToType( - const NestedNameSpecifier *NNS) const { +const Type *HeuristicResolverImpl::resolveNestedNameSpecifierToType( + const NestedNameSpecifier *NNS) { if (!NNS) return nullptr; @@ -270,8 +342,6 @@ const Type *HeuristicResolver::resolveNestedNameSpecifierToType( return nullptr; } -namespace { - bool isOrdinaryMember(const NamedDecl *ND) { return ND->isInIdentifierNamespace(Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member); @@ -287,11 +357,9 @@ bool findOrdinaryMember(const CXXRecordDecl *RD, CXXBasePath &Path, return false; } -} // namespace - -bool HeuristicResolver::findOrdinaryMemberInDependentClasses( +bool HeuristicResolverImpl::findOrdinaryMemberInDependentClasses( const CXXBaseSpecifier *Specifier, CXXBasePath &Path, - DeclarationName Name) const { + DeclarationName Name) { CXXRecordDecl *RD = resolveTypeToRecordDecl(Specifier->getType().getTypePtr()); if (!RD) @@ -299,9 +367,9 @@ bool HeuristicResolver::findOrdinaryMemberInDependentClasses( return findOrdinaryMember(RD, Path, Name); } -std::vector HeuristicResolver::lookupDependentName( +std::vector HeuristicResolverImpl::lookupDependentName( CXXRecordDecl *RD, DeclarationName Name, - llvm::function_ref Filter) const { + llvm::function_ref Filter) { std::vector Results; // Lookup in the class. @@ -332,9 +400,9 @@ std::vector HeuristicResolver::lookupDependentName( return Results; } -std::vector HeuristicResolver::resolveDependentMember( +std::vector HeuristicResolverImpl::resolveDependentMember( const Type *T, DeclarationName Name, - llvm::function_ref Filter) const { + llvm::function_ref Filter) { if (!T) return {}; if (auto *ET = T->getAs()) { @@ -349,6 +417,44 @@ std::vector HeuristicResolver::resolveDependentMember( } return {}; } +} // namespace + +std::vector HeuristicResolver::resolveMemberExpr( + const CXXDependentScopeMemberExpr *ME) const { + return HeuristicResolverImpl(Ctx).resolveMemberExpr(ME); +} +std::vector HeuristicResolver::resolveDeclRefExpr( + const DependentScopeDeclRefExpr *RE) const { + return HeuristicResolverImpl(Ctx).resolveDeclRefExpr(RE); +} +std::vector +HeuristicResolver::resolveTypeOfCallExpr(const CallExpr *CE) const { + return HeuristicResolverImpl(Ctx).resolveTypeOfCallExpr(CE); +} +std::vector +HeuristicResolver::resolveCalleeOfCallExpr(const CallExpr *CE) const { + return HeuristicResolverImpl(Ctx).resolveCalleeOfCallExpr(CE); +} +std::vector HeuristicResolver::resolveUsingValueDecl( + const UnresolvedUsingValueDecl *UUVD) const { + return HeuristicResolverImpl(Ctx).resolveUsingValueDecl(UUVD); +} +std::vector HeuristicResolver::resolveDependentNameType( + const DependentNameType *DNT) const { + return HeuristicResolverImpl(Ctx).resolveDependentNameType(DNT); +} +std::vector +HeuristicResolver::resolveTemplateSpecializationType( + const DependentTemplateSpecializationType *DTST) const { + return HeuristicResolverImpl(Ctx).resolveTemplateSpecializationType(DTST); +} +const Type *HeuristicResolver::resolveNestedNameSpecifierToType( + const NestedNameSpecifier *NNS) const { + return HeuristicResolverImpl(Ctx).resolveNestedNameSpecifierToType(NNS); +} +const Type *HeuristicResolver::getPointeeType(const Type *T) const { + return HeuristicResolverImpl(Ctx).getPointeeType(T); +} } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/HeuristicResolver.h b/clang-tools-extra/clangd/HeuristicResolver.h index dc04123d37593..dcc063bbc4adc 100644 --- a/clang-tools-extra/clangd/HeuristicResolver.h +++ b/clang-tools-extra/clangd/HeuristicResolver.h @@ -77,43 +77,6 @@ class HeuristicResolver { private: ASTContext &Ctx; - - // Given a tag-decl type and a member name, heuristically resolve the - // name to one or more declarations. - // The current heuristic is simply to look up the name in the primary - // template. This is a heuristic because the template could potentially - // have specializations that declare different members. - // Multiple declarations could be returned if the name is overloaded - // (e.g. an overloaded method in the primary template). - // This heuristic will give the desired answer in many cases, e.g. - // for a call to vector::size(). - std::vector resolveDependentMember( - const Type *T, DeclarationName Name, - llvm::function_ref Filter) const; - - // Try to heuristically resolve the type of a possibly-dependent expression - // `E`. - const Type *resolveExprToType(const Expr *E) const; - std::vector resolveExprToDecls(const Expr *E) const; - - // Helper function for HeuristicResolver::resolveDependentMember() - // which takes a possibly-dependent type `T` and heuristically - // resolves it to a CXXRecordDecl in which we can try name lookup. - CXXRecordDecl *resolveTypeToRecordDecl(const Type *T) const; - - // This is a reimplementation of CXXRecordDecl::lookupDependentName() - // so that the implementation can call into other HeuristicResolver helpers. - // FIXME: Once HeuristicResolver is upstreamed to the clang libraries - // (https://github.com/clangd/clangd/discussions/1662), - // CXXRecordDecl::lookupDepenedentName() can be removed, and its call sites - // can be modified to benefit from the more comprehensive heuristics offered - // by HeuristicResolver instead. - std::vector lookupDependentName( - CXXRecordDecl *RD, DeclarationName Name, - llvm::function_ref Filter) const; - bool findOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, - DeclarationName Name) const; }; } // namespace clangd diff --git a/clang-tools-extra/clangd/IncludeCleaner.cpp b/clang-tools-extra/clangd/IncludeCleaner.cpp index f86a121340f7f..7375b7b086091 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); 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 b3ba3a716083e..387763de34076 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/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp index 671a9c30ffa95..a0ebc631ef828 100644 --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/clang-tools-extra/clangd/InlayHints.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// #include "InlayHints.h" +#include "../clang-tidy/utils/DesignatedInitializers.h" #include "AST.h" #include "Config.h" #include "HeuristicResolver.h" @@ -24,7 +25,6 @@ #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" @@ -42,169 +42,6 @@ namespace { // For now, inlay hints are always anchored at the left or right of their range. enum class HintSide { Left, Right }; -// Helper class to iterate over the designator names of an aggregate type. -// -// For an array type, yields [0], [1], [2]... -// For aggregate classes, yields null for each base, then .field1, .field2, ... -class AggregateDesignatorNames { -public: - AggregateDesignatorNames(QualType T) { - if (!T.isNull()) { - T = T.getCanonicalType(); - if (T->isArrayType()) { - IsArray = true; - Valid = true; - return; - } - if (const RecordDecl *RD = T->getAsRecordDecl()) { - Valid = true; - FieldsIt = RD->field_begin(); - FieldsEnd = RD->field_end(); - if (const auto *CRD = llvm::dyn_cast(RD)) { - BasesIt = CRD->bases_begin(); - BasesEnd = CRD->bases_end(); - Valid = CRD->isAggregate(); - } - OneField = Valid && BasesIt == BasesEnd && FieldsIt != FieldsEnd && - std::next(FieldsIt) == FieldsEnd; - } - } - } - // Returns false if the type was not an aggregate. - operator bool() { return Valid; } - // Advance to the next element in the aggregate. - void next() { - if (IsArray) - ++Index; - else if (BasesIt != BasesEnd) - ++BasesIt; - else if (FieldsIt != FieldsEnd) - ++FieldsIt; - } - // Print the designator to Out. - // Returns false if we could not produce a designator for this element. - bool append(std::string &Out, bool ForSubobject) { - if (IsArray) { - Out.push_back('['); - Out.append(std::to_string(Index)); - Out.push_back(']'); - return true; - } - if (BasesIt != BasesEnd) - return false; // Bases can't be designated. Should we make one up? - if (FieldsIt != FieldsEnd) { - llvm::StringRef FieldName; - if (const IdentifierInfo *II = FieldsIt->getIdentifier()) - FieldName = II->getName(); - - // For certain objects, their subobjects may be named directly. - if (ForSubobject && - (FieldsIt->isAnonymousStructOrUnion() || - // std::array x = {1,2,3}. Designators not strictly valid! - (OneField && isReservedName(FieldName)))) - return true; - - if (!FieldName.empty() && !isReservedName(FieldName)) { - Out.push_back('.'); - Out.append(FieldName.begin(), FieldName.end()); - return true; - } - return false; - } - return false; - } - -private: - bool Valid = false; - bool IsArray = false; - bool OneField = false; // e.g. std::array { T __elements[N]; } - unsigned Index = 0; - CXXRecordDecl::base_class_const_iterator BasesIt; - CXXRecordDecl::base_class_const_iterator BasesEnd; - RecordDecl::field_iterator FieldsIt; - RecordDecl::field_iterator FieldsEnd; -}; - -// Collect designator labels describing the elements of an init list. -// -// This function contributes the designators of some (sub)object, which is -// represented by the semantic InitListExpr Sem. -// This includes any nested subobjects, but *only* if they are part of the same -// original syntactic init list (due to brace elision). -// In other words, it may descend into subobjects but not written init-lists. -// -// For example: struct Outer { Inner a,b; }; struct Inner { int x, y; } -// Outer o{{1, 2}, 3}; -// This function will be called with Sem = { {1, 2}, {3, ImplicitValue} } -// It should generate designators '.a:' and '.b.x:'. -// '.a:' is produced directly without recursing into the written sublist. -// (The written sublist will have a separate collectDesignators() call later). -// Recursion with Prefix='.b' and Sem = {3, ImplicitValue} produces '.b.x:'. -void collectDesignators(const InitListExpr *Sem, - llvm::DenseMap &Out, - const llvm::DenseSet &NestedBraces, - std::string &Prefix) { - if (!Sem || Sem->isTransparent()) - return; - assert(Sem->isSemanticForm()); - - // The elements of the semantic form all correspond to direct subobjects of - // the aggregate type. `Fields` iterates over these subobject names. - AggregateDesignatorNames Fields(Sem->getType()); - if (!Fields) - return; - for (const Expr *Init : Sem->inits()) { - auto Next = llvm::make_scope_exit([&, Size(Prefix.size())] { - Fields.next(); // Always advance to the next subobject name. - Prefix.resize(Size); // Erase any designator we appended. - }); - // Skip for a broken initializer or if it is a "hole" in a subobject that - // was not explicitly initialized. - if (!Init || llvm::isa(Init)) - continue; - - const auto *BraceElidedSubobject = llvm::dyn_cast(Init); - if (BraceElidedSubobject && - NestedBraces.contains(BraceElidedSubobject->getLBraceLoc())) - BraceElidedSubobject = nullptr; // there were braces! - - if (!Fields.append(Prefix, BraceElidedSubobject != nullptr)) - continue; // no designator available for this subobject - if (BraceElidedSubobject) { - // If the braces were elided, this aggregate subobject is initialized - // inline in the same syntactic list. - // Descend into the semantic list describing the subobject. - // (NestedBraces are still correct, they're from the same syntactic list). - collectDesignators(BraceElidedSubobject, Out, NestedBraces, Prefix); - continue; - } - Out.try_emplace(Init->getBeginLoc(), Prefix); - } -} - -// Get designators describing the elements of a (syntactic) init list. -// This does not produce designators for any explicitly-written nested lists. -llvm::DenseMap -getDesignators(const InitListExpr *Syn) { - assert(Syn->isSyntacticForm()); - - // collectDesignators needs to know which InitListExprs in the semantic tree - // were actually written, but InitListExpr::isExplicit() lies. - // Instead, record where braces of sub-init-lists occur in the syntactic form. - llvm::DenseSet NestedBraces; - for (const Expr *Init : Syn->inits()) - if (auto *Nested = llvm::dyn_cast(Init)) - NestedBraces.insert(Nested->getLBraceLoc()); - - // Traverse the semantic form to find the designators. - // We use their SourceLocation to correlate with the syntactic form later. - llvm::DenseMap Designators; - std::string EmptyPrefix; - collectDesignators(Syn->isSemanticForm() ? Syn : Syn->getSemanticForm(), - Designators, NestedBraces, EmptyPrefix); - return Designators; -} - void stripLeadingUnderscores(StringRef &Name) { Name = Name.ltrim('_'); } // getDeclForType() returns the decl responsible for Type's spelling. @@ -847,14 +684,15 @@ class InlayHintVisitor : public RecursiveASTVisitor { // This is the one we will ultimately attach designators to. // It may have subobject initializers inlined without braces. The *semantic* // form of the init-list has nested init-lists for these. - // getDesignators will look at the semantic form to determine the labels. + // getUnwrittenDesignators will look at the semantic form to determine the + // labels. assert(Syn->isSyntacticForm() && "RAV should not visit implicit code!"); if (!Cfg.InlayHints.Designators) return true; if (Syn->isIdiomaticZeroInitializer(AST.getLangOpts())) return true; llvm::DenseMap Designators = - getDesignators(Syn); + tidy::utils::getUnwrittenDesignators(Syn); for (const Expr *Init : Syn->inits()) { if (llvm::isa(Init)) continue; diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp index bbb0e2c77b3f3..862f06196a710 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); } @@ -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/refactor/Rename.cpp b/clang-tools-extra/clangd/refactor/Rename.cpp index 4e135801f6853..75b30e66d6376 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/CMakeLists.txt b/clang-tools-extra/clangd/tool/CMakeLists.txt index 6c21175d7687c..4012b6401c008 100644 --- a/clang-tools-extra/clangd/tool/CMakeLists.txt +++ b/clang-tools-extra/clangd/tool/CMakeLists.txt @@ -33,6 +33,7 @@ clang_target_link_libraries(clangdMain target_link_libraries(clangdMain PRIVATE clangTidy + clangTidyUtils clangDaemon clangdRemoteIndex diff --git a/clang-tools-extra/clangd/unittests/CMakeLists.txt b/clang-tools-extra/clangd/unittests/CMakeLists.txt index 9cd195eaf164f..e432db8d0912e 100644 --- a/clang-tools-extra/clangd/unittests/CMakeLists.txt +++ b/clang-tools-extra/clangd/unittests/CMakeLists.txt @@ -175,6 +175,7 @@ target_link_libraries(ClangdTests clangIncludeCleaner clangTesting clangTidy + clangTidyUtils clangdSupport ) diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 6d387fec9b385..5721feecd58ea 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/FindSymbolsTests.cpp b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp index b1b8b4ccd184c..4276a44275f53 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/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp index 29cff68cf03b2..0af6036734ba5 100644 --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -1009,6 +1009,33 @@ TEST_F(TargetDeclTest, DependentTypes) { )cpp"; EXPECT_DECLS("DependentTemplateSpecializationTypeLoc", "template struct B"); + + // Dependent name with recursive definition. We don't expect a + // result, but we shouldn't get into a stack overflow either. + Code = R"cpp( + template + struct waldo { + typedef typename waldo::type::[[next]] type; + }; + )cpp"; + EXPECT_DECLS("DependentNameTypeLoc"); + + // Similar to above but using mutually recursive templates. + Code = R"cpp( + template + struct odd; + + template + struct even { + using type = typename odd::type::next; + }; + + template + struct odd { + using type = typename even::type::[[next]]; + }; + )cpp"; + EXPECT_DECLS("DependentNameTypeLoc"); } TEST_F(TargetDeclTest, TypedefCascade) { diff --git a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp index 7ed4a9103e1f2..142310837bd9c 100644 --- a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp +++ b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp @@ -252,7 +252,7 @@ TEST(IncludeCleaner, GenerateMissingHeaderDiags) { 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/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 3f90e7d63d6b2..1b839a35c3ed6 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -104,6 +104,18 @@ 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. + + Finds initializer lists for aggregate types that could be + written as designated initializers instead. + - New :doc:`readability-use-std-min-max ` check. @@ -134,9 +146,18 @@ 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. + +- 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 ` @@ -151,6 +172,10 @@ Changes in existing checks ` check by replacing the local option `HeaderFileExtensions` by the global option of the same name. +- Improved :doc:`google-explicit-constructor + ` check to better handle + ``C++-20`` `explicit(bool)`. + - Improved :doc:`google-global-names-in-headers ` check by replacing the local option `HeaderFileExtensions` by the global option of the same name. 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 0000000000000..afd88764b5967 --- /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 1e3c8a3268222..8d5eddbe215cb 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 @@ -10,8 +10,9 @@ 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, 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 8509292eff994..08bb5374bab1f 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 59ef69f390ee9..d03e7af688f00 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 `, @@ -287,6 +288,7 @@ Clang-Tidy Checks :doc:`modernize-use-bool-literals `, "Yes" :doc:`modernize-use-constraints `, "Yes" :doc:`modernize-use-default-member-init `, "Yes" + :doc:`modernize-use-designated-initializers `, "Yes" :doc:`modernize-use-emplace `, "Yes" :doc:`modernize-use-equals-default `, "Yes" :doc:`modernize-use-equals-delete `, "Yes" diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-designated-initializers.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-designated-initializers.rst new file mode 100644 index 0000000000000..22f50980baade --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-designated-initializers.rst @@ -0,0 +1,62 @@ +.. title:: clang-tidy - modernize-use-designated-initializers + +modernize-use-designated-initializers +===================================== + +Finds initializer lists for aggregate types which could be written as designated +initializers instead. + +With plain initializer lists, it is very easy to introduce bugs when adding new +fields in the middle of a struct or class type. The same confusion might arise +when changing the order of fields. + +C++20 supports the designated initializer syntax for aggregate types. By +applying it, we can always be sure that aggregates are constructed correctly, +because every variable being initialized is referenced by its name. + +Example: + +.. code-block:: + + struct S { int i, j; }; + +is an aggregate type that should be initialized as + +.. code-block:: + + S s{.i = 1, .j = 2}; + +instead of + +.. code-block:: + + S s{1, 2}; + +which could easily become an issue when ``i`` and ``j`` are swapped in the +declaration of ``S``. + +Even when compiling in a language version older than C++20, depending on your +compiler, designated initializers are potentially supported. Therefore, the +check is not restricted to C++20 and newer versions. Check out the options +``-Wc99-designator`` to get support for mixed designators in initializer list in +C and ``-Wc++20-designator`` for support of designated initializers in older C++ +language modes. + +Options +------- + +.. option:: IgnoreMacros + + The value `false` specifies that components of initializer lists expanded from + macros are not checked. The default value is `true`. + +.. option:: IgnoreSingleElementAggregates + + The value `false` specifies that even initializers for aggregate types with + only a single element should be checked. The default value is `true`. + +.. option:: RestrictToPODTypes + + The value `true` specifies that only Plain Old Data (POD) types shall be + checked. This makes the check applicable to even older C++ standards. The + default value is `false`. diff --git a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp index 277e6ec5b0890..878067aca0173 100644 --- a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp +++ b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp @@ -228,6 +228,11 @@ class ASTWalker : public RecursiveASTVisitor { // Mark declaration from definition as it needs type-checking. if (FD->isThisDeclarationADefinition()) report(FD->getLocation(), FD); + // Explicit specializaiton/instantiations of a function template requires + // primary template. + if (clang::isTemplateExplicitInstantiationOrSpecialization( + FD->getTemplateSpecializationKind())) + report(FD->getLocation(), FD->getPrimaryTemplate()); return true; } bool VisitVarDecl(VarDecl *VD) { diff --git a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp index e238dc3d902bb..5dc88157e13af 100644 --- a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp +++ b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp @@ -229,13 +229,9 @@ TEST(WalkAST, FunctionTemplates) { EXPECT_THAT(testWalk("template void foo(T) {}", "template void ^foo(int);"), ElementsAre()); - // FIXME: Report specialized template as used from explicit specializations. - EXPECT_THAT(testWalk("template void foo(T);", + EXPECT_THAT(testWalk("template void $explicit^foo(T);", "template<> void ^foo(int);"), - ElementsAre()); - EXPECT_THAT(testWalk("template void foo(T) {}", - "template void ^foo(T*) {}"), - ElementsAre()); + ElementsAre(Decl::FunctionTemplate)); // Implicit instantiations references most relevant template. EXPECT_THAT(testWalk(R"cpp( @@ -510,6 +506,8 @@ TEST(WalkAST, Functions) { // Definition uses declaration, not the other way around. testWalk("void $explicit^foo();", "void ^foo() {}"); testWalk("void foo() {}", "void ^foo();"); + testWalk("template void $explicit^foo();", + "template void ^foo() {}"); // Unresolved calls marks all the overloads. testWalk("void $ambiguous^foo(int); void $ambiguous^foo(char);", 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 0000000000000..cb41923df157c --- /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-custom.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/unused-return-value-custom.cpp index d3650b210ab02..3035183573ccd 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/use-after-move.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp index 00b1da1e727e4..7d9f63479a1b4 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 @@ class PR38187 { 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 20e43f04180ff..9a50eabf619bd 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/google/explicit-constructor-cxx20.cpp b/clang-tools-extra/test/clang-tidy/checkers/google/explicit-constructor-cxx20.cpp new file mode 100644 index 0000000000000..95206f1ef420c --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/google/explicit-constructor-cxx20.cpp @@ -0,0 +1,59 @@ +// RUN: %check_clang_tidy %s google-explicit-constructor %t -std=c++20-or-later + +namespace issue_81121 +{ + +static constexpr bool ConstFalse = false; +static constexpr bool ConstTrue = true; + +struct A { + explicit(true) A(int); +}; + +struct B { + explicit(false) B(int); +}; + +struct C { + explicit(ConstTrue) C(int); +}; + +struct D { + explicit(ConstFalse) D(int); + // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: single-argument constructors explicit expression evaluates to 'false' [google-explicit-constructor] +}; + +template +struct E { + explicit(true) E(int); +}; + +template +struct F { + explicit(false) F(int); +}; + +template +struct G { + explicit(ConstTrue) G(int); +}; + +template +struct H { + explicit(ConstFalse) H(int); + // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: single-argument constructors explicit expression evaluates to 'false' [google-explicit-constructor] +}; + +template +struct I { + explicit(Val > 0) I(int); +}; + +template +struct J { + explicit(Val > 0) J(int); +}; + +void useJ(J<0>, J<100>); + +} // namespace issue_81121 diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp new file mode 100644 index 0000000000000..7e5c26e3f4404 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp @@ -0,0 +1,203 @@ +// RUN: %check_clang_tidy -std=c++17 %s modernize-use-designated-initializers %t \ +// RUN: -- \ +// RUN: -- -fno-delayed-template-parsing +// RUN: %check_clang_tidy -check-suffixes=,SINGLE-ELEMENT -std=c++17 %s modernize-use-designated-initializers %t \ +// RUN: -- -config="{CheckOptions: {modernize-use-designated-initializers.IgnoreSingleElementAggregates: false}}" \ +// RUN: -- -fno-delayed-template-parsing +// RUN: %check_clang_tidy -check-suffixes=POD -std=c++17 %s modernize-use-designated-initializers %t \ +// RUN: -- -config="{CheckOptions: {modernize-use-designated-initializers.RestrictToPODTypes: true}}" \ +// RUN: -- -fno-delayed-template-parsing +// RUN: %check_clang_tidy -check-suffixes=,MACROS -std=c++17 %s modernize-use-designated-initializers %t \ +// RUN: -- -config="{CheckOptions: {modernize-use-designated-initializers.IgnoreMacros: false}}" \ +// RUN: -- -fno-delayed-template-parsing + +struct S1 {}; + +S1 s11{}; +S1 s12 = {}; +S1 s13(); +S1 s14; + +struct S2 { int i, j; }; + +S2 s21{.i=1, .j =2}; + +S2 s22 = {1, 2}; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use designated initializer list to initialize 'S2' [modernize-use-designated-initializers] +// CHECK-MESSAGES: :[[@LINE-6]]:1: note: aggregate type is defined here +// CHECK-MESSAGES-POD: :[[@LINE-3]]:10: warning: use designated initializer list to initialize 'S2' [modernize-use-designated-initializers] +// CHECK-MESSAGES-POD: :[[@LINE-8]]:1: note: aggregate type is defined here +// CHECK-FIXES: S2 s22 = {.i=1, .j=2}; + +S2 s23{1}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use designated initializer list to initialize 'S2' [modernize-use-designated-initializers] +// CHECK-MESSAGES: :[[@LINE-13]]:1: note: aggregate type is defined here +// CHECK-MESSAGES-POD: :[[@LINE-3]]:7: warning: use designated initializer list to initialize 'S2' [modernize-use-designated-initializers] +// CHECK-MESSAGES-POD: :[[@LINE-15]]:1: note: aggregate type is defined here +// CHECK-FIXES: S2 s23{.i=1}; + +S2 s24{.i = 1}; + +S2 s25 = {.i=1, 2}; +// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use designated init expression to initialize field 'j' [modernize-use-designated-initializers] +// CHECK-MESSAGES-POD: :[[@LINE-2]]:17: warning: use designated init expression to initialize field 'j' [modernize-use-designated-initializers] +// CHECK-FIXES: S2 s25 = {.i=1, .j=2}; + +class S3 { + public: + S2 s2; + double d; +}; + +S3 s31 = {.s2 = 1, 2, 3.1}; +// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use designated init expression to initialize field 's2.j' [modernize-use-designated-initializers] +// CHECK-MESSAGES: :[[@LINE-2]]:23: warning: use designated init expression to initialize field 'd' [modernize-use-designated-initializers] +// CHECK-MESSAGES-POD: :[[@LINE-3]]:20: warning: use designated init expression to initialize field 's2.j' [modernize-use-designated-initializers] +// CHECK-MESSAGES-POD: :[[@LINE-4]]:23: warning: use designated init expression to initialize field 'd' [modernize-use-designated-initializers] +// CHECK-FIXES: S3 s31 = {.s2 = 1, .s2.j=2, .d=3.1}; + +S3 s32 = {{.i = 1, 2}}; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use designated initializer list to initialize 'S3' [modernize-use-designated-initializers] +// CHECK-MESSAGES: :[[@LINE-15]]:1: note: aggregate type is defined here +// CHECK-MESSAGES: :[[@LINE-3]]:20: warning: use designated init expression to initialize field 'j' [modernize-use-designated-initializers] +// CHECK-MESSAGES-POD: :[[@LINE-4]]:10: warning: use designated initializer list to initialize 'S3' [modernize-use-designated-initializers] +// CHECK-MESSAGES-POD: :[[@LINE-18]]:1: note: aggregate type is defined here +// CHECK-MESSAGES-POD: :[[@LINE-6]]:20: warning: use designated init expression to initialize field 'j' [modernize-use-designated-initializers] +// CHECK-FIXES: S3 s32 = {.s2={.i = 1, .j=2}}; + +S3 s33 = {{2}, .d=3.1}; +// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use designated init expression to initialize field 's2' [modernize-use-designated-initializers] +// CHECK-MESSAGES: :[[@LINE-2]]:11: warning: use designated initializer list to initialize 'S2' [modernize-use-designated-initializers] +// CHECK-MESSAGES: :[[@LINE-50]]:1: note: aggregate type is defined here +// CHECK-MESSAGES-POD: :[[@LINE-4]]:11: warning: use designated init expression to initialize field 's2' [modernize-use-designated-initializers] +// CHECK-MESSAGES-POD: :[[@LINE-5]]:11: warning: use designated initializer list to initialize 'S2' [modernize-use-designated-initializers] +// CHECK-MESSAGES-POD: :[[@LINE-53]]:1: note: aggregate type is defined here +// CHECK-FIXES: S3 s33 = {.s2={.i=2}, .d=3.1}; + +struct S4 { + double d; + private: static int i; +}; + +S4 s41 {2.2}; +// CHECK-MESSAGES-SINGLE-ELEMENT: :[[@LINE-1]]:8: warning: use designated initializer list to initialize 'S4' [modernize-use-designated-initializers] +// CHECK-MESSAGES-SINGLE-ELEMENT: :[[@LINE-7]]:1: note: aggregate type is defined here +// CHECK-FIXES-SINGLE-ELEMENT: S4 s41 {.d=2.2}; + +S4 s42 = {{}}; +// CHECK-MESSAGES-SINGLE-ELEMENT: :[[@LINE-1]]:10: warning: use designated initializer list to initialize 'S4' [modernize-use-designated-initializers] +// CHECK-MESSAGES-SINGLE-ELEMENT: :[[@LINE-12]]:1: note: aggregate type is defined here +// CHECK-FIXES-SINGLE-ELEMENT: S4 s42 = {.d={}}; + +template S template1() { return {10, 11}; } + +S2 s26 = template1(); + +template S template2() { return {}; } + +S2 s27 = template2(); + +struct S5: S2 { int x, y; }; + +S5 s51 {1, 2, .x = 3, .y = 4}; + +struct S6 { + int i; + struct { int j; } s; +}; + +S6 s61 {1, 2}; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use designated initializer list to initialize 'S6' [modernize-use-designated-initializers] +// CHECK-MESSAGES: :[[@LINE-7]]:1: note: aggregate type is defined here +// CHECK-MESSAGES-POD: :[[@LINE-3]]:8: warning: use designated initializer list to initialize 'S6' [modernize-use-designated-initializers] +// CHECK-MESSAGES-POD: :[[@LINE-9]]:1: note: aggregate type is defined here +// CHECK-FIXES: S6 s61 {.i=1, .s.j=2}; + +struct S7 { + union { + int k; + double d; + } u; +}; + +S7 s71 {1}; +// CHECK-MESSAGES-SINGLE-ELEMENT: :[[@LINE-1]]:8: warning: use designated initializer list to initialize 'S7' [modernize-use-designated-initializers] +// CHECK-MESSAGES-SINGLE-ELEMENT: :[[@LINE-9]]:1: note: aggregate type is defined here +// CHECK-FIXES-SINGLE-ELEMENT: S7 s71 {.u.k=1}; + +struct S8: S7 { int i; }; + +S8 s81{1, 2}; + +struct S9 { + int i, j; + S9 &operator=(S9); +}; + +S9 s91{1, 2}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use designated initializer list to initialize 'S9' [modernize-use-designated-initializers] +// CHECK-MESSAGES: :[[@LINE-7]]:1: note: aggregate type is defined here +// CHECK-FIXES: S9 s91{.i=1, .j=2}; + +struct S10 { int i = 1, j = 2; }; + +S10 s101 {1, .j=2}; +// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use designated init expression to initialize field 'i' [modernize-use-designated-initializers] +// CHECK-FIXES: S10 s101 {.i=1, .j=2}; + +struct S11 { int i; S10 s10; }; + +S11 s111 { .i = 1 }; +S11 s112 { 1 }; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use designated initializer list to initialize 'S11' [modernize-use-designated-initializers] +// CHECK-MESSAGES: :[[@LINE-5]]:1: note: aggregate type is defined here +// CHECK-FIXES: S11 s112 { .i=1 }; + +S11 s113 { .i=1, {}}; +// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use designated init expression to initialize field 's10' [modernize-use-designated-initializers] +// CHECK-FIXES: S11 s113 { .i=1, .s10={}}; + +S11 s114 { .i=1, .s10={1, .j=2}}; +// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use designated init expression to initialize field 'i' [modernize-use-designated-initializers] +// CHECK-FIXES: S11 s114 { .i=1, .s10={.i=1, .j=2}}; + +struct S12 { + int i; + struct { int j; }; +}; + +S12 s121 {1, 2}; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use designated initializer list to initialize 'S12' [modernize-use-designated-initializers] +// CHECK-MESSAGES: :[[@LINE-7]]:1: note: aggregate type is defined here +// CHECK-MESSAGES-POD: :[[@LINE-3]]:10: warning: use designated initializer list to initialize 'S12' [modernize-use-designated-initializers] +// CHECK-MESSAGES-POD: :[[@LINE-9]]:1: note: aggregate type is defined here +// CHECK-FIXES: S12 s121 {.i=1, .j=2}; + +struct S13 { + union { + int k; + double d; + }; + int i; +}; + +S13 s131 {1, 2}; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use designated initializer list to initialize 'S13' [modernize-use-designated-initializers] +// CHECK-MESSAGES: :[[@LINE-10]]:1: note: aggregate type is defined here +// CHECK-MESSAGES-POD: :[[@LINE-3]]:10: warning: use designated initializer list to initialize 'S13' [modernize-use-designated-initializers] +// CHECK-MESSAGES-POD: :[[@LINE-12]]:1: note: aggregate type is defined here +// CHECK-FIXES: S13 s131 {.k=1, .i=2}; + +#define A (3+2) +#define B .j=1 + +S9 s92 {A, B}; +// CHECK-MESSAGES-MACROS: :[[@LINE-1]]:9: warning: use designated init expression to initialize field 'i' [modernize-use-designated-initializers] +// CHECK-MESSAGES-MACROS: :[[@LINE-5]]:11: note: expanded from macro 'A' + +#define DECLARE_S93 S9 s93 {1, 2} + +DECLARE_S93; +// CHECK-MESSAGES-MACROS: :[[@LINE-1]]:1: warning: use designated initializer list to initialize 'S9' [modernize-use-designated-initializers] +// CHECK-MESSAGES-MACROS: :[[@LINE-4]]:28: note: expanded from macro 'DECLARE_S93' +// CHECK-MESSAGES-MACROS: :[[@LINE-71]]:1: note: aggregate type is defined here diff --git a/clang/cmake/caches/Fuchsia-stage2.cmake b/clang/cmake/caches/Fuchsia-stage2.cmake index eee37c5e7901f..db7430b3344c3 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 df399a229d8d4..5b00a8f4c00fb 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/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 09766f2821da1..e8e2ccaa98905 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -3498,7 +3498,7 @@ internal linkage. ----------------------- ``__builtin_popcountg`` returns the number of 1 bits in the argument. The -argument can be of any integer type. +argument can be of any unsigned integer type. **Syntax**: @@ -3510,20 +3510,20 @@ argument can be of any integer type. .. code-block:: c++ - int x = 1; + unsigned int x = 1; int x_pop = __builtin_popcountg(x); unsigned long y = 3; int y_pop = __builtin_popcountg(y); - _BitInt(128) z = 7; + unsigned _BitInt(128) z = 7; int z_pop = __builtin_popcountg(z); **Description**: ``__builtin_popcountg`` is meant to be a type-generic alternative to the ``__builtin_popcount{,l,ll}`` builtins, with support for other integer types, -such as ``__int128`` and C23 ``_BitInt(N)``. +such as ``unsigned __int128`` and C23 ``unsigned _BitInt(N)``. Multiprecision Arithmetic Builtins ---------------------------------- diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index c40d679e383bb..8a06084955aa6 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -7049,7 +7049,7 @@

AST Traversal Matchers

-Matcher<
CXXFoldExpr>hasFoldInitast_matchers::Matcher<Expr> InnerMacher +Matcher<CXXFoldExpr>hasFoldInitMatcher<Expr> InnerMacher
Matches the operand that does not contain the parameter pack.
 
 Example matches `(0 + ... + args)` and `(args * ... * 1)`
@@ -7089,7 +7089,7 @@ 

AST Traversal Matchers

-Matcher<CXXFoldExpr>hasPatternast_matchers::Matcher<Expr> InnerMacher +Matcher<CXXFoldExpr>hasPatternMatcher<Expr> InnerMacher
Matches the operand that contains the parameter pack.
 
 Example matches `(0 + ... + args)`
@@ -7859,7 +7859,7 @@ 

AST Traversal Matchers

-Matcher<ClassTemplateSpecializationDecl>forEachTemplateArgumentclang::ast_matchers::Matcher<TemplateArgument> InnerMatcher +Matcher<ClassTemplateSpecializationDecl>forEachTemplateArgumentMatcher<TemplateArgument> InnerMatcher
Matches classTemplateSpecialization, templateSpecializationType and
 functionDecl nodes where the template argument matches the inner matcher.
 This matcher may produce multiple matches.
@@ -8454,7 +8454,7 @@ 

AST Traversal Matchers

-Matcher<Expr>ignoringElidableConstructorCallast_matchers::Matcher<Expr> InnerMatcher +Matcher<Expr>ignoringElidableConstructorCallMatcher<Expr> InnerMatcher
Matches expressions that match InnerMatcher that are possibly wrapped in an
 elidable constructor and other corresponding bookkeeping nodes.
 
@@ -8691,7 +8691,7 @@ 

AST Traversal Matchers

-Matcher<FunctionDecl>forEachTemplateArgumentclang::ast_matchers::Matcher<TemplateArgument> InnerMatcher +Matcher<FunctionDecl>forEachTemplateArgumentMatcher<TemplateArgument> InnerMatcher
Matches classTemplateSpecialization, templateSpecializationType and
 functionDecl nodes where the template argument matches the inner matcher.
 This matcher may produce multiple matches.
@@ -8959,7 +8959,7 @@ 

AST Traversal Matchers

-Matcher<InitListExpr>hasInitunsigned N, ast_matchers::Matcher<Expr> InnerMatcher +Matcher<InitListExpr>hasInitunsigned N, Matcher<Expr> InnerMatcher
Matches the n'th item of an initializer list expression.
 
 Example matches y.
@@ -10026,7 +10026,7 @@ 

AST Traversal Matchers

-Matcher<TemplateSpecializationType>forEachTemplateArgumentclang::ast_matchers::Matcher<TemplateArgument> InnerMatcher +Matcher<TemplateSpecializationType>forEachTemplateArgumentMatcher<TemplateArgument> InnerMatcher
Matches classTemplateSpecialization, templateSpecializationType and
 functionDecl nodes where the template argument matches the inner matcher.
 This matcher may produce multiple matches.
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7e16b9f0c67db..0ff4a93b15ea8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -42,6 +42,8 @@ C/C++ Language Potentially Breaking Changes
 
 C++ Specific Potentially Breaking Changes
 -----------------------------------------
+- Clang now diagnoses function/variable templates that shadow their own template parameters, e.g. ``template void T();``.
+  This error can be disabled via `-Wno-strict-primary-template-shadow` for compatibility with previous versions of clang.
 
 ABI Changes in This Version
 ---------------------------
@@ -79,11 +81,16 @@ C++20 Feature Support
   more to ease the implementation and improve the user's using experience.
   This follows the MSVC's behavior. Users interested in testing the more strict
   behavior can use the flag '-Xclang -fno-skip-odr-check-in-gmf'.
-  (`#79240 `_).
+  (#GH79240).
 
 - 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 `_.
+
 C++23 Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
 
@@ -116,7 +123,7 @@ C Language Changes
 C23 Feature Support
 ^^^^^^^^^^^^^^^^^^^
 - No longer diagnose use of binary literals as an extension in C23 mode. Fixes
-  `#72017 `_.
+  #GH72017.
 
 - Corrected parsing behavior for the ``alignas`` specifier/qualifier in C23. We
   previously handled it as an attribute as in C++, but there are parsing
@@ -129,13 +136,16 @@ C23 Feature Support
      };
      int i alignas(8) /* was accepted, now rejected */ ;
 
-  Fixes (`#81472 `_).
+  Fixes (#GH81472).
 
 - Clang now generates predefined macros of the form ``__TYPE_FMTB__`` and
   ``__TYPE_FMTb__`` (e.g., ``__UINT_FAST64_FMTB__``) in C23 mode for use with
   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
 -------------------------------------------------
 
@@ -148,6 +158,10 @@ Non-comprehensive list of changes in this release
 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
 -------------------------
 
@@ -173,7 +187,10 @@ Improvements to Clang's diagnostics
   name specifiers.
 
 - The ``-Wshorten-64-to-32`` diagnostic is now grouped under ``-Wimplicit-int-conversion`` instead
-   of ``-Wconversion``. Fixes `#69444 `_.
+   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.
 
@@ -186,12 +203,15 @@ Improvements to Clang's diagnostics
   ``unsigned long long``, but this behavior may change in the future when Clang
   implements
   `WG14 N3029 `_.
-  Fixes `#69352 `_.
+  (#GH69352).
 
 - Clang now diagnoses extraneous template parameter lists as a language extension.
 
 - Clang now diagnoses declarative nested name specifiers that name alias templates.
 
+- Clang now diagnoses lambda function expressions being implicitly cast to boolean values, under ``-Wpointer-bool-conversion``.
+  Fixes #GH82512.
+
 Improvements to Clang's time-trace
 ----------------------------------
 
@@ -203,17 +223,21 @@ Bug Fixes in This Version
 - Clang now accepts elaborated-type-specifiers that explicitly specialize
   a member class template for an implicit instantiation of a class template.
 
-- Fixed missing warnings when doing bool-like conversions in C23 (`#79435 `_).
+- Fixed missing warnings when doing bool-like conversions in C23 (#GH79435).
 - Clang's ``-Wshadow`` no longer warns when an init-capture is named the same as
   a class field unless the lambda can capture this.
-  Fixes (`#71976 `_)
+  Fixes (#GH71976)
 
 - Clang now accepts qualified partial/explicit specializations of variable templates that
   are not nominable in the lookup context of the specialization.
 
 - Clang now doesn't produce false-positive warning `-Wconstant-logical-operand`
   for logical operators in C23.
-  Fixes (`#64356 `_).
+  Fixes (#GH64356).
+
+- 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).
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -225,71 +249,76 @@ Bug Fixes to C++ Support
 ^^^^^^^^^^^^^^^^^^^^^^^^
 
 - Fix crash when calling the constructor of an invalid class.
-  Fixes (`#10518 `_),
-  (`#67914 `_),
-  and (`#78388 `_)
+  (#GH10518) (#GH67914) (#GH78388)
 - Fix crash when using lifetimebound attribute in function with trailing return.
-  Fixes (`#73619 `_)
+  (#GH73619)
 - Addressed an issue where constraints involving injected class types are perceived
-  distinct from its specialization types.
-  (`#56482 `_)
+  distinct from its specialization types. (#GH56482)
 - Fixed a bug where variables referenced by requires-clauses inside
-  nested generic lambdas were not properly injected into the constraint scope.
-  (`#73418 `_)
+  nested generic lambdas were not properly injected into the constraint scope. (#GH73418)
 - Fixed a crash where substituting into a requires-expression that refers to function
   parameters during the equivalence determination of two constraint expressions.
-  (`#74447 `_)
+  (#GH74447)
 - Fixed deducing auto& from const int in template parameters of partial
-  specializations.
-  (`#77189 `_)
+  specializations. (#GH77189)
 - Fix for crash when using a erroneous type in a return statement.
-  Fixes (`#63244 `_)
-  and (`#79745 `_)
+  (#GH63244) (#GH79745)
 - Fixed an out-of-bounds error caused by building a recovery expression for ill-formed
-  function calls while substituting into constraints.
-  (`#58548 `_)
-- Fix incorrect code generation caused by the object argument of ``static operator()`` and ``static operator[]`` calls not being evaluated.
-  Fixes (`#67976 `_)
+  function calls while substituting into constraints. (#GH58548)
+- Fix incorrect code generation caused by the object argument
+  of ``static operator()`` and ``static operator[]`` calls not being evaluated. (#GH67976)
 - Fix crash and diagnostic with const qualified member operator new.
-  Fixes (`#79748 `_)
+  Fixes (#GH79748)
 - Fixed a crash where substituting into a requires-expression that involves parameter packs
-  during the equivalence determination of two constraint expressions.
-  (`#72557 `_)
+  during the equivalence determination of two constraint expressions. (#GH72557)
 - Fix a crash when specializing an out-of-line member function with a default
   parameter where we did an incorrect specialization of the initialization of
-  the default parameter.
-  Fixes (`#68490 `_)
+  the default parameter. (#GH68490)
 - Fix a crash when trying to call a varargs function that also has an explicit object parameter.
-  Fixes (`#80971 ICE when explicit object parameter be a function parameter pack`)
-- Reject explicit object parameters on `new` and `delete` operators.
-  Fixes (`#82249 ` _)
+  Fixes (#GH80971)
+- Reject explicit object parameters on `new` and `delete` operators. (#GH82249)
+- 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. Fixes
-  some of (`#80510 `).
-- Clang now ignores top-level cv-qualifiers on function parameters in template partial orderings.
-  (`#75404 `_)
+  elements were considered, misclassifying some initializers as constant. Partially fixes
+  #GH80510.
+- Clang now ignores top-level cv-qualifiers on function parameters in template partial orderings. (#GH75404)
 - No longer reject valid use of the ``_Alignas`` specifier when declaring a
   local variable, which is supported as a C11 extension in C++. Previously, it
   was only accepted at namespace scope but not at local function scope.
-- Clang no longer tries to call consteval constructors at runtime when they appear in a member initializer.
-  (`#82154 `_`)
-- Fix crash when using an immediate-escalated function at global scope.
-  (`#82258 `_)
-- Correctly immediate-escalate lambda conversion functions.
-  (`#82258 `_)
+- Clang no longer tries to call consteval constructors at runtime when they appear in a member initializer. (#GH82154)
+- Fix crash when using an immediate-escalated function at global scope. (#GH82258)
+- Correctly immediate-escalate lambda conversion functions. (#GH82258)
 - Fixed an issue where template parameters of a nested abbreviated generic lambda within
   a requires-clause lie at the same depth as those of the surrounding lambda. This,
   in turn, results in the wrong template argument substitution during constraint checking.
-  (`#78524 `_)
+  (#GH78524)
 - Clang no longer instantiates the exception specification of discarded candidate function
   templates when determining the primary template of an explicit specialization.
 - Fixed a crash in Microsoft compatibility mode where unqualified dependent base class
   lookup searches the bases of an incomplete class.
 - Fix a crash when an unresolved overload set is encountered on the RHS of a ``.*`` operator.
-  (`#53815 `_)
+  (#GH53815)
+- In ``__restrict``-qualified member functions, attach ``__restrict`` to the pointer type of
+  ``this`` rather than the pointee type.
+  Fixes (#GH82941), (#GH42411) and (#GH18121).
+- Clang now properly reports supported C++11 attributes when using
+  ``__has_cpp_attribute`` and parses attributes with arguments in C++03 (#GH82995)
+- Clang now properly diagnoses missing 'default' template arguments on a variety
+  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)
+- Fix a crash when an explicit template argument list is used with a name for which lookup
+  finds a non-template function and a dependent using declarator.
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -300,6 +329,10 @@ Miscellaneous Bug Fixes
 Miscellaneous Clang Crashes Fixed
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+- Do not attempt to dump the layout of dependent types or invalid declarations
+  when ``-fdump-record-layouts-complete`` is passed.
+  Fixes (`#83684 `_).
+
 OpenACC Specific Changes
 ------------------------
 
@@ -325,6 +358,11 @@ Arm and AArch64 Support
   improvements for most targets. We have not changed the default behavior for
   ARMv6, but may revisit that decision in the future. Users can restore the old
   behavior with -m[no-]unaligned-access.
+- An alias identifier (rdma) has been added for targeting the AArch64
+  Architecture Extension which uses Rounding Doubling Multiply Accumulate
+  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``.
 
 Android Support
 ^^^^^^^^^^^^^^^
diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 899622ae283b1..fe21151491427 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -1320,10 +1320,23 @@ range of the argument.
 
 **Parameters**
 
-The checker models functions (and emits diagnostics) from the C standard by
-default. The ``ModelPOSIX`` option enables modeling (and emit diagnostics) of
-additional functions that are defined in the POSIX standard. This option is
-disabled by default.
+The ``ModelPOSIX`` option controls if functions from the POSIX standard are
+recognized by the checker.
+
+With ``ModelPOSIX=true``, many POSIX functions are modeled according to the
+`POSIX standard`_. This includes ranges of parameters and possible return
+values. Furthermore the behavior related to ``errno`` in the POSIX case is
+often that ``errno`` is set only if a function call fails, and it becomes
+undefined after a successful function call.
+
+With ``ModelPOSIX=false``, this checker follows the C99 language standard and
+only models the functions that are described there. It is possible that the
+same functions are modeled differently in the two cases because differences in
+the standards. The C standard specifies less aspects of the functions, for
+example exact ``errno`` behavior is often unspecified (and not modeled by the
+checker).
+
+Default value of the option is ``true``.
 
 .. _osx-checkers:
 
diff --git a/clang/docs/conf.py b/clang/docs/conf.py
index 31a4daa39d5b8..4cee382a718fa 100644
--- a/clang/docs/conf.py
+++ b/clang/docs/conf.py
@@ -18,7 +18,7 @@
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
-# sys.path.insert(0, os.path.abspath('.'))
+sys.path.insert(0, os.path.abspath("."))
 
 # -- General configuration -----------------------------------------------------
 
@@ -27,7 +27,7 @@
 
 # Add any Sphinx extension module names here, as strings. They can be extensions
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ["sphinx.ext.todo", "sphinx.ext.mathjax", "sphinx.ext.graphviz"]
+extensions = ["sphinx.ext.todo", "sphinx.ext.mathjax", "sphinx.ext.graphviz", "ghlinks"]
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ["_templates"]
@@ -35,8 +35,17 @@
 
 import sphinx
 
-if sphinx.version_info >= (3, 0):
+# When building man pages, we do not use the markdown pages,
+# So, we can continue without the myst_parser dependencies.
+# Doing so reduces dependencies of some packaged llvm distributions.
+try:
+    import myst_parser
+
     extensions.append("myst_parser")
+except ImportError:
+    if not tags.has("builder-man"):
+        raise
+
 
 # The encoding of source files.
 # source_encoding = 'utf-8-sig'
diff --git a/clang/docs/ghlinks.py b/clang/docs/ghlinks.py
new file mode 100644
index 0000000000000..bad0f9fbf0adb
--- /dev/null
+++ b/clang/docs/ghlinks.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python3
+
+from sphinx.application import Sphinx
+import re
+
+__version__ = "1.0"
+
+
+def subst_gh_links(app: Sphinx, docname, source):
+    regex = re.compile("#GH([0-9]+)")
+    out_pattern = r"`#\1 `_"
+    result = source[0]
+    result = regex.sub(out_pattern, result)
+    source[0] = result
+
+
+def setup(app: Sphinx):
+    app.connect("source-read", subst_gh_links)
+    return dict(version=__version__, parallel_read_safe=True, parallel_write_safe=True)
diff --git a/clang/docs/tools/dump_ast_matchers.py b/clang/docs/tools/dump_ast_matchers.py
index cc7024d1627b9..705ff0d4d4098 100755
--- a/clang/docs/tools/dump_ast_matchers.py
+++ b/clang/docs/tools/dump_ast_matchers.py
@@ -116,6 +116,8 @@ def strip_doxygen(comment):
 
 def unify_arguments(args):
     """Gets rid of anything the user doesn't care about in the argument list."""
+    args = re.sub(r"clang::ast_matchers::internal::", r"", args)
+    args = re.sub(r"ast_matchers::internal::", r"", args)
     args = re.sub(r"internal::", r"", args)
     args = re.sub(r"extern const\s+(.*)&", r"\1 ", args)
     args = re.sub(r"&", r" ", args)
diff --git a/clang/docs/tools/dump_format_style.py b/clang/docs/tools/dump_format_style.py
index af0124b94ecaf..af0e658fcdc55 100755
--- a/clang/docs/tools/dump_format_style.py
+++ b/clang/docs/tools/dump_format_style.py
@@ -129,6 +129,7 @@ def __str__(self):
             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/APINotes/APINotesWriter.h b/clang/include/clang/APINotes/APINotesWriter.h
index dad44623e16ae..c5ca3e4617796 100644
--- a/clang/include/clang/APINotes/APINotesWriter.h
+++ b/clang/include/clang/APINotes/APINotesWriter.h
@@ -5,7 +5,13 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-
+//
+// This file defines the \c APINotesWriter class that writes out source
+// API notes data providing additional information about source code as
+// a separate input, such as the non-nil/nilable annotations for
+// method parameters.
+//
+//===----------------------------------------------------------------------===//
 #ifndef LLVM_CLANG_APINOTES_WRITER_H
 #define LLVM_CLANG_APINOTES_WRITER_H
 
@@ -20,11 +26,16 @@ namespace clang {
 class FileEntry;
 
 namespace api_notes {
+
+/// A class that writes API notes data to a binary representation that can be
+/// read by the \c APINotesReader.
 class APINotesWriter {
   class Implementation;
   std::unique_ptr Implementation;
 
 public:
+  /// Create a new API notes writer with the given module name and
+  /// (optional) source file.
   APINotesWriter(llvm::StringRef ModuleName, const FileEntry *SF);
   ~APINotesWriter();
 
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 1cf8adad11f02..e856848c7c3a6 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -1875,6 +1875,17 @@ class StringLiteral final
     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; }
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index dc1f49525a004..ced89ff127ab3 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -4580,8 +4580,7 @@ AST_POLYMORPHIC_MATCHER_P2(hasArgument,
 ///       return (args * ... * 1);
 ///   }
 /// \endcode
-AST_MATCHER_P(CXXFoldExpr, hasFoldInit, ast_matchers::internal::Matcher,
-              InnerMacher) {
+AST_MATCHER_P(CXXFoldExpr, hasFoldInit, internal::Matcher, InnerMacher) {
   const auto *const Init = Node.getInit();
   return Init && InnerMacher.matches(*Init, Finder, Builder);
 }
@@ -4603,8 +4602,7 @@ AST_MATCHER_P(CXXFoldExpr, hasFoldInit, ast_matchers::internal::Matcher,
 ///       return (args * ... * 1);
 ///   }
 /// \endcode
-AST_MATCHER_P(CXXFoldExpr, hasPattern, ast_matchers::internal::Matcher,
-              InnerMacher) {
+AST_MATCHER_P(CXXFoldExpr, hasPattern, internal::Matcher, InnerMacher) {
   const Expr *const Pattern = Node.getPattern();
   return Pattern && InnerMacher.matches(*Pattern, Finder, Builder);
 }
@@ -4685,8 +4683,8 @@ AST_MATCHER(CXXFoldExpr, isBinaryFold) { return Node.getInit() != nullptr; }
 /// \code
 ///   int x{y}.
 /// \endcode
-AST_MATCHER_P2(InitListExpr, hasInit, unsigned, N,
-               ast_matchers::internal::Matcher, InnerMatcher) {
+AST_MATCHER_P2(InitListExpr, hasInit, unsigned, N, internal::Matcher,
+               InnerMatcher) {
   return N < Node.getNumInits() &&
           InnerMatcher.matches(*Node.getInit(N), Finder, Builder);
 }
@@ -5309,7 +5307,7 @@ AST_POLYMORPHIC_MATCHER_P(
     forEachTemplateArgument,
     AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
                                     TemplateSpecializationType, FunctionDecl),
-    clang::ast_matchers::internal::Matcher, InnerMatcher) {
+    internal::Matcher, InnerMatcher) {
   ArrayRef TemplateArgs =
       clang::ast_matchers::internal::getTemplateSpecializationArgs(Node);
   clang::ast_matchers::internal::BoundNodesTreeBuilder Result;
@@ -8525,8 +8523,8 @@ AST_MATCHER(FunctionDecl, hasTrailingReturn) {
 ///
 /// ``varDecl(hasInitializer(ignoringElidableConstructorCall(callExpr())))``
 /// matches ``H D = G()`` in C++11 through C++17 (and beyond).
-AST_MATCHER_P(Expr, ignoringElidableConstructorCall,
-              ast_matchers::internal::Matcher, InnerMatcher) {
+AST_MATCHER_P(Expr, ignoringElidableConstructorCall, internal::Matcher,
+              InnerMatcher) {
   // E tracks the node that we are examining.
   const Expr *E = &Node;
   // If present, remove an outer `ExprWithCleanups` corresponding to the
diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
index 7f8c70d169376..62e7af7ac219b 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
@@ -723,9 +723,12 @@ RecordStorageLocation *getImplicitObjectLocation(const CXXMemberCallExpr &MCE,
 RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME,
                                              const Environment &Env);
 
-/// Returns the fields of `RD` that are initialized by an `InitListExpr`, in the
-/// order in which they appear in `InitListExpr::inits()`.
-std::vector getFieldsForInitListExpr(const RecordDecl *RD);
+/// Returns the fields of a `RecordDecl` that are initialized by an
+/// `InitListExpr`, in the order in which they appear in
+/// `InitListExpr::inits()`.
+/// `Init->getType()` must be a record type.
+std::vector
+getFieldsForInitListExpr(const InitListExpr *InitList);
 
 /// Associates a new `RecordValue` with `Loc` and returns the new value.
 RecordValue &refreshRecordValue(RecordStorageLocation &Loc, Environment &Env);
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 37c02c4327644..18b377d0d579c 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];
+  let Attributes = [NoThrow, Const, 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];
@@ -4536,6 +4566,30 @@ def HLSLDotProduct : LangBuiltin<"HLSL_LANG"> {
   let Prototype = "void(...)";
 }
 
+def HLSLFrac : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_elementwise_frac"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "void(...)";
+}
+
+def HLSLLerp : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_lerp"];
+  let Attributes = [NoThrow, Const];
+  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/BuiltinsBase.td b/clang/include/clang/Basic/BuiltinsBase.td
index bfccff5600ddb..724747ec76d73 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/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 08bf949d2f0a1..0430f3c660771 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -762,7 +762,6 @@ def err_drv_cannot_mix_options : Error<"cannot specify '%1' along with '%0'">;
 def err_drv_invalid_object_mode : Error<
   "OBJECT_MODE setting %0 is not recognized and is not a valid setting">;
 
-def err_aix_unsupported_tls_model : Error<"TLS model '%0' is not yet supported on AIX">;
 def err_roptr_requires_data_sections: Error<"-mxcoff-roptr is supported only with -fdata-sections">;
 def err_roptr_cannot_build_shared: Error<"-mxcoff-roptr is not supported with -shared">;
 
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index f550b2866194d..dc492213ec172 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -522,7 +522,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">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 2091c150a7d7a..12dca5d46ee15 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -808,7 +808,7 @@ def err_builtin_redeclare : Error<"cannot redeclare builtin function %0">;
 def err_arm_invalid_specialreg : Error<"invalid special register for builtin">;
 def err_arm_invalid_coproc : Error<"coprocessor %0 must be configured as "
   "%select{GCP|CDE}1">;
-def err_invalid_cpu_supports : Error<"invalid cpu feature string for builtin">;
+def warn_invalid_cpu_supports : Warning<"invalid cpu feature string for builtin">;
 def err_invalid_cpu_is : Error<"invalid cpu name for builtin">;
 def err_invalid_cpu_specific_dispatch_value : Error<
 "invalid option '%0' for %select{cpu_specific|cpu_dispatch}1">;
@@ -2989,6 +2989,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">;
@@ -4185,8 +4197,8 @@ def ext_ms_impcast_fn_obj : ExtWarn<
   "Microsoft extension">, InGroup;
 
 def warn_impcast_pointer_to_bool : Warning<
-    "address of%select{| function| array}0 '%1' will always evaluate to "
-    "'true'">,
+    "address of %select{'%1'|function '%1'|array '%1'|lambda function pointer "
+    "conversion operator}0 will always evaluate to 'true'">,
     InGroup;
 def warn_cast_nonnull_to_bool : Warning<
     "nonnull %select{function call|parameter}0 '%1' will evaluate to "
@@ -5037,6 +5049,9 @@ def err_template_param_shadow : Error<
   "declaration of %0 shadows template parameter">;
 def ext_template_param_shadow : ExtWarn<
   err_template_param_shadow.Summary>, InGroup;
+def ext_compat_template_param_shadow : ExtWarn<
+  err_template_param_shadow.Summary>, InGroup<
+  DiagGroup<"strict-primary-template-shadow">>, DefaultError;
 def note_template_param_here : Note<"template parameter is declared here">;
 def note_template_param_external : Note<
   "template parameter from hidden source: %0">;
@@ -6227,6 +6242,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>;
@@ -9973,7 +9992,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">,
@@ -10342,9 +10361,9 @@ def err_sizeless_nonlocal : Error<
   "non-local variable with sizeless type %0">;
 
 def err_vec_builtin_non_vector : Error<
- "first two arguments to %0 must be vectors">;
+ "%select{first two|all}1 arguments to %0 must be vectors">;
 def err_vec_builtin_incompatible_vector : Error<
-  "first two arguments to %0 must have the same type">;
+  "%select{first two|all}1 arguments to %0 must have the same type">;
 def err_vsx_builtin_nonconstant_argument : Error<
   "argument %0 to %1 must be a 2-bit unsigned literal (i.e. 0, 1, 2 or 3)">;
 
@@ -12066,7 +12085,7 @@ def err_builtin_invalid_arg_type: Error <
   "signed integer or floating point type|vector type|"
   "floating point type|"
   "vector of integers|"
-  "type of integer}1 (was %2)">;
+  "type of unsigned integer}1 (was %2)">;
 
 def err_builtin_matrix_disabled: Error<
   "matrix types extension is disabled. Pass -fenable-matrix to enable it">;
@@ -12476,6 +12495,10 @@ def err_acc_construct_appertainment
     : Error<"OpenACC construct '%0' cannot be used here; it can only "
             "be used in a statement context">;
 def err_acc_branch_in_out_compute_construct
-    : Error<"invalid %select{branch|return}0 %select{out of|into}1 OpenACC "
-            "Compute Construct">;
+    : Error<"invalid %select{branch|return|throw}0 %select{out of|into}1 "
+            "OpenACC Compute Construct">;
+def note_acc_branch_into_compute_construct
+    : Note<"invalid branch into OpenACC Compute Construct">;
+def note_acc_branch_out_of_compute_construct
+    : Note<"invalid branch out of OpenACC Compute Construct">;
 } // end of sema component.
diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h
index 30ec9c9931509..9f62c058ca0da 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -598,6 +598,11 @@ class alignas(8) Module {
            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 @@ class VisibleModuleSet {
                   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/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 48e9cec482755..7682f84e491c7 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -1369,13 +1369,35 @@ class TargetInfo : public TransferrableTargetInfo,
   }
 
   struct BranchProtectionInfo {
-    LangOptions::SignReturnAddressScopeKind SignReturnAddr =
-        LangOptions::SignReturnAddressScopeKind::None;
-    LangOptions::SignReturnAddressKeyKind SignKey =
-        LangOptions::SignReturnAddressKeyKind::AKey;
-    bool BranchTargetEnforcement = false;
-    bool BranchProtectionPAuthLR = false;
-    bool GuardedControlStack = false;
+    LangOptions::SignReturnAddressScopeKind SignReturnAddr;
+    LangOptions::SignReturnAddressKeyKind SignKey;
+    bool BranchTargetEnforcement;
+    bool BranchProtectionPAuthLR;
+    bool GuardedControlStack;
+
+    BranchProtectionInfo() = default;
+
+    const char *getSignReturnAddrStr() const {
+      switch (SignReturnAddr) {
+      case LangOptions::SignReturnAddressScopeKind::None:
+        return "none";
+      case LangOptions::SignReturnAddressScopeKind::NonLeaf:
+        return "non-leaf";
+      case LangOptions::SignReturnAddressScopeKind::All:
+        return "all";
+      }
+      llvm_unreachable("Unexpected SignReturnAddressScopeKind");
+    }
+
+    const char *getSignKeyStr() const {
+      switch (SignKey) {
+      case LangOptions::SignReturnAddressKeyKind::AKey:
+        return "a_key";
+      case LangOptions::SignReturnAddressKeyKind::BKey:
+        return "b_key";
+      }
+      llvm_unreachable("Unexpected SignReturnAddressKeyKind");
+    }
   };
 
   /// Determine if the Architecture in this TargetInfo supports branch
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 00906ceca99bd..a236116bcd74e 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -394,7 +394,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/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index 69f4a470c7b5f..413681e55c74c 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -162,9 +162,6 @@ class Driver {
   /// Target and driver mode components extracted from clang executable name.
   ParsedClangName ClangNameParts;
 
-  /// The path to the installed clang directory, if any.
-  std::string InstalledDir;
-
   /// The path to the compiler resource directory.
   std::string ResourceDir;
 
@@ -431,11 +428,8 @@ class Driver {
 
   /// Get the path to where the clang executable was installed.
   const char *getInstalledDir() const {
-    if (!InstalledDir.empty())
-      return InstalledDir.c_str();
     return Dir.c_str();
   }
-  void setInstalledDir(StringRef Value) { InstalledDir = std::string(Value); }
   bool isDumpDeviceCodeEnabled() const { return DumpDeviceCode; }
 
   bool isSaveTempsEnabled() const { return SaveTemps != SaveTempsNone; }
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index cedc69aa25a91..a01aec2a1bca3 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -557,6 +557,13 @@ multiclass BoolGOption;
 }
 
+multiclass BoolMOption> {
+  defm NAME : BoolOption<"m", flag_base, kpm, default, flag1, flag2, both>,
+              Group;
+}
+
 // Works like BoolOption except without marshalling
 multiclass BoolOptionWithoutMarshalling, Group,
   Visibility<[ClangOption, CLOption]>;
 def mno_retpoline : Flag<["-"], "mno-retpoline">, Group,
   Visibility<[ClangOption, CLOption]>;
-defm speculative_load_hardening : BoolOption<"m", "speculative-load-hardening",
+defm speculative_load_hardening : BoolMOption<"speculative-load-hardening",
   CodeGenOpts<"SpeculativeLoadHardening">, DefaultFalse,
   PosFlag,
-  NegFlag, BothFlags<[], [ClangOption, CLOption]>>,
-  Group;
+  NegFlag, BothFlags<[], [ClangOption, CLOption]>>;
 def mlvi_hardening : Flag<["-"], "mlvi-hardening">, Group,
   Visibility<[ClangOption, CLOption]>,
   HelpText<"Enable all mitigations for Load Value Injection (LVI)">;
@@ -5092,13 +5098,13 @@ def mexec_model_EQ : Joined<["-"], "mexec-model=">, Group;
 } // let Flags = [TargetSpecific]
 
-defm amdgpu_ieee : BoolOption<"m", "amdgpu-ieee",
+defm amdgpu_ieee : BoolMOption<"amdgpu-ieee",
   CodeGenOpts<"EmitIEEENaNCompliantInsts">, DefaultTrue,
   PosFlag,
-  NegFlag>, Group;
+  NegFlag>;
 
 def mcode_object_version_EQ : Joined<["-"], "mcode-object-version=">, Group,
   HelpText<"Specify code object ABI version. Defaults to 5. (AMDGPU only)">,
@@ -5117,14 +5123,14 @@ defm wavefrontsize64 : SimpleMFlag<"wavefrontsize64",
   "Specify wavefront size 64", "Specify wavefront size 32",
   " mode (AMDGPU only)">;
 
-defm unsafe_fp_atomics : BoolOption<"m", "unsafe-fp-atomics",
+defm unsafe_fp_atomics : BoolMOption<"unsafe-fp-atomics",
   TargetOpts<"AllowAMDGPUUnsafeFPAtomics">, DefaultFalse,
   PosFlag,
-  NegFlag>, Group;
+  NegFlag>;
 
 def faltivec : Flag<["-"], "faltivec">, Group;
 def fno_altivec : Flag<["-"], "fno-altivec">, Group;
@@ -5212,11 +5218,10 @@ def mrop_protect : Flag<["-"], "mrop-protect">,
 def mprivileged : Flag<["-"], "mprivileged">,
     Group;
 
-defm regnames : BoolOption<"m", "regnames",
+defm regnames : BoolMOption<"regnames",
   CodeGenOpts<"PPCUseFullRegisterNames">, DefaultFalse,
   PosFlag,
-  NegFlag>,
-  Group;
+  NegFlag>;
 } // let Flags = [TargetSpecific]
 def maix_small_local_exec_tls : Flag<["-"], "maix-small-local-exec-tls">,
   Group,
@@ -5258,10 +5263,10 @@ def mxcoff_build_id_EQ : Joined<["-"], "mxcoff-build-id=">, Group, M
 def mignore_xcoff_visibility : Flag<["-"], "mignore-xcoff-visibility">, Group,
 HelpText<"Not emit the visibility attribute for asm in AIX OS or give all symbols 'unspecified' visibility in XCOFF object file">,
   Flags<[TargetSpecific]>, Visibility<[ClangOption, CC1Option]>;
-defm backchain : BoolOption<"m", "backchain",
+defm backchain : BoolMOption<"backchain",
   CodeGenOpts<"Backchain">, DefaultFalse,
   PosFlag,
-  NegFlag, BothFlags<[], [ClangOption, CC1Option]>>, Group;
+  NegFlag, BothFlags<[], [ClangOption, CC1Option]>>;
 
 def mno_warn_nonportable_cfstrings : Flag<["-"], "mno-warn-nonportable-cfstrings">, Group;
 def mno_omit_leaf_frame_pointer : Flag<["-"], "mno-omit-leaf-frame-pointer">, Group;
@@ -7267,7 +7272,7 @@ def msmall_data_limit : Separate<["-"], "msmall-data-limit">,
 def funwind_tables_EQ : Joined<["-"], "funwind-tables=">,
   HelpText<"Generate unwinding tables for all functions">,
   MarshallingInfoInt>;
-defm constructor_aliases : BoolOption<"m", "constructor-aliases",
+defm constructor_aliases : BoolMOption<"constructor-aliases",
   CodeGenOpts<"CXXCtorDtorAliases">, DefaultFalse,
   PosFlag,
   NegFlag,
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 613f1fd168465..590297fd89a39 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/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h
index b97d0c636806a..cce91862ae3d0 100644
--- a/clang/include/clang/Frontend/CompilerInstance.h
+++ b/clang/include/clang/Frontend/CompilerInstance.h
@@ -225,6 +225,9 @@ class CompilerInstance : public ModuleLoader {
   // of the context or else not CompilerInstance specific.
   bool ExecuteAction(FrontendAction &Act);
 
+  /// At the end of a compilation, print the number of warnings/errors.
+  void printDiagnosticStats();
+
   /// Load the list of plugins requested in the \c FrontendOptions.
   void LoadRequestedPlugins();
 
diff --git a/clang/include/clang/Frontend/CompilerInvocation.h b/clang/include/clang/Frontend/CompilerInvocation.h
index ab7fce93aa739..ac508080af457 100644
--- a/clang/include/clang/Frontend/CompilerInvocation.h
+++ b/clang/include/clang/Frontend/CompilerInvocation.h
@@ -201,6 +201,8 @@ class CompilerInvocationBase {
   /// @}
 };
 
+class CowCompilerInvocation;
+
 /// Helper class for holding the data necessary to invoke the compiler.
 ///
 /// This class is designed to represent an abstract "invocation" of the
@@ -220,6 +222,9 @@ class CompilerInvocation : public CompilerInvocationBase {
   }
   ~CompilerInvocation() = default;
 
+  explicit CompilerInvocation(const CowCompilerInvocation &X);
+  CompilerInvocation &operator=(const CowCompilerInvocation &X);
+
   /// Const getters.
   /// @{
   // Note: These need to be pulled in manually. Otherwise, they get hidden by
diff --git a/clang/include/clang/InstallAPI/Context.h b/clang/include/clang/InstallAPI/Context.h
index 7d105920734fd..4e9e90e5d2dbe 100644
--- a/clang/include/clang/InstallAPI/Context.h
+++ b/clang/include/clang/InstallAPI/Context.h
@@ -9,12 +9,15 @@
 #ifndef LLVM_CLANG_INSTALLAPI_CONTEXT_H
 #define LLVM_CLANG_INSTALLAPI_CONTEXT_H
 
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/InstallAPI/HeaderFile.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/TextAPI/InterfaceFile.h"
-#include "llvm/TextAPI/RecordVisitor.h"
-#include "llvm/TextAPI/RecordsSlice.h"
 
 namespace clang {
 namespace installapi {
+class FrontendRecordsSlice;
 
 /// Struct used for generating validating InstallAPI.
 /// The attributes captured represent all necessary information
@@ -24,14 +27,53 @@ struct InstallAPIContext {
   /// Library attributes that are typically passed as linker inputs.
   llvm::MachO::RecordsSlice::BinaryAttrs BA;
 
-  /// Active target triple to parse.
-  llvm::Triple TargetTriple{};
+  /// All headers that represent a library.
+  HeaderSeq InputHeaders;
+
+  /// Active language mode to parse in.
+  Language LangMode = Language::ObjC;
+
+  /// Active header access type.
+  HeaderType Type = HeaderType::Unknown;
+
+  /// Active TargetSlice for symbol record collection.
+  std::shared_ptr Slice;
+
+  /// FileManager for all I/O operations.
+  FileManager *FM = nullptr;
+
+  /// DiagnosticsEngine for all error reporting.
+  DiagnosticsEngine *Diags = nullptr;
 
   /// File Path of output location.
   llvm::StringRef OutputLoc{};
 
   /// What encoding to write output as.
   llvm::MachO::FileType FT = llvm::MachO::FileType::TBD_V5;
+
+  /// Populate entries of headers that should be included for TextAPI
+  /// generation.
+  void addKnownHeader(const HeaderFile &H);
+
+  /// Record visited files during frontend actions to determine whether to
+  /// include their declarations for TextAPI generation.
+  ///
+  /// \param FE Header that is being parsed.
+  /// \param PP Preprocesser used for querying how header was imported.
+  /// \return Access level of header if it should be included for TextAPI
+  /// generation.
+  std::optional findAndRecordFile(const FileEntry *FE,
+                                              const Preprocessor &PP);
+
+private:
+  using HeaderMap = llvm::DenseMap;
+
+  // Collection of parsed header files and their access level. If set to
+  // HeaderType::Unknown, they are not used for TextAPI generation.
+  HeaderMap KnownFiles;
+
+  // Collection of expected header includes and the access level for them.
+  llvm::DenseMap KnownIncludes;
 };
 
 } // namespace installapi
diff --git a/clang/include/clang/InstallAPI/Frontend.h b/clang/include/clang/InstallAPI/Frontend.h
new file mode 100644
index 0000000000000..8774321e990c1
--- /dev/null
+++ b/clang/include/clang/InstallAPI/Frontend.h
@@ -0,0 +1,139 @@
+//===- InstallAPI/Frontend.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
+//
+//===----------------------------------------------------------------------===//
+///
+/// Top level wrappers for InstallAPI frontend operations.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INSTALLAPI_FRONTEND_H
+#define LLVM_CLANG_INSTALLAPI_FRONTEND_H
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/Availability.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/InstallAPI/Context.h"
+#include "clang/InstallAPI/Visitor.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+namespace clang {
+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.
+class FrontendRecordsSlice : public llvm::MachO::RecordsSlice {
+public:
+  FrontendRecordsSlice(const llvm::Triple &T)
+      : llvm::MachO::RecordsSlice({T}) {}
+
+  /// Add non-ObjC global record with attributes from AST.
+  ///
+  /// \param Name The name of symbol.
+  /// \param Linkage The linkage of symbol.
+  /// \param GV The kind of global.
+  /// \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 Flags The flags that describe attributes of the symbol.
+  /// \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);
+
+  /// Add ObjC Class record with attributes from AST.
+  ///
+  /// \param Name The name of class, 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 IsEHType Whether declaration has an exception attribute.
+  /// \return The non-owning pointer to added record in slice.
+  ObjCInterfaceRecord *addObjCInterface(StringRef Name, RecordLinkage Linkage,
+                                        const clang::AvailabilityInfo Avail,
+                                        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 {
+    const AvailabilityInfo Avail;
+    const Decl *D;
+    const HeaderType Access;
+  };
+
+  /// Mapping of records stored in slice to their frontend attributes.
+  llvm::DenseMap FrontendRecords;
+};
+
+/// Create a buffer that contains all headers to scan
+/// for global symbols with.
+std::unique_ptr createInputBuffer(InstallAPIContext &Ctx);
+
+class InstallAPIAction : public ASTFrontendAction {
+public:
+  explicit InstallAPIAction(InstallAPIContext &Ctx) : Ctx(Ctx) {}
+
+  std::unique_ptr CreateASTConsumer(CompilerInstance &CI,
+                                                 StringRef InFile) override {
+    return std::make_unique(
+        CI.getASTContext(), Ctx, CI.getSourceManager(), CI.getPreprocessor());
+  }
+
+private:
+  InstallAPIContext &Ctx;
+};
+} // namespace installapi
+} // namespace clang
+
+#endif // LLVM_CLANG_INSTALLAPI_FRONTEND_H
diff --git a/clang/include/clang/InstallAPI/HeaderFile.h b/clang/include/clang/InstallAPI/HeaderFile.h
index fc64a43b3def5..70e83bbb3e76f 100644
--- a/clang/include/clang/InstallAPI/HeaderFile.h
+++ b/clang/include/clang/InstallAPI/HeaderFile.h
@@ -15,6 +15,7 @@
 
 #include "clang/Basic/LangStandard.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Regex.h"
 #include 
 #include 
@@ -32,6 +33,20 @@ enum class HeaderType {
   Project,
 };
 
+inline StringRef getName(const HeaderType T) {
+  switch (T) {
+  case HeaderType::Public:
+    return "Public";
+  case HeaderType::Private:
+    return "Private";
+  case HeaderType::Project:
+    return "Project";
+  case HeaderType::Unknown:
+    return "Unknown";
+  }
+  llvm_unreachable("unexpected header type");
+}
+
 class HeaderFile {
   /// Full input path to header.
   std::string FullPath;
@@ -52,6 +67,14 @@ class HeaderFile {
 
   static llvm::Regex getFrameworkIncludeRule();
 
+  HeaderType getType() const { return Type; }
+  StringRef getIncludeName() const { return IncludeName; }
+  StringRef getPath() const { return FullPath; }
+
+  bool useIncludeName() const {
+    return Type != HeaderType::Project && !IncludeName.empty();
+  }
+
   bool operator==(const HeaderFile &Other) const {
     return std::tie(Type, FullPath, IncludeName, Language) ==
            std::tie(Other.Type, Other.FullPath, Other.IncludeName,
diff --git a/clang/include/clang/InstallAPI/Visitor.h b/clang/include/clang/InstallAPI/Visitor.h
new file mode 100644
index 0000000000000..ff0a9957aa86b
--- /dev/null
+++ b/clang/include/clang/InstallAPI/Visitor.h
@@ -0,0 +1,72 @@
+//===- InstallAPI/Visitor.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
+//
+//===----------------------------------------------------------------------===//
+///
+/// ASTVisitor Interface for InstallAPI frontend operations.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INSTALLAPI_VISITOR_H
+#define LLVM_CLANG_INSTALLAPI_VISITOR_H
+
+#include "clang/AST/Mangle.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/InstallAPI/Context.h"
+#include "llvm/ADT/Twine.h"
+
+namespace clang {
+namespace installapi {
+
+/// ASTVisitor for collecting declarations that represent global symbols.
+class InstallAPIVisitor final : public ASTConsumer,
+                                public RecursiveASTVisitor {
+public:
+  InstallAPIVisitor(ASTContext &ASTCtx, InstallAPIContext &Ctx,
+                    SourceManager &SrcMgr, Preprocessor &PP)
+      : Ctx(Ctx), SrcMgr(SrcMgr), PP(PP),
+        MC(ItaniumMangleContext::create(ASTCtx, ASTCtx.getDiagnostics())),
+        Layout(ASTCtx.getTargetInfo().getDataLayoutString()) {}
+  void HandleTranslationUnit(ASTContext &ASTCtx) override;
+
+  /// Collect global variables.
+  bool VisitVarDecl(const VarDecl *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);
+
+private:
+  std::string getMangledName(const NamedDecl *D) const;
+  std::string getBackendMangledName(llvm::Twine Name) 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);
+
+  InstallAPIContext &Ctx;
+  SourceManager &SrcMgr;
+  Preprocessor &PP;
+  std::unique_ptr MC;
+  StringRef Layout;
+};
+
+} // namespace installapi
+} // namespace clang
+
+#endif // LLVM_CLANG_INSTALLAPI_VISITOR_H
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index 316e8071169a3..a176159707486 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -2359,11 +2359,27 @@ class Declarator {
       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 c4b6713105d66..2a7389f78a168 100644
--- a/clang/include/clang/Sema/ParsedAttr.h
+++ b/clang/include/clang/Sema/ParsedAttr.h
@@ -685,6 +685,7 @@ class AttributeFactory {
   ~AttributeFactory();
 };
 
+class ParsedAttributesView;
 class AttributePool {
   friend class AttributeFactory;
   friend class ParsedAttributes;
@@ -739,6 +740,10 @@ class AttributePool {
     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,
@@ -821,6 +826,7 @@ class AttributePool {
 };
 
 class ParsedAttributesView {
+  friend class AttributePool;
   using VecTy = llvm::SmallVector;
   using SizeType = decltype(std::declval().size());
 
diff --git a/clang/include/clang/Sema/Scope.h b/clang/include/clang/Sema/Scope.h
index b6b5a1f3479a2..099c2739e8603 100644
--- a/clang/include/clang/Sema/Scope.h
+++ b/clang/include/clang/Sema/Scope.h
@@ -43,6 +43,9 @@ class Scope {
   /// ScopeFlags - These are bitfields that are or'd together when creating a
   /// scope, which defines the sorts of things the scope contains.
   enum ScopeFlags {
+    // A bitfield value representing no scopes.
+    NoScope = 0,
+
     /// This indicates that the scope corresponds to a function, which
     /// means that labels are set here.
     FnScope = 0x01,
@@ -203,6 +206,10 @@ class Scope {
   /// other template parameter scopes as parents.
   Scope *TemplateParamParent;
 
+  /// DeclScopeParent - This is a direct link to the immediately containing
+  /// DeclScope, i.e. scope which can contain declarations.
+  Scope *DeclParent;
+
   /// DeclsInScope - This keeps track of all declarations in this scope.  When
   /// the declaration is added to the scope, it is set as the current
   /// declaration for the identifier in the IdentifierTable.  When the scope is
@@ -302,6 +309,9 @@ class Scope {
   Scope *getTemplateParamParent() { return TemplateParamParent; }
   const Scope *getTemplateParamParent() const { return TemplateParamParent; }
 
+  Scope *getDeclParent() { return DeclParent; }
+  const Scope *getDeclParent() const { return DeclParent; }
+
   /// Returns the depth of this scope. The translation-unit has scope depth 0.
   unsigned getDepth() const { return Depth; }
 
@@ -521,10 +531,17 @@ class Scope {
     return getFlags() & Scope::OpenACCComputeConstructScope;
   }
 
-  bool isInOpenACCComputeConstructScope() const {
+  /// Determine if this scope (or its parents) are a compute construct. If the
+  /// argument is provided, the search will stop at any of the specified scopes.
+  /// Otherwise, it will stop only at the normal 'no longer search' scopes.
+  bool isInOpenACCComputeConstructScope(ScopeFlags Flags = NoScope) const {
     for (const Scope *S = this; S; S = S->getParent()) {
-      if (S->getFlags() & Scope::OpenACCComputeConstructScope)
+      if (S->isOpenACCComputeConstructScope())
         return true;
+
+      if (S->getFlags() & Flags)
+        return false;
+
       else if (S->getFlags() &
                (Scope::FnScope | Scope::ClassScope | Scope::BlockScope |
                 Scope::TemplateParamScope | Scope::FunctionPrototypeScope |
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index cb6f95225fa10..247c5016451af 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -77,168 +77,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.
@@ -610,591 +610,709 @@ 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;
+  Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
+       TranslationUnitKind TUKind = TU_Complete,
+       CodeCompleteConsumer *CompletionConsumer = nullptr);
+  ~Sema();
 
-  const LangOptions &LangOpts;
-  Preprocessor &PP;
-  ASTContext &Context;
-  ASTConsumer &Consumer;
-  DiagnosticsEngine &Diags;
-  SourceManager &SourceMgr;
-  api_notes::APINotesManager APINotes;
+  /// Perform initialization that occurs after the parser has been
+  /// initialized but before it parses anything.
+  void Initialize();
 
-  /// Flag indicating whether or not to collect detailed statistics.
-  bool CollectStats;
+  /// 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();
 
-  /// Code-completion consumer.
-  CodeCompleteConsumer *CodeCompleter;
+  const LangOptions &getLangOpts() const { return LangOpts; }
+  OpenCLOptions &getOpenCLOptions() { return OpenCLFeatures; }
+  FPOptions &getCurFPFeatures() { return CurFPFeatures; }
 
-  /// CurContext - This is the current declaration context of parsing.
-  DeclContext *CurContext;
+  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(); }
 
-  /// Generally null except when we temporarily switch decl contexts,
-  /// like in \see ActOnObjCTemporaryExitContainerContext.
-  DeclContext *OriginalLexicalContext;
+  DarwinSDKInfo *getDarwinSDKInfoForAvailabilityChecking(SourceLocation Loc,
+                                                         StringRef Platform);
+  DarwinSDKInfo *getDarwinSDKInfoForAvailabilityChecking();
 
-  /// 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;
+  /// 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);
 
-  bool MSStructPragmaOn; // True when \#pragma ms_struct on
+  /// 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;
 
-  /// Controls member pointer representation format under the MS ABI.
-  LangOptions::PragmaMSPointersToMembersKind
-      MSPointerToMemberRepresentationMethod;
+  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) {}
 
-  /// Stack of active SEH __finally scopes.  Can be empty.
-  SmallVector CurrentSEHFinally;
+    // 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;
 
-  /// Source location for newly created implicit MSInheritanceAttrs
-  SourceLocation ImplicitMSInheritanceAttrLoc;
+    ~ImmediateDiagBuilder() {
+      // If we aren't active, there is nothing to do.
+      if (!isActive())
+        return;
 
-  /// 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;
+      // 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();
 
-  /// pragma clang section kind
-  enum PragmaClangSectionKind {
-    PCSK_Invalid      = 0,
-    PCSK_BSS          = 1,
-    PCSK_Data         = 2,
-    PCSK_Rodata       = 3,
-    PCSK_Text         = 4,
-    PCSK_Relro        = 5
-   };
+      // Dispatch to Sema to emit the diagnostic.
+      SemaRef.EmitCurrentDiagnostic(DiagID);
+    }
 
-  enum PragmaClangSectionAction {
-    PCSA_Set     = 0,
-    PCSA_Clear   = 1
-  };
+    /// 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 PragmaClangSection {
-    std::string SectionName;
-    bool Valid = false;
-    SourceLocation PragmaLocation;
+    // 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;
+    }
   };
 
-   PragmaClangSection PragmaClangBSSSection;
-   PragmaClangSection PragmaClangDataSection;
-   PragmaClangSection PragmaClangRodataSection;
-   PragmaClangSection PragmaClangRelroSection;
-   PragmaClangSection PragmaClangTextSection;
+  /// Bitmask to contain the list of reasons a single diagnostic should be
+  /// emitted, based on its language.  This permits multiple offload systems
+  /// to coexist in the same translation unit.
+  enum class DeviceDiagnosticReason {
+    /// Diagnostic doesn't apply to anything. Included for completeness, but
+    /// should make this a no-op.
+    None = 0,
+    /// OpenMP specific diagnostic.
+    OmpDevice = 1 << 0,
+    OmpHost = 1 << 1,
+    OmpAll = OmpDevice | OmpHost,
+    /// CUDA specific diagnostics.
+    CudaDevice = 1 << 2,
+    CudaHost = 1 << 3,
+    CudaAll = CudaDevice | CudaHost,
+    /// SYCL specific diagnostic.
+    Sycl = 1 << 4,
+    /// ESIMD specific diagnostic.
+    Esimd = 1 << 5,
+    /// A flag representing 'all'.  This can be used to avoid the check
+    /// all-together and make this behave as it did before the
+    /// DiagnosticReason was added (that is, unconditionally emit).
+    /// Note: This needs to be updated if any flags above are added.
+    All = OmpAll | CudaAll | Sycl | Esimd,
 
-  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)
+    LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/All)
   };
 
-  struct PragmaPackInfo {
-    PragmaMsStackAction Action;
-    StringRef SlotLabel;
-    Token Alignment;
-  };
+private:
+  // A collection of a pair of undefined functions and their callers known
+  // to be reachable from a routine on the device (kernel or device function).
+  typedef std::pair CallPair;
+  llvm::SmallVector UndefinedReachableFromSyclDevice;
 
-  // #pragma pack and align.
-  class AlignPackInfo {
+public:
+  // Helper routine to add a pair of Callee-Caller pair of FunctionDecl *
+  // to UndefinedReachableFromSyclDevice.
+  void addFDToReachableFromSyclDevice(const FunctionDecl *Callee,
+                                      const FunctionDecl *Caller) {
+    UndefinedReachableFromSyclDevice.push_back(std::make_pair(Callee, Caller));
+  }
+  // Helper routine to check if a pair of Callee-Caller FunctionDecl *
+  // is in UndefinedReachableFromSyclDevice.
+  bool isFDReachableFromSyclDevice(const FunctionDecl *Callee,
+                                   const FunctionDecl *Caller) {
+    return llvm::any_of(UndefinedReachableFromSyclDevice,
+                        [Callee, Caller](const CallPair &P) {
+                          return P.first == Callee && P.second == Caller;
+                        });
+  }
+
+  /// 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 };
+    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
+    };
 
-    // #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.");
-    }
+    SemaDiagnosticBuilder(Kind K, SourceLocation Loc, unsigned DiagID,
+                          const FunctionDecl *Fn, Sema &S, DeviceDiagnosticReason R);
+    SemaDiagnosticBuilder(SemaDiagnosticBuilder &&D);
+    SemaDiagnosticBuilder(const SemaDiagnosticBuilder &) = default;
 
-    // #pragma align info constructor
-    AlignPackInfo(AlignPackInfo::Mode M, bool IsXL)
-        : PackAttr(false), AlignMode(M),
-          PackNumber(M == Packed ? 1 : UninitPackVal), XLStack(IsXL) {}
+    // The copy and move assignment operator is defined as deleted pending
+    // further motivation.
+    SemaDiagnosticBuilder &operator=(const SemaDiagnosticBuilder &) = delete;
+    SemaDiagnosticBuilder &operator=(SemaDiagnosticBuilder &&) = delete;
 
-    explicit AlignPackInfo(bool IsXL) : AlignPackInfo(Native, IsXL) {}
+    ~SemaDiagnosticBuilder();
 
-    AlignPackInfo() : AlignPackInfo(Native, false) {}
+    bool isImmediate() const { return ImmediateDiag.has_value(); }
 
-    // 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;
+    /// 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.getAlignMode()) << 1;
+    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]
+                .getDiag()
+                .second
+            << Value;
+      return Diag;
+    }
 
-      if (Info.IsPackAttr())
-        Encoding |= PackAttrMask;
+    // 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].getDiag().second
+            << std::move(V);
+      return *this;
+    }
 
-      Encoding |= static_cast(Info.getPackNumber()) << 4;
+    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]
+            .getDiag()
+            .second = PD;
+      return Diag;
+    }
 
-      return Encoding;
+    void AddFixItHint(const FixItHint &Hint) const {
+      if (ImmediateDiag)
+        ImmediateDiag->AddFixItHint(Hint);
+      else if (PartialDiagId)
+        S.DeviceDeferredDiags[Fn][*PartialDiagId].getDiag().second.AddFixItHint(
+            Hint);
     }
 
-    static AlignPackInfo getFromRawEncoding(unsigned Encoding) {
-      bool IsXL = static_cast(Encoding & IsXLMask);
-      AlignPackInfo::Mode M =
-          static_cast((Encoding & AlignModeMask) >> 1);
-      int PackNumber = (Encoding & PackNumMask) >> 4;
+    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); }
 
-      if (Encoding & PackAttrMask)
-        return AlignPackInfo(M, PackNumber, IsXL);
+  private:
+    Sema &S;
+    SourceLocation Loc;
+    unsigned DiagID;
+    const FunctionDecl *Fn;
+    bool ShowCallStack;
 
-      return AlignPackInfo(M, IsXL);
-    }
+    // 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;
+  };
 
-    bool IsPackAttr() const { return PackAttr; }
+  void PrintStats() const;
 
-    bool IsAlignAttr() const { return !PackAttr; }
+  /// Warn that the stack is nearly exhausted.
+  void warnStackExhausted(SourceLocation Loc);
 
-    Mode getAlignMode() const { return AlignMode; }
+  /// 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);
 
-    unsigned getPackNumber() const { return PackNumber; }
+  /// Returns default addr space for method qualifiers.
+  LangAS getDefaultCXXMethodAddrSpace() 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;
-    }
+  /// Load weak undeclared identifiers from the external source.
+  void LoadExternalWeakUndeclaredIdentifiers();
 
-    bool IsXLStack() const { return XLStack; }
+  /// 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 operator==(const AlignPackInfo &Info) const {
-      return std::tie(AlignMode, PackNumber, PackAttr, XLStack) ==
-             std::tie(Info.AlignMode, Info.PackNumber, Info.PackAttr,
-                      Info.XLStack);
-    }
+  /// Obtain a sorted list of functions that are undefined but ODR-used.
+  void getUndefinedButUsed(
+      SmallVectorImpl> &Undefined);
 
-    bool operator!=(const AlignPackInfo &Info) const {
-      return !(*this == Info);
-    }
+  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;
 
-  private:
-    /// \brief True if this is a pragma pack attribute,
-    ///         not a pragma align attribute.
-    bool PackAttr;
+  /// 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 The alignment mode that is in effect.
-    Mode AlignMode;
+  void addImplicitTypedef(StringRef Name, QualType T);
 
-    /// \brief The pack number of the stack.
-    unsigned char PackNumber;
+  /// Emit a diagnostic.
+  SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID,
+                             bool DeferHint = false);
 
-    /// \brief True if it is a XL #pragma align/pack stack.
-    bool XLStack;
+  /// Emit a partial diagnostic.
+  SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic &PD,
+                             bool DeferHint = false);
 
-    /// \brief Uninitialized pack value.
-    static constexpr unsigned char UninitPackVal = -1;
+  /// Whether uncompilable error has occurred. This includes error happens
+  /// in deferred diagnostics.
+  bool hasUncompilableErrorOccurred() const;
 
-    // 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};
-  };
+  bool findMacroSpelling(SourceLocation &loc, StringRef name);
 
-  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) {}
-    };
+  /// Calls \c Lexer::getLocForEndOfToken()
+  SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0);
 
-    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;
-      }
-    }
+  /// Retrieve the module loader associated with the preprocessor.
+  ModuleLoader &getModuleLoader() 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);
-    }
+  /// Invent a new identifier for parameters of abbreviated templates.
+  IdentifierInfo *
+  InventAbbreviatedTemplateParameterTypeName(IdentifierInfo *ParamName,
+                                             unsigned Index);
 
-    // Constructors.
-    explicit PragmaStack(const ValueType &Default)
-        : DefaultValue(Default), CurrentValue(Default) {}
+  void emitAndClearUnusedLocalTypedefWarnings();
 
-    bool hasValue() const { return CurrentValue != DefaultValue; }
+  // Emit all deferred diagnostics.
+  void emitDeferredDiags();
 
-    SmallVector Stack;
-    ValueType DefaultValue; // Value used for PSK_Reset action.
-    ValueType CurrentValue;
-    SourceLocation CurrentPragmaLocation;
+  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
   };
-  // FIXME: We should serialize / deserialize these if they occur in a PCH (but
-  // we shouldn't do so if they're in a module).
 
-  /// 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 ActOnStartOfTranslationUnit();
+  void ActOnEndOfTranslationUnit();
+  void ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind);
 
-  // #pragma strict_gs_check.
-  PragmaStack StrictGuardStackCheckStack;
+  Scope *getScopeForContext(DeclContext *Ctx);
 
-  // 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;
-  }
+  void PushFunctionScope();
+  void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
+  sema::LambdaScopeInfo *PushLambdaScope();
 
-  // 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); }
+  /// 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);
 
-  private:
-    Sema &S;
-    PragmaStack SavedStack;
-  };
+  void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD,
+                               RecordDecl *RD, CapturedRegionKind K,
+                               unsigned OpenMPCaptureLevel = 0);
 
-  void resetFPOptions(FPOptions FPO) {
-    CurFPFeatures = FPO;
-    FpPragmaStack.CurrentValue = FPO.getChangesFrom(FPOptions(LangOpts));
-  }
+  /// Custom deleter to allow FunctionScopeInfos to be kept alive for a short
+  /// time after they've been popped.
+  class PoppedFunctionScopeDeleter {
+    Sema *Self;
 
-  // 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();
-
-  private:
-    Sema &S;
-    StringRef SlotLabel;
-    bool ShouldAct;
+    explicit PoppedFunctionScopeDeleter(Sema *Self) : Self(Self) {}
+    void operator()(sema::FunctionScopeInfo *Scope) const;
   };
 
-  /// A mapping that describes the nullability we've seen in each header file.
-  FileNullabilityMap NullabilityMap;
+  using PoppedFunctionScopePtr =
+      std::unique_ptr;
 
-  /// Last section used with #pragma init_seg.
-  StringLiteral *CurInitSeg;
-  SourceLocation CurInitSegLoc;
+  PoppedFunctionScopePtr
+  PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP = nullptr,
+                       const Decl *D = nullptr,
+                       QualType BlockType = QualType());
 
-  /// Sections used with #pragma alloc_text.
-  llvm::StringMap> FunctionToSectionMap;
+  sema::FunctionScopeInfo *getEnclosingFunction() const;
 
-  /// VisContext - Manages the stack for \#pragma GCC visibility.
-  void *VisContext; // Really a "PragmaVisStack*"
+  void setFunctionHasBranchIntoScope();
+  void setFunctionHasBranchProtectedScope();
+  void setFunctionHasIndirectGoto();
+  void setFunctionHasMustTail();
 
-  /// This an attribute introduced by \#pragma clang attribute.
-  struct PragmaAttributeEntry {
-    SourceLocation Loc;
-    ParsedAttr *Attribute;
-    SmallVector MatchRules;
-    bool IsUsed;
-  };
+  void PushCompoundScope(bool IsStmtExpr);
+  void PopCompoundScope();
 
-  /// 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;
-  };
+  bool hasAnyUnrecoverableErrorsInThisFunction() const;
 
-  SmallVector PragmaAttributeStack;
+  /// Retrieve the current block, if any.
+  sema::BlockScopeInfo *getCurBlock();
 
-  /// The declaration that is currently receiving an attribute from the
-  /// #pragma attribute stack.
-  const Decl *PragmaAttributeCurrentTargetDecl;
+  /// 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;
 
-  /// 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;
+  /// 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);
 
-  /// 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;
+  /// Retrieve the current generic lambda info, if any.
+  sema::LambdaScopeInfo *getCurGenericLambda();
 
-  /// Set of no-builtin functions listed by \#pragma function.
-  llvm::SmallSetVector MSFunctionNoBuiltins;
+  /// Retrieve the current captured region, if any.
+  sema::CapturedRegionScopeInfo *getCurCapturedRegion();
 
-  /// Flag indicating if Sema is building a recovery call expression.
+  void ActOnComment(SourceRange Comment);
+
+  /// Retrieve the parser's current scope.
   ///
-  /// This flag is used to avoid building recovery call expressions
-  /// if Sema is already doing so, which would cause infinite recursions.
-  bool IsBuildingRecoveryCallExpr;
+  /// 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; }
 
-  /// Used to control the generation of ExprWithCleanups.
-  CleanupInfo Cleanup;
+  IdentifierInfo *getSuperIdentifier() const;
 
-  /// ExprCleanupObjects - This is the stack of objects requiring
-  /// cleanup that are created by the current full expression.
-  SmallVector ExprCleanupObjects;
+  DeclContext *getCurLexicalContext() const {
+    return OriginalLexicalContext ? OriginalLexicalContext : CurContext;
+  }
 
-  /// 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;
+  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;
+  }
 
-  std::unique_ptr CachedFunctionScope;
+  /// Check if the type is allowed to be used for the current target.
+  void checkTypeSupport(QualType Ty, SourceLocation Loc,
+                        ValueDecl *D = nullptr);
 
-  /// Stack containing information about each of the nested
-  /// function, block, and method scopes that are currently active.
-  SmallVector FunctionScopes;
+  /// 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
+  };
 
-  /// The index of the first FunctionScope that corresponds to the current
-  /// context.
-  unsigned FunctionScopesStart = 0;
+  /// 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);
 
-  /// Track the number of currently active capturing scopes.
-  unsigned CapturingFunctionScopes = 0;
+  /// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding
+  /// to the conversion from scalar type ScalarTy to the Boolean type.
+  static CastKind ScalarTypeToBooleanCastKind(QualType ScalarTy);
 
-  ArrayRef getFunctionScopes() const {
-    return llvm::ArrayRef(FunctionScopes.begin() + FunctionScopesStart,
-                          FunctionScopes.end());
-  }
+  /// If \p AllowLambda is true, treat lambda as function.
+  DeclContext *getFunctionLevelDeclContext(bool AllowLambda = false) const;
 
-  /// 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;
+  /// 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;
 
-  /// The index of the first InventedParameterInfo that refers to the current
-  /// context.
-  unsigned InventedParameterInfosStart = 0;
+  /// 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();
 
-  ArrayRef getInventedParameterInfos() const {
-    return llvm::ArrayRef(InventedParameterInfos.begin() +
-                              InventedParameterInfosStart,
-                          InventedParameterInfos.end());
+  /// 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;
+
+  /// 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);
   }
 
-  typedef LazyVector
-    ExtVectorDeclsType;
+  /// Retrieve a suitable printing policy for diagnostics.
+  static PrintingPolicy getPrintingPolicy(const ASTContext &Ctx,
+                                          const Preprocessor &PP);
 
-  /// 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;
+  /// Scope actions.
+  void ActOnTranslationUnitScope(Scope *S);
 
-  /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes.
-  std::unique_ptr FieldCollector;
+  /// Determine whether \param D is function like (function or function
+  /// template) for parsing.
+  bool isDeclaratorFunctionLike(Declarator &D);
 
-  typedef llvm::SmallSetVector NamedDeclSetType;
+  /// 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;
 
-  /// Set containing all declared private fields that are not used.
-  NamedDeclSetType UnusedPrivateFields;
+  /// Flag indicating whether or not to collect detailed statistics.
+  bool CollectStats;
 
-  /// Set containing all typedefs that are likely unused.
-  llvm::SmallSetVector
-      UnusedLocalTypedefNameCandidates;
+  std::unique_ptr CachedFunctionScope;
 
-  /// Delete-expressions to be analyzed at the end of translation unit
+  /// Stack containing information about each of the nested
+  /// function, block, and method scopes that are currently active.
+  SmallVector FunctionScopes;
+
+  /// The index of the first FunctionScope that corresponds to the current
+  /// context.
+  unsigned FunctionScopesStart = 0;
+
+  /// Track the number of currently active capturing scopes.
+  unsigned CapturingFunctionScopes = 0;
+
+  llvm::BumpPtrAllocator BumpAlloc;
+
+  /// The kind of translation unit we are processing.
   ///
-  /// 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;
+  /// 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 llvm::SmallPtrSet RecordDeclSetTy;
+  /// 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;
 
-  /// 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 WarnedStackExhausted = false;
 
-  /// ParsingInitForAutoVars - a set of declarations with auto types for which
-  /// we are currently parsing the initializer.
-  llvm::SmallPtrSet ParsingInitForAutoVars;
+  void incrementMSManglingNumber() const {
+    return CurScope->incrementMSManglingNumber();
+  }
 
-  /// Look for a locally scoped extern "C" declaration by the given name.
-  NamedDecl *findLocallyScopedExternCDecl(DeclarationName Name);
+  /// 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);
 
-  typedef LazyVector
-    TentativeDefinitionsType;
+  /// Figure out if an expression could be turned into a call.
+  bool tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
+                     UnresolvedSetImpl &NonTemplateOverloads);
 
-  /// All the tentative definitions encountered in the TU.
-  TentativeDefinitionsType TentativeDefinitions;
+  typedef OpaquePtr DeclGroupPtrTy;
+  typedef OpaquePtr TemplateTy;
+  typedef OpaquePtr TypeTy;
 
-  /// All the external declarations encoutered and used in the TU.
-  SmallVector ExternalDeclarations;
+  OpenCLOptions OpenCLFeatures;
+  FPOptions CurFPFeatures;
 
-  typedef LazyVector
-    UnusedFileScopedDeclsType;
+  const LangOptions &LangOpts;
+  Preprocessor &PP;
+  ASTContext &Context;
+  ASTConsumer &Consumer;
+  DiagnosticsEngine &Diags;
+  SourceManager &SourceMgr;
+  api_notes::APINotesManager APINotes;
 
-  /// 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;
+  /// A RAII object to enter scope of a compound statement.
+  class CompoundScopeRAII {
+  public:
+    CompoundScopeRAII(Sema &S, bool IsStmtExpr = false) : S(S) {
+      S.ActOnStartOfCompoundStmt(IsStmtExpr);
+    }
 
-  typedef LazyVector
-    DelegatingCtorDeclsType;
+    ~CompoundScopeRAII() { S.ActOnFinishOfCompoundStmt(); }
 
-  /// All the delegating constructors seen so far in the file, used for
-  /// cycle detection at the end of the TU.
-  DelegatingCtorDeclsType DelegatingCtorDecls;
+  private:
+    Sema &S;
+  };
 
-  /// All the overriding functions seen during a class definition
-  /// that had their exception spec checks delayed, plus the overridden
-  /// function.
-  SmallVector, 2>
-    DelayedOverridingExceptionSpecChecks;
+  /// 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; }
+  };
 
-  /// 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;
+  /// Build a partial diagnostic.
+  PartialDiagnostic PDiag(unsigned DiagID = 0); // in SemaInternal.h
 
-  typedef llvm::MapVector>
-      LateParsedTemplateMapT;
-  LateParsedTemplateMapT LateParsedTemplateMap;
+  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);
@@ -1204,8 +1322,7 @@ class Sema final {
   void *OpaqueParser;
 
   void SetLateTemplateParser(LateTemplateParserCB *LTP,
-                             LateTemplateParserCleanupCB *LTPCleanup,
-                             void *P) {
+                             LateTemplateParserCleanupCB *LTPCleanup, void *P) {
     LateTemplateParser = LTP;
     LateTemplateParserCleanup = LTPCleanup;
     OpaqueParser = P;
@@ -1215,6 +1332,14 @@ class Sema final {
   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 {
@@ -1241,9 +1366,7 @@ class Sema final {
     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.
@@ -1277,1751 +1400,1677 @@ class Sema final {
     }
   } 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();
-    }
-  };
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// 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;
+  /// \name C++ Access Control
+  /// Implementations are in SemaAccess.cpp
+  ///@{
 
-  /// 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;
+public:
+  enum AccessResult {
+    AR_accessible,
+    AR_inaccessible,
+    AR_dependent,
+    AR_delayed
+  };
 
+  bool SetMemberAccessSpecifier(NamedDecl *MemberDecl,
+                                NamedDecl *PrevMemberDecl,
+                                AccessSpecifier LexicalAS);
 
-  /// Load weak undeclared identifiers from the external source.
-  void LoadExternalWeakUndeclaredIdentifiers();
+  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());
+  }
 
-  /// 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;
+  void HandleDependentAccessCheck(
+      const DependentDiagnostic &DD,
+      const MultiLevelTemplateArgumentList &TemplateArgs);
+  void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
 
-  IdentifierResolver IdResolver;
+  ///@}
 
-  /// 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 C++ "std" namespace, where the standard library resides.
-  LazyDeclPtr StdNamespace;
+  /// \name Attributes
+  /// Implementations are in SemaAttr.cpp
+  ///@{
 
-  /// The C++ "std::bad_alloc" class, which is defined by the C++
-  /// standard library.
-  LazyDeclPtr StdBadAlloc;
+public:
+  /// Controls member pointer representation format under the MS ABI.
+  LangOptions::PragmaMSPointersToMembersKind
+      MSPointerToMemberRepresentationMethod;
 
-  /// The C++ "std::align_val_t" enum class, which is defined by the C++
-  /// standard library.
-  LazyDeclPtr StdAlignValT;
+  bool MSStructPragmaOn; // True when \#pragma ms_struct on
 
-  /// The C++ "std::initializer_list" template, which is defined in
-  /// \.
-  ClassTemplateDecl *StdInitializerList;
+  /// Source location for newly created implicit MSInheritanceAttrs
+  SourceLocation ImplicitMSInheritanceAttrLoc;
 
-  /// The C++ "std::coroutine_traits" template, which is defined in
-  /// \
-  ClassTemplateDecl *StdCoroutineTraitsCache;
+  /// 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++ "type_info" declaration, which is defined in \.
-  RecordDecl *CXXTypeInfoDecl;
+  enum PragmaClangSectionAction { PCSA_Set = 0, PCSA_Clear = 1 };
 
-  /// The C++ "std::source_location::__impl" struct, defined in
-  /// \.
-  RecordDecl *StdSourceLocationImplDecl;
+  struct PragmaClangSection {
+    std::string SectionName;
+    bool Valid = false;
+    SourceLocation PragmaLocation;
+  };
 
-  /// Caches identifiers/selectors for NSFoundation APIs.
-  std::unique_ptr NSAPIObj;
+  PragmaClangSection PragmaClangBSSSection;
+  PragmaClangSection PragmaClangDataSection;
+  PragmaClangSection PragmaClangRodataSection;
+  PragmaClangSection PragmaClangRelroSection;
+  PragmaClangSection PragmaClangTextSection;
 
-  /// The declaration of the Objective-C NSNumber class.
-  ObjCInterfaceDecl *NSNumberDecl;
+  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)
+  };
 
-  /// The declaration of the Objective-C NSValue class.
-  ObjCInterfaceDecl *NSValueDecl;
+  struct PragmaPackInfo {
+    PragmaMsStackAction Action;
+    StringRef SlotLabel;
+    Token Alignment;
+  };
 
-  /// Pointer to NSNumber type (NSNumber *).
-  QualType NSNumberPointer;
+  // #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 };
 
-  /// Pointer to NSValue type (NSValue *).
-  QualType NSValuePointer;
+    // #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.");
+    }
 
-  /// The Objective-C NSNumber methods used to create NSNumber literals.
-  ObjCMethodDecl *NSNumberLiteralMethods[NSAPI::NumNSNumberLiteralMethods];
+    // #pragma align info constructor
+    AlignPackInfo(AlignPackInfo::Mode M, bool IsXL)
+        : PackAttr(false), AlignMode(M),
+          PackNumber(M == Packed ? 1 : UninitPackVal), XLStack(IsXL) {}
 
-  /// The declaration of the Objective-C NSString class.
-  ObjCInterfaceDecl *NSStringDecl;
+    explicit AlignPackInfo(bool IsXL) : AlignPackInfo(Native, IsXL) {}
 
-  /// Pointer to NSString type (NSString *).
-  QualType NSStringPointer;
+    AlignPackInfo() : AlignPackInfo(Native, false) {}
 
-  /// The declaration of the stringWithUTF8String: method.
-  ObjCMethodDecl *StringWithUTF8StringMethod;
+    // 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;
 
-  /// The declaration of the valueWithBytes:objCType: method.
-  ObjCMethodDecl *ValueWithBytesObjCTypeMethod;
+      Encoding |= static_cast(Info.getAlignMode()) << 1;
 
-  /// The declaration of the Objective-C NSArray class.
-  ObjCInterfaceDecl *NSArrayDecl;
+      if (Info.IsPackAttr())
+        Encoding |= PackAttrMask;
 
-  /// The declaration of the arrayWithObjects:count: method.
-  ObjCMethodDecl *ArrayWithObjectsMethod;
+      Encoding |= static_cast(Info.getPackNumber()) << 4;
 
-  /// The declaration of the Objective-C NSDictionary class.
-  ObjCInterfaceDecl *NSDictionaryDecl;
-
-  /// The declaration of the dictionaryWithObjects:forKeys:count: method.
-  ObjCMethodDecl *DictionaryWithObjectsMethod;
+      return Encoding;
+    }
 
-  /// id type.
-  QualType QIDNSCopying;
+    static AlignPackInfo getFromRawEncoding(unsigned Encoding) {
+      bool IsXL = static_cast(Encoding & IsXLMask);
+      AlignPackInfo::Mode M =
+          static_cast((Encoding & AlignModeMask) >> 1);
+      int PackNumber = (Encoding & PackNumMask) >> 4;
 
-  /// will hold 'respondsToSelector:'
-  Selector RespondsToSelectorSel;
+      if (Encoding & PackAttrMask)
+        return AlignPackInfo(M, PackNumber, IsXL);
 
-  /// A flag to remember whether the implicit forms of operator new and delete
-  /// have been declared.
-  bool GlobalNewDeleteDeclared;
+      return AlignPackInfo(M, IsXL);
+    }
 
-  /// 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,
+    bool IsPackAttr() const { return PackAttr; }
 
-    /// 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,
+    bool IsAlignAttr() const { return !PackAttr; }
 
-    /// 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,
+    Mode getAlignMode() const { return AlignMode; }
 
-    /// 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,
+    unsigned getPackNumber() const { return PackNumber; }
 
-    /// 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 IsPackSet() const {
+      // #pragma align, #pragma pack(), and #pragma pack(0) do not set the pack
+      // attriute on a decl.
+      return PackNumber != UninitPackVal && PackNumber != 0;
+    }
 
-    /// 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 IsXLStack() const { return XLStack; }
 
-    /// 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,
+    bool operator==(const AlignPackInfo &Info) const {
+      return std::tie(AlignMode, PackNumber, PackAttr, XLStack) ==
+             std::tie(Info.AlignMode, Info.PackNumber, Info.PackAttr,
+                      Info.XLStack);
+    }
 
-    /// 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
-  };
+    bool operator!=(const AlignPackInfo &Info) const {
+      return !(*this == Info);
+    }
 
-  using ImmediateInvocationCandidate = llvm::PointerIntPair;
+  private:
+    /// \brief True if this is a pragma pack attribute,
+    ///         not a pragma align attribute.
+    bool PackAttr;
 
-  /// Data structure used to record current or nested
-  /// expression evaluation contexts.
-  struct ExpressionEvaluationContextRecord {
-    /// The expression evaluation context.
-    ExpressionEvaluationContext Context;
+    /// \brief The alignment mode that is in effect.
+    Mode AlignMode;
 
-    /// Whether the enclosing context needed a cleanup.
-    CleanupInfo ParentCleanup;
+    /// \brief The pack number of the stack.
+    unsigned char PackNumber;
 
-    /// The number of active cleanup objects when we entered
-    /// this expression evaluation context.
-    unsigned NumCleanupObjects;
+    /// \brief True if it is a XL #pragma align/pack stack.
+    bool XLStack;
 
-    /// The number of typos encountered during this expression evaluation
-    /// context (i.e. the number of TypoExprs created).
-    unsigned NumTypos;
+    /// \brief Uninitialized pack value.
+    static constexpr unsigned char UninitPackVal = -1;
 
-    MaybeODRUseExprSet SavedMaybeODRUseExprs;
+    // 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 lambdas that are present within this context, if it
-    /// is indeed an unevaluated context.
-    SmallVector Lambdas;
+  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) {}
+    };
 
-    /// 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;
+    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;
+      }
+    }
 
-    /// 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;
+    // 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);
+    }
 
-    /// If we are processing a decltype type, a set of temporary binding
-    /// expressions for which we have deferred checking the destructor.
-    SmallVector DelayedDecltypeBinds;
+    // Constructors.
+    explicit PragmaStack(const ValueType &Default)
+        : DefaultValue(Default), CurrentValue(Default) {}
 
-    llvm::SmallPtrSet PossibleDerefs;
+    bool hasValue() const { return CurrentValue != DefaultValue; }
 
-    /// 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;
+    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).
 
-    /// Set of candidates for starting an immediate invocation.
-    llvm::SmallVector ImmediateInvocationCandidates;
+  /// 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;
 
-    /// Set of DeclRefExprs referencing a consteval function when used in a
-    /// context not already known to be immediately invoked.
-    llvm::SmallPtrSet ReferenceToConsteval;
+  // #pragma strict_gs_check.
+  PragmaStack StrictGuardStackCheckStack;
 
-    /// 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;
+  // 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;
+  }
 
-    /// \brief Describes whether we are in an expression constext which we have
-    /// to handle differently.
-    enum ExpressionKind {
-      EK_Decltype, EK_TemplateArgument, EK_Other
-    } ExprContext;
+  enum PragmaSectionKind {
+    PSK_DataSeg,
+    PSK_BSSSeg,
+    PSK_ConstSeg,
+    PSK_CodeSeg,
+  };
 
-    // 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;
+  // 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();
 
-    bool IsCurrentlyCheckingDefaultArgumentOrInitializer = false;
+  private:
+    Sema &S;
+    StringRef SlotLabel;
+    bool ShouldAct;
+  };
 
-    // 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;
+  /// Last section used with #pragma init_seg.
+  StringLiteral *CurInitSeg;
+  SourceLocation CurInitSegLoc;
 
-    /// 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;
+  /// Sections used with #pragma alloc_text.
+  llvm::StringMap> FunctionToSectionMap;
 
-    /// 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;
+  /// VisContext - Manages the stack for \#pragma GCC visibility.
+  void *VisContext; // Really a "PragmaVisStack*"
 
-    // 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");
-      }
+  /// This an attribute introduced by \#pragma clang attribute.
+  struct PragmaAttributeEntry {
+    SourceLocation Loc;
+    ParsedAttr *Attribute;
+    SmallVector MatchRules;
+    bool IsUsed;
+  };
 
-      SourceLocation Loc;
-      ValueDecl *Decl = nullptr;
-      DeclContext *Context = nullptr;
-    };
-    std::optional DelayedDefaultInitializationContext;
+  /// 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;
+  };
 
-    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) {}
+  SmallVector PragmaAttributeStack;
 
-    bool isUnevaluated() const {
-      return Context == ExpressionEvaluationContext::Unevaluated ||
-             Context == ExpressionEvaluationContext::UnevaluatedAbstract ||
-             Context == ExpressionEvaluationContext::UnevaluatedList;
-    }
+  /// The declaration that is currently receiving an attribute from the
+  /// #pragma attribute stack.
+  const Decl *PragmaAttributeCurrentTargetDecl;
 
-    bool isConstantEvaluated() const {
-      return Context == ExpressionEvaluationContext::ConstantEvaluated ||
-             Context == ExpressionEvaluationContext::ImmediateFunctionContext;
-    }
+  /// 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 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);
-    }
+  /// 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 isDiscardedStatementContext() const {
-      return Context == ExpressionEvaluationContext::DiscardedStatement ||
-             (Context ==
-                  ExpressionEvaluationContext::ImmediateFunctionContext &&
-              InDiscardedStatement);
-    }
-  };
+  /// 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;
 
-  /// A stack of expression evaluation contexts.
-  SmallVector ExprEvalContexts;
+  /// Set of no-builtin functions listed by \#pragma function.
+  llvm::SmallSetVector MSFunctionNoBuiltins;
 
-  // Set of failed immediate invocations to avoid double diagnosing.
-  llvm::SmallPtrSet FailedImmediateInvocations;
+  /// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to
+  /// a the record decl, to handle '\#pragma pack' and '\#pragma options align'.
+  void AddAlignmentAttributesForRecord(RecordDecl *RD);
 
-  /// Emit a warning for all pending noderef expressions that we recorded.
-  void WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec);
+  /// AddMsStructLayoutForRecord - Adds ms_struct layout attribute to record.
+  void AddMsStructLayoutForRecord(RecordDecl *RD);
 
-  /// 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 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);
 
+  /// Add [[gsl::Owner]] and [[gsl::Pointer]] attributes for std:: types.
+  void inferGslOwnerPointerAttribute(CXXRecordDecl *Record);
 
-  /// 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
-    };
+  /// Add [[gsl::Pointer]] attributes for std:: types.
+  void inferGslPointerAttribute(TypedefNameDecl *TD);
 
-  private:
-    llvm::PointerIntPair Pair;
+  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:
-    SpecialMemberOverloadResult() {}
-    SpecialMemberOverloadResult(CXXMethodDecl *MD)
-        : Pair(MD, MD->isDeleted() ? NoMemberOrDeleted : Success) {}
+  /// ActOnPragmaClangSection - Called on well formed \#pragma clang section
+  void ActOnPragmaClangSection(SourceLocation PragmaLoc,
+                               PragmaClangSectionAction Action,
+                               PragmaClangSectionKind SecKind,
+                               StringRef SecName);
 
-    CXXMethodDecl *getMethod() const { return Pair.getPointer(); }
-    void setMethod(CXXMethodDecl *MD) { Pair.setPointer(MD); }
+  /// ActOnPragmaOptionsAlign - Called on well formed \#pragma options align.
+  void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
+                               SourceLocation PragmaLoc);
 
-    Kind getKind() const { return static_cast(Pair.getInt()); }
-    void setKind(Kind K) { Pair.setInt(K); }
-  };
+  /// ActOnPragmaPack - Called on well formed \#pragma pack(...).
+  void ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
+                       StringRef SlotLabel, Expr *Alignment);
 
-  class SpecialMemberOverloadResultEntry
-      : public llvm::FastFoldingSetNode,
-        public SpecialMemberOverloadResult {
-  public:
-    SpecialMemberOverloadResultEntry(const llvm::FoldingSetNodeID &ID)
-      : FastFoldingSetNode(ID)
-    {}
+  /// 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);
+
+  enum class PragmaAlignPackDiagnoseKind {
+    NonDefaultStateAtInclude,
+    ChangedStateAtExit
   };
 
-  /// A cache of special member function overload resolution results
-  /// for C++ records.
-  llvm::FoldingSet SpecialMemberCache;
+  void DiagnoseNonDefaultPragmaAlignPack(PragmaAlignPackDiagnoseKind Kind,
+                                         SourceLocation IncludeLoc);
+  void DiagnoseUnterminatedPragmaAlignPack();
 
-  /// A cache of the flags available in enumerations with the flag_bits
-  /// attribute.
-  mutable llvm::DenseMap FlagBitsCache;
+  /// ActOnPragmaMSStruct - Called on well formed \#pragma ms_struct [on|off].
+  void ActOnPragmaMSStruct(PragmaMSStructKind Kind);
 
-  /// 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;
+  /// ActOnPragmaMSComment - Called on well formed
+  /// \#pragma comment(kind, "arg").
+  void ActOnPragmaMSComment(SourceLocation CommentLoc, PragmaMSCommentKind Kind,
+                            StringRef Arg);
 
-  llvm::BumpPtrAllocator BumpAlloc;
+  /// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch
+  void ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name,
+                                 StringRef Value);
 
-  /// The number of SFINAE diagnostics that have been trapped.
-  unsigned NumSFINAEErrors;
+  /// Are precise floating point semantics currently enabled?
+  bool isPreciseFPEnabled() {
+    return !CurFPFeatures.getAllowFPReassociate() &&
+           !CurFPFeatures.getNoSignedZero() &&
+           !CurFPFeatures.getAllowReciprocal() &&
+           !CurFPFeatures.getAllowApproxFunc();
+  }
 
-  typedef llvm::DenseMap>
-    UnparsedDefaultArgInstantiationsMap;
+  void ActOnPragmaFPEvalMethod(SourceLocation Loc,
+                               LangOptions::FPEvalMethodKind 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;
+  /// ActOnPragmaFloatControl - Call on well-formed \#pragma float_control
+  void ActOnPragmaFloatControl(SourceLocation Loc, PragmaMsStackAction Action,
+                               PragmaFloatControlKind Value);
 
-  // Contains the locations of the beginning of unparsed default
-  // argument locations.
-  llvm::DenseMap UnparsedDefaultArgLocs;
+  /// ActOnPragmaMSPointersToMembers - called on well formed \#pragma
+  /// pointers_to_members(representation method[, general purpose
+  /// representation]).
+  void ActOnPragmaMSPointersToMembers(
+      LangOptions::PragmaMSPointersToMembersKind Kind,
+      SourceLocation PragmaLoc);
 
-  /// UndefinedInternals - all the used, undefined objects which require a
-  /// definition in this translation unit.
-  llvm::MapVector UndefinedButUsed;
+  /// Called on well formed \#pragma vtordisp().
+  void ActOnPragmaMSVtorDisp(PragmaMsStackAction Action,
+                             SourceLocation PragmaLoc, MSVtorDispMode Value);
 
-  /// 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();
-
-  /// 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();
-
-  const LangOptions &getLangOpts() const { return LangOpts; }
-  OpenCLOptions &getOpenCLOptions() { return OpenCLFeatures; }
-  FPOptions     &getCurFPFeatures() { return CurFPFeatures; }
+  /// Called on well formed '\#pragma clang fp' that has option 'exceptions'.
+  void ActOnPragmaFPExceptions(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(); }
+  /// Called to set constant rounding mode for floating point operations.
+  void ActOnPragmaFEnvRound(SourceLocation Loc, llvm::RoundingMode);
 
-  DarwinSDKInfo *getDarwinSDKInfoForAvailabilityChecking(SourceLocation Loc,
-                                                         StringRef Platform);
-  DarwinSDKInfo *getDarwinSDKInfoForAvailabilityChecking();
+  /// Called to set exception behavior for floating point operations.
+  void setExceptionMode(SourceLocation Loc, LangOptions::FPExceptionModeKind);
 
-  ///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);
+  /// PushNamespaceVisibilityAttr - Note that we've entered a
+  /// namespace with a visibility attribute.
+  void PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
+                                   SourceLocation Loc);
 
-  void PrintStats() const;
+  /// 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);
 
-  /// Warn that the stack is nearly exhausted.
-  void warnStackExhausted(SourceLocation Loc);
+  /// 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);
 
-  /// 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);
+  ///@}
 
-  /// 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:
-    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) {}
+  /// \name Availability Attribute Handling
+  /// Implementations are in SemaAvailability.cpp
+  ///@{
 
-    // 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;
+public:
+  /// Issue any -Wunguarded-availability warnings in \c FD
+  void DiagnoseUnguardedAvailabilityViolations(Decl *FD);
 
-    ~ImmediateDiagBuilder() {
-      // If we aren't active, there is nothing to do.
-      if (!isActive()) return;
+  void handleDelayedAvailabilityCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
 
-      // 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();
+  /// Retrieve the current function, if any, that should be analyzed for
+  /// potential availability violations.
+  sema::FunctionScopeInfo *getCurFunctionAvailabilityContext();
 
-      // Dispatch to Sema to emit the diagnostic.
-      SemaRef.EmitCurrentDiagnostic(DiagID);
-    }
+  void DiagnoseAvailabilityOfDecl(NamedDecl *D, ArrayRef Locs,
+                                  const ObjCInterfaceDecl *UnknownObjCClass,
+                                  bool ObjCPropertyAccess,
+                                  bool AvoidPartialAvailabilityChecks = false,
+                                  ObjCInterfaceDecl *ClassReceiver = nullptr);
 
-    /// 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;
-    }
+  ///@}
 
-    // 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;
-    }
-  };
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// Bitmask to contain the list of reasons a single diagnostic should be
-  /// emitted, based on its language.  This permits multiple offload systems
-  /// to coexist in the same translation unit.
-  enum class DeviceDiagnosticReason {
-    /// Diagnostic doesn't apply to anything. Included for completeness, but
-    /// should make this a no-op.
-    None = 0,
-    /// OpenMP specific diagnostic.
-    OmpDevice = 1 << 0,
-    OmpHost = 1 << 1,
-    OmpAll = OmpDevice | OmpHost,
-    /// CUDA specific diagnostics.
-    CudaDevice = 1 << 2,
-    CudaHost = 1 << 3,
-    CudaAll = CudaDevice | CudaHost,
-    /// SYCL specific diagnostic.
-    Sycl = 1 << 4,
-    /// ESIMD specific diagnostic.
-    Esimd = 1 << 5,
-    /// A flag representing 'all'.  This can be used to avoid the check
-    /// all-together and make this behave as it did before the
-    /// DiagnosticReason was added (that is, unconditionally emit).
-    /// Note: This needs to be updated if any flags above are added.
-    All = OmpAll | CudaAll | Sycl | Esimd,
+  SYCLIntelIVDepAttr *
+  BuildSYCLIntelIVDepAttr(const AttributeCommonInfo &CI, Expr *Expr1,
+                          Expr *Expr2);
+  LoopUnrollHintAttr *BuildLoopUnrollHintAttr(const AttributeCommonInfo &A,
+                                              Expr *E);
+  OpenCLUnrollHintAttr *
+  BuildOpenCLLoopUnrollHintAttr(const AttributeCommonInfo &A, Expr *E);
 
-    LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/All)
-  };
+  SYCLIntelLoopCountAttr *
+  BuildSYCLIntelLoopCountAttr(const AttributeCommonInfo &CI, Expr *E);
+  SYCLIntelInitiationIntervalAttr *
+  BuildSYCLIntelInitiationIntervalAttr(const AttributeCommonInfo &CI,
+                                       Expr *E);
+  SYCLIntelMaxConcurrencyAttr *
+  BuildSYCLIntelMaxConcurrencyAttr(const AttributeCommonInfo &CI, Expr *E);
+  SYCLIntelMaxInterleavingAttr *
+  BuildSYCLIntelMaxInterleavingAttr(const AttributeCommonInfo &CI, Expr *E);
+  SYCLIntelSpeculatedIterationsAttr *
+  BuildSYCLIntelSpeculatedIterationsAttr(const AttributeCommonInfo &CI,
+                                         Expr *E);
+  SYCLIntelLoopCoalesceAttr *
+  BuildSYCLIntelLoopCoalesceAttr(const AttributeCommonInfo &CI, Expr *E);
+  SYCLIntelMaxReinvocationDelayAttr *
+  BuildSYCLIntelMaxReinvocationDelayAttr(const AttributeCommonInfo &CI,
+                                         Expr *E);
 
-private:
-  // A collection of a pair of undefined functions and their callers known
-  // to be reachable from a routine on the device (kernel or device function).
-  typedef std::pair CallPair;
-  llvm::SmallVector UndefinedReachableFromSyclDevice;
+  /// \name Casts
+  /// Implementations are in SemaCast.cpp
+  ///@{
 
 public:
-  // Helper routine to add a pair of Callee-Caller pair of FunctionDecl *
-  // to UndefinedReachableFromSyclDevice.
-  void addFDToReachableFromSyclDevice(const FunctionDecl *Callee,
-                                      const FunctionDecl *Caller) {
-    UndefinedReachableFromSyclDevice.push_back(std::make_pair(Callee, Caller));
-  }
-  // Helper routine to check if a pair of Callee-Caller FunctionDecl *
-  // is in UndefinedReachableFromSyclDevice.
-  bool isFDReachableFromSyclDevice(const FunctionDecl *Callee,
-                                   const FunctionDecl *Caller) {
-    return llvm::any_of(UndefinedReachableFromSyclDevice,
-                        [Callee, Caller](const CallPair &P) {
-                          return P.first == Callee && P.second == Caller;
-                        });
+  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
-    };
-
-    SemaDiagnosticBuilder(Kind K, SourceLocation Loc, unsigned DiagID,
-                          const FunctionDecl *Fn, Sema &S, DeviceDiagnosticReason R);
-    SemaDiagnosticBuilder(SemaDiagnosticBuilder &&D);
-    SemaDiagnosticBuilder(const SemaDiagnosticBuilder &) = default;
+  /// 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);
 
-    // The copy and move assignment operator is defined as deleted pending
-    // further motivation.
-    SemaDiagnosticBuilder &operator=(const SemaDiagnosticBuilder &) = delete;
-    SemaDiagnosticBuilder &operator=(SemaDiagnosticBuilder &&) = delete;
+  ExprResult BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
+                               TypeSourceInfo *Ty, Expr *E,
+                               SourceRange AngleBrackets, SourceRange Parens);
 
-    ~SemaDiagnosticBuilder();
+  ExprResult ActOnBuiltinBitCastExpr(SourceLocation KWLoc, Declarator &Dcl,
+                                     ExprResult Operand,
+                                     SourceLocation RParenLoc);
 
-    bool isImmediate() const { return ImmediateDiag.has_value(); }
+  ExprResult BuildBuiltinBitCastExpr(SourceLocation KWLoc, TypeSourceInfo *TSI,
+                                     Expr *Operand, SourceLocation RParenLoc);
 
-    /// 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(); }
-
-    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]
-                .getDiag()
-                .second
-            << Value;
-      return Diag;
-    }
-
-    // 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].getDiag().second
-            << std::move(V);
-      return *this;
-    }
+  // Checks that reinterpret casts don't have undefined behavior.
+  void CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType,
+                                      bool IsDereference, SourceRange Range);
 
-    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]
-            .getDiag()
-            .second = PD;
-      return Diag;
-    }
+  // 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);
 
-    void AddFixItHint(const FixItHint &Hint) const {
-      if (ImmediateDiag)
-        ImmediateDiag->AddFixItHint(Hint);
-      else if (PartialDiagId)
-        S.DeviceDeferredDiags[Fn][*PartialDiagId].getDiag().second.AddFixItHint(
-            Hint);
-    }
+  // 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);
 
-    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); }
+  ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty,
+                                 SourceLocation RParenLoc, Expr *Op);
 
-  private:
-    Sema &S;
-    SourceLocation Loc;
-    unsigned DiagID;
-    const FunctionDecl *Fn;
-    bool ShowCallStack;
+  ExprResult BuildCXXFunctionalCastExpr(TypeSourceInfo *TInfo, QualType Type,
+                                        SourceLocation LParenLoc,
+                                        Expr *CastExpr,
+                                        SourceLocation RParenLoc);
 
-    // 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;
-  };
+  ///@}
 
-  /// Is the last error level diagnostic immediate. This is used to determined
-  /// whether the next info diagnostic should be immediate.
-  bool IsLastErrorImmediate = true;
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// Emit a diagnostic.
-  SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID,
-                             bool DeferHint = false);
+  /// \name Extra Semantic Checking
+  /// Implementations are in SemaChecking.cpp
+  ///@{
 
-  /// Emit a partial diagnostic.
-  SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic &PD,
-                             bool DeferHint = false);
+public:
+  /// Used to change context to isConstantEvaluated without pushing a heavy
+  /// ExpressionEvaluationContextRecord object.
+  bool isConstantEvaluatedOverride = false;
 
-  /// Build a partial diagnostic.
-  PartialDiagnostic PDiag(unsigned DiagID = 0); // in SemaInternal.h
+  bool isConstantEvaluatedContext() const {
+    return currentEvaluationContext().isConstantEvaluated() ||
+           isConstantEvaluatedOverride;
+  }
 
-  /// Whether deferrable diagnostics should be deferred.
-  bool DeferDiags = false;
+  SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL,
+                                                unsigned ByteNo) const;
 
-  /// RAII class to control scope of DeferDiags.
-  class DeferDiagsRAII {
-    Sema &S;
-    bool SavedDeferDiags = 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
+  };
 
-  public:
-    DeferDiagsRAII(Sema &S, bool DeferDiags)
-        : S(S), SavedDeferDiags(S.DeferDiags) {
-      S.DeferDiags = DeferDiags;
-    }
-    ~DeferDiagsRAII() { S.DeferDiags = SavedDeferDiags; }
+  // Used to grab the relevant information from a FormatAttr and a
+  // FunctionDeclaration.
+  struct FormatStringInfo {
+    unsigned FormatIdx;
+    unsigned FirstDataArg;
+    FormatArgumentPassingKind ArgPassingKind;
   };
 
-  /// Whether uncompilable error has occurred. This includes error happens
-  /// in deferred diagnostics.
-  bool hasUncompilableErrorOccurred() const;
+  static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
+                                  bool IsVariadic, FormatStringInfo *FSI);
 
-  bool findMacroSpelling(SourceLocation &loc, StringRef name);
+  // Used by C++ template instantiation.
+  ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
+  ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
+                                   SourceLocation BuiltinLoc,
+                                   SourceLocation RParenLoc);
 
-  /// 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;
+  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);
 
-  /// Calls \c Lexer::getLocForEndOfToken()
-  SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0);
+  bool FormatStringHasSArg(const StringLiteral *FExpr);
 
-  /// Retrieve the module loader associated with the preprocessor.
-  ModuleLoader &getModuleLoader() const;
+  static bool GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx);
 
-  /// Invent a new identifier for parameters of abbreviated templates.
-  IdentifierInfo *
-  InventAbbreviatedTemplateParameterTypeName(IdentifierInfo *ParamName,
-                                             unsigned Index);
+  void CheckFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS,
+                            BinaryOperatorKind Opcode);
 
-  void emitAndClearUnusedLocalTypedefWarnings();
+  /// 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);
 
-  private:
-    /// Function or variable declarations to be checked for whether the deferred
-    /// diagnostics should be emitted.
-    llvm::SmallSetVector DeclsToCheckForDeferredDiags;
+  struct TypeTagData {
+    TypeTagData() {}
 
-  public:
-  // Emit all deferred diagnostics.
-  void emitDeferredDiags();
+    TypeTagData(QualType Type, bool LayoutCompatible, bool MustBeNull)
+        : Type(Type), LayoutCompatible(LayoutCompatible),
+          MustBeNull(MustBeNull) {}
 
-  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
+    QualType Type;
+
+    /// 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;
   };
 
-  void ActOnStartOfTranslationUnit();
-  void ActOnEndOfTranslationUnit();
-  void ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind);
+  /// A pair of ArgumentKind identifier and magic value.  This uniquely
+  /// identifies the magic value.
+  typedef std::pair TypeTagMagicValue;
 
-  void CheckDelegatingCtorCycles();
+  /// Diagnoses the current set of gathered accesses. This typically
+  /// happens at full expression level. The set is cleared after emitting the
+  /// diagnostics.
+  void DiagnoseMisalignedMembers();
 
-  Scope *getScopeForContext(DeclContext *Ctx);
+  /// 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 PushFunctionScope();
-  void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
-  sema::LambdaScopeInfo *PushLambdaScope();
+  /// 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);
 
-  /// 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);
+  enum class AtomicArgumentOrder { API, AST };
+  ExprResult
+  BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
+                  SourceLocation RParenLoc, MultiExprArg Args,
+                  AtomicExpr::AtomicOp Op,
+                  AtomicArgumentOrder ArgOrder = AtomicArgumentOrder::API);
 
-  void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD,
-                               RecordDecl *RD, CapturedRegionKind K,
-                               unsigned OpenMPCaptureLevel = 0);
+  /// Check to see if a given expression could have '.c_str()' called on it.
+  bool hasCStrMethod(const Expr *E);
 
-  /// Custom deleter to allow FunctionScopeInfos to be kept alive for a short
-  /// time after they've been popped.
-  class PoppedFunctionScopeDeleter {
-    Sema *Self;
-
-  public:
-    explicit PoppedFunctionScopeDeleter(Sema *Self) : Self(Self) {}
-    void operator()(sema::FunctionScopeInfo *Scope) const;
-  };
-
-  using PoppedFunctionScopePtr =
-      std::unique_ptr;
-
-  PoppedFunctionScopePtr
-  PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP = nullptr,
-                       const Decl *D = nullptr,
-                       QualType BlockType = QualType());
-
-  sema::FunctionScopeInfo *getCurFunction() const {
-    return FunctionScopes.empty() ? nullptr : FunctionScopes.back();
-  }
-
-  sema::FunctionScopeInfo *getEnclosingFunction() const;
+  void DiagnoseAlwaysNonNullPointer(Expr *E,
+                                    Expr::NullPointerConstantKind NullType,
+                                    bool IsEqual, SourceRange Range);
 
-  void setFunctionHasBranchIntoScope();
-  void setFunctionHasBranchProtectedScope();
-  void setFunctionHasIndirectGoto();
-  void setFunctionHasMustTail();
+  bool CheckParmsForFunctionDef(ArrayRef Parameters,
+                                bool CheckParameterNames);
 
-  void PushCompoundScope(bool IsStmtExpr);
-  void PopCompoundScope();
+  void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange);
 
-  sema::CompoundScopeInfo &getCurCompoundScope() 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);
 
-  bool hasAnyUnrecoverableErrorsInThisFunction() const;
+  /// checkUnsafeAssigns - Check whether +1 expr is being assigned
+  /// to weak/__unsafe_unretained type.
+  bool checkUnsafeAssigns(SourceLocation Loc, QualType LHS, Expr *RHS);
 
-  /// Retrieve the current block, if any.
-  sema::BlockScopeInfo *getCurBlock();
+  /// checkUnsafeExprAssigns - Check whether +1 expr is being assigned
+  /// to weak/__unsafe_unretained expression.
+  void checkUnsafeExprAssigns(SourceLocation Loc, Expr *LHS, Expr *RHS);
 
-  /// 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;
+  /// 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);
 
-  /// 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);
+  /// 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);
 
-  /// Retrieve the current generic lambda info, if any.
-  sema::LambdaScopeInfo *getCurGenericLambda();
+  /// Warn if a value is moved to itself.
+  void DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
+                        SourceLocation OpLoc);
 
-  /// Retrieve the current captured region, if any.
-  sema::CapturedRegionScopeInfo *getCurCapturedRegion();
+  // Used for emitting the right warning by DefaultVariadicArgumentPromotion
+  enum VariadicCallType {
+    VariadicFunction,
+    VariadicBlock,
+    VariadicMethod,
+    VariadicConstructor,
+    VariadicDoesNotApply
+  };
 
-  /// Retrieve the current function, if any, that should be analyzed for
-  /// potential availability violations.
-  sema::FunctionScopeInfo *getCurFunctionAvailabilityContext();
+  bool IsLayoutCompatible(QualType T1, QualType T2) const;
+  template 
+  static bool isTypeDecoratedWithDeclAttribute(QualType Ty) {
+    const CXXRecordDecl *RecTy = Ty->getAsCXXRecordDecl();
+    if (!RecTy)
+      return false;
 
-  /// WeakTopLevelDeclDecls - access to \#pragma weak-generated Decls
-  SmallVectorImpl &WeakTopLevelDecls() { return WeakTopLevelDecl; }
+    if (RecTy->hasAttr())
+      return true;
 
-  /// Called before parsing a function declarator belonging to a function
-  /// declaration.
-  void ActOnStartFunctionDeclarationDeclarator(Declarator &D,
-                                               unsigned TemplateParameterDepth);
+    if (auto *CTSD = dyn_cast(RecTy)) {
+      ClassTemplateDecl *Template = CTSD->getSpecializedTemplate();
+      if (CXXRecordDecl *RD = Template->getTemplatedDecl())
+        return RD->hasAttr();
+    }
+    return false;
+  }
+private:
+  void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
+                        const ArraySubscriptExpr *ASE = nullptr,
+                        bool AllowOnePastEnd = true, bool IndexNegated = false);
+  void CheckArrayAccess(const Expr *E);
 
-  /// Called after parsing a function declarator belonging to a function
-  /// declaration.
-  void ActOnFinishFunctionDeclarationDeclarator(Declarator &D);
+  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);
 
-  void ActOnComment(SourceRange Comment);
+  void checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg);
 
-  //===--------------------------------------------------------------------===//
-  // Type Analysis / Processing: SemaType.cpp.
-  //
+  void CheckArgAlignment(SourceLocation Loc, NamedDecl *FDecl,
+                         StringRef ParamName, QualType ArgTy, QualType ParamTy);
 
-  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);
+  void checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
+                 const Expr *ThisArg, ArrayRef Args,
+                 bool IsMemberFunction, SourceLocation Loc, SourceRange Range,
+                 VariadicCallType CallType);
 
-  QualType BuildAddressSpaceAttr(QualType &T, LangAS ASIdx, Expr *AddrSpace,
-                                 SourceLocation AttrLoc);
+  bool CheckObjCString(Expr *Arg);
+  ExprResult CheckOSLogFormatStringArg(Expr *Arg);
 
-  /// Same as above, but constructs the AddressSpace index if not provided.
-  QualType BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,
-                                 SourceLocation AttrLoc);
-  SYCLIntelIVDepAttr *
-  BuildSYCLIntelIVDepAttr(const AttributeCommonInfo &CI, Expr *Expr1,
-                          Expr *Expr2);
-  LoopUnrollHintAttr *BuildLoopUnrollHintAttr(const AttributeCommonInfo &A,
-                                              Expr *E);
-  OpenCLUnrollHintAttr *
-  BuildOpenCLLoopUnrollHintAttr(const AttributeCommonInfo &A, Expr *E);
+  ExprResult CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
+                                      CallExpr *TheCall);
 
-  SYCLIntelLoopCountAttr *
-  BuildSYCLIntelLoopCountAttr(const AttributeCommonInfo &CI, Expr *E);
-  SYCLIntelInitiationIntervalAttr *
-  BuildSYCLIntelInitiationIntervalAttr(const AttributeCommonInfo &CI,
-                                       Expr *E);
-  SYCLIntelMaxConcurrencyAttr *
-  BuildSYCLIntelMaxConcurrencyAttr(const AttributeCommonInfo &CI, Expr *E);
-  SYCLIntelMaxInterleavingAttr *
-  BuildSYCLIntelMaxInterleavingAttr(const AttributeCommonInfo &CI, Expr *E);
-  SYCLIntelSpeculatedIterationsAttr *
-  BuildSYCLIntelSpeculatedIterationsAttr(const AttributeCommonInfo &CI,
-                                         Expr *E);
-  SYCLIntelLoopCoalesceAttr *
-  BuildSYCLIntelLoopCoalesceAttr(const AttributeCommonInfo &CI, Expr *E);
-  SYCLIntelMaxReinvocationDelayAttr *
-  BuildSYCLIntelMaxReinvocationDelayAttr(const AttributeCommonInfo &CI,
-                                         Expr *E);
+  bool CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
+                                  CallExpr *TheCall);
 
-  CodeAlignAttr *BuildCodeAlignAttr(const AttributeCommonInfo &CI, Expr *E);
-  bool CheckRebuiltStmtAttributes(ArrayRef Attrs);
+  void checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD, CallExpr *TheCall);
 
-  bool CheckQualifiedFunctionForTypeId(QualType T, SourceLocation Loc);
+  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);
 
-  bool CheckFunctionReturnType(QualType T, 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 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);
 
-  /// Check an argument list for placeholders that we won't try to
-  /// handle later.
-  bool CheckArgsForPlaceholders(MultiExprArg args);
+  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);
 
-  /// 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);
+  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);
 
-  /// 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);
+  bool CheckPPCMMAType(QualType Type, SourceLocation TypeLoc);
 
-  TypeResult ActOnTypeName(Declarator &D);
+  bool SemaBuiltinElementwiseMath(CallExpr *TheCall);
+  bool SemaBuiltinElementwiseTernaryMath(CallExpr *TheCall,
+                                         bool CheckForFloatArgs = true);
+  bool PrepareBuiltinElementwiseMathOneArgCall(CallExpr *TheCall);
+  bool PrepareBuiltinReduceMathOneArgCall(CallExpr *TheCall);
 
-  /// The parser has parsed the context-sensitive type 'instancetype'
-  /// in an Objective-C message declaration. Return the appropriate type.
-  ParsedType ActOnObjCInstanceType(SourceLocation Loc);
+  bool SemaBuiltinNonDeterministicValue(CallExpr *TheCall);
 
-  /// Abstract class used to diagnose incomplete types.
-  struct TypeDiagnoser {
-    TypeDiagnoser() {}
+  // Matrix builtin handling.
+  ExprResult SemaBuiltinMatrixTranspose(CallExpr *TheCall,
+                                        ExprResult CallResult);
+  ExprResult SemaBuiltinMatrixColumnMajorLoad(CallExpr *TheCall,
+                                              ExprResult CallResult);
+  ExprResult SemaBuiltinMatrixColumnMajorStore(CallExpr *TheCall,
+                                               ExprResult CallResult);
 
-    virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) = 0;
-    virtual ~TypeDiagnoser() {}
-  };
+  // 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);
 
-  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();}
+  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);
 
-  template  class BoundTypeDiagnoser : public TypeDiagnoser {
-  protected:
-    unsigned DiagID;
-    std::tuple Args;
+  void CheckInfNaNFunction(const CallExpr *Call, const FunctionDecl *FDecl);
 
-    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;
-    }
+  void CheckAbsoluteValueFunction(const CallExpr *Call,
+                                  const FunctionDecl *FDecl);
 
-  public:
-    BoundTypeDiagnoser(unsigned DiagID, const Ts &...Args)
-        : TypeDiagnoser(), DiagID(DiagID), Args(Args...) {
-      assert(DiagID != 0 && "no diagnostic for type diagnoser");
-    }
+  void CheckMaxUnsignedZero(const CallExpr *Call, const FunctionDecl *FDecl);
 
-    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 CheckMemaccessArguments(const CallExpr *Call, unsigned BId,
+                               IdentifierInfo *FnName);
 
-  /// 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);
+  void CheckStrlcpycatArguments(const CallExpr *Call, IdentifierInfo *FnName);
 
-  /// 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...) {}
+  void CheckStrncatArguments(const CallExpr *Call, IdentifierInfo *FnName);
 
-    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;
-    }
-  };
+  void CheckFreeArguments(const CallExpr *E);
 
-  enum class CompleteTypeKind {
-    /// Apply the normal rules for complete types.  In particular,
-    /// treat all sizeless types as incomplete.
-    Normal,
+  void CheckReturnValExpr(Expr *RetValExp, QualType lhsType,
+                          SourceLocation ReturnLoc, bool isObjCMethod = false,
+                          const AttrVec *Attrs = nullptr,
+                          const FunctionDecl *FD = nullptr);
 
-    /// Relax the normal rules for complete types so that they include
-    /// sizeless built-in types.
-    AcceptSizeless,
+  void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation());
+  void CheckBoolLikeConversion(Expr *E, SourceLocation CC);
+  void CheckForIntOverflow(const Expr *E);
+  void CheckUnsequencedOperations(const Expr *E);
 
-    // FIXME: Eventually we should flip the default to Normal and opt in
-    // to AcceptSizeless rather than opt out of it.
-    Default = AcceptSizeless
-  };
+  /// 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);
 
-  enum class AcceptableKind { Visible, Reachable };
+  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);
 
-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);
+  void CheckTCBEnforcement(const SourceLocation CallExprLoc,
+                           const NamedDecl *Callee);
 
-  bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
-                               CompleteTypeKind Kind, TypeDiagnoser *Diagnoser);
+  /// A map from magic value to type information.
+  std::unique_ptr>
+      TypeTagForDatatypeMagicValues;
 
-  struct ModuleScope {
-    SourceLocation BeginLoc;
-    clang::Module *Module = nullptr;
-    VisibleModuleSet OuterVisibleModules;
-  };
-  /// The modules we're currently parsing.
-  llvm::SmallVector ModuleScopes;
+  /// 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);
 
-  /// For an interface unit, this is the implicitly imported interface unit.
-  clang::Module *ThePrimaryInterface = nullptr;
+  /// 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);
 
-  /// 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;
-
-  /// 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;
+  /// Helper class that collects misaligned member designations and
+  /// their location info for delayed diagnostics.
+  struct MisalignedMember {
+    Expr *E;
+    RecordDecl *RD;
+    ValueDecl *MD;
+    CharUnits Alignment;
 
-  /// Namespace definitions that we will export when they finish.
-  llvm::SmallPtrSet DeferredExportedNamespaces;
+    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()) {}
 
-  /// 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;
+    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;
 
-  /// Helper function to judge if we are in module purview.
-  /// Return false if we are not in a module.
-  bool isCurrentModulePurview() const;
+  /// Adds an expression to the set of gathered misaligned members.
+  void AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD,
+                                     CharUnits Alignment);
+  ///@}
 
-  /// Enter the scope of the explicit global module fragment.
-  Module *PushGlobalModuleFragment(SourceLocation BeginLoc);
-  /// Leave the scope of the explicit global module fragment.
-  void PopGlobalModuleFragment();
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// Enter the scope of an implicit global module fragment.
-  Module *PushImplicitGlobalModuleFragment(SourceLocation BeginLoc);
-  /// Leave the scope of an implicit global module fragment.
-  void PopImplicitGlobalModuleFragment();
+  /// \name C++ Coroutines
+  /// Implementations are in SemaCoroutine.cpp
+  ///@{
 
-  VisibleModuleSet VisibleModules;
+public:
+  /// The C++ "std::coroutine_traits" template, which is defined in
+  /// \
+  ClassTemplateDecl *StdCoroutineTraitsCache;
 
-  /// Cache for module units which is usable for current module.
-  llvm::DenseSet UsableModuleUnitsCache;
+  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);
 
-  bool isUsableModule(const Module *M);
+  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);
 
-  bool isAcceptableSlow(const NamedDecl *D, AcceptableKind Kind);
+  // 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);
 
-public:
-  /// Get the module unit whose scope we are currently within.
-  Module *getCurrentModule() const {
-    return ModuleScopes.empty() ? nullptr : ModuleScopes.back().Module;
-  }
+  ///@}
 
-  /// Is the module scope we are an implementation unit?
-  bool currentModuleIsImplementation() const {
-    return ModuleScopes.empty()
-               ? false
-               : ModuleScopes.back().Module->isModuleImplementation();
-  }
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// Is the module scope we are in a C++ Header Unit?
-  bool currentModuleIsHeaderUnit() const {
-    return ModuleScopes.empty() ? false
-                                : ModuleScopes.back().Module->isHeaderUnit();
-  }
+  /// \name C++ Scope Specifiers
+  /// Implementations are in SemaCXXScopeSpec.cpp
+  ///@{
 
-  /// Get the module owning an entity.
-  Module *getOwningModule(const Decl *Entity) {
-    return Entity->getOwningModule();
-  }
+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);
 
-  /// Make a merged definition of an existing hidden definition \p ND
-  /// visible at the specified location.
-  void makeMergedDefinitionVisible(NamedDecl *ND);
+  DeclContext *computeDeclContext(QualType T);
+  DeclContext *computeDeclContext(const CXXScopeSpec &SS,
+                                  bool EnteringContext = false);
+  bool isDependentScopeSpecifier(const CXXScopeSpec &SS);
+  CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS);
 
-  bool isModuleVisible(const Module *M, bool ModulePrivate = false);
+  /// 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);
 
-  // When loading a non-modular PCH files, this is used to restore module
-  // visibility.
-  void makeModuleVisible(Module *Mod, SourceLocation ImportLoc) {
-    VisibleModules.setVisible(Mod, ImportLoc);
-  }
+  /// 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);
 
-  /// Determine whether a declaration is visible to name lookup.
-  bool isVisible(const NamedDecl *D) {
-    return D->isUnconditionallyVisible() ||
-           isAcceptableSlow(D, AcceptableKind::Visible);
-  }
+  bool isAcceptableNestedNameSpecifier(const NamedDecl *SD,
+                                       bool *CanCorrect = nullptr);
+  NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
 
-  /// Determine whether a declaration is reachable.
-  bool isReachable(const NamedDecl *D) {
-    // All visible declarations are reachable.
-    return D->isUnconditionallyVisible() ||
-           isAcceptableSlow(D, AcceptableKind::Reachable);
-  }
+  /// 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;
 
-  /// Determine whether a declaration is acceptable (visible/reachable).
-  bool isAcceptable(const NamedDecl *D, AcceptableKind Kind) {
-    return Kind == AcceptableKind::Visible ? isVisible(D) : isReachable(D);
-  }
+    /// The identifier preceding the '::'.
+    IdentifierInfo *Identifier;
 
-  /// 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 location of the identifier.
+    SourceLocation IdentifierLoc;
 
-  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 location of the '::'.
+    SourceLocation CCLoc;
 
-  bool hasVisibleMergedDefinition(const NamedDecl *Def);
-  bool hasMergedDefinitionInCurrentModule(const NamedDecl *Def);
+    /// 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) {}
 
-  /// 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);
+    NestedNameSpecInfo(IdentifierInfo *II, SourceLocation IdLoc,
+                       SourceLocation ColonColonLoc, QualType ObjectType)
+        : ObjectType(ParsedType::make(ObjectType)), Identifier(II),
+          IdentifierLoc(IdLoc), CCLoc(ColonColonLoc) {}
+  };
 
-  /// 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);
-  }
+  bool BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo,
+                                   bool EnteringContext, CXXScopeSpec &SS,
+                                   NamedDecl *ScopeLookupResult,
+                                   bool ErrorRecoveryLookup,
+                                   bool *IsCorrectedToColon = nullptr,
+                                   bool OnlyNamespace = false);
 
-  /// 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);
-  }
+  /// 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);
 
-  bool hasAcceptableDefinition(NamedDecl *D, NamedDecl **Suggested,
-                               AcceptableKind Kind,
-                               bool OnlyNeedComplete = false);
-  bool hasAcceptableDefinition(NamedDecl *D, AcceptableKind Kind) {
-    NamedDecl *Hidden;
-    return hasAcceptableDefinition(D, &Hidden, Kind);
-  }
-
-  /// 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);
-
-  /// 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);
-
-  bool isUsualDeallocationFunction(const CXXMethodDecl *FD);
-
-  // 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 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);
 
-  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);
+  bool ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS, const DeclSpec &DS,
+                                           SourceLocation ColonColonLoc);
 
-  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);
-  }
+  bool ActOnCXXNestedNameSpecifierIndexedPack(CXXScopeSpec &SS,
+                                              const DeclSpec &DS,
+                                              SourceLocation ColonColonLoc,
+                                              QualType Type);
 
-  template 
-  bool RequireCompleteType(SourceLocation Loc, QualType T, unsigned DiagID,
-                           const Ts &...Args) {
-    BoundTypeDiagnoser Diagnoser(DiagID, Args...);
-    return RequireCompleteType(Loc, T, Diagnoser);
-  }
+  bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
+                                 NestedNameSpecInfo &IdInfo,
+                                 bool EnteringContext);
 
-  template 
-  bool RequireCompleteSizedType(SourceLocation Loc, QualType T, unsigned DiagID,
-                                const Ts &... Args) {
-    SizelessTypeDiagnoser Diagnoser(DiagID, Args...);
-    return RequireCompleteType(Loc, T, CompleteTypeKind::Normal, Diagnoser);
-  }
+  /// 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);
 
-  /// 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.
+  /// Given an annotation pointer for a nested-name-specifier, restore
+  /// the nested-name-specifier structure.
   ///
-  /// 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);
+  /// \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);
 
-  void completeExprArrayBound(Expr *E);
-  bool RequireCompleteExprType(Expr *E, CompleteTypeKind Kind,
-                               TypeDiagnoser &Diagnoser);
-  bool RequireCompleteExprType(Expr *E, unsigned DiagID);
+  bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
 
-  template 
-  bool RequireCompleteExprType(Expr *E, unsigned DiagID, const Ts &...Args) {
-    BoundTypeDiagnoser Diagnoser(DiagID, Args...);
-    return RequireCompleteExprType(E, CompleteTypeKind::Default, Diagnoser);
-  }
+  /// 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);
 
-  template 
-  bool RequireCompleteSizedExprType(Expr *E, unsigned DiagID,
-                                    const Ts &... Args) {
-    SizelessTypeDiagnoser Diagnoser(DiagID, Args...);
-    return RequireCompleteExprType(E, CompleteTypeKind::Normal, Diagnoser);
-  }
+  /// 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);
 
-  bool RequireLiteralType(SourceLocation Loc, QualType T,
-                          TypeDiagnoser &Diagnoser);
-  bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID);
+  ///@}
 
-  template 
-  bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID,
-                          const Ts &...Args) {
-    BoundTypeDiagnoser Diagnoser(DiagID, Args...);
-    return RequireLiteralType(Loc, T, Diagnoser);
-  }
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  QualType getElaboratedType(ElaboratedTypeKeyword Keyword,
-                             const CXXScopeSpec &SS, QualType T,
-                             TagDecl *OwnedTagDecl = nullptr);
+  /// \name Declarations
+  /// Implementations are in SemaDecl.cpp
+  ///@{
 
-  // Returns the underlying type of a decltype with the given expression.
-  QualType getDecltypeForExpr(Expr *E);
+public:
+  IdentifierResolver IdResolver;
 
-  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);
+  /// The index of the first InventedParameterInfo that refers to the current
+  /// context.
+  unsigned InventedParameterInfosStart = 0;
 
-  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 = {});
+  /// A RAII object to temporarily push a declaration context.
+  class ContextRAII {
+  private:
+    Sema &S;
+    DeclContext *SavedContext;
+    ProcessingContextState SavedContextState;
+    QualType SavedCXXThisTypeOverride;
+    unsigned SavedFunctionScopesStart;
+    unsigned SavedInventedParameterInfosStart;
 
-  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);
+  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();
+    }
 
-  //===--------------------------------------------------------------------===//
-  // Symbol table / Decl tracking callbacks: SemaDecl.cpp.
-  //
+    void pop() {
+      if (!SavedContext)
+        return;
+      S.CurContext = SavedContext;
+      S.DelayedDiagnostics.popUndelayed(SavedContextState);
+      S.CXXThisTypeOverride = SavedCXXThisTypeOverride;
+      S.FunctionScopesStart = SavedFunctionScopesStart;
+      S.InventedParameterInfosStart = SavedInventedParameterInfosStart;
+      SavedContext = nullptr;
+    }
 
-  struct SkipBodyInfo {
-    SkipBodyInfo() = default;
-    bool ShouldSkip = false;
-    bool CheckSameAsPrevious = false;
-    NamedDecl *Previous = nullptr;
-    NamedDecl *New = nullptr;
+    ~ContextRAII() { pop(); }
   };
 
-  DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = nullptr);
+  void DiagnoseInvalidJumps(Stmt *Body);
 
-  void DiagnoseUseOfUnimplementedSelectors();
+  /// 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;
+
+  /// A cache of the flags available in enumerations with the flag_bits
+  /// attribute.
+  mutable llvm::DenseMap FlagBitsCache;
+
+  /// 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;
+
+  /// 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;
+
+  /// Set containing all typedefs that are likely unused.
+  llvm::SmallSetVector
+      UnusedLocalTypedefNameCandidates;
+
+  typedef LazyVector
+      UnusedFileScopedDeclsType;
+
+  /// 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;
+
+  typedef LazyVector
+      TentativeDefinitionsType;
+
+  /// All the tentative definitions encountered in the TU.
+  TentativeDefinitionsType TentativeDefinitions;
+
+  /// All the external declarations encoutered and used in the TU.
+  SmallVector ExternalDeclarations;
+
+  /// 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;
+    bool ShouldSkip = false;
+    bool CheckSameAsPrevious = false;
+    NamedDecl *Previous = nullptr;
+    NamedDecl *New = nullptr;
+  };
+
+  DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = nullptr);
 
   ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
                          Scope *S, CXXScopeSpec *SS = nullptr,
@@ -3035,10 +3084,8 @@ class Sema final {
                          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);
 
@@ -3107,9 +3154,7 @@ class Sema final {
 
     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);
@@ -3283,9 +3328,6 @@ class Sema final {
     // diagnoseExprIntendedAsTemplateName.
     return false;
   }
-  void diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName,
-                                          SourceLocation Less,
-                                          SourceLocation Greater);
 
   void warnOnReservedIdentifier(const NamedDecl *D);
 
@@ -3293,8 +3335,8 @@ class Sema final {
 
   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);
@@ -3302,16 +3344,7 @@ class Sema final {
                                     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);
@@ -3328,68 +3361,35 @@ class Sema final {
 
   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,
@@ -3408,8 +3408,7 @@ class Sema final {
   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,
@@ -3418,17 +3417,6 @@ class Sema final {
                               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.
@@ -3476,13 +3464,11 @@ class Sema final {
   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);
@@ -3519,14 +3505,6 @@ class Sema final {
   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
@@ -3547,10 +3525,6 @@ class Sema final {
   /// \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);
@@ -3572,194 +3546,63 @@ class Sema final {
   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);
 
-  /// 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();
+  /// Called once it is known whether
+  /// a tag declaration is an anonymous union or struct.
+  void ActOnDefinedDeclarationSpecifier(Decl *D);
 
-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);
+  void DiagPlaceholderFieldDeclDefinitions(RecordDecl *Record);
 
-  /// 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);
+  Decl *BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
+                                       RecordDecl *Record);
 
-  /// 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);
+  /// Common ways to introduce type names without a tag for use in diagnostics.
+  /// Keep in sync with err_tag_reference_non_tag.
+  enum NonTagKind {
+    NTK_NonStruct,
+    NTK_NonClass,
+    NTK_NonUnion,
+    NTK_NonEnum,
+    NTK_Typedef,
+    NTK_TypeAlias,
+    NTK_Template,
+    NTK_TypeAliasTemplate,
+    NTK_TemplateTemplateArgument,
+  };
 
-  /// 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 = {});
+  /// Given a non-tag type declaration, returns an enum useful for indicating
+  /// what kind of non-tag type this is.
+  NonTagKind getNonTagTypeDeclKind(const Decl *D, TagTypeKind TTK);
 
-  /// 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);
+  bool isAcceptableTagRedeclaration(const TagDecl *Previous, TagTypeKind NewTag,
+                                    bool isDefinition, SourceLocation NewTagLoc,
+                                    const IdentifierInfo *Name);
 
-  /// 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);
-
-  void DiagPlaceholderFieldDeclDefinitions(RecordDecl *Record);
-
-  Decl *BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS,
-                                       RecordDecl *Record);
-
-  /// Common ways to introduce type names without a tag for use in diagnostics.
-  /// Keep in sync with err_tag_reference_non_tag.
-  enum NonTagKind {
-    NTK_NonStruct,
-    NTK_NonClass,
-    NTK_NonUnion,
-    NTK_NonEnum,
-    NTK_Typedef,
-    NTK_TypeAlias,
-    NTK_Template,
-    NTK_TypeAliasTemplate,
-    NTK_TemplateTemplateArgument,
-  };
-
-  /// Given a non-tag type declaration, returns an enum useful for indicating
-  /// 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,
-                                    const IdentifierInfo *Name);
-
-  enum TagUseKind {
-    TUK_Reference,   // Reference to a tag:  'struct foo *X;'
-    TUK_Declaration, // Fwd decl of a tag:   'struct foo;'
-    TUK_Definition,  // Definition of a tag: 'struct foo { int X; } Y;'
-    TUK_Friend       // Friend declaration:  'friend struct foo;'
-  };
+  enum TagUseKind {
+    TUK_Reference,   // Reference to a tag:  'struct foo *X;'
+    TUK_Declaration, // Fwd decl of a tag:   'struct foo;'
+    TUK_Definition,  // Definition of a tag: 'struct foo { int X; } Y;'
+    TUK_Friend       // Friend declaration:  'friend struct foo;'
+  };
 
   enum OffsetOfKind {
     // Not parsing a type within __builtin_offsetof.
@@ -3783,106 +3626,21 @@ class Sema final {
                       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);
@@ -3904,20 +3662,6 @@ class Sema final {
   /// 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.
@@ -3956,8 +3700,7 @@ class Sema final {
 
   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,
@@ -3986,34 +3729,15 @@ class Sema final {
   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);
 
@@ -4055,9654 +3779,9266 @@ class Sema final {
     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);
+  bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const;
 
-  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);
+  /// If it's a file scoped decl that must warn if not used, keep track
+  /// of it.
+  void MarkUnusedFileScopedDecl(const DeclaratorDecl *D);
 
-  // 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
-  };
+  typedef llvm::function_ref
+      DiagReceiverTy;
 
-  /// C++ Overloading.
-  enum OverloadKind {
-    /// This is a legitimate overload: the existing declarations are
-    /// functions or function templates with different signatures.
-    Ovl_Overload,
+  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 signature exactly matches
-    /// an existing declaration.
-    Ovl_Match,
+  /// If VD is set but not otherwise used, diagnose, for a parameter or a
+  /// variable.
+  void DiagnoseUnusedButSetDecl(const VarDecl *VD, 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);
+  ObjCInterfaceDecl *getObjCInterfaceDecl(IdentifierInfo *&Id,
+                                          SourceLocation IdLoc,
+                                          bool TypoCorrection = false);
 
-  // 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);
+  Scope *getNonFieldDeclScope(Scope *S);
 
-  // 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);
+  FunctionDecl *CreateBuiltin(IdentifierInfo *II, QualType Type, unsigned ID,
+                              SourceLocation Loc);
+  NamedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, Scope *S,
+                                 bool ForRedeclaration, SourceLocation Loc);
 
-  // Calculates whether the friend function depends on an enclosing template for
-  // the purposes of [temp.friend] p9.
-  bool FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD);
+  /// 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;
 
-  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
-  };
+  DeclarationNameInfo GetNameForDeclarator(Declarator &D);
+  DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name);
 
-  ImplicitConversionSequence
-  TryImplicitConversion(Expr *From, QualType ToType,
-                        bool SuppressUserConversions,
-                        AllowedExplicit AllowExplicit,
-                        bool InOverloadResolution,
-                        bool CStyle,
-                        bool AllowObjCWritebackConversion);
+  /// ParsingInitForAutoVars - a set of declarations with auto types for which
+  /// we are currently parsing the initializer.
+  llvm::SmallPtrSet ParsingInitForAutoVars;
 
-  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);
+  /// Look for a locally scoped extern "C" declaration by the given name.
+  NamedDecl *findLocallyScopedExternCDecl(DeclarationName Name);
 
-  bool FunctionParamTypesAreEqual(ArrayRef Old,
-                                  ArrayRef New,
-                                  unsigned *ArgPos = nullptr,
-                                  bool Reversed = false);
+  bool inferObjCARCLifetime(ValueDecl *decl);
 
-  bool FunctionParamTypesAreEqual(const FunctionProtoType *OldType,
-                                  const FunctionProtoType *NewType,
-                                  unsigned *ArgPos = nullptr,
-                                  bool Reversed = false);
+  void deduceOpenCLAddressSpace(ValueDecl *decl);
 
-  bool FunctionNonObjectParamTypesAreEqual(const FunctionDecl *OldFunction,
-                                           const FunctionDecl *NewFunction,
-                                           unsigned *ArgPos = nullptr,
-                                           bool Reversed = false);
+  static bool adjustContextForLocalExternDecl(DeclContext *&DC);
 
-  void HandleFunctionTypeMismatch(PartialDiagnostic &PDiag,
-                                  QualType FromType, QualType ToType);
+  void MarkTypoCorrectedFunctionDefinition(const NamedDecl *F);
 
-  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);
+  /// 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 CanPerformAggregateInitializationForOverloadResolution(
-      const InitializedEntity &Entity, InitListExpr *From);
+  /// type checking declaration initializers (C99 6.7.8)
+  bool CheckForConstantInitializer(Expr *e, QualType t);
 
-  bool IsStringInit(Expr *Init, const ArrayType *AT);
+  QualType deduceVarTypeFromInitializer(VarDecl *VDecl, DeclarationName Name,
+                                        QualType Type, TypeSourceInfo *TSI,
+                                        SourceRange Range, bool DirectInit,
+                                        Expr *Init);
 
-  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);
+  bool DeduceVariableDeclarationType(VarDecl *VDecl, 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);
+  sema::LambdaScopeInfo *RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator);
 
-  ExprResult PerformContextuallyConvertToBool(Expr *From);
-  ExprResult PerformContextuallyConvertToObjCPointer(Expr *From);
+  /// 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);
 
-  /// 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.
-  };
+  // 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 BuildConvertedConstantExpression(Expr *From, QualType T,
-                                              CCEKind CCE,
-                                              NamedDecl *Dest = nullptr);
+  NamedDecl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II,
+                                      Scope *S);
+  void AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction(
+      FunctionDecl *FD);
+  void AddKnownFunctionAttributes(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);
+  /// 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);
 
-  ExprResult
-  EvaluateConvertedConstantExpression(Expr *E, QualType T, APValue &Value,
-                                      CCEKind CCE, bool RequireInt,
-                                      const APValue &PreNarrowingValue);
+  /// 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;
 
-  /// 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;
-
-    ContextualImplicitConverter(bool Suppress = false,
-                                bool SuppressConversion = false)
-        : Suppress(Suppress), SuppressConversion(SuppressConversion) {}
-
-    /// Determine whether the specified type is a valid destination type
-    /// for this conversion.
-    virtual bool match(QualType T) = 0;
-
-    /// Emits a diagnostic complaining that the expression does not have
-    /// integral or enumeration type.
-    virtual SemaDiagnosticBuilder
-    diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) = 0;
-
-    /// Emits a diagnostic when the expression has incomplete class type.
-    virtual SemaDiagnosticBuilder
-    diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) = 0;
+  /// ActOnPragmaWeakID - Called on well formed \#pragma weak ident.
+  void ActOnPragmaWeakID(IdentifierInfo *WeakName, SourceLocation PragmaLoc,
+                         SourceLocation WeakNameLoc);
 
-    /// Emits a diagnostic when the only matching conversion function
-    /// is explicit.
-    virtual SemaDiagnosticBuilder diagnoseExplicitConv(
-        Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) = 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 note for the explicit conversion function.
-    virtual SemaDiagnosticBuilder
-    noteExplicitConv(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 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 there are multiple possible conversion
-    /// functions.
-    virtual SemaDiagnosticBuilder
-    diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) = 0;
+  ObjCContainerDecl *getObjCDeclContext() const;
 
-    /// Emits a note for one of the candidate conversions.
-    virtual SemaDiagnosticBuilder
-    noteAmbiguous(Sema &S, CXXConversionDecl *Conv, 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 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;
+  // Whether the callee should be ignored in CUDA/HIP/OpenMP host/device check.
+  bool shouldIgnoreInHostDeviceCheck(FunctionDecl *Callee);
 
-    virtual ~ContextualImplicitConverter() {}
-  };
+private:
+  /// Function or variable declarations to be checked for whether the deferred
+  /// diagnostics should be emitted.
+  llvm::SmallSetVector DeclsToCheckForDeferredDiags;
 
-  class ICEConvertDiagnoser : public ContextualImplicitConverter {
-    bool AllowScopedEnumerations;
+  /// 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:
-    ICEConvertDiagnoser(bool AllowScopedEnumerations,
-                        bool Suppress, bool SuppressConversion)
-        : ContextualImplicitConverter(Suppress, SuppressConversion),
-          AllowScopedEnumerations(AllowScopedEnumerations) {}
+  static bool mightHaveNonExternalLinkage(const DeclaratorDecl *FD);
 
-    /// Match an integral or (possibly scoped) enumeration type.
-    bool match(QualType T) override;
+  ///@}
 
-    SemaDiagnosticBuilder
-    diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) override {
-      return diagnoseNotInt(S, Loc, T);
-    }
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-    /// Emits a diagnostic complaining that the expression does not have
-    /// integral or enumeration type.
-    virtual SemaDiagnosticBuilder
-    diagnoseNotInt(Sema &S, SourceLocation Loc, QualType T) = 0;
-  };
+  /// \name Declaration Attribute Handling
+  /// Implementations are in SemaDeclAttr.cpp
+  ///@{
 
-  /// Perform a contextual implicit conversion.
-  ExprResult PerformContextualImplicitConversion(
-      SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter);
+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,
 
+    /// The availability attribute was applied using '#pragma clang attribute'.
+    AP_PragmaClangAttribute = 1,
 
-  enum ObjCSubscriptKind {
-    OS_Array,
-    OS_Dictionary,
-    OS_Error
+    /// The availability attribute for a specific platform was inferred from
+    /// an availability attribute for another platform.
+    AP_InferredFromOtherPlatform = 2
   };
-  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
+  /// Describes the reason a calling convention specification was ignored, used
+  /// for diagnostics.
+  enum class CallingConventionIgnoredReason {
+    ForThisTarget = 0,
+    VariadicFunction,
+    ConstructorDestructor,
+    BuiltinFunction
   };
-  ObjCLiteralKind CheckLiteralKind(Expr *FromE);
 
-  ExprResult PerformObjectMemberConversion(Expr *From,
-                                           NestedNameSpecifier *Qualifier,
-                                           NamedDecl *FoundDecl,
-                                           NamedDecl *Member);
+  /// 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;
 
-  // Members have to be NamespaceDecl* or TranslationUnitDecl*.
-  // TODO: make this is a typesafe union.
-  typedef llvm::SmallSetVector AssociatedNamespaceSet;
-  typedef llvm::SmallSetVector AssociatedClassSet;
+  /// WeakTopLevelDeclDecls - access to \#pragma weak-generated Decls
+  SmallVectorImpl &WeakTopLevelDecls() { return WeakTopLevelDecl; }
 
-  using ADLCallKind = CallExpr::ADLCallKind;
+  typedef LazyVector
+      ExtVectorDeclsType;
 
-  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);
+  /// 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;
 
-  // 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);
+  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 series of 'note's all template and non-templates identified by
-  // the expression Expr
-  void NoteAllOverloadCandidates(Expr *E, 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);
 
-  /// 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);
+  /// AddAssumeAlignedAttr - Adds an assume_aligned attribute to a particular
+  /// declaration.
+  void AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
+                            Expr *OE);
 
-  /// Find the failed Boolean condition within a given Boolean
-  /// constant expression, and describe it with a string.
-  std::pair findFailedBooleanCondition(Expr *Cond);
+  /// AddAllocAlignAttr - Adds an alloc_align attribute to a particular
+  /// declaration.
+  void AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI,
+                         Expr *ParamExpr);
 
-  /// 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;
-  }
+  /// addSYCLIntelPipeIOAttr - Adds a pipe I/O attribute to a particular
+  /// declaration.
+  void addSYCLIntelPipeIOAttr(Decl *D, const AttributeCommonInfo &CI, Expr *ID);
+  SYCLIntelPipeIOAttr *MergeSYCLIntelPipeIOAttr(Decl *D,
+                                                const SYCLIntelPipeIOAttr &A);
 
-  /// 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,
-  };
+  /// AddSYCLIntelMaxConcurrencyAttr - Adds a max_concurrency attribute to a
+  /// particular declaration.
+  void AddSYCLIntelMaxConcurrencyAttr(Decl *D,
+                                      const AttributeCommonInfo &CI,
+                                      Expr *E);
 
-  SpecialMemberOverloadResult LookupSpecialMember(CXXRecordDecl *D,
-                                                  CXXSpecialMember SM,
-                                                  bool ConstArg,
-                                                  bool VolatileArg,
-                                                  bool RValueThis,
-                                                  bool ConstThis,
-                                                  bool VolatileThis);
+  bool checkAllowedSYCLInitializer(VarDecl *VD);
+  //===--------------------------------------------------------------------===//
+  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);
 
-  typedef std::function TypoDiagnosticGenerator;
-  typedef std::function
-      TypoRecoveryCallback;
+  bool CheckCountedByAttr(Scope *Scope, const FieldDecl *FD);
 
-private:
-  bool CppLookupName(LookupResult &R, Scope *S);
+  EnforceTCBAttr *mergeEnforceTCBAttr(Decl *D, const EnforceTCBAttr &AL);
+  EnforceTCBLeafAttr *mergeEnforceTCBLeafAttr(Decl *D,
+                                              const EnforceTCBLeafAttr &AL);
 
-  struct TypoExprState {
-    std::unique_ptr Consumer;
-    TypoDiagnosticGenerator DiagHandler;
-    TypoRecoveryCallback RecoveryHandler;
-    TypoExprState();
-    TypoExprState(TypoExprState &&other) noexcept;
-    TypoExprState &operator=(TypoExprState &&other) noexcept;
-  };
+public:
 
-  /// The set of unhandled TypoExprs and their associated state.
-  llvm::MapVector DelayedTypos;
+  DeviceDiagnosticReason getEmissionReason(const FunctionDecl *Decl);
 
-  /// Creates a new TypoExpr AST node.
-  TypoExpr *createDelayedTypo(std::unique_ptr TCC,
-                              TypoDiagnosticGenerator TDG,
-                              TypoRecoveryCallback TRC, SourceLocation TypoLoc);
+  //@}
 
-  // 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;
+  // More parsing and symbol table subroutines.
 
-  /// Whether we have already loaded known namespaces from an extenal
-  /// source.
-  bool LoadedExternalKnownNamespaces;
+  // Helper for delayed processing of attributes.
+  void ProcessDeclAttributeDelayed(Decl *D,
+                                   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);
+  // Options for ProcessDeclAttributeList().
+  struct ProcessDeclAttributeOptions {
+    ProcessDeclAttributeOptions()
+        : IncludeCXX11Attributes(true), IgnoreTypeAttributes(false) {}
 
-public:
-  const TypoExprState &getTypoExprState(TypoExpr *TE) const;
+    ProcessDeclAttributeOptions WithIncludeCXX11Attributes(bool Val) {
+      ProcessDeclAttributeOptions Result = *this;
+      Result.IncludeCXX11Attributes = Val;
+      return Result;
+    }
 
-  /// Clears the state of the given TypoExpr.
-  void clearDelayedTypo(TypoExpr *TE);
+    ProcessDeclAttributeOptions WithIgnoreTypeAttributes(bool Val) {
+      ProcessDeclAttributeOptions Result = *this;
+      Result.IgnoreTypeAttributes = Val;
+      return Result;
+    }
 
-  /// 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);
+    // Should C++11 attributes be processed?
+    bool IncludeCXX11Attributes;
 
-  void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
-                                    UnresolvedSetImpl &Functions);
+    // 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;
+  };
 
-  LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
-                                 SourceLocation GnuLabelLoc = SourceLocation());
+  void ProcessDeclAttributeList(Scope *S, Decl *D,
+                                const ParsedAttributesView &AttrList,
+                                const ProcessDeclAttributeOptions &Options =
+                                    ProcessDeclAttributeOptions());
+  bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
+                                      const ParsedAttributesView &AttrList);
 
-  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);
+  void checkUnusedDeclAttributes(Declarator &D);
 
-  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);
+  NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, const IdentifierInfo *II,
+                                 SourceLocation Loc);
+  void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, const WeakInfo &W);
 
-  /// 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);
-  DeviceDiagnosticReason getEmissionReason(const FunctionDecl *Decl);
+  void ProcessPragmaWeak(Scope *S, Decl *D);
+  // Decl attributes - this routine is the top level dispatcher.
+  void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD);
 
-  // Whether the callee should be ignored in CUDA/HIP/OpenMP host/device check.
-  bool shouldIgnoreInHostDeviceCheck(FunctionDecl *Callee);
+public:
 
-  void ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
-                               ArrayRef Args, ADLResult &Functions);
+  bool CheckRebuiltAttributedStmtAttributes(ArrayRef Attrs);
 
-  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);
+  void PopParsingDeclaration(ParsingDeclState state, Decl *decl);
 
-  enum CorrectTypoKind {
-    CTK_NonError,     // CorrectTypo used in a non error recovery situation.
-    CTK_ErrorRecovery // CorrectTypo used in normal error recovery.
-  };
-
-  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);
-
-  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);
+  void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);
 
-  /// 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; });
+  ///@}
+  //
+public:
+  void CheckDelegatingCtorCycles();
 
-  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);
-  }
+  /// Called before parsing a function declarator belonging to a function
+  /// declaration.
+  void ActOnStartFunctionDeclarationDeclarator(Declarator &D,
+                                               unsigned TemplateParameterDepth);
 
-  void diagnoseTypo(const TypoCorrection &Correction,
-                    const PartialDiagnostic &TypoDiag,
-                    bool ErrorRecovery = true);
+  /// Called after parsing a function declarator belonging to a function
+  /// declaration.
+  void ActOnFinishFunctionDeclarationDeclarator(Declarator &D);
 
-  void diagnoseTypo(const TypoCorrection &Correction,
-                    const PartialDiagnostic &TypoDiag,
-                    const PartialDiagnostic &PrevNote,
-                    bool ErrorRecovery = 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);
 
-  void MarkTypoCorrectedFunctionDefinition(const NamedDecl *F);
+  NamespaceDecl *getStdNamespace() const;
+  NamespaceDecl *getOrCreateStdNamespace();
 
-  void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc,
-                                          ArrayRef Args,
-                                   AssociatedNamespaceSet &AssociatedNamespaces,
-                                   AssociatedClassSet &AssociatedClasses);
+  CXXRecordDecl *getStdBadAlloc() const;
+  EnumDecl *getStdAlignValT() const;
 
-  void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S,
-                            bool ConsiderLinkage, bool AllowInlineNamespace);
+  ValueDecl *tryLookupUnambiguousFieldDecl(RecordDecl *ClassDecl,
+                                           const IdentifierInfo *MemberOrBase);
 
-  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;
+  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,
+  };
 
-  void DiagnoseAmbiguousLookup(LookupResult &Result);
-  //@}
+  /// Lookup the specified comparison category types in the standard
+  ///   library, an check the VarDecls possibly returned by the operator<=>
+  ///   builtins for that type.
+  ///
+  /// \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);
 
-  /// Attempts to produce a RecoveryExpr after some AST node cannot be created.
-  ExprResult CreateRecoveryExpr(SourceLocation Begin, SourceLocation End,
-                                ArrayRef SubExprs,
-                                QualType T = QualType());
+  /// 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);
 
-  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);
+  /// 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);
 
-  // More parsing and symbol table subroutines.
+  /// Determine whether Ctor is an initializer-list constructor, as
+  /// defined in [dcl.init.list]p2.
+  bool isInitListConstructor(const FunctionDecl *Ctor);
 
-  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 *ActOnUsingDirective(Scope *CurScope, SourceLocation UsingLoc,
+                            SourceLocation NamespcLoc, CXXScopeSpec &SS,
+                            SourceLocation IdentLoc,
+                            IdentifierInfo *NamespcName,
+                            const ParsedAttributesView &AttrList);
 
-  // Options for ProcessDeclAttributeList().
-  struct ProcessDeclAttributeOptions {
-    ProcessDeclAttributeOptions()
-        : IncludeCXX11Attributes(true), IgnoreTypeAttributes(false) {}
+  void PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir);
 
-    ProcessDeclAttributeOptions WithIncludeCXX11Attributes(bool Val) {
-      ProcessDeclAttributeOptions Result = *this;
-      Result.IncludeCXX11Attributes = Val;
-      return Result;
-    }
+  Decl *ActOnNamespaceAliasDef(Scope *CurScope, SourceLocation NamespaceLoc,
+                               SourceLocation AliasLoc, IdentifierInfo *Alias,
+                               CXXScopeSpec &SS, SourceLocation IdentLoc,
+                               IdentifierInfo *Ident);
 
-    ProcessDeclAttributeOptions WithIgnoreTypeAttributes(bool Val) {
-      ProcessDeclAttributeOptions Result = *this;
-      Result.IgnoreTypeAttributes = Val;
-      return Result;
-    }
+  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);
 
-    // Should C++11 attributes be processed?
-    bool IncludeCXX11Attributes;
+  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);
 
-    // 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;
-  };
+  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);
 
-  void ProcessDeclAttributeList(Scope *S, Decl *D,
-                                const ParsedAttributesView &AttrList,
-                                const ProcessDeclAttributeOptions &Options =
-                                    ProcessDeclAttributeOptions());
-  bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
-                                   const ParsedAttributesView &AttrList);
+  bool CheckInheritingConstructorUsingDecl(UsingDecl *UD);
 
-  void checkUnusedDeclAttributes(Declarator &D);
+  /// 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);
 
-  /// 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);
+  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);
 
-  /// Map any API notes provided for this declaration to attributes on the
-  /// declaration.
+  /// BuildCXXConstructExpr - Creates a complete call to a constructor,
+  /// including handling of its default argument expressions.
   ///
-  /// Triggered by declaration-attribute processing.
-  void ProcessAPINotes(Decl *D);
-
-  /// 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);
+  /// \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 CheckRegparmAttr(const ParsedAttr &attr, unsigned &value);
+  /// 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);
 
-  /// 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);
+  // 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);
 
-  void CheckAlignasUnderalignment(Decl *D);
+  ExprResult ConvertMemberDefaultInitExpression(FieldDecl *FD, Expr *InitExpr,
+                                                SourceLocation InitLoc);
 
-  bool CheckNoInlineAttr(const Stmt *OrigSt, const Stmt *CurSt,
-                         const AttributeCommonInfo &A);
-  bool CheckAlwaysInlineAttr(const Stmt *OrigSt, const Stmt *CurSt,
-                             const AttributeCommonInfo &A);
+  /// FinalizeVarWithDestructor - Prepare for calling destructor on the
+  /// constructed variable.
+  void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType);
 
-  bool CheckCountedByAttr(Scope *Scope, const FieldDecl *FD);
+  /// 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;
 
-  /// 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);
+    void ClearExceptions() {
+      ExceptionsSeen.clear();
+      Exceptions.clear();
+    }
 
-  // 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);
+  public:
+    explicit ImplicitExceptionSpecification(Sema &Self)
+        : Self(&Self), ComputedEST(EST_BasicNoexcept) {
+      if (!Self.getLangOpts().CPlusPlus11)
+        ComputedEST = EST_DynamicNone;
+    }
 
-  /// 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;
+    /// Get the computed exception specification type.
+    ExceptionSpecificationType getExceptionSpecType() const {
+      assert(!isComputedNoexcept(ComputedEST) &&
+             "noexcept(expr) should not be a possible result");
+      return ComputedEST;
+    }
 
-  /// 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);
+    /// The number of exceptions in the exception specification.
+    unsigned size() const { return Exceptions.size(); }
 
-  /// 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);
+    /// The set of exceptions in the exception specification.
+    const QualType *data() const { return Exceptions.data(); }
 
-  void WarnConflictingTypedMethods(ObjCMethodDecl *Method,
-                                   ObjCMethodDecl *MethodDecl,
-                                   bool IsProtocolMethodDecl);
+    /// Integrate another called method into the collected data.
+    void CalledDecl(SourceLocation CallLoc, const CXXMethodDecl *Method);
 
-  void CheckConflictingOverridingMethod(ObjCMethodDecl *Method,
-                                   ObjCMethodDecl *Overridden,
-                                   bool IsProtocolMethodDecl);
+    /// Integrate an invoked expression into the collected data.
+    void CalledExpr(Expr *E) { CalledStmt(E); }
 
-  /// WarnExactTypedMethods - This routine issues a warning if method
-  /// implementation declaration matches exactly that of its declaration.
-  void WarnExactTypedMethods(ObjCMethodDecl *Method,
-                             ObjCMethodDecl *MethodDecl,
-                             bool IsProtocolMethodDecl);
+    /// Integrate an invoked statement into the collected data.
+    void CalledStmt(Stmt *S);
 
-  typedef llvm::SmallPtrSet SelectorSet;
+    /// 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;
+    }
+  };
 
-  /// 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);
+  /// Evaluate the implicit exception specification for a defaulted
+  /// special member function.
+  void EvaluateImplicitExceptionSpec(SourceLocation Loc, FunctionDecl *FD);
 
-  /// 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);
+  /// 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);
 
-  /// DiagnoseUnimplementedProperties - This routine warns on those properties
-  /// which must be implemented by this implementation.
-  void DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
-                                       ObjCContainerDecl *CDecl,
-                                       bool SynthesizeProperties);
+  /// 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);
 
-  /// Diagnose any null-resettable synthesized setters.
-  void diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl);
+  /// Kinds of C++ special members.
+  enum CXXSpecialMember {
+    CXXDefaultConstructor,
+    CXXCopyConstructor,
+    CXXMoveConstructor,
+    CXXCopyAssignment,
+    CXXMoveAssignment,
+    CXXDestructor,
+    CXXInvalid
+  };
 
-  /// 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);
+  class InheritedConstructorInfo;
 
-  /// 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 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);
 
-  /// 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);
+  /// Produce notes explaining why a defaulted function was defined as deleted.
+  void DiagnoseDeletedDefaultedFunction(FunctionDecl *FD);
 
-  /// 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;
+  /// 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);
 
-  /// 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);
+  /// DefineImplicitDefaultConstructor - Checks for feasibility of
+  /// defining this constructor as the default constructor.
+  void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
+                                        CXXConstructorDecl *Constructor);
 
-  /// 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);
+  /// 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);
 
-  /// 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);
+  /// DefineImplicitDestructor - Checks for feasibility of
+  /// defining this destructor as the default destructor.
+  void DefineImplicitDestructor(SourceLocation CurrentLocation,
+                                CXXDestructorDecl *Destructor);
 
-  void DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D);
+  /// 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);
 
-  void DiagnoseMissingDesignatedInitOverrides(
-                                          const ObjCImplementationDecl *ImplD,
-                                          const ObjCInterfaceDecl *IFD);
+  /// Define the specified inheriting constructor.
+  void DefineInheritingConstructor(SourceLocation UseLoc,
+                                   CXXConstructorDecl *Constructor);
 
-  void DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, ObjCInterfaceDecl *SID);
+  /// 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);
 
-  enum MethodMatchStrategy {
-    MMS_loose,
-    MMS_strict
-  };
+  /// DefineImplicitCopyConstructor - Checks for feasibility of
+  /// defining this constructor as the copy constructor.
+  void DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
+                                     CXXConstructorDecl *Constructor);
 
-  /// 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);
-
-  /// 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);
+  /// 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);
 
-  /// 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);
+  /// DefineImplicitMoveConstructor - Checks for feasibility of
+  /// defining this constructor as the move constructor.
+  void DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
+                                     CXXConstructorDecl *Constructor);
 
-  /// Add the given method to the list of globally-known methods.
-  void addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method);
+  /// 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);
 
-  /// Returns default addr space for method qualifiers.
-  LangAS getDefaultCXXMethodAddrSpace() const;
+  /// Defines an implicitly-declared copy assignment operator.
+  void DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
+                                    CXXMethodDecl *MethodDecl);
 
-private:
-  /// AddMethodToGlobalPool - Add an instance or factory method to the global
-  /// pool. See descriptoin of AddInstanceMethodToGlobalPool.
-  void AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, bool instance);
+  /// 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);
 
-  /// 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);
+  /// Defines an implicitly-declared move assignment operator.
+  void DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
+                                    CXXMethodDecl *MethodDecl);
 
-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);
+  /// Check a completed declaration of an implicit special member.
+  void CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD);
 
-  bool
-  AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod,
-                                 SourceRange R, bool receiverIdOrClass,
-                                 SmallVectorImpl& Methods);
+  /// Determine whether the given function is an implicitly-deleted
+  /// special member function.
+  bool isImplicitlyDeleted(FunctionDecl *FD);
 
-  void
-  DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl &Methods,
-                                     Selector Sel, SourceRange R,
-                                     bool receiverIdOrClass);
+  /// 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);
 
-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);
+  /// Whether this' shows up in the exception specification of a static
+  /// member function.
+  bool checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method);
 
+  /// Check whether 'this' shows up in the attributes of the given
+  /// static member function.
+  ///
+  /// \returns true if an error occurred.
+  bool checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method);
 
-  /// 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 CheckImmediateEscalatingFunctionDefinition(
+      FunctionDecl *FD, const sema::FunctionScopeInfo *FSI);
 
-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);
-  }
+  void DiagnoseImmediateEscalatingReason(FunctionDecl *FD);
 
-  /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods.
-  void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false) {
-    AddMethodToGlobalPool(Method, impl, /*instance*/false);
-  }
+  bool CompleteConstructorCall(CXXConstructorDecl *Constructor,
+                               QualType DeclInitType, MultiExprArg ArgsPtr,
+                               SourceLocation Loc,
+                               SmallVectorImpl &ConvertedArgs,
+                               bool AllowExplicit = false,
+                               bool IsListInitialization = false);
 
-  /// AddAnyMethodToGlobalPool - Add any method, instance or factory to global
-  /// pool.
-  void AddAnyMethodToGlobalPool(Decl *D);
+  /// 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);
 
-  /// 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);
-  }
+  /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
+  /// initializer for the declaration 'Dcl'.
+  void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl);
 
-  /// 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);
-  }
+  /// 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);
 
-  const ObjCMethodDecl *SelectorsForTypoCorrection(Selector Sel,
-                              QualType ObjectType=QualType());
-  /// LookupImplementedMethodInGlobalPool - Returns the method which has an
-  /// implementation.
-  ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel);
+  /// 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);
 
-  /// CollectIvarsToConstructOrDestruct - Collect those ivars which require
-  /// initialization.
-  void CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI,
-                                  SmallVectorImpl &Ivars);
+  Decl *ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc,
+                                       Expr *LangStr, SourceLocation LBraceLoc);
+  Decl *ActOnFinishLinkageSpecification(Scope *S, Decl *LinkageSpec,
+                                        SourceLocation RBraceLoc);
 
   //===--------------------------------------------------------------------===//
-  // Statement Parsing Callbacks: SemaStmt.cpp.
-public:
-  class FullExprArg {
-  public:
-    FullExprArg() : E(nullptr) { }
-    FullExprArg(Sema &actions) : E(nullptr) { }
-
-    ExprResult release() {
-      return E;
-    }
+  // 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);
 
-    Expr *get() const { return E; }
+  bool ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc,
+                            SourceLocation ColonLoc,
+                            const ParsedAttributesView &Attrs);
 
-    Expr *operator->() {
-      return E;
-    }
+  NamedDecl *
+  ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
+                           MultiTemplateParamsArg TemplateParameterLists,
+                           Expr *BitfieldWidth, const VirtSpecifiers &VS,
+                           InClassInitStyle InitStyle);
 
-  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;
+  void ActOnStartCXXInClassMemberInitializer();
+  void ActOnFinishCXXInClassMemberInitializer(Decl *VarDecl,
+                                              SourceLocation EqualLoc,
+                                              Expr *Init);
 
-    explicit FullExprArg(Expr *expr) : E(expr) {}
+  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);
 
-    Expr *E;
-  };
+  MemInitResult ActOnMemInitializer(Decl *ConstructorD, Scope *S,
+                                    CXXScopeSpec &SS,
+                                    IdentifierInfo *MemberOrBase,
+                                    ParsedType TemplateTypeTy,
+                                    const DeclSpec &DS, SourceLocation IdLoc,
+                                    Expr *InitList, SourceLocation EllipsisLoc);
 
-  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());
-  }
+  MemInitResult BuildMemInitializer(Decl *ConstructorD, Scope *S,
+                                    CXXScopeSpec &SS,
+                                    IdentifierInfo *MemberOrBase,
+                                    ParsedType TemplateTypeTy,
+                                    const DeclSpec &DS, SourceLocation IdLoc,
+                                    Expr *Init, SourceLocation EllipsisLoc);
 
-  StmtResult ActOnExprStmt(ExprResult Arg, bool DiscardedValue = true);
-  StmtResult ActOnExprStmtError();
+  MemInitResult BuildMemberInitializer(ValueDecl *Member, Expr *Init,
+                                       SourceLocation IdLoc);
 
-  StmtResult ActOnNullStmt(SourceLocation SemiLoc,
-                           bool HasLeadingEmptyMacro = false);
+  MemInitResult BuildBaseInitializer(QualType BaseType,
+                                     TypeSourceInfo *BaseTInfo, Expr *Init,
+                                     CXXRecordDecl *ClassDecl,
+                                     SourceLocation EllipsisLoc);
 
-  void ActOnStartOfCompoundStmt(bool IsStmtExpr);
-  void ActOnAfterCompoundStatementLeadingPragmas();
-  void ActOnFinishOfCompoundStmt();
-  StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
-                               ArrayRef Elts, bool isStmtExpr);
+  MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
+                                           CXXRecordDecl *ClassDecl);
 
-  /// A RAII object to enter scope of a compound statement.
-  class CompoundScopeRAII {
-  public:
-    CompoundScopeRAII(Sema &S, bool IsStmtExpr = false) : S(S) {
-      S.ActOnStartOfCompoundStmt(IsStmtExpr);
-    }
+  bool SetDelegatingInitializer(CXXConstructorDecl *Constructor,
+                                CXXCtorInitializer *Initializer);
 
-    ~CompoundScopeRAII() {
-      S.ActOnFinishOfCompoundStmt();
-    }
+  bool SetCtorInitializers(
+      CXXConstructorDecl *Constructor, bool AnyErrors,
+      ArrayRef Initializers = std::nullopt);
 
-  private:
-    Sema &S;
-  };
+  void SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation);
 
-  /// 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; }
-  };
+  /// MarkBaseAndMemberDestructorsReferenced - Given a record decl,
+  /// mark all the non-trivial destructors of its members and bases as
+  /// referenced.
+  void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
+                                              CXXRecordDecl *Record);
 
-  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);
-
-  StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
-                                      SourceLocation ColonLoc,
-                                      Stmt *SubStmt, Scope *CurScope);
-  StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
-                            SourceLocation ColonLoc, Stmt *SubStmt);
-
-  StmtResult BuildAttributedStmt(SourceLocation AttrsLoc,
-                                 ArrayRef Attrs, Stmt *SubStmt);
-  StmtResult ActOnAttributedStmt(const ParsedAttributes &AttrList,
-                                 Stmt *SubStmt);
-  bool CheckRebuiltAttributedStmtAttributes(ArrayRef Attrs);
-
-  class ConditionResult;
-
-  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);
+  /// 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);
 
-  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);
+  /// 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);
 
-  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
-  };
+  /// 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;
 
-  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);
+  /// The list of vtables that are required but have not yet been
+  /// materialized.
+  SmallVector VTableUses;
 
-  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);
+  /// 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;
 
-  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);
+  /// Load any externally-stored vtable uses.
+  void LoadExternalVTableUses();
 
-  struct NamedReturnInfo {
-    const VarDecl *Candidate;
+  /// Note that the vtable for the given class was used at the
+  /// given location.
+  void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
+                      bool DefinitionRequired = false);
 
-    enum Status : uint8_t { None, MoveEligible, MoveEligibleAndCopyElidable };
-    Status S;
+  /// Mark the exception specifications of all virtual member functions
+  /// in the given class as needed.
+  void MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc,
+                                             const CXXRecordDecl *RD);
 
-    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);
+  /// MarkVirtualMembersReferenced - Will mark all members of the given
+  /// CXXRecordDecl referenced.
+  void MarkVirtualMembersReferenced(SourceLocation Loc, const CXXRecordDecl *RD,
+                                    bool ConstexprOnly = false);
 
-  ExprResult
-  PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
-                                  const NamedReturnInfo &NRInfo, Expr *Value,
-                                  bool SupressSimplerImplicitMoves = false);
+  /// 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();
 
-  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);
+  void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl);
 
-  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);
+  void ActOnMemInitializers(Decl *ConstructorDecl, SourceLocation ColonLoc,
+                            ArrayRef MemInits,
+                            bool AnyErrors);
 
-  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);
+  /// 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);
 
-  VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType,
-                                  SourceLocation StartLoc,
-                                  SourceLocation IdLoc, IdentifierInfo *Id,
-                                  bool Invalid = false);
+  void referenceDLLExportedClassMethods();
 
-  Decl *ActOnObjCExceptionDecl(Scope *S, Declarator &D);
+  void propagateDLLAttrToBaseClassTemplate(
+      CXXRecordDecl *Class, Attr *ClassAttr,
+      ClassTemplateSpecializationDecl *BaseTemplateSpec,
+      SourceLocation BaseLoc);
 
-  StmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen,
-                                  Decl *Parm, Stmt *Body);
+  void CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record);
 
-  StmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body);
+  /// 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);
 
-  StmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
-                                MultiStmtArg Catch, Stmt *Finally);
+  void ActOnFinishCXXMemberSpecification(Scope *S, SourceLocation RLoc,
+                                         Decl *TagDecl, SourceLocation LBrac,
+                                         SourceLocation RBrac,
+                                         const ParsedAttributesView &AttrList);
+  void ActOnFinishCXXMemberDecls();
+  void ActOnFinishCXXNonNestedClass();
 
-  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);
+  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 ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body);
+  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);
 
-  VarDecl *BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo,
-                                     SourceLocation StartLoc,
-                                     SourceLocation IdLoc,
-                                     IdentifierInfo *Id);
+  Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
+                            MultiTemplateParamsArg TemplateParams);
+  NamedDecl *ActOnFriendFunctionDecl(Scope *S, Declarator &D,
+                                     MultiTemplateParamsArg TemplateParams);
 
-  Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D);
+  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 ActOnCXXCatchBlock(SourceLocation CatchLoc,
-                                Decl *ExDecl, Stmt *HandlerBlock);
-  StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
-                              ArrayRef Handlers);
+  void CheckExplicitlyDefaultedFunction(Scope *S, FunctionDecl *MD);
 
-  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);
+  bool CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
+                                             CXXSpecialMember CSM,
+                                             SourceLocation DefaultLoc);
+  void CheckDelayedMemberExceptionSpecs();
 
-  void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock);
+  /// 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,
+  };
 
-  bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const;
+  bool CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *MD,
+                                          DefaultedComparisonKind DCK);
+  void DeclareImplicitEqualityComparison(CXXRecordDecl *RD,
+                                         FunctionDecl *Spaceship);
+  void DefineDefaultedComparison(SourceLocation Loc, FunctionDecl *FD,
+                                 DefaultedComparisonKind DCK);
 
-  /// If it's a file scoped decl that must warn if not used, keep track
-  /// of it.
-  void MarkUnusedFileScopedDecl(const DeclaratorDecl *D);
+  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);
 
-  typedef llvm::function_ref
-      DiagReceiverTy;
+  //===--------------------------------------------------------------------===//
+  // C++ Derived Classes
+  //
 
-  /// 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);
+  /// ActOnBaseSpecifier - Parsed a base specifier
+  CXXBaseSpecifier *CheckBaseSpecifier(CXXRecordDecl *Class,
+                                       SourceRange SpecifierRange, bool Virtual,
+                                       AccessSpecifier Access,
+                                       TypeSourceInfo *TInfo,
+                                       SourceLocation EllipsisLoc);
 
-  /// If VD is set but not otherwise used, diagnose, for a parameter or a
-  /// variable.
-  void DiagnoseUnusedButSetDecl(const VarDecl *VD, DiagReceiverTy DiagReceiver);
+  BaseResult ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
+                                const ParsedAttributesView &Attrs, bool Virtual,
+                                AccessSpecifier Access, ParsedType basetype,
+                                SourceLocation BaseLoc,
+                                SourceLocation EllipsisLoc);
 
-  /// 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);
+  bool AttachBaseSpecifiers(CXXRecordDecl *Class,
+                            MutableArrayRef Bases);
+  void ActOnBaseSpecifiers(Decl *ClassDecl,
+                           MutableArrayRef Bases);
 
-  /// 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);
+  bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base);
+  bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base,
+                     CXXBasePaths &Paths);
 
-  /// Warn if a value is moved to itself.
-  void DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr,
-                        SourceLocation OpLoc);
+  // FIXME: I don't like this name.
+  void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath);
 
-  /// 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);
+  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);
 
-  /// Warn if we're implicitly casting from a _Nullable pointer type to a
-  /// _Nonnull one.
-  void diagnoseNullableToNonnullConversion(QualType DstType, QualType SrcType,
-                                           SourceLocation Loc);
+  std::string getAmbiguousPathsDisplayString(CXXBasePaths &Paths);
 
-  /// Warn when implicitly casting 0 to nullptr.
-  void diagnoseZeroToNullptrConversion(CastKind Kind, const Expr *E);
+  bool CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
+                                         const CXXMethodDecl *Old);
 
-  ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool) {
-    return DelayedDiagnostics.push(pool);
-  }
-  void PopParsingDeclaration(ParsingDeclState state, Decl *decl);
+  /// CheckOverridingFunctionReturnType - Checks whether the return types are
+  /// covariant, according to C++ [class.virtual]p5.
+  bool CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
+                                         const CXXMethodDecl *Old);
 
-  typedef ProcessingContextState ParsingClassState;
-  ParsingClassState PushParsingClass() {
-    ParsingClassDepth++;
-    return DelayedDiagnostics.pushUndelayed();
-  }
-  void PopParsingClass(ParsingClassState state) {
-    ParsingClassDepth--;
-    DelayedDiagnostics.popUndelayed(state);
-  }
+  // Check that the overriding method has no explicit object parameter.
+  bool CheckExplicitObjectOverride(CXXMethodDecl *New,
+                                   const CXXMethodDecl *Old);
 
-  void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);
+  bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange);
 
-  void DiagnoseAvailabilityOfDecl(NamedDecl *D, ArrayRef Locs,
-                                  const ObjCInterfaceDecl *UnknownObjCClass,
-                                  bool ObjCPropertyAccess,
-                                  bool AvoidPartialAvailabilityChecks = false,
-                                  ObjCInterfaceDecl *ClassReceiver = nullptr);
+  /// CheckOverrideControl - Check C++11 override control semantics.
+  void CheckOverrideControl(NamedDecl *D);
 
-  bool makeUnavailableInSystemHeader(SourceLocation loc,
-                                     UnavailableAttr::ImplicitReason reason);
+  /// DiagnoseAbsenceOfOverrideControl - Diagnose if 'override' keyword was
+  /// not used in the declaration of an overriding method.
+  void DiagnoseAbsenceOfOverrideControl(NamedDecl *D, bool Inconsistent);
 
-  /// Issue any -Wunguarded-availability warnings in \c FD
-  void DiagnoseUnguardedAvailabilityViolations(Decl *FD);
+  /// 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);
 
-  void handleDelayedAvailabilityCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
+  enum AbstractDiagSelID {
+    AbstractNone = -1,
+    AbstractReturnType,
+    AbstractParamType,
+    AbstractVariableType,
+    AbstractFieldType,
+    AbstractIvarType,
+    AbstractSynthesizedIvarType,
+    AbstractArrayType
+  };
 
-  //===--------------------------------------------------------------------===//
-  // Expression Parsing Callbacks: SemaExpr.cpp.
+  struct TypeDiagnoser;
 
-  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);
+  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);
   }
 
-  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);
+  void DiagnoseAbstractType(const CXXRecordDecl *RD);
 
-  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();
+  //===--------------------------------------------------------------------===//
+  // C++ Overloaded Operators [C++ 13.5]
+  //
 
-  void DiscardCleanupsInEvaluationContext();
+  bool CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl);
 
-  ExprResult TransformToPotentiallyEvaluated(Expr *E);
-  TypeSourceInfo *TransformToPotentiallyEvaluated(TypeSourceInfo *TInfo);
-  ExprResult HandleExprEvaluationContextForTypeof(Expr *E);
+  bool CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl);
 
-  ExprResult CheckUnevaluatedOperand(Expr *E);
-  void CheckUnusedVolatileAssignment(Expr *E);
+  /// ActOnExplicitBoolSpecifier - Build an ExplicitSpecifier from an expression
+  /// found in an explicit(bool) specifier.
+  ExplicitSpecifier ActOnExplicitBoolSpecifier(Expr *E);
 
-  ExprResult ActOnConstantExpression(ExprResult Res);
+  /// tryResolveExplicitSpecifier - Attempt to resolve the explict specifier.
+  /// Returns true if the explicit specifier is now resolved.
+  bool tryResolveExplicitSpecifier(ExplicitSpecifier &ExplicitSpec);
 
-  // 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);
+  DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D);
 
-  ExprResult CheckLValueToRValueConversionOperand(Expr *E);
-  void CleanupVarDeclMarking();
+  // Emitting members of dllexported classes is delayed until the class
+  // (including field initializers) is fully parsed.
+  SmallVector DelayedDllExportClasses;
+  SmallVector DelayedDllExportMemberFunctions;
 
-  enum TryCaptureKind {
-    TryCapture_Implicit, TryCapture_ExplicitByVal, TryCapture_ExplicitByRef
-  };
+  void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old);
+  bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S);
 
-  /// 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);
+  /// Helpers for dealing with blocks and functions.
+  void CheckCXXDefaultArguments(FunctionDecl *FD);
+  void CheckExtraCXXDefaultArguments(Declarator &D);
 
-  /// Try to capture the given variable.
-  bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc,
-                          TryCaptureKind Kind = TryCapture_Implicit,
-                          SourceLocation EllipsisLoc = SourceLocation());
+  CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD) {
+    return getDefaultedFunctionKind(MD).asSpecialMember();
+  }
 
-  /// Checks if the variable must be captured.
-  bool NeedToCaptureVariable(ValueDecl *Var, SourceLocation Loc);
+  VarDecl *BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo,
+                                     SourceLocation StartLoc,
+                                     SourceLocation IdLoc, IdentifierInfo *Id);
 
-  /// Given a variable, determine the type that a reference to that
-  /// variable will have in the given scope.
-  QualType getCapturedDeclRefType(ValueDecl *Var, SourceLocation Loc);
+  Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D);
 
-  /// 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 DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock);
 
-  /// 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);
+  DeclResult ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
+                                     unsigned TagSpec, SourceLocation TagLoc,
+                                     CXXScopeSpec &SS, IdentifierInfo *Name,
+                                     SourceLocation NameLoc,
+                                     const ParsedAttributesView &Attr,
+                                     MultiTemplateParamsArg TempParamLists);
 
-  /// Figure out if an expression could be turned into a call.
-  bool tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
-                     UnresolvedSetImpl &NonTemplateOverloads);
+  MSPropertyDecl *HandleMSProperty(Scope *S, RecordDecl *TagD,
+                                   SourceLocation DeclStart, Declarator &D,
+                                   Expr *BitfieldWidth,
+                                   InClassInitStyle InitStyle,
+                                   AccessSpecifier AS,
+                                   const ParsedAttr &MSPropertyAttr);
 
-  /// Try to convert an expression \p E to type \p Ty. Returns the result of the
-  /// conversion.
-  ExprResult tryConvertExprToType(Expr *E, QualType Ty);
+  void DiagnoseNontrivial(const CXXRecordDecl *Record, CXXSpecialMember CSM);
 
-  /// 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);
+  enum TrivialABIHandling {
+    /// The triviality of a method unaffected by "trivial_abi".
+    TAH_IgnoreTrivialABI,
 
-  /// 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);
+    /// The triviality of a method affected by "trivial_abi".
+    TAH_ConsiderTrivialABI
+  };
 
-  // Primary Expressions.
-  SourceRange getExprRange(Expr *E) const;
+  bool SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
+                              TrivialABIHandling TAH = TAH_IgnoreTrivialABI,
+                              bool Diagnose = false);
 
-  ExprResult ActOnIdExpression(
-      Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
-      UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand,
-      CorrectionCandidateCallback *CCC = nullptr,
-      bool IsInlineAsmIdentifier = false, Token *KeywordReplacement = nullptr);
+  /// For a defaulted function, the kind of defaulted function that it is.
+  class DefaultedFunctionKind {
+    unsigned SpecialMember : 8;
+    unsigned Comparison : 8;
 
-  void DecomposeUnqualifiedId(const UnqualifiedId &Id,
-                              TemplateArgumentListInfo &Buffer,
-                              DeclarationNameInfo &NameInfo,
-                              const TemplateArgumentListInfo *&TemplateArgs);
+  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 DiagnoseDependentMemberLookup(const LookupResult &R);
+    bool isSpecialMember() const { return SpecialMember != CXXInvalid; }
+    bool isComparison() const {
+      return static_cast(Comparison) !=
+             DefaultedComparisonKind::None;
+    }
 
-  bool
-  DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
-                      CorrectionCandidateCallback &CCC,
-                      TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
-                      ArrayRef Args = std::nullopt,
-                      DeclContext *LookupCtx = nullptr,
-                      TypoExpr **Out = nullptr);
+    explicit operator bool() const {
+      return isSpecialMember() || isComparison();
+    }
 
-  DeclResult LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S,
-                                    IdentifierInfo *II);
-  ExprResult BuildIvarRefExpr(Scope *S, SourceLocation Loc, ObjCIvarDecl *IV);
+    CXXSpecialMember asSpecialMember() const {
+      return static_cast(SpecialMember);
+    }
+    DefaultedComparisonKind asComparison() const {
+      return static_cast(Comparison);
+    }
 
-  ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S,
-                                IdentifierInfo *II,
-                                bool AllowBuiltinCreation=false);
+    /// 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;
+    }
+  };
 
-  ExprResult ActOnDependentIdExpression(const CXXScopeSpec &SS,
-                                        SourceLocation TemplateKWLoc,
-                                        const DeclarationNameInfo &NameInfo,
-                                        bool isAddressOfOperand,
-                                const TemplateArgumentListInfo *TemplateArgs);
+  DefaultedFunctionKind getDefaultedFunctionKind(const FunctionDecl *FD);
 
-  /// 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);
+  /// Handle a C++11 empty-declaration and attribute-declaration.
+  Decl *ActOnEmptyDeclaration(Scope *S, const ParsedAttributesView &AttrList,
+                              SourceLocation SemiLoc);
 
-  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);
+  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
+  };
 
-  ExprResult
-  BuildAnonymousStructUnionMemberReference(
-      const CXXScopeSpec &SS,
-      SourceLocation nameLoc,
-      IndirectFieldDecl *indirectField,
-      DeclAccessPair FoundDecl = DeclAccessPair::make(nullptr, AS_none),
-      Expr *baseObjectExpr = nullptr,
-      SourceLocation opLoc = SourceLocation());
+  bool CheckConstexprFunctionDefinition(const FunctionDecl *FD,
+                                        CheckConstexprKind Kind);
 
-  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);
+  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);
 
-  ExprResult
-  BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
-                                    const DeclarationNameInfo &NameInfo,
-                                    bool IsAddressOfOperand, const Scope *S,
-                                    TypeSourceInfo **RecoveryTSI = nullptr);
+  void ActOnPureSpecifier(Decl *D, SourceLocation PureSpecLoc);
+  void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc);
+  void SetDeclDefaulted(Decl *dcl, SourceLocation DefaultLoc);
 
-  ExprResult BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
-                                       SourceLocation TemplateKWLoc,
-                                const DeclarationNameInfo &NameInfo,
-                                const TemplateArgumentListInfo *TemplateArgs);
+  void SetFunctionBodyKind(Decl *D, SourceLocation Loc, FnBodyKind BodyKind);
+  void ActOnStartTrailingRequiresClause(Scope *S, Declarator &D);
+  ExprResult ActOnFinishTrailingRequiresClause(ExprResult ConstraintExpr);
+  ExprResult ActOnRequiresClause(ExprResult ConstraintExpr);
 
-  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);
+  NamedDecl *
+  ActOnDecompositionDeclarator(Scope *S, Declarator &D,
+                               MultiTemplateParamsArg TemplateParamLists);
+  void DiagPlaceholderVariableDefinition(SourceLocation Loc);
+  bool DiagRedefinedPlaceholderFieldDecl(SourceLocation Loc,
+                                         RecordDecl *ClassDecl,
+                                         const IdentifierInfo *Name);
 
-  ExprResult BuildLiteralOperatorCall(LookupResult &R,
-                      DeclarationNameInfo &SuffixInfo,
-                      ArrayRef Args,
-                      SourceLocation LitEndLoc,
-                      TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr);
+  void CheckCompleteDecompositionDeclaration(DecompositionDecl *DD);
 
-  // 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);
+  /// 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;
 
-  ExprResult BuildPredefinedExpr(SourceLocation Loc, PredefinedIdentKind IK);
-  ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind);
-  ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val);
+  /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes.
+  std::unique_ptr FieldCollector;
 
-  ExprResult BuildSYCLUniqueStableNameExpr(SourceLocation OpLoc,
-                                           SourceLocation LParen,
-                                           SourceLocation RParen,
-                                           TypeSourceInfo *TSI);
-  ExprResult ActOnSYCLUniqueStableNameExpr(SourceLocation OpLoc,
-                                           SourceLocation LParen,
-                                           SourceLocation RParen,
-                                           ParsedType ParsedTy);
+  typedef llvm::SmallSetVector NamedDeclSetType;
+  /// Set containing all declared private fields that are not used.
+  NamedDeclSetType UnusedPrivateFields;
 
-  ExprResult BuildSYCLUniqueStableIdExpr(SourceLocation OpLoc,
-                                         SourceLocation LParen,
-                                         SourceLocation RParen, Expr *E);
-  ExprResult ActOnSYCLUniqueStableIdExpr(SourceLocation OpLoc,
-                                         SourceLocation LParen,
-                                         SourceLocation RParen, Expr *E);
+  typedef llvm::SmallPtrSet RecordDeclSetTy;
 
-  bool CheckLoopHintExpr(Expr *E, SourceLocation Loc);
+  /// 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;
 
-  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);
+  typedef LazyVector
+      DelegatingCtorDeclsType;
 
-  /// ActOnStringLiteral - The specified tokens were lexed as pasted string
-  /// fragments (e.g. "foo" "bar" L"baz").
-  ExprResult ActOnStringLiteral(ArrayRef StringToks,
-                                Scope *UDLScope = nullptr);
+  /// All the delegating constructors seen so far in the file, used for
+  /// cycle detection at the end of the TU.
+  DelegatingCtorDeclsType DelegatingCtorDecls;
 
-  ExprResult ActOnUnevaluatedStringLiteral(ArrayRef StringToks);
+  /// The C++ "std" namespace, where the standard library resides.
+  LazyDeclPtr StdNamespace;
 
-  /// 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);
+  /// The C++ "std::initializer_list" template, which is defined in
+  /// \.
+  ClassTemplateDecl *StdInitializerList;
 
-  // 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);
+  // Contains the locations of the beginning of unparsed default
+  // argument locations.
+  llvm::DenseMap UnparsedDefaultArgLocs;
 
-  bool isQualifiedMemberAccess(Expr *E);
-  bool CheckUseOfCXXMethodAsAddressOfOperand(SourceLocation OpLoc,
-                                             const Expr *Op,
-                                             const CXXMethodDecl *MD);
+  /// UndefinedInternals - all the used, undefined objects which require a
+  /// definition in this translation unit.
+  llvm::MapVector UndefinedButUsed;
 
-  QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc);
+  typedef llvm::PointerIntPair
+      SpecialMemberDecl;
 
-  bool CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N);
+  /// 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;
 
-  bool ActOnAlignasTypeArgument(StringRef KWName, ParsedType Ty,
-                                SourceLocation OpLoc, SourceRange R);
-  bool CheckAlignasTypeArgument(StringRef KWName, TypeSourceInfo *TInfo,
-                                SourceLocation OpLoc, SourceRange R);
+  void NoteDeletedInheritingConstructor(CXXConstructorDecl *CD);
 
-  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);
+  void ActOnDefaultCtorInitializers(Decl *CDtorDecl);
 
-  ExprResult CheckPlaceholderExpr(Expr *E);
-  bool CheckVecStepExpr(Expr *E);
+  typedef ProcessingContextState ParsingClassState;
+  ParsingClassState PushParsingClass() {
+    ParsingClassDepth++;
+    return DelayedDiagnostics.pushUndelayed();
+  }
+  void PopParsingClass(ParsingClassState state) {
+    ParsingClassDepth--;
+    DelayedDiagnostics.popUndelayed(state);
+  }
 
-  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);
+private:
+  void setupImplicitSpecialMemberType(CXXMethodDecl *SpecialMem,
+                                      QualType ResultTy,
+                                      ArrayRef Args);
 
-  ExprResult ActOnPackIndexingExpr(Scope *S, Expr *PackExpression,
-                                   SourceLocation EllipsisLoc,
-                                   SourceLocation LSquareLoc, Expr *IndexExpr,
-                                   SourceLocation RSquareLoc);
+  // 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 BuildPackIndexingExpr(Expr *PackExpression,
-                                   SourceLocation EllipsisLoc, Expr *IndexExpr,
-                                   SourceLocation RSquareLoc,
-                                   ArrayRef ExpandedExprs = {},
-                                   bool EmptyPack = false);
+  ValueDecl *tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl,
+                                         CXXScopeSpec &SS,
+                                         ParsedType TemplateTypeTy,
+                                         IdentifierInfo *MemberOrBase);
 
-  ExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
-                                 tok::TokenKind Kind, Expr *Input);
+  /// Check if there is a field shadowing.
+  void CheckShadowInheritedFields(const SourceLocation &Loc,
+                                  DeclarationName FieldName,
+                                  const CXXRecordDecl *RD,
+                                  bool DeclIsField = true);
 
-  ExprResult ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc,
-                                     MultiExprArg ArgExprs,
-                                     SourceLocation RLoc);
-  ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
-                                             Expr *Idx, SourceLocation RLoc);
+  ///@}
 
-  ExprResult CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx,
-                                              Expr *ColumnIdx,
-                                              SourceLocation RBLoc);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  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);
+  /// \name C++ Exception Specifications
+  /// Implementations are in SemaExceptionSpec.cpp
+  ///@{
 
-  /// Data structure for iterator expression.
-  struct OMPIteratorData {
-    IdentifierInfo *DeclIdent = nullptr;
-    SourceLocation DeclIdentLoc;
-    ParsedType Type;
-    OMPIteratorExpr::IteratorRange Range;
-    SourceLocation AssignLoc;
-    SourceLocation ColonLoc;
-    SourceLocation SecColonLoc;
-  };
+public:
+  /// All the overriding functions seen during a class definition
+  /// that had their exception spec checks delayed, plus the overridden
+  /// function.
+  SmallVector, 2>
+      DelayedOverridingExceptionSpecChecks;
 
-  ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc,
-                                  SourceLocation LLoc, SourceLocation RLoc,
-                                  ArrayRef Data);
+  /// 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;
 
-  // 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;
-  };
+  /// 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);
 
-  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);
+  /// Check the given noexcept-specifier, convert its expression, and compute
+  /// the appropriate ExceptionSpecificationType.
+  ExprResult ActOnNoexceptSpec(Expr *NoexceptExpr,
+                               ExceptionSpecificationType &EST);
 
-  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);
+  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);
 
-  ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,
-                                     SourceLocation OpLoc,
-                                     const CXXScopeSpec &SS, FieldDecl *Field,
-                                     DeclAccessPair FoundDecl,
-                                     const DeclarationNameInfo &MemberNameInfo);
+  bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType);
 
-  ExprResult PerformMemberExprBaseConversion(Expr *Base, bool IsArrow);
+  /// CheckOverridingFunctionExceptionSpec - Checks whether the exception
+  /// spec is a subset of base spec.
+  bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
+                                            const CXXMethodDecl *Old);
 
-  bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType,
-                                     const CXXScopeSpec &SS,
-                                     const LookupResult &R);
-
-  ExprResult ActOnDependentMemberExpr(Expr *Base, QualType BaseType,
-                                      bool IsArrow, SourceLocation OpLoc,
-                                      const CXXScopeSpec &SS,
-                                      SourceLocation TemplateKWLoc,
-                                      NamedDecl *FirstQualifierInScope,
-                               const DeclarationNameInfo &NameInfo,
-                               const TemplateArgumentListInfo *TemplateArgs);
-
-  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 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);
+  /// \name Expressions
+  /// Implementations are in SemaExpr.cpp
+  ///@{
 
-  /// 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);
+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 ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
-                                     MultiExprArg ExecConfig,
-                                     SourceLocation GGGLoc);
+    /// 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 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);
+    /// 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,
 
-  /// Build an altivec or OpenCL literal.
-  ExprResult BuildVectorLiteral(SourceLocation LParenLoc,
-                                SourceLocation RParenLoc, Expr *E,
-                                TypeSourceInfo *TInfo);
+    /// 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 MaybeConvertParenListExprToParenExpr(Scope *S, Expr *ME);
+    /// 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,
 
-  ExprResult ActOnCompoundLiteral(SourceLocation LParenLoc,
-                                  ParsedType Ty,
-                                  SourceLocation RParenLoc,
-                                  Expr *InitExpr);
+    /// 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 BuildCompoundLiteralExpr(SourceLocation LParenLoc,
-                                      TypeSourceInfo *TInfo,
-                                      SourceLocation RParenLoc,
-                                      Expr *LiteralExpr);
+    /// 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,
 
-  ExprResult ActOnInitList(SourceLocation LBraceLoc,
-                           MultiExprArg InitArgList,
-                           SourceLocation RBraceLoc);
+    /// 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 BuildInitList(SourceLocation LBraceLoc,
-                           MultiExprArg InitArgList,
-                           SourceLocation RBraceLoc);
+  /// 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 ActOnDesignatedInitializer(Designation &Desig,
-                                        SourceLocation EqualOrColonLoc,
-                                        bool GNUSyntax,
-                                        ExprResult Init);
+  using ImmediateInvocationCandidate = llvm::PointerIntPair;
 
-private:
-  static BinaryOperatorKind ConvertTokenKindToBinaryOpcode(tok::TokenKind Kind);
+  /// Data structure used to record current or nested
+  /// expression evaluation contexts.
+  struct ExpressionEvaluationContextRecord {
+    /// The expression evaluation context.
+    ExpressionEvaluationContext Context;
 
-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 the enclosing context needed a cleanup.
+    CleanupInfo ParentCleanup;
 
-  void DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc);
+    /// The number of active cleanup objects when we entered
+    /// this expression evaluation context.
+    unsigned NumCleanupObjects;
 
-  /// 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);
+    /// The number of typos encountered during this expression evaluation
+    /// context (i.e. the number of TypoExprs created).
+    unsigned NumTypos;
 
-  /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
-  ExprResult ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
-                            LabelDecl *TheDecl);
+    MaybeODRUseExprSet SavedMaybeODRUseExprs;
 
-  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();
+    /// The lambdas that are present within this context, if it
+    /// is indeed an unevaluated context.
+    SmallVector Lambdas;
 
-  // __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;
-  };
+    /// 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;
 
-  /// __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);
+    /// 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;
 
-  // __builtin_choose_expr(constExpr, expr1, expr2)
-  ExprResult ActOnChooseExpr(SourceLocation BuiltinLoc,
-                             Expr *CondExpr, Expr *LHSExpr,
-                             Expr *RHSExpr, SourceLocation RPLoc);
+    /// If we are processing a decltype type, a set of temporary binding
+    /// expressions for which we have deferred checking the destructor.
+    SmallVector DelayedDecltypeBinds;
 
-  // __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);
+    llvm::SmallPtrSet PossibleDerefs;
 
-  // __builtin_LINE(), __builtin_FUNCTION(), __builtin_FUNCSIG(),
-  // __builtin_FILE(), __builtin_COLUMN(), __builtin_source_location()
-  ExprResult ActOnSourceLocExpr(SourceLocIdentKind Kind,
-                                SourceLocation BuiltinLoc,
-                                SourceLocation RPLoc);
+    /// 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;
 
-  // Build a potentially resolved SourceLocExpr.
-  ExprResult BuildSourceLocExpr(SourceLocIdentKind Kind, QualType ResultTy,
-                                SourceLocation BuiltinLoc, SourceLocation RPLoc,
-                                DeclContext *ParentContext);
+    /// Set of candidates for starting an immediate invocation.
+    llvm::SmallVector
+        ImmediateInvocationCandidates;
 
-  // __null
-  ExprResult ActOnGNUNullExpr(SourceLocation TokenLoc);
+    /// Set of DeclRefExprs referencing a consteval function when used in a
+    /// context not already known to be immediately invoked.
+    llvm::SmallPtrSet ReferenceToConsteval;
 
-  bool CheckCaseExpression(Expr *E);
+    /// 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;
 
-  /// Describes the result of an "if-exists" condition check.
-  enum IfExistsResult {
-    /// The symbol exists.
-    IER_Exists,
+    /// \brief Describes whether we are in an expression constext which we have
+    /// to handle differently.
+    enum ExpressionKind {
+      EK_Decltype,
+      EK_TemplateArgument,
+      EK_Other
+    } ExprContext;
 
-    /// The symbol does not exist.
-    IER_DoesNotExist,
+    // 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;
 
-    /// The name is a dependent name, so the results will differ
-    /// from one instantiation to the next.
-    IER_Dependent,
+    bool IsCurrentlyCheckingDefaultArgumentOrInitializer = false;
 
-    /// An error occurred.
-    IER_Error
-  };
+    // 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;
 
-  IfExistsResult
-  CheckMicrosoftIfExistsSymbol(Scope *S, CXXScopeSpec &SS,
-                               const DeclarationNameInfo &TargetNameInfo);
+    /// 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;
 
-  IfExistsResult
-  CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc,
-                               bool IsIfExists, CXXScopeSpec &SS,
-                               UnqualifiedId &Name);
+    /// 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;
 
-  StmtResult BuildMSDependentExistsStmt(SourceLocation KeywordLoc,
-                                        bool IsIfExists,
-                                        NestedNameSpecifierLoc QualifierLoc,
-                                        DeclarationNameInfo NameInfo,
-                                        Stmt *Nested);
-  StmtResult ActOnMSDependentExistsStmt(SourceLocation KeywordLoc,
-                                        bool IsIfExists,
-                                        CXXScopeSpec &SS, UnqualifiedId &Name,
-                                        Stmt *Nested);
+    // 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");
+      }
 
-  //===------------------------- "Block" Extension ------------------------===//
+      SourceLocation Loc;
+      ValueDecl *Decl = nullptr;
+      DeclContext *Context = nullptr;
+    };
+    std::optional DelayedDefaultInitializationContext;
 
-  /// ActOnBlockStart - This callback is invoked when a block literal is
-  /// started.
-  void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope);
+    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) {}
 
-  /// 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 isUnevaluated() const {
+      return Context == ExpressionEvaluationContext::Unevaluated ||
+             Context == ExpressionEvaluationContext::UnevaluatedAbstract ||
+             Context == ExpressionEvaluationContext::UnevaluatedList;
+    }
 
-  /// 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);
+    bool isConstantEvaluated() const {
+      return Context == ExpressionEvaluationContext::ConstantEvaluated ||
+             Context == ExpressionEvaluationContext::ImmediateFunctionContext;
+    }
 
-  /// 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);
+    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);
+    }
 
-  //===---------------------------- Clang Extensions ----------------------===//
+    bool isDiscardedStatementContext() const {
+      return Context == ExpressionEvaluationContext::DiscardedStatement ||
+             (Context ==
+                  ExpressionEvaluationContext::ImmediateFunctionContext &&
+              InDiscardedStatement);
+    }
+  };
 
-  /// __builtin_convertvector(...)
-  ExprResult ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy,
-                                    SourceLocation BuiltinLoc,
-                                    SourceLocation RParenLoc);
+  const ExpressionEvaluationContextRecord ¤tEvaluationContext() const {
+    assert(!ExprEvalContexts.empty() &&
+           "Must be in an expression evaluation context");
+    return ExprEvalContexts.back();
+  };
 
-  //===---------------------------- OpenCL Features -----------------------===//
+  /// 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;
 
-  /// __builtin_astype(...)
-  ExprResult ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy,
-                             SourceLocation BuiltinLoc,
-                             SourceLocation RParenLoc);
-  ExprResult BuildAsTypeExpr(Expr *E, QualType DestTy,
-                             SourceLocation BuiltinLoc,
-                             SourceLocation RParenLoc);
+  /// Used to control the generation of ExprWithCleanups.
+  CleanupInfo Cleanup;
 
-  //===---------------------------- HLSL Features -------------------------===//
-  Decl *ActOnStartHLSLBuffer(Scope *BufferScope, bool CBuffer,
-                             SourceLocation KwLoc, IdentifierInfo *Ident,
-                             SourceLocation IdentLoc, SourceLocation LBrace);
-  void ActOnFinishHLSLBuffer(Decl *Dcl, SourceLocation RBrace);
+  /// ExprCleanupObjects - This is the stack of objects requiring
+  /// cleanup that are created by the current full expression.
+  SmallVector ExprCleanupObjects;
 
-  //===---------------------------- C++ Features --------------------------===//
+  // 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
+  };
 
-  // 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);
+  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);
+  }
 
-  NamespaceDecl *getStdNamespace() const;
-  NamespaceDecl *getOrCreateStdNamespace();
+  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);
 
-  CXXRecordDecl *getStdBadAlloc() const;
-  EnumDecl *getStdAlignValT() const;
+  void DiagnoseSentinelCalls(const NamedDecl *D, SourceLocation Loc,
+                             ArrayRef Args);
 
-  ValueDecl *tryLookupUnambiguousFieldDecl(RecordDecl *ClassDecl,
-                                           const IdentifierInfo *MemberOrBase);
+  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();
 
-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;
+  void DiscardCleanupsInEvaluationContext();
 
-  ValueDecl *tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl,
-                                         CXXScopeSpec &SS,
-                                         ParsedType TemplateTypeTy,
-                                         IdentifierInfo *MemberOrBase);
+  ExprResult TransformToPotentiallyEvaluated(Expr *E);
+  TypeSourceInfo *TransformToPotentiallyEvaluated(TypeSourceInfo *TInfo);
+  ExprResult HandleExprEvaluationContextForTypeof(Expr *E);
 
-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,
-  };
+  void CheckUnusedVolatileAssignment(Expr *E);
 
-  /// Lookup the specified comparison category types in the standard
-  ///   library, an check the VarDecls possibly returned by the operator<=>
-  ///   builtins for that type.
-  ///
-  /// \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 ActOnConstantExpression(ExprResult Res);
 
-  /// 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);
+  // 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);
 
-  /// 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);
+  ExprResult CheckLValueToRValueConversionOperand(Expr *E);
+  void CleanupVarDeclMarking();
 
-  /// Determine whether Ctor is an initializer-list constructor, as
-  /// defined in [dcl.init.list]p2.
-  bool isInitListConstructor(const FunctionDecl *Ctor);
-
-  Decl *ActOnUsingDirective(Scope *CurScope, SourceLocation UsingLoc,
-                            SourceLocation NamespcLoc, CXXScopeSpec &SS,
-                            SourceLocation IdentLoc,
-                            IdentifierInfo *NamespcName,
-                            const ParsedAttributesView &AttrList);
-
-  void PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir);
-
-  Decl *ActOnNamespaceAliasDef(Scope *CurScope,
-                               SourceLocation NamespaceLoc,
-                               SourceLocation AliasLoc,
-                               IdentifierInfo *Alias,
-                               CXXScopeSpec &SS,
-                               SourceLocation IdentLoc,
-                               IdentifierInfo *Ident);
+  enum TryCaptureKind {
+    TryCapture_Implicit,
+    TryCapture_ExplicitByVal,
+    TryCapture_ExplicitByRef
+  };
 
-  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);
+  /// 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);
 
-  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);
+  /// Try to capture the given variable.
+  bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc,
+                          TryCaptureKind Kind = TryCapture_Implicit,
+                          SourceLocation EllipsisLoc = SourceLocation());
 
-  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);
+  /// Checks if the variable must be captured.
+  bool NeedToCaptureVariable(ValueDecl *Var, SourceLocation Loc);
 
-  bool CheckInheritingConstructorUsingDecl(UsingDecl *UD);
+  /// Given a variable, determine the type that a reference to that
+  /// variable will have in the given scope.
+  QualType getCapturedDeclRefType(ValueDecl *Var, SourceLocation Loc);
 
-  /// 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);
+  /// 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);
 
-  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);
+  /// Try to convert an expression \p E to type \p Ty. Returns the result of the
+  /// conversion.
+  ExprResult tryConvertExprToType(Expr *E, QualType Ty);
 
-  /// BuildCXXConstructExpr - Creates a complete call to a constructor,
-  /// including handling of its default argument expressions.
+  /// Conditionally issue a diagnostic based on the statements's reachability
+  /// analysis.
   ///
-  /// \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);
-
-  /// 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);
+  /// \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);
 
-  // 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);
+  /// 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);
 
-  ExprResult ConvertMemberDefaultInitExpression(FieldDecl *FD, Expr *InitExpr,
-                                                SourceLocation InitLoc);
+  // Primary Expressions.
+  SourceRange getExprRange(Expr *E) const;
 
-  ExprResult BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field);
+  ExprResult ActOnIdExpression(Scope *S, CXXScopeSpec &SS,
+                               SourceLocation TemplateKWLoc, UnqualifiedId &Id,
+                               bool HasTrailingLParen, bool IsAddressOfOperand,
+                               CorrectionCandidateCallback *CCC = nullptr,
+                               bool IsInlineAsmIdentifier = false,
+                               Token *KeywordReplacement = nullptr);
 
+  void DecomposeUnqualifiedId(const UnqualifiedId &Id,
+                              TemplateArgumentListInfo &Buffer,
+                              DeclarationNameInfo &NameInfo,
+                              const TemplateArgumentListInfo *&TemplateArgs);
 
-  /// 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 DiagnoseDependentMemberLookup(const LookupResult &R);
 
-  /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating
-  /// the default expr if needed.
-  ExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
-                                    ParmVarDecl *Param, Expr *Init = nullptr);
+  bool
+  DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R,
+                      CorrectionCandidateCallback &CCC,
+                      TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
+                      ArrayRef Args = std::nullopt,
+                      DeclContext *LookupCtx = nullptr,
+                      TypoExpr **Out = nullptr);
 
-  /// FinalizeVarWithDestructor - Prepare for calling destructor on the
-  /// constructed variable.
-  void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType);
+  DeclResult LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S,
+                                    IdentifierInfo *II);
+  ExprResult BuildIvarRefExpr(Scope *S, SourceLocation Loc, ObjCIvarDecl *IV);
 
-  /// 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 LookupInObjCMethod(LookupResult &LookUp, Scope *S,
+                                IdentifierInfo *II,
+                                bool AllowBuiltinCreation = false);
 
-    void ClearExceptions() {
-      ExceptionsSeen.clear();
-      Exceptions.clear();
-    }
+  /// 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);
 
-  public:
-    explicit ImplicitExceptionSpecification(Sema &Self)
-      : Self(&Self), ComputedEST(EST_BasicNoexcept) {
-      if (!Self.getLangOpts().CPlusPlus11)
-        ComputedEST = EST_DynamicNone;
-    }
+  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);
 
-    /// Get the computed exception specification type.
-    ExceptionSpecificationType getExceptionSpecType() const {
-      assert(!isComputedNoexcept(ComputedEST) &&
-             "noexcept(expr) should not be a possible result");
-      return ComputedEST;
-    }
+  bool UseArgumentDependentLookup(const CXXScopeSpec &SS, const LookupResult &R,
+                                  bool HasTrailingLParen);
 
-    /// The number of exceptions in the exception specification.
-    unsigned size() const { return Exceptions.size(); }
+  ExprResult
+  BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS,
+                                    const DeclarationNameInfo &NameInfo,
+                                    bool IsAddressOfOperand, const Scope *S,
+                                    TypeSourceInfo **RecoveryTSI = nullptr);
 
-    /// The set of exceptions in the exception specification.
-    const QualType *data() const { return Exceptions.data(); }
+  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);
 
-    /// Integrate another called method into the collected data.
-    void CalledDecl(SourceLocation CallLoc, const CXXMethodDecl *Method);
+  // 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);
 
-    /// Integrate an invoked expression into the collected data.
-    void CalledExpr(Expr *E) { CalledStmt(E); }
+  ExprResult BuildPredefinedExpr(SourceLocation Loc, PredefinedIdentKind IK);
+  ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind);
+  ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val);
 
-    /// Integrate an invoked statement into the collected data.
-    void CalledStmt(Stmt *S);
+  ExprResult BuildSYCLUniqueStableNameExpr(SourceLocation OpLoc,
+                                           SourceLocation LParen,
+                                           SourceLocation RParen,
+                                           TypeSourceInfo *TSI);
+  ExprResult ActOnSYCLUniqueStableNameExpr(SourceLocation OpLoc,
+                                           SourceLocation LParen,
+                                           SourceLocation RParen,
+                                           ParsedType ParsedTy);
 
-    /// 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 BuildSYCLUniqueStableIdExpr(SourceLocation OpLoc,
+                                         SourceLocation LParen,
+                                         SourceLocation RParen, Expr *E);
+  ExprResult ActOnSYCLUniqueStableIdExpr(SourceLocation OpLoc,
+                                         SourceLocation LParen,
+                                         SourceLocation RParen, Expr *E);
 
-  /// Evaluate the implicit exception specification for a defaulted
-  /// special member function.
-  void EvaluateImplicitExceptionSpec(SourceLocation Loc, FunctionDecl *FD);
+  bool CheckLoopHintExpr(Expr *E, SourceLocation Loc);
 
-  /// Check the given noexcept-specifier, convert its expression, and compute
-  /// the appropriate ExceptionSpecificationType.
-  ExprResult ActOnNoexceptSpec(Expr *NoexceptExpr,
-                               ExceptionSpecificationType &EST);
+  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);
 
-  /// 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);
+  /// ActOnStringLiteral - The specified tokens were lexed as pasted string
+  /// fragments (e.g. "foo" "bar" L"baz").
+  ExprResult ActOnStringLiteral(ArrayRef StringToks,
+                                Scope *UDLScope = nullptr);
 
-  /// 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);
+  ExprResult ActOnUnevaluatedStringLiteral(ArrayRef StringToks);
 
-  /// 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);
+  /// 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);
 
-  class InheritedConstructorInfo;
+  // 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);
 
-  /// 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);
+  bool isQualifiedMemberAccess(Expr *E);
+  bool CheckUseOfCXXMethodAsAddressOfOperand(SourceLocation OpLoc,
+                                             const Expr *Op,
+                                             const CXXMethodDecl *MD);
 
-  /// Produce notes explaining why a defaulted function was defined as deleted.
-  void DiagnoseDeletedDefaultedFunction(FunctionDecl *FD);
+  QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc);
 
-  /// 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);
+  bool ActOnAlignasTypeArgument(StringRef KWName, ParsedType Ty,
+                                SourceLocation OpLoc, SourceRange R);
+  bool CheckAlignasTypeArgument(StringRef KWName, TypeSourceInfo *TInfo,
+                                SourceLocation OpLoc, SourceRange R);
 
-  /// DefineImplicitDefaultConstructor - Checks for feasibility of
-  /// defining this constructor as the default constructor.
-  void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
-                                        CXXConstructorDecl *Constructor);
+  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);
 
-  /// 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);
+  ExprResult CheckPlaceholderExpr(Expr *E);
+  bool CheckVecStepExpr(Expr *E);
 
-  /// DefineImplicitDestructor - Checks for feasibility of
-  /// defining this destructor as the default destructor.
-  void DefineImplicitDestructor(SourceLocation CurrentLocation,
-                                CXXDestructorDecl *Destructor);
+  bool CheckUnaryExprOrTypeTraitOperand(Expr *E, UnaryExprOrTypeTrait ExprKind);
+  bool CheckUnaryExprOrTypeTraitOperand(QualType ExprType, SourceLocation OpLoc,
+                                        SourceRange ExprRange,
+                                        UnaryExprOrTypeTrait ExprKind,
+                                        StringRef KWName);
 
-  /// 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 ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc,
+                                 tok::TokenKind Kind, Expr *Input);
 
-  /// Define the specified inheriting constructor.
-  void DefineInheritingConstructor(SourceLocation UseLoc,
-                                   CXXConstructorDecl *Constructor);
+  ExprResult ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc,
+                                     MultiExprArg ArgExprs,
+                                     SourceLocation RLoc);
+  ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
+                                             Expr *Idx, SourceLocation RLoc);
 
-  /// 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 CreateBuiltinMatrixSubscriptExpr(Expr *Base, Expr *RowIdx,
+                                              Expr *ColumnIdx,
+                                              SourceLocation RBLoc);
 
-  /// DefineImplicitCopyConstructor - Checks for feasibility of
-  /// defining this constructor as the copy constructor.
-  void DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
-                                     CXXConstructorDecl *Constructor);
+  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);
 
-  /// 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);
+  /// Data structure for iterator expression.
+  struct OMPIteratorData {
+    IdentifierInfo *DeclIdent = nullptr;
+    SourceLocation DeclIdentLoc;
+    ParsedType Type;
+    OMPIteratorExpr::IteratorRange Range;
+    SourceLocation AssignLoc;
+    SourceLocation ColonLoc;
+    SourceLocation SecColonLoc;
+  };
 
-  /// DefineImplicitMoveConstructor - Checks for feasibility of
-  /// defining this constructor as the move constructor.
-  void DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
-                                     CXXConstructorDecl *Constructor);
+  ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc,
+                                  SourceLocation LLoc, SourceLocation RLoc,
+                                  ArrayRef Data);
 
-  /// 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);
+  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);
 
-  /// Defines an implicitly-declared copy assignment operator.
-  void DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
-                                    CXXMethodDecl *MethodDecl);
+  /// 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);
 
-  /// 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);
-
-  /// Defines an implicitly-declared move assignment operator.
-  void DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
-                                    CXXMethodDecl *MethodDecl);
-
-  /// Force the declaration of any implicitly-declared members of this
-  /// class.
-  void ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class);
+  using ADLCallKind = CallExpr::ADLCallKind;
 
-  /// Check a completed declaration of an implicit special member.
-  void CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD);
+  ExprResult
+  BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, SourceLocation LParenLoc,
+                        ArrayRef Arg, SourceLocation RParenLoc,
+                        Expr *Config = nullptr, bool IsExecConfig = false,
+                        ADLCallKind UsesADL = ADLCallKind::NotADL);
 
-  /// Determine whether the given function is an implicitly-deleted
-  /// special member function.
-  bool isImplicitlyDeleted(FunctionDecl *FD);
+  ExprResult ActOnCastExpr(Scope *S, SourceLocation LParenLoc, Declarator &D,
+                           ParsedType &Ty, SourceLocation RParenLoc,
+                           Expr *CastExpr);
 
-  /// 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);
+  CastKind PrepareScalarCast(ExprResult &src, QualType destType);
 
-  /// Whether this' shows up in the exception specification of a static
-  /// member function.
-  bool checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method);
+  /// Build an altivec or OpenCL literal.
+  ExprResult BuildVectorLiteral(SourceLocation LParenLoc,
+                                SourceLocation RParenLoc, Expr *E,
+                                TypeSourceInfo *TInfo);
 
-  /// Check whether 'this' shows up in the attributes of the given
-  /// static member function.
-  ///
-  /// \returns true if an error occurred.
-  bool checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method);
+  ExprResult MaybeConvertParenListExprToParenExpr(Scope *S, Expr *ME);
 
-  /// 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);
+  ExprResult ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty,
+                                  SourceLocation RParenLoc, Expr *InitExpr);
 
-  /// Wrap the expression in a ConstantExpr if it is a potential immediate
-  /// invocation.
-  ExprResult CheckForImmediateInvocation(ExprResult E, FunctionDecl *Decl);
+  ExprResult BuildCompoundLiteralExpr(SourceLocation LParenLoc,
+                                      TypeSourceInfo *TInfo,
+                                      SourceLocation RParenLoc,
+                                      Expr *LiteralExpr);
 
-  bool CheckImmediateEscalatingFunctionDefinition(
-      FunctionDecl *FD, const sema::FunctionScopeInfo *FSI);
+  ExprResult ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
+                           SourceLocation RBraceLoc);
 
-  void MarkExpressionAsImmediateEscalating(Expr *E);
+  ExprResult BuildInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
+                           SourceLocation RBraceLoc);
 
-  void DiagnoseImmediateEscalatingReason(FunctionDecl *FD);
+  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);
 
-  bool CompleteConstructorCall(CXXConstructorDecl *Constructor,
-                               QualType DeclInitType, MultiExprArg ArgsPtr,
-                               SourceLocation Loc,
-                               SmallVectorImpl &ConvertedArgs,
-                               bool AllowExplicit = false,
-                               bool IsListInitialization = false);
+  void DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc);
 
-  ParsedType getInheritingConstructorName(CXXScopeSpec &SS,
-                                          SourceLocation NameLoc,
-                                          IdentifierInfo &Name);
+  /// 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);
 
-  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);
+  /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
+  ExprResult ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
+                            LabelDecl *TheDecl);
 
-  ParsedType getDestructorTypeForDecltype(const DeclSpec &DS,
-                                          ParsedType ObjectType);
+  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();
 
-  // Checks that reinterpret casts don't have undefined behavior.
-  void CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType,
-                                      bool IsDereference, SourceRange Range);
+  // __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;
+  };
 
-  // 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_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);
 
-  // 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);
+  // __builtin_choose_expr(constExpr, expr1, expr2)
+  ExprResult ActOnChooseExpr(SourceLocation BuiltinLoc, Expr *CondExpr,
+                             Expr *LHSExpr, Expr *RHSExpr,
+                             SourceLocation RPLoc);
 
-  /// 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);
+  // __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);
 
-  ExprResult BuildCXXNamedCast(SourceLocation OpLoc,
-                               tok::TokenKind Kind,
-                               TypeSourceInfo *Ty,
-                               Expr *E,
-                               SourceRange AngleBrackets,
-                               SourceRange Parens);
+  // __builtin_LINE(), __builtin_FUNCTION(), __builtin_FUNCSIG(),
+  // __builtin_FILE(), __builtin_COLUMN(), __builtin_source_location()
+  ExprResult ActOnSourceLocExpr(SourceLocIdentKind Kind,
+                                SourceLocation BuiltinLoc,
+                                SourceLocation RPLoc);
 
-  ExprResult ActOnBuiltinBitCastExpr(SourceLocation KWLoc, Declarator &Dcl,
-                                     ExprResult Operand,
-                                     SourceLocation RParenLoc);
+  // Build a potentially resolved SourceLocExpr.
+  ExprResult BuildSourceLocExpr(SourceLocIdentKind Kind, QualType ResultTy,
+                                SourceLocation BuiltinLoc, SourceLocation RPLoc,
+                                DeclContext *ParentContext);
 
-  ExprResult BuildBuiltinBitCastExpr(SourceLocation KWLoc, TypeSourceInfo *TSI,
-                                     Expr *Operand, SourceLocation RParenLoc);
+  // __null
+  ExprResult ActOnGNUNullExpr(SourceLocation TokenLoc);
 
-  ExprResult BuildCXXTypeId(QualType TypeInfoType,
-                            SourceLocation TypeidLoc,
-                            TypeSourceInfo *Operand,
-                            SourceLocation RParenLoc);
-  ExprResult BuildCXXTypeId(QualType TypeInfoType,
-                            SourceLocation TypeidLoc,
-                            Expr *Operand,
-                            SourceLocation RParenLoc);
+  bool CheckCaseExpression(Expr *E);
 
-  /// ActOnCXXTypeid - Parse typeid( something ).
-  ExprResult ActOnCXXTypeid(SourceLocation OpLoc,
-                            SourceLocation LParenLoc, bool isType,
-                            void *TyOrExpr,
-                            SourceLocation RParenLoc);
+  //===------------------------- "Block" Extension ------------------------===//
 
-  ExprResult BuildCXXUuidof(QualType TypeInfoType,
-                            SourceLocation TypeidLoc,
-                            TypeSourceInfo *Operand,
-                            SourceLocation RParenLoc);
-  ExprResult BuildCXXUuidof(QualType TypeInfoType,
-                            SourceLocation TypeidLoc,
-                            Expr *Operand,
-                            SourceLocation RParenLoc);
+  /// ActOnBlockStart - This callback is invoked when a block literal is
+  /// started.
+  void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope);
 
-  /// ActOnCXXUuidof - Parse __uuidof( something ).
-  ExprResult ActOnCXXUuidof(SourceLocation OpLoc,
-                            SourceLocation LParenLoc, bool isType,
-                            void *TyOrExpr,
-                            SourceLocation RParenLoc);
+  /// 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);
 
-  /// 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);
+  /// 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);
 
-  //// ActOnCXXThis -  Parse 'this' pointer.
-  ExprResult ActOnCXXThis(SourceLocation loc);
+  /// 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);
 
-  /// Build a CXXThisExpr and mark it referenced in the current context.
-  Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit);
-  void MarkThisReferenced(CXXThisExpr *This);
+  //===---------------------------- Clang Extensions ----------------------===//
 
-  /// Try to retrieve the type of the 'this' pointer.
-  ///
-  /// \returns The type of 'this', if possible. Otherwise, returns a NULL type.
-  QualType getCurrentThisType();
+  /// __builtin_convertvector(...)
+  ExprResult ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy,
+                                    SourceLocation BuiltinLoc,
+                                    SourceLocation RParenLoc);
 
-  /// 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;
+  //===---------------------------- OpenCL Features -----------------------===//
 
-  /// 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;
+  /// __builtin_astype(...)
+  ExprResult ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy,
+                             SourceLocation BuiltinLoc,
+                             SourceLocation RParenLoc);
+  ExprResult BuildAsTypeExpr(Expr *E, QualType DestTy,
+                             SourceLocation BuiltinLoc,
+                             SourceLocation RParenLoc);
 
-  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);
+  /// Attempts to produce a RecoveryExpr after some AST node cannot be created.
+  ExprResult CreateRecoveryExpr(SourceLocation Begin, SourceLocation End,
+                                ArrayRef SubExprs,
+                                QualType T = QualType());
 
-    ~CXXThisScopeRAII();
+  // 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);
 
-  /// 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);
-
-  /// 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);
+  ExprResult PerformObjectMemberConversion(Expr *From,
+                                           NestedNameSpecifier *Qualifier,
+                                           NamedDecl *FoundDecl,
+                                           NamedDecl *Member);
 
-  /// ActOnCXXBoolLiteral - Parse {true,false} literals.
-  ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
+  /// 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);
 
+  /// Emit a warning for all pending noderef expressions that we recorded.
+  void WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec);
 
-  /// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals.
-  ExprResult ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
+  ExprResult BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field);
 
-  ExprResult
-  ActOnObjCAvailabilityCheckExpr(llvm::ArrayRef AvailSpecs,
-                                 SourceLocation AtLoc, SourceLocation RParen);
+  /// 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);
 
-  /// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
-  ExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc);
+  /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating
+  /// the default expr if needed.
+  ExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
+                                    ParmVarDecl *Param, Expr *Init = 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);
+  /// Wrap the expression in a ConstantExpr if it is a potential immediate
+  /// invocation.
+  ExprResult CheckForImmediateInvocation(ExprResult E, FunctionDecl *Decl);
 
-  /// 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);
+  void MarkExpressionAsImmediateEscalating(Expr *E);
 
-  ExprResult BuildCXXTypeConstructExpr(TypeSourceInfo *Type,
-                                       SourceLocation LParenLoc,
-                                       MultiExprArg Exprs,
-                                       SourceLocation RParenLoc,
-                                       bool ListInitialization);
+  bool IsInvalidSMECallConversion(QualType FromType, QualType ToType);
 
-  /// 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);
+  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;
+  }
 
-  /// Determine whether \p FD is an aligned allocation or deallocation
-  /// function that is unavailable.
-  bool isUnavailableAlignedAllocationFunction(const FunctionDecl &FD) const;
+  /// Abstract base class used for diagnosing integer constant
+  /// expression violations.
+  class VerifyICEDiagnoser {
+  public:
+    bool Suppress;
 
-  /// Produce diagnostics if \p FD is an aligned allocation or deallocation
-  /// function that is unavailable.
-  void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD,
-                                            SourceLocation Loc);
+    VerifyICEDiagnoser(bool Suppress = false) : Suppress(Suppress) {}
 
-  bool CheckAllocatedType(QualType AllocType, SourceLocation Loc,
-                          SourceRange R);
+    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() {}
+  };
 
-  /// 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
+  enum AllowFoldKind {
+    NoFold,
+    AllowFold,
   };
 
-  /// 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);
+  /// 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);
+  }
 
-  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);
+  /// DiagnoseAssignmentAsCondition - Given that an expression is
+  /// being used as a boolean condition, warn if it's an assignment.
+  void DiagnoseAssignmentAsCondition(Expr *E);
 
-  /// 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);
+  /// Redundant parentheses over an equality comparison can indicate
+  /// that the user intended an assignment used as condition.
+  void DiagnoseEqualityWithExtraParens(ParenExpr *ParenE);
 
-  ExprResult ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation LParen,
-                               Expr *Operand, SourceLocation RParen);
-  ExprResult BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
-                                  SourceLocation RParen);
+  class FullExprArg {
+  public:
+    FullExprArg() : E(nullptr) {}
+    FullExprArg(Sema &actions) : E(nullptr) {}
 
-  /// 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);
+    ExprResult release() { return E; }
 
-  /// ActOnArrayTypeTrait - Parsed one of the binary type trait support
-  /// pseudo-functions.
-  ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT,
-                                 SourceLocation KWLoc,
-                                 ParsedType LhsTy,
-                                 Expr *DimExpr,
-                                 SourceLocation RParen);
+    Expr *get() const { return E; }
 
-  ExprResult BuildArrayTypeTrait(ArrayTypeTrait ATT,
-                                 SourceLocation KWLoc,
-                                 TypeSourceInfo *TSInfo,
-                                 Expr *DimExpr,
-                                 SourceLocation RParen);
+    Expr *operator->() { return E; }
 
-  /// ActOnExpressionTrait - Parsed one of the unary type trait support
-  /// pseudo-functions.
-  ExprResult ActOnExpressionTrait(ExpressionTrait OET,
-                                  SourceLocation KWLoc,
-                                  Expr *Queried,
-                                  SourceLocation RParen);
+  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 BuildExpressionTrait(ExpressionTrait OET,
-                                  SourceLocation KWLoc,
-                                  Expr *Queried,
-                                  SourceLocation RParen);
+    explicit FullExprArg(Expr *expr) : E(expr) {}
 
-  ExprResult ActOnStartCXXMemberReference(Scope *S,
-                                          Expr *Base,
-                                          SourceLocation OpLoc,
-                                          tok::TokenKind OpKind,
-                                          ParsedType &ObjectType,
-                                          bool &MayBePseudoDestructor);
+    Expr *E;
+  };
 
-  ExprResult BuildPseudoDestructorExpr(Expr *Base,
-                                       SourceLocation OpLoc,
-                                       tok::TokenKind OpKind,
-                                       const CXXScopeSpec &SS,
-                                       TypeSourceInfo *ScopeType,
-                                       SourceLocation CCLoc,
-                                       SourceLocation TildeLoc,
-                                     PseudoDestructorTypeStorage DestroyedType);
+  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());
+  }
 
-  ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
-                                       SourceLocation OpLoc,
-                                       tok::TokenKind OpKind,
-                                       CXXScopeSpec &SS,
-                                       UnqualifiedId &FirstTypeName,
-                                       SourceLocation CCLoc,
-                                       SourceLocation TildeLoc,
-                                       UnqualifiedId &SecondTypeName);
+  class ConditionResult {
+    Decl *ConditionVar;
+    FullExprArg Condition;
+    bool Invalid;
+    std::optional KnownValue;
 
-  ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
-                                       SourceLocation OpLoc,
-                                       tok::TokenKind OpKind,
-                                       SourceLocation TildeLoc,
-                                       const DeclSpec& DS);
+    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) {}
 
-  /// 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);
+  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); }
 
-  MaterializeTemporaryExpr *
-  CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary,
-                                 bool BoundToLvalueReference);
+  /// 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);
 
-  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);
+  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.
+  };
 
-  // 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);
+  ConditionResult ActOnCondition(Scope *S, SourceLocation Loc, Expr *SubExpr,
+                                 ConditionKind CK, bool MissingOK = false);
 
-  DeclContext *computeDeclContext(QualType T);
-  DeclContext *computeDeclContext(const CXXScopeSpec &SS,
-                                  bool EnteringContext = false);
-  bool isDependentScopeSpecifier(const CXXScopeSpec &SS);
-  CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS);
+  QualType CheckConditionalOperands( // C99 6.5.15
+      ExprResult &Cond, ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK,
+      ExprObjectKind &OK, SourceLocation QuestionLoc);
 
-  /// 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);
+  QualType FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
+                                        SourceLocation QuestionLoc);
 
-  /// 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 DiagnoseConditionalForNull(const Expr *LHSExpr, const Expr *RHSExpr,
+                                  SourceLocation QuestionLoc);
 
-  bool isAcceptableNestedNameSpecifier(const NamedDecl *SD,
-                                       bool *CanCorrect = nullptr);
-  NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS);
+  /// 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);
 
-  /// 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;
+  /// 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,
+  };
 
-    /// The identifier preceding the '::'.
-    IdentifierInfo *Identifier;
+  // type checking for sizeless vector binary operators.
+  QualType CheckSizelessVectorOperands(ExprResult &LHS, ExprResult &RHS,
+                                       SourceLocation Loc, bool IsCompAssign,
+                                       ArithConvKind OperationKind);
 
-    /// The location of the identifier.
-    SourceLocation IdentifierLoc;
+  /// 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);
 
-    /// The location of the '::'.
-    SourceLocation CCLoc;
+  bool isValidSveBitcast(QualType srcType, QualType destType);
+  bool isValidRVVBitcast(QualType srcType, QualType destType);
 
-    /// 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) {
-    }
+  bool areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy);
 
-    NestedNameSpecInfo(IdentifierInfo *II, SourceLocation IdLoc,
-                       SourceLocation ColonColonLoc, QualType ObjectType)
-      : ObjectType(ParsedType::make(ObjectType)), Identifier(II),
-        IdentifierLoc(IdLoc), CCLoc(ColonColonLoc) {
-    }
-  };
+  bool areVectorTypesSameSize(QualType srcType, QualType destType);
+  bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType);
+  bool isLaxVectorConversion(QualType srcType, QualType destType);
+  bool anyAltivecTypes(QualType srcType, QualType destType);
 
-  bool BuildCXXNestedNameSpecifier(Scope *S,
-                                   NestedNameSpecInfo &IdInfo,
-                                   bool EnteringContext,
-                                   CXXScopeSpec &SS,
-                                   NamedDecl *ScopeLookupResult,
-                                   bool ErrorRecoveryLookup,
-                                   bool *IsCorrectedToColon = nullptr,
-                                   bool OnlyNamespace = false);
+  // type checking C++ declaration initializers (C++ [dcl.init]).
 
-  /// 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);
+  ExprResult checkUnknownAnyCast(SourceRange TypeRange, QualType CastType,
+                                 Expr *CastExpr, CastKind &CastKind,
+                                 ExprValueKind &VK, CXXCastPath &Path);
 
-  ExprResult ActOnDecltypeExpression(Expr *E);
+  /// Force an expression with unknown-type to an expression of the
+  /// given type.
+  ExprResult forceUnknownAnyToType(Expr *E, QualType ToType);
 
-  bool ActOnCXXNestedNameSpecifierDecltype(CXXScopeSpec &SS,
-                                           const DeclSpec &DS,
-                                           SourceLocation ColonColonLoc);
+  /// Type-check an expression that's being passed to an
+  /// __unknown_anytype parameter.
+  ExprResult checkUnknownAnyArg(SourceLocation callLoc, Expr *result,
+                                QualType ¶mType);
 
-  bool ActOnCXXNestedNameSpecifierIndexedPack(CXXScopeSpec &SS,
-                                              const DeclSpec &DS,
-                                              SourceLocation ColonColonLoc,
-                                              QualType Type);
+  // 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 IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS,
-                                 NestedNameSpecInfo &IdInfo,
-                                 bool EnteringContext);
+  // 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 IsInvalidSMECallConversion(QualType FromType, QualType ToType);
+  /// Prepare `SplattedExpr` for a vector splat operation, adding
+  /// implicit casts if necessary.
+  ExprResult prepareVectorSplat(QualType VectorTy, Expr *SplattedExpr);
 
-  /// 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);
+  // 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);
 
-  /// 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);
+  QualType PreferredConditionType(ConditionKind K) const {
+    return K == ConditionKind::Switch ? Context.IntTy : Context.BoolTy;
+  }
 
-  /// 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);
+  // 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);
 
-  bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
+  /// CallExprUnaryConversions - a special case of an unary conversion
+  /// performed on a function designator of a call expression.
+  ExprResult CallExprUnaryConversions(Expr *E);
 
-  /// 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);
+  // DefaultFunctionArrayConversion - converts functions and arrays
+  // to their respective pointers (C99 6.3.2.1).
+  ExprResult DefaultFunctionArrayConversion(Expr *E, bool Diagnose = true);
 
-  /// 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);
+  // DefaultFunctionArrayLvalueConversion - converts functions and
+  // arrays to their respective pointers and performs the
+  // lvalue-to-rvalue conversion.
+  ExprResult DefaultFunctionArrayLvalueConversion(Expr *E,
+                                                  bool Diagnose = true);
 
-  /// 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);
+  // 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);
 
-  /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
-  /// initializer for the declaration 'Dcl'.
-  void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl);
+  // 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);
 
-  /// Create a new lambda closure type.
-  CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange,
-                                         TypeSourceInfo *Info,
-                                         unsigned LambdaDependencyKind,
-                                         LambdaCaptureDefault CaptureDefault);
+  VariadicCallType getVariadicCallType(FunctionDecl *FDecl,
+                                       const FunctionProtoType *Proto,
+                                       Expr *Fn);
 
-  /// Number lambda for linkage purposes if necessary.
-  void handleLambdaNumbering(CXXRecordDecl *Class, CXXMethodDecl *Method,
-                             std::optional
-                                 NumberingOverride = std::nullopt);
+  // 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
+  };
 
-  /// 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);
+  // Determines which VarArgKind fits an expression.
+  VarArgKind isValidVarArgType(const QualType &Ty);
 
-  CXXMethodDecl *CreateLambdaCallOperator(SourceRange IntroducerRange,
-                                          CXXRecordDecl *Class);
+  /// 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);
 
-  void AddTemplateParametersToLambdaCallOperator(
-      CXXMethodDecl *CallOperator, CXXRecordDecl *Class,
-      TemplateParameterList *TemplateParams);
+  /// 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 CompleteLambdaCallOperator(
-      CXXMethodDecl *Method, SourceLocation LambdaLoc,
-      SourceLocation CallOperatorLoc, Expr *TrailingRequiresClause,
-      TypeSourceInfo *MethodTyInfo, ConstexprSpecKind ConstexprKind,
-      StorageClass SC, ArrayRef Params,
-      bool HasExplicitResultType);
+  // 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);
 
-  void DiagnoseInvalidExplicitObjectParameterInLambda(CXXMethodDecl *Method);
+  // 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);
 
-  /// 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);
+  /// 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,
 
-  /// 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);
+    /// PointerToInt - The assignment converts a pointer to an int, which we
+    /// accept as an extension.
+    PointerToInt,
 
-  /// Add an init-capture to a lambda scope.
-  void addInitCapture(sema::LambdaScopeInfo *LSI, VarDecl *Var, bool ByRef);
+    /// IntToPointer - The assignment converts an int to a pointer, which we
+    /// accept as an extension.
+    IntToPointer,
 
-  /// Note that we have finished the explicit captures for the
-  /// given lambda.
-  void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI);
+    /// FunctionVoidPointer - The assignment is between a function pointer and
+    /// void*, which the standard doesn't allow, but we accept as an extension.
+    FunctionVoidPointer,
 
-  /// Deduce a block or lambda's return type based on the return
-  /// statements present in the body.
-  void deduceClosureReturnType(sema::CapturingScopeInfo &CSI);
+    /// IncompatiblePointer - The assignment is between two pointers types that
+    /// are not compatible, but we accept them as an extension.
+    IncompatiblePointer,
 
-  /// 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);
+    /// IncompatibleFunctionPointer - The assignment is between two function
+    /// pointers types that are not compatible, but we accept them as an
+    /// extension.
+    IncompatibleFunctionPointer,
 
-  /// 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);
+    /// 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,
 
-  void ActOnLambdaClosureQualifiers(LambdaIntroducer &Intro,
-                                    SourceLocation MutableLoc);
+    /// 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,
 
-  void ActOnLambdaClosureParameters(
-      Scope *LambdaScope,
-      MutableArrayRef ParamInfo);
+    /// CompatiblePointerDiscardsQualifiers - The assignment discards
+    /// c/v/r qualifiers, which we accept as an extension.
+    CompatiblePointerDiscardsQualifiers,
 
-  /// 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);
+    /// IncompatiblePointerDiscardsQualifiers - The assignment
+    /// discards qualifiers that we don't permit to be discarded,
+    /// like address spaces.
+    IncompatiblePointerDiscardsQualifiers,
 
-  /// 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);
+    /// 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,
 
-  /// ActOnLambdaExpr - This is called when the body of a lambda expression
-  /// was successfully completed.
-  ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body);
+    /// 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,
 
-  /// Does copying/destroying the captured variable have side effects?
-  bool CaptureHasSideEffects(const sema::Capture &From);
+    /// IncompatibleVectors - The assignment is between two vector types that
+    /// have the same size, which we accept as an extension.
+    IncompatibleVectors,
 
-  /// Diagnose if an explicit lambda capture is unused. Returns true if a
-  /// diagnostic is emitted.
-  bool DiagnoseUnusedLambdaCapture(SourceRange CaptureRange,
-                                   const sema::Capture &From);
+    /// IntToBlockPointer - The assignment converts an int to a block
+    /// pointer. We disallow this.
+    IntToBlockPointer,
 
-  /// Build a FieldDecl suitable to hold the given capture.
-  FieldDecl *BuildCaptureField(RecordDecl *RD, const sema::Capture &Capture);
+    /// IncompatibleBlockPointer - The assignment is between two block
+    /// pointers types that are not compatible.
+    IncompatibleBlockPointer,
 
-  /// Initialize the given capture with a suitable expression.
-  ExprResult BuildCaptureInit(const sema::Capture &Capture,
-                              SourceLocation ImplicitCaptureLoc,
-                              bool IsOpenMPMapping = false);
+    /// 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,
 
-  /// Complete a lambda-expression having processed and attached the
-  /// lambda body.
-  ExprResult BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
-                             sema::LambdaScopeInfo *LSI);
+    /// IncompatibleObjCWeakRef - Assigning a weak-unavailable object to an
+    /// object with __weak qualifier.
+    IncompatibleObjCWeakRef,
 
-  /// 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);
-
-  /// 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);
+    /// Incompatible - We reject this conversion outright, it is invalid to
+    /// represent it in the AST.
+    Incompatible
+  };
 
-  /// 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);
+  /// 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);
 
-  ExprResult BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
-                                           SourceLocation ConvLocation,
-                                           CXXConversionDecl *Conv,
-                                           Expr *Src);
+  /// 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);
 
-  sema::LambdaScopeInfo *RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator);
+  /// 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);
 
-  class LambdaScopeForCallOperatorInstantiationRAII
-      : private FunctionScopeRAII {
-  public:
-    LambdaScopeForCallOperatorInstantiationRAII(
-        Sema &SemasRef, FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL,
-        LocalInstantiationScope &Scope,
-        bool ShouldAddDeclsFromParentScope = true);
-  };
+  /// 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);
 
-  /// 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);
+  // 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);
 
-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;
+  /// the following "Check" methods will return a valid/converted QualType
+  /// or a null QualType (indicating an error diagnostic was issued).
 
-  llvm::ContextualFoldingSet
-      SatisfactionCache;
+  /// type checking binary operators (subroutines of CreateBuiltinBinOp).
+  QualType InvalidOperands(SourceLocation Loc, ExprResult &LHS,
+                           ExprResult &RHS);
+  QualType InvalidLogicalVectorOperands(SourceLocation Loc, ExprResult &LHS,
+                                        ExprResult &RHS);
 
-  /// 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);
+  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);
 
-  /// Introduce the instantiated captures of the lambda into the local
-  /// instantiation scope.
-  bool addInstantiatedCapturesToScope(
-      FunctionDecl *Function, const FunctionDecl *PatternDecl,
-      LocalInstantiationScope &Scope,
-      const MultiLevelTemplateArgumentList &TemplateArgs);
+  bool CheckConversionToObjCLiteral(QualType DstType, Expr *&SrcExpr,
+                                    bool Diagnose = true);
 
-  /// 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);
+  /// 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;
+  }
 
-  /// 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);
+  /// 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;
 
-private:
-  // The current stack of constraint satisfactions, so we can exit-early.
-  using SatisfactionStackEntryTy =
-      std::pair;
-  llvm::SmallVector
-      SatisfactionStack;
+  bool isAlwaysConstantEvaluatedContext() const {
+    const ExpressionEvaluationContextRecord &Ctx = currentEvaluationContext();
+    return (Ctx.isConstantEvaluated() || isConstantEvaluatedOverride) &&
+           !Ctx.InConditionallyConstantEvaluateContext;
+  }
 
-public:
-  void PushSatisfactionStackEntry(const NamedDecl *D,
-                                  const llvm::FoldingSetNodeID &ID) {
-    const NamedDecl *Can = cast(D->getCanonicalDecl());
-    SatisfactionStack.emplace_back(Can, ID);
+  /// Determines whether we are currently in a context that
+  /// is not evaluated as per C++ [expr] p5.
+  bool isUnevaluatedContext() const {
+    return currentEvaluationContext().isUnevaluated();
   }
 
-  void PopSatisfactionStackEntry() { SatisfactionStack.pop_back(); }
+  bool isImmediateFunctionContext() const {
+    return currentEvaluationContext().isImmediateFunctionContext();
+  }
 
-  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();
+  bool isInLifetimeExtendingContext() const {
+    assert(!ExprEvalContexts.empty() &&
+           "Must be in an expression evaluation context");
+    return ExprEvalContexts.back().InLifetimeExtendingContext;
   }
 
-  // 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;
+  bool isCheckingDefaultArgumentOrInitializer() const {
+    const ExpressionEvaluationContextRecord &Ctx = currentEvaluationContext();
+    return (Ctx.Context ==
+            ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed) ||
+           Ctx.IsCurrentlyCheckingDefaultArgumentOrInitializer;
+  }
 
-  public:
-    SatisfactionStackResetRAII(Sema &S) : SemaRef(S) {
-      SemaRef.SwapSatisfactionStack(BackupSatisfactionStack);
+  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;
+  }
 
-    ~SatisfactionStackResetRAII() {
-      SemaRef.SwapSatisfactionStack(BackupSatisfactionStack);
+  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;
     }
-  };
-
-  void SwapSatisfactionStack(
-      llvm::SmallVectorImpl &NewSS) {
-    SatisfactionStack.swap(NewSS);
+    return Res;
   }
 
-  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);
+  /// 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;
+    }
+  }
 
-  /// 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);
+  /// 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;
+    }
+  }
 
-  /// \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);
+  DefaultedComparisonKind getDefaultedComparisonKind(const FunctionDecl *FD) {
+    return getDefaultedFunctionKind(FD).asComparison();
   }
 
-  /// \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);
+  /// 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);
 
-  /// \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);
+  void MaybeSuggestAddingStaticToDecl(const FunctionDecl *D);
 
-  /// 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);
+  template 
+  bool RequireCompleteSizedType(SourceLocation Loc, QualType T, unsigned DiagID,
+                                const Ts &...Args) {
+    SizelessTypeDiagnoser Diagnoser(DiagID, Args...);
+    return RequireCompleteType(Loc, T, CompleteTypeKind::Normal, Diagnoser);
+  }
 
-  /// \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);
+  template 
+  bool RequireCompleteSizedExprType(Expr *E, unsigned DiagID,
+                                    const Ts &...Args) {
+    SizelessTypeDiagnoser Diagnoser(DiagID, Args...);
+    return RequireCompleteExprType(E, CompleteTypeKind::Normal, Diagnoser);
+  }
 
-  /// \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);
+  /// Abstract class used to diagnose incomplete types.
+  struct TypeDiagnoser {
+    TypeDiagnoser() {}
 
-  /// \brief Emit diagnostics explaining why a constraint expression was deemed
-  /// unsatisfied.
-  void
-  DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction &Satisfaction,
-                                bool First = true);
+    virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) = 0;
+    virtual ~TypeDiagnoser() {}
+  };
 
-  // ParseObjCStringLiteral - Parse Objective-C string literals.
-  ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
-                                    ArrayRef Strings);
+  template  class BoundTypeDiagnoser : public TypeDiagnoser {
+  protected:
+    unsigned DiagID;
+    std::tuple Args;
 
-  ExprResult BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S);
+    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;
+    }
 
-  /// 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);
+  public:
+    BoundTypeDiagnoser(unsigned DiagID, const Ts &...Args)
+        : TypeDiagnoser(), DiagID(DiagID), Args(Args...) {
+      assert(DiagID != 0 && "no diagnostic for type diagnoser");
+    }
 
-  /// 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);
+    void diagnose(Sema &S, SourceLocation Loc, QualType T) override {
+      const SemaDiagnosticBuilder &DB = S.Diag(Loc, DiagID);
+      emit(DB, std::index_sequence_for());
+      DB << T;
+    }
+  };
 
-  ExprResult BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
-                                          Expr *IndexExpr,
-                                          ObjCMethodDecl *getterMethod,
-                                          ObjCMethodDecl *setterMethod);
+  /// 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...) {}
 
-  ExprResult BuildObjCDictionaryLiteral(SourceRange SR,
-                               MutableArrayRef Elements);
+    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;
+    }
+  };
 
-  ExprResult BuildObjCEncodeExpression(SourceLocation AtLoc,
-                                  TypeSourceInfo *EncodedTypeInfo,
-                                  SourceLocation RParenLoc);
-  ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl,
-                                    CXXConversionDecl *Method,
-                                    bool HadMultipleCandidates);
+  /// Check an argument list for placeholders that we won't try to
+  /// handle later.
+  bool CheckArgsForPlaceholders(MultiExprArg args);
 
-  ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc,
-                                       SourceLocation EncodeLoc,
-                                       SourceLocation LParenLoc,
-                                       ParsedType Ty,
-                                       SourceLocation RParenLoc);
+  /// The C++ "std::source_location::__impl" struct, defined in
+  /// \.
+  RecordDecl *StdSourceLocationImplDecl;
 
-  /// ParseObjCSelectorExpression - Build selector expression for \@selector
-  ExprResult ParseObjCSelectorExpression(Selector Sel,
-                                         SourceLocation AtLoc,
-                                         SourceLocation SelLoc,
-                                         SourceLocation LParenLoc,
-                                         SourceLocation RParenLoc,
-                                         bool WarnMultipleSelectors);
+  /// A stack of expression evaluation contexts.
+  SmallVector ExprEvalContexts;
 
-  /// ParseObjCProtocolExpression - Build protocol expression for \@protocol
-  ExprResult ParseObjCProtocolExpression(IdentifierInfo * ProtocolName,
-                                         SourceLocation AtLoc,
-                                         SourceLocation ProtoLoc,
-                                         SourceLocation LParenLoc,
-                                         SourceLocation ProtoIdLoc,
-                                         SourceLocation RParenLoc);
+  // Set of failed immediate invocations to avoid double diagnosing.
+  llvm::SmallPtrSet FailedImmediateInvocations;
 
-  //===--------------------------------------------------------------------===//
-  // C++ Declarations
-  //
-  Decl *ActOnStartLinkageSpecification(Scope *S,
-                                       SourceLocation ExternLoc,
-                                       Expr *LangStr,
-                                       SourceLocation LBraceLoc);
-  Decl *ActOnFinishLinkageSpecification(Scope *S,
-                                        Decl *LinkageSpec,
-                                        SourceLocation RBraceLoc);
+  /// List of SourceLocations where 'self' is implicitly retained inside a
+  /// block.
+  llvm::SmallVector, 1>
+      ImplicitlyRetainedSelfLocs;
 
+private:
+  static BinaryOperatorKind ConvertTokenKindToBinaryOpcode(tok::TokenKind Kind);
 
-  //===--------------------------------------------------------------------===//
-  // 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);
+  /// 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);
 
-  bool ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc,
-                            SourceLocation ColonLoc,
-                            const ParsedAttributesView &Attrs);
+  ///@}
 
-  NamedDecl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS,
-                                 Declarator &D,
-                                 MultiTemplateParamsArg TemplateParameterLists,
-                                 Expr *BitfieldWidth, const VirtSpecifiers &VS,
-                                 InClassInitStyle InitStyle);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  void ActOnStartCXXInClassMemberInitializer();
-  void ActOnFinishCXXInClassMemberInitializer(Decl *VarDecl,
-                                              SourceLocation EqualLoc,
-                                              Expr *Init);
+  /// \name C++ Expressions
+  /// Implementations are in SemaExprCXX.cpp
+  ///@{
 
-  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:
+  /// The C++ "std::bad_alloc" class, which is defined by the C++
+  /// standard library.
+  LazyDeclPtr StdBadAlloc;
 
-  MemInitResult ActOnMemInitializer(Decl *ConstructorD,
-                                    Scope *S,
-                                    CXXScopeSpec &SS,
-                                    IdentifierInfo *MemberOrBase,
-                                    ParsedType TemplateTypeTy,
-                                    const DeclSpec &DS,
-                                    SourceLocation IdLoc,
-                                    Expr *InitList,
-                                    SourceLocation EllipsisLoc);
+  /// The C++ "std::align_val_t" enum class, which is defined by the C++
+  /// standard library.
+  LazyDeclPtr StdAlignValT;
 
-  MemInitResult BuildMemInitializer(Decl *ConstructorD,
-                                    Scope *S,
-                                    CXXScopeSpec &SS,
-                                    IdentifierInfo *MemberOrBase,
-                                    ParsedType TemplateTypeTy,
-                                    const DeclSpec &DS,
-                                    SourceLocation IdLoc,
-                                    Expr *Init,
-                                    SourceLocation EllipsisLoc);
+  /// The C++ "type_info" declaration, which is defined in \.
+  RecordDecl *CXXTypeInfoDecl;
 
-  MemInitResult BuildMemberInitializer(ValueDecl *Member,
-                                       Expr *Init,
-                                       SourceLocation IdLoc);
+  /// A flag to remember whether the implicit forms of operator new and delete
+  /// have been declared.
+  bool GlobalNewDeleteDeclared;
 
-  MemInitResult BuildBaseInitializer(QualType BaseType,
-                                     TypeSourceInfo *BaseTInfo,
-                                     Expr *Init,
-                                     CXXRecordDecl *ClassDecl,
-                                     SourceLocation EllipsisLoc);
+  /// 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;
 
-  MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo,
-                                           Expr *Init,
-                                           CXXRecordDecl *ClassDecl);
+  bool isInMaterializeTemporaryObjectContext() const {
+    assert(!ExprEvalContexts.empty() &&
+           "Must be in an expression evaluation context");
+    return ExprEvalContexts.back().InMaterializeTemporaryObjectContext;
+  }
 
-  bool SetDelegatingInitializer(CXXConstructorDecl *Constructor,
-                                CXXCtorInitializer *Initializer);
+  ParsedType getInheritingConstructorName(CXXScopeSpec &SS,
+                                          SourceLocation NameLoc,
+                                          IdentifierInfo &Name);
 
-  bool SetCtorInitializers(
-      CXXConstructorDecl *Constructor, bool AnyErrors,
-      ArrayRef Initializers = std::nullopt);
+  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);
 
-  void SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation);
+  ParsedType getDestructorTypeForDecltype(const DeclSpec &DS,
+                                          ParsedType ObjectType);
 
+  ExprResult BuildCXXTypeId(QualType TypeInfoType, SourceLocation TypeidLoc,
+                            TypeSourceInfo *Operand, SourceLocation RParenLoc);
+  ExprResult BuildCXXTypeId(QualType TypeInfoType, SourceLocation TypeidLoc,
+                            Expr *Operand, SourceLocation RParenLoc);
 
-  /// MarkBaseAndMemberDestructorsReferenced - Given a record decl,
-  /// mark all the non-trivial destructors of its members and bases as
-  /// referenced.
-  void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc,
-                                              CXXRecordDecl *Record);
+  /// ActOnCXXTypeid - Parse typeid( something ).
+  ExprResult ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
+                            bool isType, void *TyOrExpr,
+                            SourceLocation RParenLoc);
 
-  /// 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);
+  ExprResult BuildCXXUuidof(QualType TypeInfoType, SourceLocation TypeidLoc,
+                            TypeSourceInfo *Operand, SourceLocation RParenLoc);
+  ExprResult BuildCXXUuidof(QualType TypeInfoType, SourceLocation TypeidLoc,
+                            Expr *Operand, SourceLocation RParenLoc);
 
-  /// 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);
+  /// ActOnCXXUuidof - Parse __uuidof( something ).
+  ExprResult ActOnCXXUuidof(SourceLocation OpLoc, SourceLocation LParenLoc,
+                            bool isType, void *TyOrExpr,
+                            SourceLocation RParenLoc);
 
-  /// 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;
+  //// ActOnCXXThis -  Parse 'this' pointer.
+  ExprResult ActOnCXXThis(SourceLocation loc);
 
-  /// The list of vtables that are required but have not yet been
-  /// materialized.
-  SmallVector VTableUses;
+  /// Build a CXXThisExpr and mark it referenced in the current context.
+  Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit);
+  void MarkThisReferenced(CXXThisExpr *This);
 
-  /// 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;
+  /// Try to retrieve the type of the 'this' pointer.
+  ///
+  /// \returns The type of 'this', if possible. Otherwise, returns a NULL type.
+  QualType getCurrentThisType();
 
-  /// Load any externally-stored vtable uses.
-  void LoadExternalVTableUses();
+  /// 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;
 
-  /// Note that the vtable for the given class was used at the
-  /// given location.
-  void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
-                      bool DefinitionRequired = false);
+  /// 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;
 
-  /// Mark the exception specifications of all virtual member functions
-  /// in the given class as needed.
-  void MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc,
-                                             const CXXRecordDecl *RD);
+  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);
 
-  /// MarkVirtualMembersReferenced - Will mark all members of the given
-  /// CXXRecordDecl referenced.
-  void MarkVirtualMembersReferenced(SourceLocation Loc, const CXXRecordDecl *RD,
-                                    bool ConstexprOnly = false);
+    ~CXXThisScopeRAII();
+  };
 
-  /// Define all of the vtables that have been used in this
-  /// translation unit and reference any virtual members used by those
-  /// vtables.
+  /// Make sure the value of 'this' is actually available in the current
+  /// context, if it is a potentially evaluated context.
   ///
-  /// \returns true if any work was done, false otherwise.
-  bool DefineUsedVTables();
+  /// \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);
 
-  void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl);
+  /// 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);
 
-  void ActOnMemInitializers(Decl *ConstructorDecl,
-                            SourceLocation ColonLoc,
-                            ArrayRef MemInits,
-                            bool AnyErrors);
+  /// ActOnCXXBoolLiteral - Parse {true,false} literals.
+  ExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
 
-  /// 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);
+  /// ActOnObjCBoolLiteral - Parse {__objc_yes,__objc_no} literals.
+  ExprResult ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind);
 
-  void referenceDLLExportedClassMethods();
+  ExprResult
+  ActOnObjCAvailabilityCheckExpr(llvm::ArrayRef AvailSpecs,
+                                 SourceLocation AtLoc, SourceLocation RParen);
 
-  void propagateDLLAttrToBaseClassTemplate(
-      CXXRecordDecl *Class, Attr *ClassAttr,
-      ClassTemplateSpecializationDecl *BaseTemplateSpec,
-      SourceLocation BaseLoc);
+  /// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
+  ExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc);
 
-  /// 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);
+  //// 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);
 
-  /// Add [[gsl::Owner]] and [[gsl::Pointer]] attributes for std:: types.
-  void inferGslOwnerPointerAttribute(CXXRecordDecl *Record);
+  /// 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);
 
-  /// Add [[gsl::Pointer]] attributes for std:: types.
-  void inferGslPointerAttribute(TypedefNameDecl *TD);
+  ExprResult BuildCXXTypeConstructExpr(TypeSourceInfo *Type,
+                                       SourceLocation LParenLoc,
+                                       MultiExprArg Exprs,
+                                       SourceLocation RParenLoc,
+                                       bool ListInitialization);
 
-  void CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record);
+  /// 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);
 
-  /// 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);
+  /// Determine whether \p FD is an aligned allocation or deallocation
+  /// function that is unavailable.
+  bool isUnavailableAlignedAllocationFunction(const FunctionDecl &FD) const;
 
-  void ActOnFinishCXXMemberSpecification(Scope *S, SourceLocation RLoc,
-                                         Decl *TagDecl, SourceLocation LBrac,
-                                         SourceLocation RBrac,
-                                         const ParsedAttributesView &AttrList);
-  void ActOnFinishCXXMemberDecls();
-  void ActOnFinishCXXNonNestedClass();
+  /// Produce diagnostics if \p FD is an aligned allocation or deallocation
+  /// function that is unavailable.
+  void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD,
+                                            SourceLocation Loc);
 
-  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();
+  bool CheckAllocatedType(QualType AllocType, SourceLocation Loc,
+                          SourceRange R);
 
-  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);
+  /// 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
+  };
 
-  Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
-                            MultiTemplateParamsArg TemplateParams);
-  NamedDecl *ActOnFriendFunctionDecl(Scope *S, Declarator &D,
-                                     MultiTemplateParamsArg TemplateParams);
+  /// 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);
 
-  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 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 CheckExplicitlyDefaultedFunction(Scope *S, FunctionDecl *MD);
+  /// 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);
 
-  bool CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD,
-                                             CXXSpecialMember CSM,
-                                             SourceLocation DefaultLoc);
-  void CheckDelayedMemberExceptionSpecs();
+  ExprResult ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation LParen,
+                               Expr *Operand, SourceLocation RParen);
+  ExprResult BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
+                                  SourceLocation RParen);
 
-  bool CheckExplicitlyDefaultedComparison(Scope *S, FunctionDecl *MD,
-                                          DefaultedComparisonKind DCK);
-  void DeclareImplicitEqualityComparison(CXXRecordDecl *RD,
-                                         FunctionDecl *Spaceship);
-  void DefineDefaultedComparison(SourceLocation Loc, FunctionDecl *FD,
-                                 DefaultedComparisonKind DCK);
+  ExprResult ActOnStartCXXMemberReference(Scope *S, Expr *Base,
+                                          SourceLocation OpLoc,
+                                          tok::TokenKind OpKind,
+                                          ParsedType &ObjectType,
+                                          bool &MayBePseudoDestructor);
 
-  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);
+  ExprResult BuildPseudoDestructorExpr(
+      Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind,
+      const CXXScopeSpec &SS, TypeSourceInfo *ScopeType, SourceLocation CCLoc,
+      SourceLocation TildeLoc, PseudoDestructorTypeStorage DestroyedType);
 
-  //===--------------------------------------------------------------------===//
-  // C++ Derived Classes
-  //
+  ExprResult ActOnPseudoDestructorExpr(
+      Scope *S, Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind,
+      CXXScopeSpec &SS, UnqualifiedId &FirstTypeName, SourceLocation CCLoc,
+      SourceLocation TildeLoc, UnqualifiedId &SecondTypeName);
 
-  /// ActOnBaseSpecifier - Parsed a base specifier
-  CXXBaseSpecifier *CheckBaseSpecifier(CXXRecordDecl *Class,
-                                       SourceRange SpecifierRange,
-                                       bool Virtual, AccessSpecifier Access,
-                                       TypeSourceInfo *TInfo,
-                                       SourceLocation EllipsisLoc);
+  ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base,
+                                       SourceLocation OpLoc,
+                                       tok::TokenKind OpKind,
+                                       SourceLocation TildeLoc,
+                                       const DeclSpec &DS);
 
-  BaseResult ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
-                                const ParsedAttributesView &Attrs, bool Virtual,
-                                AccessSpecifier Access, ParsedType basetype,
-                                SourceLocation BaseLoc,
-                                SourceLocation EllipsisLoc);
+  /// 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);
 
-  bool AttachBaseSpecifiers(CXXRecordDecl *Class,
-                            MutableArrayRef Bases);
-  void ActOnBaseSpecifiers(Decl *ClassDecl,
-                           MutableArrayRef Bases);
+  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);
 
-  bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base);
-  bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base,
-                     CXXBasePaths &Paths);
+  ExprResult ActOnDecltypeExpression(Expr *E);
 
-  // FIXME: I don't like this name.
-  void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath);
+  bool checkLiteralOperatorId(const CXXScopeSpec &SS, const UnqualifiedId &Id,
+                              bool IsUDSuffix);
 
-  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);
+  bool isUsualDeallocationFunction(const CXXMethodDecl *FD);
 
-  std::string getAmbiguousPathsDisplayString(CXXBasePaths &Paths);
+  ConditionResult ActOnConditionVariable(Decl *ConditionVar,
+                                         SourceLocation StmtLoc,
+                                         ConditionKind CK);
 
-  bool CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
-                                         const CXXMethodDecl *Old);
+  ExprResult CheckConditionVariable(VarDecl *ConditionVar,
+                                    SourceLocation StmtLoc, ConditionKind CK);
 
-  /// CheckOverridingFunctionReturnType - Checks whether the return types are
-  /// covariant, according to C++ [class.virtual]p5.
-  bool CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
-                                         const CXXMethodDecl *Old);
+  /// CheckCXXBooleanCondition - Returns true if conversion to bool is invalid.
+  ExprResult CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr = false);
 
-  // Check that the overriding method has no explicit object parameter.
-  bool CheckExplicitObjectOverride(CXXMethodDecl *New,
-                                   const CXXMethodDecl *Old);
+  bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType);
 
-  /// CheckOverridingFunctionExceptionSpec - Checks whether the exception
-  /// spec is a subset of base spec.
-  bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
-                                            const CXXMethodDecl *Old);
+  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 CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange);
+  bool CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N);
 
-  /// CheckOverrideControl - Check C++11 override control semantics.
-  void CheckOverrideControl(NamedDecl *D);
+  /// 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);
 
-  /// DiagnoseAbsenceOfOverrideControl - Diagnose if 'override' keyword was
-  /// not used in the declaration of an overriding method.
-  void DiagnoseAbsenceOfOverrideControl(NamedDecl *D, bool Inconsistent);
+  /// ActOnArrayTypeTrait - Parsed one of the binary type trait support
+  /// pseudo-functions.
+  ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT, SourceLocation KWLoc,
+                                 ParsedType LhsTy, Expr *DimExpr,
+                                 SourceLocation RParen);
 
-  /// 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);
+  ExprResult BuildArrayTypeTrait(ArrayTypeTrait ATT, SourceLocation KWLoc,
+                                 TypeSourceInfo *TSInfo, Expr *DimExpr,
+                                 SourceLocation RParen);
 
+  /// ActOnExpressionTrait - Parsed one of the unary type trait support
+  /// pseudo-functions.
+  ExprResult ActOnExpressionTrait(ExpressionTrait OET, SourceLocation KWLoc,
+                                  Expr *Queried, SourceLocation RParen);
 
-  //===--------------------------------------------------------------------===//
-  // C++ Access Control
-  //
+  ExprResult BuildExpressionTrait(ExpressionTrait OET, SourceLocation KWLoc,
+                                  Expr *Queried, SourceLocation RParen);
 
-  enum AccessResult {
-    AR_accessible,
-    AR_inaccessible,
-    AR_dependent,
-    AR_delayed
-  };
+  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 SetMemberAccessSpecifier(NamedDecl *MemberDecl,
-                                NamedDecl *PrevMemberDecl,
-                                AccessSpecifier LexicalAS);
+  QualType CheckSizelessVectorConditionalTypes(ExprResult &Cond,
+                                               ExprResult &LHS, ExprResult &RHS,
+                                               SourceLocation QuestionLoc);
 
-  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());
+  QualType CXXCheckConditionalOperands( // C++ 5.16
+      ExprResult &cond, ExprResult &lhs, ExprResult &rhs, ExprValueKind &VK,
+      ExprObjectKind &OK, 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;
   }
 
-  void HandleDependentAccessCheck(const DependentDiagnostic &DD,
-                         const MultiLevelTemplateArgumentList &TemplateArgs);
-  void PerformDependentDiagnostics(const DeclContext *Pattern,
-                        const MultiLevelTemplateArgumentList &TemplateArgs);
+  /// 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);
 
-  void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx);
+  /// IgnoredValueConversions - Given that an expression's result is
+  /// syntactically ignored, perform any conversions that are
+  /// required.
+  ExprResult IgnoredValueConversions(Expr *E);
 
-  /// When true, access checking violations are treated as SFINAE
-  /// failures rather than hard errors.
-  bool AccessCheckingSFINAE;
+  ExprResult CheckUnevaluatedOperand(Expr *E);
 
-  enum AbstractDiagSelID {
-    AbstractNone = -1,
-    AbstractReturnType,
-    AbstractParamType,
-    AbstractVariableType,
-    AbstractFieldType,
-    AbstractIvarType,
-    AbstractSynthesizedIvarType,
-    AbstractArrayType
-  };
+  /// 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; });
 
-  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 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);
   }
 
-  void DiagnoseAbstractType(const CXXRecordDecl *RD);
-
-  //===--------------------------------------------------------------------===//
-  // C++ Overloaded Operators [C++ 13.5]
-  //
-
-  bool CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl);
-
-  bool CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl);
-
-  //===--------------------------------------------------------------------===//
-  // 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);
+  /// Describes the result of an "if-exists" condition check.
+  enum IfExistsResult {
+    /// The symbol exists.
+    IER_Exists,
 
-  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) {}
+    /// The symbol does not exist.
+    IER_DoesNotExist,
 
-    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(); }
+    /// The name is a dependent name, so the results will differ
+    /// from one instantiation to the next.
+    IER_Dependent,
 
-  private:
-    std::optional TemplateKW;
+    /// An error occurred.
+    IER_Error
   };
 
-  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);
+  IfExistsResult
+  CheckMicrosoftIfExistsSymbol(Scope *S, CXXScopeSpec &SS,
+                               const DeclarationNameInfo &TargetNameInfo);
 
-  TemplateNameKind isTemplateName(Scope *S,
-                                  CXXScopeSpec &SS,
-                                  bool hasTemplateKeyword,
-                                  const UnqualifiedId &Name,
-                                  ParsedType ObjectType,
-                                  bool EnteringContext,
-                                  TemplateTy &Template,
-                                  bool &MemberOfUnknownSpecialization,
-                                  bool Disambiguation = false);
+  IfExistsResult CheckMicrosoftIfExistsSymbol(Scope *S,
+                                              SourceLocation KeywordLoc,
+                                              bool IsIfExists, CXXScopeSpec &SS,
+                                              UnqualifiedId &Name);
 
-  /// 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);
+  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 resolveAssumedTemplateNameAsType(Scope *S, TemplateName &Name,
-                                        SourceLocation NameLoc,
-                                        bool Diagnose = true);
+private:
+  ExprResult SemaBuiltinOperatorNewDeleteOverloaded(ExprResult TheCallResult,
+                                                    bool IsDelete);
 
-  /// 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);
+  void AnalyzeDeleteExprMismatch(const CXXDeleteExpr *DE);
+  void AnalyzeDeleteExprMismatch(FieldDecl *Field, SourceLocation DeleteLoc,
+                                 bool DeleteWasArrayForm);
 
-  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);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
-  TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl);
+  /// \name Member Access Expressions
+  /// Implementations are in SemaExprMember.cpp
+  ///@{
 
-  NamedDecl *ActOnTypeParameter(Scope *S, bool Typename,
-                                SourceLocation EllipsisLoc,
-                                SourceLocation KeyLoc,
-                                IdentifierInfo *ParamName,
-                                SourceLocation ParamNameLoc,
-                                unsigned Depth, unsigned Position,
-                                SourceLocation EqualLoc,
-                                ParsedType DefaultArg, bool HasTypeConstraint);
+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 CheckTypeConstraint(TemplateIdAnnotation *TypeConstraint);
+  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);
 
-  bool ActOnTypeConstraint(const CXXScopeSpec &SS,
-                           TemplateIdAnnotation *TypeConstraint,
-                           TemplateTypeParmDecl *ConstrainedParameter,
-                           SourceLocation EllipsisLoc);
-  bool BuildTypeConstraint(const CXXScopeSpec &SS,
-                           TemplateIdAnnotation *TypeConstraint,
-                           TemplateTypeParmDecl *ConstrainedParameter,
-                           SourceLocation EllipsisLoc,
-                           bool AllowUnexpandedPack);
-
-  bool AttachTypeConstraint(NestedNameSpecifierLoc NS,
-                            DeclarationNameInfo NameInfo,
-                            ConceptDecl *NamedConcept,
-                            const TemplateArgumentListInfo *TemplateArgs,
-                            TemplateTypeParmDecl *ConstrainedParameter,
-                            SourceLocation EllipsisLoc);
-
-  bool AttachTypeConstraint(AutoTypeLoc TL,
-                            NonTypeTemplateParmDecl *NewConstrainedParm,
-                            NonTypeTemplateParmDecl *OrigConstrainedParm,
-                            SourceLocation EllipsisLoc);
-
-  bool RequireStructuralType(QualType T, SourceLocation Loc);
+  bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType,
+                                     const CXXScopeSpec &SS,
+                                     const LookupResult &R);
 
-  QualType CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI,
-                                             SourceLocation Loc);
-  QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc);
+  // 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;
+  };
 
-  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);
+  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);
 
-  TemplateParameterList *
-  ActOnTemplateParameterList(unsigned Depth,
-                             SourceLocation ExportLoc,
-                             SourceLocation TemplateLoc,
-                             SourceLocation LAngleLoc,
-                             ArrayRef Params,
-                             SourceLocation RAngleLoc,
-                             Expr *RequiresClause);
+  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);
 
-  /// 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
-  };
+  ExprResult BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,
+                                     SourceLocation OpLoc,
+                                     const CXXScopeSpec &SS, FieldDecl *Field,
+                                     DeclAccessPair FoundDecl,
+                                     const DeclarationNameInfo &MemberNameInfo);
 
-  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);
+  ExprResult PerformMemberExprBaseConversion(Expr *Base, bool IsArrow);
 
-  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);
+  ExprResult BuildAnonymousStructUnionMemberReference(
+      const CXXScopeSpec &SS, SourceLocation nameLoc,
+      IndirectFieldDecl *indirectField,
+      DeclAccessPair FoundDecl = DeclAccessPair::make(nullptr, AS_none),
+      Expr *baseObjectExpr = nullptr, SourceLocation opLoc = SourceLocation());
 
-  TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
-                                                    QualType NTTPType,
-                                                    SourceLocation Loc);
+private:
+  void CheckMemberAccessOfNoDeref(const MemberExpr *E);
 
-  /// 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);
+  ///@}
 
-  void translateTemplateArguments(const ASTTemplateArgsPtr &In,
-                                  TemplateArgumentListInfo &Out);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  ParsedTemplateArgument ActOnTemplateTypeArgument(TypeResult ParsedType);
+  /// \name Initializers
+  /// Implementations are in SemaInit.cpp
+  ///@{
 
-  void NoteAllFoundTemplates(TemplateName Name);
+public:
+  /// Stack of types that correspond to the parameter entities that are
+  /// currently being copy-initialized. Can be empty.
+  llvm::SmallVector CurrentParameterCopyTypes;
 
-  QualType CheckTemplateIdType(TemplateName Template,
-                               SourceLocation TemplateLoc,
-                              TemplateArgumentListInfo &TemplateArgs);
+  llvm::DenseMap
+      AggregateDeductionCandidates;
 
-  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);
+  bool IsStringInit(Expr *Init, const ArrayType *AT);
 
-  /// 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);
+  bool CanPerformAggregateInitializationForOverloadResolution(
+      const InitializedEntity &Entity, InitListExpr *From);
 
-  DeclResult ActOnVarTemplateSpecialization(
-      Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous,
-      SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
-      StorageClass SC, bool IsPartialSpecialization);
+  ExprResult ActOnDesignatedInitializer(Designation &Desig,
+                                        SourceLocation EqualOrColonLoc,
+                                        bool GNUSyntax, ExprResult Init);
 
-  /// 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);
+  /// 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);
 
-  /// 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);
+  MaterializeTemporaryExpr *
+  CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary,
+                                 bool BoundToLvalueReference);
 
-  ExprResult
-  CheckConceptTemplateId(const CXXScopeSpec &SS,
-                         SourceLocation TemplateKWLoc,
-                         const DeclarationNameInfo &ConceptNameInfo,
-                         NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
-                         const TemplateArgumentListInfo *TemplateArgs);
+  /// 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);
 
-  void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);
+  ExprResult PerformQualificationConversion(
+      Expr *E, QualType Ty, ExprValueKind VK = VK_PRValue,
+      CheckedConversionKind CCK = CCK_ImplicitConversion);
 
-  ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
-                                 SourceLocation TemplateKWLoc,
-                                 LookupResult &R,
-                                 bool RequiresADL,
-                               const TemplateArgumentListInfo *TemplateArgs);
+  bool CanPerformCopyInitialization(const InitializedEntity &Entity,
+                                    ExprResult Init);
+  ExprResult PerformCopyInitialization(const InitializedEntity &Entity,
+                                       SourceLocation EqualLoc, ExprResult Init,
+                                       bool TopLevelOfInitList = false,
+                                       bool AllowExplicit = false);
 
-  ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS,
-                                          SourceLocation TemplateKWLoc,
-                               const DeclarationNameInfo &NameInfo,
-                               const TemplateArgumentListInfo *TemplateArgs);
+  QualType DeduceTemplateSpecializationFromInitializer(
+      TypeSourceInfo *TInfo, const InitializedEntity &Entity,
+      const InitializationKind &Kind, MultiExprArg Init);
 
-  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);
+  /// \name C++ Lambda Expressions
+  /// Implementations are in SemaLambda.cpp
+  ///@{
 
-  Decl *ActOnTemplateDeclarator(Scope *S,
-                                MultiTemplateParamsArg TemplateParameterLists,
-                                Declarator &D);
+public:
+  /// Create a new lambda closure type.
+  CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange,
+                                         TypeSourceInfo *Info,
+                                         unsigned LambdaDependencyKind,
+                                         LambdaCaptureDefault CaptureDefault);
 
-  bool
-  CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
-                                         TemplateSpecializationKind NewTSK,
-                                         NamedDecl *PrevDecl,
-                                         TemplateSpecializationKind PrevTSK,
-                                         SourceLocation PrevPtOfInstantiation,
-                                         bool &SuppressNew);
+  /// Number lambda for linkage purposes if necessary.
+  void handleLambdaNumbering(CXXRecordDecl *Class, CXXMethodDecl *Method,
+                             std::optional
+                                 NumberingOverride = std::nullopt);
 
-  bool CheckDependentFunctionTemplateSpecialization(
-      FunctionDecl *FD, const TemplateArgumentListInfo *ExplicitTemplateArgs,
-      LookupResult &Previous);
+  /// 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);
 
-  bool CheckFunctionTemplateSpecialization(
-      FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs,
-      LookupResult &Previous, bool QualifiedFriend = false);
-  bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
-  void CompleteMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
+  CXXMethodDecl *CreateLambdaCallOperator(SourceRange IntroducerRange,
+                                          CXXRecordDecl *Class);
 
-  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);
+  void AddTemplateParametersToLambdaCallOperator(
+      CXXMethodDecl *CallOperator, CXXRecordDecl *Class,
+      TemplateParameterList *TemplateParams);
 
-  DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc,
-                                        SourceLocation TemplateLoc,
-                                        unsigned TagSpec, SourceLocation KWLoc,
-                                        CXXScopeSpec &SS, IdentifierInfo *Name,
-                                        SourceLocation NameLoc,
-                                        const ParsedAttributesView &Attr);
+  void CompleteLambdaCallOperator(
+      CXXMethodDecl *Method, SourceLocation LambdaLoc,
+      SourceLocation CallOperatorLoc, Expr *TrailingRequiresClause,
+      TypeSourceInfo *MethodTyInfo, ConstexprSpecKind ConstexprKind,
+      StorageClass SC, ArrayRef Params,
+      bool HasExplicitResultType);
 
-  DeclResult ActOnExplicitInstantiation(Scope *S,
-                                        SourceLocation ExternLoc,
-                                        SourceLocation TemplateLoc,
-                                        Declarator &D);
+  void DiagnoseInvalidExplicitObjectParameterInLambda(CXXMethodDecl *Method);
 
-  TemplateArgumentLoc SubstDefaultTemplateArgumentIfAvailable(
-      TemplateDecl *Template, SourceLocation TemplateLoc,
-      SourceLocation RAngleLoc, Decl *Param,
-      ArrayRef SugaredConverted,
-      ArrayRef CanonicalConverted, bool &HasDefaultArg);
-
-  SourceLocation getTopMostPointOfInstantiation(const NamedDecl *) const;
+  /// 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);
 
-  /// 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,
+  /// 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);
 
-    /// The template argument was deduced via template argument
-    /// deduction.
-    CTAK_Deduced,
+  /// Add an init-capture to a lambda scope.
+  void addInitCapture(sema::LambdaScopeInfo *LSI, VarDecl *Var, bool ByRef);
 
-    /// The template argument was deduced from an array bound
-    /// via template argument deduction.
-    CTAK_DeducedFromArrayBound
-  };
+  /// Note that we have finished the explicit captures for the
+  /// given lambda.
+  void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI);
 
-  bool
-  CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &Arg,
-                        NamedDecl *Template, SourceLocation TemplateLoc,
-                        SourceLocation RAngleLoc, unsigned ArgumentPackIndex,
-                        SmallVectorImpl &SugaredConverted,
-                        SmallVectorImpl &CanonicalConverted,
-                        CheckTemplateArgumentKind CTAK);
+  /// Deduce a block or lambda's return type based on the return
+  /// statements present in the body.
+  void deduceClosureReturnType(sema::CapturingScopeInfo &CSI);
 
-  /// 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);
+  /// 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);
 
-  bool CheckTemplateTypeArgument(
-      TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg,
-      SmallVectorImpl &SugaredConverted,
-      SmallVectorImpl &CanonicalConverted);
+  /// 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);
 
-  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);
+  void ActOnLambdaClosureQualifiers(LambdaIntroducer &Intro,
+                                    SourceLocation MutableLoc);
 
-  void NoteTemplateLocation(const NamedDecl &Decl,
-                            std::optional ParamRange = {});
-  void NoteTemplateParameterLocation(const NamedDecl &Decl);
+  void ActOnLambdaClosureParameters(
+      Scope *LambdaScope,
+      MutableArrayRef ParamInfo);
 
-  ExprResult
-  BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg,
-                                          QualType ParamType,
-                                          SourceLocation Loc);
-  ExprResult
-  BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
-                                             SourceLocation Loc);
+  /// 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);
 
-  /// 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,
+  /// 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);
 
-    /// 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,
+  /// ActOnLambdaExpr - This is called when the body of a lambda expression
+  /// was successfully completed.
+  ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body);
 
-    /// 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,
+  /// Does copying/destroying the captured variable have side effects?
+  bool CaptureHasSideEffects(const sema::Capture &From);
 
-    /// 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,
-  };
+  /// Diagnose if an explicit lambda capture is unused. Returns true if a
+  /// diagnostic is emitted.
+  bool DiagnoseUnusedLambdaCapture(SourceRange CaptureRange,
+                                   const sema::Capture &From);
 
-  // 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;
+  /// Build a FieldDecl suitable to hold the given capture.
+  FieldDecl *BuildCaptureField(RecordDecl *RD, const sema::Capture &Capture);
 
-  public:
-    TemplateCompareNewDeclInfo(const NamedDecl *ND) : ND(ND) {}
-    TemplateCompareNewDeclInfo(const DeclContext *DeclCtx,
-                               const DeclContext *LexicalDeclCtx,
-                               SourceLocation Loc)
+  /// Initialize the given capture with a suitable expression.
+  ExprResult BuildCaptureInit(const sema::Capture &Capture,
+                              SourceLocation ImplicitCaptureLoc,
+                              bool IsOpenMPMapping = false);
 
-        : DC(DeclCtx), LexicalDC(LexicalDeclCtx), Loc(Loc) {
-      assert(DC && LexicalDC &&
-             "Constructor only for cases where we have the information to put "
-             "in here");
-    }
+  /// Complete a lambda-expression having processed and attached the
+  /// lambda body.
+  ExprResult BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
+                             sema::LambdaScopeInfo *LSI);
 
-    // 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; }
+  /// 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);
 
-    const NamedDecl *getDecl() const { return ND; }
+  ExprResult BuildBlockForLambdaConversion(SourceLocation CurrentLocation,
+                                           SourceLocation ConvLocation,
+                                           CXXConversionDecl *Conv, Expr *Src);
 
-    bool ContainsDecl(const NamedDecl *ND) const { return this->ND == ND; }
+  class LambdaScopeForCallOperatorInstantiationRAII
+      : private FunctionScopeRAII {
+  public:
+    LambdaScopeForCallOperatorInstantiationRAII(
+        Sema &SemasRef, FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL,
+        LocalInstantiationScope &Scope,
+        bool ShouldAddDeclsFromParentScope = true);
+  };
 
-    const DeclContext *getLexicalDeclContext() const {
-      return ND ? ND->getLexicalDeclContext() : LexicalDC;
-    }
+  /// 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);
 
-    const DeclContext *getDeclContext() const {
-      return ND ? ND->getDeclContext() : DC;
-    }
+  ///@}
 
-    SourceLocation getLocation() const { return ND ? ND->getLocation() : Loc; }
-  };
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  bool TemplateParameterListsAreEqual(
-      const TemplateCompareNewDeclInfo &NewInstFrom, TemplateParameterList *New,
-      const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain,
-      TemplateParameterListEqualKind Kind,
-      SourceLocation TemplateArgLoc = SourceLocation());
+  /// \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.
+  ///
+  /// Implementations are in SemaLookup.cpp
+  ///@{
 
-  bool TemplateParameterListsAreEqual(
-      TemplateParameterList *New, TemplateParameterList *Old, bool Complain,
-      TemplateParameterListEqualKind Kind,
-      SourceLocation TemplateArgLoc = SourceLocation()) {
-    return TemplateParameterListsAreEqual(nullptr, New, nullptr, Old, Complain,
-                                          Kind, TemplateArgLoc);
-  }
+public:
+  /// Tracks whether we are in a context where typo correction is
+  /// disabled.
+  bool DisableTypoCorrection;
 
-  // 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);
+  /// The number of typos corrected by CorrectTypo.
+  unsigned TyposCorrected;
 
-  bool CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams);
+  typedef llvm::SmallSet SrcLocSet;
+  typedef llvm::DenseMap IdentifierSourceLocations;
 
-  /// 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);
+  /// 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;
 
-  /// Called when the parser has parsed a C++ typename
-  /// specifier that ends in a template-id, e.g.,
-  /// "typename MetaFun::template apply".
+  /// SpecialMemberOverloadResult - The overloading result for a special member
+  /// function.
   ///
-  /// \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);
+  /// 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 };
 
-  QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
-                             SourceLocation KeywordLoc,
-                             NestedNameSpecifierLoc QualifierLoc,
-                             const IdentifierInfo &II,
-                             SourceLocation IILoc,
-                             TypeSourceInfo **TSI,
-                             bool DeducedTSTContext);
+  private:
+    llvm::PointerIntPair Pair;
 
-  QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
-                             SourceLocation KeywordLoc,
-                             NestedNameSpecifierLoc QualifierLoc,
-                             const IdentifierInfo &II,
-                             SourceLocation IILoc,
-                             bool DeducedTSTContext = true);
+  public:
+    SpecialMemberOverloadResult() {}
+    SpecialMemberOverloadResult(CXXMethodDecl *MD)
+        : Pair(MD, MD->isDeleted() ? NoMemberOrDeleted : Success) {}
 
+    CXXMethodDecl *getMethod() const { return Pair.getPointer(); }
+    void setMethod(CXXMethodDecl *MD) { Pair.setPointer(MD); }
 
-  TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
-                                                    SourceLocation Loc,
-                                                    DeclarationName Name);
-  bool RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS);
+    Kind getKind() const { return static_cast(Pair.getInt()); }
+    void setKind(Kind K) { Pair.setInt(K); }
+  };
 
-  ExprResult RebuildExprInCurrentInstantiation(Expr *E);
-  bool RebuildTemplateParamsInCurrentInstantiation(
-                                                TemplateParameterList *Params);
+  class SpecialMemberOverloadResultEntry : public llvm::FastFoldingSetNode,
+                                           public SpecialMemberOverloadResult {
+  public:
+    SpecialMemberOverloadResultEntry(const llvm::FoldingSetNodeID &ID)
+        : FastFoldingSetNode(ID) {}
+  };
 
-  std::string
-  getTemplateArgumentBindingsText(const TemplateParameterList *Params,
-                                  const TemplateArgumentList &Args);
+  /// A cache of special member function overload resolution results
+  /// for C++ records.
+  llvm::FoldingSet SpecialMemberCache;
 
-  std::string
-  getTemplateArgumentBindingsText(const TemplateParameterList *Params,
-                                  const TemplateArgument *Args,
-                                  unsigned NumArgs);
+  /// 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;
 
-  //===--------------------------------------------------------------------===//
-  // C++ Concepts
-  //===--------------------------------------------------------------------===//
-  Decl *ActOnConceptDefinition(
-      Scope *S, MultiTemplateParamsArg TemplateParameterLists,
-      IdentifierInfo *Name, SourceLocation NameLoc, Expr *ConstraintExpr);
+  enum class AcceptableKind { Visible, Reachable };
 
-  void CheckConceptRedefinition(ConceptDecl *NewDecl, LookupResult &Previous,
-                                bool &AddToScope);
+  // Members have to be NamespaceDecl* or TranslationUnitDecl*.
+  // TODO: make this is a typesafe union.
+  typedef llvm::SmallSetVector AssociatedNamespaceSet;
+  typedef llvm::SmallSetVector AssociatedClassSet;
 
-  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);
+  /// 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
+  };
 
-  //===--------------------------------------------------------------------===//
-  // C++ Variadic Templates (C++0x [temp.variadic])
-  //===--------------------------------------------------------------------===//
+  /// 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,
+  };
 
-  /// Determine whether an unexpanded parameter pack might be permitted in this
-  /// location. Useful for error recovery.
-  bool isUnexpandedParameterPackPermitted();
+  SpecialMemberOverloadResult
+  LookupSpecialMember(CXXRecordDecl *D, CXXSpecialMember SM, bool ConstArg,
+                      bool VolatileArg, bool RValueThis, bool ConstThis,
+                      bool VolatileThis);
 
-  /// 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,
+  typedef std::function TypoDiagnosticGenerator;
+  typedef std::function
+      TypoRecoveryCallback;
 
-    /// The base type of a class type.
-    UPPC_BaseType,
+  /// 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
+  };
 
-    /// The type of an arbitrary declaration.
-    UPPC_DeclarationType,
+  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;
+  }
 
-    /// The type of a data member.
-    UPPC_DataMemberType,
+  /// 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);
 
-    /// The size of a bit-field.
-    UPPC_BitFieldWidth,
+  void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S,
+                                    UnresolvedSetImpl &Functions);
 
-    /// The expression in a static assertion.
-    UPPC_StaticAssertExpression,
+  LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
+                                 SourceLocation GnuLabelLoc = SourceLocation());
 
-    /// The fixed underlying type of an enumeration.
-    UPPC_FixedUnderlyingType,
+  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);
 
-    /// The enumerator value.
-    UPPC_EnumeratorValue,
+  /// Force the declaration of any implicitly-declared members of this
+  /// class.
+  void ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class);
 
-    /// A using declaration.
-    UPPC_UsingDeclaration,
+  /// Make a merged definition of an existing hidden definition \p ND
+  /// visible at the specified location.
+  void makeMergedDefinitionVisible(NamedDecl *ND);
 
-    /// A friend declaration.
-    UPPC_FriendDeclaration,
+  /// 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();
 
-    /// A declaration qualifier.
-    UPPC_DeclarationQualifier,
+  bool hasVisibleMergedDefinition(const NamedDecl *Def);
+  bool hasMergedDefinitionInCurrentModule(const NamedDecl *Def);
 
-    /// An initializer.
-    UPPC_Initializer,
+  /// 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);
 
-    /// A default argument.
-    UPPC_DefaultArgument,
+  /// 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);
 
-    /// The type of a non-type template parameter.
-    UPPC_NonTypeTemplateParameterType,
+  /// 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);
 
-    /// The type of an exception.
-    UPPC_ExceptionType,
+  bool isModuleVisible(const Module *M, bool ModulePrivate = false);
 
-    /// Explicit specialization.
-    UPPC_ExplicitSpecialization,
+  /// Determine whether any declaration of an entity is visible.
+  bool
+  hasVisibleDeclaration(const NamedDecl *D,
+                        llvm::SmallVectorImpl *Modules = nullptr) {
+    return isVisible(D) || hasVisibleDeclarationSlow(D, Modules);
+  }
 
-    /// Partial specialization.
-    UPPC_PartialSpecialization,
+  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);
 
-    /// Microsoft __if_exists.
-    UPPC_IfExists,
+  void diagnoseTypo(const TypoCorrection &Correction,
+                    const PartialDiagnostic &TypoDiag,
+                    bool ErrorRecovery = true);
 
-    /// Microsoft __if_not_exists.
-    UPPC_IfNotExists,
+  void diagnoseTypo(const TypoCorrection &Correction,
+                    const PartialDiagnostic &TypoDiag,
+                    const PartialDiagnostic &PrevNote,
+                    bool ErrorRecovery = true);
 
-    /// Lambda expression.
-    UPPC_Lambda,
+  void FindAssociatedClassesAndNamespaces(
+      SourceLocation InstantiationLoc, ArrayRef Args,
+      AssociatedNamespaceSet &AssociatedNamespaces,
+      AssociatedClassSet &AssociatedClasses);
 
-    /// Block expression.
-    UPPC_Block,
+  void DiagnoseAmbiguousLookup(LookupResult &Result);
 
-    /// A type constraint.
-    UPPC_TypeConstraint,
+  LiteralOperatorLookupResult
+  LookupLiteralOperator(Scope *S, LookupResult &R, ArrayRef ArgTys,
+                        bool AllowRaw, bool AllowTemplate,
+                        bool AllowStringTemplate, bool DiagnoseMissing,
+                        StringLiteral *StringLit = nullptr);
 
-    // A requirement in a requires-expression.
-    UPPC_Requirement,
+  void ArgumentDependentLookup(DeclarationName Name, SourceLocation Loc,
+                               ArrayRef Args, ADLResult &Functions);
 
-    // A requires-clause.
-    UPPC_RequiresClause,
+  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);
+
+  enum CorrectTypoKind {
+    CTK_NonError,     // CorrectTypo used in a non error recovery situation.
+    CTK_ErrorRecovery // CorrectTypo used in normal error recovery.
   };
 
-  /// 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);
+  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);
 
-  /// 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);
+  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);
 
-  /// 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);
+  /// Kinds of missing import. Note, the values of these enumerators correspond
+  /// to %select values in diagnostics.
+  enum class MissingImportKind {
+    Declaration,
+    Definition,
+    DefaultArgument,
+    ExplicitSpecialization,
+    PartialSpecialization
+  };
 
-  /// 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);
+  /// 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);
 
-  /// 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);
+  struct TypoExprState {
+    std::unique_ptr Consumer;
+    TypoDiagnosticGenerator DiagHandler;
+    TypoRecoveryCallback RecoveryHandler;
+    TypoExprState();
+    TypoExprState(TypoExprState &&other) noexcept;
+    TypoExprState &operator=(TypoExprState &&other) noexcept;
+  };
 
-  /// 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);
+  const TypoExprState &getTypoExprState(TypoExpr *TE) const;
 
-  /// 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);
+  /// Clears the state of the given TypoExpr.
+  void clearDelayedTypo(TypoExpr *TE);
 
-  /// 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);
+  /// Called on #pragma clang __debug dump II
+  void ActOnPragmaDump(Scope *S, SourceLocation Loc, IdentifierInfo *II);
 
-  /// 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);
+  /// Called on #pragma clang __debug dump E
+  void ActOnPragmaDump(Expr *E);
 
-  /// 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);
+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;
 
-  /// 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);
+  /// Whether we have already loaded known namespaces from an extenal
+  /// source.
+  bool LoadedExternalKnownNamespaces;
 
-  /// 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);
+  bool CppLookupName(LookupResult &R, Scope *S);
 
-  /// 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);
+  bool isUsableModule(const Module *M);
 
-  /// 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);
+  /// 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);
 
-  /// 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 set of unhandled TypoExprs and their associated state.
+  llvm::MapVector DelayedTypos;
 
-  /// 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);
+  /// Creates a new TypoExpr AST node.
+  TypoExpr *createDelayedTypo(std::unique_ptr TCC,
+                              TypoDiagnosticGenerator TDG,
+                              TypoRecoveryCallback TRC, SourceLocation TypoLoc);
 
-  /// Construct a pack expansion type from the pattern of the pack
-  /// expansion.
-  TypeSourceInfo *CheckPackExpansion(TypeSourceInfo *Pattern,
-                                     SourceLocation EllipsisLoc,
-                                     std::optional NumExpansions);
+  /// Cache for module units which is usable for current module.
+  llvm::DenseSet UsableModuleUnitsCache;
 
-  /// Construct a pack expansion type from the pattern of the pack
-  /// expansion.
-  QualType CheckPackExpansion(QualType Pattern, SourceRange PatternRange,
-                              SourceLocation EllipsisLoc,
-                              std::optional NumExpansions);
+  /// 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();
+  }
 
-  /// 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);
+  bool isAcceptableSlow(const NamedDecl *D, AcceptableKind Kind);
 
-  /// 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 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);
 
-  /// 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);
+  /// \name Modules
+  /// Implementations are in SemaModule.cpp
+  ///@{
 
-  /// 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;
+public:
+  /// Get the module unit whose scope we are currently within.
+  Module *getCurrentModule() const {
+    return ModuleScopes.empty() ? nullptr : ModuleScopes.back().Module;
+  }
 
-  /// 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);
+  /// Is the module scope we are an implementation unit?
+  bool currentModuleIsImplementation() const {
+    return ModuleScopes.empty()
+               ? false
+               : ModuleScopes.back().Module->isModuleImplementation();
+  }
 
-  //===--------------------------------------------------------------------===//
-  // C++ Template Argument Deduction (C++ [temp.deduct])
-  //===--------------------------------------------------------------------===//
+  // When loading a non-modular PCH files, this is used to restore module
+  // visibility.
+  void makeModuleVisible(Module *Mod, SourceLocation ImportLoc) {
+    VisibleModules.setVisible(Mod, ImportLoc);
+  }
 
-  /// 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);
+  enum class ModuleDeclKind {
+    Interface,               ///< 'export module X;'
+    Implementation,          ///< 'module X;'
+    PartitionInterface,      ///< 'export module X:Y;'
+    PartitionImplementation, ///< 'module X:Y;'
+  };
 
-  TemplateDeductionResult
-  DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
-                          ArrayRef TemplateArgs,
-                          sema::TemplateDeductionInfo &Info);
+  /// 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.
+  };
 
-  TemplateDeductionResult
-  DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
-                          ArrayRef TemplateArgs,
-                          sema::TemplateDeductionInfo &Info);
+  /// 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);
 
-  TemplateDeductionResult SubstituteExplicitTemplateArguments(
-      FunctionTemplateDecl *FunctionTemplate,
-      TemplateArgumentListInfo &ExplicitTemplateArgs,
-      SmallVectorImpl &Deduced,
-      SmallVectorImpl &ParamTypes, QualType *FunctionType,
-      sema::TemplateDeductionInfo &Info);
+  /// 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);
 
-  /// 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) {}
+  /// 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);
 
-    QualType OriginalParamType;
-    bool DecomposedParam;
-    unsigned ArgIdx;
-    QualType OriginalArgType;
-  };
+  /// 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 = {});
 
-  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; });
+  /// 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);
 
-  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);
+  /// The parsed has entered a submodule.
+  void ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod);
+  /// The parser has left a submodule.
+  void ActOnModuleEnd(SourceLocation DirectiveLoc, Module *Mod);
 
-  TemplateDeductionResult
-  DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
-                          TemplateArgumentListInfo *ExplicitTemplateArgs,
-                          QualType ArgFunctionType,
-                          FunctionDecl *&Specialization,
-                          sema::TemplateDeductionInfo &Info,
-                          bool IsAddressOfFunction = false);
+  /// 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);
 
-  TemplateDeductionResult DeduceTemplateArguments(
-      FunctionTemplateDecl *FunctionTemplate, QualType ObjectType,
-      Expr::Classification ObjectClassification, QualType ToType,
-      CXXConversionDecl *&Specialization, sema::TemplateDeductionInfo &Info);
+  Decl *ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc,
+                             SourceLocation LBraceLoc);
+  Decl *ActOnFinishExportDecl(Scope *S, Decl *ExportDecl,
+                              SourceLocation RBraceLoc);
 
-  TemplateDeductionResult
-  DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
-                          TemplateArgumentListInfo *ExplicitTemplateArgs,
-                          FunctionDecl *&Specialization,
-                          sema::TemplateDeductionInfo &Info,
-                          bool IsAddressOfFunction = false);
+private:
+  /// The parser has begun a translation unit to be compiled as a C++20
+  /// Header Unit, helper for ActOnStartOfTranslationUnit() only.
+  void HandleStartOfHeaderUnit();
 
-  /// 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);
+  struct ModuleScope {
+    SourceLocation BeginLoc;
+    clang::Module *Module = nullptr;
+    VisibleModuleSet OuterVisibleModules;
+  };
+  /// The modules we're currently parsing.
+  llvm::SmallVector ModuleScopes;
 
-  // Substitute auto in TypeWithAuto for a Dependent auto type
-  QualType SubstAutoTypeDependent(QualType TypeWithAuto);
+  /// For an interface unit, this is the implicitly imported interface unit.
+  clang::Module *ThePrimaryInterface = nullptr;
 
-  // Substitute auto in TypeWithAuto for a Dependent auto type
-  TypeSourceInfo *
-  SubstAutoTypeSourceInfoDependent(TypeSourceInfo *TypeWithAuto);
+  /// 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;
 
-  /// 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);
+  /// 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;
 
-  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);
+  /// Namespace definitions that we will export when they finish.
+  llvm::SmallPtrSet DeferredExportedNamespaces;
 
-  bool CheckIfFunctionSpecializationIsImmediate(FunctionDecl *FD,
-                                                SourceLocation Loc);
+  /// 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;
 
-  /// 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;
+  /// Helper function to judge if we are in module purview.
+  /// Return false if we are not in a module.
+  bool isCurrentModulePurview() const;
 
-  QualType DeduceTemplateSpecializationFromInitializer(
-      TypeSourceInfo *TInfo, const InitializedEntity &Entity,
-      const InitializationKind &Kind, MultiExprArg Init);
+  /// Enter the scope of the explicit global module fragment.
+  Module *PushGlobalModuleFragment(SourceLocation BeginLoc);
+  /// Leave the scope of the explicit global module fragment.
+  void PopGlobalModuleFragment();
 
-  QualType deduceVarTypeFromInitializer(VarDecl *VDecl, DeclarationName Name,
-                                        QualType Type, TypeSourceInfo *TSI,
-                                        SourceRange Range, bool DirectInit,
-                                        Expr *Init);
+  /// Enter the scope of an implicit global module fragment.
+  Module *PushImplicitGlobalModuleFragment(SourceLocation BeginLoc);
+  /// Leave the scope of an implicit global module fragment.
+  void PopImplicitGlobalModuleFragment();
 
-  TypeLoc getReturnTypeLoc(FunctionDecl *FD) const;
+  VisibleModuleSet VisibleModules;
 
-  bool DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
-                                        SourceLocation ReturnLoc, Expr *RetExpr,
-                                        const AutoType *AT);
+  ///@}
 
-  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());
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  ClassTemplatePartialSpecializationDecl *
-  getMoreSpecializedPartialSpecialization(
-                                  ClassTemplatePartialSpecializationDecl *PS1,
-                                  ClassTemplatePartialSpecializationDecl *PS2,
-                                  SourceLocation Loc);
+  /// \name C++ Overloading
+  /// Implementations are in SemaOverload.cpp
+  ///@{
 
-  bool isMoreSpecializedThanPrimary(ClassTemplatePartialSpecializationDecl *T,
-                                    sema::TemplateDeductionInfo &Info);
+public:
+  /// Whether deferrable diagnostics should be deferred.
+  bool DeferDiags = false;
 
-  VarTemplatePartialSpecializationDecl *getMoreSpecializedPartialSpecialization(
-      VarTemplatePartialSpecializationDecl *PS1,
-      VarTemplatePartialSpecializationDecl *PS2, SourceLocation Loc);
+  /// RAII class to control scope of DeferDiags.
+  class DeferDiagsRAII {
+    Sema &S;
+    bool SavedDeferDiags = false;
 
-  bool isMoreSpecializedThanPrimary(VarTemplatePartialSpecializationDecl *T,
-                                    sema::TemplateDeductionInfo &Info);
+  public:
+    DeferDiagsRAII(Sema &S, bool DeferDiags)
+        : S(S), SavedDeferDiags(S.DeferDiags) {
+      S.DeferDiags = DeferDiags;
+    }
+    ~DeferDiagsRAII() { S.DeferDiags = SavedDeferDiags; }
+  };
 
-  bool isTemplateTemplateParameterAtLeastAsSpecializedAs(
-      TemplateParameterList *PParam, TemplateDecl *AArg, SourceLocation Loc);
+  /// 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;
 
-  void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced,
-                                  unsigned Depth, llvm::SmallBitVector &Used);
+  enum OverloadKind {
+    /// This is a legitimate overload: the existing declarations are
+    /// functions or function templates with different signatures.
+    Ovl_Overload,
 
-  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);
+    /// This is not an overload because the signature exactly matches
+    /// an existing declaration.
+    Ovl_Match,
 
-  //===--------------------------------------------------------------------===//
-  // C++ Template Instantiation
-  //
+    /// 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);
 
-  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);
+  // 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);
 
-  /// 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,
+  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
+  };
 
-      /// 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,
+  ImplicitConversionSequence TryImplicitConversion(
+      Expr *From, QualType ToType, bool SuppressUserConversions,
+      AllowedExplicit AllowExplicit, bool InOverloadResolution, bool CStyle,
+      bool AllowObjCWritebackConversion);
 
-      /// We are instantiating a default argument for a function.
-      /// The Entity is the ParmVarDecl, and TemplateArgs/NumTemplateArgs
-      /// provides the template arguments as specified.
-      DefaultFunctionArgumentInstantiation,
+  ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
+                                       AssignmentAction Action,
+                                       bool AllowExplicit = false);
 
-      /// We are substituting explicit template arguments provided for
-      /// a function template. The entity is a FunctionTemplateDecl.
-      ExplicitTemplateArgumentSubstitution,
+  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);
 
-      /// 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,
+  bool FunctionParamTypesAreEqual(ArrayRef Old,
+                                  ArrayRef New,
+                                  unsigned *ArgPos = nullptr,
+                                  bool Reversed = false);
 
-      /// We are substituting into a lambda expression.
-      LambdaExpressionSubstitution,
+  bool FunctionParamTypesAreEqual(const FunctionProtoType *OldType,
+                                  const FunctionProtoType *NewType,
+                                  unsigned *ArgPos = nullptr,
+                                  bool Reversed = false);
 
-      /// We are substituting prior template arguments into a new
-      /// template parameter. The template parameter itself is either a
-      /// NonTypeTemplateParmDecl or a TemplateTemplateParmDecl.
-      PriorTemplateArgumentSubstitution,
+  bool FunctionNonObjectParamTypesAreEqual(const FunctionDecl *OldFunction,
+                                           const FunctionDecl *NewFunction,
+                                           unsigned *ArgPos = nullptr,
+                                           bool Reversed = false);
 
-      /// We are checking the validity of a default template argument that
-      /// has been used when naming a template-id.
-      DefaultTemplateArgumentChecking,
+  void HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, QualType FromType,
+                                  QualType ToType);
 
-      /// We are computing the exception specification for a defaulted special
-      /// member function.
-      ExceptionSpecEvaluation,
+  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);
 
-      /// We are instantiating the exception specification for a function
-      /// template which was deferred until it was needed.
-      ExceptionSpecInstantiation,
+  ExprResult InitializeExplicitObjectArgument(Sema &S, Expr *Obj,
+                                              FunctionDecl *Fun);
+  ExprResult PerformImplicitObjectArgumentInitialization(
+      Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl,
+      CXXMethodDecl *Method);
 
-      /// We are instantiating a requirement of a requires expression.
-      RequirementInstantiation,
+  ExprResult PerformContextuallyConvertToBool(Expr *From);
+  ExprResult PerformContextuallyConvertToObjCPointer(Expr *From);
 
-      /// We are checking the satisfaction of a nested requirement of a requires
-      /// expression.
-      NestedRequirementConstraintsCheck,
+  /// 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.
+  };
 
-      /// We are declaring an implicit special member function.
-      DeclaringSpecialMember,
+  ExprResult BuildConvertedConstantExpression(Expr *From, QualType T,
+                                              CCEKind CCE,
+                                              NamedDecl *Dest = nullptr);
 
-      /// We are declaring an implicit 'operator==' for a defaulted
-      /// 'operator<=>'.
-      DeclaringImplicitEqualityComparison,
+  ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
+                                              llvm::APSInt &Value, CCEKind CCE);
+  ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
+                                              APValue &Value, CCEKind CCE,
+                                              NamedDecl *Dest = nullptr);
 
-      /// We are defining a synthesized function (such as a defaulted special
-      /// member).
-      DefiningSynthesizedFunction,
+  ExprResult
+  EvaluateConvertedConstantExpression(Expr *E, QualType T, APValue &Value,
+                                      CCEKind CCE, bool RequireInt,
+                                      const APValue &PreNarrowingValue);
 
-      // 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,
+  /// 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 substituting template arguments into a constraint expression.
-      ConstraintSubstitution,
+    ContextualImplicitConverter(bool Suppress = false,
+                                bool SuppressConversion = false)
+        : Suppress(Suppress), SuppressConversion(SuppressConversion) {}
 
-      // We are normalizing a constraint expression.
-      ConstraintNormalization,
+    /// Determine whether the specified type is a valid destination type
+    /// for this conversion.
+    virtual bool match(QualType T) = 0;
 
-      // Instantiating a Requires Expression parameter clause.
-      RequirementParameterInstantiation,
+    /// 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 into the parameter mapping of an atomic constraint
-      // during normalization.
-      ParameterMappingSubstitution,
+    /// Emits a diagnostic when the expression has incomplete class type.
+    virtual SemaDiagnosticBuilder
+    diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) = 0;
 
-      /// We are rewriting a comparison operator in terms of an operator<=>.
-      RewritingOperatorAsSpaceship,
+    /// 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 initializing a structured binding.
-      InitializingStructuredBinding,
+    /// Emits a note for the explicit conversion function.
+    virtual SemaDiagnosticBuilder
+    noteExplicitConv(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0;
 
-      /// We are marking a class as __dllexport.
-      MarkingClassDllexported,
+    /// Emits a diagnostic when there are multiple possible conversion
+    /// functions.
+    virtual SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
+                                                    QualType T) = 0;
 
-      /// We are building an implied call from __builtin_dump_struct. The
-      /// arguments are in CallArgs.
-      BuildingBuiltinDumpStructCall,
+    /// Emits a note for one of the candidate conversions.
+    virtual SemaDiagnosticBuilder
+    noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0;
 
-      /// 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,
+    /// 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 building deduction guides for a class.
-      BuildingDeductionGuides,
-    } Kind;
+    virtual ~ContextualImplicitConverter() {}
+  };
 
-    /// Was the enclosing context a non-instantiation SFINAE context?
-    bool SavedInNonInstantiationSFINAEContext;
+  class ICEConvertDiagnoser : public ContextualImplicitConverter {
+    bool AllowScopedEnumerations;
 
-    /// The point of instantiation or synthesis within the source code.
-    SourceLocation PointOfInstantiation;
+  public:
+    ICEConvertDiagnoser(bool AllowScopedEnumerations, bool Suppress,
+                        bool SuppressConversion)
+        : ContextualImplicitConverter(Suppress, SuppressConversion),
+          AllowScopedEnumerations(AllowScopedEnumerations) {}
 
-    /// The entity that is being synthesized.
-    Decl *Entity;
+    /// Match an integral or (possibly scoped) enumeration type.
+    bool match(QualType T) override;
 
-    /// The template (or partial specialization) in which we are
-    /// performing the instantiation, for substitutions of prior template
-    /// arguments.
-    NamedDecl *Template;
+    SemaDiagnosticBuilder diagnoseNoMatch(Sema &S, SourceLocation Loc,
+                                          QualType T) override {
+      return diagnoseNotInt(S, Loc, T);
+    }
 
-    union {
-      /// The list of template arguments we are substituting, if they
-      /// are not part of the entity.
-      const TemplateArgument *TemplateArgs;
+    /// 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 list of argument expressions in a synthesized call.
-      const Expr *const *CallArgs;
-    };
+  /// Perform a contextual implicit conversion.
+  ExprResult
+  PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE,
+                                      ContextualImplicitConverter &Converter);
 
-    // 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;
+  /// 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
+  };
 
-      /// The number of expressions in CallArgs.
-      unsigned NumCallArgs;
+  // 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,
 
-      /// The special member being declared or defined.
-      CXXSpecialMember SpecialMember;
+      LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/ObjCLifetime)
     };
+  };
+  using ReferenceConversions = ReferenceConversionsScope::ReferenceConversions;
 
-    ArrayRef template_arguments() const {
-      assert(Kind != DeclaringSpecialMember);
-      return {TemplateArgs, NumTemplateArgs};
-    }
-
-    /// The template deduction info object associated with the
-    /// substitution or checking of explicit or deduced template arguments.
-    sema::TemplateDeductionInfo *DeductionInfo;
+  ReferenceCompareResult
+  CompareReferenceRelationship(SourceLocation Loc, QualType T1, QualType T2,
+                               ReferenceConversions *Conv = 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;
+  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);
 
-    CodeSynthesisContext()
-        : Kind(TemplateInstantiation),
-          SavedInNonInstantiationSFINAEContext(false), Entity(nullptr),
-          Template(nullptr), TemplateArgs(nullptr), NumTemplateArgs(0),
-          DeductionInfo(nullptr) {}
+  /// 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);
 
-    /// Determines whether this template is an actual instantiation
-    /// that should be counted toward the maximum instantiation depth.
-    bool isInstantiationRecord() const;
-  };
+  /// 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);
 
-  /// List of active code synthesis contexts.
+  /// Emit diagnostics for the diagnose_if attributes on Function, ignoring any
+  /// ArgDependent DiagnoseIfAttrs.
   ///
-  /// 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;
+  /// 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);
 
-  /// Specializations whose definitions are currently being instantiated.
-  llvm::DenseSet> InstantiatingSpecializations;
+  /// 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);
 
-  /// Non-dependent types used in templates that have already been instantiated
-  /// by some template instantiation.
-  llvm::DenseSet InstantiatedNonDependentTypes;
+  // 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);
 
-  /// Extra modules inspected when performing a lookup during a template
-  /// instantiation. Computed lazily.
-  SmallVector CodeSynthesisContextLookupModules;
+  // 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);
 
-  /// 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;
+  /// 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());
 
-  /// 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();
+  // [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);
 
-  /// Map from the most recent declaration of a namespace to the most
-  /// recent visible declaration of that namespace.
-  llvm::DenseMap VisibleNamespaceCache;
+  FunctionDecl *
+  ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetType,
+                                     bool Complain, DeclAccessPair &Found,
+                                     bool *pHadMultipleCandidates = nullptr);
 
-  /// 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;
+  FunctionDecl *
+  resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &FoundResult);
 
-  /// 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;
+  bool resolveAndFixAddressOfSingleOverloadCandidate(
+      ExprResult &SrcExpr, bool DoFunctionPointerConversion = false);
 
-  /// 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;
+  FunctionDecl *ResolveSingleFunctionTemplateSpecialization(
+      OverloadExpr *ovl, bool Complain = false, DeclAccessPair *Found = nullptr,
+      TemplateSpecCandidateSet *FailedTSC = nullptr);
 
-  /// 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;
-
-  /// 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;
-
-  /// 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;
+  bool ResolveAndFixSingleFunctionTemplateSpecialization(
+      ExprResult &SrcExpr, bool DoFunctionPointerConversion = false,
+      bool Complain = false, SourceRange OpRangeForComplaining = SourceRange(),
+      QualType DestTypeForComplaining = QualType(),
+      unsigned DiagIDForComplaining = 0);
 
-  public:
-    ArgumentPackSubstitutionIndexRAII(Sema &Self, int NewSubstitutionIndex)
-      : Self(Self), OldSubstitutionIndex(Self.ArgumentPackSubstitutionIndex) {
-      Self.ArgumentPackSubstitutionIndex = NewSubstitutionIndex;
-    }
+  void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE,
+                                   ArrayRef Args,
+                                   OverloadCandidateSet &CandidateSet,
+                                   bool PartialOverloading = false);
+  void AddOverloadedCallCandidates(
+      LookupResult &R, TemplateArgumentListInfo *ExplicitTemplateArgs,
+      ArrayRef Args, OverloadCandidateSet &CandidateSet);
 
-    ~ArgumentPackSubstitutionIndexRAII() {
-      Self.ArgumentPackSubstitutionIndex = OldSubstitutionIndex;
-    }
+  // An enum used to represent the different possible results of building a
+  // range-based for loop.
+  enum ForRangeStatus {
+    FRS_Success,
+    FRS_NoViableFunction,
+    FRS_DiagnosticIssued
   };
 
-  friend class ArgumentPackSubstitutionRAII;
+  ForRangeStatus BuildForRangeBeginEndCall(SourceLocation Loc,
+                                           SourceLocation RangeLoc,
+                                           const DeclarationNameInfo &NameInfo,
+                                           LookupResult &MemberLookup,
+                                           OverloadCandidateSet *CandidateSet,
+                                           Expr *Range, ExprResult *CallExpr);
 
-  /// 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;
+  ExprResult BuildOverloadedCallExpr(
+      Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, SourceLocation LParenLoc,
+      MultiExprArg Args, SourceLocation RParenLoc, Expr *ExecConfig,
+      bool AllowTypoCorrection = true, bool CalleesAddressIsTaken = false);
 
-  /// 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());
+  bool buildOverloadedCallSet(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
+                              MultiExprArg Args, SourceLocation RParenLoc,
+                              OverloadCandidateSet *CandidateSet,
+                              ExprResult *Result);
 
-    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());
+  ExprResult CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass,
+                                        NestedNameSpecifierLoc NNSLoc,
+                                        DeclarationNameInfo DNI,
+                                        const UnresolvedSetImpl &Fns,
+                                        bool PerformADL = true);
 
-    /// 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());
+  ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc,
+                                     UnaryOperatorKind Opc,
+                                     const UnresolvedSetImpl &Fns, Expr *input,
+                                     bool RequiresADL = true);
 
-    /// 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());
+  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);
 
-    /// 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());
+  ExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
+                                                SourceLocation RLoc, Expr *Base,
+                                                MultiExprArg Args);
 
-    /// 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());
+  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);
 
-    /// 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());
+  ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base,
+                                      SourceLocation OpLoc,
+                                      bool *NoArrowOperatorFound = nullptr);
 
-    /// Note that we are instantiating a default argument for a function
-    /// parameter.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          ParmVarDecl *Param,
-                          ArrayRef TemplateArgs,
-                          SourceRange InstantiationRange = SourceRange());
+  ExprResult BuildCXXMemberCallExpr(Expr *Exp, NamedDecl *FoundDecl,
+                                    CXXConversionDecl *Method,
+                                    bool HadMultipleCandidates);
 
-    /// 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);
+  ExprResult BuildLiteralOperatorCall(
+      LookupResult &R, DeclarationNameInfo &SuffixInfo, ArrayRef Args,
+      SourceLocation LitEndLoc,
+      TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr);
 
-    /// 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);
+  ExprResult FixOverloadedFunctionReference(Expr *E, DeclAccessPair FoundDecl,
+                                            FunctionDecl *Fn);
+  ExprResult FixOverloadedFunctionReference(ExprResult,
+                                            DeclAccessPair FoundDecl,
+                                            FunctionDecl *Fn);
 
-    /// 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);
+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);
 
-    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);
+  ///@}
 
-    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);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-    struct ConstraintNormalization {};
-    /// \brief Note that we are normalizing a constraint expression.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          ConstraintNormalization, NamedDecl *Template,
-                          SourceRange InstantiationRange);
+  /// \name Pseudo-Object
+  /// Implementations are in SemaPseudoObject.cpp
+  ///@{
 
-    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);
+public:
+  void maybeExtendBlockObject(ExprResult &E);
+  CastKind PrepareCastToObjCObjectPointer(ExprResult &E);
 
-    /// \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());
+  enum ObjCSubscriptKind { OS_Array, OS_Dictionary, OS_Error };
+  ObjCSubscriptKind CheckSubscriptingKind(Expr *FromE);
 
-    /// \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());
+  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);
 
-    /// \brief Note that we are checking a requires clause.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          const RequiresExpr *E,
-                          sema::TemplateDeductionInfo &DeductionInfo,
-                          SourceRange InstantiationRange);
+  ///@}
 
-    struct BuildingDeductionGuidesTag {};
-    /// \brief Note that we are building deduction guides.
-    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          TemplateDecl *Entity, BuildingDeductionGuidesTag,
-                          SourceRange InstantiationRange = SourceRange());
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-    /// Note that we have finished instantiating this template.
-    void Clear();
+  /// \name Statements
+  /// Implementations are in SemaStmt.cpp
+  ///@{
 
-    ~InstantiatingTemplate() { Clear(); }
+public:
+  /// Stack of active SEH __finally scopes.  Can be empty.
+  SmallVector CurrentSEHFinally;
 
-    /// Determines whether we have exceeded the maximum
-    /// recursive template instantiations.
-    bool isInvalid() const { return Invalid; }
+  StmtResult ActOnExprStmt(ExprResult Arg, bool DiscardedValue = true);
+  StmtResult ActOnExprStmtError();
 
-    /// Determine whether we are already instantiating this
-    /// specialization in some surrounding active instantiation.
-    bool isAlreadyInstantiating() const { return AlreadyInstantiating; }
+  StmtResult ActOnNullStmt(SourceLocation SemiLoc,
+                           bool HasLeadingEmptyMacro = false);
 
-  private:
-    Sema &SemaRef;
-    bool Invalid;
-    bool AlreadyInstantiating;
-    bool CheckInstantiationDepth(SourceLocation PointOfInstantiation,
-                                 SourceRange InstantiationRange);
+  StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc,
+                           SourceLocation EndLoc);
+  void ActOnForEachDeclStmt(DeclGroupPtrTy Decl);
 
-    InstantiatingTemplate(
-        Sema &SemaRef, CodeSynthesisContext::SynthesisKind Kind,
-        SourceLocation PointOfInstantiation, SourceRange InstantiationRange,
-        Decl *Entity, NamedDecl *Template = nullptr,
-        ArrayRef TemplateArgs = std::nullopt,
-        sema::TemplateDeductionInfo *DeductionInfo = nullptr);
+  /// DiagnoseUnusedExprResult - If the statement passed in is an expression
+  /// whose result is unused, warn.
+  void DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID);
 
-    InstantiatingTemplate(const InstantiatingTemplate&) = delete;
+  void ActOnStartOfCompoundStmt(bool IsStmtExpr);
+  void ActOnAfterCompoundStatementLeadingPragmas();
+  void ActOnFinishOfCompoundStmt();
+  StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R,
+                               ArrayRef Elts, bool isStmtExpr);
 
-    InstantiatingTemplate&
-    operator=(const InstantiatingTemplate&) = delete;
-  };
+  sema::CompoundScopeInfo &getCurCompoundScope() const;
 
-  void pushCodeSynthesisContext(CodeSynthesisContext Ctx);
-  void popCodeSynthesisContext();
+  ExprResult ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val);
+  StmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHS,
+                           SourceLocation DotDotDotLoc, ExprResult RHS,
+                           SourceLocation ColonLoc);
+  void ActOnCaseStmtBody(Stmt *CaseStmt, Stmt *SubStmt);
 
-  /// Determine whether we are currently performing template instantiation.
-  bool inTemplateInstantiation() const {
-    return CodeSynthesisContexts.size() > NonInstantiationEntries;
-  }
+  StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc,
+                              SourceLocation ColonLoc, Stmt *SubStmt,
+                              Scope *CurScope);
+  StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
+                            SourceLocation ColonLoc, Stmt *SubStmt);
 
-  void PrintContextStack() {
-    if (!CodeSynthesisContexts.empty() &&
-        CodeSynthesisContexts.size() != LastEmittedCodeSynthesisContextDepth) {
-      PrintInstantiationStack();
-      LastEmittedCodeSynthesisContextDepth = CodeSynthesisContexts.size();
-    }
-    if (PragmaAttributeCurrentTargetDecl)
-      PrintPragmaAttributeInstantiationPoint();
-  }
-  void PrintInstantiationStack();
+  StmtResult BuildAttributedStmt(SourceLocation AttrsLoc,
+                                 ArrayRef Attrs, Stmt *SubStmt);
+  StmtResult ActOnAttributedStmt(const ParsedAttributes &AttrList,
+                                 Stmt *SubStmt);
 
-  void PrintPragmaAttributeInstantiationPoint();
+  /// 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);
 
-  /// 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;
+  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);
 
-  /// 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 CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond);
 
-  /// Used to change context to isConstantEvaluated without pushing a heavy
-  /// ExpressionEvaluationContextRecord object.
-  bool isConstantEvaluatedOverride = false;
+  StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
+                                    SourceLocation LParenLoc, Stmt *InitStmt,
+                                    ConditionResult Cond,
+                                    SourceLocation RParenLoc);
+  StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
+                                   Stmt *Body);
 
-  const ExpressionEvaluationContextRecord ¤tEvaluationContext() const {
-    assert(!ExprEvalContexts.empty() &&
-           "Must be in an expression evaluation context");
-    return ExprEvalContexts.back();
-  };
+  /// 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);
 
-  bool isConstantEvaluatedContext() const {
-    return currentEvaluationContext().isConstantEvaluated() ||
-           isConstantEvaluatedOverride;
-  }
+  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);
 
-  bool isAlwaysConstantEvaluatedContext() const {
-    const ExpressionEvaluationContextRecord &Ctx = currentEvaluationContext();
-    return (Ctx.isConstantEvaluated() || isConstantEvaluatedOverride) &&
-           !Ctx.InConditionallyConstantEvaluateContext;
-  }
+  StmtResult ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
+                          Stmt *First, ConditionResult Second,
+                          FullExprArg Third, SourceLocation RParenLoc,
+                          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 ActOnForEachLValueExpr(Expr *E);
 
-  bool isImmediateFunctionContext() const {
-    return currentEvaluationContext().isImmediateFunctionContext();
-  }
+  ExprResult CheckObjCForCollectionOperand(SourceLocation forLoc,
+                                           Expr *collection);
+  StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc, Stmt *First,
+                                        Expr *collection,
+                                        SourceLocation RParenLoc);
+  StmtResult FinishObjCForCollectionStmt(Stmt *ForCollection, Stmt *Body);
 
-  bool isInLifetimeExtendingContext() const {
-    assert(!ExprEvalContexts.empty() &&
-           "Must be in an expression evaluation context");
-    return ExprEvalContexts.back().InLifetimeExtendingContext;
-  }
+  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
+  };
 
-  bool isInMaterializeTemporaryObjectContext() const {
-    assert(!ExprEvalContexts.empty() &&
-           "Must be in an expression evaluation context");
-    return ExprEvalContexts.back().InMaterializeTemporaryObjectContext;
-  }
+  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);
 
-  bool isCheckingDefaultArgumentOrInitializer() const {
-    const ExpressionEvaluationContextRecord &Ctx = currentEvaluationContext();
-    return (Ctx.Context ==
-            ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed) ||
-           Ctx.IsCurrentlyCheckingDefaultArgumentOrInitializer;
-  }
+  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);
 
-  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;
-  }
+  struct NamedReturnInfo {
+    const VarDecl *Candidate;
 
-  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;
-  }
+    enum Status : uint8_t { None, MoveEligible, MoveEligibleAndCopyElidable };
+    Status S;
 
-  /// 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;
-    }
-  }
+    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);
 
-  /// 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;
-    }
-  }
+  ExprResult
+  PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
+                                  const NamedReturnInfo &NRInfo, Expr *Value,
+                                  bool SupressSimplerImplicitMoves = false);
 
-  /// 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;
+  TypeLoc getReturnTypeLoc(FunctionDecl *FD) const;
 
-  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;
-    }
+  bool DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
+                                        SourceLocation ReturnLoc, Expr *RetExpr,
+                                        const AutoType *AT);
 
-    ~SFINAETrap() {
-      SemaRef.NumSFINAEErrors = PrevSFINAEErrors;
-      SemaRef.InNonInstantiationSFINAEContext
-        = PrevInNonInstantiationSFINAEContext;
-      SemaRef.AccessCheckingSFINAE = PrevAccessCheckingSFINAE;
-      SemaRef.getDiagnostics().setLastDiagnosticIgnored(
-          PrevLastDiagnosticIgnored);
-    }
+  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);
 
-    /// Determine whether any SFINAE errors have been trapped.
-    bool hasErrorOccurred() const {
-      return SemaRef.NumSFINAEErrors > PrevSFINAEErrors;
-    }
-  };
+  StmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen,
+                                  Decl *Parm, Stmt *Body);
 
-  /// 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;
-    }
-  };
+  StmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body);
 
-  /// The current instantiation scope used to store local
-  /// variables.
-  LocalInstantiationScope *CurrentInstantiationScope;
+  StmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
+                                MultiStmtArg Catch, Stmt *Finally);
 
-  /// Tracks whether we are in a context where typo correction is
-  /// disabled.
-  bool DisableTypoCorrection;
+  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);
 
-  /// The number of typos corrected by CorrectTypo.
-  unsigned TyposCorrected;
+  StmtResult ActOnObjCAutoreleasePoolStmt(SourceLocation AtLoc, Stmt *Body);
 
-  typedef llvm::SmallSet SrcLocSet;
-  typedef llvm::DenseMap IdentifierSourceLocations;
+  StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl,
+                                Stmt *HandlerBlock);
+  StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
+                              ArrayRef Handlers);
 
-  /// 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;
+  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);
 
-  /// Worker object for performing CFG-based warnings.
-  sema::AnalysisBasedWarnings AnalysisWarnings;
-  threadSafety::BeforeSet *ThreadSafetyDeclCache;
+  StmtResult BuildMSDependentExistsStmt(SourceLocation KeywordLoc,
+                                        bool IsIfExists,
+                                        NestedNameSpecifierLoc QualifierLoc,
+                                        DeclarationNameInfo NameInfo,
+                                        Stmt *Nested);
+  StmtResult ActOnMSDependentExistsStmt(SourceLocation KeywordLoc,
+                                        bool IsIfExists, CXXScopeSpec &SS,
+                                        UnqualifiedId &Name, Stmt *Nested);
 
-  /// 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;
+  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);
 
-  /// The queue of implicit template instantiations that are required
-  /// but have not yet been performed.
-  std::deque PendingInstantiations;
+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);
 
-  /// Queue of implicit template instantiations that cannot be performed
-  /// eagerly.
-  SmallVector LateParsedInstantiations;
+  /// Check if the given expression contains 'break' or 'continue'
+  /// statement that produces control flow different from GCC.
+  void CheckBreakContinueBinding(Expr *E);
 
-  SmallVector, 8> SavedVTableUses;
-  SmallVector, 8>
-      SavedPendingInstantiations;
+  ///@}
 
-  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);
+  /// \name `inline asm` Statement
+  /// Implementations are in SemaStmtAsm.cpp
+  ///@{
 
-      S.SavedVTableUses.emplace_back();
-      S.SavedVTableUses.back().swap(S.VTableUses);
-    }
+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);
 
-    void perform() {
-      if (Enabled) {
-        S.DefineUsedVTables();
-        S.PerformPendingInstantiations();
-      }
-    }
+  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);
 
-    ~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();
-      }
-    }
+  /// \name Statement Attribute Handling
+  /// Implementations are in SemaStmtAttr.cpp
+  ///@{
 
-  private:
-    Sema &S;
-    bool Enabled;
-  };
+public:
+  bool CheckNoInlineAttr(const Stmt *OrigSt, const Stmt *CurSt,
+                         const AttributeCommonInfo &A);
+  bool CheckAlwaysInlineAttr(const Stmt *OrigSt, const Stmt *CurSt,
+                             const AttributeCommonInfo &A);
 
-  /// 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;
+  CodeAlignAttr *BuildCodeAlignAttr(const AttributeCommonInfo &CI, Expr *E);
+  bool CheckRebuiltStmtAttributes(ArrayRef Attrs);
 
-  class LocalEagerInstantiationScope {
-  public:
-    LocalEagerInstantiationScope(Sema &S) : S(S) {
-      SavedPendingLocalImplicitInstantiations.swap(
-          S.PendingLocalImplicitInstantiations);
-    }
+  /// 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);
 
-    void perform() { S.PerformPendingInstantiations(/*LocalOnly=*/true); }
+  ///@}
 
-    ~LocalEagerInstantiationScope() {
-      assert(S.PendingLocalImplicitInstantiations.empty() &&
-             "there shouldn't be any pending local implicit instantiations");
-      SavedPendingLocalImplicitInstantiations.swap(
-          S.PendingLocalImplicitInstantiations);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
+
+  /// \name C++ Templates
+  /// Implementations are in SemaTemplate.cpp
+  ///@{
+
+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;
-    std::deque
-        SavedPendingLocalImplicitInstantiations;
+    PragmaStack SavedStack;
   };
 
-  /// A helper class for building up ExtParameterInfos.
-  class ExtParameterInfoBuilder {
-    SmallVector Infos;
-    bool HasInteresting = false;
+  void resetFPOptions(FPOptions FPO) {
+    CurFPFeatures = FPO;
+    FpPragmaStack.CurrentValue = FPO.getChangesFrom(FPOptions(LangOpts));
+  }
 
-  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);
+  ArrayRef getInventedParameterInfos() const {
+    return llvm::ArrayRef(InventedParameterInfos.begin() +
+                              InventedParameterInfosStart,
+                          InventedParameterInfos.end());
+  }
 
-      if (!HasInteresting)
-        HasInteresting = (info != FunctionProtoType::ExtParameterInfo());
-    }
+  /// The number of SFINAE diagnostics that have been trapped.
+  unsigned NumSFINAEErrors;
 
-    /// 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();
-    }
-  };
+  ArrayRef getFunctionScopes() const {
+    return llvm::ArrayRef(FunctionScopes.begin() + FunctionScopesStart,
+                          FunctionScopes.end());
+  }
 
-  void PerformPendingInstantiations(bool LocalOnly = false);
+  typedef llvm::MapVector>
+      LateParsedTemplateMapT;
+  LateParsedTemplateMapT LateParsedTemplateMap;
 
-  TypeSourceInfo *SubstType(TypeSourceInfo *T,
-                            const MultiLevelTemplateArgumentList &TemplateArgs,
-                            SourceLocation Loc, DeclarationName Entity,
-                            bool AllowDeducedTST = false);
+  /// 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;
 
-  QualType SubstType(QualType T,
-                     const MultiLevelTemplateArgumentList &TemplateArgs,
-                     SourceLocation Loc, DeclarationName Entity);
+  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);
 
-  TypeSourceInfo *SubstType(TypeLoc TL,
-                            const MultiLevelTemplateArgumentList &TemplateArgs,
-                            SourceLocation Loc, DeclarationName Entity);
+  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) {}
 
-  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);
+    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(); }
 
-  // A RAII type used by the TemplateDeclInstantiator and TemplateInstantiator
-  // to disable constraint evaluation, then restore the state.
-  template  struct ConstraintEvalRAII {
-    InstTy &TI;
-    bool OldValue;
+  private:
+    std::optional TemplateKW;
+  };
 
-    ConstraintEvalRAII(InstTy &TI)
-        : TI(TI), OldValue(TI.getEvaluateConstraints()) {
-      TI.setEvaluateConstraints(false);
-    }
-    ~ConstraintEvalRAII() { TI.setEvaluateConstraints(OldValue); }
+  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);
 
-  // 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);
+  TemplateNameKind isTemplateName(Scope *S, CXXScopeSpec &SS,
+                                  bool hasTemplateKeyword,
+                                  const UnqualifiedId &Name,
+                                  ParsedType ObjectType, bool EnteringContext,
+                                  TemplateTy &Template,
+                                  bool &MemberOfUnknownSpecialization,
+                                  bool Disambiguation = false);
 
-  /// 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.
-  ///
-  /// \param TemplateArgs The set of template arguments to substitute.
-  ///
-  /// \param Outputs Will receive all of the substituted arguments.
+  /// Try to resolve an undeclared template name as a type template.
   ///
-  /// \returns true if an error occurred, false otherwise.
-  bool SubstExprs(ArrayRef Exprs, bool IsCall,
-                  const MultiLevelTemplateArgumentList &TemplateArgs,
-                  SmallVectorImpl &Outputs);
+  /// 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);
 
-  StmtResult SubstStmt(Stmt *S,
-                       const MultiLevelTemplateArgumentList &TemplateArgs);
+  bool resolveAssumedTemplateNameAsType(Scope *S, TemplateName &Name,
+                                        SourceLocation NameLoc,
+                                        bool Diagnose = true);
 
-  TemplateParameterList *
-  SubstTemplateParams(TemplateParameterList *Params, DeclContext *Owner,
-                      const MultiLevelTemplateArgumentList &TemplateArgs,
-                      bool EvaluateConstraints = true);
+  /// 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
-  SubstTemplateArguments(ArrayRef Args,
-                         const MultiLevelTemplateArgumentList &TemplateArgs,
-                         TemplateArgumentListInfo &Outputs);
+  bool DiagnoseUnknownTemplateName(const IdentifierInfo &II,
+                                   SourceLocation IILoc, Scope *S,
+                                   const CXXScopeSpec *SS,
+                                   TemplateTy &SuggestedTemplate,
+                                   TemplateNameKind &SuggestedKind);
 
-  Decl *SubstDecl(Decl *D, DeclContext *Owner,
-                  const MultiLevelTemplateArgumentList &TemplateArgs);
+  bool DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation,
+                                      NamedDecl *Instantiation,
+                                      bool InstantiatedFromMember,
+                                      const NamedDecl *Pattern,
+                                      const NamedDecl *PatternDef,
+                                      TemplateSpecializationKind TSK,
+                                      bool Complain = true);
 
-  /// Substitute the name and return type of a defaulted 'operator<=>' to form
-  /// an implicit 'operator=='.
-  FunctionDecl *SubstSpaceshipAsEqualEqual(CXXRecordDecl *RD,
-                                           FunctionDecl *Spaceship);
+  /// 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);
 
-  ExprResult SubstInitializer(Expr *E,
-                       const MultiLevelTemplateArgumentList &TemplateArgs,
-                       bool CXXDirectInit);
+  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
-  SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
-                      CXXRecordDecl *Pattern,
-                      const MultiLevelTemplateArgumentList &TemplateArgs);
+  bool CheckTypeConstraint(TemplateIdAnnotation *TypeConstraint);
 
-  bool
-  InstantiateClass(SourceLocation PointOfInstantiation,
-                   CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
-                   const MultiLevelTemplateArgumentList &TemplateArgs,
-                   TemplateSpecializationKind TSK,
-                   bool Complain = true);
+  bool ActOnTypeConstraint(const CXXScopeSpec &SS,
+                           TemplateIdAnnotation *TypeConstraint,
+                           TemplateTypeParmDecl *ConstrainedParameter,
+                           SourceLocation EllipsisLoc);
+  bool BuildTypeConstraint(const CXXScopeSpec &SS,
+                           TemplateIdAnnotation *TypeConstraint,
+                           TemplateTypeParmDecl *ConstrainedParameter,
+                           SourceLocation EllipsisLoc,
+                           bool AllowUnexpandedPack);
 
-  bool InstantiateEnum(SourceLocation PointOfInstantiation,
-                       EnumDecl *Instantiation, EnumDecl *Pattern,
-                       const MultiLevelTemplateArgumentList &TemplateArgs,
-                       TemplateSpecializationKind TSK);
+  bool AttachTypeConstraint(NestedNameSpecifierLoc NS,
+                            DeclarationNameInfo NameInfo,
+                            ConceptDecl *NamedConcept,
+                            const TemplateArgumentListInfo *TemplateArgs,
+                            TemplateTypeParmDecl *ConstrainedParameter,
+                            SourceLocation EllipsisLoc);
 
-  bool InstantiateInClassInitializer(
-      SourceLocation PointOfInstantiation, FieldDecl *Instantiation,
-      FieldDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs);
+  bool AttachTypeConstraint(AutoTypeLoc TL,
+                            NonTypeTemplateParmDecl *NewConstrainedParm,
+                            NonTypeTemplateParmDecl *OrigConstrainedParm,
+                            SourceLocation EllipsisLoc);
 
-  struct LateInstantiatedAttribute {
-    const Attr *TmplAttr;
-    LocalInstantiationScope *Scope;
-    Decl *NewDecl;
+  bool RequireStructuralType(QualType T, SourceLocation Loc);
 
-    LateInstantiatedAttribute(const Attr *A, LocalInstantiationScope *S,
-                              Decl *D)
-      : TmplAttr(A), Scope(S), NewDecl(D)
-    { }
-  };
-  typedef SmallVector LateInstantiatedAttrVec;
+  QualType CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI,
+                                             SourceLocation Loc);
+  QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc);
 
-  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);
+  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);
 
-  void InstantiateDefaultCtorDefaultArgs(CXXConstructorDecl *Ctor);
+  /// 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 usesPartialOrExplicitSpecialization(
-      SourceLocation Loc, ClassTemplateSpecializationDecl *ClassTemplateSpec);
+  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);
 
-  bool
-  InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation,
-                           ClassTemplateSpecializationDecl *ClassTemplateSpec,
-                           TemplateSpecializationKind TSK,
-                           bool Complain = true);
+  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 InstantiateClassMembers(SourceLocation PointOfInstantiation,
-                               CXXRecordDecl *Instantiation,
-                            const MultiLevelTemplateArgumentList &TemplateArgs,
-                               TemplateSpecializationKind TSK);
+  void translateTemplateArguments(const ASTTemplateArgsPtr &In,
+                                  TemplateArgumentListInfo &Out);
 
-  void InstantiateClassTemplateSpecializationMembers(
-                                          SourceLocation PointOfInstantiation,
-                           ClassTemplateSpecializationDecl *ClassTemplateSpec,
-                                                TemplateSpecializationKind TSK);
+  ParsedTemplateArgument ActOnTemplateTypeArgument(TypeResult ParsedType);
 
-  NestedNameSpecifierLoc
-  SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
-                           const MultiLevelTemplateArgumentList &TemplateArgs);
+  void NoteAllFoundTemplates(TemplateName Name);
 
-  DeclarationNameInfo
-  SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo,
-                           const MultiLevelTemplateArgumentList &TemplateArgs);
-  TemplateName
-  SubstTemplateName(NestedNameSpecifierLoc QualifierLoc, TemplateName Name,
-                    SourceLocation Loc,
-                    const MultiLevelTemplateArgumentList &TemplateArgs);
+  QualType CheckTemplateIdType(TemplateName Template,
+                               SourceLocation TemplateLoc,
+                               TemplateArgumentListInfo &TemplateArgs);
 
-  bool SubstTypeConstraint(TemplateTypeParmDecl *Inst, const TypeConstraint *TC,
-                           const MultiLevelTemplateArgumentList &TemplateArgs,
-                           bool EvaluateConstraint);
+  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);
 
-  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);
+  /// 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);
 
-  void InstantiateVariableInitializer(
-      VarDecl *Var, VarDecl *OldVar,
-      const MultiLevelTemplateArgumentList &TemplateArgs);
-  void InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
-                                     VarDecl *Var, bool Recursive = false,
-                                     bool DefinitionRequired = false,
-                                     bool AtEndOfTU = false);
+  DeclResult ActOnVarTemplateSpecialization(
+      Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous,
+      SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
+      StorageClass SC, bool IsPartialSpecialization);
 
-  void InstantiateMemInitializers(CXXConstructorDecl *New,
-                                  const CXXConstructorDecl *Tmpl,
-                            const MultiLevelTemplateArgumentList &TemplateArgs);
+  /// 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);
 
-  ExplicitSpecifier instantiateExplicitSpecifier(
-      const MultiLevelTemplateArgumentList &TemplateArgs, ExplicitSpecifier ES);
+  /// 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);
 
-  NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
-                          const MultiLevelTemplateArgumentList &TemplateArgs,
-                          bool FindingInstantiatedContext = false);
-  DeclContext *FindInstantiatedContext(SourceLocation Loc, DeclContext *DC,
-                          const MultiLevelTemplateArgumentList &TemplateArgs);
+  ExprResult
+  CheckConceptTemplateId(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+                         const DeclarationNameInfo &ConceptNameInfo,
+                         NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
+                         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;
+  void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);
 
-  DeclResult actOnObjCTypeParam(Scope *S,
-                                ObjCTypeParamVariance variance,
-                                SourceLocation varianceLoc,
-                                unsigned index,
-                                IdentifierInfo *paramName,
-                                SourceLocation paramLoc,
-                                SourceLocation colonLoc,
-                                ParsedType typeBound);
+  ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
+                                 SourceLocation TemplateKWLoc, LookupResult &R,
+                                 bool RequiresADL,
+                                 const TemplateArgumentListInfo *TemplateArgs);
 
-  ObjCTypeParamList *actOnObjCTypeParamList(Scope *S, SourceLocation lAngleLoc,
-                                            ArrayRef typeParams,
-                                            SourceLocation rAngleLoc);
-  void popObjCTypeParamList(Scope *S, ObjCTypeParamList *typeParamList);
+  ExprResult
+  BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+                               const DeclarationNameInfo &NameInfo,
+                               const TemplateArgumentListInfo *TemplateArgs);
 
-  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);
+  TemplateNameKind ActOnTemplateName(Scope *S, CXXScopeSpec &SS,
+                                     SourceLocation TemplateKWLoc,
+                                     const UnqualifiedId &Name,
+                                     ParsedType ObjectType,
+                                     bool EnteringContext, TemplateTy &Template,
+                                     bool AllowInjectedClassName = false);
 
-  void ActOnSuperClassOfClassInterface(Scope *S,
-                                       SourceLocation AtInterfaceLoc,
-                                       ObjCInterfaceDecl *IDecl,
-                                       IdentifierInfo *ClassName,
-                                       SourceLocation ClassLoc,
-                                       IdentifierInfo *SuperName,
-                                       SourceLocation SuperLoc,
-                                       ArrayRef SuperTypeArgs,
-                                       SourceRange SuperTypeArgsRange);
+  DeclResult ActOnClassTemplateSpecialization(
+      Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
+      SourceLocation ModulePrivateLoc, CXXScopeSpec &SS,
+      TemplateIdAnnotation &TemplateId, const ParsedAttributesView &Attr,
+      MultiTemplateParamsArg TemplateParameterLists,
+      SkipBodyInfo *SkipBody = nullptr);
 
-  void ActOnTypedefedProtocols(SmallVectorImpl &ProtocolRefs,
-                               SmallVectorImpl &ProtocolLocs,
-                               IdentifierInfo *SuperName,
-                               SourceLocation SuperLoc);
+  bool CheckTemplatePartialSpecializationArgs(SourceLocation Loc,
+                                              TemplateDecl *PrimaryTemplate,
+                                              unsigned NumExplicitArgs,
+                                              ArrayRef Args);
+  void CheckTemplatePartialSpecialization(
+      ClassTemplatePartialSpecializationDecl *Partial);
+  void CheckTemplatePartialSpecialization(
+      VarTemplatePartialSpecializationDecl *Partial);
 
-  Decl *ActOnCompatibilityAlias(
-                    SourceLocation AtCompatibilityAliasLoc,
-                    IdentifierInfo *AliasName,  SourceLocation AliasLocation,
-                    IdentifierInfo *ClassName, SourceLocation ClassLocation);
+  Decl *ActOnTemplateDeclarator(Scope *S,
+                                MultiTemplateParamsArg TemplateParameterLists,
+                                Declarator &D);
 
-  bool CheckForwardProtocolDeclarationForCircularDependency(
-    IdentifierInfo *PName,
-    SourceLocation &PLoc, SourceLocation PrevLoc,
-    const ObjCList &PList);
+  bool CheckSpecializationInstantiationRedecl(
+      SourceLocation NewLoc,
+      TemplateSpecializationKind ActOnExplicitInstantiationNewTSK,
+      NamedDecl *PrevDecl, TemplateSpecializationKind PrevTSK,
+      SourceLocation PrevPtOfInstantiation, bool &SuppressNew);
 
-  ObjCProtocolDecl *ActOnStartProtocolInterface(
-      SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName,
-      SourceLocation ProtocolLoc, Decl *const *ProtoRefNames,
-      unsigned NumProtoRefs, const SourceLocation *ProtoLocs,
-      SourceLocation EndProtoLoc, const ParsedAttributesView &AttrList,
-      SkipBodyInfo *SkipBody);
+  bool CheckDependentFunctionTemplateSpecialization(
+      FunctionDecl *FD, const TemplateArgumentListInfo *ExplicitTemplateArgs,
+      LookupResult &Previous);
 
-  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);
+  bool CheckFunctionTemplateSpecialization(
+      FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs,
+      LookupResult &Previous, bool QualifiedFriend = false);
+  bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
+  void CompleteMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
 
-  ObjCImplementationDecl *ActOnStartClassImplementation(
-      SourceLocation AtClassImplLoc, IdentifierInfo *ClassName,
-      SourceLocation ClassLoc, IdentifierInfo *SuperClassname,
-      SourceLocation SuperClassLoc, const ParsedAttributesView &AttrList);
+  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);
 
-  ObjCCategoryImplDecl *ActOnStartCategoryImplementation(
-      SourceLocation AtCatImplLoc, IdentifierInfo *ClassName,
-      SourceLocation ClassLoc, IdentifierInfo *CatName, SourceLocation CatLoc,
-      const ParsedAttributesView &AttrList);
+  DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc,
+                                        SourceLocation TemplateLoc,
+                                        unsigned TagSpec, SourceLocation KWLoc,
+                                        CXXScopeSpec &SS, IdentifierInfo *Name,
+                                        SourceLocation NameLoc,
+                                        const ParsedAttributesView &Attr);
 
-  DeclGroupPtrTy ActOnFinishObjCImplementation(Decl *ObjCImpDecl,
-                                               ArrayRef Decls);
+  DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc,
+                                        SourceLocation TemplateLoc,
+                                        Declarator &D);
 
-  DeclGroupPtrTy ActOnForwardClassDeclaration(SourceLocation Loc,
-                   IdentifierInfo **IdentList,
-                   SourceLocation *IdentLocs,
-                   ArrayRef TypeParamLists,
-                   unsigned NumElts);
+  TemplateArgumentLoc SubstDefaultTemplateArgumentIfAvailable(
+      TemplateDecl *Template, SourceLocation TemplateLoc,
+      SourceLocation RAngleLoc, Decl *Param,
+      ArrayRef SugaredConverted,
+      ArrayRef CanonicalConverted, bool &HasDefaultArg);
 
-  DeclGroupPtrTy
-  ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc,
-                                  ArrayRef IdentList,
-                                  const ParsedAttributesView &attrList);
+  SourceLocation getTopMostPointOfInstantiation(const NamedDecl *) const;
 
-  void FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
-                               ArrayRef ProtocolId,
-                               SmallVectorImpl &Protocols);
+  /// 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,
 
-  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);
-
-  /// 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);
+    /// The template argument was deduced via template argument
+    /// deduction.
+    CTAK_Deduced,
 
-  /// Build an Objective-C type parameter type.
-  QualType BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl,
-                                  SourceLocation ProtocolLAngleLoc,
-                                  ArrayRef Protocols,
-                                  ArrayRef ProtocolLocs,
-                                  SourceLocation ProtocolRAngleLoc,
-                                  bool FailOnError = false);
+    /// The template argument was deduced from an array bound
+    /// via template argument deduction.
+    CTAK_DeducedFromArrayBound
+  };
 
-  /// 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);
+  bool
+  CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &Arg,
+                        NamedDecl *Template, SourceLocation TemplateLoc,
+                        SourceLocation RAngleLoc, unsigned ArgumentPackIndex,
+                        SmallVectorImpl &SugaredConverted,
+                        SmallVectorImpl &CanonicalConverted,
+                        CheckTemplateArgumentKind CTAK);
 
-  /// 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);
+  /// 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);
 
-  /// 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);
+  bool CheckTemplateTypeArgument(
+      TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg,
+      SmallVectorImpl &SugaredConverted,
+      SmallVectorImpl &CanonicalConverted);
 
+  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);
 
-  void DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
-                                ObjCPropertyDecl *SuperProperty,
-                                const IdentifierInfo *Name,
-                                bool OverridingProtocolProperty);
+  void NoteTemplateLocation(const NamedDecl &Decl,
+                            std::optional ParamRange = {});
+  void NoteTemplateParameterLocation(const NamedDecl &Decl);
 
-  void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
-                                        ObjCInterfaceDecl *ID);
+  ExprResult BuildExpressionFromDeclTemplateArgument(
+      const TemplateArgument &Arg, QualType ParamType, SourceLocation Loc);
+  ExprResult
+  BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
+                                             SourceLocation Loc);
 
-  Decl *ActOnAtEnd(Scope *S, SourceRange AtEnd,
-                   ArrayRef allMethods = std::nullopt,
-                   ArrayRef allTUVars = std::nullopt);
+  /// 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,
 
-  Decl *ActOnProperty(Scope *S, SourceLocation AtLoc,
-                      SourceLocation LParenLoc,
-                      FieldDeclarator &FD, ObjCDeclSpec &ODS,
-                      Selector GetterSel, Selector SetterSel,
-                      tok::ObjCKeywordKind MethodImplKind,
-                      DeclContext *lexicalDC = nullptr);
+    /// 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,
 
-  Decl *ActOnPropertyImplDecl(Scope *S,
-                              SourceLocation AtLoc,
-                              SourceLocation PropertyLoc,
-                              bool ImplKind,
-                              IdentifierInfo *PropertyId,
-                              IdentifierInfo *PropertyIvar,
-                              SourceLocation PropertyIvarLoc,
-                              ObjCPropertyQueryKind QueryKind);
+    /// 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,
 
-  enum ObjCSpecialMethodKind {
-    OSMK_None,
-    OSMK_Alloc,
-    OSMK_New,
-    OSMK_Copy,
-    OSMK_RetainingInit,
-    OSMK_NonRetainingInit
+    /// 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,
   };
 
-  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;
-  };
+  // 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;
 
-  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);
+  public:
+    TemplateCompareNewDeclInfo(const NamedDecl *ND) : ND(ND) {}
+    TemplateCompareNewDeclInfo(const DeclContext *DeclCtx,
+                               const DeclContext *LexicalDeclCtx,
+                               SourceLocation Loc)
 
-  ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel,
-                                              const ObjCObjectPointerType *OPT,
-                                              bool IsInstance);
-  ObjCMethodDecl *LookupMethodInObjectType(Selector Sel, QualType Ty,
-                                           bool IsInstance);
+        : DC(DeclCtx), LexicalDC(LexicalDeclCtx), Loc(Loc) {
+      assert(DC && LexicalDC &&
+             "Constructor only for cases where we have the information to put "
+             "in here");
+    }
 
-  bool CheckARCMethodDecl(ObjCMethodDecl *method);
-  bool inferObjCARCLifetime(ValueDecl *decl);
+    // 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; }
 
-  void deduceOpenCLAddressSpace(ValueDecl *decl);
+    const NamedDecl *getDecl() const { return ND; }
 
-  ExprResult
-  HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
-                            Expr *BaseExpr,
-                            SourceLocation OpLoc,
-                            DeclarationName MemberName,
-                            SourceLocation MemberLoc,
-                            SourceLocation SuperLoc, QualType SuperType,
-                            bool Super);
+    bool ContainsDecl(const NamedDecl *ND) const { return this->ND == ND; }
 
-  ExprResult
-  ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
-                            IdentifierInfo &propertyName,
-                            SourceLocation receiverNameLoc,
-                            SourceLocation propertyNameLoc);
+    const DeclContext *getLexicalDeclContext() const {
+      return ND ? ND->getLexicalDeclContext() : LexicalDC;
+    }
 
-  ObjCMethodDecl *tryCaptureObjCSelf(SourceLocation Loc);
+    const DeclContext *getDeclContext() const {
+      return ND ? ND->getDeclContext() : DC;
+    }
 
-  /// 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
+    SourceLocation getLocation() const { return ND ? ND->getLocation() : Loc; }
   };
 
-  ObjCMessageKind getObjCMessageKind(Scope *S,
-                                     IdentifierInfo *Name,
-                                     SourceLocation NameLoc,
-                                     bool IsSuper,
-                                     bool HasTrailingDot,
-                                     ParsedType &ReceiverType);
+  bool TemplateParameterListsAreEqual(
+      const TemplateCompareNewDeclInfo &NewInstFrom, TemplateParameterList *New,
+      const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain,
+      TemplateParameterListEqualKind Kind,
+      SourceLocation TemplateArgLoc = SourceLocation());
 
-  ExprResult ActOnSuperMessage(Scope *S, SourceLocation SuperLoc,
-                               Selector Sel,
-                               SourceLocation LBracLoc,
-                               ArrayRef SelectorLocs,
-                               SourceLocation RBracLoc,
-                               MultiExprArg Args);
+  bool TemplateParameterListsAreEqual(
+      TemplateParameterList *New, TemplateParameterList *Old, bool Complain,
+      TemplateParameterListEqualKind Kind,
+      SourceLocation TemplateArgLoc = SourceLocation()) {
+    return TemplateParameterListsAreEqual(nullptr, New, nullptr, Old, Complain,
+                                          Kind, TemplateArgLoc);
+  }
 
-  ExprResult BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
-                               QualType ReceiverType,
-                               SourceLocation SuperLoc,
-                               Selector Sel,
-                               ObjCMethodDecl *Method,
-                               SourceLocation LBracLoc,
-                               ArrayRef SelectorLocs,
-                               SourceLocation RBracLoc,
-                               MultiExprArg Args,
-                               bool isImplicit = false);
+  bool CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams);
 
-  ExprResult BuildClassMessageImplicit(QualType ReceiverType,
-                                       bool isSuperReceiver,
-                                       SourceLocation Loc,
-                                       Selector Sel,
-                                       ObjCMethodDecl *Method,
-                                       MultiExprArg Args);
+  /// 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 ActOnClassMessage(Scope *S,
-                               ParsedType Receiver,
-                               Selector Sel,
-                               SourceLocation LBracLoc,
-                               ArrayRef SelectorLocs,
-                               SourceLocation RBracLoc,
-                               MultiExprArg Args);
+  /// 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);
 
-  ExprResult BuildInstanceMessage(Expr *Receiver,
-                                  QualType ReceiverType,
-                                  SourceLocation SuperLoc,
-                                  Selector Sel,
-                                  ObjCMethodDecl *Method,
-                                  SourceLocation LBracLoc,
-                                  ArrayRef SelectorLocs,
-                                  SourceLocation RBracLoc,
-                                  MultiExprArg Args,
-                                  bool isImplicit = false);
+  QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
+                             SourceLocation KeywordLoc,
+                             NestedNameSpecifierLoc QualifierLoc,
+                             const IdentifierInfo &II, SourceLocation IILoc,
+                             TypeSourceInfo **TSI, bool DeducedTSTContext);
 
-  ExprResult BuildInstanceMessageImplicit(Expr *Receiver,
-                                          QualType ReceiverType,
-                                          SourceLocation Loc,
-                                          Selector Sel,
-                                          ObjCMethodDecl *Method,
-                                          MultiExprArg Args);
+  QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
+                             SourceLocation KeywordLoc,
+                             NestedNameSpecifierLoc QualifierLoc,
+                             const IdentifierInfo &II, SourceLocation IILoc,
+                             bool DeducedTSTContext = true);
 
-  ExprResult ActOnInstanceMessage(Scope *S,
-                                  Expr *Receiver,
-                                  Selector Sel,
-                                  SourceLocation LBracLoc,
-                                  ArrayRef SelectorLocs,
-                                  SourceLocation RBracLoc,
-                                  MultiExprArg Args);
+  TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
+                                                    SourceLocation Loc,
+                                                    DeclarationName Name);
+  bool RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS);
 
-  ExprResult BuildObjCBridgedCast(SourceLocation LParenLoc,
-                                  ObjCBridgeCastKind Kind,
-                                  SourceLocation BridgeKeywordLoc,
-                                  TypeSourceInfo *TSInfo,
-                                  Expr *SubExpr);
+  ExprResult RebuildExprInCurrentInstantiation(Expr *E);
+  bool
+  RebuildTemplateParamsInCurrentInstantiation(TemplateParameterList *Params);
 
-  ExprResult ActOnObjCBridgedCast(Scope *S,
-                                  SourceLocation LParenLoc,
-                                  ObjCBridgeCastKind Kind,
-                                  SourceLocation BridgeKeywordLoc,
-                                  ParsedType Type,
-                                  SourceLocation RParenLoc,
-                                  Expr *SubExpr);
+  std::string
+  getTemplateArgumentBindingsText(const TemplateParameterList *Params,
+                                  const TemplateArgumentList &Args);
 
-  void CheckTollFreeBridgeCast(QualType castType, Expr *castExpr);
+  std::string
+  getTemplateArgumentBindingsText(const TemplateParameterList *Params,
+                                  const TemplateArgument *Args,
+                                  unsigned NumArgs);
 
-  void CheckObjCBridgeRelatedCast(QualType castType, Expr *castExpr);
+  void diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName,
+                                          SourceLocation Less,
+                                          SourceLocation Greater);
 
-  bool CheckTollFreeBridgeStaticCast(QualType castType, Expr *castExpr,
-                                     CastKind &Kind);
+  ExprResult ActOnDependentIdExpression(
+      const CXXScopeSpec &SS, SourceLocation TemplateKWLoc,
+      const DeclarationNameInfo &NameInfo, bool isAddressOfOperand,
+      const TemplateArgumentListInfo *TemplateArgs);
 
-  bool checkObjCBridgeRelatedComponents(SourceLocation Loc,
-                                        QualType DestType, QualType SrcType,
-                                        ObjCInterfaceDecl *&RelatedClass,
-                                        ObjCMethodDecl *&ClassMethod,
-                                        ObjCMethodDecl *&InstanceMethod,
-                                        TypedefNameDecl *&TDNDecl,
-                                        bool CfToNs, bool Diagnose = true);
+  ExprResult
+  BuildDependentDeclRefExpr(const CXXScopeSpec &SS,
+                            SourceLocation TemplateKWLoc,
+                            const DeclarationNameInfo &NameInfo,
+                            const TemplateArgumentListInfo *TemplateArgs);
 
-  bool CheckObjCBridgeRelatedConversions(SourceLocation Loc,
-                                         QualType DestType, QualType SrcType,
-                                         Expr *&SrcExpr, bool Diagnose = true);
+  // 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);
 
-  bool CheckConversionToObjCLiteral(QualType DstType, Expr *&SrcExpr,
-                                    bool Diagnose = true);
+  /// 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);
 
-  bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall);
+  /// Find the failed Boolean condition within a given Boolean
+  /// constant expression, and describe it with a string.
+  std::pair findFailedBooleanCondition(Expr *Cond);
 
-  /// 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);
+  void CheckDeductionGuideTemplate(FunctionTemplateDecl *TD);
 
-  /// Describes the compatibility of a result type with its method.
-  enum ResultTypeCompatibilityKind {
-    RTC_Compatible,
-    RTC_Incompatible,
-    RTC_Unknown
-  };
+  Decl *ActOnConceptDefinition(Scope *S,
+                               MultiTemplateParamsArg TemplateParameterLists,
+                               IdentifierInfo *Name, SourceLocation NameLoc,
+                               Expr *ConstraintExpr);
 
-  void CheckObjCMethodDirectOverrides(ObjCMethodDecl *method,
-                                      ObjCMethodDecl *overridden);
+  void CheckConceptRedefinition(ConceptDecl *NewDecl, LookupResult &Previous,
+                                bool &AddToScope);
 
-  void CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod,
-                                ObjCInterfaceDecl *CurrentClass,
-                                ResultTypeCompatibilityKind RTC);
+  TypeResult ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
+                               const CXXScopeSpec &SS, IdentifierInfo *Name,
+                               SourceLocation TagLoc, SourceLocation NameLoc);
 
-  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
-  };
+  void MarkAsLateParsedTemplate(FunctionDecl *FD, Decl *FnD,
+                                CachedTokens &Toks);
+  void UnmarkAsLateParsedTemplate(FunctionDecl *FD);
+  bool IsInsideALocalClassWithinATemplateFunction();
 
-  /// ActOnPragmaClangSection - Called on well formed \#pragma clang section
-  void ActOnPragmaClangSection(SourceLocation PragmaLoc,
-                               PragmaClangSectionAction Action,
-                               PragmaClangSectionKind SecKind, StringRef SecName);
+  /// 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);
 
-  /// ActOnPragmaOptionsAlign - Called on well formed \#pragma options align.
-  void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
-                               SourceLocation PragmaLoc);
+  ///@}
 
-  /// ActOnPragmaPack - Called on well formed \#pragma pack(...).
-  void ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
-                       StringRef SlotLabel, Expr *Alignment);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  enum class PragmaAlignPackDiagnoseKind {
-    NonDefaultStateAtInclude,
-    ChangedStateAtExit
-  };
+  /// \name C++ Template Argument Deduction
+  /// Implementations are in SemaTemplateDeduction.cpp
+  ///@{
 
-  void DiagnoseNonDefaultPragmaAlignPack(PragmaAlignPackDiagnoseKind Kind,
-                                         SourceLocation IncludeLoc);
-  void DiagnoseUnterminatedPragmaAlignPack();
+public:
+  /// When true, access checking violations are treated as SFINAE
+  /// failures rather than hard errors.
+  bool AccessCheckingSFINAE;
 
-  /// ActOnPragmaMSStrictGuardStackCheck - Called on well formed \#pragma
-  /// strict_gs_check.
-  void ActOnPragmaMSStrictGuardStackCheck(SourceLocation PragmaLocation,
-                                          PragmaMsStackAction Action,
-                                          bool Value);
+  /// 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;
 
-  /// ActOnPragmaMSStruct - Called on well formed \#pragma ms_struct [on|off].
-  void ActOnPragmaMSStruct(PragmaMSStructKind Kind);
+  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;
+    }
 
-  /// ActOnPragmaMSComment - Called on well formed
-  /// \#pragma comment(kind, "arg").
-  void ActOnPragmaMSComment(SourceLocation CommentLoc, PragmaMSCommentKind Kind,
-                            StringRef Arg);
+    ~SFINAETrap() {
+      SemaRef.NumSFINAEErrors = PrevSFINAEErrors;
+      SemaRef.InNonInstantiationSFINAEContext =
+          PrevInNonInstantiationSFINAEContext;
+      SemaRef.AccessCheckingSFINAE = PrevAccessCheckingSFINAE;
+      SemaRef.getDiagnostics().setLastDiagnosticIgnored(
+          PrevLastDiagnosticIgnored);
+    }
 
-  /// ActOnPragmaMSPointersToMembers - called on well formed \#pragma
-  /// pointers_to_members(representation method[, general purpose
-  /// representation]).
-  void ActOnPragmaMSPointersToMembers(
-      LangOptions::PragmaMSPointersToMembersKind Kind,
-      SourceLocation PragmaLoc);
+    /// Determine whether any SFINAE errors have been trapped.
+    bool hasErrorOccurred() const {
+      return SemaRef.NumSFINAEErrors > PrevSFINAEErrors;
+    }
+  };
 
-  /// Called on well formed \#pragma vtordisp().
-  void ActOnPragmaMSVtorDisp(PragmaMsStackAction Action,
-                             SourceLocation PragmaLoc,
-                             MSVtorDispMode Value);
+  /// 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 PragmaSectionKind {
-    PSK_DataSeg,
-    PSK_BSSSeg,
-    PSK_ConstSeg,
-    PSK_CodeSeg,
+  public:
+    explicit TentativeAnalysisScope(Sema &SemaRef)
+        : SemaRef(SemaRef), Trap(SemaRef, true),
+          PrevDisableTypoCorrection(SemaRef.DisableTypoCorrection) {
+      SemaRef.DisableTypoCorrection = true;
+    }
+    ~TentativeAnalysisScope() {
+      SemaRef.DisableTypoCorrection = PrevDisableTypoCorrection;
+    }
   };
 
-  bool UnifySection(StringRef SectionName, int SectionFlags,
-                    NamedDecl *TheDecl);
-  bool UnifySection(StringRef SectionName,
-                    int SectionFlags,
-                    SourceLocation PragmaSectionLocation);
+  /// 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;
 
-  /// 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);
-
-  /// Called on well formed \#pragma section().
-  void ActOnPragmaMSSection(SourceLocation PragmaLocation,
-                            int SectionFlags, StringLiteral *SegmentName);
-
-  /// Called on well-formed \#pragma init_seg().
-  void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation,
-                            StringLiteral *SegmentName);
+  bool isSameOrCompatibleFunctionType(QualType Param, QualType Arg);
 
-  /// Called on well-formed \#pragma alloc_text().
-  void ActOnPragmaMSAllocText(
-      SourceLocation PragmaLocation, StringRef Section,
-      const SmallVector>
-          &Functions);
+  TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,
+                                                    QualType NTTPType,
+                                                    SourceLocation Loc);
 
-  /// Called on #pragma clang __debug dump II
-  void ActOnPragmaDump(Scope *S, SourceLocation Loc, IdentifierInfo *II);
+  /// 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);
 
-  /// Called on #pragma clang __debug dump E
-  void ActOnPragmaDump(Expr *E);
+  /// 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);
 
-  /// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch
-  void ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name,
-                                 StringRef Value);
+  TemplateDeductionResult
+  DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
+                          ArrayRef TemplateArgs,
+                          sema::TemplateDeductionInfo &Info);
 
-  /// Are precise floating point semantics currently enabled?
-  bool isPreciseFPEnabled() {
-    return !CurFPFeatures.getAllowFPReassociate() &&
-           !CurFPFeatures.getNoSignedZero() &&
-           !CurFPFeatures.getAllowReciprocal() &&
-           !CurFPFeatures.getAllowApproxFunc();
-  }
+  TemplateDeductionResult
+  DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
+                          ArrayRef TemplateArgs,
+                          sema::TemplateDeductionInfo &Info);
 
-  void ActOnPragmaFPEvalMethod(SourceLocation Loc,
-                               LangOptions::FPEvalMethodKind Value);
+  TemplateDeductionResult SubstituteExplicitTemplateArguments(
+      FunctionTemplateDecl *FunctionTemplate,
+      TemplateArgumentListInfo &ExplicitTemplateArgs,
+      SmallVectorImpl &Deduced,
+      SmallVectorImpl &ParamTypes, QualType *FunctionType,
+      sema::TemplateDeductionInfo &Info);
 
-  /// ActOnPragmaFloatControl - Call on well-formed \#pragma float_control
-  void ActOnPragmaFloatControl(SourceLocation Loc, PragmaMsStackAction Action,
-                               PragmaFloatControlKind Value);
+  /// 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) {}
 
-  /// ActOnPragmaUnused - Called on well-formed '\#pragma unused'.
-  void ActOnPragmaUnused(const Token &Identifier,
-                         Scope *curScope,
-                         SourceLocation PragmaLoc);
+    QualType OriginalParamType;
+    bool DecomposedParam;
+    unsigned ArgIdx;
+    QualType OriginalArgType;
+  };
 
-  /// ActOnPragmaVisibility - Called on well formed \#pragma GCC visibility... .
-  void ActOnPragmaVisibility(const IdentifierInfo* VisType,
-                             SourceLocation PragmaLoc);
+  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; });
 
-  NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, const IdentifierInfo *II,
-                                 SourceLocation Loc);
-  void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, const WeakInfo &W);
+  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);
 
-  /// ActOnPragmaWeakID - Called on well formed \#pragma weak ident.
-  void ActOnPragmaWeakID(IdentifierInfo* WeakName,
-                         SourceLocation PragmaLoc,
-                         SourceLocation WeakNameLoc);
+  TemplateDeductionResult DeduceTemplateArguments(
+      FunctionTemplateDecl *FunctionTemplate,
+      TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ArgFunctionType,
+      FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info,
+      bool IsAddressOfFunction = false);
 
-  /// ActOnPragmaRedefineExtname - Called on well formed
-  /// \#pragma redefine_extname oldname newname.
-  void ActOnPragmaRedefineExtname(IdentifierInfo* WeakName,
-                                  IdentifierInfo* AliasName,
-                                  SourceLocation PragmaLoc,
-                                  SourceLocation WeakNameLoc,
-                                  SourceLocation AliasNameLoc);
+  TemplateDeductionResult DeduceTemplateArguments(
+      FunctionTemplateDecl *FunctionTemplate, QualType ObjectType,
+      Expr::Classification ObjectClassification, QualType ToType,
+      CXXConversionDecl *&Specialization, sema::TemplateDeductionInfo &Info);
 
-  /// ActOnPragmaWeakAlias - Called on well formed \#pragma weak ident = ident.
-  void ActOnPragmaWeakAlias(IdentifierInfo* WeakName,
-                            IdentifierInfo* AliasName,
-                            SourceLocation PragmaLoc,
-                            SourceLocation WeakNameLoc,
-                            SourceLocation AliasNameLoc);
+  TemplateDeductionResult
+  DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+                          TemplateArgumentListInfo *ExplicitTemplateArgs,
+                          FunctionDecl *&Specialization,
+                          sema::TemplateDeductionInfo &Info,
+                          bool IsAddressOfFunction = false);
 
-  /// ActOnPragmaFPContract - Called on well formed
-  /// \#pragma {STDC,OPENCL} FP_CONTRACT and
-  /// \#pragma clang fp contract
-  void ActOnPragmaFPContract(SourceLocation Loc, LangOptions::FPModeKind FPC);
+  /// 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);
 
-  /// Called on well formed
-  /// \#pragma clang fp reassociate
-  /// or
-  /// \#pragma clang fp reciprocal
-  void ActOnPragmaFPValueChangingOption(SourceLocation Loc, PragmaFPKind Kind,
-                                        bool IsEnabled);
+  // Substitute auto in TypeWithAuto for a Dependent auto type
+  QualType SubstAutoTypeDependent(QualType TypeWithAuto);
 
-  /// ActOnPragmaFenvAccess - Called on well formed
-  /// \#pragma STDC FENV_ACCESS
-  void ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled);
+  // Substitute auto in TypeWithAuto for a Dependent auto type
+  TypeSourceInfo *
+  SubstAutoTypeSourceInfoDependent(TypeSourceInfo *TypeWithAuto);
 
-  /// ActOnPragmaCXLimitedRange - Called on well formed
-  /// \#pragma STDC CX_LIMITED_RANGE
-  void ActOnPragmaCXLimitedRange(SourceLocation Loc,
-                                 LangOptions::ComplexRangeKind Range);
+  /// 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);
 
-  /// Called on well formed '\#pragma clang fp' that has option 'exceptions'.
-  void ActOnPragmaFPExceptions(SourceLocation Loc,
-                               LangOptions::FPExceptionModeKind);
+  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);
 
-  /// Called to set constant rounding mode for floating point operations.
-  void ActOnPragmaFEnvRound(SourceLocation Loc, llvm::RoundingMode);
+  bool CheckIfFunctionSpecializationIsImmediate(FunctionDecl *FD,
+                                                SourceLocation Loc);
 
-  /// Called to set exception behavior for floating point operations.
-  void setExceptionMode(SourceLocation Loc, LangOptions::FPExceptionModeKind);
+  ClassTemplatePartialSpecializationDecl *
+  getMoreSpecializedPartialSpecialization(
+      ClassTemplatePartialSpecializationDecl *PS1,
+      ClassTemplatePartialSpecializationDecl *PS2, SourceLocation Loc);
 
-  /// AddAlignmentAttributesForRecord - Adds any needed alignment attributes to
-  /// a the record decl, to handle '\#pragma pack' and '\#pragma options align'.
-  void AddAlignmentAttributesForRecord(RecordDecl *RD);
+  bool isMoreSpecializedThanPrimary(ClassTemplatePartialSpecializationDecl *T,
+                                    sema::TemplateDeductionInfo &Info);
 
-  /// AddMsStructLayoutForRecord - Adds ms_struct layout attribute to record.
-  void AddMsStructLayoutForRecord(RecordDecl *RD);
+  VarTemplatePartialSpecializationDecl *getMoreSpecializedPartialSpecialization(
+      VarTemplatePartialSpecializationDecl *PS1,
+      VarTemplatePartialSpecializationDecl *PS2, SourceLocation Loc);
 
-  /// PushNamespaceVisibilityAttr - Note that we've entered a
-  /// namespace with a visibility attribute.
-  void PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
-                                   SourceLocation Loc);
+  bool isMoreSpecializedThanPrimary(VarTemplatePartialSpecializationDecl *T,
+                                    sema::TemplateDeductionInfo &Info);
 
-  /// AddPushedVisibilityAttribute - If '\#pragma GCC visibility' was used,
-  /// add an appropriate visibility attribute.
-  void AddPushedVisibilityAttribute(Decl *RD);
+  bool isTemplateTemplateParameterAtLeastAsSpecializedAs(
+      TemplateParameterList *PParam, TemplateDecl *AArg, SourceLocation Loc);
 
-  /// 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);
+  void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced,
+                                  unsigned Depth, llvm::SmallBitVector &Used);
 
-  /// FreeVisContext - Deallocate and null out VisContext.
-  void FreeVisContext();
+  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);
 
-  /// 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);
+  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());
 
-  void ActOnPragmaAttributeAttribute(ParsedAttr &Attribute,
-                                     SourceLocation PragmaLoc,
-                                     attr::ParsedSubjectMatchRuleSet Rules);
-  void ActOnPragmaAttributeEmptyPush(SourceLocation PragmaLoc,
-                                     const IdentifierInfo *Namespace);
+  ///@}
 
-  /// Called on well-formed '\#pragma clang attribute pop'.
-  void ActOnPragmaAttributePop(SourceLocation PragmaLoc,
-                               const IdentifierInfo *Namespace);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// Adds the attributes that have been specified using the
-  /// '\#pragma clang attribute push' directives to the given declaration.
-  void AddPragmaAttributes(Scope *S, Decl *D);
+  /// \name C++ Template Instantiation
+  /// Implementations are in SemaTemplateInstantiate.cpp
+  ///@{
 
-  void DiagnoseUnterminatedPragmaAttribute();
+public:
+  /// A helper class for building up ExtParameterInfos.
+  class ExtParameterInfoBuilder {
+    SmallVector Infos;
+    bool HasInteresting = false;
 
-  /// Called on well formed \#pragma clang optimize.
-  void ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc);
+  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);
 
-  /// #pragma optimize("[optimization-list]", on | off).
-  void ActOnPragmaMSOptimize(SourceLocation Loc, bool IsOn);
+      if (!HasInteresting)
+        HasInteresting = (info != FunctionProtoType::ExtParameterInfo());
+    }
 
-  /// Call on well formed \#pragma function.
-  void
-  ActOnPragmaMSFunction(SourceLocation Loc,
-                        const llvm::SmallVectorImpl &NoBuiltins);
+    /// 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();
+    }
+  };
 
-  /// 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;
-  }
+  /// The current instantiation scope used to store local
+  /// variables.
+  LocalInstantiationScope *CurrentInstantiationScope;
 
-  /// 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);
+  typedef llvm::DenseMap>
+      UnparsedDefaultArgInstantiationsMap;
 
-  /// 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);
+  /// 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;
 
-  /// 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);
+  /// 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,
 
-  void AddSYCLIntelBankBitsAttr(Decl *D, const AttributeCommonInfo &CI,
-                                Expr **Exprs, unsigned Size);
-  bool AnyWorkGroupSizesDiffer(const Expr *LHSXDim, const Expr *LHSYDim,
-                               const Expr *LHSZDim, const Expr *RHSXDim,
-                               const Expr *RHSYDim, const Expr *RHSZDim);
-  bool AllWorkGroupSizesSame(const Expr *LHSXDim, const Expr *LHSYDim,
-                             const Expr *LHSZDim, const Expr *RHSXDim,
-                             const Expr *RHSYDim, const Expr *RHSZDim);
-  void AddSYCLWorkGroupSizeHintAttr(Decl *D, const AttributeCommonInfo &CI,
-                                    Expr *XDim, Expr *YDim, Expr *ZDim);
-  SYCLWorkGroupSizeHintAttr *
-  MergeSYCLWorkGroupSizeHintAttr(Decl *D, const SYCLWorkGroupSizeHintAttr &A);
-  void AddIntelReqdSubGroupSize(Decl *D, const AttributeCommonInfo &CI,
-                                Expr *E);
-  IntelReqdSubGroupSizeAttr *
-  MergeIntelReqdSubGroupSizeAttr(Decl *D, const IntelReqdSubGroupSizeAttr &A);
-  IntelNamedSubGroupSizeAttr *
-  MergeIntelNamedSubGroupSizeAttr(Decl *D, const IntelNamedSubGroupSizeAttr &A);
-  void AddSYCLIntelNumSimdWorkItemsAttr(Decl *D, const AttributeCommonInfo &CI,
-                                        Expr *E);
-  SYCLIntelNumSimdWorkItemsAttr *
-  MergeSYCLIntelNumSimdWorkItemsAttr(Decl *D,
-                                     const SYCLIntelNumSimdWorkItemsAttr &A);
-  void AddSYCLIntelESimdVectorizeAttr(Decl *D, const AttributeCommonInfo &CI,
-                                      Expr *E);
-  SYCLIntelESimdVectorizeAttr *
-  MergeSYCLIntelESimdVectorizeAttr(Decl *D,
-                                   const SYCLIntelESimdVectorizeAttr &A);
-  void AddSYCLIntelSchedulerTargetFmaxMhzAttr(Decl *D,
-                                              const AttributeCommonInfo &CI,
-                                              Expr *E);
-  SYCLIntelSchedulerTargetFmaxMhzAttr *MergeSYCLIntelSchedulerTargetFmaxMhzAttr(
-      Decl *D, const SYCLIntelSchedulerTargetFmaxMhzAttr &A);
-  void AddSYCLIntelNoGlobalWorkOffsetAttr(Decl *D,
-                                          const AttributeCommonInfo &CI,
-                                          Expr *E);
-  SYCLIntelNoGlobalWorkOffsetAttr *MergeSYCLIntelNoGlobalWorkOffsetAttr(
-      Decl *D, const SYCLIntelNoGlobalWorkOffsetAttr &A);
-  void AddSYCLIntelLoopFuseAttr(Decl *D, const AttributeCommonInfo &CI,
-                                Expr *E);
-  SYCLIntelLoopFuseAttr *
-  MergeSYCLIntelLoopFuseAttr(Decl *D, const SYCLIntelLoopFuseAttr &A);
-  void AddSYCLIntelPrivateCopiesAttr(Decl *D, const AttributeCommonInfo &CI,
-                                     Expr *E);
-  void AddSYCLIntelMaxReplicatesAttr(Decl *D, const AttributeCommonInfo &CI,
-                                     Expr *E);
-  SYCLIntelMaxReplicatesAttr *
-  MergeSYCLIntelMaxReplicatesAttr(Decl *D, const SYCLIntelMaxReplicatesAttr &A);
-  void AddSYCLIntelForcePow2DepthAttr(Decl *D, const AttributeCommonInfo &CI,
-                                      Expr *E);
-  SYCLIntelForcePow2DepthAttr *
-  MergeSYCLIntelForcePow2DepthAttr(Decl *D,
-                                   const SYCLIntelForcePow2DepthAttr &A);
-  void AddSYCLIntelInitiationIntervalAttr(Decl *D,
-                                          const AttributeCommonInfo &CI,
-                                          Expr *E);
-  SYCLIntelInitiationIntervalAttr *MergeSYCLIntelInitiationIntervalAttr(
-      Decl *D, const SYCLIntelInitiationIntervalAttr &A);
+      /// 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,
 
-  SYCLIntelMaxConcurrencyAttr *MergeSYCLIntelMaxConcurrencyAttr(
-      Decl *D, const SYCLIntelMaxConcurrencyAttr &A);
-  void AddSYCLIntelMaxGlobalWorkDimAttr(Decl *D, const AttributeCommonInfo &CI,
-                                        Expr *E);
-  SYCLIntelMaxGlobalWorkDimAttr *
-  MergeSYCLIntelMaxGlobalWorkDimAttr(Decl *D,
-                                     const SYCLIntelMaxGlobalWorkDimAttr &A);
-  void AddSYCLIntelMinWorkGroupsPerComputeUnitAttr(
-      Decl *D, const AttributeCommonInfo &CI, Expr *E);
-  SYCLIntelMinWorkGroupsPerComputeUnitAttr *
-  MergeSYCLIntelMinWorkGroupsPerComputeUnitAttr(
-      Decl *D, const SYCLIntelMinWorkGroupsPerComputeUnitAttr &A);
-  void AddSYCLIntelMaxWorkGroupsPerMultiprocessorAttr(
-      Decl *D, const AttributeCommonInfo &CI, Expr *E);
-  SYCLIntelMaxWorkGroupsPerMultiprocessorAttr *
-  MergeSYCLIntelMaxWorkGroupsPerMultiprocessorAttr(
-      Decl *D, const SYCLIntelMaxWorkGroupsPerMultiprocessorAttr &A);
-  void AddSYCLIntelBankWidthAttr(Decl *D, const AttributeCommonInfo &CI,
-                                 Expr *E);
-  SYCLIntelBankWidthAttr *
-  MergeSYCLIntelBankWidthAttr(Decl *D, const SYCLIntelBankWidthAttr &A);
-  void AddSYCLIntelNumBanksAttr(Decl *D, const AttributeCommonInfo &CI,
-                                Expr *E);
-  SYCLIntelNumBanksAttr *
-  MergeSYCLIntelNumBanksAttr(Decl *D, const SYCLIntelNumBanksAttr &A);
-  SYCLDeviceHasAttr *MergeSYCLDeviceHasAttr(Decl *D,
-                                            const SYCLDeviceHasAttr &A);
-  void AddSYCLDeviceHasAttr(Decl *D, const AttributeCommonInfo &CI,
-                            Expr **Exprs, unsigned Size);
-  SYCLUsesAspectsAttr *MergeSYCLUsesAspectsAttr(Decl *D,
-                                                const SYCLUsesAspectsAttr &A);
-  void AddSYCLUsesAspectsAttr(Decl *D, const AttributeCommonInfo &CI,
-                              Expr **Exprs, unsigned Size);
-  bool CheckMaxAllowedWorkGroupSize(const Expr *RWGSXDim, const Expr *RWGSYDim,
-                                    const Expr *RWGSZDim, const Expr *MWGSXDim,
-                                    const Expr *MWGSYDim, const Expr *MWGSZDim);
-  void AddSYCLIntelMaxWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI,
-                                        Expr *XDim, Expr *YDim, Expr *ZDim);
-  SYCLIntelMaxWorkGroupSizeAttr *
-  MergeSYCLIntelMaxWorkGroupSizeAttr(Decl *D,
-                                     const SYCLIntelMaxWorkGroupSizeAttr &A);
-  void CheckSYCLAddIRAttributesFunctionAttrConflicts(Decl *D);
-  SYCLAddIRAttributesFunctionAttr *MergeSYCLAddIRAttributesFunctionAttr(
-      Decl *D, const SYCLAddIRAttributesFunctionAttr &A);
-  void AddSYCLAddIRAttributesFunctionAttr(Decl *D,
-                                          const AttributeCommonInfo &CI,
-                                          MutableArrayRef Args);
-  SYCLAddIRAttributesKernelParameterAttr *
-  MergeSYCLAddIRAttributesKernelParameterAttr(
-      Decl *D, const SYCLAddIRAttributesKernelParameterAttr &A);
-  void AddSYCLAddIRAttributesKernelParameterAttr(Decl *D,
-                                                 const AttributeCommonInfo &CI,
-                                                 MutableArrayRef Args);
-  SYCLAddIRAttributesGlobalVariableAttr *
-  MergeSYCLAddIRAttributesGlobalVariableAttr(
-      Decl *D, const SYCLAddIRAttributesGlobalVariableAttr &A);
-  void AddSYCLAddIRAttributesGlobalVariableAttr(Decl *D,
-                                                const AttributeCommonInfo &CI,
-                                                MutableArrayRef Args);
-  SYCLAddIRAnnotationsMemberAttr *
-  MergeSYCLAddIRAnnotationsMemberAttr(Decl *D,
-                                      const SYCLAddIRAnnotationsMemberAttr &A);
-  void AddSYCLAddIRAnnotationsMemberAttr(Decl *D, const AttributeCommonInfo &CI,
-                                         MutableArrayRef Args);
-  void AddSYCLReqdWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI,
-                                    Expr *XDim, Expr *YDim, Expr *ZDim);
-  SYCLReqdWorkGroupSizeAttr *
-  MergeSYCLReqdWorkGroupSizeAttr(Decl *D, const SYCLReqdWorkGroupSizeAttr &A);
+      /// We are instantiating a default argument for a function.
+      /// The Entity is the ParmVarDecl, and TemplateArgs/NumTemplateArgs
+      /// provides the template arguments as specified.
+      DefaultFunctionArgumentInstantiation,
 
-  SYCLTypeAttr *MergeSYCLTypeAttr(Decl *D, const AttributeCommonInfo &CI,
-                                  SYCLTypeAttr::SYCLType TypeName);
+      /// 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 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 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 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 substituting into a lambda expression.
+      LambdaExpressionSubstitution,
 
-  /// 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 substituting prior template arguments into a new
+      /// template parameter. The template parameter itself is either a
+      /// NonTypeTemplateParmDecl or a TemplateTemplateParmDecl.
+      PriorTemplateArgumentSubstitution,
 
-  /// AddAssumeAlignedAttr - Adds an assume_aligned attribute to a particular
-  /// declaration.
-  void AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
-                            Expr *OE);
+      /// We are checking the validity of a default template argument that
+      /// has been used when naming a template-id.
+      DefaultTemplateArgumentChecking,
 
-  /// AddAllocAlignAttr - Adds an alloc_align attribute to a particular
-  /// declaration.
-  void AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI,
-                         Expr *ParamExpr);
+      /// We are computing the exception specification for a defaulted special
+      /// member function.
+      ExceptionSpecEvaluation,
 
-  /// AddAlignValueAttr - Adds an align_value attribute to a particular
-  /// declaration.
-  void AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E);
+      /// We are instantiating the exception specification for a function
+      /// template which was deferred until it was needed.
+      ExceptionSpecInstantiation,
 
-  /// AddAnnotationAttr - Adds an annotation Annot with Args arguments to D.
-  void AddAnnotationAttr(Decl *D, const AttributeCommonInfo &CI,
-                         StringRef Annot, MutableArrayRef Args);
+      /// We are instantiating a requirement of a requires expression.
+      RequirementInstantiation,
 
-  /// 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 checking the satisfaction of a nested requirement of a requires
+      /// expression.
+      NestedRequirementConstraintsCheck,
 
-  /// Create an CUDALaunchBoundsAttr attribute.
-  CUDALaunchBoundsAttr *CreateLaunchBoundsAttr(const AttributeCommonInfo &CI,
-                                               Expr *MaxThreads,
-                                               Expr *MinBlocks,
-                                               Expr *MaxBlocks);
+      /// We are declaring an implicit special member function.
+      DeclaringSpecialMember,
 
-  /// AddLaunchBoundsAttr - Adds a launch_bounds attribute to a particular
-  /// declaration.
-  void AddLaunchBoundsAttr(Decl *D, const AttributeCommonInfo &CI,
-                           Expr *MaxThreads, Expr *MinBlocks, Expr *MaxBlocks);
-
-  /// AddModeAttr - Adds a mode attribute to a particular declaration.
-  void AddModeAttr(Decl *D, const AttributeCommonInfo &CI, IdentifierInfo *Name,
-                   bool InInstantiation = false);
+      /// We are declaring an implicit 'operator==' for a defaulted
+      /// 'operator<=>'.
+      DeclaringImplicitEqualityComparison,
 
-  void AddParameterABIAttr(Decl *D, const AttributeCommonInfo &CI,
-                           ParameterABI ABI);
+      /// We are defining a synthesized function (such as a defaulted special
+      /// member).
+      DefiningSynthesizedFunction,
 
-  enum class RetainOwnershipKind {NS, CF, OS};
-  void AddXConsumedAttr(Decl *D, const AttributeCommonInfo &CI,
-                        RetainOwnershipKind K, bool IsTemplateInstantiation);
+      // 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,
 
-  /// Create an AMDGPUWavesPerEUAttr attribute.
-  AMDGPUFlatWorkGroupSizeAttr *
-  CreateAMDGPUFlatWorkGroupSizeAttr(const AttributeCommonInfo &CI, Expr *Min,
-                                    Expr *Max);
+      // We are substituting template arguments into a constraint expression.
+      ConstraintSubstitution,
 
-  /// 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 normalizing a constraint expression.
+      ConstraintNormalization,
 
-  /// Create an AMDGPUWavesPerEUAttr attribute.
-  AMDGPUWavesPerEUAttr *
-  CreateAMDGPUWavesPerEUAttr(const AttributeCommonInfo &CI, Expr *Min,
-                             Expr *Max);
+      // Instantiating a Requires Expression parameter clause.
+      RequirementParameterInstantiation,
 
-  /// 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 substituting into the parameter mapping of an atomic constraint
+      // during normalization.
+      ParameterMappingSubstitution,
 
-  /// addSYCLIntelPipeIOAttr - Adds a pipe I/O attribute to a particular
-  /// declaration.
-  void addSYCLIntelPipeIOAttr(Decl *D, const AttributeCommonInfo &CI, Expr *ID);
-  SYCLIntelPipeIOAttr *MergeSYCLIntelPipeIOAttr(Decl *D,
-                                                const SYCLIntelPipeIOAttr &A);
+      /// We are rewriting a comparison operator in terms of an operator<=>.
+      RewritingOperatorAsSpaceship,
 
-  /// AddSYCLIntelMaxConcurrencyAttr - Adds a max_concurrency attribute to a
-  /// particular declaration.
-  void AddSYCLIntelMaxConcurrencyAttr(Decl *D,
-                                      const AttributeCommonInfo &CI,
-                                      Expr *E);
+      /// We are initializing a structured binding.
+      InitializingStructuredBinding,
 
-  bool checkNSReturnsRetainedReturnType(SourceLocation loc, QualType type);
-  bool checkAllowedSYCLInitializer(VarDecl *VD);
-  //===--------------------------------------------------------------------===//
-  // 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 marking a class as __dllexport.
+      MarkingClassDllexported,
 
-  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);
+      /// We are building an implied call from __builtin_dump_struct. The
+      /// arguments are in CallArgs.
+      BuildingBuiltinDumpStructCall,
 
-  // 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);
+      /// 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,
 
-  // 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);
+      /// We are building deduction guides for a class.
+      BuildingDeductionGuides,
+    } Kind;
 
-  //===--------------------------------------------------------------------===//
-  // OpenMP directives and clauses.
-  //
-private:
-  void *VarDataSharingAttributesStack;
+    /// Was the enclosing context a non-instantiation SFINAE context?
+    bool SavedInNonInstantiationSFINAEContext;
 
-  struct DeclareTargetContextInfo {
-    struct MapInfo {
-      OMPDeclareTargetDeclAttr::MapTypeTy MT;
-      SourceLocation Loc;
-    };
-    /// Explicitly listed variables and functions in a 'to' or 'link' clause.
-    llvm::DenseMap ExplicitlyMapped;
+    /// The point of instantiation or synthesis within the source code.
+    SourceLocation PointOfInstantiation;
 
-    /// The 'device_type' as parsed from the clause.
-    OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any;
+    /// The entity that is being synthesized.
+    Decl *Entity;
 
-    /// The directive kind, `begin declare target` or `declare target`.
-    OpenMPDirectiveKind Kind;
+    /// The template (or partial specialization) in which we are
+    /// performing the instantiation, for substitutions of prior template
+    /// arguments.
+    NamedDecl *Template;
 
-    /// The directive with indirect clause.
-    std::optional Indirect;
+    union {
+      /// The list of template arguments we are substituting, if they
+      /// are not part of the entity.
+      const TemplateArgument *TemplateArgs;
 
-    /// The directive location.
-    SourceLocation Loc;
+      /// The list of argument expressions in a synthesized call.
+      const Expr *const *CallArgs;
+    };
 
-    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);
-
-  /// Helper to keep information about the current `omp begin/end declare
-  /// variant` nesting.
-  struct OMPDeclareVariantScope {
-    /// The associated OpenMP context selector.
-    OMPTraitInfo *TI;
+  /// 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());
 
-    /// The associated OpenMP context selector mangling.
-    std::string NameSuffix;
+    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());
 
-    OMPDeclareVariantScope(OMPTraitInfo &TI);
-  };
+    /// 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());
 
-  /// Return the OMPTraitInfo for the surrounding scope, if any.
-  OMPTraitInfo *getOMPTraitInfoForSurroundingScope() {
-    return OMPDeclareVariantScopes.empty() ? nullptr
-                                           : OMPDeclareVariantScopes.back().TI;
-  }
-
-  /// The current `omp begin/end declare variant` scopes.
-  SmallVector OMPDeclareVariantScopes;
+    /// 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());
 
-  /// The current `omp begin/end assumes` scopes.
-  SmallVector OMPAssumeScoped;
+    /// 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());
 
-  /// All `omp assumes` we encountered so far.
-  SmallVector OMPAssumeGlobal;
+    /// 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());
 
-  /// 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 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());
 
-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 instantiating a default argument for a function
+    /// parameter.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          ParmVarDecl *Param,
+                          ArrayRef TemplateArgs,
+                          SourceRange InstantiationRange = SourceRange());
 
-  /// 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 substituting prior template arguments into a
+    /// non-type parameter.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          NamedDecl *Template, NonTypeTemplateParmDecl *Param,
+                          ArrayRef TemplateArgs,
+                          SourceRange InstantiationRange);
 
-  /// Act on \p D, a function definition inside of an `omp [begin/end] assumes`.
-  void ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D);
+    /// 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);
 
-  /// Can we exit an OpenMP declare variant scope at the moment.
-  bool isInOpenMPDeclareVariantScope() const {
-    return !OMPDeclareVariantScopes.empty();
-  }
+    /// 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);
 
-  ExprResult
-  VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind,
-                                        bool StrictlyPositive = true,
-                                        bool SuppressExprDiags = false);
+    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);
 
-  /// 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 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);
 
-  /// Handle a `omp begin declare variant`.
-  void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI);
+    struct ConstraintNormalization {};
+    /// \brief Note that we are normalizing a constraint expression.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          ConstraintNormalization, NamedDecl *Template,
+                          SourceRange InstantiationRange);
 
-  /// Handle a `omp end declare variant`.
-  void ActOnOpenMPEndDeclareVariant();
+    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);
 
-  /// 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 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());
 
-  /// Function tries to capture lambda's captured variables in the OpenMP region
-  /// before the original lambda is captured.
-  void tryCaptureOpenMPLambdas(ValueDecl *V);
+    /// \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());
 
-  /// 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 Note that we are checking a requires clause.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          const RequiresExpr *E,
+                          sema::TemplateDeductionInfo &DeductionInfo,
+                          SourceRange InstantiationRange);
 
-  /// 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);
+    struct BuildingDeductionGuidesTag {};
+    /// \brief Note that we are building deduction guides.
+    InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+                          TemplateDecl *Entity, BuildingDeductionGuidesTag,
+                          SourceRange InstantiationRange = SourceRange());
 
-  /// 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);
+    /// Note that we have finished instantiating this template.
+    void Clear();
 
-  ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
-                                   ExprObjectKind OK, SourceLocation Loc);
+    ~InstantiatingTemplate() { Clear(); }
 
-  /// If the current region is a loop-based region, mark the start of the loop
-  /// construct.
-  void startOpenMPLoop();
+    /// Determines whether we have exceeded the maximum
+    /// recursive template instantiations.
+    bool isInvalid() const { return Invalid; }
 
-  /// If the current region is a range loop-based region, mark the start of the
-  /// loop construct.
-  void startOpenMPCXXRangeFor();
+    /// Determine whether we are already instantiating this
+    /// specialization in some surrounding active instantiation.
+    bool isAlreadyInstantiating() const { return AlreadyInstantiating; }
 
-  /// 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;
+  private:
+    Sema &SemaRef;
+    bool Invalid;
+    bool AlreadyInstantiating;
+    bool CheckInstantiationDepth(SourceLocation PointOfInstantiation,
+                                 SourceRange InstantiationRange);
 
-  /// 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(
+        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 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;
+    InstantiatingTemplate(const InstantiatingTemplate &) = delete;
 
-  /// 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;
+    InstantiatingTemplate &operator=(const InstantiatingTemplate &) = delete;
+  };
 
-  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);
+  bool
+  SubstTemplateArguments(ArrayRef Args,
+                         const MultiLevelTemplateArgumentList &TemplateArgs,
+                         TemplateArgumentListInfo &Outputs);
 
-  /// 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);
+  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);
 
-  /// Called on well-formed '\#pragma omp metadirective' after parsing
-  /// of the  associated statement.
-  StmtResult ActOnOpenMPMetaDirective(ArrayRef Clauses,
-                                      Stmt *AStmt, SourceLocation StartLoc,
-                                      SourceLocation EndLoc);
+  /// RAII object to handle the state changes required to synthesize
+  /// a function body.
+  class SynthesizedFunctionScope {
+    Sema &S;
+    Sema::ContextRAII SavedContext;
+    bool PushedCodeSynthesisContext = false;
 
-  // 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);
+  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 [begin] assume[s]'.
-  void ActOnOpenMPAssumesDirective(SourceLocation Loc,
-                                   OpenMPDirectiveKind DKind,
-                                   ArrayRef Assumptions,
-                                   bool SkippedClauses);
+    void addContextNote(SourceLocation UseLoc) {
+      assert(!PushedCodeSynthesisContext);
 
-  /// Check if there is an active global `omp begin assumes` directive.
-  bool isInOpenMPAssumeScope() const { return !OMPAssumeScoped.empty(); }
+      Sema::CodeSynthesisContext Ctx;
+      Ctx.Kind = Sema::CodeSynthesisContext::DefiningSynthesizedFunction;
+      Ctx.PointOfInstantiation = UseLoc;
+      Ctx.Entity = cast(S.CurContext);
+      S.pushCodeSynthesisContext(Ctx);
 
-  /// Check if there is an active global `omp assumes` directive.
-  bool hasGlobalOpenMPAssumes() const { return !OMPAssumeGlobal.empty(); }
+      PushedCodeSynthesisContext = true;
+    }
 
-  /// Called on well-formed '#pragma omp end assumes'.
-  void ActOnOpenMPEndAssumesDirective();
+    ~SynthesizedFunctionScope() {
+      if (PushedCodeSynthesisContext)
+        S.popCodeSynthesisContext();
+      if (auto *FD = dyn_cast(S.CurContext)) {
+        FD->setWillHaveBody(false);
+        S.CheckImmediateEscalatingFunctionDefinition(FD, S.getCurFunction());
+      }
+      S.PopExpressionEvaluationContext();
+      S.PopFunctionScopeInfo();
+    }
+  };
 
-  /// 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);
+  /// 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;
 
-  /// 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;
+  /// Specializations whose definitions are currently being instantiated.
+  llvm::DenseSet> InstantiatingSpecializations;
 
-  /// Called on the start of target region i.e. '#pragma omp declare target'.
-  bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI);
+  /// Non-dependent types used in templates that have already been instantiated
+  /// by some template instantiation.
+  llvm::DenseSet InstantiatedNonDependentTypes;
 
-  /// Called at the end of target region i.e. '#pragma omp end declare target'.
-  const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective();
+  /// Extra modules inspected when performing a lookup during a template
+  /// instantiation. Computed lazily.
+  SmallVector CodeSynthesisContextLookupModules;
 
-  /// 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);
+  /// 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;
 
-  /// Report unterminated 'omp declare target' or 'omp begin declare target' at
-  /// the end of a compilation unit.
-  void DiagnoseUnterminatedOpenMPDeclareTarget();
+  /// Map from the most recent declaration of a namespace to the most
+  /// recent visible declaration of that namespace.
+  llvm::DenseMap VisibleNamespaceCache;
 
-  /// Searches for the provided declaration name for OpenMP declare target
-  /// directive.
-  NamedDecl *lookupOpenMPDeclareTargetName(Scope *CurScope,
-                                           CXXScopeSpec &ScopeSpec,
-                                           const DeclarationNameInfo &Id);
+  /// 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;
 
-  /// Called on correct id-expression from the '#pragma omp declare target'.
-  void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc,
-                                    OMPDeclareTargetDeclAttr::MapTypeTy MT,
-                                    DeclareTargetContextInfo &DTCI);
+  /// 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;
 
-  /// Check declaration inside target region.
-  void
-  checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
-                                   SourceLocation IdLoc = SourceLocation());
+  /// 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;
 
-  /// Adds OMPDeclareTargetDeclAttr to referenced variables in declare target
-  /// directive.
-  void ActOnOpenMPDeclareTargetInitializer(Decl *D);
+  /// 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;
 
-  /// 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);
+  /// 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;
 
-  /// Return true if currently in OpenMP task with untied clause context.
-  bool isInOpenMPTaskUntiedContext() const;
+  /// 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;
 
-  /// Return true inside OpenMP declare target region.
-  bool isInOpenMPDeclareTargetContext() const {
-    return !DeclareTargetNesting.empty();
-  }
-  /// Return true inside OpenMP target region.
-  bool isInOpenMPTargetExecutionDirective() const;
+  public:
+    ArgumentPackSubstitutionIndexRAII(Sema &Self, int NewSubstitutionIndex)
+        : Self(Self), OldSubstitutionIndex(Self.ArgumentPackSubstitutionIndex) {
+      Self.ArgumentPackSubstitutionIndex = NewSubstitutionIndex;
+    }
 
-  /// Return the number of captured regions created for an OpenMP directive.
-  static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind);
+    ~ArgumentPackSubstitutionIndexRAII() {
+      Self.ArgumentPackSubstitutionIndex = OldSubstitutionIndex;
+    }
+  };
 
-  /// Initialization of captured region for OpenMP region.
-  void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope);
+  friend class ArgumentPackSubstitutionRAII;
 
-  /// Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to
-  /// an OpenMP loop directive.
-  StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt);
+  void pushCodeSynthesisContext(CodeSynthesisContext Ctx);
+  void popCodeSynthesisContext();
 
-  /// 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 PrintContextStack() {
+    if (!CodeSynthesisContexts.empty() &&
+        CodeSynthesisContexts.size() != LastEmittedCodeSynthesisContextDepth) {
+      PrintInstantiationStack();
+      LastEmittedCodeSynthesisContextDepth = CodeSynthesisContexts.size();
+    }
+    if (PragmaAttributeCurrentTargetDecl)
+      PrintPragmaAttributeInstantiationPoint();
+  }
+  void PrintInstantiationStack();
 
-  /// End of OpenMP region.
+  /// Determines whether we are currently in a context where
+  /// template argument substitution failures are not considered
+  /// errors.
   ///
-  /// \param S Statement associated with the current OpenMP region.
-  /// \param Clauses List of clauses for the current OpenMP region.
+  /// \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;
+
+  TypeSourceInfo *SubstType(TypeSourceInfo *T,
+                            const MultiLevelTemplateArgumentList &TemplateArgs,
+                            SourceLocation Loc, DeclarationName Entity,
+                            bool AllowDeducedTST = false);
+
+  QualType SubstType(QualType T,
+                     const MultiLevelTemplateArgumentList &TemplateArgs,
+                     SourceLocation Loc, DeclarationName Entity);
+
+  TypeSourceInfo *SubstType(TypeLoc TL,
+                            const MultiLevelTemplateArgumentList &TemplateArgs,
+                            SourceLocation Loc, DeclarationName Entity);
+
+  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.
   ///
-  /// \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 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.
+  ///
+  /// \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);
+  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,
+      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);
+
+  /// Build an Objective-C type parameter type.
+  QualType BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl,
+                                  SourceLocation ProtocolLAngleLoc,
+                                  ArrayRef Protocols,
+                                  ArrayRef ProtocolLocs,
+                                  SourceLocation ProtocolRAngleLoc,
+                                  bool FailOnError = 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);
+
+  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);
+
+  QualType BuildAddressSpaceAttr(QualType &T, LangAS ASIdx, Expr *AddrSpace,
+                                 SourceLocation AttrLoc);
+
+  /// 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());
 
-  /// 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);
+  /// Retrieve the keyword associated
+  IdentifierInfo *getNullabilityKeyword(NullabilityKind nullability);
 
-  /// 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);
+  /// The struct behind the CFErrorRef pointer.
+  RecordDecl *CFError = nullptr;
+  bool isCFError(RecordDecl *D);
 
-  /// 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);
+  /// Retrieve the identifier "NSError".
+  IdentifierInfo *getNSErrorIdent();
 
-  /// 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);
+  /// 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);
 
-  /// 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);
+  // 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);
+
+  bool RequireLiteralType(SourceLocation Loc, QualType T,
+                          TypeDiagnoser &Diagnoser);
+  bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID);
+
+  template 
+  bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID,
+                          const Ts &...Args) {
+    BoundTypeDiagnoser Diagnoser(DiagID, Args...);
+    return RequireLiteralType(Loc, T, Diagnoser);
+  }
+
+  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);
+
+  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);
+  }
+
+  template 
+  bool RequireCompleteType(SourceLocation Loc, QualType T, unsigned DiagID,
+                           const Ts &...Args) {
+    BoundTypeDiagnoser Diagnoser(DiagID, Args...);
+    return RequireCompleteType(Loc, T, Diagnoser);
+  }
+
+  /// Determine whether a declaration is visible to name lookup.
+  bool isVisible(const NamedDecl *D) {
+    return D->isUnconditionallyVisible() ||
+           isAcceptableSlow(D, AcceptableKind::Visible);
+  }
+
+  /// Determine whether a declaration is reachable.
+  bool isReachable(const NamedDecl *D) {
+    // All visible declarations are reachable.
+    return D->isUnconditionallyVisible() ||
+           isAcceptableSlow(D, AcceptableKind::Reachable);
+  }
+
+  /// Determine whether a declaration is acceptable (visible/reachable).
+  bool isAcceptable(const NamedDecl *D, AcceptableKind Kind) {
+    return Kind == AcceptableKind::Visible ? isVisible(D) : isReachable(D);
+  }
+
+  /// 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);
+
+  /// 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);
+  }
+
+  /// 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 hasAcceptableDefinition(NamedDecl *D, NamedDecl **Suggested,
+                               AcceptableKind Kind,
+                               bool OnlyNeedComplete = false);
+  bool hasAcceptableDefinition(NamedDecl *D, AcceptableKind Kind) {
+    NamedDecl *Hidden;
+    return hasAcceptableDefinition(D, &Hidden, Kind);
+  }
+
+private:
+  bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
+                               CompleteTypeKind Kind, TypeDiagnoser *Diagnoser);
+
+  /// Nullability type specifiers.
+  IdentifierInfo *Ident__Nonnull = nullptr;
+  IdentifierInfo *Ident__Nullable = nullptr;
+  IdentifierInfo *Ident__Nullable_result = nullptr;
+  IdentifierInfo *Ident__Null_unspecified = nullptr;
+
+  IdentifierInfo *Ident_NSError = nullptr;
+
+  ///@}
+
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
+
+  /// \name ObjC Declarations
+  /// Implementations are in SemaDeclObjC.cpp
+  ///@{
+
+public:
+  enum ObjCSpecialMethodKind {
+    OSMK_None,
+    OSMK_Alloc,
+    OSMK_New,
+    OSMK_Copy,
+    OSMK_RetainingInit,
+    OSMK_NonRetainingInit
+  };
 
-  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);
+  /// Method selectors used in a \@selector expression. Used for implementation
+  /// of -Wselector.
+  llvm::MapVector ReferencedSelectors;
 
-  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);
+  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(); }
 
-  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);
+  private:
+    llvm::DenseMap Methods;
+  };
 
-  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);
+  /// 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;
 
-  /// 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 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 on well-formed 'init' clause.
-  OMPClause *
-  ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo,
-                        SourceLocation StartLoc, SourceLocation LParenLoc,
-                        SourceLocation VarLoc, SourceLocation EndLoc);
+    // Make the previous decl visible.
+    makeMergedDefinitionVisible(Previous);
+    return true;
+  }
 
-  /// Called on well-formed 'use' clause.
-  OMPClause *ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc,
-                                  SourceLocation LParenLoc,
-                                  SourceLocation VarLoc, SourceLocation EndLoc);
+  typedef llvm::SmallPtrSet SelectorSet;
 
-  /// 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);
+  enum MethodMatchStrategy { MMS_loose, MMS_strict };
 
-  /// Called on well-formed 'unified_address' clause.
-  OMPClause *ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc,
-                                                  SourceLocation EndLoc);
+  enum ObjCContainerKind {
+    OCK_None = -1,
+    OCK_Interface = 0,
+    OCK_Protocol,
+    OCK_Category,
+    OCK_ClassExtension,
+    OCK_Implementation,
+    OCK_CategoryImplementation
+  };
+  ObjCContainerKind getObjCContainerKind() const;
 
-  /// Called on well-formed 'reverse_offload' clause.
-  OMPClause *ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc,
-                                             SourceLocation EndLoc);
+  DeclResult actOnObjCTypeParam(Scope *S, ObjCTypeParamVariance variance,
+                                SourceLocation varianceLoc, unsigned index,
+                                IdentifierInfo *paramName,
+                                SourceLocation paramLoc,
+                                SourceLocation colonLoc, ParsedType typeBound);
 
-  /// Called on well-formed 'dynamic_allocators' clause.
-  OMPClause *ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc,
-                                                SourceLocation EndLoc);
+  ObjCTypeParamList *actOnObjCTypeParamList(Scope *S, SourceLocation lAngleLoc,
+                                            ArrayRef typeParams,
+                                            SourceLocation rAngleLoc);
+  void popObjCTypeParamList(Scope *S, ObjCTypeParamList *typeParamList);
 
-  /// Called on well-formed 'atomic_default_mem_order' clause.
-  OMPClause *ActOnOpenMPAtomicDefaultMemOrderClause(
-      OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc,
-      SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc);
+  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);
 
-  /// Called on well-formed 'at' clause.
-  OMPClause *ActOnOpenMPAtClause(OpenMPAtClauseKind Kind,
-                                 SourceLocation KindLoc,
-                                 SourceLocation StartLoc,
-                                 SourceLocation LParenLoc,
-                                 SourceLocation EndLoc);
+  void ActOnSuperClassOfClassInterface(
+      Scope *S, SourceLocation AtInterfaceLoc, ObjCInterfaceDecl *IDecl,
+      IdentifierInfo *ClassName, SourceLocation ClassLoc,
+      IdentifierInfo *SuperName, SourceLocation SuperLoc,
+      ArrayRef SuperTypeArgs, SourceRange SuperTypeArgsRange);
 
-  /// Called on well-formed 'severity' clause.
-  OMPClause *ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind,
-                                       SourceLocation KindLoc,
-                                       SourceLocation StartLoc,
-                                       SourceLocation LParenLoc,
-                                       SourceLocation EndLoc);
+  void ActOnTypedefedProtocols(SmallVectorImpl &ProtocolRefs,
+                               SmallVectorImpl &ProtocolLocs,
+                               IdentifierInfo *SuperName,
+                               SourceLocation SuperLoc);
 
-  /// Called on well-formed 'message' clause.
-  /// passing string for message.
-  OMPClause *ActOnOpenMPMessageClause(Expr *MS, SourceLocation StartLoc,
-                                      SourceLocation LParenLoc,
-                                      SourceLocation EndLoc);
+  Decl *ActOnCompatibilityAlias(SourceLocation AtCompatibilityAliasLoc,
+                                IdentifierInfo *AliasName,
+                                SourceLocation AliasLocation,
+                                IdentifierInfo *ClassName,
+                                SourceLocation ClassLocation);
 
-  /// 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
-  };
+  bool CheckForwardProtocolDeclarationForCircularDependency(
+      IdentifierInfo *PName, SourceLocation &PLoc, SourceLocation PrevLoc,
+      const ObjCList &PList);
 
-  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);
+  ObjCProtocolDecl *ActOnStartProtocolInterface(
+      SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName,
+      SourceLocation ProtocolLoc, Decl *const *ProtoRefNames,
+      unsigned NumProtoRefs, const SourceLocation *ProtoLocs,
+      SourceLocation EndProtoLoc, const ParsedAttributesView &AttrList,
+      SkipBodyInfo *SkipBody);
 
-  /// 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);
+  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);
 
-  /// Called on a well-formed 'ompx_dyn_cgroup_mem' clause.
-  OMPClause *ActOnOpenMPXDynCGroupMemClause(Expr *Size, SourceLocation StartLoc,
-                                            SourceLocation LParenLoc,
-                                            SourceLocation EndLoc);
+  ObjCImplementationDecl *ActOnStartClassImplementation(
+      SourceLocation AtClassImplLoc, IdentifierInfo *ClassName,
+      SourceLocation ClassLoc, IdentifierInfo *SuperClassname,
+      SourceLocation SuperClassLoc, const ParsedAttributesView &AttrList);
 
-  /// Called on well-formed 'doacross' clause.
-  OMPClause *
-  ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType,
-                            SourceLocation DepLoc, SourceLocation ColonLoc,
-                            ArrayRef VarList, SourceLocation StartLoc,
-                            SourceLocation LParenLoc, SourceLocation EndLoc);
+  ObjCCategoryImplDecl *ActOnStartCategoryImplementation(
+      SourceLocation AtCatImplLoc, IdentifierInfo *ClassName,
+      SourceLocation ClassLoc, IdentifierInfo *CatName, SourceLocation CatLoc,
+      const ParsedAttributesView &AttrList);
 
-  /// Called on a well-formed 'ompx_attribute' clause.
-  OMPClause *ActOnOpenMPXAttributeClause(ArrayRef Attrs,
-                                         SourceLocation StartLoc,
-                                         SourceLocation LParenLoc,
-                                         SourceLocation EndLoc);
+  DeclGroupPtrTy ActOnFinishObjCImplementation(Decl *ObjCImpDecl,
+                                               ArrayRef Decls);
 
-  /// Called on a well-formed 'ompx_bare' clause.
-  OMPClause *ActOnOpenMPXBareClause(SourceLocation StartLoc,
-                                    SourceLocation EndLoc);
+  DeclGroupPtrTy
+  ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc,
+                                  ArrayRef IdentList,
+                                  const ParsedAttributesView &attrList);
 
-  //===--------------------------------------------------------------------===//
-  // OpenACC directives and clauses.
+  void FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer,
+                               ArrayRef ProtocolId,
+                               SmallVectorImpl &Protocols);
 
-  /// Called after parsing an OpenACC Clause so that it can be checked.
-  bool ActOnOpenACCClause(OpenACCClauseKind ClauseKind,
-                          SourceLocation StartLoc);
+  void DiagnoseTypeArgsAndProtocols(IdentifierInfo *ProtocolId,
+                                    SourceLocation ProtocolLoc,
+                                    IdentifierInfo *TypeArgId,
+                                    SourceLocation TypeArgLoc,
+                                    bool SelectProtocolFirst = false);
 
-  /// 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);
+  /// 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);
 
-  /// 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);
+  void DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
+                                        ObjCInterfaceDecl *ID);
 
-  /// 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);
+  Decl *ActOnAtEnd(Scope *S, SourceRange AtEnd,
+                   ArrayRef allMethods = std::nullopt,
+                   ArrayRef allTUVars = std::nullopt);
 
-  /// 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();
+  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;
 
-  /// 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
+    /// ArgAttrs - Attribute list for this argument.
+    ParsedAttributesView ArgAttrs;
   };
 
-  static bool isCast(CheckedConversionKind CCK) {
-    return CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast ||
-           CCK == CCK_OtherCast;
-  }
+  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);
 
-  /// 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);
+  bool CheckARCMethodDecl(ObjCMethodDecl *method);
 
-  /// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding
-  /// to the conversion from scalar type ScalarTy to the Boolean type.
-  static CastKind ScalarTypeToBooleanCastKind(QualType ScalarTy);
+  bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall);
 
-  /// IgnoredValueConversions - Given that an expression's result is
-  /// syntactically ignored, perform any conversions that are
-  /// required.
-  ExprResult IgnoredValueConversions(Expr *E);
+  /// 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);
 
-  // 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);
+  /// Describes the compatibility of a result type with its method.
+  enum ResultTypeCompatibilityKind {
+    RTC_Compatible,
+    RTC_Incompatible,
+    RTC_Unknown
+  };
 
-  /// CallExprUnaryConversions - a special case of an unary conversion
-  /// performed on a function designator of a call expression.
-  ExprResult CallExprUnaryConversions(Expr *E);
+  void CheckObjCMethodDirectOverrides(ObjCMethodDecl *method,
+                                      ObjCMethodDecl *overridden);
 
-  // DefaultFunctionArrayConversion - converts functions and arrays
-  // to their respective pointers (C99 6.3.2.1).
-  ExprResult DefaultFunctionArrayConversion(Expr *E, bool Diagnose = true);
+  void CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod,
+                                ObjCInterfaceDecl *CurrentClass,
+                                ResultTypeCompatibilityKind RTC);
 
-  // DefaultFunctionArrayLvalueConversion - converts functions and
-  // arrays to their respective pointers and performs the
-  // lvalue-to-rvalue conversion.
-  ExprResult DefaultFunctionArrayLvalueConversion(Expr *E,
-                                                  bool Diagnose = true);
+  /// AddAnyMethodToGlobalPool - Add any method, instance or factory to global
+  /// pool.
+  void AddAnyMethodToGlobalPool(Decl *D);
 
-  // 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);
+  void ActOnStartOfObjCMethodDef(Scope *S, Decl *D);
+  bool isObjCMethodDecl(Decl *D) { return D && isa(D); }
 
-  // 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);
+  /// 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);
+
+  void WarnConflictingTypedMethods(ObjCMethodDecl *Method,
+                                   ObjCMethodDecl *MethodDecl,
+                                   bool IsProtocolMethodDecl);
+
+  void CheckConflictingOverridingMethod(ObjCMethodDecl *Method,
+                                        ObjCMethodDecl *Overridden,
+                                        bool IsProtocolMethodDecl);
+
+  /// WarnExactTypedMethods - This routine issues a warning if method
+  /// implementation declaration matches exactly that of its declaration.
+  void WarnExactTypedMethods(ObjCMethodDecl *Method, ObjCMethodDecl *MethodDecl,
+                             bool IsProtocolMethodDecl);
+
+  /// 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);
+
+  /// 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);
+
+  /// 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);
+
+  DeclGroupPtrTy ActOnForwardClassDeclaration(
+      SourceLocation Loc, IdentifierInfo **IdentList, SourceLocation *IdentLocs,
+      ArrayRef TypeParamLists, unsigned NumElts);
+
+  /// 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);
+
+  /// Add the given method to the list of globally-known methods.
+  void addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method);
+
+  void ReadMethodPool(Selector Sel);
+  void updateOutOfDateSelector(Selector Sel);
+
+  /// - 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);
 
-  /// 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
+  AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod,
+                                 SourceRange R, bool receiverIdOrClass,
+                                 SmallVectorImpl &Methods);
 
-  // Used for emitting the right warning by DefaultVariadicArgumentPromotion
-  enum VariadicCallType {
-    VariadicFunction,
-    VariadicBlock,
-    VariadicMethod,
-    VariadicConstructor,
-    VariadicDoesNotApply
-  };
+  void
+  DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl &Methods,
+                                     Selector Sel, SourceRange R,
+                                     bool receiverIdOrClass);
 
-  VariadicCallType getVariadicCallType(FunctionDecl *FDecl,
-                                       const FunctionProtoType *Proto,
-                                       Expr *Fn);
+  const ObjCMethodDecl *
+  SelectorsForTypoCorrection(Selector Sel, QualType ObjectType = QualType());
+  /// LookupImplementedMethodInGlobalPool - Returns the method which has an
+  /// implementation.
+  ObjCMethodDecl *LookupImplementedMethodInGlobalPool(Selector Sel);
 
-  // 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
-  };
+  void DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, ObjCInterfaceDecl *SID);
 
-  // Determines which VarArgKind fits an expression.
-  VarArgKind isValidVarArgType(const QualType &Ty);
+  /// 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);
 
-  /// 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);
+  void ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart,
+                 IdentifierInfo *ClassName, SmallVectorImpl &Decls);
 
-  /// 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);
+  VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType,
+                                  SourceLocation StartLoc, SourceLocation IdLoc,
+                                  IdentifierInfo *Id, bool Invalid = false);
 
-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);
+  Decl *ActOnObjCExceptionDecl(Scope *S, Declarator &D);
 
-public:
-  /// Check to see if a given expression could have '.c_str()' called on it.
-  bool hasCStrMethod(const Expr *E);
+  /// CollectIvarsToConstructOrDestruct - Collect those ivars which require
+  /// initialization.
+  void
+  CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI,
+                                    SmallVectorImpl &Ivars);
 
-  /// 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 DiagnoseUseOfUnimplementedSelectors();
 
-  // 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);
+  /// 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);
 
-  /// 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,
-  };
+  /// 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;
 
-  // 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);
+  /// 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);
+  }
 
-  /// 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,
+  /// AddFactoryMethodToGlobalPool - Same as above, but for factory methods.
+  void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl = false) {
+    AddMethodToGlobalPool(Method, impl, /*instance*/ false);
+  }
 
-    /// PointerToInt - The assignment converts a pointer to an int, which we
-    /// accept as an extension.
-    PointerToInt,
+  void AddSYCLIntelBankBitsAttr(Decl *D, const AttributeCommonInfo &CI,
+                                Expr **Exprs, unsigned Size);
+  bool AnyWorkGroupSizesDiffer(const Expr *LHSXDim, const Expr *LHSYDim,
+                               const Expr *LHSZDim, const Expr *RHSXDim,
+                               const Expr *RHSYDim, const Expr *RHSZDim);
+  bool AllWorkGroupSizesSame(const Expr *LHSXDim, const Expr *LHSYDim,
+                             const Expr *LHSZDim, const Expr *RHSXDim,
+                             const Expr *RHSYDim, const Expr *RHSZDim);
+  void AddSYCLWorkGroupSizeHintAttr(Decl *D, const AttributeCommonInfo &CI,
+                                    Expr *XDim, Expr *YDim, Expr *ZDim);
+  SYCLWorkGroupSizeHintAttr *
+  MergeSYCLWorkGroupSizeHintAttr(Decl *D, const SYCLWorkGroupSizeHintAttr &A);
+  void AddIntelReqdSubGroupSize(Decl *D, const AttributeCommonInfo &CI,
+                                Expr *E);
+  IntelReqdSubGroupSizeAttr *
+  MergeIntelReqdSubGroupSizeAttr(Decl *D, const IntelReqdSubGroupSizeAttr &A);
+  IntelNamedSubGroupSizeAttr *
+  MergeIntelNamedSubGroupSizeAttr(Decl *D, const IntelNamedSubGroupSizeAttr &A);
+  void AddSYCLIntelNumSimdWorkItemsAttr(Decl *D, const AttributeCommonInfo &CI,
+                                        Expr *E);
+  SYCLIntelNumSimdWorkItemsAttr *
+  MergeSYCLIntelNumSimdWorkItemsAttr(Decl *D,
+                                     const SYCLIntelNumSimdWorkItemsAttr &A);
+  void AddSYCLIntelESimdVectorizeAttr(Decl *D, const AttributeCommonInfo &CI,
+                                      Expr *E);
+  SYCLIntelESimdVectorizeAttr *
+  MergeSYCLIntelESimdVectorizeAttr(Decl *D,
+                                   const SYCLIntelESimdVectorizeAttr &A);
+  void AddSYCLIntelSchedulerTargetFmaxMhzAttr(Decl *D,
+                                              const AttributeCommonInfo &CI,
+                                              Expr *E);
+  SYCLIntelSchedulerTargetFmaxMhzAttr *MergeSYCLIntelSchedulerTargetFmaxMhzAttr(
+      Decl *D, const SYCLIntelSchedulerTargetFmaxMhzAttr &A);
+  void AddSYCLIntelNoGlobalWorkOffsetAttr(Decl *D,
+                                          const AttributeCommonInfo &CI,
+                                          Expr *E);
+  SYCLIntelNoGlobalWorkOffsetAttr *MergeSYCLIntelNoGlobalWorkOffsetAttr(
+      Decl *D, const SYCLIntelNoGlobalWorkOffsetAttr &A);
+  void AddSYCLIntelLoopFuseAttr(Decl *D, const AttributeCommonInfo &CI,
+                                Expr *E);
+  SYCLIntelLoopFuseAttr *
+  MergeSYCLIntelLoopFuseAttr(Decl *D, const SYCLIntelLoopFuseAttr &A);
+  void AddSYCLIntelPrivateCopiesAttr(Decl *D, const AttributeCommonInfo &CI,
+                                     Expr *E);
+  void AddSYCLIntelMaxReplicatesAttr(Decl *D, const AttributeCommonInfo &CI,
+                                     Expr *E);
+  SYCLIntelMaxReplicatesAttr *
+  MergeSYCLIntelMaxReplicatesAttr(Decl *D, const SYCLIntelMaxReplicatesAttr &A);
+  void AddSYCLIntelForcePow2DepthAttr(Decl *D, const AttributeCommonInfo &CI,
+                                      Expr *E);
+  SYCLIntelForcePow2DepthAttr *
+  MergeSYCLIntelForcePow2DepthAttr(Decl *D,
+                                   const SYCLIntelForcePow2DepthAttr &A);
+  void AddSYCLIntelInitiationIntervalAttr(Decl *D,
+                                          const AttributeCommonInfo &CI,
+                                          Expr *E);
+  SYCLIntelInitiationIntervalAttr *MergeSYCLIntelInitiationIntervalAttr(
+      Decl *D, const SYCLIntelInitiationIntervalAttr &A);
 
-    /// IntToPointer - The assignment converts an int to a pointer, which we
-    /// accept as an extension.
-    IntToPointer,
+  SYCLIntelMaxConcurrencyAttr *MergeSYCLIntelMaxConcurrencyAttr(
+      Decl *D, const SYCLIntelMaxConcurrencyAttr &A);
+  void AddSYCLIntelMaxGlobalWorkDimAttr(Decl *D, const AttributeCommonInfo &CI,
+                                        Expr *E);
+  SYCLIntelMaxGlobalWorkDimAttr *
+  MergeSYCLIntelMaxGlobalWorkDimAttr(Decl *D,
+                                     const SYCLIntelMaxGlobalWorkDimAttr &A);
+  void AddSYCLIntelMinWorkGroupsPerComputeUnitAttr(
+      Decl *D, const AttributeCommonInfo &CI, Expr *E);
+  SYCLIntelMinWorkGroupsPerComputeUnitAttr *
+  MergeSYCLIntelMinWorkGroupsPerComputeUnitAttr(
+      Decl *D, const SYCLIntelMinWorkGroupsPerComputeUnitAttr &A);
+  void AddSYCLIntelMaxWorkGroupsPerMultiprocessorAttr(
+      Decl *D, const AttributeCommonInfo &CI, Expr *E);
+  SYCLIntelMaxWorkGroupsPerMultiprocessorAttr *
+  MergeSYCLIntelMaxWorkGroupsPerMultiprocessorAttr(
+      Decl *D, const SYCLIntelMaxWorkGroupsPerMultiprocessorAttr &A);
+  void AddSYCLIntelBankWidthAttr(Decl *D, const AttributeCommonInfo &CI,
+                                 Expr *E);
+  SYCLIntelBankWidthAttr *
+  MergeSYCLIntelBankWidthAttr(Decl *D, const SYCLIntelBankWidthAttr &A);
+  void AddSYCLIntelNumBanksAttr(Decl *D, const AttributeCommonInfo &CI,
+                                Expr *E);
+  SYCLIntelNumBanksAttr *
+  MergeSYCLIntelNumBanksAttr(Decl *D, const SYCLIntelNumBanksAttr &A);
+  SYCLDeviceHasAttr *MergeSYCLDeviceHasAttr(Decl *D,
+                                            const SYCLDeviceHasAttr &A);
+  void AddSYCLDeviceHasAttr(Decl *D, const AttributeCommonInfo &CI,
+                            Expr **Exprs, unsigned Size);
+  SYCLUsesAspectsAttr *MergeSYCLUsesAspectsAttr(Decl *D,
+                                                const SYCLUsesAspectsAttr &A);
+  void AddSYCLUsesAspectsAttr(Decl *D, const AttributeCommonInfo &CI,
+                              Expr **Exprs, unsigned Size);
+  bool CheckMaxAllowedWorkGroupSize(const Expr *RWGSXDim, const Expr *RWGSYDim,
+                                    const Expr *RWGSZDim, const Expr *MWGSXDim,
+                                    const Expr *MWGSYDim, const Expr *MWGSZDim);
+  void AddSYCLIntelMaxWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI,
+                                        Expr *XDim, Expr *YDim, Expr *ZDim);
+  SYCLIntelMaxWorkGroupSizeAttr *
+  MergeSYCLIntelMaxWorkGroupSizeAttr(Decl *D,
+                                     const SYCLIntelMaxWorkGroupSizeAttr &A);
+  void CheckSYCLAddIRAttributesFunctionAttrConflicts(Decl *D);
+  SYCLAddIRAttributesFunctionAttr *MergeSYCLAddIRAttributesFunctionAttr(
+      Decl *D, const SYCLAddIRAttributesFunctionAttr &A);
+  void AddSYCLAddIRAttributesFunctionAttr(Decl *D,
+                                          const AttributeCommonInfo &CI,
+                                          MutableArrayRef Args);
+  SYCLAddIRAttributesKernelParameterAttr *
+  MergeSYCLAddIRAttributesKernelParameterAttr(
+      Decl *D, const SYCLAddIRAttributesKernelParameterAttr &A);
+  void AddSYCLAddIRAttributesKernelParameterAttr(Decl *D,
+                                                 const AttributeCommonInfo &CI,
+                                                 MutableArrayRef Args);
+  SYCLAddIRAttributesGlobalVariableAttr *
+  MergeSYCLAddIRAttributesGlobalVariableAttr(
+      Decl *D, const SYCLAddIRAttributesGlobalVariableAttr &A);
+  void AddSYCLAddIRAttributesGlobalVariableAttr(Decl *D,
+                                                const AttributeCommonInfo &CI,
+                                                MutableArrayRef Args);
+  SYCLAddIRAnnotationsMemberAttr *
+  MergeSYCLAddIRAnnotationsMemberAttr(Decl *D,
+                                      const SYCLAddIRAnnotationsMemberAttr &A);
+  void AddSYCLAddIRAnnotationsMemberAttr(Decl *D, const AttributeCommonInfo &CI,
+                                         MutableArrayRef Args);
+  void AddSYCLReqdWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI,
+                                    Expr *XDim, Expr *YDim, Expr *ZDim);
+  SYCLReqdWorkGroupSizeAttr *
+  MergeSYCLReqdWorkGroupSizeAttr(Decl *D, const SYCLReqdWorkGroupSizeAttr &A);
 
-    /// FunctionVoidPointer - The assignment is between a function pointer and
-    /// void*, which the standard doesn't allow, but we accept as an extension.
-    FunctionVoidPointer,
+  SYCLTypeAttr *MergeSYCLTypeAttr(Decl *D, const AttributeCommonInfo &CI,
+                                  SYCLTypeAttr::SYCLType TypeName);
 
-    /// IncompatiblePointer - The assignment is between two pointers types that
-    /// are not compatible, but we accept them as an extension.
-    IncompatiblePointer,
 
-    /// IncompatibleFunctionPointer - The assignment is between two function
-    /// pointers types that are not compatible, but we accept them as an
-    /// extension.
-    IncompatibleFunctionPointer,
+private:
+  /// AddMethodToGlobalPool - Add an instance or factory method to the global
+  /// pool. See descriptoin of AddInstanceMethodToGlobalPool.
+  void AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, bool instance);
 
-    /// 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,
+  /// 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);
 
-    /// 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,
+  ///@}
 
-    /// CompatiblePointerDiscardsQualifiers - The assignment discards
-    /// c/v/r qualifiers, which we accept as an extension.
-    CompatiblePointerDiscardsQualifiers,
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-    /// IncompatiblePointerDiscardsQualifiers - The assignment
-    /// discards qualifiers that we don't permit to be discarded,
-    /// like address spaces.
-    IncompatiblePointerDiscardsQualifiers,
+  /// \name ObjC Expressions
+  /// Implementations are in SemaExprObjC.cpp
+  ///@{
 
-    /// 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,
+public:
+  /// Caches identifiers/selectors for NSFoundation APIs.
+  std::unique_ptr NSAPIObj;
 
-    /// 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 NSNumber class.
+  ObjCInterfaceDecl *NSNumberDecl;
 
-    /// IncompatibleVectors - The assignment is between two vector types that
-    /// have the same size, which we accept as an extension.
-    IncompatibleVectors,
+  /// The declaration of the Objective-C NSValue class.
+  ObjCInterfaceDecl *NSValueDecl;
 
-    /// IntToBlockPointer - The assignment converts an int to a block
-    /// pointer. We disallow this.
-    IntToBlockPointer,
+  /// Pointer to NSNumber type (NSNumber *).
+  QualType NSNumberPointer;
 
-    /// IncompatibleBlockPointer - The assignment is between two block
-    /// pointers types that are not compatible.
-    IncompatibleBlockPointer,
+  /// Pointer to NSValue type (NSValue *).
+  QualType NSValuePointer;
 
-    /// 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 Objective-C NSNumber methods used to create NSNumber literals.
+  ObjCMethodDecl *NSNumberLiteralMethods[NSAPI::NumNSNumberLiteralMethods];
 
-    /// IncompatibleObjCWeakRef - Assigning a weak-unavailable object to an
-    /// object with __weak qualifier.
-    IncompatibleObjCWeakRef,
+  /// The declaration of the Objective-C NSString class.
+  ObjCInterfaceDecl *NSStringDecl;
 
-    /// Incompatible - We reject this conversion outright, it is invalid to
-    /// represent it in the AST.
-    Incompatible
-  };
+  /// Pointer to NSString type (NSString *).
+  QualType NSStringPointer;
 
-  /// 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 stringWithUTF8String: method.
+  ObjCMethodDecl *StringWithUTF8StringMethod;
 
-  /// 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 valueWithBytes:objCType: method.
+  ObjCMethodDecl *ValueWithBytesObjCTypeMethod;
 
-  /// 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 Objective-C NSArray class.
+  ObjCInterfaceDecl *NSArrayDecl;
 
-  /// 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 arrayWithObjects:count: method.
+  ObjCMethodDecl *ArrayWithObjectsMethod;
 
-  /// 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 Objective-C NSDictionary class.
+  ObjCInterfaceDecl *NSDictionaryDecl;
 
-  /// 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);
+  /// The declaration of the dictionaryWithObjects:forKeys:count: method.
+  ObjCMethodDecl *DictionaryWithObjectsMethod;
 
-  // 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);
+  /// id type.
+  QualType QIDNSCopying;
 
-  bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType);
+  /// will hold 'respondsToSelector:'
+  Selector RespondsToSelectorSel;
 
-  bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType);
+  ExprResult HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
+                                       Expr *BaseExpr, SourceLocation OpLoc,
+                                       DeclarationName MemberName,
+                                       SourceLocation MemberLoc,
+                                       SourceLocation SuperLoc,
+                                       QualType SuperType, bool Super);
 
-  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);
+  ExprResult ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
+                                       IdentifierInfo &propertyName,
+                                       SourceLocation receiverNameLoc,
+                                       SourceLocation propertyNameLoc);
 
-  ExprResult PerformQualificationConversion(
-      Expr *E, QualType Ty, ExprValueKind VK = VK_PRValue,
-      CheckedConversionKind CCK = CCK_ImplicitConversion);
+  // ParseObjCStringLiteral - Parse Objective-C string literals.
+  ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
+                                    ArrayRef Strings);
 
-  /// the following "Check" methods will return a valid/converted QualType
-  /// or a null QualType (indicating an error diagnostic was issued).
+  ExprResult BuildObjCStringLiteral(SourceLocation AtLoc, StringLiteral *S);
 
-  /// 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);
+  /// 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);
 
-  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);
+  /// 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);
 
-  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 BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
+                                          Expr *IndexExpr,
+                                          ObjCMethodDecl *getterMethod,
+                                          ObjCMethodDecl *setterMethod);
 
-  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
+  BuildObjCDictionaryLiteral(SourceRange SR,
+                             MutableArrayRef Elements);
 
-  QualType FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
-                                        SourceLocation QuestionLoc);
+  ExprResult BuildObjCEncodeExpression(SourceLocation AtLoc,
+                                       TypeSourceInfo *EncodedTypeInfo,
+                                       SourceLocation RParenLoc);
 
-  bool DiagnoseConditionalForNull(const Expr *LHSExpr, const Expr *RHSExpr,
-                                  SourceLocation QuestionLoc);
+  ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc,
+                                       SourceLocation EncodeLoc,
+                                       SourceLocation LParenLoc, ParsedType Ty,
+                                       SourceLocation RParenLoc);
 
-  void DiagnoseAlwaysNonNullPointer(Expr *E,
-                                    Expr::NullPointerConstantKind NullType,
-                                    bool IsEqual, SourceRange Range);
+  /// ParseObjCSelectorExpression - Build selector expression for \@selector
+  ExprResult ParseObjCSelectorExpression(Selector Sel, SourceLocation AtLoc,
+                                         SourceLocation SelLoc,
+                                         SourceLocation LParenLoc,
+                                         SourceLocation RParenLoc,
+                                         bool WarnMultipleSelectors);
+
+  /// 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 };
 
@@ -13713,8 +13049,7 @@ class Sema final {
                                           CheckedConversionKind CCK,
                                           bool Diagnose = true,
                                           bool DiagnoseCFAudited = false,
-                                          BinaryOperatorKind Opc = BO_PtrMemD
-                                          );
+                                          BinaryOperatorKind Opc = BO_PtrMemD);
 
   Expr *stripARCUnbridgedCast(Expr *e);
   void diagnoseARCUnbridgedCast(Expr *e);
@@ -13722,20 +13057,6 @@ class Sema final {
   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.
@@ -13764,142 +13085,398 @@ class Sema final {
   /// 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);
+  }
+
+  /// 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);
+  }
+
+  ///@}
+
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
+
+  /// \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);
 
-    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) {}
+  ///@}
 
-  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.
+  /// \name Code Completion
+  /// Implementations are in SemaCodeComplete.cpp
+  ///@{
+
+public:
+  /// Code-completion consumer.
+  CodeCompleteConsumer *CodeCompleter;
+
+  /// 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,
   };
-  QualType PreferredConditionType(ConditionKind K) const {
-    return K == ConditionKind::Switch ? Context.IntTy : Context.BoolTy;
-  }
 
-  ConditionResult ActOnCondition(Scope *S, SourceLocation Loc, Expr *SubExpr,
-                                 ConditionKind CK, bool MissingOK = false);
+  void CodeCompleteModuleImport(SourceLocation ImportLoc, ModuleIdPath Path);
+  void CodeCompleteOrdinaryName(Scope *S,
+                                ParserCompletionContext CompletionContext);
+  void CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, bool AllowNonIdentifiers,
+                            bool AllowNestedNameSpecifiers);
 
-  ConditionResult ActOnConditionVariable(Decl *ConditionVar,
-                                         SourceLocation StmtLoc,
-                                         ConditionKind CK);
+  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);
 
-  DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D);
+  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);
 
-  ExprResult CheckConditionVariable(VarDecl *ConditionVar,
-                                    SourceLocation StmtLoc,
-                                    ConditionKind CK);
-  ExprResult CheckSwitchCondition(SourceLocation SwitchLoc, Expr *Cond);
+  void CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
+                                    bool AfterAmpersand);
+  void CodeCompleteAfterFunctionEquals(Declarator &D);
 
-  /// 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);
+  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);
 
-  /// ActOnExplicitBoolSpecifier - Build an ExplicitSpecifier from an expression
-  /// found in an explicit(bool) specifier.
-  ExplicitSpecifier ActOnExplicitBoolSpecifier(Expr *E);
+  ///@}
 
-  /// tryResolveExplicitSpecifier - Attempt to resolve the explict specifier.
-  /// Returns true if the explicit specifier is now resolved.
-  bool tryResolveExplicitSpecifier(ExplicitSpecifier &ExplicitSpec);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// DiagnoseAssignmentAsCondition - Given that an expression is
-  /// being used as a boolean condition, warn if it's an assignment.
-  void DiagnoseAssignmentAsCondition(Expr *E);
+  /// \name FixIt Helpers
+  /// Implementations are in SemaFixItUtils.cpp
+  ///@{
 
-  /// Redundant parentheses over an equality comparison can indicate
-  /// that the user intended an assignment used as condition.
-  void DiagnoseEqualityWithExtraParens(ParenExpr *ParenE);
+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;
 
-  /// 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);
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
 
-  /// Abstract base class used for diagnosing integer constant
-  /// expression violations.
-  class VerifyICEDiagnoser {
-  public:
-    bool Suppress;
+  /// \name API Notes
+  /// Implementations are in SemaAPINotes.cpp
+  ///@{
 
-    VerifyICEDiagnoser(bool Suppress = false) : Suppress(Suppress) { }
+public:
+  /// Map any API notes provided for this declaration to attributes on the
+  /// declaration.
+  ///
+  /// Triggered by declaration-attribute processing.
+  void ProcessAPINotes(Decl *D);
 
-    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 Name Lookup for RISC-V Vector Intrinsic
+  /// Implementations are in SemaRISCVVectorLookup.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:
+  /// Indicate RISC-V vector builtin functions enabled or not.
+  bool DeclareRISCVVBuiltins = false;
 
-  /// 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);
+  /// 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
@@ -13912,6 +13489,9 @@ class Sema final {
   /// before incrementing, so you can emit an error.
   bool PopForceCUDAHostDevice();
 
+  ExprResult ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc,
+                                     MultiExprArg ExecConfig,
+                                     SourceLocation GGGLoc);
   class DeviceDeferredDiagnostic {
   public:
     DeviceDeferredDiagnostic(SourceLocation SL, const PartialDiagnostic &PD,
@@ -13925,7 +13505,6 @@ class Sema final {
     PartialDiagnosticAt Diagnostic;
     DeviceDiagnosticReason Reason;
   };
-
   /// 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.
@@ -13980,54 +13559,6 @@ class Sema final {
   /// 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.
   ///
@@ -14118,7 +13649,6 @@ class Sema final {
   /// 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
@@ -14169,8 +13699,7 @@ class Sema final {
   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).
@@ -14199,739 +13728,1471 @@ class Sema final {
   /// parameters specified via <<<>>>.
   std::string getCudaConfigureFuncName() const;
 
-  /// \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,
-  };
+private:
+  unsigned ForceCUDAHostDeviceDepth = 0;
 
-  void CodeCompleteModuleImport(SourceLocation ImportLoc, ModuleIdPath Path);
-  void CodeCompleteOrdinaryName(Scope *S,
-                                ParserCompletionContext CompletionContext);
-  void CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
-                            bool AllowNonIdentifiers,
-                            bool AllowNestedNameSpecifiers);
+  ///@}
+
+  //
+  //
+  // -------------------------------------------------------------------------
+  //
+  //
+
+  /// \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);
 
-  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.
+  /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current
+  /// context is "used as host code".
   ///
-  /// If the code completion point has been reached, also reports the function
-  /// signatures that were considered.
+  /// - 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.
   ///
-  /// 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);
+  /// 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);
 
-  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);
+  /// 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);
 
-  void CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
-                                    bool AfterAmpersand);
-  void CodeCompleteAfterFunctionEquals(Declarator &D);
+  /// Act on \p D, a function definition inside of an `omp [begin/end] assumes`.
+  void ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D);
 
-  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);
-  //@}
+  /// Can we exit an OpenMP declare variant scope at the moment.
+  bool isInOpenMPDeclareVariantScope() const {
+    return !OMPDeclareVariantScopes.empty();
+  }
 
-  //===--------------------------------------------------------------------===//
-  // Extra semantic analysis beyond the C type system
+  ExprResult
+  VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind,
+                                        bool StrictlyPositive = true,
+                                        bool SuppressExprDiags = false);
 
-public:
-  SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL,
-                                                unsigned ByteNo) const;
+  /// 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);
 
-  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
-  };
+  /// Handle a `omp begin declare variant`.
+  void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI);
 
-  // Used to grab the relevant information from a FormatAttr and a
-  // FunctionDeclaration.
-  struct FormatStringInfo {
-    unsigned FormatIdx;
-    unsigned FirstDataArg;
-    FormatArgumentPassingKind ArgPassingKind;
-  };
+  /// Handle a `omp end declare variant`.
+  void ActOnOpenMPEndDeclareVariant();
 
-  static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember,
-                                  bool IsVariadic, FormatStringInfo *FSI);
+  /// Function tries to capture lambda's captured variables in the OpenMP region
+  /// before the original lambda is captured.
+  void tryCaptureOpenMPLambdas(ValueDecl *V);
 
-private:
-  void CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr,
-                        const ArraySubscriptExpr *ASE = nullptr,
-                        bool AllowOnePastEnd = true, bool IndexNegated = false);
-  void CheckArrayAccess(const Expr *E);
+  /// 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;
 
-  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 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);
 
-  void checkAIXMemberAlignment(SourceLocation Loc, const Expr *Arg);
+  /// 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);
+
+  ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK,
+                                   ExprObjectKind OK, SourceLocation Loc);
+
+  /// If the current region is a loop-based region, mark the start of the loop
+  /// construct.
+  void startOpenMPLoop();
+
+  /// If the current region is a range loop-based region, mark the start of the
+  /// loop construct.
+  void startOpenMPCXXRangeFor();
+
+  /// 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;
+
+  /// 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);
+
+  /// 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;
+
+  /// 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;
+
+  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);
+
+  /// 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);
 
-  void CheckArgAlignment(SourceLocation Loc, NamedDecl *FDecl,
-                         StringRef ParamName, QualType ArgTy, QualType ParamTy);
+  /// Called on well-formed '\#pragma omp metadirective' after parsing
+  /// of the  associated statement.
+  StmtResult ActOnOpenMPMetaDirective(ArrayRef Clauses,
+                                      Stmt *AStmt, SourceLocation StartLoc,
+                                      SourceLocation EndLoc);
 
-  void checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto,
-                 const Expr *ThisArg, ArrayRef Args,
-                 bool IsMemberFunction, SourceLocation Loc, SourceRange Range,
-                 VariadicCallType CallType);
+  // 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);
 
-  void CheckSYCLKernelCall(FunctionDecl *CallerFunc,
-                           ArrayRef Args);
+  /// Called on well-formed '#pragma omp [begin] assume[s]'.
+  void ActOnOpenMPAssumesDirective(SourceLocation Loc,
+                                   OpenMPDirectiveKind DKind,
+                                   ArrayRef Assumptions,
+                                   bool SkippedClauses);
 
-  bool CheckObjCString(Expr *Arg);
-  ExprResult CheckOSLogFormatStringArg(Expr *Arg);
+  /// Check if there is an active global `omp begin assumes` directive.
+  bool isInOpenMPAssumeScope() const { return !OMPAssumeScoped.empty(); }
 
-  ExprResult CheckBuiltinFunctionCall(FunctionDecl *FDecl,
-                                      unsigned BuiltinID, CallExpr *TheCall);
+  /// Check if there is an active global `omp assumes` directive.
+  bool hasGlobalOpenMPAssumes() const { return !OMPAssumeGlobal.empty(); }
 
-  bool CheckTSBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
-                                  CallExpr *TheCall);
+  /// Called on well-formed '#pragma omp end assumes'.
+  void ActOnOpenMPEndAssumesDirective();
 
-  void checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD, CallExpr *TheCall);
+  /// 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);
 
-  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);
+  /// 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 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);
+  struct DeclareTargetContextInfo {
+    struct MapInfo {
+      OMPDeclareTargetDeclAttr::MapTypeTy MT;
+      SourceLocation Loc;
+    };
+    /// Explicitly listed variables and functions in a 'to' or 'link' clause.
+    llvm::DenseMap ExplicitlyMapped;
 
-  bool CheckIntelFPGARegBuiltinFunctionCall(unsigned BuiltinID, CallExpr *Call);
-  bool CheckIntelFPGAMemBuiltinFunctionCall(CallExpr *Call);
+    /// The 'device_type' as parsed from the clause.
+    OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any;
 
-  bool CheckIntelSYCLPtrAnnotationBuiltinFunctionCall(unsigned BuiltinID,
-                                                      CallExpr *Call);
+    /// The directive kind, `begin declare target` or `declare target`.
+    OpenMPDirectiveKind Kind;
 
-  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);
+    /// The directive with indirect clause.
+    std::optional Indirect;
 
-public:
-  bool IsLayoutCompatible(QualType T1, QualType T2) const;
+    /// The directive location.
+    SourceLocation Loc;
 
-  // Used by C++ template instantiation.
-  ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
-  ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
-                                   SourceLocation BuiltinLoc,
-                                   SourceLocation RParenLoc);
+    DeclareTargetContextInfo(OpenMPDirectiveKind Kind, SourceLocation Loc)
+        : Kind(Kind), Loc(Loc) {}
+  };
 
-  template 
-  static bool isTypeDecoratedWithDeclAttribute(QualType Ty) {
-    const CXXRecordDecl *RecTy = Ty->getAsCXXRecordDecl();
-    if (!RecTy)
-      return false;
+  /// Called on the start of target region i.e. '#pragma omp declare target'.
+  bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI);
 
-    if (RecTy->hasAttr())
-      return true;
+  /// Called at the end of target region i.e. '#pragma omp end declare target'.
+  const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective();
 
-    if (auto *CTSD = dyn_cast(RecTy)) {
-      ClassTemplateDecl *Template = CTSD->getSpecializedTemplate();
-      if (CXXRecordDecl *RD = Template->getTemplatedDecl())
-        return RD->hasAttr();
-    }
-    return false;
-  }
+  /// 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);
 
-  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);
+  /// Called on correct id-expression from the '#pragma omp declare target'.
+  void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc,
+                                    OMPDeclareTargetDeclAttr::MapTypeTy MT,
+                                    DeclareTargetContextInfo &DTCI);
 
-  bool SemaBuiltinNonDeterministicValue(CallExpr *TheCall);
+  /// Check declaration inside target region.
+  void
+  checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
+                                   SourceLocation IdLoc = SourceLocation());
 
-  // Matrix builtin handling.
-  ExprResult SemaBuiltinMatrixTranspose(CallExpr *TheCall,
-                                        ExprResult CallResult);
-  ExprResult SemaBuiltinMatrixColumnMajorLoad(CallExpr *TheCall,
-                                              ExprResult CallResult);
-  ExprResult SemaBuiltinMatrixColumnMajorStore(CallExpr *TheCall,
-                                               ExprResult CallResult);
+  /// Adds OMPDeclareTargetDeclAttr to referenced variables in declare target
+  /// directive.
+  void ActOnOpenMPDeclareTargetInitializer(Decl *D);
 
-  // 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);
+  /// 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:
-  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 if currently in OpenMP task with untied clause context.
+  bool isInOpenMPTaskUntiedContext() const;
 
-  bool FormatStringHasSArg(const StringLiteral *FExpr);
+  /// Return true inside OpenMP declare target region.
+  bool isInOpenMPDeclareTargetContext() const {
+    return !DeclareTargetNesting.empty();
+  }
+  /// Return true inside OpenMP target region.
+  bool isInOpenMPTargetExecutionDirective() const;
 
-  static bool GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx);
+  /// Return the number of captured regions created for an OpenMP directive.
+  static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind);
 
-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);
+  /// Initialization of captured region for OpenMP region.
+  void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope);
 
-  void CheckInfNaNFunction(const CallExpr *Call, const FunctionDecl *FDecl);
+  /// Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to
+  /// an OpenMP loop directive.
+  StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt);
 
-  void CheckAbsoluteValueFunction(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);
+
+  /// 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);
 
-  /// A pair of ArgumentKind identifier and magic value.  This uniquely
-  /// identifies the magic value.
-  typedef std::pair TypeTagMagicValue;
+  /// Called on well-formed 'message' clause.
+  /// passing string for message.
+  OMPClause *ActOnOpenMPMessageClause(Expr *MS, SourceLocation StartLoc,
+                                      SourceLocation LParenLoc,
+                                      SourceLocation EndLoc);
 
-private:
-  /// A map from magic value to type information.
-  std::unique_ptr>
-      TypeTagForDatatypeMagicValues;
+  /// 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
+  };
 
-  /// 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);
+  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);
 
-  /// 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);
+  /// 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);
 
-  /// The parser's current scope.
-  ///
-  /// The parser maintains this state here.
-  Scope *CurScope;
+  /// Called on a well-formed 'ompx_dyn_cgroup_mem' clause.
+  OMPClause *ActOnOpenMPXDynCGroupMemClause(Expr *Size, SourceLocation StartLoc,
+                                            SourceLocation LParenLoc,
+                                            SourceLocation EndLoc);
 
-  mutable IdentifierInfo *Ident_super;
+  /// Called on well-formed 'doacross' clause.
+  OMPClause *
+  ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType,
+                            SourceLocation DepLoc, SourceLocation ColonLoc,
+                            ArrayRef VarList, 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 a well-formed 'ompx_attribute' clause.
+  OMPClause *ActOnOpenMPXAttributeClause(ArrayRef Attrs,
+                                         SourceLocation StartLoc,
+                                         SourceLocation LParenLoc,
+                                         SourceLocation EndLoc);
 
-  IdentifierInfo *Ident_NSError = nullptr;
+  /// Called on a well-formed 'ompx_bare' clause.
+  OMPClause *ActOnOpenMPXBareClause(SourceLocation StartLoc,
+                                    SourceLocation EndLoc);
 
-  /// The handler for the FileChanged preprocessor events.
-  ///
-  /// Used for diagnostics that implement custom semantic analysis for #include
-  /// directives, like -Wpragma-pack.
-  sema::SemaPPCallbacks *SemaPPCallbackHandler;
+private:
+  void *VarDataSharingAttributesStack;
 
-protected:
-  friend class Parser;
-  friend class InitializationSequence;
-  friend class ASTReader;
-  friend class ASTDeclReader;
-  friend class ASTWriter;
+  /// Number of nested '#pragma omp declare target' directives.
+  SmallVector DeclareTargetNesting;
 
-public:
-  /// Retrieve the keyword associated
-  IdentifierInfo *getNullabilityKeyword(NullabilityKind nullability);
+  /// Initialization of data-sharing attributes stack.
+  void InitDataSharingAttributesStack();
+  void DestroyDataSharingAttributesStack();
 
-  /// The struct behind the CFErrorRef pointer.
-  RecordDecl *CFError = nullptr;
-  bool isCFError(RecordDecl *D);
+  /// Returns OpenMP nesting level for current directive.
+  unsigned getOpenMPNestingLevel() const;
 
-  /// Retrieve the identifier "NSError".
-  IdentifierInfo *getNSErrorIdent();
+  /// Adjusts the function scopes index for the target-based regions.
+  void adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
+                                    unsigned Level) const;
 
-  /// 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; }
+  /// Returns the number of scopes associated with the construct on the given
+  /// OpenMP level.
+  int getNumberOfConstructScopes(unsigned Level) const;
 
-  void incrementMSManglingNumber() const {
-    return CurScope->incrementMSManglingNumber();
-  }
+  /// Push new OpenMP function region for non-capturing function.
+  void pushOpenMPFunctionRegion();
 
-  IdentifierInfo *getSuperIdentifier() const;
+  /// Pop OpenMP function region for non-capturing function.
+  void popOpenMPFunctionRegion(const sema::FunctionScopeInfo *OldFSI);
 
-  ObjCContainerDecl *getObjCDeclContext() const;
+  /// Analyzes and checks a loop nest for use by a loop transformation.
+  ///
+  /// \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();
-    }
-
-  private:
-    Sema &S;
-    decltype(DelayedOverridingExceptionSpecChecks)
-        SavedOverridingExceptionSpecChecks;
-    decltype(DelayedEquivalentExceptionSpecChecks)
-        SavedEquivalentExceptionSpecChecks;
+  /// The current `omp begin/end declare variant` scopes.
+  SmallVector OMPDeclareVariantScopes;
 
-    void swapSavedState() {
-      SavedOverridingExceptionSpecChecks.swap(
-          S.DelayedOverridingExceptionSpecChecks);
-      SavedEquivalentExceptionSpecChecks.swap(
-          S.DelayedEquivalentExceptionSpecChecks);
-    }
-  };
+  /// The current `omp begin/end assumes` scopes.
+  SmallVector OMPAssumeScoped;
 
-  /// Helper class that collects misaligned member designations and
-  /// their location info for delayed diagnostics.
-  struct MisalignedMember {
-    Expr *E;
-    RecordDecl *RD;
-    ValueDecl *MD;
-    CharUnits Alignment;
+  /// All `omp assumes` we encountered so far.
+  SmallVector OMPAssumeGlobal;
 
-    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()) {}
+  /// 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);
 
-    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();
+private:
 
-  /// 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 CheckSYCLKernelCall(FunctionDecl *CallerFunc,
+                           ArrayRef Args);
 
-  /// 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
-  };
+  bool CheckIntelFPGARegBuiltinFunctionCall(unsigned BuiltinID, CallExpr *Call);
+  bool CheckIntelFPGAMemBuiltinFunctionCall(CallExpr *Call);
 
+  bool CheckIntelSYCLPtrAnnotationBuiltinFunctionCall(unsigned BuiltinID,
+                                                      CallExpr *Call);
 private:
   // We store SYCL Kernels here and handle separately -- which is a hack.
   // FIXME: It would be best to refactor this.
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index e7774e5a9392d..686e5e99f4a62 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -578,7 +578,7 @@ def StdCLibraryFunctionsChecker : Checker<"StdCLibraryFunctions">,
                   "ModelPOSIX",
                   "If set to true, the checker models additional functions "
                   "from the POSIX standard.",
-                  "false",
+                  "true",
                   InAlpha>
   ]>,
   WeakDependencies<[CallAndMessageChecker, NonNullParamChecker]>,
@@ -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/PathSensitive/CallDescription.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h
index 965838a4408c2..3432d2648633c 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h
@@ -27,20 +27,48 @@ class IdentifierInfo;
 
 namespace clang {
 namespace ento {
-
-enum CallDescriptionFlags : unsigned {
-  CDF_None = 0,
-
-  /// Describes a C standard function that is sometimes implemented as a macro
-  /// that expands to a compiler builtin with some __builtin prefix.
-  /// The builtin may as well have a few extra arguments on top of the requested
-  /// number of arguments.
-  CDF_MaybeBuiltin = 1 << 0,
-};
-
-/// This class represents a description of a function call using the number of
-/// arguments and the name of the function.
+/// A `CallDescription` is a pattern that can be used to _match_ calls
+/// based on the qualified name and the argument/parameter counts.
 class CallDescription {
+public:
+  enum class Mode {
+    /// Match calls to functions from the C standard library. On some platforms
+    /// some functions may be implemented as macros that expand to calls to
+    /// built-in variants of the given functions, so in this mode we use some
+    /// heuristics to recognize these implementation-defined variants:
+    ///  - We also accept calls where the name is derived from the specified
+    ///    name by adding "__builtin" or similar prefixes/suffixes.
+    ///  - 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 .
+    CLibrary,
+
+    /// Matches "simple" functions that are not methods. (Static methods are
+    /// methods.)
+    SimpleFunc,
+
+    /// Matches a C++ method (may be static, may be virtual, may be an
+    /// overloaded operator, a constructor or a destructor).
+    CXXMethod,
+
+    /// Match any CallEvent that is not an ObjCMethodCall.
+    /// FIXME: Previously this was the default behavior of CallDescription, but
+    /// its use should be replaced by a more specific mode almost everywhere.
+    Unspecified,
+
+    /// FIXME: Add support for ObjCMethodCall events (I'm not adding it because
+    /// I'm not familiar with Objective-C). Note that currently an early return
+    /// in `bool matches(const CallEvent &Call) const;` discards all
+    /// Objective-C method calls.
+  };
+
+private:
   friend class CallEvent;
   using MaybeCount = std::optional;
 
@@ -50,20 +78,26 @@ class CallDescription {
   std::vector QualifiedName;
   MaybeCount RequiredArgs;
   MaybeCount RequiredParams;
-  int Flags;
+  Mode MatchAs;
 
 public:
   /// Constructs a CallDescription object.
   ///
+  /// @param MatchAs Specifies the kind of the call that should be matched.
+  ///
   /// @param QualifiedName The list of the name qualifiers of the function that
   /// will be matched. The user is allowed to skip any of the qualifiers.
   /// For example, {"std", "basic_string", "c_str"} would match both
   /// std::basic_string<...>::c_str() and std::__1::basic_string<...>::c_str().
   ///
-  /// @param RequiredArgs The number of arguments that is expected to match a
-  /// call. Omit this parameter to match every occurrence of call with a given
-  /// name regardless the number of arguments.
-  CallDescription(CallDescriptionFlags Flags, ArrayRef QualifiedName,
+  /// @param RequiredArgs The expected number of arguments that are passed to
+  /// the function. Omit this parameter (or pass std::nullopt) to match every
+  /// occurrence without checking the argument count in the call.
+  ///
+  /// @param RequiredParams The expected number of parameters in the function
+  /// definition that is called. Omit this parameter to match every occurrence
+  /// without checking the parameter count in the definition.
+  CallDescription(Mode MatchAs, ArrayRef QualifiedName,
                   MaybeCount RequiredArgs = std::nullopt,
                   MaybeCount RequiredParams = std::nullopt);
 
@@ -222,6 +256,10 @@ template  class CallDescriptionMap {
   }
 };
 
+/// Enumerators of this enum class are used to construct CallDescription
+/// objects; in that context the fully qualified name is needlessly verbose.
+using CDM = CallDescription::Mode;
+
 /// An immutable set of CallDescriptions.
 /// Checkers can efficiently decide if a given CallEvent matches any
 /// CallDescription in the set.
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
index 8dbe767cef9d7..8e392421fef9b 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
@@ -149,12 +149,6 @@ class CoreEngine {
   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 ed5c4adb5e3d5..f7894fb83ce65 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -190,16 +190,6 @@ class ExprEngine {
     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/lib/APINotes/APINotesReader.cpp b/clang/lib/APINotes/APINotesReader.cpp
index 55ea4bae81e6e..fbbe9c32ce125 100644
--- a/clang/lib/APINotes/APINotesReader.cpp
+++ b/clang/lib/APINotes/APINotesReader.cpp
@@ -5,7 +5,13 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-
+//
+// This file implements the \c APINotesReader class that reads source
+// API notes data providing additional information about source code as
+// a separate input, such as the non-nil/nilable annotations for
+// method parameters.
+//
+//===----------------------------------------------------------------------===//
 #include "clang/APINotes/APINotesReader.h"
 #include "APINotesFormat.h"
 #include "llvm/ADT/Hashing.h"
diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt
index 6ea1ca3e76cf3..3fba052d916c9 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 0e9d97cad94a0..c8567edbd2e9f 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -2469,7 +2469,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.
@@ -2491,14 +2491,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 {
@@ -2576,11 +2581,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,
@@ -2638,7 +2643,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());
 
@@ -5046,7 +5053,13 @@ void RecordDecl::completeDefinition() {
 
   // Layouts are dumped when computed, so if we are dumping for all complete
   // types, we need to force usage to get types that wouldn't be used elsewhere.
-  if (Ctx.getLangOpts().DumpRecordLayoutsComplete)
+  //
+  // If the type is dependent, then we can't compute its layout because there
+  // is no way for us to know the size or alignment of a dependent type. Also
+  // ignore declarations marked as invalid since 'getASTRecordLayout()' asserts
+  // on that.
+  if (Ctx.getLangOpts().DumpRecordLayoutsComplete && !isDependentType() &&
+      !isInvalidDecl())
     (void)Ctx.getASTRecordLayout(this);
 }
 
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 117e802dae2d9..b4f2327d9c560 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -2543,8 +2543,19 @@ QualType CXXMethodDecl::getThisType(const FunctionProtoType *FPT,
                                     const CXXRecordDecl *Decl) {
   ASTContext &C = Decl->getASTContext();
   QualType ObjectTy = ::getThisObjectType(C, FPT, Decl);
-  return C.getLangOpts().HLSL ? C.getLValueReferenceType(ObjectTy)
-                              : C.getPointerType(ObjectTy);
+
+  // Unlike 'const' and 'volatile', a '__restrict' qualifier must be
+  // attached to the pointer type, not the pointee.
+  bool Restrict = FPT->getMethodQuals().hasRestrict();
+  if (Restrict)
+    ObjectTy.removeLocalRestrict();
+
+  ObjectTy = C.getLangOpts().HLSL ? C.getLValueReferenceType(ObjectTy)
+                                  : C.getPointerType(ObjectTy);
+
+  if (Restrict)
+    ObjectTy.addRestrict();
+  return ObjectTy;
 }
 
 QualType CXXMethodDecl::getThisType() const {
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 79c3c79e417fc..4051b31d20e1e 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)
@@ -13940,7 +13949,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()))
@@ -15852,7 +15863,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 60d8afecb2b3b..d912c101449d8 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"
@@ -108,8 +107,12 @@ Function *ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) {
         this->LambdaCaptures[Cap.first] = {
             Offset, Cap.second->getType()->isReferenceType()};
       }
-      if (LTC)
-        this->LambdaThisCapture = R->getField(LTC)->Offset;
+      if (LTC) {
+        QualType CaptureType = R->getField(LTC)->Decl->getType();
+        this->LambdaThisCapture = {R->getField(LTC)->Offset,
+                                   CaptureType->isReferenceType() ||
+                                       CaptureType->isPointerType()};
+      }
     }
   }
 
@@ -298,10 +301,7 @@ bool ByteCodeEmitter::emitOp(Opcode Op, const Tys &... Args, const SourceInfo &S
   if (SI)
     SrcMap.emplace_back(Code.size(), SI);
 
-  // The initializer list forces the expression to be evaluated
-  // for each argument in the variadic template, in order.
-  (void)std::initializer_list{(emit(P, Code, Args, Success), 0)...};
-
+  (..., emit(P, Code, Args, Success));
   return Success;
 }
 
diff --git a/clang/lib/AST/Interp/ByteCodeEmitter.h b/clang/lib/AST/Interp/ByteCodeEmitter.h
index 03de286582c91..548769329b7f8 100644
--- a/clang/lib/AST/Interp/ByteCodeEmitter.h
+++ b/clang/lib/AST/Interp/ByteCodeEmitter.h
@@ -62,7 +62,7 @@ class ByteCodeEmitter {
   /// Lambda captures.
   llvm::DenseMap LambdaCaptures;
   /// Offset of the This parameter in a lambda record.
-  unsigned LambdaThisCapture = 0;
+  ParamOffset LambdaThisCapture{0, false};
   /// Local descriptors.
   llvm::SmallVector, 2> Descriptors;
 
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index b151f8d0d7a79..d887170cbc5d2 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"
@@ -1220,14 +1219,18 @@ bool ByteCodeExprGen::VisitArrayInitLoopExpr(
 
 template 
 bool ByteCodeExprGen::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
+  const Expr *SourceExpr = E->getSourceExpr();
+  if (!SourceExpr)
+    return false;
+
   if (Initializing)
-    return this->visitInitializer(E->getSourceExpr());
+    return this->visitInitializer(SourceExpr);
 
-  PrimType SubExprT = classify(E->getSourceExpr()).value_or(PT_Ptr);
+  PrimType SubExprT = classify(SourceExpr).value_or(PT_Ptr);
   if (auto It = OpaqueExprs.find(E); It != OpaqueExprs.end())
     return this->emitGetLocal(SubExprT, It->second, E);
 
-  if (!this->visit(E->getSourceExpr()))
+  if (!this->visit(SourceExpr))
     return false;
 
   // At this point we either have the evaluated source expression or a pointer
@@ -2659,6 +2662,11 @@ bool ByteCodeExprGen::visitVarDecl(const VarDecl *VD) {
     if (P.getGlobal(VD))
       return true;
 
+    // Ignore external declarations. We will instead emit a dummy
+    // pointer when we see a DeclRefExpr for them.
+    if (VD->hasExternalStorage())
+      return true;
+
     std::optional GlobalIndex = P.createGlobal(VD, Init);
 
     if (!GlobalIndex)
@@ -2721,6 +2729,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()) {
@@ -2732,10 +2752,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;
@@ -2838,7 +2857,8 @@ bool ByteCodeExprGen::VisitCallExpr(const CallExpr *E) {
         return false;
     } else if (Func->isVariadic()) {
       uint32_t VarArgSize = 0;
-      unsigned NumParams = Func->getNumWrittenParams();
+      unsigned NumParams =
+          Func->getNumWrittenParams() + isa(E);
       for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I)
         VarArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));
       if (!this->emitCallVar(Func, VarArgSize, E))
@@ -2929,8 +2949,11 @@ bool ByteCodeExprGen::VisitCXXThisExpr(const CXXThisExpr *E) {
   if (DiscardResult)
     return true;
 
-  if (this->LambdaThisCapture > 0)
-    return this->emitGetThisFieldPtr(this->LambdaThisCapture, E);
+  if (this->LambdaThisCapture.Offset > 0) {
+    if (this->LambdaThisCapture.IsPtr)
+      return this->emitGetThisFieldPtr(this->LambdaThisCapture.Offset, E);
+    return this->emitGetPtrThisField(this->LambdaThisCapture.Offset, E);
+  }
 
   return this->emitThis(E);
 }
@@ -3213,12 +3236,6 @@ bool ByteCodeExprGen::VisitDeclRefExpr(const DeclRefExpr *E) {
   // we haven't seen yet.
   if (Ctx.getLangOpts().CPlusPlus) {
     if (const auto *VD = dyn_cast(D)) {
-      // Dummy for static locals
-      if (VD->isStaticLocal()) {
-        if (std::optional I = P.getOrCreateDummy(D))
-          return this->emitGetPtrGlobal(*I, E);
-        return false;
-      }
       // Visit local const variables like normal.
       if (VD->isLocalVarDecl() && VD->getType().isConstQualified()) {
         if (!this->visitVarDecl(VD))
@@ -3226,6 +3243,9 @@ bool ByteCodeExprGen::VisitDeclRefExpr(const DeclRefExpr *E) {
         // Retry.
         return this->VisitDeclRefExpr(E);
       }
+
+      if (VD->hasExternalStorage())
+        return this->emitInvalidDeclRef(E, E);
     }
   } else {
     if (const auto *VD = dyn_cast(D);
@@ -3235,11 +3255,11 @@ bool ByteCodeExprGen::VisitDeclRefExpr(const DeclRefExpr *E) {
       // Retry.
       return this->VisitDeclRefExpr(E);
     }
-
-    if (std::optional I = P.getOrCreateDummy(D))
-      return this->emitGetPtrGlobal(*I, E);
   }
 
+  if (std::optional I = P.getOrCreateDummy(D))
+    return this->emitGetPtrGlobal(*I, E);
+
   return this->emitInvalidDeclRef(E, E);
 }
 
diff --git a/clang/lib/AST/Interp/ByteCodeGenError.h b/clang/lib/AST/Interp/ByteCodeGenError.h
deleted file mode 100644
index af464b5ed4ab1..0000000000000
--- 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 d9213b12cbd08..6da3860f98d8c 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 b09019f3e65b7..15a9d46880e95 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"
@@ -41,8 +40,8 @@ bool Context::isPotentialConstantExpr(State &Parent, const FunctionDecl *FD) {
 }
 
 bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
-  assert(Stk.empty());
-  ByteCodeExprGen C(*this, *P, Parent, Stk, Result);
+  bool Recursing = !Stk.empty();
+  ByteCodeExprGen C(*this, *P, Parent, Stk);
 
   auto Res = C.interpretExpr(E, /*ConvertResultToRValue=*/E->isGLValue());
 
@@ -51,12 +50,14 @@ bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
     return false;
   }
 
-  assert(Stk.empty());
+  if (!Recursing) {
+    assert(Stk.empty());
 #ifndef NDEBUG
-  // Make sure we don't rely on some value being still alive in
-  // InterpStack memory.
-  Stk.clear();
+    // Make sure we don't rely on some value being still alive in
+    // InterpStack memory.
+    Stk.clear();
 #endif
+  }
 
   Result = Res.toAPValue();
 
@@ -64,8 +65,8 @@ bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
 }
 
 bool Context::evaluate(State &Parent, const Expr *E, APValue &Result) {
-  assert(Stk.empty());
-  ByteCodeExprGen C(*this, *P, Parent, Stk, Result);
+  bool Recursing = !Stk.empty();
+  ByteCodeExprGen C(*this, *P, Parent, Stk);
 
   auto Res = C.interpretExpr(E);
   if (Res.isInvalid()) {
@@ -73,20 +74,23 @@ bool Context::evaluate(State &Parent, const Expr *E, APValue &Result) {
     return false;
   }
 
-  assert(Stk.empty());
+  if (!Recursing) {
+    assert(Stk.empty());
 #ifndef NDEBUG
-  // Make sure we don't rely on some value being still alive in
-  // InterpStack memory.
-  Stk.clear();
+    // Make sure we don't rely on some value being still alive in
+    // InterpStack memory.
+    Stk.clear();
 #endif
+  }
+
   Result = Res.toAPValue();
   return true;
 }
 
 bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
                                     APValue &Result) {
-  assert(Stk.empty());
-  ByteCodeExprGen C(*this, *P, Parent, Stk, Result);
+  bool Recursing = !Stk.empty();
+  ByteCodeExprGen C(*this, *P, Parent, Stk);
 
   bool CheckGlobalInitialized =
       shouldBeGloballyIndexed(VD) &&
@@ -97,12 +101,14 @@ bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
     return false;
   }
 
-  assert(Stk.empty());
+  if (!Recursing) {
+    assert(Stk.empty());
 #ifndef NDEBUG
-  // Make sure we don't rely on some value being still alive in
-  // InterpStack memory.
-  Stk.clear();
+    // Make sure we don't rely on some value being still alive in
+    // InterpStack memory.
+    Stk.clear();
 #endif
+  }
 
   Result = Res.toAPValue();
   return true;
@@ -201,22 +207,14 @@ 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,
                                const CXXRecordDecl *StaticDecl,
                                const CXXMethodDecl *InitialFunction) const {
+  assert(DynamicDecl);
+  assert(StaticDecl);
+  assert(InitialFunction);
 
   const CXXRecordDecl *CurRecord = DynamicDecl;
   const CXXMethodDecl *FoundFunction = InitialFunction;
diff --git a/clang/lib/AST/Interp/Context.h b/clang/lib/AST/Interp/Context.h
index c7620921e467e..23c439ad8912a 100644
--- a/clang/lib/AST/Interp/Context.h
+++ b/clang/lib/AST/Interp/Context.h
@@ -75,6 +75,7 @@ class Context final {
 
   /// Classifies an expression.
   std::optional classify(const Expr *E) const {
+    assert(E);
     if (E->isGLValue()) {
       if (E->getType()->isFunctionType())
         return PT_FnPtr;
@@ -107,9 +108,6 @@ class Context final {
   /// 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 c9c2bf9b145b2..caffb69d83e37 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"
@@ -18,7 +17,7 @@ using namespace clang;
 using namespace clang::interp;
 
 EvalEmitter::EvalEmitter(Context &Ctx, Program &P, State &Parent,
-                         InterpStack &Stk, APValue &Result)
+                         InterpStack &Stk)
     : Ctx(Ctx), P(P), S(Parent, P, Stk, Ctx, this), EvalResult(&Ctx) {
   // Create a dummy frame for the interpreter which does not have locals.
   S.Current =
diff --git a/clang/lib/AST/Interp/EvalEmitter.h b/clang/lib/AST/Interp/EvalEmitter.h
index 032c8860ee677..116f1d6fc134a 100644
--- a/clang/lib/AST/Interp/EvalEmitter.h
+++ b/clang/lib/AST/Interp/EvalEmitter.h
@@ -41,8 +41,7 @@ class EvalEmitter : public SourceMapper {
   InterpState &getState() { return S; }
 
 protected:
-  EvalEmitter(Context &Ctx, Program &P, State &Parent, InterpStack &Stk,
-              APValue &Result);
+  EvalEmitter(Context &Ctx, Program &P, State &Parent, InterpStack &Stk);
 
   virtual ~EvalEmitter();
 
@@ -74,7 +73,7 @@ class EvalEmitter : public SourceMapper {
   /// Lambda captures.
   llvm::DenseMap LambdaCaptures;
   /// Offset of the This parameter in a lambda record.
-  unsigned LambdaThisCapture = 0;
+  ParamOffset LambdaThisCapture{0, false};
   /// Local descriptors.
   llvm::SmallVector, 2> Descriptors;
 
diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index 5670888c245eb..4f3cd6cd21a15 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -285,10 +285,6 @@ static bool CheckConstant(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
   return CheckConstant(S, OpPC, Ptr.getDeclDesc());
 }
 
-bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
-  return !Ptr.isDummy();
-}
-
 bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                CheckSubobjectKind CSK) {
   if (!Ptr.isZero())
@@ -595,10 +591,8 @@ bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
   return true;
 }
 
-/// We aleady know the given DeclRefExpr is invalid for some reason,
-/// now figure out why and print appropriate diagnostics.
-bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
-  const ValueDecl *D = DR->getDecl();
+static bool diagnoseUnknownDecl(InterpState &S, CodePtr OpPC,
+                                const ValueDecl *D) {
   const SourceInfo &E = S.Current->getSource(OpPC);
 
   if (isa(D)) {
@@ -621,10 +615,28 @@ bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
       return false;
     }
   }
-
   return false;
 }
 
+/// We aleady know the given DeclRefExpr is invalid for some reason,
+/// now figure out why and print appropriate diagnostics.
+bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR) {
+  const ValueDecl *D = DR->getDecl();
+  return diagnoseUnknownDecl(S, OpPC, D);
+}
+
+bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
+  if (!Ptr.isDummy())
+    return true;
+
+  const Descriptor *Desc = Ptr.getDeclDesc();
+  const ValueDecl *D = Desc->asValueDecl();
+  if (!D)
+    return false;
+
+  return diagnoseUnknownDecl(S, OpPC, D);
+}
+
 bool CheckNonNullArgs(InterpState &S, CodePtr OpPC, const Function *F,
                       const CallExpr *CE, unsigned ArgSize) {
   auto Args = llvm::ArrayRef(CE->getArgs(), CE->getNumArgs());
diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index db52f6649c18b..baa1b8e9071ab 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -199,6 +199,8 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
 bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,
                        llvm::ArrayRef ArrayIndices, int64_t &Result);
 
+inline bool Invalid(InterpState &S, CodePtr OpPC);
+
 enum class ArithOp { Add, Sub };
 
 //===----------------------------------------------------------------------===//
@@ -285,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();
@@ -497,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();
@@ -522,6 +528,11 @@ bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
   if (Ptr.isDummy())
     return false;
 
+  if constexpr (std::is_same_v) {
+    if (!S.getLangOpts().CPlusPlus14)
+      return Invalid(S, OpPC);
+  }
+
   const T &Value = Ptr.deref();
   T Result;
 
@@ -554,7 +565,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();
@@ -572,7 +585,8 @@ 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())
+    return false;
   if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
     return false;
 
@@ -585,7 +599,8 @@ bool Inc(InterpState &S, CodePtr OpPC) {
 template ::T>
 bool IncPop(InterpState &S, CodePtr OpPC) {
   const Pointer &Ptr = S.Stk.pop();
-
+  if (Ptr.isDummy())
+    return false;
   if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
     return false;
 
@@ -599,7 +614,8 @@ bool IncPop(InterpState &S, CodePtr OpPC) {
 template ::T>
 bool Dec(InterpState &S, CodePtr OpPC) {
   const Pointer &Ptr = S.Stk.pop();
-
+  if (Ptr.isDummy())
+    return false;
   if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
     return false;
 
@@ -612,7 +628,8 @@ bool Dec(InterpState &S, CodePtr OpPC) {
 template ::T>
 bool DecPop(InterpState &S, CodePtr OpPC) {
   const Pointer &Ptr = S.Stk.pop();
-
+  if (Ptr.isDummy())
+    return false;
   if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
     return false;
 
@@ -641,7 +658,8 @@ bool IncDecFloatHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
 
 inline bool Incf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
   const Pointer &Ptr = S.Stk.pop();
-
+  if (Ptr.isDummy())
+    return false;
   if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
     return false;
 
@@ -650,7 +668,8 @@ inline bool Incf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
 
 inline bool IncfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
   const Pointer &Ptr = S.Stk.pop();
-
+  if (Ptr.isDummy())
+    return false;
   if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
     return false;
 
@@ -660,6 +679,9 @@ inline bool IncfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
 inline bool Decf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
   const Pointer &Ptr = S.Stk.pop();
 
+  if (Ptr.isDummy())
+    return false;
+
   if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
     return false;
 
@@ -669,6 +691,8 @@ inline bool Decf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
 inline bool DecfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
   const Pointer &Ptr = S.Stk.pop();
 
+  if (Ptr.isDummy())
+    return false;
   if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
     return false;
 
@@ -728,6 +752,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;
 }
@@ -774,9 +809,9 @@ inline bool CmpHelperEQ(InterpState &S, CodePtr OpPC, CompareFn Fn) {
     // element in the same array are NOT equal. They have the same Base value,
     // but a different Offset. This is a pretty rare case, so we fix this here
     // by comparing pointers to the first elements.
-    if (LHS.isArrayRoot())
+    if (!LHS.isDummy() && LHS.isArrayRoot())
       VL = LHS.atIndex(0).getByteOffset();
-    if (RHS.isArrayRoot())
+    if (!RHS.isDummy() && RHS.isArrayRoot())
       VR = RHS.atIndex(0).getByteOffset();
 
     S.Stk.push(BoolT::from(Fn(Compare(VL, VR))));
@@ -1430,6 +1465,8 @@ template ::T>
 bool InitElem(InterpState &S, CodePtr OpPC, uint32_t Idx) {
   const T &Value = S.Stk.pop();
   const Pointer &Ptr = S.Stk.peek().atIndex(Idx);
+  if (Ptr.isUnknownSizeArray())
+    return false;
   if (!CheckInit(S, OpPC, Ptr))
     return false;
   Ptr.initialize();
@@ -1442,6 +1479,8 @@ template ::T>
 bool InitElemPop(InterpState &S, CodePtr OpPC, uint32_t Idx) {
   const T &Value = S.Stk.pop();
   const Pointer &Ptr = S.Stk.pop().atIndex(Idx);
+  if (Ptr.isUnknownSizeArray())
+    return false;
   if (!CheckInit(S, OpPC, Ptr))
     return false;
   Ptr.initialize();
@@ -1680,7 +1719,7 @@ bool CastFloatingIntegral(InterpState &S, CodePtr OpPC) {
     auto Status = F.convertToInteger(Result);
 
     // Float-to-Integral overflow check.
-    if ((Status & APFloat::opStatus::opInvalidOp) && F.isFinite()) {
+    if ((Status & APFloat::opStatus::opInvalidOp)) {
       const Expr *E = S.Current->getExpr(OpPC);
       QualType Type = E->getType();
 
@@ -1895,7 +1934,7 @@ inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) {
   const T &Offset = S.Stk.pop();
   const Pointer &Ptr = S.Stk.peek();
 
-  if (!CheckDummy(S, OpPC, Ptr))
+  if (Ptr.isDummy())
     return true;
 
   if (!OffsetHelper(S, OpPC, Offset, Ptr))
@@ -1909,7 +1948,7 @@ inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) {
   const T &Offset = S.Stk.pop();
   const Pointer &Ptr = S.Stk.pop();
 
-  if (!CheckDummy(S, OpPC, Ptr)) {
+  if (Ptr.isDummy()) {
     S.Stk.push(Ptr);
     return true;
   }
@@ -1933,7 +1972,7 @@ inline bool ArrayElemPop(InterpState &S, CodePtr OpPC, uint32_t Index) {
 inline bool ArrayDecay(InterpState &S, CodePtr OpPC) {
   const Pointer &Ptr = S.Stk.pop();
 
-  if (Ptr.isDummy()) {
+  if (Ptr.isZero() || Ptr.isDummy()) {
     S.Stk.push(Ptr);
     return true;
   }
@@ -2056,8 +2095,12 @@ inline bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
   size_t ThisOffset = ArgSize - (Func->hasRVO() ? primSize(PT_Ptr) : 0);
   Pointer &ThisPtr = S.Stk.peek(ThisOffset);
 
-  const CXXRecordDecl *DynamicDecl =
-      ThisPtr.getDeclDesc()->getType()->getAsCXXRecordDecl();
+  QualType DynamicType = ThisPtr.getDeclDesc()->getType();
+  const CXXRecordDecl *DynamicDecl;
+  if (DynamicType->isPointerType() || DynamicType->isReferenceType())
+    DynamicDecl = DynamicType->getPointeeCXXRecordDecl();
+  else
+    DynamicDecl = ThisPtr.getDeclDesc()->getType()->getAsCXXRecordDecl();
   const auto *StaticDecl = cast(Func->getParentDecl());
   const auto *InitialFunction = cast(Func->getDecl());
   const CXXMethodDecl *Overrider = S.getContext().getOverridingFunction(
diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp
index 4ba518e5f0619..5250d02be85a6 100644
--- a/clang/lib/AST/Interp/InterpBuiltin.cpp
+++ b/clang/lib/AST/Interp/InterpBuiltin.cpp
@@ -132,6 +132,9 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
   if (!CheckLive(S, OpPC, A, AK_Read) || !CheckLive(S, OpPC, B, AK_Read))
     return false;
 
+  if (A.isDummy() || B.isDummy())
+    return false;
+
   assert(A.getFieldDesc()->isPrimitiveArray());
   assert(B.getFieldDesc()->isPrimitiveArray());
 
@@ -460,9 +463,6 @@ static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC,
                                      const InterpFrame *Frame,
                                      const Function *Func,
                                      const CallExpr *Call) {
-
-  Func->getDecl()->dump();
-
   PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
   APSInt Val = peekToAPSInt(S.Stk, ArgT);
   pushInteger(S, Val.popcount(), Call->getType());
@@ -900,6 +900,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 +926,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()));
@@ -1206,7 +1222,16 @@ 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)
+        << S.Current->getRange(OpPC);
+
     return false;
   }
 
@@ -1230,7 +1255,7 @@ bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,
       const RecordType *RT = CurrentType->getAs();
       if (!RT)
         return false;
-      RecordDecl *RD = RT->getDecl();
+      const RecordDecl *RD = RT->getDecl();
       if (RD->isInvalidDecl())
         return false;
       const ASTRecordLayout &RL = S.getCtx().getASTRecordLayout(RD);
diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td
index 3e3ba1b163e33..ffc54646f0279 100644
--- a/clang/lib/AST/Interp/Opcodes.td
+++ b/clang/lib/AST/Interp/Opcodes.td
@@ -563,10 +563,10 @@ def Inv: Opcode {
 }
 
 // Increment and decrement.
-def Inc: IntegerOpcode;
-def IncPop : IntegerOpcode;
-def Dec: IntegerOpcode;
-def DecPop: IntegerOpcode;
+def Inc: AluOpcode;
+def IncPop : AluOpcode;
+def Dec: AluOpcode;
+def DecPop: AluOpcode;
 
 // Float increment and decrement.
 def Incf: FloatOpcode;
diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h
index fa2e03d71190f..34ecdb967960d 100644
--- a/clang/lib/AST/Interp/Pointer.h
+++ b/clang/lib/AST/Interp/Pointer.h
@@ -215,7 +215,6 @@ class Pointer {
       assert(Offset == PastEndMark && "cannot get base of a block");
       return Pointer(Pointee, Base, 0);
     }
-    assert(Offset == Base && "not an inner field");
     unsigned NewBase = Base - getInlineDesc()->Offset;
     return Pointer(Pointee, NewBase, NewBase);
   }
diff --git a/clang/lib/AST/StmtOpenACC.cpp b/clang/lib/AST/StmtOpenACC.cpp
index f74a777cd695b..e6191bc6db708 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/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index d487944ce9211..fd7b06efcc786 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -361,8 +361,8 @@ getFieldsGlobalsAndFuncs(const Stmt &S, FieldSet &Fields,
     if (const auto *FD = dyn_cast(VD))
       Fields.insert(FD);
   } else if (auto *InitList = dyn_cast(&S)) {
-    if (RecordDecl *RD = InitList->getType()->getAsRecordDecl())
-      for (const auto *FD : getFieldsForInitListExpr(RD))
+    if (InitList->getType()->isRecordType())
+      for (const auto *FD : getFieldsForInitListExpr(InitList))
         Fields.insert(FD);
   }
 }
@@ -983,7 +983,7 @@ StorageLocation &Environment::createObjectInternal(const ValueDecl *D,
   }
 
   Value *Val = nullptr;
-  if (InitExpr)
+  if (InitExpr) {
     // In the (few) cases where an expression is intentionally
     // "uninterpreted", `InitExpr` is not associated with a value.  There are
     // two ways to handle this situation: propagate the status, so that
@@ -998,6 +998,11 @@ StorageLocation &Environment::createObjectInternal(const ValueDecl *D,
     // default value (assuming we don't update the environment API to return
     // references).
     Val = getValue(*InitExpr);
+
+    if (!Val && isa(InitExpr) &&
+        InitExpr->getType()->isPointerType())
+      Val = &getOrCreateNullPointerValue(InitExpr->getType()->getPointeeType());
+  }
   if (!Val)
     Val = createValue(Ty);
 
@@ -1104,12 +1109,22 @@ RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME,
   return Env.get(*Base);
 }
 
-std::vector getFieldsForInitListExpr(const RecordDecl *RD) {
+std::vector
+getFieldsForInitListExpr(const InitListExpr *InitList) {
+  const RecordDecl *RD = InitList->getType()->getAsRecordDecl();
+  assert(RD != nullptr);
+
+  std::vector Fields;
+
+  if (InitList->getType()->isUnionType()) {
+    Fields.push_back(InitList->getInitializedFieldInUnion());
+    return Fields;
+  }
+
   // Unnamed bitfields are only used for padding and do not appear in
   // `InitListExpr`'s inits. However, those fields do appear in `RecordDecl`'s
   // field list, and we thus need to remove them before mapping inits to
   // fields to avoid mapping inits to the wrongs fields.
-  std::vector Fields;
   llvm::copy_if(
       RD->fields(), std::back_inserter(Fields),
       [](const FieldDecl *Field) { return !Field->isUnnamedBitfield(); });
diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index 089854264f483..04aa2831df055 100644
--- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -663,14 +663,7 @@ class TransferVisitor : public ConstStmtVisitor {
   void VisitInitListExpr(const InitListExpr *S) {
     QualType Type = S->getType();
 
-    if (Type->isUnionType()) {
-      // FIXME: Initialize unions properly.
-      if (auto *Val = Env.createValue(Type))
-        Env.setValue(*S, *Val);
-      return;
-    }
-
-    if (!Type->isStructureOrClassType()) {
+    if (!Type->isRecordType()) {
       // Until array initialization is implemented, we skip arrays and don't
       // need to care about cases where `getNumInits() > 1`.
       if (!Type->isArrayType() && S->getNumInits() == 1)
@@ -688,14 +681,26 @@ class TransferVisitor : public ConstStmtVisitor {
     llvm::DenseMap FieldLocs;
 
     // This only contains the direct fields for the given type.
-    std::vector FieldsForInit =
-        getFieldsForInitListExpr(Type->getAsRecordDecl());
+    std::vector FieldsForInit = getFieldsForInitListExpr(S);
 
-    // `S->inits()` contains all the initializer epressions, including the
+    // `S->inits()` contains all the initializer expressions, including the
     // ones for direct base classes.
-    auto Inits = S->inits();
+    ArrayRef Inits = S->inits();
     size_t InitIdx = 0;
 
+    // Unions initialized with an empty initializer list need special treatment.
+    // For structs/classes initialized with an empty initializer list, Clang
+    // puts `ImplicitValueInitExpr`s in `InitListExpr::inits()`, but for unions,
+    // it doesn't do this -- so we create an `ImplicitValueInitExpr` ourselves.
+    std::optional ImplicitValueInitForUnion;
+    SmallVector InitsForUnion;
+    if (S->getType()->isUnionType() && Inits.empty()) {
+      assert(FieldsForInit.size() == 1);
+      ImplicitValueInitForUnion.emplace(FieldsForInit.front()->getType());
+      InitsForUnion.push_back(&*ImplicitValueInitForUnion);
+      Inits = InitsForUnion;
+    }
+
     // Initialize base classes.
     if (auto* R = S->getType()->getAsCXXRecordDecl()) {
       assert(FieldsForInit.size() + R->getNumBases() == Inits.size());
@@ -731,6 +736,17 @@ class TransferVisitor : public ConstStmtVisitor {
       FieldLocs.insert({Field, &Loc});
     }
 
+    // In the case of a union, we don't in general have initializers for all
+    // of the fields. Create storage locations for the remaining fields (but
+    // don't associate them with values).
+    if (Type->isUnionType()) {
+      for (const FieldDecl *Field :
+           Env.getDataflowAnalysisContext().getModeledFields(Type)) {
+        if (auto [it, inserted] = FieldLocs.insert({Field, nullptr}); inserted)
+          it->second = &Env.createStorageLocation(Field->getType());
+      }
+    }
+
     // Check that we satisfy the invariant that a `RecordStorageLoation`
     // contains exactly the set of modeled fields for that type.
     // `ModeledFields` includes fields from all the bases, but only the
diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index 701f1ac852c25..e1ff0d92f6b2f 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -130,42 +130,42 @@ class MatchDescendantVisitor
 
   bool TraverseGenericSelectionExpr(GenericSelectionExpr *Node) {
     // These are unevaluated, except the result expression.
-    if(ignoreUnevaluatedContext)
+    if (ignoreUnevaluatedContext)
       return TraverseStmt(Node->getResultExpr());
     return VisitorBase::TraverseGenericSelectionExpr(Node);
   }
 
   bool TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) {
     // Unevaluated context.
-    if(ignoreUnevaluatedContext)
+    if (ignoreUnevaluatedContext)
       return true;
     return VisitorBase::TraverseUnaryExprOrTypeTraitExpr(Node);
   }
 
   bool TraverseTypeOfExprTypeLoc(TypeOfExprTypeLoc Node) {
     // Unevaluated context.
-    if(ignoreUnevaluatedContext)
+    if (ignoreUnevaluatedContext)
       return true;
     return VisitorBase::TraverseTypeOfExprTypeLoc(Node);
   }
 
   bool TraverseDecltypeTypeLoc(DecltypeTypeLoc Node) {
     // Unevaluated context.
-    if(ignoreUnevaluatedContext)
+    if (ignoreUnevaluatedContext)
       return true;
     return VisitorBase::TraverseDecltypeTypeLoc(Node);
   }
 
   bool TraverseCXXNoexceptExpr(CXXNoexceptExpr *Node) {
     // Unevaluated context.
-    if(ignoreUnevaluatedContext)
+    if (ignoreUnevaluatedContext)
       return true;
     return VisitorBase::TraverseCXXNoexceptExpr(Node);
   }
 
   bool TraverseCXXTypeidExpr(CXXTypeidExpr *Node) {
     // Unevaluated context.
-    if(ignoreUnevaluatedContext)
+    if (ignoreUnevaluatedContext)
       return true;
     return VisitorBase::TraverseCXXTypeidExpr(Node);
   }
@@ -213,24 +213,26 @@ class MatchDescendantVisitor
 
 // Because we're dealing with raw pointers, let's define what we mean by that.
 static auto hasPointerType() {
-    return hasType(hasCanonicalType(pointerType()));
+  return hasType(hasCanonicalType(pointerType()));
 }
 
-static auto hasArrayType() {
-    return hasType(hasCanonicalType(arrayType()));
-}
+static auto hasArrayType() { return hasType(hasCanonicalType(arrayType())); }
 
-AST_MATCHER_P(Stmt, forEachDescendantEvaluatedStmt, internal::Matcher, innerMatcher) {
+AST_MATCHER_P(Stmt, forEachDescendantEvaluatedStmt, internal::Matcher,
+              innerMatcher) {
   const DynTypedMatcher &DTM = static_cast(innerMatcher);
 
-  MatchDescendantVisitor Visitor(&DTM, Finder, Builder, ASTMatchFinder::BK_All, true);
+  MatchDescendantVisitor Visitor(&DTM, Finder, Builder, ASTMatchFinder::BK_All,
+                                 true);
   return Visitor.findMatch(DynTypedNode::create(Node));
 }
 
-AST_MATCHER_P(Stmt, forEachDescendantStmt, internal::Matcher, innerMatcher) {
+AST_MATCHER_P(Stmt, forEachDescendantStmt, internal::Matcher,
+              innerMatcher) {
   const DynTypedMatcher &DTM = static_cast(innerMatcher);
 
-  MatchDescendantVisitor Visitor(&DTM, Finder, Builder, ASTMatchFinder::BK_All, false);
+  MatchDescendantVisitor Visitor(&DTM, Finder, Builder, ASTMatchFinder::BK_All,
+                                 false);
   return Visitor.findMatch(DynTypedNode::create(Node));
 }
 
@@ -268,10 +270,9 @@ static auto isInUnspecifiedLvalueContext(internal::Matcher innerMatcher) {
         hasLHS(innerMatcher)
       )
     ));
-// clang-format on
+  // clang-format on
 }
 
-
 // Returns a matcher that matches any expression `e` such that `InnerMatcher`
 // matches `e` and `e` is in an Unspecified Pointer Context (UPC).
 static internal::Matcher
@@ -315,7 +316,7 @@ isInUnspecifiedPointerContext(internal::Matcher InnerMatcher) {
   // clang-format on
 
   return stmt(anyOf(CallArgMatcher, CastOperandMatcher, CompOperandMatcher,
-		    PtrSubtractionMatcher));
+                    PtrSubtractionMatcher));
   // FIXME: any more cases? (UPC excludes the RHS of an assignment.  For now we
   // don't have to check that.)
 }
@@ -481,7 +482,9 @@ class Gadget {
 #ifndef NDEBUG
   StringRef getDebugName() const {
     switch (K) {
-#define GADGET(x) case Kind::x: return #x;
+#define GADGET(x)                                                              \
+  case Kind::x:                                                                \
+    return #x;
 #include "clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def"
     }
     llvm_unreachable("Unhandled Gadget::Kind enum");
@@ -502,7 +505,6 @@ class Gadget {
   Kind K;
 };
 
-
 /// Warning gadgets correspond to unsafe code patterns that warrants
 /// an immediate warning.
 class WarningGadget : public Gadget {
@@ -513,10 +515,10 @@ class WarningGadget : public Gadget {
   bool isWarningGadget() const final { return true; }
 };
 
-/// Fixable gadgets correspond to code patterns that aren't always unsafe but need to be
-/// properly recognized in order to emit fixes. For example, if a raw pointer-type
-/// variable is replaced by a safe C++ container, every use of such variable must be
-/// carefully considered and possibly updated.
+/// Fixable gadgets correspond to code patterns that aren't always unsafe but
+/// need to be properly recognized in order to emit fixes. For example, if a raw
+/// pointer-type variable is replaced by a safe C++ container, every use of such
+/// variable must be carefully considered and possibly updated.
 class FixableGadget : public Gadget {
 public:
   FixableGadget(Kind K) : Gadget(K) {}
@@ -531,20 +533,19 @@ class FixableGadget : public Gadget {
     return std::nullopt;
   }
 
-  /// Returns a list of two elements where the first element is the LHS of a pointer assignment
-  /// statement and the second element is the RHS. This two-element list represents the fact that
-  /// the LHS buffer gets its bounds information from the RHS buffer. This information will be used
-  /// later to group all those variables whose types must be modified together to prevent type
-  /// mismatches.
+  /// Returns a list of two elements where the first element is the LHS of a
+  /// pointer assignment statement and the second element is the RHS. This
+  /// two-element list represents the fact that the LHS buffer gets its bounds
+  /// information from the RHS buffer. This information will be used later to
+  /// group all those variables whose types must be modified together to prevent
+  /// type mismatches.
   virtual std::optional>
   getStrategyImplications() const {
     return std::nullopt;
   }
 };
 
-static auto toSupportedVariable() {
-  return to(varDecl());
-}
+static auto toSupportedVariable() { return to(varDecl()); }
 
 using FixableGadgetList = std::vector>;
 using WarningGadgetList = std::vector>;
@@ -565,10 +566,10 @@ class IncrementGadget : public WarningGadget {
   }
 
   static Matcher matcher() {
-    return stmt(unaryOperator(
-      hasOperatorName("++"),
-      hasUnaryOperand(ignoringParenImpCasts(hasPointerType()))
-    ).bind(OpTag));
+    return stmt(
+        unaryOperator(hasOperatorName("++"),
+                      hasUnaryOperand(ignoringParenImpCasts(hasPointerType())))
+            .bind(OpTag));
   }
 
   const UnaryOperator *getBaseStmt() const override { return Op; }
@@ -600,10 +601,10 @@ class DecrementGadget : public WarningGadget {
   }
 
   static Matcher matcher() {
-    return stmt(unaryOperator(
-      hasOperatorName("--"),
-      hasUnaryOperand(ignoringParenImpCasts(hasPointerType()))
-    ).bind(OpTag));
+    return stmt(
+        unaryOperator(hasOperatorName("--"),
+                      hasUnaryOperand(ignoringParenImpCasts(hasPointerType())))
+            .bind(OpTag));
   }
 
   const UnaryOperator *getBaseStmt() const override { return Op; }
@@ -754,26 +755,25 @@ class PointerInitGadget : public FixableGadget {
 private:
   static constexpr const char *const PointerInitLHSTag = "ptrInitLHS";
   static constexpr const char *const PointerInitRHSTag = "ptrInitRHS";
-  const VarDecl * PtrInitLHS;         // the LHS pointer expression in `PI`
-  const DeclRefExpr * PtrInitRHS;         // the RHS pointer expression in `PI`
+  const VarDecl *PtrInitLHS;     // the LHS pointer expression in `PI`
+  const DeclRefExpr *PtrInitRHS; // the RHS pointer expression in `PI`
 
 public:
   PointerInitGadget(const MatchFinder::MatchResult &Result)
       : FixableGadget(Kind::PointerInit),
-    PtrInitLHS(Result.Nodes.getNodeAs(PointerInitLHSTag)),
-    PtrInitRHS(Result.Nodes.getNodeAs(PointerInitRHSTag)) {}
+        PtrInitLHS(Result.Nodes.getNodeAs(PointerInitLHSTag)),
+        PtrInitRHS(Result.Nodes.getNodeAs(PointerInitRHSTag)) {}
 
   static bool classof(const Gadget *G) {
     return G->getKind() == Kind::PointerInit;
   }
 
   static Matcher matcher() {
-    auto PtrInitStmt = declStmt(hasSingleDecl(varDecl(
-                                 hasInitializer(ignoringImpCasts(declRefExpr(
-                                                  hasPointerType(),
-                                                    toSupportedVariable()).
-                                                  bind(PointerInitRHSTag)))).
-                                              bind(PointerInitLHSTag)));
+    auto PtrInitStmt = declStmt(hasSingleDecl(
+        varDecl(hasInitializer(ignoringImpCasts(
+                    declRefExpr(hasPointerType(), toSupportedVariable())
+                        .bind(PointerInitRHSTag))))
+            .bind(PointerInitLHSTag)));
 
     return stmt(PtrInitStmt);
   }
@@ -793,8 +793,7 @@ class PointerInitGadget : public FixableGadget {
 
   virtual std::optional>
   getStrategyImplications() const override {
-      return std::make_pair(PtrInitLHS,
-                            cast(PtrInitRHS->getDecl()));
+    return std::make_pair(PtrInitLHS, cast(PtrInitRHS->getDecl()));
   }
 };
 
@@ -807,8 +806,8 @@ class PtrToPtrAssignmentGadget : public FixableGadget {
 private:
   static constexpr const char *const PointerAssignLHSTag = "ptrLHS";
   static constexpr const char *const PointerAssignRHSTag = "ptrRHS";
-  const DeclRefExpr * PtrLHS;         // the LHS pointer expression in `PA`
-  const DeclRefExpr * PtrRHS;         // the RHS pointer expression in `PA`
+  const DeclRefExpr *PtrLHS; // the LHS pointer expression in `PA`
+  const DeclRefExpr *PtrRHS; // the RHS pointer expression in `PA`
 
 public:
   PtrToPtrAssignmentGadget(const MatchFinder::MatchResult &Result)
@@ -821,13 +820,13 @@ class PtrToPtrAssignmentGadget : public FixableGadget {
   }
 
   static Matcher matcher() {
-    auto PtrAssignExpr = binaryOperator(allOf(hasOperatorName("="),
-      hasRHS(ignoringParenImpCasts(declRefExpr(hasPointerType(),
-                                               toSupportedVariable()).
-                                   bind(PointerAssignRHSTag))),
-                                   hasLHS(declRefExpr(hasPointerType(),
-                                                      toSupportedVariable()).
-                                          bind(PointerAssignLHSTag))));
+    auto PtrAssignExpr = binaryOperator(
+        allOf(hasOperatorName("="),
+              hasRHS(ignoringParenImpCasts(
+                  declRefExpr(hasPointerType(), toSupportedVariable())
+                      .bind(PointerAssignRHSTag))),
+              hasLHS(declRefExpr(hasPointerType(), toSupportedVariable())
+                         .bind(PointerAssignLHSTag))));
 
     return stmt(isInUnspecifiedUntypedContext(PtrAssignExpr));
   }
@@ -981,9 +980,8 @@ class ULCArraySubscriptGadget : public FixableGadget {
 
   static Matcher matcher() {
     auto ArrayOrPtr = anyOf(hasPointerType(), hasArrayType());
-    auto BaseIsArrayOrPtrDRE =
-        hasBase(ignoringParenImpCasts(declRefExpr(ArrayOrPtr,
-                                                  toSupportedVariable())));
+    auto BaseIsArrayOrPtrDRE = hasBase(
+        ignoringParenImpCasts(declRefExpr(ArrayOrPtr, toSupportedVariable())));
     auto Target =
         arraySubscriptExpr(BaseIsArrayOrPtrDRE).bind(ULCArraySubscriptTag);
 
@@ -1025,9 +1023,9 @@ class UPCStandalonePointerGadget : public FixableGadget {
 
   static Matcher matcher() {
     auto ArrayOrPtr = anyOf(hasPointerType(), hasArrayType());
-    auto target = expr(
-        ignoringParenImpCasts(declRefExpr(allOf(ArrayOrPtr,
-                              toSupportedVariable())).bind(DeclRefExprTag)));
+    auto target = expr(ignoringParenImpCasts(
+        declRefExpr(allOf(ArrayOrPtr, toSupportedVariable()))
+            .bind(DeclRefExprTag)));
     return stmt(isInUnspecifiedPointerContext(target));
   }
 
@@ -1036,9 +1034,7 @@ class UPCStandalonePointerGadget : public FixableGadget {
 
   virtual const Stmt *getBaseStmt() const override { return Node; }
 
-  virtual DeclUseList getClaimedVarUseSites() const override {
-    return {Node};
-  }
+  virtual DeclUseList getClaimedVarUseSites() const override { return {Node}; }
 };
 
 class PointerDereferenceGadget : public FixableGadget {
@@ -1103,10 +1099,10 @@ class UPCAddressofArraySubscriptGadget : public FixableGadget {
 
   static Matcher matcher() {
     return expr(isInUnspecifiedPointerContext(expr(ignoringImpCasts(
-        unaryOperator(hasOperatorName("&"),
-                      hasUnaryOperand(arraySubscriptExpr(
-                          hasBase(ignoringParenImpCasts(declRefExpr(
-                                                  toSupportedVariable()))))))
+        unaryOperator(
+            hasOperatorName("&"),
+            hasUnaryOperand(arraySubscriptExpr(hasBase(
+                ignoringParenImpCasts(declRefExpr(toSupportedVariable()))))))
             .bind(UPCAddressofArraySubscriptTag)))));
   }
 
@@ -1195,13 +1191,13 @@ class DeclUseTracker {
 class UPCPreIncrementGadget : public FixableGadget {
 private:
   static constexpr const char *const UPCPreIncrementTag =
-    "PointerPreIncrementUnderUPC";
+      "PointerPreIncrementUnderUPC";
   const UnaryOperator *Node; // the `++Ptr` node
 
 public:
   UPCPreIncrementGadget(const MatchFinder::MatchResult &Result)
-    : FixableGadget(Kind::UPCPreIncrement),
-      Node(Result.Nodes.getNodeAs(UPCPreIncrementTag)) {
+      : FixableGadget(Kind::UPCPreIncrement),
+        Node(Result.Nodes.getNodeAs(UPCPreIncrementTag)) {
     assert(Node != nullptr && "Expecting a non-null matching result");
   }
 
@@ -1215,10 +1211,9 @@ class UPCPreIncrementGadget : public FixableGadget {
     // can have the matcher be general, so long as `getClaimedVarUseSites` does
     // things right.
     return stmt(isInUnspecifiedPointerContext(expr(ignoringImpCasts(
-								    unaryOperator(isPreInc(),
-										  hasUnaryOperand(declRefExpr(
-                                                    toSupportedVariable()))
-										  ).bind(UPCPreIncrementTag)))));
+        unaryOperator(isPreInc(),
+                      hasUnaryOperand(declRefExpr(toSupportedVariable())))
+            .bind(UPCPreIncrementTag)))));
   }
 
   virtual std::optional
@@ -1782,9 +1777,9 @@ static SourceRange getSourceRangeToTokenEnd(const Decl *D,
                                             const LangOptions &LangOpts) {
   SourceLocation Begin = D->getBeginLoc();
   SourceLocation
-    End = // `D->getEndLoc` should always return the starting location of the
-    // last token, so we should get the end of the token
-    Lexer::getLocForEndOfToken(D->getEndLoc(), 0, SM, LangOpts);
+      End = // `D->getEndLoc` should always return the starting location of the
+      // last token, so we should get the end of the token
+      Lexer::getLocForEndOfToken(D->getEndLoc(), 0, SM, LangOpts);
 
   return SourceRange(Begin, End);
 }
@@ -1976,7 +1971,7 @@ PointerDereferenceGadget::getFixits(const FixitStrategy &S) const {
     if (auto LocPastOperand =
             getPastLoc(BaseDeclRefExpr, SM, Ctx.getLangOpts())) {
       return FixItList{{FixItHint::CreateRemoval(derefRange),
-			FixItHint::CreateInsertion(*LocPastOperand, "[0]")}};
+                        FixItHint::CreateInsertion(*LocPastOperand, "[0]")}};
     }
     break;
   }
@@ -2162,7 +2157,8 @@ FixVarInitializerWithSpan(const Expr *Init, ASTContext &Ctx,
   // NULL pointer, we use the default constructor to initialize the span
   // object, i.e., a `std:span` variable declaration with no initializer.
   // So the fix-it is just to remove the initializer.
-  if (Init->isNullPointerConstant(Ctx,
+  if (Init->isNullPointerConstant(
+          Ctx,
           // FIXME: Why does this function not ask for `const ASTContext
           // &`? It should. Maybe worth an NFC patch later.
           Expr::NullPointerConstantValueDependence::
@@ -2230,8 +2226,10 @@ FixVarInitializerWithSpan(const Expr *Init, ASTContext &Ctx,
 }
 
 #ifndef NDEBUG
-#define DEBUG_NOTE_DECL_FAIL(D, Msg)  \
-Handler.addDebugNoteForVar((D), (D)->getBeginLoc(), "failed to produce fixit for declaration '" + (D)->getNameAsString() + "'" + (Msg))
+#define DEBUG_NOTE_DECL_FAIL(D, Msg)                                           \
+  Handler.addDebugNoteForVar((D), (D)->getBeginLoc(),                          \
+                             "failed to produce fixit for declaration '" +     \
+                                 (D)->getNameAsString() + "'" + (Msg))
 #else
 #define DEBUG_NOTE_DECL_FAIL(D, Msg)
 #endif
@@ -2239,8 +2237,8 @@ Handler.addDebugNoteForVar((D), (D)->getBeginLoc(), "failed to produce fixit for
 // For the given variable declaration with a pointer-to-T type, returns the text
 // `std::span`.  If it is unable to generate the text, returns
 // `std::nullopt`.
-static std::optional createSpanTypeForVarDecl(const VarDecl *VD,
-                                                           const ASTContext &Ctx) {
+static std::optional
+createSpanTypeForVarDecl(const VarDecl *VD, const ASTContext &Ctx) {
   assert(VD->getType()->isPointerType());
 
   std::optional PteTyQualifiers = std::nullopt;
@@ -2277,8 +2275,8 @@ static std::optional createSpanTypeForVarDecl(const VarDecl *VD,
 //    the non-empty fix-it list, if fix-its are successfuly generated; empty
 //    list otherwise.
 static FixItList fixLocalVarDeclWithSpan(const VarDecl *D, ASTContext &Ctx,
-					 const StringRef UserFillPlaceHolder,
-					 UnsafeBufferUsageHandler &Handler) {
+                                         const StringRef UserFillPlaceHolder,
+                                         UnsafeBufferUsageHandler &Handler) {
   if (hasUnsupportedSpecifiers(D, Ctx.getSourceManager()))
     return {};
 
@@ -2431,9 +2429,9 @@ createOverloadsForFixedParams(const FixitStrategy &S, const FunctionDecl *FD,
         // print parameter name if provided:
         if (IdentifierInfo *II = Parm->getIdentifier())
           SS << ' ' << II->getName().str();
-      } else if (auto ParmTypeText = getRangeText(
-                     getSourceRangeToTokenEnd(Parm, SM, LangOpts),
-                     SM, LangOpts)) {
+      } else if (auto ParmTypeText =
+                     getRangeText(getSourceRangeToTokenEnd(Parm, SM, LangOpts),
+                                  SM, LangOpts)) {
         // print the whole `Parm` without modification:
         SS << ParmTypeText->str();
       } else
@@ -2577,7 +2575,8 @@ static FixItList fixVariableWithSpan(const VarDecl *VD,
                                      UnsafeBufferUsageHandler &Handler) {
   const DeclStmt *DS = Tracker.lookupDecl(VD);
   if (!DS) {
-    DEBUG_NOTE_DECL_FAIL(VD, " : variables declared this way not implemented yet");
+    DEBUG_NOTE_DECL_FAIL(VD,
+                         " : variables declared this way not implemented yet");
     return {};
   }
   if (!DS->isSingleDecl()) {
@@ -2979,8 +2978,8 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
 #endif
 
   assert(D && D->getBody());
-  // We do not want to visit a Lambda expression defined inside a method independently.
-  // Instead, it should be visited along with the outer method.
+  // We do not want to visit a Lambda expression defined inside a method
+  // independently. Instead, it should be visited along with the outer method.
   // FIXME: do we want to do the same thing for `BlockDecl`s?
   if (const auto *fd = dyn_cast(D)) {
     if (fd->getParent()->isLambda() && fd->getParent()->isLocalClass())
@@ -2990,7 +2989,7 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
   // Do not emit fixit suggestions for functions declared in an
   // extern "C" block.
   if (const auto *FD = dyn_cast(D)) {
-      for (FunctionDecl *FReDecl : FD->redecls()) {
+    for (FunctionDecl *FReDecl : FD->redecls()) {
       if (FReDecl->isExternC()) {
         EmitSuggestions = false;
         break;
@@ -3002,7 +3001,7 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
   FixableGadgetSets FixablesForAllVars;
 
   auto [FixableGadgets, WarningGadgets, Tracker] =
-    findGadgets(D, Handler, EmitSuggestions);
+      findGadgets(D, Handler, EmitSuggestions);
 
   if (!EmitSuggestions) {
     // Our job is very easy without suggestions. Just warn about
@@ -3055,36 +3054,36 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
   // Filter out non-local vars and vars with unclaimed DeclRefExpr-s.
   for (auto it = FixablesForAllVars.byVar.cbegin();
        it != FixablesForAllVars.byVar.cend();) {
-      // FIXME: need to deal with global variables later
-      if ((!it->first->isLocalVarDecl() && !isa(it->first))) {
+    // FIXME: need to deal with global variables later
+    if ((!it->first->isLocalVarDecl() && !isa(it->first))) {
 #ifndef NDEBUG
-          Handler.addDebugNoteForVar(
-              it->first, it->first->getBeginLoc(),
-              ("failed to produce fixit for '" + it->first->getNameAsString() +
-               "' : neither local nor a parameter"));
+      Handler.addDebugNoteForVar(it->first, it->first->getBeginLoc(),
+                                 ("failed to produce fixit for '" +
+                                  it->first->getNameAsString() +
+                                  "' : neither local nor a parameter"));
 #endif
-        it = FixablesForAllVars.byVar.erase(it);
-      } else if (it->first->getType().getCanonicalType()->isReferenceType()) {
+      it = FixablesForAllVars.byVar.erase(it);
+    } else if (it->first->getType().getCanonicalType()->isReferenceType()) {
 #ifndef NDEBUG
-        Handler.addDebugNoteForVar(it->first, it->first->getBeginLoc(),
-                                   ("failed to produce fixit for '" +
-                                    it->first->getNameAsString() +
-                                    "' : has a reference type"));
+      Handler.addDebugNoteForVar(it->first, it->first->getBeginLoc(),
+                                 ("failed to produce fixit for '" +
+                                  it->first->getNameAsString() +
+                                  "' : has a reference type"));
 #endif
-        it = FixablesForAllVars.byVar.erase(it);
-      } else if (Tracker.hasUnclaimedUses(it->first)) {
-        it = FixablesForAllVars.byVar.erase(it);
-      } else if (it->first->isInitCapture()) {
+      it = FixablesForAllVars.byVar.erase(it);
+    } else if (Tracker.hasUnclaimedUses(it->first)) {
+      it = FixablesForAllVars.byVar.erase(it);
+    } else if (it->first->isInitCapture()) {
 #ifndef NDEBUG
-        Handler.addDebugNoteForVar(
-            it->first, it->first->getBeginLoc(),
-                                   ("failed to produce fixit for '" + it->first->getNameAsString() +
-                                    "' : init capture"));
+      Handler.addDebugNoteForVar(it->first, it->first->getBeginLoc(),
+                                 ("failed to produce fixit for '" +
+                                  it->first->getNameAsString() +
+                                  "' : init capture"));
 #endif
-        it = FixablesForAllVars.byVar.erase(it);
-      } else {
-        ++it;
-      }
+      it = FixablesForAllVars.byVar.erase(it);
+    } else {
+      ++it;
+    }
   }
 
 #ifndef NDEBUG
@@ -3115,7 +3114,7 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
   for (auto it : FixablesForAllVars.byVar) {
     for (const FixableGadget *fixable : it.second) {
       std::optional> ImplPair =
-                                  fixable->getStrategyImplications();
+          fixable->getStrategyImplications();
       if (ImplPair) {
         std::pair Impl = std::move(*ImplPair);
         PtrAssignmentGraph[Impl.first].insert(Impl.second);
@@ -3144,10 +3143,10 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
   for (const auto &[Var, ignore] : UnsafeOps.byVar) {
     if (VisitedVarsDirected.find(Var) == VisitedVarsDirected.end()) {
 
-      std::queue QueueDirected{};
+      std::queue QueueDirected{};
       QueueDirected.push(Var);
-      while(!QueueDirected.empty()) {
-        const VarDecl* CurrentVar = QueueDirected.front();
+      while (!QueueDirected.empty()) {
+        const VarDecl *CurrentVar = QueueDirected.front();
         QueueDirected.pop();
         VisitedVarsDirected.insert(CurrentVar);
         auto AdjacentNodes = PtrAssignmentGraph[CurrentVar];
@@ -3178,11 +3177,11 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
   for (const auto &[Var, ignore] : UnsafeOps.byVar) {
     if (VisitedVars.find(Var) == VisitedVars.end()) {
       VarGrpTy &VarGroup = Groups.emplace_back();
-      std::queue Queue{};
+      std::queue Queue{};
 
       Queue.push(Var);
-      while(!Queue.empty()) {
-        const VarDecl* CurrentVar = Queue.front();
+      while (!Queue.empty()) {
+        const VarDecl *CurrentVar = Queue.front();
         Queue.pop();
         VisitedVars.insert(CurrentVar);
         VarGroup.push_back(CurrentVar);
diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp
index 1c5043a618fff..9f597dcf8b0f5 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/CodeGen/ABIInfo.cpp b/clang/lib/CodeGen/ABIInfo.cpp
index 1b56cf7c596d0..efcff958ce545 100644
--- a/clang/lib/CodeGen/ABIInfo.cpp
+++ b/clang/lib/CodeGen/ABIInfo.cpp
@@ -184,6 +184,58 @@ ABIArgInfo ABIInfo::getNaturalAlignIndirectInReg(QualType Ty,
                                       /*ByVal*/ false, Realign);
 }
 
+void ABIInfo::appendAttributeMangling(TargetAttr *Attr,
+                                      raw_ostream &Out) const {
+  if (Attr->isDefaultVersion())
+    return;
+  appendAttributeMangling(Attr->getFeaturesStr(), Out);
+}
+
+void ABIInfo::appendAttributeMangling(TargetVersionAttr *Attr,
+                                      raw_ostream &Out) const {
+  appendAttributeMangling(Attr->getNamesStr(), Out);
+}
+
+void ABIInfo::appendAttributeMangling(TargetClonesAttr *Attr, unsigned Index,
+                                      raw_ostream &Out) const {
+  appendAttributeMangling(Attr->getFeatureStr(Index), Out);
+  Out << '.' << Attr->getMangledIndex(Index);
+}
+
+void ABIInfo::appendAttributeMangling(StringRef AttrStr,
+                                      raw_ostream &Out) const {
+  if (AttrStr == "default") {
+    Out << ".default";
+    return;
+  }
+
+  Out << '.';
+  const TargetInfo &TI = CGT.getTarget();
+  ParsedTargetAttr Info = TI.parseTargetAttr(AttrStr);
+
+  llvm::sort(Info.Features, [&TI](StringRef LHS, StringRef RHS) {
+    // Multiversioning doesn't allow "no-${feature}", so we can
+    // only have "+" prefixes here.
+    assert(LHS.starts_with("+") && RHS.starts_with("+") &&
+           "Features should always have a prefix.");
+    return TI.multiVersionSortPriority(LHS.substr(1)) >
+           TI.multiVersionSortPriority(RHS.substr(1));
+  });
+
+  bool IsFirst = true;
+  if (!Info.CPU.empty()) {
+    IsFirst = false;
+    Out << "arch_" << Info.CPU;
+  }
+
+  for (StringRef Feat : Info.Features) {
+    if (!IsFirst)
+      Out << '_';
+    IsFirst = false;
+    Out << Feat.substr(1);
+  }
+}
+
 // Pin the vtable to this file.
 SwiftABIInfo::~SwiftABIInfo() = default;
 
diff --git a/clang/lib/CodeGen/ABIInfo.h b/clang/lib/CodeGen/ABIInfo.h
index b9a5ef6e43669..ff4ae44a42c33 100644
--- a/clang/lib/CodeGen/ABIInfo.h
+++ b/clang/lib/CodeGen/ABIInfo.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_CLANG_LIB_CODEGEN_ABIINFO_H
 #define LLVM_CLANG_LIB_CODEGEN_ABIINFO_H
 
+#include "clang/AST/Attr.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/Type.h"
 #include "llvm/IR/CallingConv.h"
@@ -111,6 +112,15 @@ class ABIInfo {
 
   CodeGen::ABIArgInfo getNaturalAlignIndirectInReg(QualType Ty,
                                                    bool Realign = false) const;
+
+  virtual void appendAttributeMangling(TargetAttr *Attr,
+                                       raw_ostream &Out) const;
+  virtual void appendAttributeMangling(TargetVersionAttr *Attr,
+                                       raw_ostream &Out) const;
+  virtual void appendAttributeMangling(TargetClonesAttr *Attr, unsigned Index,
+                                       raw_ostream &Out) const;
+  virtual void appendAttributeMangling(StringRef AttrStr,
+                                       raw_ostream &Out) const;
 };
 
 /// Target specific hooks for defining how a type should be passed or returned
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 98e2bdd2b7ef6..9089a0c4b2ed5 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -203,6 +203,14 @@ class EmitAssemblyHelper {
            TargetTriple.getVendor() != llvm::Triple::Apple;
   }
 
+  /// Check whether we should emit a flag for UnifiedLTO.
+  /// The UnifiedLTO module flag should be set when UnifiedLTO is enabled for
+  /// ThinLTO or Full LTO with module summaries.
+  bool shouldEmitUnifiedLTOModueFlag() const {
+    return CodeGenOpts.UnifiedLTO &&
+           (CodeGenOpts.PrepareForThinLTO || shouldEmitRegularLTOSummary());
+  }
+
 public:
   EmitAssemblyHelper(DiagnosticsEngine &_Diags,
                      const HeaderSearchOptions &HeaderSearchOpts,
@@ -1137,7 +1145,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
   if (!actionRequiresCodeGen(Action) && CodeGenOpts.VerifyModule)
     MPM.addPass(VerifierPass());
 
-  if (Action == Backend_EmitBC || Action == Backend_EmitLL) {
+  if (Action == Backend_EmitBC || Action == Backend_EmitLL ||
+      CodeGenOpts.FatLTO) {
     if (CodeGenOpts.PrepareForThinLTO && !CodeGenOpts.DisableLLVMPasses) {
       if (!TheModule->getModuleFlag("EnableSplitLTOUnit"))
         TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit",
@@ -1148,11 +1157,9 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
           if (!ThinLinkOS)
             return;
         }
-        if (CodeGenOpts.UnifiedLTO)
-          TheModule->addModuleFlag(Module::Error, "UnifiedLTO", uint32_t(1));
         MPM.addPass(ThinLTOBitcodeWriterPass(
             *OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr));
-      } else {
+      } else if (Action == Backend_EmitLL) {
         MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists,
                                     /*EmitLTOSummary=*/true));
       }
@@ -1166,24 +1173,17 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
         if (!TheModule->getModuleFlag("EnableSplitLTOUnit"))
           TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit",
                                    uint32_t(1));
-        if (CodeGenOpts.UnifiedLTO)
-          TheModule->addModuleFlag(Module::Error, "UnifiedLTO", uint32_t(1));
       }
-      if (Action == Backend_EmitBC)
+      if (Action == Backend_EmitBC) {
         MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists,
                                       EmitLTOSummary));
-      else
+      } else if (Action == Backend_EmitLL) {
         MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists,
                                     EmitLTOSummary));
+      }
     }
-  }
-  if (CodeGenOpts.FatLTO) {
-    // Set the EnableSplitLTOUnit and UnifiedLTO module flags, since FatLTO
-    // uses a different action than Backend_EmitBC or Backend_EmitLL.
-    if (!TheModule->getModuleFlag("EnableSplitLTOUnit"))
-      TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit",
-                               uint32_t(CodeGenOpts.EnableSplitLTOUnit));
-    if (CodeGenOpts.UnifiedLTO && !TheModule->getModuleFlag("UnifiedLTO"))
+
+    if (shouldEmitUnifiedLTOModueFlag())
       TheModule->addModuleFlag(llvm::Module::Error, "UnifiedLTO", uint32_t(1));
   }
 
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 04c4252017d7f..6b96c42a63b7d 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -14048,6 +14048,8 @@ Value *CodeGenFunction::EmitX86CpuIs(StringRef CPUStr) {
 Value *CodeGenFunction::EmitX86CpuSupports(const CallExpr *E) {
   const Expr *FeatureExpr = E->getArg(0)->IgnoreParenCasts();
   StringRef FeatureStr = cast(FeatureExpr)->getString();
+  if (!getContext().getTargetInfo().validateCpuSupports(FeatureStr))
+    return Builder.getFalse();
   return EmitX86CpuSupports(FeatureStr);
 }
 
@@ -14137,6 +14139,8 @@ Value *CodeGenFunction::EmitAArch64CpuSupports(const CallExpr *E) {
   ArgStr.split(Features, "+");
   for (auto &Feature : Features) {
     Feature = Feature.trim();
+    if (!llvm::AArch64::parseArchExtension(Feature))
+      return Builder.getFalse();
     if (Feature != "default")
       Features.push_back(Feature);
   }
@@ -16735,7 +16739,8 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
   .Case(Name, {FA_WORD, Bitmask})
 #include "llvm/TargetParser/PPCTargetParser.def"
             .Default({0, 0});
-    assert(BitMask && "Invalid target feature string. Missed by SemaChecking?");
+    if (!BitMask)
+      return Builder.getFalse();
     Value *Op0 = llvm::ConstantInt::get(Int32Ty, FeatureWord);
     llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_fixed_addr_ld);
     Value *TheCall = Builder.CreateCall(F, {Op0}, "cpu_supports");
@@ -17183,37 +17188,24 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
     }
     return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");
   }
-  // Rotate and insert under mask operation.
-  // __rldimi(rs, is, shift, mask)
-  // (rotl64(rs, shift) & mask) | (is & ~mask)
-  // __rlwimi(rs, is, shift, mask)
-  // (rotl(rs, shift) & mask) | (is & ~mask)
   case PPC::BI__builtin_ppc_rldimi:
   case PPC::BI__builtin_ppc_rlwimi: {
     Value *Op0 = EmitScalarExpr(E->getArg(0));
     Value *Op1 = EmitScalarExpr(E->getArg(1));
     Value *Op2 = EmitScalarExpr(E->getArg(2));
     Value *Op3 = EmitScalarExpr(E->getArg(3));
-    llvm::Type *Ty = Op0->getType();
-    Function *F = CGM.getIntrinsic(Intrinsic::fshl, Ty);
-    if (BuiltinID == PPC::BI__builtin_ppc_rldimi)
-      Op2 = Builder.CreateZExt(Op2, Int64Ty);
-    Value *Shift = Builder.CreateCall(F, {Op0, Op0, Op2});
-    Value *X = Builder.CreateAnd(Shift, Op3);
-    Value *Y = Builder.CreateAnd(Op1, Builder.CreateNot(Op3));
-    return Builder.CreateOr(X, Y);
-  }
-  // Rotate and insert under mask operation.
-  // __rlwnm(rs, shift, mask)
-  // rotl(rs, shift) & mask
+    return Builder.CreateCall(
+        CGM.getIntrinsic(BuiltinID == PPC::BI__builtin_ppc_rldimi
+                             ? Intrinsic::ppc_rldimi
+                             : Intrinsic::ppc_rlwimi),
+        {Op0, Op1, Op2, Op3});
+  }
   case PPC::BI__builtin_ppc_rlwnm: {
     Value *Op0 = EmitScalarExpr(E->getArg(0));
     Value *Op1 = EmitScalarExpr(E->getArg(1));
     Value *Op2 = EmitScalarExpr(E->getArg(2));
-    llvm::Type *Ty = Op0->getType();
-    Function *F = CGM.getIntrinsic(Intrinsic::fshl, Ty);
-    Value *Shift = Builder.CreateCall(F, {Op0, Op0, Op1});
-    return Builder.CreateAnd(Shift, Op2);
+    return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_rlwnm),
+                              {Op0, Op1, Op2});
   }
   case PPC::BI__builtin_ppc_poppar4:
   case PPC::BI__builtin_ppc_poppar8: {
@@ -18068,6 +18060,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));
@@ -18101,9 +18099,81 @@ 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: {
+    Value *X = EmitScalarExpr(E->getArg(0));
+    Value *Y = EmitScalarExpr(E->getArg(1));
+    Value *S = EmitScalarExpr(E->getArg(2));
+    llvm::Type *Xty = X->getType();
+    llvm::Type *Yty = Y->getType();
+    llvm::Type *Sty = S->getType();
+    if (!Xty->isVectorTy() && !Yty->isVectorTy() && !Sty->isVectorTy()) {
+      if (Xty->isFloatingPointTy()) {
+        auto V = Builder.CreateFSub(Y, X);
+        V = Builder.CreateFMul(S, V);
+        return Builder.CreateFAdd(X, V, "dx.lerp");
+      }
+      llvm_unreachable("Scalar Lerp is only supported on floats.");
+    }
+    // A VectorSplat should have happened
+    assert(Xty->isVectorTy() && Yty->isVectorTy() && Sty->isVectorTy() &&
+           "Lerp of vector and scalar is not supported.");
+
+    [[maybe_unused]] auto *XVecTy =
+        E->getArg(0)->getType()->getAs();
+    [[maybe_unused]] auto *YVecTy =
+        E->getArg(1)->getType()->getAs();
+    [[maybe_unused]] auto *SVecTy =
+        E->getArg(2)->getType()->getAs();
+    // A HLSLVectorTruncation should have happend
+    assert(XVecTy->getNumElements() == YVecTy->getNumElements() &&
+           XVecTy->getNumElements() == SVecTy->getNumElements() &&
+           "Lerp requires vectors to be of the same size.");
+    assert(XVecTy->getElementType()->isRealFloatingType() &&
+           XVecTy->getElementType() == YVecTy->getElementType() &&
+           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},
+        nullptr, "dx.lerp");
+  }
+  case Builtin::BI__builtin_hlsl_elementwise_frac: {
+    Value *Op0 = EmitScalarExpr(E->getArg(0));
+    if (!E->getArg(0)->getType()->hasFloatingRepresentation())
+      llvm_unreachable("frac operand must have a float representation");
+    return Builder.CreateIntrinsic(
+        /*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;
 }
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index f15c0876e5493..7e7dfb799652e 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -3303,12 +3303,11 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
 
       llvm::StructType *STy =
           dyn_cast(ArgI.getCoerceToType());
-      llvm::TypeSize StructSize;
-      llvm::TypeSize PtrElementSize;
       if (ArgI.isDirect() && !ArgI.getCanBeFlattened() && STy &&
           STy->getNumElements() > 1) {
-        StructSize = CGM.getDataLayout().getTypeAllocSize(STy);
-        PtrElementSize =
+        [[maybe_unused]] llvm::TypeSize StructSize =
+            CGM.getDataLayout().getTypeAllocSize(STy);
+        [[maybe_unused]] llvm::TypeSize PtrElementSize =
             CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(Ty));
         if (STy->containsHomogeneousScalableVectorTypes()) {
           assert(StructSize == PtrElementSize &&
@@ -5396,12 +5395,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
 
       llvm::StructType *STy =
           dyn_cast(ArgInfo.getCoerceToType());
-      llvm::Type *SrcTy = ConvertTypeForMem(I->Ty);
-      llvm::TypeSize SrcTypeSize;
-      llvm::TypeSize DstTypeSize;
       if (STy && ArgInfo.isDirect() && !ArgInfo.getCanBeFlattened()) {
-        SrcTypeSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
-        DstTypeSize = CGM.getDataLayout().getTypeAllocSize(STy);
+        llvm::Type *SrcTy = ConvertTypeForMem(I->Ty);
+        [[maybe_unused]] llvm::TypeSize SrcTypeSize =
+            CGM.getDataLayout().getTypeAllocSize(SrcTy);
+        [[maybe_unused]] llvm::TypeSize DstTypeSize =
+            CGM.getDataLayout().getTypeAllocSize(STy);
         if (STy->containsHomogeneousScalableVectorTypes()) {
           assert(SrcTypeSize == DstTypeSize &&
                  "Only allow non-fractional movement of structure with "
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index e887d35198b3c..794d93358b0a4 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 27d77e9a8a551..e815e097e1fb4 100644
--- a/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/clang/lib/CodeGen/CGObjCMac.cpp
@@ -1593,12 +1593,20 @@ class CGObjCNonFragileABIMac : public CGObjCCommonMac {
   }
 
   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/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 3c62bb81a7903..9cd16dc811e96 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -7023,31 +7023,47 @@ void CodeGenFunction::EmitOMPInteropDirective(const OMPInteropDirective &S) {
                                      S.getSingleClause())) &&
          "OMPNowaitClause clause is used separately in OMPInteropDirective.");
 
-  if (const auto *C = S.getSingleClause()) {
-    llvm::Value *InteropvarPtr =
-        EmitLValue(C->getInteropVar()).getPointer(*this);
-    llvm::omp::OMPInteropType InteropType = llvm::omp::OMPInteropType::Unknown;
-    if (C->getIsTarget()) {
-      InteropType = llvm::omp::OMPInteropType::Target;
-    } else {
-      assert(C->getIsTargetSync() && "Expected interop-type target/targetsync");
-      InteropType = llvm::omp::OMPInteropType::TargetSync;
+  auto ItOMPInitClause = S.getClausesOfKind();
+  if (!ItOMPInitClause.empty()) {
+    // Look at the multiple init clauses
+    for (const OMPInitClause *C : ItOMPInitClause) {
+      llvm::Value *InteropvarPtr =
+          EmitLValue(C->getInteropVar()).getPointer(*this);
+      llvm::omp::OMPInteropType InteropType =
+          llvm::omp::OMPInteropType::Unknown;
+      if (C->getIsTarget()) {
+        InteropType = llvm::omp::OMPInteropType::Target;
+      } else {
+        assert(C->getIsTargetSync() &&
+               "Expected interop-type target/targetsync");
+        InteropType = llvm::omp::OMPInteropType::TargetSync;
+      }
+      OMPBuilder.createOMPInteropInit(Builder, InteropvarPtr, InteropType,
+                                      Device, NumDependences, DependenceList,
+                                      Data.HasNowaitClause);
+    }
+  }
+  auto ItOMPDestroyClause = S.getClausesOfKind();
+  if (!ItOMPDestroyClause.empty()) {
+    // Look at the multiple destroy clauses
+    for (const OMPDestroyClause *C : ItOMPDestroyClause) {
+      llvm::Value *InteropvarPtr =
+          EmitLValue(C->getInteropVar()).getPointer(*this);
+      OMPBuilder.createOMPInteropDestroy(Builder, InteropvarPtr, Device,
+                                         NumDependences, DependenceList,
+                                         Data.HasNowaitClause);
+    }
+  }
+  auto ItOMPUseClause = S.getClausesOfKind();
+  if (!ItOMPUseClause.empty()) {
+    // Look at the multiple use clauses
+    for (const OMPUseClause *C : ItOMPUseClause) {
+      llvm::Value *InteropvarPtr =
+          EmitLValue(C->getInteropVar()).getPointer(*this);
+      OMPBuilder.createOMPInteropUse(Builder, InteropvarPtr, Device,
+                                     NumDependences, DependenceList,
+                                     Data.HasNowaitClause);
     }
-    OMPBuilder.createOMPInteropInit(Builder, InteropvarPtr, InteropType, Device,
-                                    NumDependences, DependenceList,
-                                    Data.HasNowaitClause);
-  } else if (const auto *C = S.getSingleClause()) {
-    llvm::Value *InteropvarPtr =
-        EmitLValue(C->getInteropVar()).getPointer(*this);
-    OMPBuilder.createOMPInteropDestroy(Builder, InteropvarPtr, Device,
-                                       NumDependences, DependenceList,
-                                       Data.HasNowaitClause);
-  } else if (const auto *C = S.getSingleClause()) {
-    llvm::Value *InteropvarPtr =
-        EmitLValue(C->getInteropVar()).getPointer(*this);
-    OMPBuilder.createOMPInteropUse(Builder, InteropvarPtr, Device,
-                                   NumDependences, DependenceList,
-                                   Data.HasNowaitClause);
   }
 }
 
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index a9890aa9c5a8f..b23bf3b828b27 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1819,59 +1819,6 @@ static void AppendCPUSpecificCPUDispatchMangling(const CodeGenModule &CGM,
     Out << ".resolver";
 }
 
-static void AppendTargetVersionMangling(const CodeGenModule &CGM,
-                                        const TargetVersionAttr *Attr,
-                                        raw_ostream &Out) {
-  if (Attr->isDefaultVersion()) {
-    Out << ".default";
-    return;
-  }
-  Out << "._";
-  const TargetInfo &TI = CGM.getTarget();
-  llvm::SmallVector Feats;
-  Attr->getFeatures(Feats);
-  llvm::stable_sort(Feats, [&TI](const StringRef FeatL, const StringRef FeatR) {
-    return TI.multiVersionSortPriority(FeatL) <
-           TI.multiVersionSortPriority(FeatR);
-  });
-  for (const auto &Feat : Feats) {
-    Out << 'M';
-    Out << Feat;
-  }
-}
-
-static void AppendTargetMangling(const CodeGenModule &CGM,
-                                 const TargetAttr *Attr, raw_ostream &Out) {
-  if (Attr->isDefaultVersion())
-    return;
-
-  Out << '.';
-  const TargetInfo &Target = CGM.getTarget();
-  ParsedTargetAttr Info = Target.parseTargetAttr(Attr->getFeaturesStr());
-  llvm::sort(Info.Features, [&Target](StringRef LHS, StringRef RHS) {
-    // Multiversioning doesn't allow "no-${feature}", so we can
-    // only have "+" prefixes here.
-    assert(LHS.starts_with("+") && RHS.starts_with("+") &&
-           "Features should always have a prefix.");
-    return Target.multiVersionSortPriority(LHS.substr(1)) >
-           Target.multiVersionSortPriority(RHS.substr(1));
-  });
-
-  bool IsFirst = true;
-
-  if (!Info.CPU.empty()) {
-    IsFirst = false;
-    Out << "arch_" << Info.CPU;
-  }
-
-  for (StringRef Feat : Info.Features) {
-    if (!IsFirst)
-      Out << '_';
-    IsFirst = false;
-    Out << Feat.substr(1);
-  }
-}
-
 // Returns true if GD is a function decl with internal linkage and
 // needs a unique suffix after the mangled name.
 static bool isUniqueInternalLinkageDecl(GlobalDecl GD,
@@ -1881,41 +1828,6 @@ static bool isUniqueInternalLinkageDecl(GlobalDecl GD,
          (CGM.getFunctionLinkage(GD) == llvm::GlobalValue::InternalLinkage);
 }
 
-static void AppendTargetClonesMangling(const CodeGenModule &CGM,
-                                       const TargetClonesAttr *Attr,
-                                       unsigned VersionIndex,
-                                       raw_ostream &Out) {
-  const TargetInfo &TI = CGM.getTarget();
-  if (TI.getTriple().isAArch64()) {
-    StringRef FeatureStr = Attr->getFeatureStr(VersionIndex);
-    if (FeatureStr == "default") {
-      Out << ".default";
-      return;
-    }
-    Out << "._";
-    SmallVector Features;
-    FeatureStr.split(Features, "+");
-    llvm::stable_sort(Features,
-                      [&TI](const StringRef FeatL, const StringRef FeatR) {
-                        return TI.multiVersionSortPriority(FeatL) <
-                               TI.multiVersionSortPriority(FeatR);
-                      });
-    for (auto &Feat : Features) {
-      Out << 'M';
-      Out << Feat;
-    }
-  } else {
-    Out << '.';
-    StringRef FeatureStr = Attr->getFeatureStr(VersionIndex);
-    if (FeatureStr.starts_with("arch="))
-      Out << "arch_" << FeatureStr.substr(sizeof("arch=") - 1);
-    else
-      Out << FeatureStr;
-
-    Out << '.' << Attr->getMangledIndex(VersionIndex);
-  }
-}
-
 static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD,
                                       const NamedDecl *ND,
                                       bool OmitMultiVersionMangling = false) {
@@ -1969,16 +1881,25 @@ static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD,
                                              FD->getAttr(),
                                              GD.getMultiVersionIndex(), Out);
         break;
-      case MultiVersionKind::Target:
-        AppendTargetMangling(CGM, FD->getAttr(), Out);
+      case MultiVersionKind::Target: {
+        auto *Attr = FD->getAttr();
+        const ABIInfo &Info = CGM.getTargetCodeGenInfo().getABIInfo();
+        Info.appendAttributeMangling(Attr, Out);
         break;
-      case MultiVersionKind::TargetVersion:
-        AppendTargetVersionMangling(CGM, FD->getAttr(), Out);
+      }
+      case MultiVersionKind::TargetVersion: {
+        auto *Attr = FD->getAttr();
+        const ABIInfo &Info = CGM.getTargetCodeGenInfo().getABIInfo();
+        Info.appendAttributeMangling(Attr, Out);
         break;
-      case MultiVersionKind::TargetClones:
-        AppendTargetClonesMangling(CGM, FD->getAttr(),
-                                   GD.getMultiVersionIndex(), Out);
+      }
+      case MultiVersionKind::TargetClones: {
+        auto *Attr = FD->getAttr();
+        unsigned Index = GD.getMultiVersionIndex();
+        const ABIInfo &Info = CGM.getTargetCodeGenInfo().getABIInfo();
+        Info.appendAttributeMangling(Attr, Index, Out);
         break;
+      }
       case MultiVersionKind::None:
         llvm_unreachable("None multiversion type isn't valid here");
       }
diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index 94f8e7be2ee6e..725e8a70fddfe 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -9,6 +9,7 @@
 #include "ABIInfoImpl.h"
 #include "TargetInfo.h"
 #include "clang/Basic/DiagnosticFrontend.h"
+#include "llvm/TargetParser/AArch64TargetParser.h"
 
 using namespace clang;
 using namespace clang::CodeGen;
@@ -75,6 +76,12 @@ class AArch64ABIInfo : public ABIInfo {
   bool allowBFloatArgsAndRet() const override {
     return getTarget().hasBFloat16Type();
   }
+
+  using ABIInfo::appendAttributeMangling;
+  void appendAttributeMangling(TargetClonesAttr *Attr, unsigned Index,
+                               raw_ostream &Out) const override;
+  void appendAttributeMangling(StringRef AttrStr,
+                               raw_ostream &Out) const override;
 };
 
 class AArch64SwiftABIInfo : public SwiftABIInfo {
@@ -125,8 +132,7 @@ class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {
     assert(Error.empty());
 
     auto *Fn = cast(GV);
-    static const char *SignReturnAddrStr[] = {"none", "non-leaf", "all"};
-    Fn->addFnAttr("sign-return-address", SignReturnAddrStr[static_cast(BPI.SignReturnAddr)]);
+    Fn->addFnAttr("sign-return-address", BPI.getSignReturnAddrStr());
 
     if (BPI.SignReturnAddr != LangOptions::SignReturnAddressScopeKind::None) {
       Fn->addFnAttr("sign-return-address-key",
@@ -857,6 +863,34 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABI(
           << Callee->getDeclName();
 }
 
+void AArch64ABIInfo::appendAttributeMangling(TargetClonesAttr *Attr,
+                                             unsigned Index,
+                                             raw_ostream &Out) const {
+  appendAttributeMangling(Attr->getFeatureStr(Index), Out);
+}
+
+void AArch64ABIInfo::appendAttributeMangling(StringRef AttrStr,
+                                             raw_ostream &Out) const {
+  if (AttrStr == "default") {
+    Out << ".default";
+    return;
+  }
+
+  Out << "._";
+  SmallVector Features;
+  AttrStr.split(Features, "+");
+  for (auto &Feat : Features)
+    Feat = Feat.trim();
+
+  llvm::sort(Features, [](const StringRef LHS, const StringRef RHS) {
+    return LHS.compare(RHS) < 0;
+  });
+
+  for (auto &Feat : Features)
+    if (auto Ext = llvm::AArch64::parseArchExtension(Feat))
+      Out << 'M' << Ext->Name;
+}
+
 std::unique_ptr
 CodeGen::createAArch64TargetCodeGenInfo(CodeGenModule &CGM,
                                         AArch64ABIKind Kind) {
diff --git a/clang/lib/CodeGen/Targets/ARM.cpp b/clang/lib/CodeGen/Targets/ARM.cpp
index d7d175ff1724f..5d42e6286e525 100644
--- a/clang/lib/CodeGen/Targets/ARM.cpp
+++ b/clang/lib/CodeGen/Targets/ARM.cpp
@@ -152,13 +152,7 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
               diag::warn_target_unsupported_branch_protection_attribute)
               << Arch;
         } else {
-          static const char *SignReturnAddrStr[] = {"none", "non-leaf", "all"};
-          assert(static_cast(BPI.SignReturnAddr) <= 2 &&
-                 "Unexpected SignReturnAddressScopeKind");
-          Fn->addFnAttr(
-              "sign-return-address",
-              SignReturnAddrStr[static_cast(BPI.SignReturnAddr)]);
-
+          Fn->addFnAttr("sign-return-address", BPI.getSignReturnAddrStr());
           Fn->addFnAttr("branch-target-enforcement",
                         BPI.BranchTargetEnforcement ? "true" : "false");
         }
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index dff22182fbc0c..73a5a61a0aa3b 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -216,11 +216,10 @@ Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,
 
   Name = std::string(llvm::sys::path::filename(ClangExecutable));
   Dir = std::string(llvm::sys::path::parent_path(ClangExecutable));
-  InstalledDir = Dir; // Provide a sensible default installed dir.
 
   if ((!SysRoot.empty()) && llvm::sys::path::is_relative(SysRoot)) {
     // Prepend InstalledDir if SysRoot is relative
-    SmallString<128> P(InstalledDir);
+    SmallString<128> P(Dir);
     llvm::sys::path::append(P, SysRoot);
     SysRoot = std::string(P);
   }
@@ -1694,7 +1693,7 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) {
   if (const Arg *A = Args.getLastArg(options::OPT_target))
     TargetTriple = A->getValue();
   if (const Arg *A = Args.getLastArg(options::OPT_ccc_install_dir))
-    Dir = InstalledDir = A->getValue();
+    Dir = Dir = A->getValue();
   for (const Arg *A : Args.filtered(options::OPT_B)) {
     A->claim();
     PrefixDirs.push_back(A->getValue(0));
@@ -2476,7 +2475,7 @@ void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const {
   OS << '\n';
 
   // Print out the install directory.
-  OS << "InstalledDir: " << InstalledDir << '\n';
+  OS << "InstalledDir: " << Dir << '\n';
 
   // If configuration files were used, print their paths.
   for (auto ConfigFile : ConfigFiles)
@@ -4185,7 +4184,7 @@ class OffloadingActionBuilder final {
                       const Driver::InputList &Inputs,
                       OffloadingActionBuilder &OAB)
         : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_Cuda, OAB) {
-      DefaultCudaArch = CudaArch::SM_35;
+      DefaultCudaArch = CudaArch::CudaDefault;
     }
 
     StringRef getCanonicalOffloadArch(StringRef ArchStr) override {
diff --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp
index e6126ff62db3c..3c7049a99982d 100644
--- a/clang/lib/Driver/ToolChains/AIX.cpp
+++ b/clang/lib/Driver/ToolChains/AIX.cpp
@@ -342,9 +342,7 @@ void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
 /// AIX - AIX tool chain which can call as(1) and ld(1) directly.
 AIX::AIX(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
     : ToolChain(D, Triple, Args) {
-  getProgramPaths().push_back(getDriver().getInstalledDir());
-  if (getDriver().getInstalledDir() != getDriver().Dir)
-    getProgramPaths().push_back(getDriver().Dir);
+  getProgramPaths().push_back(getDriver().Dir);
 
   ParseInlineAsmUsingAsmParser = Args.hasFlag(
       options::OPT_fintegrated_as, options::OPT_fno_integrated_as, true);
diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp
index 856aeaa3ed256..ee148d8b462bc 100644
--- a/clang/lib/Driver/ToolChains/AMDGPU.cpp
+++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp
@@ -209,7 +209,7 @@ RocmInstallationDetector::getInstallationPathCandidates() {
   }
 
   // Try to find relative to the compiler binary.
-  const char *InstallDir = D.getInstalledDir();
+  StringRef InstallDir = D.Dir;
 
   // Check both a normal Unix prefix position of the clang binary, as well as
   // the Windows-esque layout the ROCm packages use with the host architecture
diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
index 0cf96bb5c9cb0..aa3b80cb16e55 100644
--- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
@@ -165,11 +165,14 @@ getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
   // Handle CPU name is 'native'.
   if (MtuneLowerCase == "native")
     MtuneLowerCase = std::string(llvm::sys::getHostCPUName());
+
+  // 'cyclone' and later have zero-cycle register moves and zeroing.
   if (MtuneLowerCase == "cyclone" ||
       StringRef(MtuneLowerCase).starts_with("apple")) {
     Features.push_back("+zcm");
     Features.push_back("+zcz");
   }
+
   return true;
 }
 
diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp
index d5fc1d5dd25a8..221c481579240 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -100,9 +100,7 @@ static bool findRISCVMultilibs(const Driver &D,
 BareMetal::BareMetal(const Driver &D, const llvm::Triple &Triple,
                      const ArgList &Args)
     : ToolChain(D, Triple, Args) {
-  getProgramPaths().push_back(getDriver().getInstalledDir());
-  if (getDriver().getInstalledDir() != getDriver().Dir)
-    getProgramPaths().push_back(getDriver().Dir);
+  getProgramPaths().push_back(getDriver().Dir);
 
   findMultilibs(D, Triple, Args);
   SmallString<128> SysRoot(computeSysRoot());
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 2eaa416224ebb..1f556e230670c 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -1209,7 +1209,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
     if ((getToolChain().getTriple().isNVPTX() ||
          getToolChain().getTriple().isAMDGCN()) &&
         C.getActiveOffloadKinds() == Action::OFK_None) {
-      SmallString<128> P(llvm::sys::path::parent_path(D.InstalledDir));
+      SmallString<128> P(llvm::sys::path::parent_path(D.Dir));
       llvm::sys::path::append(P, "include");
       llvm::sys::path::append(P, getToolChain().getTripleString());
       CmdArgs.push_back("-internal-isystem");
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index db8c8a5eaae3b..48aeaa3790d82 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -2791,14 +2791,10 @@ void tools::addOpenMPDeviceRTL(const Driver &D,
                                const llvm::opt::ArgList &DriverArgs,
                                llvm::opt::ArgStringList &CC1Args,
                                StringRef BitcodeSuffix,
-                               const llvm::Triple &Triple) {
+                               const llvm::Triple &Triple,
+                               const ToolChain &HostTC) {
   SmallVector LibraryPaths;
 
-  // Add path to clang lib / lib64 folder.
-  SmallString<256> DefaultLibPath = llvm::sys::path::parent_path(D.Dir);
-  llvm::sys::path::append(DefaultLibPath, CLANG_INSTALL_LIBDIR_BASENAME);
-  LibraryPaths.emplace_back(DefaultLibPath.c_str());
-
   // Add user defined library paths from LIBRARY_PATH.
   std::optional LibPath =
       llvm::sys::Process::GetEnv("LIBRARY_PATH");
@@ -2810,6 +2806,10 @@ void tools::addOpenMPDeviceRTL(const Driver &D,
       LibraryPaths.emplace_back(Path.trim());
   }
 
+  // Check all of the standard library search paths used by the compiler.
+  for (const auto &LibPath : HostTC.getFilePaths())
+    LibraryPaths.emplace_back(LibPath);
+
   OptSpecifier LibomptargetBCPathOpt =
       Triple.isAMDGCN() ? options::OPT_libomptarget_amdgpu_bc_path_EQ
                         : options::OPT_libomptarget_nvptx_bc_path_EQ;
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h
index f97bca2ea77cd..f861080d6e365 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.h
+++ b/clang/lib/Driver/ToolChains/CommonArgs.h
@@ -221,7 +221,8 @@ void addMachineOutlinerArgs(const Driver &D, const llvm::opt::ArgList &Args,
 
 void addOpenMPDeviceRTL(const Driver &D, const llvm::opt::ArgList &DriverArgs,
                         llvm::opt::ArgStringList &CC1Args,
-                        StringRef BitcodeSuffix, const llvm::Triple &Triple);
+                        StringRef BitcodeSuffix, const llvm::Triple &Triple,
+                        const ToolChain &HostTC);
 
 void addOutlineAtomicsArgs(const Driver &D, const ToolChain &TC,
                            const llvm::opt::ArgList &Args,
diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp
index 8bcb0a81766e1..f18845e5de315 100644
--- a/clang/lib/Driver/ToolChains/Cuda.cpp
+++ b/clang/lib/Driver/ToolChains/Cuda.cpp
@@ -1063,7 +1063,7 @@ void CudaToolChain::addClangTargetOptions(
       return;
 
     addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, GpuArch.str(),
-                       getTriple());
+                       getTriple(), HostTC);
     AddStaticDeviceLibsPostLinking(getDriver(), DriverArgs, CC1Args, "nvptx",
                                    GpuArch, /*isBitCodeSDL=*/true,
                                    /*postClangLink=*/true);
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index cc1219d69d991..c7682c7f1d337 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -643,9 +643,8 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
 
   // It seems that the 'e' option is completely ignored for dynamic executables
   // (the default), and with static executables, the last one wins, as expected.
-  Args.addAllArgs(CmdArgs,
-                  {options::OPT_d_Flag, options::OPT_s, options::OPT_t,
-                   options::OPT_Z_Flag, options::OPT_u_Group, options::OPT_r});
+  Args.addAllArgs(CmdArgs, {options::OPT_d_Flag, options::OPT_s, options::OPT_t,
+                            options::OPT_Z_Flag, options::OPT_u_Group});
 
   // Forward -ObjC when either -ObjC or -ObjC++ is used, to force loading
   // members of static archive libraries which implement Objective-C classes or
@@ -926,9 +925,7 @@ void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA,
 MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
     : ToolChain(D, Triple, Args) {
   // We expect 'as', 'ld', etc. to be adjacent to our install dir.
-  getProgramPaths().push_back(getDriver().getInstalledDir());
-  if (getDriver().getInstalledDir() != getDriver().Dir)
-    getProgramPaths().push_back(getDriver().Dir);
+  getProgramPaths().push_back(getDriver().Dir);
 }
 
 /// Darwin - Darwin tool chain for i386 and x86_64.
@@ -2517,25 +2514,19 @@ void DarwinClang::AddClangCXXStdlibIncludeArgs(
   switch (GetCXXStdlibType(DriverArgs)) {
   case ToolChain::CST_Libcxx: {
     // On Darwin, libc++ can be installed in one of the following places:
-    // 1. Alongside the compiler in /include/c++/v1
-    // 2. Alongside the compiler in /../include/c++/v1
-    // 3. In a SDK (or a custom sysroot) in /usr/include/c++/v1
+    // 1. Alongside the compiler in /../include/c++/v1
+    // 2. In a SDK (or a custom sysroot) in /usr/include/c++/v1
     //
     // The precedence of paths is as listed above, i.e. we take the first path
     // that exists. Note that we never include libc++ twice -- we take the first
     // path that exists and don't send the other paths to CC1 (otherwise
     // include_next could break).
-    //
-    // Also note that in most cases, (1) and (2) are exactly the same path.
-    // Those two paths will differ only when the `clang` program being run
-    // is actually a symlink to the real executable.
 
     // Check for (1)
     // Get from '/bin' to '/include/c++/v1'.
     // Note that InstallBin can be relative, so we use '..' instead of
     // parent_path.
-    llvm::SmallString<128> InstallBin =
-        llvm::StringRef(getDriver().getInstalledDir()); // /bin
+    llvm::SmallString<128> InstallBin(getDriver().Dir); // /bin
     llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1");
     if (getVFS().exists(InstallBin)) {
       addSystemInclude(DriverArgs, CC1Args, InstallBin);
@@ -2545,20 +2536,7 @@ void DarwinClang::AddClangCXXStdlibIncludeArgs(
                    << "\"\n";
     }
 
-    // (2) Check for the folder where the executable is located, if different.
-    if (getDriver().getInstalledDir() != getDriver().Dir) {
-      InstallBin = llvm::StringRef(getDriver().Dir);
-      llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1");
-      if (getVFS().exists(InstallBin)) {
-        addSystemInclude(DriverArgs, CC1Args, InstallBin);
-        return;
-      } else if (DriverArgs.hasArg(options::OPT_v)) {
-        llvm::errs() << "ignoring nonexistent directory \"" << InstallBin
-                     << "\"\n";
-      }
-    }
-
-    // Otherwise, check for (3)
+    // Otherwise, check for (2)
     llvm::SmallString<128> SysrootUsr = Sysroot;
     llvm::sys::path::append(SysrootUsr, "usr", "include", "c++", "v1");
     if (getVFS().exists(SysrootUsr)) {
diff --git a/clang/lib/Driver/ToolChains/DragonFly.cpp b/clang/lib/Driver/ToolChains/DragonFly.cpp
index 9942fc632e0a9..b59a172bd6ae8 100644
--- a/clang/lib/Driver/ToolChains/DragonFly.cpp
+++ b/clang/lib/Driver/ToolChains/DragonFly.cpp
@@ -122,7 +122,7 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   }
 
   Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
-                            options::OPT_s, options::OPT_t, options::OPT_r});
+                            options::OPT_s, options::OPT_t});
   ToolChain.AddFilePathLibArgs(Args, CmdArgs);
 
   AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
@@ -205,11 +205,8 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
 DragonFly::DragonFly(const Driver &D, const llvm::Triple &Triple,
                      const ArgList &Args)
     : Generic_ELF(D, Triple, Args) {
-
   // Path mangling to find libexec
-  getProgramPaths().push_back(getDriver().getInstalledDir());
-  if (getDriver().getInstalledDir() != getDriver().Dir)
-    getProgramPaths().push_back(getDriver().Dir);
+  getProgramPaths().push_back(getDriver().Dir);
 
   getFilePaths().push_back(getDriver().Dir + "/../lib");
   getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib"));
diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp
index b7c9e0e51cdb6..c5757ddebb0f3 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();
@@ -261,8 +266,8 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
 
   Args.AddAllArgs(CmdArgs, options::OPT_L);
   ToolChain.AddFilePathLibArgs(Args, CmdArgs);
-  Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,
-                            options::OPT_t, options::OPT_r});
+  Args.addAllArgs(CmdArgs,
+                  {options::OPT_T_Group, options::OPT_s, options::OPT_t});
 
   if (D.isUsingLTO()) {
     assert(!Inputs.empty() && "Must have at least one input.");
diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp
index 14b838500becc..598289f48ff43 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());
@@ -251,9 +254,7 @@ void fuchsia::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA,
 Fuchsia::Fuchsia(const Driver &D, const llvm::Triple &Triple,
                  const ArgList &Args)
     : ToolChain(D, Triple, Args) {
-  getProgramPaths().push_back(getDriver().getInstalledDir());
-  if (getDriver().getInstalledDir() != D.Dir)
-    getProgramPaths().push_back(D.Dir);
+  getProgramPaths().push_back(getDriver().Dir);
 
   if (!D.SysRoot.empty()) {
     SmallString<128> P(D.SysRoot);
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index 0df09e5823f9f..c52fdfa4876c7 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -2424,7 +2424,7 @@ void Generic_GCC::GCCInstallationDetector::init(
     }
 
     // Then look for gcc installed alongside clang.
-    Prefixes.push_back(D.InstalledDir + "/..");
+    Prefixes.push_back(D.Dir + "/..");
 
     // Next, look for prefix(es) that correspond to distribution-supplied gcc
     // installations.
@@ -3193,9 +3193,7 @@ Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple &Triple,
                          const ArgList &Args)
     : ToolChain(D, Triple, Args), GCCInstallation(D),
       CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) {
-  getProgramPaths().push_back(getDriver().getInstalledDir());
-  if (getDriver().getInstalledDir() != getDriver().Dir)
-    getProgramPaths().push_back(getDriver().Dir);
+  getProgramPaths().push_back(getDriver().Dir);
 }
 
 Generic_GCC::~Generic_GCC() {}
diff --git a/clang/lib/Driver/ToolChains/Haiku.cpp b/clang/lib/Driver/ToolChains/Haiku.cpp
index e0d94035823fd..30464e2229e65 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()) {
@@ -80,7 +83,7 @@ void haiku::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   }
 
   Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
-                            options::OPT_s, options::OPT_t, options::OPT_r});
+                            options::OPT_s, options::OPT_t});
   ToolChain.AddFilePathLibArgs(Args, CmdArgs);
 
   if (D.isUsingLTO()) {
diff --git a/clang/lib/Driver/ToolChains/Hexagon.cpp b/clang/lib/Driver/ToolChains/Hexagon.cpp
index fa47c98901e14..12b3b99df7ca1 100644
--- a/clang/lib/Driver/ToolChains/Hexagon.cpp
+++ b/clang/lib/Driver/ToolChains/Hexagon.cpp
@@ -411,7 +411,7 @@ constructHexagonLinkArgs(Compilation &C, const JobAction &JA,
   const std::string MCpuSuffix = "/" + CpuVer.str();
   const std::string MCpuG0Suffix = MCpuSuffix + "/G0";
   const std::string RootDir =
-      HTC.getHexagonTargetDir(D.InstalledDir, D.PrefixDirs) + "/";
+      HTC.getHexagonTargetDir(D.Dir, D.PrefixDirs) + "/";
   const std::string StartSubDir =
       "hexagon/lib" + (UseG0 ? MCpuG0Suffix : MCpuSuffix);
 
@@ -569,8 +569,7 @@ void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,
   std::copy(D.PrefixDirs.begin(), D.PrefixDirs.end(),
             std::back_inserter(RootDirs));
 
-  std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
-                                              D.PrefixDirs);
+  std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);
   if (!llvm::is_contained(RootDirs, TargetDir))
     RootDirs.push_back(TargetDir);
 
@@ -597,8 +596,7 @@ void HexagonToolChain::getHexagonLibraryPaths(const ArgList &Args,
 HexagonToolChain::HexagonToolChain(const Driver &D, const llvm::Triple &Triple,
                                    const llvm::opt::ArgList &Args)
     : Linux(D, Triple, Args) {
-  const std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
-                                                    D.PrefixDirs);
+  const std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);
 
   // Note: Generic_GCC::Generic_GCC adds InstalledDir and getDriver().Dir to
   // program paths
@@ -728,8 +726,7 @@ void HexagonToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
 
   if (HasSysRoot)
     return;
-  std::string TargetDir = getHexagonTargetDir(D.getInstalledDir(),
-                                              D.PrefixDirs);
+  std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);
   addExternCSystemInclude(DriverArgs, CC1Args, TargetDir + "/hexagon/include");
 }
 
@@ -744,7 +741,7 @@ void HexagonToolChain::addLibCxxIncludePaths(
     addLibStdCXXIncludePaths("/usr/include/c++/v1", "", "", DriverArgs,
                              CC1Args);
   else {
-    std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
+    std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);
     addLibStdCXXIncludePaths(TargetDir + "/hexagon/include/c++/v1", "", "",
                              DriverArgs, CC1Args);
   }
@@ -753,7 +750,7 @@ void HexagonToolChain::addLibStdCxxIncludePaths(
     const llvm::opt::ArgList &DriverArgs,
     llvm::opt::ArgStringList &CC1Args) const {
   const Driver &D = getDriver();
-  std::string TargetDir = getHexagonTargetDir(D.InstalledDir, D.PrefixDirs);
+  std::string TargetDir = getHexagonTargetDir(D.Dir, D.PrefixDirs);
   addLibStdCXXIncludePaths(TargetDir + "/hexagon/include/c++", "", "",
                            DriverArgs, CC1Args);
 }
diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index 01887706d8757..c151debdc5c07 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -242,11 +242,18 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
     ExtraOpts.push_back("relro");
   }
 
-  // Android ARM/AArch64 use max-page-size=4096 to reduce VMA usage. Note, lld
-  // from 11 onwards default max-page-size to 65536 for both ARM and AArch64.
-  if ((Triple.isARM() || Triple.isAArch64()) && Triple.isAndroid()) {
-    ExtraOpts.push_back("-z");
-    ExtraOpts.push_back("max-page-size=4096");
+  // Note, lld from 11 onwards default max-page-size to 65536 for both ARM and
+  // AArch64.
+  if (Triple.isAndroid()) {
+    if (Triple.isARM()) {
+      // Android ARM uses max-page-size=4096 to reduce VMA usage.
+      ExtraOpts.push_back("-z");
+      ExtraOpts.push_back("max-page-size=4096");
+    } else if (Triple.isAArch64()) {
+      // Android AArch64 uses max-page-size=16384 to support 4k/16k page sizes.
+      ExtraOpts.push_back("-z");
+      ExtraOpts.push_back("max-page-size=16384");
+    }
   }
 
   if (GCCInstallation.getParentLibPath().contains("opt/rh/"))
@@ -390,7 +397,7 @@ std::string Linux::computeSysRoot() const {
   if (getTriple().isAndroid()) {
     // Android toolchains typically include a sysroot at ../sysroot relative to
     // the clang binary.
-    const StringRef ClangDir = getDriver().getInstalledDir();
+    const StringRef ClangDir = getDriver().Dir;
     std::string AndroidSysRootPath = (ClangDir + "/../sysroot").str();
     if (getVFS().exists(AndroidSysRootPath))
       return AndroidSysRootPath;
diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp
index 5e08965320004..ce59bc4fa6317 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -515,9 +515,7 @@ MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
                              const ArgList &Args)
     : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args),
       RocmInstallation(D, Triple, Args) {
-  getProgramPaths().push_back(getDriver().getInstalledDir());
-  if (getDriver().getInstalledDir() != getDriver().Dir)
-    getProgramPaths().push_back(getDriver().Dir);
+  getProgramPaths().push_back(getDriver().Dir);
 
   std::optional VCToolsDir, VCToolsVersion;
   if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir))
diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp
index 2b7fc104ea95a..11e81ebde7eeb 100644
--- a/clang/lib/Driver/ToolChains/MinGW.cpp
+++ b/clang/lib/Driver/ToolChains/MinGW.cpp
@@ -463,7 +463,7 @@ findClangRelativeSysroot(const Driver &D, const llvm::Triple &LiteralTriple,
   Subdirs.back() += "-w64-mingw32";
   Subdirs.emplace_back(T.getArchName());
   Subdirs.back() += "-w64-mingw32ucrt";
-  StringRef ClangRoot = llvm::sys::path::parent_path(D.getInstalledDir());
+  StringRef ClangRoot = llvm::sys::path::parent_path(D.Dir);
   StringRef Sep = llvm::sys::path::get_separator();
   for (StringRef CandidateSubdir : Subdirs) {
     if (llvm::sys::fs::is_directory(ClangRoot + Sep + CandidateSubdir)) {
@@ -487,10 +487,10 @@ toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple,
                          const ArgList &Args)
     : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args),
       RocmInstallation(D, Triple, Args) {
-  getProgramPaths().push_back(getDriver().getInstalledDir());
+  getProgramPaths().push_back(getDriver().Dir);
 
   std::string InstallBase =
-      std::string(llvm::sys::path::parent_path(getDriver().getInstalledDir()));
+      std::string(llvm::sys::path::parent_path(getDriver().Dir));
   // The sequence for detecting a sysroot here should be kept in sync with
   // the testTriple function below.
   llvm::Triple LiteralTriple = getLiteralTriple(D, getTriple());
@@ -796,8 +796,7 @@ static bool testTriple(const Driver &D, const llvm::Triple &Triple,
   if (D.SysRoot.size())
     return true;
   llvm::Triple LiteralTriple = getLiteralTriple(D, Triple);
-  std::string InstallBase =
-      std::string(llvm::sys::path::parent_path(D.getInstalledDir()));
+  std::string InstallBase = std::string(llvm::sys::path::parent_path(D.Dir));
   if (llvm::ErrorOr TargetSubdir =
           findClangRelativeSysroot(D, LiteralTriple, Triple, SubdirName))
     return true;
diff --git a/clang/lib/Driver/ToolChains/MipsLinux.cpp b/clang/lib/Driver/ToolChains/MipsLinux.cpp
index 4183eccceedb4..f61ae471b86d5 100644
--- a/clang/lib/Driver/ToolChains/MipsLinux.cpp
+++ b/clang/lib/Driver/ToolChains/MipsLinux.cpp
@@ -57,8 +57,7 @@ void MipsLLVMToolChain::AddClangSystemIncludeArgs(
   const auto &Callback = Multilibs.includeDirsCallback();
   if (Callback) {
     for (const auto &Path : Callback(SelectedMultilibs.back()))
-      addExternCSystemIncludeIfExists(DriverArgs, CC1Args,
-                                      D.getInstalledDir() + Path);
+      addExternCSystemIncludeIfExists(DriverArgs, CC1Args, D.Dir + Path);
   }
 }
 
@@ -70,7 +69,7 @@ std::string MipsLLVMToolChain::computeSysRoot() const {
   if (!getDriver().SysRoot.empty())
     return getDriver().SysRoot + SelectedMultilibs.back().osSuffix();
 
-  const std::string InstalledDir(getDriver().getInstalledDir());
+  const std::string InstalledDir(getDriver().Dir);
   std::string SysRootPath =
       InstalledDir + "/../sysroot" + SelectedMultilibs.back().osSuffix();
   if (llvm::sys::fs::exists(SysRootPath))
@@ -97,7 +96,7 @@ void MipsLLVMToolChain::addLibCxxIncludePaths(
     llvm::opt::ArgStringList &CC1Args) const {
   if (const auto &Callback = Multilibs.includeDirsCallback()) {
     for (std::string Path : Callback(SelectedMultilibs.back())) {
-      Path = getDriver().getInstalledDir() + Path + "/c++/v1";
+      Path = getDriver().Dir + Path + "/c++/v1";
       if (llvm::sys::fs::exists(Path)) {
         addSystemInclude(DriverArgs, CC1Args, Path);
         return;
diff --git a/clang/lib/Driver/ToolChains/NetBSD.cpp b/clang/lib/Driver/ToolChains/NetBSD.cpp
index 240bf5764b9cc..0eec8fddabd5d 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()) {
@@ -268,7 +271,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   }
 
   Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
-                            options::OPT_s, options::OPT_t, options::OPT_r});
+                            options::OPT_s, options::OPT_t});
   ToolChain.AddFilePathLibArgs(Args, CmdArgs);
 
   bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
diff --git a/clang/lib/Driver/ToolChains/OHOS.cpp b/clang/lib/Driver/ToolChains/OHOS.cpp
index 1e50c9d71d59c..4ceafa9e71392 100644
--- a/clang/lib/Driver/ToolChains/OHOS.cpp
+++ b/clang/lib/Driver/ToolChains/OHOS.cpp
@@ -274,7 +274,7 @@ std::string OHOS::computeSysRoot() const {
   std::string SysRoot =
       !getDriver().SysRoot.empty()
           ? getDriver().SysRoot
-          : makePath({getDriver().getInstalledDir(), "..", "..", "sysroot"});
+          : makePath({getDriver().Dir, "..", "..", "sysroot"});
   if (!llvm::sys::fs::exists(SysRoot))
     return std::string();
 
diff --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp
index fd6aa4d7e6844..6da6728585df9 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()) {
@@ -192,8 +196,8 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
 
   Args.AddAllArgs(CmdArgs, options::OPT_L);
   ToolChain.AddFilePathLibArgs(Args, CmdArgs);
-  Args.addAllArgs(CmdArgs, {options::OPT_T_Group, options::OPT_s,
-                            options::OPT_t, options::OPT_r});
+  Args.addAllArgs(CmdArgs,
+                  {options::OPT_T_Group, options::OPT_s, options::OPT_t});
 
   if (D.isUsingLTO()) {
     assert(!Inputs.empty() && "Must have at least one input.");
diff --git a/clang/lib/Driver/ToolChains/PS4CPU.cpp b/clang/lib/Driver/ToolChains/PS4CPU.cpp
index 8ba8b80cfec78..7bf9aa79384c5 100644
--- a/clang/lib/Driver/ToolChains/PS4CPU.cpp
+++ b/clang/lib/Driver/ToolChains/PS4CPU.cpp
@@ -208,9 +208,8 @@ void tools::PScpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
       CmdArgs.push_back("--lto=full");
   }
 
-  Args.addAllArgs(CmdArgs,
-                  {options::OPT_L, options::OPT_T_Group, options::OPT_s,
-                   options::OPT_t, options::OPT_r});
+  Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
+                            options::OPT_s, options::OPT_t});
 
   if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
     CmdArgs.push_back("--no-demangle");
diff --git a/clang/lib/Driver/ToolChains/Solaris.cpp b/clang/lib/Driver/ToolChains/Solaris.cpp
index 200ac46aa5340..5d7f0ae2a392a 100644
--- a/clang/lib/Driver/ToolChains/Solaris.cpp
+++ b/clang/lib/Driver/ToolChains/Solaris.cpp
@@ -201,8 +201,7 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
 
   ToolChain.AddFilePathLibArgs(Args, CmdArgs);
 
-  Args.addAllArgs(CmdArgs,
-                  {options::OPT_L, options::OPT_T_Group, options::OPT_r});
+  Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group});
 
   bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
   AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp
index 57f4600727ec8..b8c2573d6265f 100644
--- a/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -198,7 +198,7 @@ WebAssembly::WebAssembly(const Driver &D, const llvm::Triple &Triple,
 
   assert(Triple.isArch32Bit() != Triple.isArch64Bit());
 
-  getProgramPaths().push_back(getDriver().getInstalledDir());
+  getProgramPaths().push_back(getDriver().Dir);
 
   auto SysRoot = getDriver().SysRoot;
   if (getTriple().getOS() == llvm::Triple::UnknownOS) {
diff --git a/clang/lib/Driver/ToolChains/ZOS.cpp b/clang/lib/Driver/ToolChains/ZOS.cpp
index 96dbf602e7c1f..d5fc7b8ef562a 100644
--- a/clang/lib/Driver/ToolChains/ZOS.cpp
+++ b/clang/lib/Driver/ToolChains/ZOS.cpp
@@ -325,8 +325,7 @@ void ZOS::AddClangCXXStdlibIncludeArgs(
   switch (GetCXXStdlibType(DriverArgs)) {
   case ToolChain::CST_Libcxx: {
     // /bin/../include/c++/v1
-    llvm::SmallString<128> InstallBin =
-        llvm::StringRef(getDriver().getInstalledDir());
+    llvm::SmallString<128> InstallBin(getDriver().Dir);
     llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1");
     TryAddIncludeFromPath(InstallBin, DriverArgs, CC1Args);
     break;
diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index 0c1dce7a29408..3124549504196 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -821,8 +821,8 @@ struct FormatToken {
 
   /// Returns whether the token is the left square bracket of a C++
   /// structured binding declaration.
-  bool isCppStructuredBinding(const FormatStyle &Style) const {
-    if (!Style.isCpp() || isNot(tok::l_square))
+  bool isCppStructuredBinding(bool IsCpp) const {
+    if (!IsCpp || isNot(tok::l_square))
       return false;
     const FormatToken *T = this;
     do {
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index a60d6ae197a24..04f0374b674e5 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -126,7 +126,7 @@ class AnnotatingParser {
                    const AdditionalKeywords &Keywords,
                    SmallVector &Scopes)
       : Style(Style), Line(Line), CurrentToken(Line.First), AutoFound(false),
-        Keywords(Keywords), Scopes(Scopes) {
+        IsCpp(Style.isCpp()), Keywords(Keywords), Scopes(Scopes) {
     Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/false));
     resetTokenMetadata();
   }
@@ -676,13 +676,13 @@ class AnnotatingParser {
     // In C++, this can happen either in array of templates (foo[10])
     // or when array is a nested template type (unique_ptr[]>).
     bool CppArrayTemplates =
-        Style.isCpp() && Parent && Parent->is(TT_TemplateCloser) &&
+        IsCpp && Parent && Parent->is(TT_TemplateCloser) &&
         (Contexts.back().CanBeExpression || Contexts.back().IsExpression ||
          Contexts.back().ContextType == Context::TemplateArgument);
 
     const bool IsInnerSquare = Contexts.back().InCpp11AttributeSpecifier;
     const bool IsCpp11AttributeSpecifier =
-        isCppAttribute(Style.isCpp(), *Left) || IsInnerSquare;
+        isCppAttribute(IsCpp, *Left) || IsInnerSquare;
 
     // Treat C# Attributes [STAThread] much like C++ attributes [[...]].
     bool IsCSharpAttributeSpecifier =
@@ -690,12 +690,11 @@ class AnnotatingParser {
         Contexts.back().InCSharpAttributeSpecifier;
 
     bool InsideInlineASM = Line.startsWith(tok::kw_asm);
-    bool IsCppStructuredBinding = Left->isCppStructuredBinding(Style);
+    bool IsCppStructuredBinding = Left->isCppStructuredBinding(IsCpp);
     bool StartsObjCMethodExpr =
         !IsCppStructuredBinding && !InsideInlineASM && !CppArrayTemplates &&
-        Style.isCpp() && !IsCpp11AttributeSpecifier &&
-        !IsCSharpAttributeSpecifier && Contexts.back().CanBeExpression &&
-        Left->isNot(TT_LambdaLSquare) &&
+        IsCpp && !IsCpp11AttributeSpecifier && !IsCSharpAttributeSpecifier &&
+        Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) &&
         !CurrentToken->isOneOf(tok::l_brace, tok::r_square) &&
         (!Parent ||
          Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren,
@@ -723,7 +722,7 @@ class AnnotatingParser {
                  Contexts.back().ContextKind == tok::l_brace &&
                  Parent->isOneOf(tok::l_brace, tok::comma)) {
         Left->setType(TT_JsComputedPropertyName);
-      } else if (Style.isCpp() && Contexts.back().ContextKind == tok::l_brace &&
+      } else if (IsCpp && Contexts.back().ContextKind == tok::l_brace &&
                  Parent && Parent->isOneOf(tok::l_brace, tok::comma)) {
         Left->setType(TT_DesignatedInitializerLSquare);
       } else if (IsCSharpAttributeSpecifier) {
@@ -1161,7 +1160,7 @@ class AnnotatingParser {
         if (Previous->is(TT_JsTypeOptionalQuestion))
           Previous = Previous->getPreviousNonComment();
         if ((CurrentToken->is(tok::colon) && !Style.isTableGen() &&
-             (!Contexts.back().ColonIsDictLiteral || !Style.isCpp())) ||
+             (!Contexts.back().ColonIsDictLiteral || !IsCpp)) ||
             Style.isProto()) {
           OpeningBrace.setType(TT_DictLiteral);
           if (Previous->Tok.getIdentifierInfo() ||
@@ -1230,7 +1229,7 @@ class AnnotatingParser {
   }
 
   bool consumeToken() {
-    if (Style.isCpp()) {
+    if (IsCpp) {
       const auto *Prev = CurrentToken->getPreviousNonComment();
       if (Prev && Prev->is(tok::r_square) && Prev->is(TT_AttributeSquare) &&
           CurrentToken->isOneOf(tok::kw_if, tok::kw_switch, tok::kw_case,
@@ -1424,7 +1423,7 @@ class AnnotatingParser {
         if (CurrentToken && CurrentToken->is(Keywords.kw_await))
           next();
       }
-      if (Style.isCpp() && CurrentToken && CurrentToken->is(tok::kw_co_await))
+      if (IsCpp && CurrentToken && CurrentToken->is(tok::kw_co_await))
         next();
       Contexts.back().ColonIsForRangeExpr = true;
       if (!CurrentToken || CurrentToken->isNot(tok::l_paren))
@@ -2590,7 +2589,7 @@ class AnnotatingParser {
   /// Determine whether '(' is starting a C++ cast.
   bool lParenStartsCppCast(const FormatToken &Tok) {
     // C-style casts are only used in C++.
-    if (!Style.isCpp())
+    if (!IsCpp)
       return false;
 
     FormatToken *LeftOfParens = Tok.getPreviousNonComment();
@@ -2611,10 +2610,8 @@ class AnnotatingParser {
   /// Determine whether ')' is ending a cast.
   bool rParenEndsCast(const FormatToken &Tok) {
     // C-style casts are only used in C++, C# and Java.
-    if (!Style.isCSharp() && !Style.isCpp() &&
-        Style.Language != FormatStyle::LK_Java) {
+    if (!Style.isCSharp() && !IsCpp && Style.Language != FormatStyle::LK_Java)
       return false;
-    }
 
     // Empty parens aren't casts and there are no casts at the end of the line.
     if (Tok.Previous == Tok.MatchingParen || !Tok.Next || !Tok.MatchingParen)
@@ -2691,7 +2688,7 @@ class AnnotatingParser {
     if (Tok.Next->isOneOf(tok::kw_noexcept, tok::kw_volatile, tok::kw_const,
                           tok::kw_requires, tok::kw_throw, tok::arrow,
                           Keywords.kw_override, Keywords.kw_final) ||
-        isCppAttribute(Style.isCpp(), *Tok.Next)) {
+        isCppAttribute(IsCpp, *Tok.Next)) {
       return false;
     }
 
@@ -3012,6 +3009,7 @@ class AnnotatingParser {
   AnnotatedLine &Line;
   FormatToken *CurrentToken;
   bool AutoFound;
+  bool IsCpp;
   const AdditionalKeywords &Keywords;
 
   SmallVector &Scopes;
@@ -3559,7 +3557,7 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) {
   ExpressionParser ExprParser(Style, Keywords, Line);
   ExprParser.parse();
 
-  if (Style.isCpp()) {
+  if (IsCpp) {
     auto *Tok = getFunctionName(Line);
     if (Tok && ((!Scopes.empty() && Scopes.back() == ST_Class) ||
                 Line.endsWith(TT_FunctionLBrace) || isCtorOrDtorName(Tok))) {
@@ -3766,7 +3764,6 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
   if (AlignArrayOfStructures)
     calculateArrayInitializerColumnList(Line);
 
-  const bool IsCpp = Style.isCpp();
   bool SeenName = false;
   bool LineIsFunctionDeclaration = false;
   FormatToken *ClosingParen = nullptr;
@@ -3779,7 +3776,7 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) const {
       AfterLastAttribute = Tok;
     if (const bool IsCtorOrDtor = Tok->is(TT_CtorDtorDeclName);
         IsCtorOrDtor ||
-        isFunctionDeclarationName(Style.isCpp(), *Tok, Line, ClosingParen)) {
+        isFunctionDeclarationName(IsCpp, *Tok, Line, ClosingParen)) {
       if (!IsCtorOrDtor)
         Tok->setFinalizedType(TT_FunctionDeclarationName);
       LineIsFunctionDeclaration = true;
@@ -4717,7 +4714,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
   if (Left.is(tok::star) && Right.is(tok::comment))
     return true;
 
-  if (Style.isCpp()) {
+  if (IsCpp) {
     if (Left.is(TT_OverloadedOperator) &&
         Right.isOneOf(TT_TemplateOpener, TT_TemplateCloser)) {
       return true;
@@ -5425,7 +5422,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
     if (!Keywords.isVerilogBegin(Right) && Keywords.isVerilogEndOfLabel(Left))
       return true;
   } else if (Style.BreakAdjacentStringLiterals &&
-             (Style.isCpp() || Style.isProto() ||
+             (IsCpp || Style.isProto() ||
               Style.Language == FormatStyle::LK_TableGen)) {
     if (Left.isStringLiteral() && Right.isStringLiteral())
       return true;
diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h
index 05a6daa87d803..a631e5f52bc60 100644
--- a/clang/lib/Format/TokenAnnotator.h
+++ b/clang/lib/Format/TokenAnnotator.h
@@ -212,7 +212,7 @@ class AnnotatedLine {
 class TokenAnnotator {
 public:
   TokenAnnotator(const FormatStyle &Style, const AdditionalKeywords &Keywords)
-      : Style(Style), Keywords(Keywords) {}
+      : Style(Style), IsCpp(Style.isCpp()), Keywords(Keywords) {}
 
   /// Adapts the indent levels of comment lines to the indent of the
   /// subsequent line.
@@ -260,6 +260,8 @@ class TokenAnnotator {
 
   const FormatStyle &Style;
 
+  bool IsCpp;
+
   const AdditionalKeywords &Keywords;
 
   SmallVector Scopes;
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 3a424bdcde793..2ce291da11b86 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -159,9 +159,9 @@ UnwrappedLineParser::UnwrappedLineParser(
     llvm::SpecificBumpPtrAllocator &Allocator,
     IdentifierTable &IdentTable)
     : Line(new UnwrappedLine), MustBreakBeforeNextToken(false),
-      CurrentLines(&Lines), Style(Style), Keywords(Keywords),
-      CommentPragmasRegex(Style.CommentPragmas), Tokens(nullptr),
-      Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1),
+      CurrentLines(&Lines), Style(Style), IsCpp(Style.isCpp()),
+      Keywords(Keywords), CommentPragmasRegex(Style.CommentPragmas),
+      Tokens(nullptr), Callback(Callback), AllTokens(Tokens), PPBranchLevel(-1),
       IncludeGuard(Style.IndentPPDirectives == FormatStyle::PPDIS_None
                        ? IG_Rejected
                        : IG_Inited),
@@ -572,8 +572,8 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
                                (Style.isJavaScript() &&
                                 NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,
                                                  Keywords.kw_as));
-          ProbablyBracedList = ProbablyBracedList ||
-                               (Style.isCpp() && NextTok->is(tok::l_paren));
+          ProbablyBracedList =
+              ProbablyBracedList || (IsCpp && NextTok->is(tok::l_paren));
 
           // If there is a comma, semicolon or right paren after the closing
           // brace, we assume this is a braced initializer list.
@@ -1428,7 +1428,7 @@ void UnwrappedLineParser::parseStructuralElement(
     return;
   }
 
-  if (Style.isCpp()) {
+  if (IsCpp) {
     while (FormatTok->is(tok::l_square) && handleCppAttributes()) {
     }
   } else if (Style.isVerilog()) {
@@ -1602,7 +1602,7 @@ void UnwrappedLineParser::parseStructuralElement(
       parseJavaScriptEs6ImportExport();
       return;
     }
-    if (Style.isCpp()) {
+    if (IsCpp) {
       nextToken();
       if (FormatTok->is(tok::kw_namespace)) {
         parseNamespace();
@@ -1646,12 +1646,11 @@ void UnwrappedLineParser::parseStructuralElement(
         addUnwrappedLine();
         return;
       }
-      if (Style.isCpp() && parseModuleImport())
+      if (IsCpp && parseModuleImport())
         return;
     }
-    if (Style.isCpp() &&
-        FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,
-                           Keywords.kw_slots, Keywords.kw_qslots)) {
+    if (IsCpp && FormatTok->isOneOf(Keywords.kw_signals, Keywords.kw_qsignals,
+                                    Keywords.kw_slots, Keywords.kw_qslots)) {
       nextToken();
       if (FormatTok->is(tok::colon)) {
         nextToken();
@@ -1659,11 +1658,11 @@ void UnwrappedLineParser::parseStructuralElement(
         return;
       }
     }
-    if (Style.isCpp() && FormatTok->is(TT_StatementMacro)) {
+    if (IsCpp && FormatTok->is(TT_StatementMacro)) {
       parseStatementMacro();
       return;
     }
-    if (Style.isCpp() && FormatTok->is(TT_NamespaceMacro)) {
+    if (IsCpp && FormatTok->is(TT_NamespaceMacro)) {
       parseNamespace();
       return;
     }
@@ -1759,7 +1758,7 @@ void UnwrappedLineParser::parseStructuralElement(
       }
       break;
     case tok::kw_requires: {
-      if (Style.isCpp()) {
+      if (IsCpp) {
         bool ParsedClause = parseRequires();
         if (ParsedClause)
           return;
@@ -1780,7 +1779,7 @@ void UnwrappedLineParser::parseStructuralElement(
       if (!parseEnum())
         break;
       // This only applies to C++ and Verilog.
-      if (!Style.isCpp() && !Style.isVerilog()) {
+      if (!IsCpp && !Style.isVerilog()) {
         addUnwrappedLine();
         return;
       }
@@ -1848,7 +1847,7 @@ void UnwrappedLineParser::parseStructuralElement(
       parseParens();
       // Break the unwrapped line if a K&R C function definition has a parameter
       // declaration.
-      if (OpeningBrace || !Style.isCpp() || !Previous || eof())
+      if (OpeningBrace || !IsCpp || !Previous || eof())
         break;
       if (isC78ParameterDecl(FormatTok,
                              Tokens->peekNextToken(/*SkipComment=*/true),
@@ -1977,13 +1976,13 @@ void UnwrappedLineParser::parseStructuralElement(
         }
       }
 
-      if (!Style.isCpp() && FormatTok->is(Keywords.kw_interface)) {
+      if (!IsCpp && FormatTok->is(Keywords.kw_interface)) {
         if (parseStructLike())
           return;
         break;
       }
 
-      if (Style.isCpp() && FormatTok->is(TT_StatementMacro)) {
+      if (IsCpp && FormatTok->is(TT_StatementMacro)) {
         parseStatementMacro();
         return;
       }
@@ -2211,7 +2210,7 @@ bool UnwrappedLineParser::tryToParsePropertyAccessor() {
 
 bool UnwrappedLineParser::tryToParseLambda() {
   assert(FormatTok->is(tok::l_square));
-  if (!Style.isCpp()) {
+  if (!IsCpp) {
     nextToken();
     return false;
   }
@@ -2340,7 +2339,7 @@ bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
                      !Previous->isOneOf(tok::kw_return, tok::kw_co_await,
                                         tok::kw_co_yield, tok::kw_co_return)) ||
                     Previous->closesScope())) ||
-      LeftSquare->isCppStructuredBinding(Style)) {
+      LeftSquare->isCppStructuredBinding(IsCpp)) {
     return false;
   }
   if (FormatTok->is(tok::l_square) || tok::isLiteral(FormatTok->Tok.getKind()))
@@ -3153,7 +3152,7 @@ void UnwrappedLineParser::parseForOrWhileLoop(bool HasParens) {
   // JS' for await ( ...
   if (Style.isJavaScript() && FormatTok->is(Keywords.kw_await))
     nextToken();
-  if (Style.isCpp() && FormatTok->is(tok::kw_co_await))
+  if (IsCpp && FormatTok->is(tok::kw_co_await))
     nextToken();
   if (HasParens && FormatTok->is(tok::l_paren)) {
     // The type is only set for Verilog basically because we were afraid to
@@ -3737,7 +3736,7 @@ bool UnwrappedLineParser::parseEnum() {
       nextToken();
       // If there are two identifiers in a row, this is likely an elaborate
       // return type. In Java, this can be "implements", etc.
-      if (Style.isCpp() && FormatTok->is(tok::identifier))
+      if (IsCpp && FormatTok->is(tok::identifier))
         return false;
     }
   }
diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h
index 1403533a2d0ef..619fbb217882b 100644
--- a/clang/lib/Format/UnwrappedLineParser.h
+++ b/clang/lib/Format/UnwrappedLineParser.h
@@ -324,6 +324,7 @@ class UnwrappedLineParser {
   llvm::BitVector DeclarationScopeStack;
 
   const FormatStyle &Style;
+  bool IsCpp;
   const AdditionalKeywords &Keywords;
 
   llvm::Regex CommentPragmasRegex;
diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp
index 60cb8f8e5be53..aa5a0ba3de263 100644
--- a/clang/lib/Frontend/CompilerInstance.cpp
+++ b/clang/lib/Frontend/CompilerInstance.cpp
@@ -1063,30 +1063,7 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
     }
   }
 
-  if (getDiagnosticOpts().ShowCarets) {
-    // We can have multiple diagnostics sharing one diagnostic client.
-    // Get the total number of warnings/errors from the client.
-    unsigned NumWarnings = getDiagnostics().getClient()->getNumWarnings();
-    unsigned NumErrors = getDiagnostics().getClient()->getNumErrors();
-
-    if (NumWarnings)
-      OS << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s");
-    if (NumWarnings && NumErrors)
-      OS << " and ";
-    if (NumErrors)
-      OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s");
-    if (NumWarnings || NumErrors) {
-      OS << " generated";
-      if (getLangOpts().CUDA) {
-        if (!getLangOpts().CUDAIsDevice) {
-          OS << " when compiling for host";
-        } else {
-          OS << " when compiling for " << getTargetOpts().CPU;
-        }
-      }
-      OS << ".\n";
-    }
-  }
+  printDiagnosticStats();
 
   if (getFrontendOpts().ShowStats) {
     if (hasFileManager()) {
@@ -1114,6 +1091,36 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
   return !getDiagnostics().getClient()->getNumErrors();
 }
 
+void CompilerInstance::printDiagnosticStats() {
+  if (!getDiagnosticOpts().ShowCarets)
+    return;
+
+  raw_ostream &OS = getVerboseOutputStream();
+
+  // We can have multiple diagnostics sharing one diagnostic client.
+  // Get the total number of warnings/errors from the client.
+  unsigned NumWarnings = getDiagnostics().getClient()->getNumWarnings();
+  unsigned NumErrors = getDiagnostics().getClient()->getNumErrors();
+
+  if (NumWarnings)
+    OS << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s");
+  if (NumWarnings && NumErrors)
+    OS << " and ";
+  if (NumErrors)
+    OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s");
+  if (NumWarnings || NumErrors) {
+    OS << " generated";
+    if (getLangOpts().CUDA) {
+      if (!getLangOpts().CUDAIsDevice) {
+        OS << " when compiling for host";
+      } else {
+        OS << " when compiling for " << getTargetOpts().CPU;
+      }
+    }
+    OS << ".\n";
+  }
+}
+
 void CompilerInstance::LoadRequestedPlugins() {
   // Load any requested plugins.
   for (const std::string &Path : getFrontendOpts().Plugins) {
@@ -1586,6 +1593,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;
@@ -1824,6 +1839,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 =
@@ -2001,12 +2023,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(
@@ -2141,18 +2174,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 9094849927e10..0c97b2fa9e185 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -191,6 +191,17 @@ CompilerInvocationBase::shallow_copy_assign(const CompilerInvocationBase &X) {
   return *this;
 }
 
+CompilerInvocation::CompilerInvocation(const CowCompilerInvocation &X)
+    : CompilerInvocationBase(EmptyConstructor{}) {
+  CompilerInvocationBase::deep_copy_assign(X);
+}
+
+CompilerInvocation &
+CompilerInvocation::operator=(const CowCompilerInvocation &X) {
+  CompilerInvocationBase::deep_copy_assign(X);
+  return *this;
+}
+
 namespace {
 template 
 T &ensureOwned(std::shared_ptr &Storage) {
@@ -1982,14 +1993,6 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
     Opts.LinkBitcodeFiles.push_back(F);
   }
 
-  if (Arg *A = Args.getLastArg(OPT_ftlsmodel_EQ)) {
-    if (T.isOSAIX()) {
-      StringRef Name = A->getValue();
-      if (Name == "local-dynamic")
-        Diags.Report(diag::err_aix_unsupported_tls_model) << Name;
-    }
-  }
-
   if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) {
     StringRef Val = A->getValue();
     Opts.FPDenormalMode = llvm::parseDenormalFPAttribute(Val);
diff --git a/clang/lib/Headers/emmintrin.h b/clang/lib/Headers/emmintrin.h
index 96e3ebdecbdf8..1d451b5f5b25d 100644
--- a/clang/lib/Headers/emmintrin.h
+++ b/clang/lib/Headers/emmintrin.h
@@ -2099,9 +2099,11 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_add_epi64(__m128i __a,
 }
 
 /// Adds, with saturation, the corresponding elements of two 128-bit
-///    signed [16 x i8] vectors, saving each sum in the corresponding element of
-///    a 128-bit result vector of [16 x i8]. Positive sums greater than 0x7F are
-///    saturated to 0x7F. Negative sums less than 0x80 are saturated to 0x80.
+///    signed [16 x i8] vectors, saving each sum in the corresponding element
+///    of a 128-bit result vector of [16 x i8].
+///
+///    Positive sums greater than 0x7F are saturated to 0x7F. Negative sums
+///    less than 0x80 are saturated to 0x80.
 ///
 /// \headerfile 
 ///
@@ -2119,10 +2121,11 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_adds_epi8(__m128i __a,
 }
 
 /// Adds, with saturation, the corresponding elements of two 128-bit
-///    signed [8 x i16] vectors, saving each sum in the corresponding element of
-///    a 128-bit result vector of [8 x i16]. Positive sums greater than 0x7FFF
-///    are saturated to 0x7FFF. Negative sums less than 0x8000 are saturated to
-///    0x8000.
+///    signed [8 x i16] vectors, saving each sum in the corresponding element
+///    of a 128-bit result vector of [8 x i16].
+///
+///    Positive sums greater than 0x7FFF are saturated to 0x7FFF. Negative sums
+///    less than 0x8000 are saturated to 0x8000.
 ///
 /// \headerfile 
 ///
@@ -2141,8 +2144,10 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_adds_epi16(__m128i __a,
 
 /// Adds, with saturation, the corresponding elements of two 128-bit
 ///    unsigned [16 x i8] vectors, saving each sum in the corresponding element
-///    of a 128-bit result vector of [16 x i8]. Positive sums greater than 0xFF
-///    are saturated to 0xFF. Negative sums are saturated to 0x00.
+///    of a 128-bit result vector of [16 x i8].
+///
+///    Positive sums greater than 0xFF are saturated to 0xFF. Negative sums are
+///    saturated to 0x00.
 ///
 /// \headerfile 
 ///
@@ -2161,8 +2166,10 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_adds_epu8(__m128i __a,
 
 /// Adds, with saturation, the corresponding elements of two 128-bit
 ///    unsigned [8 x i16] vectors, saving each sum in the corresponding element
-///    of a 128-bit result vector of [8 x i16]. Positive sums greater than
-///    0xFFFF are saturated to 0xFFFF. Negative sums are saturated to 0x0000.
+///    of a 128-bit result vector of [8 x i16].
+///
+///    Positive sums greater than 0xFFFF are saturated to 0xFFFF. Negative sums
+///    are saturated to 0x0000.
 ///
 /// \headerfile 
 ///
@@ -2518,10 +2525,12 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_sub_epi64(__m128i __a,
   return (__m128i)((__v2du)__a - (__v2du)__b);
 }
 
-/// Subtracts corresponding 8-bit signed integer values in the input and
-///    returns the differences in the corresponding bytes in the destination.
-///    Differences greater than 0x7F are saturated to 0x7F, and differences less
-///    than 0x80 are saturated to 0x80.
+/// Subtracts, with saturation, corresponding 8-bit signed integer values in
+///    the input and returns the differences in the corresponding bytes in the
+///    destination.
+///
+///    Differences greater than 0x7F are saturated to 0x7F, and differences
+///    less than 0x80 are saturated to 0x80.
 ///
 /// \headerfile 
 ///
@@ -2538,8 +2547,10 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_subs_epi8(__m128i __a,
   return (__m128i)__builtin_elementwise_sub_sat((__v16qs)__a, (__v16qs)__b);
 }
 
-/// Subtracts corresponding 16-bit signed integer values in the input and
-///    returns the differences in the corresponding bytes in the destination.
+/// Subtracts, with saturation, corresponding 16-bit signed integer values in
+///    the input and returns the differences in the corresponding bytes in the
+///    destination.
+///
 ///    Differences greater than 0x7FFF are saturated to 0x7FFF, and values less
 ///    than 0x8000 are saturated to 0x8000.
 ///
@@ -2558,9 +2569,11 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_subs_epi16(__m128i __a,
   return (__m128i)__builtin_elementwise_sub_sat((__v8hi)__a, (__v8hi)__b);
 }
 
-/// Subtracts corresponding 8-bit unsigned integer values in the input
-///    and returns the differences in the corresponding bytes in the
-///    destination. Differences less than 0x00 are saturated to 0x00.
+/// Subtracts, with saturation, corresponding 8-bit unsigned integer values in
+///    the input and returns the differences in the corresponding bytes in the
+///    destination.
+///
+///    Differences less than 0x00 are saturated to 0x00.
 ///
 /// \headerfile 
 ///
@@ -2577,9 +2590,11 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_subs_epu8(__m128i __a,
   return (__m128i)__builtin_elementwise_sub_sat((__v16qu)__a, (__v16qu)__b);
 }
 
-/// Subtracts corresponding 16-bit unsigned integer values in the input
-///    and returns the differences in the corresponding bytes in the
-///    destination. Differences less than 0x0000 are saturated to 0x0000.
+/// Subtracts, with saturation, corresponding 16-bit unsigned integer values in
+///    the input and returns the differences in the corresponding bytes in the
+///    destination.
+///
+///    Differences less than 0x0000 are saturated to 0x0000.
 ///
 /// \headerfile 
 ///
@@ -4050,26 +4065,22 @@ void _mm_mfence(void);
 } // extern "C"
 #endif
 
-/// Converts 16-bit signed integers from both 128-bit integer vector
-///    operands into 8-bit signed integers, and packs the results into the
-///    destination. Positive values greater than 0x7F are saturated to 0x7F.
-///    Negative values less than 0x80 are saturated to 0x80.
+/// Converts, with saturation, 16-bit signed integers from both 128-bit integer
+///    vector operands into 8-bit signed integers, and packs the results into
+///    the destination.
+///
+///    Positive values greater than 0x7F are saturated to 0x7F. Negative values
+///    less than 0x80 are saturated to 0x80.
 ///
 /// \headerfile 
 ///
 /// This intrinsic corresponds to the  VPACKSSWB / PACKSSWB  instruction.
 ///
 /// \param __a
-///   A 128-bit integer vector of [8 x i16]. Each 16-bit element is treated as
-///   a signed integer and is converted to a 8-bit signed integer with
-///   saturation. Values greater than 0x7F are saturated to 0x7F. Values less
-///   than 0x80 are saturated to 0x80. The converted [8 x i8] values are
+///   A 128-bit integer vector of [8 x i16]. The converted [8 x i8] values are
 ///   written to the lower 64 bits of the result.
 /// \param __b
-///   A 128-bit integer vector of [8 x i16]. Each 16-bit element is treated as
-///   a signed integer and is converted to a 8-bit signed integer with
-///   saturation. Values greater than 0x7F are saturated to 0x7F. Values less
-///   than 0x80 are saturated to 0x80. The converted [8 x i8] values are
+///   A 128-bit integer vector of [8 x i16]. The converted [8 x i8] values are
 ///   written to the higher 64 bits of the result.
 /// \returns A 128-bit vector of [16 x i8] containing the converted values.
 static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_packs_epi16(__m128i __a,
@@ -4077,26 +4088,22 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_packs_epi16(__m128i __a,
   return (__m128i)__builtin_ia32_packsswb128((__v8hi)__a, (__v8hi)__b);
 }
 
-/// Converts 32-bit signed integers from both 128-bit integer vector
-///    operands into 16-bit signed integers, and packs the results into the
-///    destination. Positive values greater than 0x7FFF are saturated to 0x7FFF.
-///    Negative values less than 0x8000 are saturated to 0x8000.
+/// Converts, with saturation, 32-bit signed integers from both 128-bit integer
+///    vector operands into 16-bit signed integers, and packs the results into
+///    the destination.
+///
+///    Positive values greater than 0x7FFF are saturated to 0x7FFF. Negative
+///    values less than 0x8000 are saturated to 0x8000.
 ///
 /// \headerfile 
 ///
 /// This intrinsic corresponds to the  VPACKSSDW / PACKSSDW  instruction.
 ///
 /// \param __a
-///    A 128-bit integer vector of [4 x i32]. Each 32-bit element is treated as
-///    a signed integer and is converted to a 16-bit signed integer with
-///    saturation. Values greater than 0x7FFF are saturated to 0x7FFF. Values
-///    less than 0x8000 are saturated to 0x8000. The converted [4 x i16] values
+///    A 128-bit integer vector of [4 x i32]. The converted [4 x i16] values
 ///    are written to the lower 64 bits of the result.
 /// \param __b
-///    A 128-bit integer vector of [4 x i32]. Each 32-bit element is treated as
-///    a signed integer and is converted to a 16-bit signed integer with
-///    saturation. Values greater than 0x7FFF are saturated to 0x7FFF. Values
-///    less than 0x8000 are saturated to 0x8000. The converted [4 x i16] values
+///    A 128-bit integer vector of [4 x i32]. The converted [4 x i16] values
 ///    are written to the higher 64 bits of the result.
 /// \returns A 128-bit vector of [8 x i16] containing the converted values.
 static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_packs_epi32(__m128i __a,
@@ -4104,26 +4111,22 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_packs_epi32(__m128i __a,
   return (__m128i)__builtin_ia32_packssdw128((__v4si)__a, (__v4si)__b);
 }
 
-/// Converts 16-bit signed integers from both 128-bit integer vector
-///    operands into 8-bit unsigned integers, and packs the results into the
-///    destination. Values greater than 0xFF are saturated to 0xFF. Values less
-///    than 0x00 are saturated to 0x00.
+/// Converts, with saturation, 16-bit signed integers from both 128-bit integer
+///    vector operands into 8-bit unsigned integers, and packs the results into
+///    the destination.
+///
+///    Values greater than 0xFF are saturated to 0xFF. Values less than 0x00
+///    are saturated to 0x00.
 ///
 /// \headerfile 
 ///
 /// This intrinsic corresponds to the  VPACKUSWB / PACKUSWB  instruction.
 ///
 /// \param __a
-///    A 128-bit integer vector of [8 x i16]. Each 16-bit element is treated as
-///    a signed integer and is converted to an 8-bit unsigned integer with
-///    saturation. Values greater than 0xFF are saturated to 0xFF. Values less
-///    than 0x00 are saturated to 0x00. The converted [8 x i8] values are
+///    A 128-bit integer vector of [8 x i16]. The converted [8 x i8] values are
 ///    written to the lower 64 bits of the result.
 /// \param __b
-///    A 128-bit integer vector of [8 x i16]. Each 16-bit element is treated as
-///    a signed integer and is converted to an 8-bit unsigned integer with
-///    saturation. Values greater than 0xFF are saturated to 0xFF. Values less
-///    than 0x00 are saturated to 0x00. The converted [8 x i8] values are
+///    A 128-bit integer vector of [8 x i16]. The converted [8 x i8] values are
 ///    written to the higher 64 bits of the result.
 /// \returns A 128-bit vector of [16 x i8] containing the converted values.
 static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_packus_epi16(__m128i __a,
diff --git a/clang/lib/Headers/fmaintrin.h b/clang/lib/Headers/fmaintrin.h
index ea832fac4f992..22d1a780bbfd4 100644
--- a/clang/lib/Headers/fmaintrin.h
+++ b/clang/lib/Headers/fmaintrin.h
@@ -60,7 +60,8 @@ _mm_fmadd_pd(__m128d __A, __m128d __B, __m128d __C)
 
 /// Computes a scalar multiply-add of the single-precision values in the
 ///    low 32 bits of 128-bit vectors of [4 x float].
-/// \code
+///
+/// \code{.operation}
 /// result[31:0] = (__A[31:0] * __B[31:0]) + __C[31:0]
 /// result[127:32] = __A[127:32]
 /// \endcode
@@ -88,7 +89,8 @@ _mm_fmadd_ss(__m128 __A, __m128 __B, __m128 __C)
 
 /// Computes a scalar multiply-add of the double-precision values in the
 ///    low 64 bits of 128-bit vectors of [2 x double].
-/// \code
+///
+/// \code{.operation}
 /// result[63:0] = (__A[63:0] * __B[63:0]) + __C[63:0]
 /// result[127:64] = __A[127:64]
 /// \endcode
@@ -156,7 +158,8 @@ _mm_fmsub_pd(__m128d __A, __m128d __B, __m128d __C)
 
 /// Computes a scalar multiply-subtract of the single-precision values in
 ///    the low 32 bits of 128-bit vectors of [4 x float].
-/// \code
+///
+/// \code{.operation}
 /// result[31:0] = (__A[31:0] * __B[31:0]) - __C[31:0]
 /// result[127:32] = __A[127:32]
 /// \endcode
@@ -184,7 +187,8 @@ _mm_fmsub_ss(__m128 __A, __m128 __B, __m128 __C)
 
 /// Computes a scalar multiply-subtract of the double-precision values in
 ///    the low 64 bits of 128-bit vectors of [2 x double].
-/// \code
+///
+/// \code{.operation}
 /// result[63:0] = (__A[63:0] * __B[63:0]) - __C[63:0]
 /// result[127:64] = __A[127:64]
 /// \endcode
@@ -252,7 +256,8 @@ _mm_fnmadd_pd(__m128d __A, __m128d __B, __m128d __C)
 
 /// Computes a scalar negated multiply-add of the single-precision values in
 ///    the low 32 bits of 128-bit vectors of [4 x float].
-/// \code
+///
+/// \code{.operation}
 /// result[31:0] = -(__A[31:0] * __B[31:0]) + __C[31:0]
 /// result[127:32] = __A[127:32]
 /// \endcode
@@ -280,7 +285,8 @@ _mm_fnmadd_ss(__m128 __A, __m128 __B, __m128 __C)
 
 /// Computes a scalar negated multiply-add of the double-precision values
 ///    in the low 64 bits of 128-bit vectors of [2 x double].
-/// \code
+///
+/// \code{.operation}
 /// result[63:0] = -(__A[63:0] * __B[63:0]) + __C[63:0]
 /// result[127:64] = __A[127:64]
 /// \endcode
@@ -348,7 +354,8 @@ _mm_fnmsub_pd(__m128d __A, __m128d __B, __m128d __C)
 
 /// Computes a scalar negated multiply-subtract of the single-precision
 ///    values in the low 32 bits of 128-bit vectors of [4 x float].
-/// \code
+///
+/// \code{.operation}
 /// result[31:0] = -(__A[31:0] * __B[31:0]) - __C[31:0]
 /// result[127:32] = __A[127:32]
 /// \endcode
@@ -376,7 +383,8 @@ _mm_fnmsub_ss(__m128 __A, __m128 __B, __m128 __C)
 
 /// Computes a scalar negated multiply-subtract of the double-precision
 ///    values in the low 64 bits of 128-bit vectors of [2 x double].
-/// \code
+///
+/// \code{.operation}
 /// result[63:0] = -(__A[63:0] * __B[63:0]) - __C[63:0]
 /// result[127:64] = __A[127:64]
 /// \endcode
@@ -404,7 +412,8 @@ _mm_fnmsub_sd(__m128d __A, __m128d __B, __m128d __C)
 
 /// Computes a multiply with alternating add/subtract of 128-bit vectors of
 ///    [4 x float].
-/// \code
+///
+/// \code{.operation}
 /// result[31:0]  = (__A[31:0] * __B[31:0]) - __C[31:0]
 /// result[63:32] = (__A[63:32] * __B[63:32]) + __C[63:32]
 /// result[95:64] = (__A[95:64] * __B[95:64]) - __C[95:64]
@@ -430,7 +439,8 @@ _mm_fmaddsub_ps(__m128 __A, __m128 __B, __m128 __C)
 
 /// Computes a multiply with alternating add/subtract of 128-bit vectors of
 ///    [2 x double].
-/// \code
+///
+/// \code{.operation}
 /// result[63:0]  = (__A[63:0] * __B[63:0]) - __C[63:0]
 /// result[127:64] = (__A[127:64] * __B[127:64]) + __C[127:64]
 /// \endcode
@@ -454,7 +464,8 @@ _mm_fmaddsub_pd(__m128d __A, __m128d __B, __m128d __C)
 
 /// Computes a multiply with alternating add/subtract of 128-bit vectors of
 ///    [4 x float].
-/// \code
+///
+/// \code{.operation}
 /// result[31:0]  = (__A[31:0] * __B[31:0]) + __C[31:0]
 /// result[63:32] = (__A[63:32] * __B[63:32]) - __C[63:32]
 /// result[95:64] = (__A[95:64] * __B[95:64]) + __C[95:64]
@@ -480,7 +491,8 @@ _mm_fmsubadd_ps(__m128 __A, __m128 __B, __m128 __C)
 
 /// Computes a multiply with alternating add/subtract of 128-bit vectors of
 ///    [2 x double].
-/// \code
+///
+/// \code{.operation}
 /// result[63:0]  = (__A[63:0] * __B[63:0]) + __C[63:0]
 /// result[127:64] = (__A[127:64] * __B[127:64]) - __C[127:64]
 /// \endcode
@@ -664,7 +676,8 @@ _mm256_fnmsub_pd(__m256d __A, __m256d __B, __m256d __C)
 
 /// Computes a multiply with alternating add/subtract of 256-bit vectors of
 ///    [8 x float].
-/// \code
+///
+/// \code{.operation}
 /// result[31:0] = (__A[31:0] * __B[31:0]) - __C[31:0]
 /// result[63:32] = (__A[63:32] * __B[63:32]) + __C[63:32]
 /// result[95:64] = (__A[95:64] * __B[95:64]) - __C[95:64]
@@ -694,7 +707,8 @@ _mm256_fmaddsub_ps(__m256 __A, __m256 __B, __m256 __C)
 
 /// Computes a multiply with alternating add/subtract of 256-bit vectors of
 ///    [4 x double].
-/// \code
+///
+/// \code{.operation}
 /// result[63:0] = (__A[63:0] * __B[63:0]) - __C[63:0]
 /// result[127:64] = (__A[127:64] * __B[127:64]) + __C[127:64]
 /// result[191:128] = (__A[191:128] * __B[191:128]) - __C[191:128]
@@ -720,7 +734,8 @@ _mm256_fmaddsub_pd(__m256d __A, __m256d __B, __m256d __C)
 
 /// Computes a vector multiply with alternating add/subtract of 256-bit
 ///    vectors of [8 x float].
-/// \code
+///
+/// \code{.operation}
 /// result[31:0] = (__A[31:0] * __B[31:0]) + __C[31:0]
 /// result[63:32] = (__A[63:32] * __B[63:32]) - __C[63:32]
 /// result[95:64] = (__A[95:64] * __B[95:64]) + __C[95:64]
@@ -750,7 +765,8 @@ _mm256_fmsubadd_ps(__m256 __A, __m256 __B, __m256 __C)
 
 /// Computes a vector multiply with alternating add/subtract of 256-bit
 ///    vectors of [4 x double].
-/// \code
+///
+/// \code{.operation}
 /// result[63:0] = (__A[63:0] * __B[63:0]) + __C[63:0]
 /// result[127:64] = (__A[127:64] * __B[127:64]) - __C[127:64]
 /// result[191:128] = (__A[191:128] * __B[191:128]) + __C[191:128]
diff --git a/clang/lib/Headers/hlsl/hlsl_basic_types.h b/clang/lib/Headers/hlsl/hlsl_basic_types.h
index 3d0d296aadca3..da6903df65ffe 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 08e5d981a4a4c..45f8544392584 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
 //===----------------------------------------------------------------------===//
@@ -317,6 +493,74 @@ double3 floor(double3);
 _HLSL_BUILTIN_ALIAS(__builtin_elementwise_floor)
 double4 floor(double4);
 
+//===----------------------------------------------------------------------===//
+// frac builtins
+//===----------------------------------------------------------------------===//
+
+/// \fn T frac(T x)
+/// \brief Returns the fractional (or decimal) part of x. \a x parameter.
+/// \param x The specified input value.
+///
+/// If \a the return value is greater than or equal to 0 and less than 1.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frac)
+half frac(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frac)
+half2 frac(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frac)
+half3 frac(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frac)
+half4 frac(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frac)
+float frac(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frac)
+float2 frac(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frac)
+float3 frac(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_frac)
+float4 frac(float4);
+
+//===----------------------------------------------------------------------===//
+// lerp builtins
+//===----------------------------------------------------------------------===//
+
+/// \fn T lerp(T x, T y, T s)
+/// \brief Returns the linear interpolation of x to y by s.
+/// \param x [in] The first-floating point value.
+/// \param y [in] The second-floating point value.
+/// \param s [in] A value that linearly interpolates between the x parameter and
+/// the y parameter.
+///
+/// Linear interpolation is based on the following formula: x*(1-s) + y*s which
+/// can equivalently be written as x + s(y-x).
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_lerp)
+half lerp(half, half, half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_lerp)
+half2 lerp(half2, half2, half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_lerp)
+half3 lerp(half3, half3, half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_lerp)
+half4 lerp(half4, half4, half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_lerp)
+float lerp(float, float, float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_lerp)
+float2 lerp(float2, float2, float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_lerp)
+float3 lerp(float3, float3, float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_lerp)
+float4 lerp(float4, float4, float4);
+
 //===----------------------------------------------------------------------===//
 // log builtins
 //===----------------------------------------------------------------------===//
@@ -443,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
 //===----------------------------------------------------------------------===//
@@ -763,6 +1112,81 @@ 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
+//===----------------------------------------------------------------------===//
+
+/// \fn T round(T x)
+/// \brief Rounds the specified value \a x to the nearest integer.
+/// \param x The specified input value.
+///
+/// The return value is the \a x parameter, rounded to the nearest integer
+/// within a floating-point type. Halfway cases are
+/// rounded to the nearest even value.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round)
+half round(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round)
+half2 round(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round)
+half3 round(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round)
+half4 round(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round)
+float round(float);
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round)
+float2 round(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round)
+float3 round(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round)
+float4 round(float4);
+
 //===----------------------------------------------------------------------===//
 // sin builtins
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/Headers/larchintrin.h b/clang/lib/Headers/larchintrin.h
index a613e5ca0e5ec..f4218295919a0 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/mmintrin.h b/clang/lib/Headers/mmintrin.h
index 08849f01071ae..962d24738e7aa 100644
--- a/clang/lib/Headers/mmintrin.h
+++ b/clang/lib/Headers/mmintrin.h
@@ -105,28 +105,23 @@ _mm_cvtm64_si64(__m64 __m)
     return (long long)__m;
 }
 
-/// Converts 16-bit signed integers from both 64-bit integer vector
-///    parameters of [4 x i16] into 8-bit signed integer values, and constructs
-///    a 64-bit integer vector of [8 x i8] as the result. Positive values
-///    greater than 0x7F are saturated to 0x7F. Negative values less than 0x80
-///    are saturated to 0x80.
+/// Converts, with saturation, 16-bit signed integers from both 64-bit integer
+///    vector parameters of [4 x i16] into 8-bit signed integer values, and
+///    constructs a 64-bit integer vector of [8 x i8] as the result.
+///
+///    Positive values greater than 0x7F are saturated to 0x7F. Negative values
+///    less than 0x80 are saturated to 0x80.
 ///
 /// \headerfile 
 ///
 /// This intrinsic corresponds to the  PACKSSWB  instruction.
 ///
 /// \param __m1
-///    A 64-bit integer vector of [4 x i16]. Each 16-bit element is treated as a
-///    16-bit signed integer and is converted to an 8-bit signed integer with
-///    saturation. Positive values greater than 0x7F are saturated to 0x7F.
-///    Negative values less than 0x80 are saturated to 0x80. The converted
-///    [4 x i8] values are written to the lower 32 bits of the result.
+///    A 64-bit integer vector of [4 x i16]. The converted [4 x i8] values are
+///    written to the lower 32 bits of the result.
 /// \param __m2
-///    A 64-bit integer vector of [4 x i16]. Each 16-bit element is treated as a
-///    16-bit signed integer and is converted to an 8-bit signed integer with
-///    saturation. Positive values greater than 0x7F are saturated to 0x7F.
-///    Negative values less than 0x80 are saturated to 0x80. The converted
-///    [4 x i8] values are written to the upper 32 bits of the result.
+///    A 64-bit integer vector of [4 x i16]. The converted [4 x i8] values are
+///    written to the upper 32 bits of the result.
 /// \returns A 64-bit integer vector of [8 x i8] containing the converted
 ///    values.
 static __inline__ __m64 __DEFAULT_FN_ATTRS
@@ -135,28 +130,23 @@ _mm_packs_pi16(__m64 __m1, __m64 __m2)
     return (__m64)__builtin_ia32_packsswb((__v4hi)__m1, (__v4hi)__m2);
 }
 
-/// Converts 32-bit signed integers from both 64-bit integer vector
-///    parameters of [2 x i32] into 16-bit signed integer values, and constructs
-///    a 64-bit integer vector of [4 x i16] as the result. Positive values
-///    greater than 0x7FFF are saturated to 0x7FFF. Negative values less than
-///    0x8000 are saturated to 0x8000.
+/// Converts, with saturation, 32-bit signed integers from both 64-bit integer
+///    vector parameters of [2 x i32] into 16-bit signed integer values, and
+///    constructs a 64-bit integer vector of [4 x i16] as the result.
+///
+///    Positive values greater than 0x7FFF are saturated to 0x7FFF. Negative
+///    values less than 0x8000 are saturated to 0x8000.
 ///
 /// \headerfile 
 ///
 /// This intrinsic corresponds to the  PACKSSDW  instruction.
 ///
 /// \param __m1
-///    A 64-bit integer vector of [2 x i32]. Each 32-bit element is treated as a
-///    32-bit signed integer and is converted to a 16-bit signed integer with
-///    saturation. Positive values greater than 0x7FFF are saturated to 0x7FFF.
-///    Negative values less than 0x8000 are saturated to 0x8000. The converted
-///    [2 x i16] values are written to the lower 32 bits of the result.
+///    A 64-bit integer vector of [2 x i32]. The converted [2 x i16] values are
+///    written to the lower 32 bits of the result.
 /// \param __m2
-///    A 64-bit integer vector of [2 x i32]. Each 32-bit element is treated as a
-///    32-bit signed integer and is converted to a 16-bit signed integer with
-///    saturation. Positive values greater than 0x7FFF are saturated to 0x7FFF.
-///    Negative values less than 0x8000 are saturated to 0x8000. The converted
-///    [2 x i16] values are written to the upper 32 bits of the result.
+///    A 64-bit integer vector of [2 x i32]. The converted [2 x i16] values are
+///    written to the upper 32 bits of the result.
 /// \returns A 64-bit integer vector of [4 x i16] containing the converted
 ///    values.
 static __inline__ __m64 __DEFAULT_FN_ATTRS
@@ -165,28 +155,23 @@ _mm_packs_pi32(__m64 __m1, __m64 __m2)
     return (__m64)__builtin_ia32_packssdw((__v2si)__m1, (__v2si)__m2);
 }
 
-/// Converts 16-bit signed integers from both 64-bit integer vector
-///    parameters of [4 x i16] into 8-bit unsigned integer values, and
-///    constructs a 64-bit integer vector of [8 x i8] as the result. Values
-///    greater than 0xFF are saturated to 0xFF. Values less than 0 are saturated
-///    to 0.
+/// Converts, with saturation, 16-bit signed integers from both 64-bit integer
+///    vector parameters of [4 x i16] into 8-bit unsigned integer values, and
+///    constructs a 64-bit integer vector of [8 x i8] as the result.
+///
+///    Values greater than 0xFF are saturated to 0xFF. Values less than 0 are
+///    saturated to 0.
 ///
 /// \headerfile 
 ///
 /// This intrinsic corresponds to the  PACKUSWB  instruction.
 ///
 /// \param __m1
-///    A 64-bit integer vector of [4 x i16]. Each 16-bit element is treated as a
-///    16-bit signed integer and is converted to an 8-bit unsigned integer with
-///    saturation. Values greater than 0xFF are saturated to 0xFF. Values less
-///    than 0 are saturated to 0. The converted [4 x i8] values are written to
-///    the lower 32 bits of the result.
+///    A 64-bit integer vector of [4 x i16]. The converted [4 x i8] values are
+///    written to the lower 32 bits of the result.
 /// \param __m2
-///    A 64-bit integer vector of [4 x i16]. Each 16-bit element is treated as a
-///    16-bit signed integer and is converted to an 8-bit unsigned integer with
-///    saturation. Values greater than 0xFF are saturated to 0xFF. Values less
-///    than 0 are saturated to 0. The converted [4 x i8] values are written to
-///    the upper 32 bits of the result.
+///    A 64-bit integer vector of [4 x i16]. The converted [4 x i8] values are
+///    written to the upper 32 bits of the result.
 /// \returns A 64-bit integer vector of [8 x i8] containing the converted
 ///    values.
 static __inline__ __m64 __DEFAULT_FN_ATTRS
@@ -400,11 +385,13 @@ _mm_add_pi32(__m64 __m1, __m64 __m2)
     return (__m64)__builtin_ia32_paddd((__v2si)__m1, (__v2si)__m2);
 }
 
-/// Adds each 8-bit signed integer element of the first 64-bit integer
-///    vector of [8 x i8] to the corresponding 8-bit signed integer element of
-///    the second 64-bit integer vector of [8 x i8]. Positive sums greater than
-///    0x7F are saturated to 0x7F. Negative sums less than 0x80 are saturated to
-///    0x80. The results are packed into a 64-bit integer vector of [8 x i8].
+/// Adds, with saturation, each 8-bit signed integer element of the first
+///    64-bit integer vector of [8 x i8] to the corresponding 8-bit signed
+///    integer element of the second 64-bit integer vector of [8 x i8].
+///
+///    Positive sums greater than 0x7F are saturated to 0x7F. Negative sums
+///    less than 0x80 are saturated to 0x80. The results are packed into a
+///    64-bit integer vector of [8 x i8].
 ///
 /// \headerfile 
 ///
@@ -422,12 +409,13 @@ _mm_adds_pi8(__m64 __m1, __m64 __m2)
     return (__m64)__builtin_ia32_paddsb((__v8qi)__m1, (__v8qi)__m2);
 }
 
-/// Adds each 16-bit signed integer element of the first 64-bit integer
-///    vector of [4 x i16] to the corresponding 16-bit signed integer element of
-///    the second 64-bit integer vector of [4 x i16]. Positive sums greater than
-///    0x7FFF are saturated to 0x7FFF. Negative sums less than 0x8000 are
-///    saturated to 0x8000. The results are packed into a 64-bit integer vector
-///    of [4 x i16].
+/// Adds, with saturation, each 16-bit signed integer element of the first
+///    64-bit integer vector of [4 x i16] to the corresponding 16-bit signed
+///    integer element of the second 64-bit integer vector of [4 x i16].
+///
+///    Positive sums greater than 0x7FFF are saturated to 0x7FFF. Negative sums
+///    less than 0x8000 are saturated to 0x8000. The results are packed into a
+///    64-bit integer vector of [4 x i16].
 ///
 /// \headerfile 
 ///
@@ -445,11 +433,12 @@ _mm_adds_pi16(__m64 __m1, __m64 __m2)
     return (__m64)__builtin_ia32_paddsw((__v4hi)__m1, (__v4hi)__m2);
 }
 
-/// Adds each 8-bit unsigned integer element of the first 64-bit integer
-///    vector of [8 x i8] to the corresponding 8-bit unsigned integer element of
-///    the second 64-bit integer vector of [8 x i8]. Sums greater than 0xFF are
-///    saturated to 0xFF. The results are packed into a 64-bit integer vector of
-///    [8 x i8].
+/// Adds, with saturation, each 8-bit unsigned integer element of the first
+///    64-bit integer vector of [8 x i8] to the corresponding 8-bit unsigned
+///    integer element of the second 64-bit integer vector of [8 x i8].
+///
+///    Sums greater than 0xFF are saturated to 0xFF. The results are packed
+///    into a 64-bit integer vector of [8 x i8].
 ///
 /// \headerfile 
 ///
@@ -467,11 +456,12 @@ _mm_adds_pu8(__m64 __m1, __m64 __m2)
     return (__m64)__builtin_ia32_paddusb((__v8qi)__m1, (__v8qi)__m2);
 }
 
-/// Adds each 16-bit unsigned integer element of the first 64-bit integer
-///    vector of [4 x i16] to the corresponding 16-bit unsigned integer element
-///    of the second 64-bit integer vector of [4 x i16]. Sums greater than
-///    0xFFFF are saturated to 0xFFFF. The results are packed into a 64-bit
-///    integer vector of [4 x i16].
+/// Adds, with saturation, each 16-bit unsigned integer element of the first
+///    64-bit integer vector of [4 x i16] to the corresponding 16-bit unsigned
+///    integer element of the second 64-bit integer vector of [4 x i16].
+///
+///    Sums greater than 0xFFFF are saturated to 0xFFFF. The results are packed
+///    into a 64-bit integer vector of [4 x i16].
 ///
 /// \headerfile 
 ///
@@ -552,12 +542,13 @@ _mm_sub_pi32(__m64 __m1, __m64 __m2)
     return (__m64)__builtin_ia32_psubd((__v2si)__m1, (__v2si)__m2);
 }
 
-/// Subtracts each 8-bit signed integer element of the second 64-bit
-///    integer vector of [8 x i8] from the corresponding 8-bit signed integer
-///    element of the first 64-bit integer vector of [8 x i8]. Positive results
-///    greater than 0x7F are saturated to 0x7F. Negative results less than 0x80
-///    are saturated to 0x80. The results are packed into a 64-bit integer
-///    vector of [8 x i8].
+/// Subtracts, with saturation, each 8-bit signed integer element of the second
+///    64-bit integer vector of [8 x i8] from the corresponding 8-bit signed
+///    integer element of the first 64-bit integer vector of [8 x i8].
+///
+///    Positive results greater than 0x7F are saturated to 0x7F. Negative
+///    results less than 0x80 are saturated to 0x80. The results are packed
+///    into a 64-bit integer vector of [8 x i8].
 ///
 /// \headerfile 
 ///
@@ -575,12 +566,13 @@ _mm_subs_pi8(__m64 __m1, __m64 __m2)
     return (__m64)__builtin_ia32_psubsb((__v8qi)__m1, (__v8qi)__m2);
 }
 
-/// Subtracts each 16-bit signed integer element of the second 64-bit
-///    integer vector of [4 x i16] from the corresponding 16-bit signed integer
-///    element of the first 64-bit integer vector of [4 x i16]. Positive results
-///    greater than 0x7FFF are saturated to 0x7FFF. Negative results less than
-///    0x8000 are saturated to 0x8000. The results are packed into a 64-bit
-///    integer vector of [4 x i16].
+/// Subtracts, with saturation, each 16-bit signed integer element of the
+///    second 64-bit integer vector of [4 x i16] from the corresponding 16-bit
+///    signed integer element of the first 64-bit integer vector of [4 x i16].
+///
+///    Positive results greater than 0x7FFF are saturated to 0x7FFF. Negative
+///    results less than 0x8000 are saturated to 0x8000. The results are packed
+///    into a 64-bit integer vector of [4 x i16].
 ///
 /// \headerfile 
 ///
diff --git a/clang/lib/Headers/prfchwintrin.h b/clang/lib/Headers/prfchwintrin.h
index d2f91aa0123e0..8a13784543c5f 100644
--- a/clang/lib/Headers/prfchwintrin.h
+++ b/clang/lib/Headers/prfchwintrin.h
@@ -15,9 +15,10 @@
 #define __PRFCHWINTRIN_H
 
 /// Loads a memory sequence containing the specified memory address into
-///    all data cache levels. The cache-coherency state is set to exclusive.
-///    Data can be read from and written to the cache line without additional
-///    delay.
+///    all data cache levels.
+///
+///    The cache-coherency state is set to exclusive. Data can be read from
+///    and written to the cache line without additional delay.
 ///
 /// \headerfile 
 ///
@@ -32,10 +33,11 @@ _m_prefetch(void *__P)
 }
 
 /// Loads a memory sequence containing the specified memory address into
-///    the L1 data cache and sets the cache-coherency to modified. This
-///    provides a hint to the processor that the cache line will be modified.
-///    It is intended for use when the cache line will be written to shortly
-///    after the prefetch is performed.
+///    the L1 data cache and sets the cache-coherency state to modified.
+///
+///    This provides a hint to the processor that the cache line will be
+///    modified. It is intended for use when the cache line will be written to
+///    shortly after the prefetch is performed.
 ///
 ///    Note that the effect of this intrinsic is dependent on the processor
 ///    implementation.
diff --git a/clang/lib/Headers/smmintrin.h b/clang/lib/Headers/smmintrin.h
index 005d7db9c3c30..c52ffb77e33d5 100644
--- a/clang/lib/Headers/smmintrin.h
+++ b/clang/lib/Headers/smmintrin.h
@@ -1431,8 +1431,10 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_cvtepu32_epi64(__m128i __V) {
 }
 
 /* SSE4 Pack with Unsigned Saturation.  */
-/// Converts 32-bit signed integers from both 128-bit integer vector
-///    operands into 16-bit unsigned integers, and returns the packed result.
+/// Converts, with saturation, 32-bit signed integers from both 128-bit integer
+///    vector operands into 16-bit unsigned integers, and returns the packed
+///    result.
+///
 ///    Values greater than 0xFFFF are saturated to 0xFFFF. Values less than
 ///    0x0000 are saturated to 0x0000.
 ///
@@ -1441,17 +1443,11 @@ static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_cvtepu32_epi64(__m128i __V) {
 /// This intrinsic corresponds to the  VPACKUSDW / PACKUSDW  instruction.
 ///
 /// \param __V1
-///    A 128-bit vector of [4 x i32]. Each 32-bit element is treated as a
-///    signed integer and is converted to a 16-bit unsigned integer with
-///    saturation. Values greater than 0xFFFF are saturated to 0xFFFF. Values
-///    less than 0x0000 are saturated to 0x0000. The converted [4 x i16] values
-///    are written to the lower 64 bits of the result.
+///    A 128-bit vector of [4 x i32]. The converted [4 x i16] values are
+///    written to the lower 64 bits of the result.
 /// \param __V2
-///    A 128-bit vector of [4 x i32]. Each 32-bit element is treated as a
-///    signed integer and is converted to a 16-bit unsigned integer with
-///    saturation. Values greater than 0xFFFF are saturated to 0xFFFF. Values
-///    less than 0x0000 are saturated to 0x0000. The converted [4 x i16] values
-///    are written to the higher 64 bits of the result.
+///    A 128-bit vector of [4 x i32]. The converted [4 x i16] values are
+///    written to the higher 64 bits of the result.
 /// \returns A 128-bit vector of [8 x i16] containing the converted values.
 static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_packus_epi32(__m128i __V1,
                                                               __m128i __V2) {
diff --git a/clang/lib/Headers/tmmintrin.h b/clang/lib/Headers/tmmintrin.h
index 7d8dc46c57bfe..bf8327b692d1c 100644
--- a/clang/lib/Headers/tmmintrin.h
+++ b/clang/lib/Headers/tmmintrin.h
@@ -271,10 +271,11 @@ _mm_hadd_pi32(__m64 __a, __m64 __b)
     return (__m64)__builtin_ia32_phaddd((__v2si)__a, (__v2si)__b);
 }
 
-/// Horizontally adds the adjacent pairs of values contained in 2 packed
-///    128-bit vectors of [8 x i16]. Positive sums greater than 0x7FFF are
-///    saturated to 0x7FFF. Negative sums less than 0x8000 are saturated to
-///    0x8000.
+/// Horizontally adds, with saturation, the adjacent pairs of values contained
+///    in two packed 128-bit vectors of [8 x i16].
+///
+///    Positive sums greater than 0x7FFF are saturated to 0x7FFF. Negative sums
+///    less than 0x8000 are saturated to 0x8000.
 ///
 /// \headerfile 
 ///
@@ -296,10 +297,11 @@ _mm_hadds_epi16(__m128i __a, __m128i __b)
     return (__m128i)__builtin_ia32_phaddsw128((__v8hi)__a, (__v8hi)__b);
 }
 
-/// Horizontally adds the adjacent pairs of values contained in 2 packed
-///    64-bit vectors of [4 x i16]. Positive sums greater than 0x7FFF are
-///    saturated to 0x7FFF. Negative sums less than 0x8000 are saturated to
-///    0x8000.
+/// Horizontally adds, with saturation, the adjacent pairs of values contained
+///    in two packed 64-bit vectors of [4 x i16].
+///
+///    Positive sums greater than 0x7FFF are saturated to 0x7FFF. Negative sums
+///    less than 0x8000 are saturated to 0x8000.
 ///
 /// \headerfile 
 ///
@@ -413,10 +415,11 @@ _mm_hsub_pi32(__m64 __a, __m64 __b)
     return (__m64)__builtin_ia32_phsubd((__v2si)__a, (__v2si)__b);
 }
 
-/// Horizontally subtracts the adjacent pairs of values contained in 2
-///    packed 128-bit vectors of [8 x i16]. Positive differences greater than
-///    0x7FFF are saturated to 0x7FFF. Negative differences less than 0x8000 are
-///    saturated to 0x8000.
+/// Horizontally subtracts, with saturation, the adjacent pairs of values
+///    contained in two packed 128-bit vectors of [8 x i16].
+///
+///    Positive differences greater than 0x7FFF are saturated to 0x7FFF.
+///    Negative differences less than 0x8000 are saturated to 0x8000.
 ///
 /// \headerfile 
 ///
@@ -438,10 +441,11 @@ _mm_hsubs_epi16(__m128i __a, __m128i __b)
     return (__m128i)__builtin_ia32_phsubsw128((__v8hi)__a, (__v8hi)__b);
 }
 
-/// Horizontally subtracts the adjacent pairs of values contained in 2
-///    packed 64-bit vectors of [4 x i16]. Positive differences greater than
-///    0x7FFF are saturated to 0x7FFF. Negative differences less than 0x8000 are
-///    saturated to 0x8000.
+/// Horizontally subtracts, with saturation, the adjacent pairs of values
+///    contained in two packed 64-bit vectors of [4 x i16].
+///
+///    Positive differences greater than 0x7FFF are saturated to 0x7FFF.
+///    Negative differences less than 0x8000 are saturated to 0x8000.
 ///
 /// \headerfile 
 ///
diff --git a/clang/lib/Index/IndexSymbol.cpp b/clang/lib/Index/IndexSymbol.cpp
index 0f79694d1faac..419ff79a5cbab 100644
--- a/clang/lib/Index/IndexSymbol.cpp
+++ b/clang/lib/Index/IndexSymbol.cpp
@@ -552,8 +552,7 @@ StringRef index::getSymbolSubKindString(SymbolSubKind K) {
   case SymbolSubKind::AccessorSetter: return "acc-set";
   case SymbolSubKind::UsingTypename: return "using-typename";
   case SymbolSubKind::UsingValue: return "using-value";
-  case SymbolSubKind::UsingEnum:
-    return "using-enum";
+  case SymbolSubKind::UsingEnum: return "using-enum";
   }
   llvm_unreachable("invalid symbol subkind");
 }
diff --git a/clang/lib/Index/IndexingAction.cpp b/clang/lib/Index/IndexingAction.cpp
index c9fcaad311282..81c46a0d08de6 100644
--- a/clang/lib/Index/IndexingAction.cpp
+++ b/clang/lib/Index/IndexingAction.cpp
@@ -199,7 +199,7 @@ index::createIndexingAction(std::shared_ptr DataConsumer,
 }
 
 static bool topLevelDeclVisitor(void *context, const Decl *D) {
-  IndexingContext &IndexCtx = *static_cast(context);
+  IndexingContext &IndexCtx = *static_cast(context);
   return IndexCtx.indexTopLevelDecl(D);
 }
 
diff --git a/clang/lib/InstallAPI/CMakeLists.txt b/clang/lib/InstallAPI/CMakeLists.txt
index fdc4f064f29e9..dc90d6370de41 100644
--- a/clang/lib/InstallAPI/CMakeLists.txt
+++ b/clang/lib/InstallAPI/CMakeLists.txt
@@ -1,13 +1,17 @@
 set(LLVM_LINK_COMPONENTS
   Support
   TextAPI
+  Core
   )
 
 add_clang_library(clangInstallAPI
   FileList.cpp
+  Frontend.cpp
   HeaderFile.cpp
+  Visitor.cpp
 
   LINK_LIBS
   clangAST
   clangBasic
+  clangLex
   )
diff --git a/clang/lib/InstallAPI/Frontend.cpp b/clang/lib/InstallAPI/Frontend.cpp
new file mode 100644
index 0000000000000..240a80e1d3d82
--- /dev/null
+++ b/clang/lib/InstallAPI/Frontend.cpp
@@ -0,0 +1,154 @@
+//===- Frontend.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.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/InstallAPI/Frontend.h"
+#include "clang/AST/Availability.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+
+using namespace llvm;
+using namespace llvm::MachO;
+
+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) {
+
+  auto *GR = llvm::MachO::RecordsSlice::addGlobal(Name, Linkage, GV, Flags);
+  FrontendRecords.insert({GR, FrontendAttrs{Avail, D, Access}});
+  return GR;
+}
+
+ObjCInterfaceRecord *FrontendRecordsSlice::addObjCInterface(
+    StringRef Name, RecordLinkage Linkage, const clang::AvailabilityInfo Avail,
+    const Decl *D, HeaderType Access, bool IsEHType) {
+  ObjCIFSymbolKind SymType =
+      ObjCIFSymbolKind::Class | ObjCIFSymbolKind::MetaClass;
+  if (IsEHType)
+    SymType |= ObjCIFSymbolKind::EHType;
+  auto *ObjCR =
+      llvm::MachO::RecordsSlice::addObjCInterface(Name, Linkage, SymType);
+  FrontendRecords.insert({ObjCR, FrontendAttrs{Avail, D, Access}});
+  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) {
+  if (!FE)
+    return std::nullopt;
+
+  // Check if header has been looked up already and whether it is something
+  // installapi should use.
+  auto It = KnownFiles.find(FE);
+  if (It != KnownFiles.end()) {
+    if (It->second != HeaderType::Unknown)
+      return It->second;
+    else
+      return std::nullopt;
+  }
+
+  // If file was not found, search by how the header was
+  // included. This is primarily to resolve headers found
+  // in a different location than what passed directly as input.
+  StringRef IncludeName = PP.getHeaderSearchInfo().getIncludeNameForHeader(FE);
+  auto BackupIt = KnownIncludes.find(IncludeName.str());
+  if (BackupIt != KnownIncludes.end()) {
+    KnownFiles[FE] = BackupIt->second;
+    return BackupIt->second;
+  }
+
+  // Record that the file was found to avoid future string searches for the
+  // same file.
+  KnownFiles.insert({FE, HeaderType::Unknown});
+  return std::nullopt;
+}
+
+void InstallAPIContext::addKnownHeader(const HeaderFile &H) {
+  auto FE = FM->getFile(H.getPath());
+  if (!FE)
+    return; // File does not exist.
+  KnownFiles[*FE] = H.getType();
+
+  if (!H.useIncludeName())
+    return;
+
+  KnownIncludes[H.getIncludeName()] = H.getType();
+}
+
+static StringRef getFileExtension(clang::Language Lang) {
+  switch (Lang) {
+  default:
+    llvm_unreachable("Unexpected language option.");
+  case clang::Language::C:
+    return ".c";
+  case clang::Language::CXX:
+    return ".cpp";
+  case clang::Language::ObjC:
+    return ".m";
+  case clang::Language::ObjCXX:
+    return ".mm";
+  }
+}
+
+std::unique_ptr createInputBuffer(InstallAPIContext &Ctx) {
+  assert(Ctx.Type != HeaderType::Unknown &&
+         "unexpected access level for parsing");
+  SmallString<4096> Contents;
+  raw_svector_ostream OS(Contents);
+  for (const HeaderFile &H : Ctx.InputHeaders) {
+    if (H.getType() != Ctx.Type)
+      continue;
+    if (Ctx.LangMode == Language::C || Ctx.LangMode == Language::CXX)
+      OS << "#include ";
+    else
+      OS << "#import ";
+    if (H.useIncludeName())
+      OS << "<" << H.getIncludeName() << ">";
+    else
+      OS << "\"" << H.getPath() << "\"";
+
+    Ctx.addKnownHeader(H);
+  }
+  if (Contents.empty())
+    return nullptr;
+
+  SmallString<64> BufferName(
+      {"installapi-includes-", Ctx.Slice->getTriple().str(), "-",
+       getName(Ctx.Type), getFileExtension(Ctx.LangMode)});
+  return llvm::MemoryBuffer::getMemBufferCopy(Contents, BufferName);
+}
+
+} // namespace clang::installapi
diff --git a/clang/lib/InstallAPI/Visitor.cpp b/clang/lib/InstallAPI/Visitor.cpp
new file mode 100644
index 0000000000000..fbe6f1dabe005
--- /dev/null
+++ b/clang/lib/InstallAPI/Visitor.cpp
@@ -0,0 +1,207 @@
+//===- Visitor.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.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/InstallAPI/Visitor.h"
+#include "clang/Basic/Linkage.h"
+#include "clang/InstallAPI/Frontend.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Mangler.h"
+
+using namespace llvm;
+using namespace llvm::MachO;
+
+namespace clang::installapi {
+
+// Exported NamedDecl needs to have external linkage and
+// default visibility from LinkageComputer.
+static bool isExported(const NamedDecl *D) {
+  auto LV = D->getLinkageAndVisibility();
+  return isExternallyVisible(LV.getLinkage()) &&
+         (LV.getVisibility() == DefaultVisibility);
+}
+
+static SymbolFlags getFlags(bool WeakDef, bool ThreadLocal) {
+  SymbolFlags Result = SymbolFlags::None;
+  if (WeakDef)
+    Result |= SymbolFlags::WeakDefined;
+  if (ThreadLocal)
+    Result |= SymbolFlags::ThreadLocalValue;
+
+  return Result;
+}
+
+void InstallAPIVisitor::HandleTranslationUnit(ASTContext &ASTCtx) {
+  if (ASTCtx.getDiagnostics().hasErrorOccurred())
+    return;
+
+  auto *D = ASTCtx.getTranslationUnitDecl();
+  TraverseDecl(D);
+}
+
+std::string InstallAPIVisitor::getMangledName(const NamedDecl *D) const {
+  SmallString<256> Name;
+  if (MC->shouldMangleDeclName(D)) {
+    raw_svector_ostream NStream(Name);
+    MC->mangleName(D, NStream);
+  } else
+    Name += D->getNameAsString();
+
+  return getBackendMangledName(Name);
+}
+
+std::string InstallAPIVisitor::getBackendMangledName(Twine Name) const {
+  SmallString<256> FinalName;
+  Mangler::getNameWithPrefix(FinalName, Name, DataLayout(Layout));
+  return std::string(FinalName);
+}
+
+std::optional
+InstallAPIVisitor::getAccessForDecl(const NamedDecl *D) const {
+  SourceLocation Loc = D->getLocation();
+  if (Loc.isInvalid())
+    return std::nullopt;
+
+  // If the loc refers to a macro expansion, InstallAPI needs to first get the
+  // file location of the expansion.
+  auto FileLoc = SrcMgr.getFileLoc(Loc);
+  FileID ID = SrcMgr.getFileID(FileLoc);
+  if (ID.isInvalid())
+    return std::nullopt;
+
+  const FileEntry *FE = SrcMgr.getFileEntryForID(ID);
+  if (!FE)
+    return std::nullopt;
+
+  auto Header = Ctx.findAndRecordFile(FE, PP);
+  if (!Header.has_value())
+    return std::nullopt;
+
+  HeaderType Access = Header.value();
+  assert(Access != HeaderType::Unknown && "unexpected access level for global");
+  return Access;
+}
+
+/// Check if the interface itself or any of its super classes have an
+/// exception attribute. InstallAPI needs to export an additional symbol
+/// ("OBJC_EHTYPE_$CLASS_NAME") if any of the classes have the exception
+/// attribute.
+static bool hasObjCExceptionAttribute(const ObjCInterfaceDecl *D) {
+  for (; D != nullptr; D = D->getSuperClass())
+    if (D->hasAttr())
+      return true;
+
+  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)
+  if (!D->isThisDeclarationADefinition())
+    return true;
+
+  // Skip over declarations that access could not be collected for.
+  auto Access = getAccessForDecl(D);
+  if (!Access)
+    return true;
+
+  StringRef Name = D->getObjCRuntimeNameAsString();
+  const RecordLinkage Linkage =
+      isExported(D) ? RecordLinkage::Exported : RecordLinkage::Internal;
+  const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D);
+  const bool IsEHType =
+      (!D->getASTContext().getLangOpts().ObjCRuntime.isFragile() &&
+       hasObjCExceptionAttribute(D));
+
+  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;
+}
+
+bool InstallAPIVisitor::VisitVarDecl(const VarDecl *D) {
+  // Skip function parameters.
+  if (isa(D))
+    return true;
+
+  // Skip variables in records. They are handled seperately for C++.
+  if (D->getDeclContext()->isRecord())
+    return true;
+
+  // Skip anything inside functions or methods.
+  if (!D->isDefinedOutsideFunctionOrMethod())
+    return true;
+
+  // If this is a template but not specialization or instantiation, skip.
+  if (D->getASTContext().getTemplateOrSpecializationInfo(D) &&
+      D->getTemplateSpecializationKind() == TSK_Undeclared)
+    return true;
+
+  // Skip over declarations that access could not collected for.
+  auto Access = getAccessForDecl(D);
+  if (!Access)
+    return true;
+
+  const RecordLinkage Linkage =
+      isExported(D) ? RecordLinkage::Exported : RecordLinkage::Internal;
+  const bool WeakDef = D->hasAttr();
+  const bool ThreadLocal = D->getTLSKind() != VarDecl::TLS_None;
+  const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D);
+  Ctx.Slice->addGlobal(getMangledName(D), Linkage, GlobalRecord::Kind::Variable,
+                       Avail, D, *Access, getFlags(WeakDef, ThreadLocal));
+  return true;
+}
+
+} // namespace clang::installapi
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index ff570576356c6..d42e7a7b58127 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4266,6 +4266,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;
@@ -7929,7 +7931,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/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 22ee60af4616d..9471f6f725efb 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 4946a61fca007..50e3c39f60919 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/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index aede602f1de84..b79683bb32a69 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/JumpDiagnostics.cpp b/clang/lib/Sema/JumpDiagnostics.cpp
index ec3892e92f3c3..6722878883be8 100644
--- a/clang/lib/Sema/JumpDiagnostics.cpp
+++ b/clang/lib/Sema/JumpDiagnostics.cpp
@@ -604,6 +604,16 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S,
     break;
   }
 
+  case Stmt::OpenACCComputeConstructClass: {
+    unsigned NewParentScope = Scopes.size();
+    OpenACCComputeConstruct *CC = cast(S);
+    Scopes.push_back(GotoScope(
+        ParentScope, diag::note_acc_branch_into_compute_construct,
+        diag::note_acc_branch_out_of_compute_construct, CC->getBeginLoc()));
+    BuildScopeInformation(CC->getStructuredBlock(), NewParentScope);
+    return;
+  }
+
   default:
     if (auto *ED = dyn_cast(S)) {
       if (!ED->isStandaloneDirective()) {
@@ -936,11 +946,16 @@ void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, SourceLocation DiagLoc,
       if (Scopes[I].InDiag == diag::note_protected_by_seh_finally) {
         S.Diag(From->getBeginLoc(), diag::warn_jump_out_of_seh_finally);
         break;
-      }
-      if (Scopes[I].InDiag == diag::note_omp_protected_structured_block) {
+      } else if (Scopes[I].InDiag ==
+                 diag::note_omp_protected_structured_block) {
         S.Diag(From->getBeginLoc(), diag::err_goto_into_protected_scope);
         S.Diag(To->getBeginLoc(), diag::note_omp_exits_structured_block);
         break;
+      } else if (Scopes[I].InDiag ==
+                 diag::note_acc_branch_into_compute_construct) {
+        S.Diag(From->getBeginLoc(), diag::err_goto_into_protected_scope);
+        S.Diag(Scopes[I].Loc, diag::note_acc_branch_out_of_compute_construct);
+        return;
       }
     }
   }
diff --git a/clang/lib/Sema/ParsedAttr.cpp b/clang/lib/Sema/ParsedAttr.cpp
index b36680582ce18..5c2ebf51c03c0 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/Scope.cpp b/clang/lib/Sema/Scope.cpp
index cea6a62e34747..11a41753a1bda 100644
--- a/clang/lib/Sema/Scope.cpp
+++ b/clang/lib/Sema/Scope.cpp
@@ -37,6 +37,7 @@ void Scope::setFlags(Scope *parent, unsigned flags) {
     FnParent       = parent->FnParent;
     BlockParent    = parent->BlockParent;
     TemplateParamParent = parent->TemplateParamParent;
+    DeclParent = parent->DeclParent;
     MSLastManglingParent = parent->MSLastManglingParent;
     MSCurManglingNumber = getMSLastManglingNumber();
     if ((Flags & (FnScope | ClassScope | BlockScope | TemplateParamScope |
@@ -52,6 +53,7 @@ void Scope::setFlags(Scope *parent, unsigned flags) {
     PrototypeIndex = 0;
     MSLastManglingParent = FnParent = BlockParent = nullptr;
     TemplateParamParent = nullptr;
+    DeclParent = nullptr;
     MSLastManglingNumber = 1;
     MSCurManglingNumber = 1;
   }
@@ -76,6 +78,7 @@ void Scope::setFlags(Scope *parent, unsigned flags) {
     PrototypeDepth++;
 
   if (flags & DeclScope) {
+    DeclParent = this;
     if (flags & FunctionPrototypeScope)
       ; // Prototype scopes are uninteresting.
     else if ((flags & ClassScope) && getParent()->isClassScope())
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 36a621e4fbc32..bfd21b4d6c671 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),
       SyclIntHeader(nullptr), SyclIntFooter(nullptr) {
   assert(pp.TUKind == TUKind);
   TUScope = nullptr;
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 62e977a56ef78..268661ed61cc6 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2183,9 +2183,11 @@ static bool SemaBuiltinCpu(Sema &S, const TargetInfo &TI, CallExpr *TheCall,
 
   // Check the contents of the string.
   StringRef Feature = cast(Arg)->getString();
-  if (IsCPUSupports && !TheTI->validateCpuSupports(Feature))
-    return S.Diag(TheCall->getBeginLoc(), diag::err_invalid_cpu_supports)
-           << Arg->getSourceRange();
+  if (IsCPUSupports && !TheTI->validateCpuSupports(Feature)) {
+    S.Diag(TheCall->getBeginLoc(), diag::warn_invalid_cpu_supports)
+        << Arg->getSourceRange();
+    return false;
+  }
   if (!IsCPUSupports && !TheTI->validateCpuIs(Feature))
     return S.Diag(TheCall->getBeginLoc(), diag::err_invalid_cpu_is)
            << Arg->getSourceRange();
@@ -2193,17 +2195,23 @@ static bool SemaBuiltinCpu(Sema &S, const TargetInfo &TI, CallExpr *TheCall,
 }
 
 /// Checks that __builtin_popcountg was called with a single argument, which is
-/// an integer.
+/// an unsigned integer.
 static bool SemaBuiltinPopcountg(Sema &S, CallExpr *TheCall) {
   if (checkArgCount(S, TheCall, 1))
     return true;
 
-  Expr *Arg = TheCall->getArg(0);
+  ExprResult ArgRes = S.DefaultLvalueConversion(TheCall->getArg(0));
+  if (ArgRes.isInvalid())
+    return true;
+
+  Expr *Arg = ArgRes.get();
+  TheCall->setArg(0, Arg);
+
   QualType ArgTy = Arg->getType();
 
-  if (!ArgTy->isIntegerType()) {
+  if (!ArgTy->isUnsignedIntegerType()) {
     S.Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
-        << 1 << /*integer ty*/ 7 << ArgTy;
+        << 1 << /*unsigned integer ty*/ 7 << ArgTy;
     return true;
   }
   return false;
@@ -5229,53 +5237,83 @@ bool Sema::CheckPPCMMAType(QualType Type, SourceLocation TypeLoc) {
 bool CheckVectorElementCallArgs(Sema *S, CallExpr *TheCall) {
   assert(TheCall->getNumArgs() > 1);
   ExprResult A = TheCall->getArg(0);
-  ExprResult B = TheCall->getArg(1);
+
   QualType ArgTyA = A.get()->getType();
-  QualType ArgTyB = B.get()->getType();
+
   auto *VecTyA = ArgTyA->getAs();
-  auto *VecTyB = ArgTyB->getAs();
   SourceLocation BuiltinLoc = TheCall->getBeginLoc();
-  if (VecTyA == nullptr && VecTyB == nullptr)
-    return false;
 
-  if (VecTyA && VecTyB) {
-    bool retValue = false;
-    if (VecTyA->getElementType() != VecTyB->getElementType()) {
-      // Note: type promotion is intended to be handeled via the intrinsics
-      //  and not the builtin itself.
-      S->Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_incompatible_vector)
-          << TheCall->getDirectCallee()
-          << SourceRange(A.get()->getBeginLoc(), B.get()->getEndLoc());
-      retValue = true;
-    }
-    if (VecTyA->getNumElements() != VecTyB->getNumElements()) {
-      // if we get here a HLSLVectorTruncation is needed.
-      S->Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector)
-          << TheCall->getDirectCallee()
-          << SourceRange(TheCall->getArg(0)->getBeginLoc(),
-                         TheCall->getArg(1)->getEndLoc());
-      retValue = true;
-    }
+  for (unsigned i = 1; i < TheCall->getNumArgs(); ++i) {
+    ExprResult B = TheCall->getArg(i);
+    QualType ArgTyB = B.get()->getType();
+    auto *VecTyB = ArgTyB->getAs();
+    if (VecTyA == nullptr && VecTyB == nullptr)
+      return false;
+
+    if (VecTyA && VecTyB) {
+      bool retValue = false;
+      if (VecTyA->getElementType() != VecTyB->getElementType()) {
+        // Note: type promotion is intended to be handeled via the intrinsics
+        //  and not the builtin itself.
+        S->Diag(TheCall->getBeginLoc(),
+                diag::err_vec_builtin_incompatible_vector)
+            << TheCall->getDirectCallee() << /*useAllTerminology*/ true
+            << SourceRange(A.get()->getBeginLoc(), B.get()->getEndLoc());
+        retValue = true;
+      }
+      if (VecTyA->getNumElements() != VecTyB->getNumElements()) {
+        // You should only be hitting this case if you are calling the builtin
+        // directly. HLSL intrinsics should avoid this case via a
+        // HLSLVectorTruncation.
+        S->Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector)
+            << TheCall->getDirectCallee() << /*useAllTerminology*/ true
+            << SourceRange(TheCall->getArg(0)->getBeginLoc(),
+                           TheCall->getArg(1)->getEndLoc());
+        retValue = true;
+      }
 
-    if (retValue)
-      TheCall->setType(VecTyA->getElementType());
+      if (!retValue)
+        TheCall->setType(VecTyA->getElementType());
 
-    return retValue;
+      return retValue;
+    }
   }
 
   // Note: if we get here one of the args is a scalar which
   // requires a VectorSplat on Arg0 or Arg1
   S->Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
-      << TheCall->getDirectCallee()
+      << TheCall->getDirectCallee() << /*useAllTerminology*/ true
       << SourceRange(TheCall->getArg(0)->getBeginLoc(),
                      TheCall->getArg(1)->getEndLoc());
   return true;
 }
 
+bool CheckAllArgsHaveFloatRepresentation(Sema *S, CallExpr *TheCall) {
+  QualType ExpectedType = S->Context.FloatTy;
+  for (unsigned i = 0; i < TheCall->getNumArgs(); ++i) {
+    QualType PassedType = TheCall->getArg(i)->getType();
+    if (!PassedType->hasFloatingRepresentation()) {
+      if (auto *VecTyA = PassedType->getAs())
+        ExpectedType = S->Context.getVectorType(
+            ExpectedType, VecTyA->getNumElements(), VecTyA->getVectorKind());
+      S->Diag(TheCall->getArg(0)->getBeginLoc(),
+              diag::err_typecheck_convert_incompatible)
+          << PassedType << ExpectedType << 1 << 0 << 0;
+      return true;
+    }
+  }
+  return false;
+}
+
 // Note: returning true in this case results in CheckBuiltinFunctionCall
 // 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;
@@ -5285,6 +5323,33 @@ 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;
+    if (CheckAllArgsHaveFloatRepresentation(this, TheCall))
+      return true;
+    break;
+  }
+  case Builtin::BI__builtin_hlsl_lerp: {
+    if (checkArgCount(*this, TheCall, 3))
+      return true;
+    if (CheckVectorElementCallArgs(this, TheCall))
+      return true;
+    if (SemaBuiltinElementwiseTernaryMath(TheCall))
+      return true;
+    if (CheckAllArgsHaveFloatRepresentation(this, 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;
 }
@@ -6364,10 +6429,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"))
@@ -6379,9 +6448,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"))
@@ -9639,7 +9705,7 @@ bool Sema::SemaBuiltinVSX(CallExpr *TheCall) {
   if ((!Arg1Ty->isVectorType() && !Arg1Ty->isDependentType()) ||
       (!Arg2Ty->isVectorType() && !Arg2Ty->isDependentType())) {
     return Diag(BuiltinLoc, diag::err_vec_builtin_non_vector)
-           << TheCall->getDirectCallee()
+           << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false
            << SourceRange(TheCall->getArg(0)->getBeginLoc(),
                           TheCall->getArg(1)->getEndLoc());
   }
@@ -9647,7 +9713,7 @@ bool Sema::SemaBuiltinVSX(CallExpr *TheCall) {
   // Check the first two arguments are the same type.
   if (!Context.hasSameUnqualifiedType(Arg1Ty, Arg2Ty)) {
     return Diag(BuiltinLoc, diag::err_vec_builtin_incompatible_vector)
-           << TheCall->getDirectCallee()
+           << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false
            << SourceRange(TheCall->getArg(0)->getBeginLoc(),
                           TheCall->getArg(1)->getEndLoc());
   }
@@ -9683,7 +9749,7 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
     if (!LHSType->isVectorType() || !RHSType->isVectorType())
       return ExprError(
           Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_non_vector)
-          << TheCall->getDirectCallee()
+          << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false
           << SourceRange(TheCall->getArg(0)->getBeginLoc(),
                          TheCall->getArg(1)->getEndLoc()));
 
@@ -9699,12 +9765,14 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) {
         return ExprError(Diag(TheCall->getBeginLoc(),
                               diag::err_vec_builtin_incompatible_vector)
                          << TheCall->getDirectCallee()
+                         << /*isMorethantwoArgs*/ false
                          << SourceRange(TheCall->getArg(1)->getBeginLoc(),
                                         TheCall->getArg(1)->getEndLoc()));
     } else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) {
       return ExprError(Diag(TheCall->getBeginLoc(),
                             diag::err_vec_builtin_incompatible_vector)
                        << TheCall->getDirectCallee()
+                       << /*isMorethantwoArgs*/ false
                        << SourceRange(TheCall->getArg(0)->getBeginLoc(),
                                       TheCall->getArg(1)->getEndLoc()));
     } else if (numElements != numResElements) {
@@ -16760,6 +16828,20 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E,
     }
   }
 
+  // Complain if we are converting a lambda expression to a boolean value
+  // outside of instantiation.
+  if (!inTemplateInstantiation()) {
+    if (const auto *MCallExpr = dyn_cast(E)) {
+      if (const auto *MRecordDecl = MCallExpr->getRecordDecl();
+          MRecordDecl && MRecordDecl->isLambda()) {
+        Diag(E->getExprLoc(), diag::warn_impcast_pointer_to_bool)
+            << /*LambdaPointerConversionOperatorType=*/3
+            << MRecordDecl->getSourceRange() << Range << IsEqual;
+        return;
+      }
+    }
+  }
+
   // Expect to find a single Decl.  Skip anything more complicated.
   ValueDecl *D = nullptr;
   if (DeclRefExpr *R = dyn_cast(E)) {
@@ -17779,20 +17861,8 @@ class SequenceChecker : public ConstEvaluatedExprVisitor {
       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) {
@@ -17800,10 +17870,20 @@ class SequenceChecker : public ConstEvaluatedExprVisitor {
       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);
@@ -19955,7 +20035,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;
 
@@ -19967,11 +20048,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 c44be0df9b0a8..8d75239009401 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/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 4f91e557b049b..157030deebe0a 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -1110,7 +1110,9 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS,
     //   unqualified-id followed by a < and name lookup finds either one
     //   or more functions or finds nothing.
     if (!IsFilteredTemplateName)
-      FilterAcceptableTemplateNames(Result);
+      FilterAcceptableTemplateNames(Result,
+                                    /*AllowFunctionTemplates=*/true,
+                                    /*AllowDependent=*/true);
 
     bool IsFunctionTemplate;
     bool IsVarTemplate;
@@ -1120,6 +1122,7 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS,
       Template = Context.getOverloadedTemplateName(Result.begin(),
                                                    Result.end());
     } else if (!Result.empty()) {
+      assert(!Result.isUnresolvableResult());
       auto *TD = cast(getAsTemplateNameDecl(
           *Result.begin(), /*AllowFunctionTemplates=*/true,
           /*AllowDependent=*/false));
@@ -2044,7 +2047,8 @@ static bool ShouldDiagnoseUnusedDecl(const LangOptions &LangOpts,
           return false;
 
         if (Init) {
-          const auto *Construct = dyn_cast(Init);
+          const auto *Construct =
+              dyn_cast(Init->IgnoreImpCasts());
           if (Construct && !Construct->isElidable()) {
             const CXXConstructorDecl *CD = Construct->getConstructor();
             if (!CD->isTrivial() && !RD->hasAttr() &&
@@ -5201,6 +5205,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());
@@ -6410,12 +6416,6 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
   } else if (DiagnoseUnexpandedParameterPack(NameInfo, UPPC_DeclarationType))
     return nullptr;
 
-  // The scope passed in may not be a decl scope.  Zip up the scope tree until
-  // we find one that is.
-  while ((S->getFlags() & Scope::DeclScope) == 0 ||
-         (S->getFlags() & Scope::TemplateParamScope) != 0)
-    S = S->getParent();
-
   DeclContext *DC = CurContext;
   if (D.getCXXScopeSpec().isInvalid())
     D.setInvalidType();
@@ -6543,12 +6543,22 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
     RemoveUsingDecls(Previous);
   }
 
-  if (Previous.isSingleResult() &&
-      Previous.getFoundDecl()->isTemplateParameter()) {
-    // Maybe we will complain about the shadowed template parameter.
-    if (!D.isInvalidType())
-      DiagnoseTemplateParameterShadow(D.getIdentifierLoc(),
-                                      Previous.getFoundDecl());
+  if (auto *TPD = Previous.getAsSingle();
+      TPD && TPD->isTemplateParameter()) {
+    // Older versions of clang allowed the names of function/variable templates
+    // to shadow the names of their template parameters. For the compatibility
+    // purposes we detect such cases and issue a default-to-error warning that
+    // can be disabled with -Wno-strict-primary-template-shadow.
+    if (!D.isInvalidType()) {
+      bool AllowForCompatibility = false;
+      if (Scope *DeclParent = S->getDeclParent();
+          Scope *TemplateParamParent = S->getTemplateParamParent()) {
+        AllowForCompatibility = DeclParent->Contains(*TemplateParamParent) &&
+                                TemplateParamParent->isDeclScope(TPD);
+      }
+      DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), TPD,
+                                      AllowForCompatibility);
+    }
 
     // Just pretend that we didn't see the previous declaration.
     Previous.clear();
@@ -6572,6 +6582,9 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
   if (getLangOpts().CPlusPlus)
     CheckExtraCXXDefaultArguments(D);
 
+  /// Get the innermost enclosing declaration scope.
+  S = S->getDeclParent();
+
   NamedDecl *New;
 
   bool AddToScope = true;
@@ -8740,6 +8753,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())
@@ -8990,6 +9035,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)) {
@@ -9372,6 +9423,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:
@@ -9405,15 +9472,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);
@@ -14003,7 +14061,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);
   }
 
@@ -14622,9 +14682,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
@@ -14632,7 +14696,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.
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 3f6d0be85f21b..9f40c14905059 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -2129,12 +2129,6 @@ static void handleTLSModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
     return;
   }
 
-  if (S.Context.getTargetInfo().getTriple().isOSAIX() &&
-      Model == "local-dynamic") {
-    S.Diag(LiteralLoc, diag::err_aix_attr_unsupported_tls_model) << Model;
-    return;
-  }
-
   D->addAttr(::new (S.Context) TLSModelAttr(S.Context, AL, Model));
 }
 
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index fe146c7726cff..12bb922fadf6c 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7321,7 +7321,7 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
   bool CanPass = canPassInRegisters(*this, Record, CCK);
 
   // Do not change ArgPassingRestrictions if it has already been set to
-  // ArgPassingKind::CanNeverPassInRegs.
+  // RecordArgPassingKind::CanNeverPassInRegs.
   if (Record->getArgPassingRestrictions() !=
       RecordArgPassingKind::CanNeverPassInRegs)
     Record->setArgPassingRestrictions(
@@ -12230,10 +12230,8 @@ Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc,
   assert(NamespcName && "Invalid NamespcName.");
   assert(IdentLoc.isValid() && "Invalid NamespceName location.");
 
-  // This can only happen along a recovery path.
-  while (S->isTemplateParamScope())
-    S = S->getParent();
-  assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
+  // Get the innermost enclosing declaration scope.
+  S = S->getDeclParent();
 
   UsingDirectiveDecl *UDir = nullptr;
   NestedNameSpecifier *Qualifier = nullptr;
@@ -13543,11 +13541,8 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS,
                                   SourceLocation UsingLoc, UnqualifiedId &Name,
                                   const ParsedAttributesView &AttrList,
                                   TypeResult Type, Decl *DeclFromDeclSpec) {
-  // Skip up to the relevant declaration scope.
-  while (S->isTemplateParamScope())
-    S = S->getParent();
-  assert((S->getFlags() & Scope::DeclScope) &&
-         "got alias-declaration outside of declaration scope");
+  // Get the innermost enclosing declaration scope.
+  S = S->getDeclParent();
 
   if (Type.isInvalid())
     return nullptr;
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index 2011f4084dd2a..94a245f0f905f 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -2233,12 +2233,16 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
     Diag(IVI->getLocation(), diag::err_inconsistent_ivar_count);
 }
 
+static bool shouldWarnUndefinedMethod(const ObjCMethodDecl *M) {
+  // No point warning no definition of method which is 'unavailable'.
+  return M->getAvailability() != AR_Unavailable;
+}
+
 static void WarnUndefinedMethod(Sema &S, ObjCImplDecl *Impl,
                                 ObjCMethodDecl *method, bool &IncompleteImpl,
                                 unsigned DiagID,
                                 NamedDecl *NeededFor = nullptr) {
-  // No point warning no definition of method which is 'unavailable'.
-  if (method->getAvailability() == AR_Unavailable)
+  if (!shouldWarnUndefinedMethod(method))
     return;
 
   // FIXME: For now ignore 'IncompleteImpl'.
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index a39283d6e0edd..21664e042fbe8 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -6332,12 +6332,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());
   }
@@ -17882,7 +17876,6 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy,
     if (lhq.getAddressSpace() != rhq.getAddressSpace()) {
       DiagKind = diag::err_typecheck_incompatible_address_space;
       break;
-
     } else if (lhq.getObjCLifetime() != rhq.getObjCLifetime()) {
       DiagKind = diag::err_typecheck_incompatible_ownership;
       break;
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index efb296b39ce9b..1ba681c03a828 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -895,6 +895,12 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
   if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope())
     Diag(OpLoc, diag::err_omp_simd_region_cannot_use_stmt) << "throw";
 
+  // Exceptions that escape a compute construct are ill-formed.
+  if (getLangOpts().OpenACC && getCurScope() &&
+      getCurScope()->isInOpenACCComputeConstructScope(Scope::TryScope))
+    Diag(OpLoc, diag::err_acc_branch_in_out_compute_construct)
+        << /*throw*/ 2 << /*out of*/ 0;
+
   if (Ex && !Ex->isTypeDependent()) {
     // Initialize the exception result.  This implicitly weeds out
     // abstract types or types with inaccessible copy constructors.
@@ -1225,7 +1231,7 @@ static QualType adjustCVQualifiersForCXXThisWithinLambda(
                     : nullptr;
     }
   }
-  return ASTCtx.getPointerType(ClassType);
+  return ThisTy;
 }
 
 QualType Sema::getCurrentThisType() {
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 57d2d6bf164ad..f29b11fe449d0 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;
       }
     }
@@ -7735,6 +7760,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:
@@ -8290,6 +8323,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;
@@ -8367,6 +8404,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) {
@@ -9193,6 +9233,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,
@@ -9210,7 +9267,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;
     }
 
@@ -10509,6 +10568,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
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index ed7f626971f34..f08c1cb3a13ef 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 d365a5151a458..d3a602d1c382f 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 4bec4e2c27fbb..62becd6e5671d 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -4964,7 +4964,8 @@ StmtResult Sema::ActOnOpenMPRegionEnd(StmtResult S,
           if (RC->getModifier() != OMPC_REDUCTION_inscan)
             continue;
           for (Expr *E : RC->copy_array_temps())
-            MarkDeclarationsReferencedInExpr(E);
+            if (E)
+              MarkDeclarationsReferencedInExpr(E);
         }
         if (auto *AC = dyn_cast(C)) {
           for (Expr *E : AC->varlists())
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index a5ee09415384f..007da76267115 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;
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index a4d83e15c8a94..a9711a7397bc7 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -527,6 +527,13 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHSVal,
     return StmtError();
   }
 
+  if (LangOpts.OpenACC &&
+      getCurScope()->isInOpenACCComputeConstructScope(Scope::SwitchScope)) {
+    Diag(CaseLoc, diag::err_acc_branch_in_out_compute_construct)
+        << /*branch*/ 0 << /*into*/ 1;
+    return StmtError();
+  }
+
   auto *CS = CaseStmt::Create(Context, LHSVal.get(), RHSVal.get(),
                               CaseLoc, DotDotDotLoc, ColonLoc);
   getCurFunction()->SwitchStack.back().getPointer()->addSwitchCase(CS);
@@ -546,6 +553,13 @@ Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
     return SubStmt;
   }
 
+  if (LangOpts.OpenACC &&
+      getCurScope()->isInOpenACCComputeConstructScope(Scope::SwitchScope)) {
+    Diag(DefaultLoc, diag::err_acc_branch_in_out_compute_construct)
+        << /*branch*/ 0 << /*into*/ 1;
+    return StmtError();
+  }
+
   DefaultStmt *DS = new (Context) DefaultStmt(DefaultLoc, ColonLoc, SubStmt);
   getCurFunction()->SwitchStack.back().getPointer()->addSwitchCase(DS);
   return DS;
@@ -567,6 +581,11 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
     Diag(IdentLoc, diag::warn_reserved_extern_symbol)
         << TheDecl << static_cast(Status);
 
+  // If this label is in a compute construct scope, we need to make sure we
+  // check gotos in/out.
+  if (getCurScope()->isInOpenACCComputeConstructScope())
+    setFunctionHasBranchProtectedScope();
+
   // Otherwise, things are good.  Fill in the declaration and return it.
   LabelStmt *LS = new (Context) LabelStmt(IdentLoc, TheDecl, SubStmt);
   TheDecl->setStmt(LS);
@@ -3304,6 +3323,12 @@ StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc,
                                SourceLocation LabelLoc,
                                LabelDecl *TheDecl) {
   setFunctionHasBranchIntoScope();
+
+  // If this goto is in a compute construct scope, we need to make sure we check
+  // gotos in/out.
+  if (getCurScope()->isInOpenACCComputeConstructScope())
+    setFunctionHasBranchProtectedScope();
+
   TheDecl->markUsed(Context);
   return new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc);
 }
@@ -3332,6 +3357,11 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,
 
   setFunctionHasIndirectGoto();
 
+  // If this goto is in a compute construct scope, we need to make sure we
+  // check gotos in/out.
+  if (getCurScope()->isInOpenACCComputeConstructScope())
+    setFunctionHasBranchProtectedScope();
+
   return new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E);
 }
 
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index e91033dd88689..df20f83ac8afe 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -491,18 +491,20 @@ bool Sema::LookupTemplateName(LookupResult &Found,
     // To keep our behavior consistent, we apply the "finds nothing" part in
     // all language modes, and diagnose the empty lookup in ActOnCallExpr if we
     // successfully form a call to an undeclared template-id.
-    bool AllFunctions =
-        getLangOpts().CPlusPlus20 && llvm::all_of(Found, [](NamedDecl *ND) {
+    bool AnyFunctions =
+        getLangOpts().CPlusPlus20 && llvm::any_of(Found, [](NamedDecl *ND) {
           return isa(ND->getUnderlyingDecl());
         });
-    if (AllFunctions || (Found.empty() && !IsDependent)) {
+    if (AnyFunctions || (Found.empty() && !IsDependent)) {
       // If lookup found any functions, or if this is a name that can only be
       // used for a function, then strongly assume this is a function
       // template-id.
       *ATK = (Found.empty() && Found.getLookupName().isIdentifier())
                  ? AssumedTemplateKind::FoundNothing
                  : AssumedTemplateKind::FoundFunctions;
-      Found.clear();
+      FilterAcceptableTemplateNames(Found,
+                                    /*AllowFunctionTemplates*/ true,
+                                    /*AllowDependent*/ true);
       return false;
     }
   }
@@ -881,20 +883,23 @@ bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation,
   return true;
 }
 
-/// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining
-/// that the template parameter 'PrevDecl' is being shadowed by a new
-/// declaration at location Loc. Returns true to indicate that this is
-/// an error, and false otherwise.
-void Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) {
+void Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl,
+                                           bool SupportedForCompatibility) {
   assert(PrevDecl->isTemplateParameter() && "Not a template parameter");
 
-  // C++ [temp.local]p4:
-  //   A template-parameter shall not be redeclared within its
-  //   scope (including nested scopes).
+  // C++23 [temp.local]p6:
+  //   The name of a template-parameter shall not be bound to any following.
+  //   declaration whose locus is contained by the scope to which the
+  //   template-parameter belongs.
   //
-  // Make this a warning when MSVC compatibility is requested.
-  unsigned DiagId = getLangOpts().MSVCCompat ? diag::ext_template_param_shadow
-                                             : diag::err_template_param_shadow;
+  // When MSVC compatibility is enabled, the diagnostic is always a warning
+  // by default. Otherwise, it an error unless SupportedForCompatibility is
+  // true, in which case it is a default-to-error warning.
+  unsigned DiagId =
+      getLangOpts().MSVCCompat
+          ? diag::ext_template_param_shadow
+          : (SupportedForCompatibility ? diag::ext_compat_template_param_shadow
+                                       : diag::err_template_param_shadow);
   const auto *ND = cast(PrevDecl);
   Diag(Loc, DiagId) << ND->getDeclName();
   NoteTemplateParameterLocation(*ND);
@@ -3141,12 +3146,14 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
            diag::note_template_param_prev_default_arg_in_other_module)
           << PrevModuleName;
       Invalid = true;
-    } else if (MissingDefaultArg && TPC != TPC_FunctionTemplate) {
-      // C++ [temp.param]p11:
-      //   If a template-parameter of a class template has a default
-      //   template-argument, each subsequent template-parameter shall either
-      //   have a default template-argument supplied or be a template parameter
-      //   pack.
+    } else if (MissingDefaultArg &&
+               (TPC == TPC_ClassTemplate || TPC == TPC_FriendClassTemplate ||
+                TPC == TPC_VarTemplate || TPC == TPC_TypeAliasTemplate)) {
+      // C++ 23[temp.param]p14:
+      // If a template-parameter of a class template, variable template, or
+      // alias template has a default template argument, each subsequent
+      // template-parameter shall either have a default template argument
+      // supplied or be a template parameter pack.
       Diag((*NewParam)->getLocation(),
            diag::err_template_param_default_arg_missing);
       Diag(PreviousDefaultArgLoc, diag::note_template_param_prev_default_arg);
@@ -8500,9 +8507,7 @@ Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) {
     return false;
 
   // Find the nearest enclosing declaration scope.
-  while ((S->getFlags() & Scope::DeclScope) == 0 ||
-         (S->getFlags() & Scope::TemplateParamScope) != 0)
-    S = S->getParent();
+  S = S->getDeclParent();
 
   // C++ [temp.pre]p6: [P2096]
   //   A template, explicit specialization, or partial specialization shall not
@@ -10617,11 +10622,8 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
     return true;
   }
 
-  // The scope passed in may not be a decl scope.  Zip up the scope tree until
-  // we find one that is.
-  while ((S->getFlags() & Scope::DeclScope) == 0 ||
-         (S->getFlags() & Scope::TemplateParamScope) != 0)
-    S = S->getParent();
+  // Get the innermost enclosing declaration scope.
+  S = S->getDeclParent();
 
   // Determine the type of the declaration.
   TypeSourceInfo *T = GetTypeForDeclarator(D);
diff --git a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
index fdcc46e58580b..29eb932584027 100644
--- a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
@@ -301,21 +301,27 @@ compareValueToThreshold(ProgramStateRef State, NonLoc Value, NonLoc Threshold,
   // calling `evalBinOpNN`:
   if (isNegative(SVB, State, Value) && isUnsigned(SVB, Threshold)) {
     if (CheckEquality) {
-      // negative_value == unsigned_value is always false
+      // negative_value == unsigned_threshold is always false
       return {nullptr, State};
     }
-    // negative_value < unsigned_value is always false
+    // negative_value < unsigned_threshold is always true
     return {State, nullptr};
   }
   if (isUnsigned(SVB, Value) && isNegative(SVB, State, Threshold)) {
-    // unsigned_value == negative_value and unsigned_value < negative_value are
-    // both always false
+    // unsigned_value == negative_threshold and
+    // unsigned_value < negative_threshold are both always false
     return {nullptr, State};
   }
-  // FIXME: these special cases are sufficient for handling real-world
+  // FIXME: These special cases are sufficient for handling real-world
   // comparisons, but in theory there could be contrived situations where
   // automatic conversion of a symbolic value (which can be negative and can be
   // positive) leads to incorrect results.
+  // NOTE: We NEED to use the `evalBinOpNN` call in the "common" case, because
+  // we want to ensure that assumptions coming from this precondition and
+  // assumptions coming from regular C/C++ operator calls are represented by
+  // constraints on the same symbolic expression. A solution that would
+  // evaluate these "mathematical" compariosns through a separate pathway would
+  // be a step backwards in this sense.
 
   const BinaryOperatorKind OpKind = CheckEquality ? BO_EQ : BO_LT;
   auto BelowThreshold =
diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index b7b64c3da4f6c..59be236ca1c76 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -124,48 +124,47 @@ class CStringChecker : public Checker< eval::Call,
                                      const CallEvent &)>;
 
   CallDescriptionMap Callbacks = {
-      {{CDF_MaybeBuiltin, {"memcpy"}, 3},
+      {{CDM::CLibrary, {"memcpy"}, 3},
        std::bind(&CStringChecker::evalMemcpy, _1, _2, _3, CK_Regular)},
-      {{CDF_MaybeBuiltin, {"wmemcpy"}, 3},
+      {{CDM::CLibrary, {"wmemcpy"}, 3},
        std::bind(&CStringChecker::evalMemcpy, _1, _2, _3, CK_Wide)},
-      {{CDF_MaybeBuiltin, {"mempcpy"}, 3},
+      {{CDM::CLibrary, {"mempcpy"}, 3},
        std::bind(&CStringChecker::evalMempcpy, _1, _2, _3, CK_Regular)},
-      {{CDF_None, {"wmempcpy"}, 3},
+      {{CDM::Unspecified, {"wmempcpy"}, 3},
        std::bind(&CStringChecker::evalMempcpy, _1, _2, _3, CK_Wide)},
-      {{CDF_MaybeBuiltin, {"memcmp"}, 3},
+      {{CDM::CLibrary, {"memcmp"}, 3},
        std::bind(&CStringChecker::evalMemcmp, _1, _2, _3, CK_Regular)},
-      {{CDF_MaybeBuiltin, {"wmemcmp"}, 3},
+      {{CDM::CLibrary, {"wmemcmp"}, 3},
        std::bind(&CStringChecker::evalMemcmp, _1, _2, _3, CK_Wide)},
-      {{CDF_MaybeBuiltin, {"memmove"}, 3},
+      {{CDM::CLibrary, {"memmove"}, 3},
        std::bind(&CStringChecker::evalMemmove, _1, _2, _3, CK_Regular)},
-      {{CDF_MaybeBuiltin, {"wmemmove"}, 3},
+      {{CDM::CLibrary, {"wmemmove"}, 3},
        std::bind(&CStringChecker::evalMemmove, _1, _2, _3, CK_Wide)},
-      {{CDF_MaybeBuiltin, {"memset"}, 3}, &CStringChecker::evalMemset},
-      {{CDF_MaybeBuiltin, {"explicit_memset"}, 3}, &CStringChecker::evalMemset},
-      {{CDF_MaybeBuiltin, {"strcpy"}, 2}, &CStringChecker::evalStrcpy},
-      {{CDF_MaybeBuiltin, {"strncpy"}, 3}, &CStringChecker::evalStrncpy},
-      {{CDF_MaybeBuiltin, {"stpcpy"}, 2}, &CStringChecker::evalStpcpy},
-      {{CDF_MaybeBuiltin, {"strlcpy"}, 3}, &CStringChecker::evalStrlcpy},
-      {{CDF_MaybeBuiltin, {"strcat"}, 2}, &CStringChecker::evalStrcat},
-      {{CDF_MaybeBuiltin, {"strncat"}, 3}, &CStringChecker::evalStrncat},
-      {{CDF_MaybeBuiltin, {"strlcat"}, 3}, &CStringChecker::evalStrlcat},
-      {{CDF_MaybeBuiltin, {"strlen"}, 1}, &CStringChecker::evalstrLength},
-      {{CDF_MaybeBuiltin, {"wcslen"}, 1}, &CStringChecker::evalstrLength},
-      {{CDF_MaybeBuiltin, {"strnlen"}, 2}, &CStringChecker::evalstrnLength},
-      {{CDF_MaybeBuiltin, {"wcsnlen"}, 2}, &CStringChecker::evalstrnLength},
-      {{CDF_MaybeBuiltin, {"strcmp"}, 2}, &CStringChecker::evalStrcmp},
-      {{CDF_MaybeBuiltin, {"strncmp"}, 3}, &CStringChecker::evalStrncmp},
-      {{CDF_MaybeBuiltin, {"strcasecmp"}, 2}, &CStringChecker::evalStrcasecmp},
-      {{CDF_MaybeBuiltin, {"strncasecmp"}, 3},
-       &CStringChecker::evalStrncasecmp},
-      {{CDF_MaybeBuiltin, {"strsep"}, 2}, &CStringChecker::evalStrsep},
-      {{CDF_MaybeBuiltin, {"bcopy"}, 3}, &CStringChecker::evalBcopy},
-      {{CDF_MaybeBuiltin, {"bcmp"}, 3},
+      {{CDM::CLibrary, {"memset"}, 3}, &CStringChecker::evalMemset},
+      {{CDM::CLibrary, {"explicit_memset"}, 3}, &CStringChecker::evalMemset},
+      {{CDM::CLibrary, {"strcpy"}, 2}, &CStringChecker::evalStrcpy},
+      {{CDM::CLibrary, {"strncpy"}, 3}, &CStringChecker::evalStrncpy},
+      {{CDM::CLibrary, {"stpcpy"}, 2}, &CStringChecker::evalStpcpy},
+      {{CDM::CLibrary, {"strlcpy"}, 3}, &CStringChecker::evalStrlcpy},
+      {{CDM::CLibrary, {"strcat"}, 2}, &CStringChecker::evalStrcat},
+      {{CDM::CLibrary, {"strncat"}, 3}, &CStringChecker::evalStrncat},
+      {{CDM::CLibrary, {"strlcat"}, 3}, &CStringChecker::evalStrlcat},
+      {{CDM::CLibrary, {"strlen"}, 1}, &CStringChecker::evalstrLength},
+      {{CDM::CLibrary, {"wcslen"}, 1}, &CStringChecker::evalstrLength},
+      {{CDM::CLibrary, {"strnlen"}, 2}, &CStringChecker::evalstrnLength},
+      {{CDM::CLibrary, {"wcsnlen"}, 2}, &CStringChecker::evalstrnLength},
+      {{CDM::CLibrary, {"strcmp"}, 2}, &CStringChecker::evalStrcmp},
+      {{CDM::CLibrary, {"strncmp"}, 3}, &CStringChecker::evalStrncmp},
+      {{CDM::CLibrary, {"strcasecmp"}, 2}, &CStringChecker::evalStrcasecmp},
+      {{CDM::CLibrary, {"strncasecmp"}, 3}, &CStringChecker::evalStrncasecmp},
+      {{CDM::CLibrary, {"strsep"}, 2}, &CStringChecker::evalStrsep},
+      {{CDM::CLibrary, {"bcopy"}, 3}, &CStringChecker::evalBcopy},
+      {{CDM::CLibrary, {"bcmp"}, 3},
        std::bind(&CStringChecker::evalMemcmp, _1, _2, _3, CK_Regular)},
-      {{CDF_MaybeBuiltin, {"bzero"}, 2}, &CStringChecker::evalBzero},
-      {{CDF_MaybeBuiltin, {"explicit_bzero"}, 2}, &CStringChecker::evalBzero},
-      {{CDF_MaybeBuiltin, {"sprintf"}, 2}, &CStringChecker::evalSprintf},
-      {{CDF_MaybeBuiltin, {"snprintf"}, 2}, &CStringChecker::evalSnprintf},
+      {{CDM::CLibrary, {"bzero"}, 2}, &CStringChecker::evalBzero},
+      {{CDM::CLibrary, {"explicit_bzero"}, 2}, &CStringChecker::evalBzero},
+      {{CDM::CLibrary, {"sprintf"}, 2}, &CStringChecker::evalSprintf},
+      {{CDM::CLibrary, {"snprintf"}, 2}, &CStringChecker::evalSnprintf},
   };
 
   // These require a bit of special handling.
diff --git a/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp b/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
index 3e5e2b9139149..01e0bed54cc6e 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
@@ -137,10 +137,7 @@ class CheckerDocumentation : public Checker< check::PreStmt,
   /// (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.
   ///
@@ -226,7 +223,7 @@ class CheckerDocumentation : public Checker< check::PreStmt,
   /// first one wins.
   ///
   /// eval::Call
-  bool evalCall(const CallExpr *CE, CheckerContext &C) const { return true; }
+  bool evalCall(const CallEvent &Call, CheckerContext &C) const { return true; }
 
   /// Handles assumptions on symbolic values.
   ///
@@ -330,5 +327,13 @@ 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/GenericTaintChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
index 4ceaf933d0bfc..4c48fdf498f7f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp
@@ -718,28 +718,24 @@ void GenericTaintChecker::initTaintRules(CheckerContext &C) const {
       {{{"isupper"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
       {{{"isxdigit"}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
 
-      {{CDF_MaybeBuiltin, {BI.getName(Builtin::BIstrncat)}},
+      {{CDM::CLibrary, {BI.getName(Builtin::BIstrncat)}},
        TR::Prop({{1, 2}}, {{0, ReturnValueIndex}})},
-      {{CDF_MaybeBuiltin, {BI.getName(Builtin::BIstrlcpy)}},
+      {{CDM::CLibrary, {BI.getName(Builtin::BIstrlcpy)}},
        TR::Prop({{1, 2}}, {{0}})},
-      {{CDF_MaybeBuiltin, {BI.getName(Builtin::BIstrlcat)}},
+      {{CDM::CLibrary, {BI.getName(Builtin::BIstrlcat)}},
        TR::Prop({{1, 2}}, {{0}})},
-      {{CDF_MaybeBuiltin, {{"snprintf"}}},
+      {{CDM::CLibrary, {{"snprintf"}}},
        TR::Prop({{1}, 3}, {{0, ReturnValueIndex}})},
-      {{CDF_MaybeBuiltin, {{"sprintf"}}},
+      {{CDM::CLibrary, {{"sprintf"}}},
        TR::Prop({{1}, 2}, {{0, ReturnValueIndex}})},
-      {{CDF_MaybeBuiltin, {{"strcpy"}}},
+      {{CDM::CLibrary, {{"strcpy"}}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})},
+      {{CDM::CLibrary, {{"stpcpy"}}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})},
+      {{CDM::CLibrary, {{"strcat"}}}, TR::Prop({{1}}, {{0, ReturnValueIndex}})},
+      {{CDM::CLibrary, {{"wcsncat"}}},
        TR::Prop({{1}}, {{0, ReturnValueIndex}})},
-      {{CDF_MaybeBuiltin, {{"stpcpy"}}},
-       TR::Prop({{1}}, {{0, ReturnValueIndex}})},
-      {{CDF_MaybeBuiltin, {{"strcat"}}},
-       TR::Prop({{1}}, {{0, ReturnValueIndex}})},
-      {{CDF_MaybeBuiltin, {{"wcsncat"}}},
-       TR::Prop({{1}}, {{0, ReturnValueIndex}})},
-      {{CDF_MaybeBuiltin, {{"strdup"}}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{CDF_MaybeBuiltin, {{"strdupa"}}},
-       TR::Prop({{0}}, {{ReturnValueIndex}})},
-      {{CDF_MaybeBuiltin, {{"wcsdup"}}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{CDM::CLibrary, {{"strdup"}}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{CDM::CLibrary, {{"strdupa"}}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
+      {{CDM::CLibrary, {{"wcsdup"}}}, TR::Prop({{0}}, {{ReturnValueIndex}})},
 
       // Sinks
       {{{"system"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
@@ -753,31 +749,29 @@ void GenericTaintChecker::initTaintRules(CheckerContext &C) const {
       {{{"execvp"}}, TR::Sink({{0, 1}}, MsgSanitizeSystemArgs)},
       {{{"execvpe"}}, TR::Sink({{0, 1, 2}}, MsgSanitizeSystemArgs)},
       {{{"dlopen"}}, TR::Sink({{0}}, MsgSanitizeSystemArgs)},
-      {{CDF_MaybeBuiltin, {{"malloc"}}}, TR::Sink({{0}}, MsgTaintedBufferSize)},
-      {{CDF_MaybeBuiltin, {{"calloc"}}}, TR::Sink({{0}}, MsgTaintedBufferSize)},
-      {{CDF_MaybeBuiltin, {{"alloca"}}}, TR::Sink({{0}}, MsgTaintedBufferSize)},
-      {{CDF_MaybeBuiltin, {{"memccpy"}}},
-       TR::Sink({{3}}, MsgTaintedBufferSize)},
-      {{CDF_MaybeBuiltin, {{"realloc"}}},
-       TR::Sink({{1}}, MsgTaintedBufferSize)},
+      {{CDM::CLibrary, {{"malloc"}}}, TR::Sink({{0}}, MsgTaintedBufferSize)},
+      {{CDM::CLibrary, {{"calloc"}}}, TR::Sink({{0}}, MsgTaintedBufferSize)},
+      {{CDM::CLibrary, {{"alloca"}}}, TR::Sink({{0}}, MsgTaintedBufferSize)},
+      {{CDM::CLibrary, {{"memccpy"}}}, TR::Sink({{3}}, MsgTaintedBufferSize)},
+      {{CDM::CLibrary, {{"realloc"}}}, TR::Sink({{1}}, MsgTaintedBufferSize)},
       {{{{"setproctitle"}}}, TR::Sink({{0}, 1}, MsgUncontrolledFormatString)},
       {{{{"setproctitle_fast"}}},
        TR::Sink({{0}, 1}, MsgUncontrolledFormatString)},
 
       // SinkProps
-      {{CDF_MaybeBuiltin, BI.getName(Builtin::BImemcpy)},
+      {{CDM::CLibrary, BI.getName(Builtin::BImemcpy)},
        TR::SinkProp({{2}}, {{1, 2}}, {{0, ReturnValueIndex}},
                     MsgTaintedBufferSize)},
-      {{CDF_MaybeBuiltin, {BI.getName(Builtin::BImemmove)}},
+      {{CDM::CLibrary, {BI.getName(Builtin::BImemmove)}},
        TR::SinkProp({{2}}, {{1, 2}}, {{0, ReturnValueIndex}},
                     MsgTaintedBufferSize)},
-      {{CDF_MaybeBuiltin, {BI.getName(Builtin::BIstrncpy)}},
+      {{CDM::CLibrary, {BI.getName(Builtin::BIstrncpy)}},
        TR::SinkProp({{2}}, {{1, 2}}, {{0, ReturnValueIndex}},
                     MsgTaintedBufferSize)},
-      {{CDF_MaybeBuiltin, {BI.getName(Builtin::BIstrndup)}},
+      {{CDM::CLibrary, {BI.getName(Builtin::BIstrndup)}},
        TR::SinkProp({{1}}, {{0, 1}}, {{ReturnValueIndex}},
                     MsgTaintedBufferSize)},
-      {{CDF_MaybeBuiltin, {{"bcopy"}}},
+      {{CDM::CLibrary, {{"bcopy"}}},
        TR::SinkProp({{2}}, {{0, 2}}, {{1}}, MsgTaintedBufferSize)}};
 
   // `getenv` returns taint only in untrusted environments.
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 79ab05f2c7866..b27ca6a449597 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -410,13 +410,13 @@ class MallocChecker
       {{{"malloc"}, 3}, &MallocChecker::checkKernelMalloc},
       {{{"calloc"}, 2}, &MallocChecker::checkCalloc},
       {{{"valloc"}, 1}, &MallocChecker::checkBasicAlloc},
-      {{CDF_MaybeBuiltin, {"strndup"}, 2}, &MallocChecker::checkStrdup},
-      {{CDF_MaybeBuiltin, {"strdup"}, 1}, &MallocChecker::checkStrdup},
+      {{CDM::CLibrary, {"strndup"}, 2}, &MallocChecker::checkStrdup},
+      {{CDM::CLibrary, {"strdup"}, 1}, &MallocChecker::checkStrdup},
       {{{"_strdup"}, 1}, &MallocChecker::checkStrdup},
       {{{"kmalloc"}, 2}, &MallocChecker::checkKernelMalloc},
       {{{"if_nameindex"}, 1}, &MallocChecker::checkIfNameIndex},
-      {{CDF_MaybeBuiltin, {"wcsdup"}, 1}, &MallocChecker::checkStrdup},
-      {{CDF_MaybeBuiltin, {"_wcsdup"}, 1}, &MallocChecker::checkStrdup},
+      {{CDM::CLibrary, {"wcsdup"}, 1}, &MallocChecker::checkStrdup},
+      {{CDM::CLibrary, {"_wcsdup"}, 1}, &MallocChecker::checkStrdup},
       {{{"g_malloc"}, 1}, &MallocChecker::checkBasicAlloc},
       {{{"g_malloc0"}, 1}, &MallocChecker::checkGMalloc0},
       {{{"g_try_malloc"}, 1}, &MallocChecker::checkBasicAlloc},
diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 65bdc4cac3094..0208f94e1b5a2 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -174,6 +174,9 @@ using FnCheck = std::function::max();
 
+const char *FeofNote = "Assuming stream reaches end-of-file here";
+const char *FerrorNote = "Assuming this stream operation fails";
+
 struct FnDescription {
   FnCheck PreFn;
   FnCheck EvalFn;
@@ -218,87 +221,6 @@ inline void assertStreamStateOpened(const StreamState *SS) {
   assert(SS->isOpened() && "Stream is expected to be opened");
 }
 
-struct StreamOperationEvaluator {
-  SValBuilder &SVB;
-  const ASTContext &ACtx;
-
-  SymbolRef StreamSym;
-  const StreamState *SS = nullptr;
-  const CallExpr *CE = nullptr;
-
-  StreamOperationEvaluator(CheckerContext &C)
-      : SVB(C.getSValBuilder()), ACtx(C.getASTContext()) {
-    ;
-  }
-
-  bool Init(const FnDescription *Desc, const CallEvent &Call, CheckerContext &C,
-            ProgramStateRef State) {
-    StreamSym = getStreamArg(Desc, Call).getAsSymbol();
-    if (!StreamSym)
-      return false;
-    SS = State->get(StreamSym);
-    if (!SS)
-      return false;
-    CE = dyn_cast_or_null(Call.getOriginExpr());
-    if (!CE)
-      return false;
-
-    assertStreamStateOpened(SS);
-
-    return true;
-  }
-
-  bool isStreamEof() const { return SS->ErrorState == ErrorFEof; }
-
-  NonLoc getZeroVal(const CallEvent &Call) {
-    return *SVB.makeZeroVal(Call.getResultType()).getAs();
-  }
-
-  ProgramStateRef setStreamState(ProgramStateRef State,
-                                 const StreamState &NewSS) {
-    return State->set(StreamSym, NewSS);
-  }
-
-  ProgramStateRef makeAndBindRetVal(ProgramStateRef State, CheckerContext &C) {
-    NonLoc RetVal = makeRetVal(C, CE).castAs();
-    return State->BindExpr(CE, C.getLocationContext(), RetVal);
-  }
-
-  ProgramStateRef bindReturnValue(ProgramStateRef State, CheckerContext &C,
-                                  uint64_t Val) {
-    return State->BindExpr(CE, C.getLocationContext(),
-                           SVB.makeIntVal(Val, CE->getCallReturnType(ACtx)));
-  }
-
-  ProgramStateRef bindReturnValue(ProgramStateRef State, CheckerContext &C,
-                                  SVal Val) {
-    return State->BindExpr(CE, C.getLocationContext(), Val);
-  }
-
-  ProgramStateRef bindNullReturnValue(ProgramStateRef State,
-                                      CheckerContext &C) {
-    return State->BindExpr(CE, C.getLocationContext(),
-                           C.getSValBuilder().makeNullWithType(CE->getType()));
-  }
-
-  ProgramStateRef assumeBinOpNN(ProgramStateRef State,
-                                BinaryOperator::Opcode Op, NonLoc LHS,
-                                NonLoc RHS) {
-    auto Cond = SVB.evalBinOpNN(State, Op, LHS, RHS, SVB.getConditionType())
-                    .getAs();
-    if (!Cond)
-      return nullptr;
-    return State->assume(*Cond, true);
-  }
-
-  ConstraintManager::ProgramStatePair
-  makeRetValAndAssumeDual(ProgramStateRef State, CheckerContext &C) {
-    DefinedSVal RetVal = makeRetVal(C, CE);
-    State = State->BindExpr(CE, C.getLocationContext(), RetVal);
-    return C.getConstraintManager().assumeDual(State, RetVal);
-  }
-};
-
 class StreamChecker : public Checker {
   BugType BT_FileNull{this, "NULL stream pointer", "Stream handling error"};
@@ -322,11 +244,59 @@ class StreamChecker : public CheckergetBT_StreamEof())
+        return "";
+
+      BR.markNotInteresting(StreamSym);
+
+      return FeofNote;
+    });
+  }
+
+  const NoteTag *constructSetErrorNoteTag(CheckerContext &C,
+                                          SymbolRef StreamSym) const {
+    return C.getNoteTag([this, StreamSym](PathSensitiveBugReport &BR) {
+      if (!BR.isInteresting(StreamSym) ||
+          &BR.getBugType() != this->getBT_IndeterminatePosition())
+        return "";
+
+      BR.markNotInteresting(StreamSym);
+
+      return FerrorNote;
+    });
+  }
+
+  const NoteTag *constructSetEofOrErrorNoteTag(CheckerContext &C,
+                                               SymbolRef StreamSym) const {
+    return C.getNoteTag([this, StreamSym](PathSensitiveBugReport &BR) {
+      if (!BR.isInteresting(StreamSym))
+        return "";
+
+      if (&BR.getBugType() == this->getBT_StreamEof()) {
+        BR.markNotInteresting(StreamSym);
+        return FeofNote;
+      }
+      if (&BR.getBugType() == this->getBT_IndeterminatePosition()) {
+        BR.markNotInteresting(StreamSym);
+        return FerrorNote;
+      }
+
+      return "";
+    });
+  }
+
   /// If true, evaluate special testing stream functions.
   bool TestMode = false;
 
-  const BugType *getBT_StreamEof() const { return &BT_StreamEof; }
-
 private:
   CallDescriptionMap FnDescriptions = {
       {{{"fopen"}, 2}, {nullptr, &StreamChecker::evalFopen, ArgNone}},
@@ -557,8 +527,8 @@ class StreamChecker : public Checker std::string {
       if (BR.isInteresting(StreamSym) && &BR.getBugType() == &BT_ResourceLeak)
@@ -567,19 +537,6 @@ class StreamChecker : public CheckergetBT_StreamEof())
-        return "";
-
-      BR.markNotInteresting(StreamSym);
-
-      return "Assuming stream reaches end-of-file here";
-    });
-  }
-
   void initMacroValues(CheckerContext &C) const {
     if (EofVal)
       return;
@@ -607,6 +564,102 @@ class StreamChecker : public Checkerget(StreamSym);
+    if (!SS)
+      return false;
+    NewES = SS->ErrorState;
+    CE = dyn_cast_or_null(Call.getOriginExpr());
+    if (!CE)
+      return false;
+
+    assertStreamStateOpened(SS);
+
+    return true;
+  }
+
+  bool isStreamEof() const { return SS->ErrorState == ErrorFEof; }
+
+  NonLoc getZeroVal(const CallEvent &Call) {
+    return *SVB.makeZeroVal(Call.getResultType()).getAs();
+  }
+
+  ProgramStateRef setStreamState(ProgramStateRef State,
+                                 const StreamState &NewSS) {
+    NewES = NewSS.ErrorState;
+    return State->set(StreamSym, NewSS);
+  }
+
+  ProgramStateRef makeAndBindRetVal(ProgramStateRef State, CheckerContext &C) {
+    NonLoc RetVal = makeRetVal(C, CE).castAs();
+    return State->BindExpr(CE, C.getLocationContext(), RetVal);
+  }
+
+  ProgramStateRef bindReturnValue(ProgramStateRef State, CheckerContext &C,
+                                  uint64_t Val) {
+    return State->BindExpr(CE, C.getLocationContext(),
+                           SVB.makeIntVal(Val, CE->getCallReturnType(ACtx)));
+  }
+
+  ProgramStateRef bindReturnValue(ProgramStateRef State, CheckerContext &C,
+                                  SVal Val) {
+    return State->BindExpr(CE, C.getLocationContext(), Val);
+  }
+
+  ProgramStateRef bindNullReturnValue(ProgramStateRef State,
+                                      CheckerContext &C) {
+    return State->BindExpr(CE, C.getLocationContext(),
+                           C.getSValBuilder().makeNullWithType(CE->getType()));
+  }
+
+  ProgramStateRef assumeBinOpNN(ProgramStateRef State,
+                                BinaryOperator::Opcode Op, NonLoc LHS,
+                                NonLoc RHS) {
+    auto Cond = SVB.evalBinOpNN(State, Op, LHS, RHS, SVB.getConditionType())
+                    .getAs();
+    if (!Cond)
+      return nullptr;
+    return State->assume(*Cond, true);
+  }
+
+  ConstraintManager::ProgramStatePair
+  makeRetValAndAssumeDual(ProgramStateRef State, CheckerContext &C) {
+    DefinedSVal RetVal = makeRetVal(C, CE);
+    State = State->BindExpr(CE, C.getLocationContext(), RetVal);
+    return C.getConstraintManager().assumeDual(State, RetVal);
+  }
+
+  const NoteTag *getFailureNoteTag(const StreamChecker *Ch, CheckerContext &C) {
+    bool SetFeof = NewES.FEof && !SS->ErrorState.FEof;
+    bool SetFerror = NewES.FError && !SS->ErrorState.FError;
+    if (SetFeof && !SetFerror)
+      return Ch->constructSetEofNoteTag(C, StreamSym);
+    if (!SetFeof && SetFerror)
+      return Ch->constructSetErrorNoteTag(C, StreamSym);
+    if (SetFeof && SetFerror)
+      return Ch->constructSetEofOrErrorNoteTag(C, StreamSym);
+    return nullptr;
+  }
+};
+
 } // end anonymous namespace
 
 const ExplodedNode *StreamChecker::getAcquisitionSite(const ExplodedNode *N,
@@ -697,7 +750,7 @@ void StreamChecker::evalFopen(const FnDescription *Desc, const CallEvent &Call,
       StateNull->set(RetSym, StreamState::getOpenFailed(Desc));
 
   C.addTransition(StateNotNull,
-                  constructNoteTag(C, RetSym, "Stream opened here"));
+                  constructLeakNoteTag(C, RetSym, "Stream opened here"));
   C.addTransition(StateNull);
 }
 
@@ -755,7 +808,7 @@ void StreamChecker::evalFreopen(const FnDescription *Desc,
       StateRetNull->set(StreamSym, StreamState::getOpenFailed(Desc));
 
   C.addTransition(StateRetNotNull,
-                  constructNoteTag(C, StreamSym, "Stream reopened here"));
+                  constructLeakNoteTag(C, StreamSym, "Stream reopened here"));
   C.addTransition(StateRetNull);
 }
 
@@ -867,10 +920,7 @@ void StreamChecker::evalFreadFwrite(const FnDescription *Desc,
   // indicator for the stream is indeterminate.
   StateFailed = E.setStreamState(
       StateFailed, StreamState::getOpened(Desc, NewES, !NewES.isFEof()));
-  if (IsFread && !E.isStreamEof())
-    C.addTransition(StateFailed, constructSetEofNoteTag(C, E.StreamSym));
-  else
-    C.addTransition(StateFailed);
+  C.addTransition(StateFailed, E.getFailureNoteTag(this, C));
 }
 
 void StreamChecker::evalFgetx(const FnDescription *Desc, const CallEvent &Call,
@@ -929,10 +979,7 @@ void StreamChecker::evalFgetx(const FnDescription *Desc, const CallEvent &Call,
       E.isStreamEof() ? ErrorFEof : ErrorFEof | ErrorFError;
   StateFailed = E.setStreamState(
       StateFailed, StreamState::getOpened(Desc, NewES, !NewES.isFEof()));
-  if (!E.isStreamEof())
-    C.addTransition(StateFailed, constructSetEofNoteTag(C, E.StreamSym));
-  else
-    C.addTransition(StateFailed);
+  C.addTransition(StateFailed, E.getFailureNoteTag(this, C));
 }
 
 void StreamChecker::evalFputx(const FnDescription *Desc, const CallEvent &Call,
@@ -974,7 +1021,7 @@ void StreamChecker::evalFputx(const FnDescription *Desc, const CallEvent &Call,
   ProgramStateRef StateFailed = E.bindReturnValue(State, C, *EofVal);
   StateFailed = E.setStreamState(
       StateFailed, StreamState::getOpened(Desc, ErrorFError, true));
-  C.addTransition(StateFailed);
+  C.addTransition(StateFailed, E.getFailureNoteTag(this, C));
 }
 
 void StreamChecker::evalFprintf(const FnDescription *Desc,
@@ -1008,7 +1055,7 @@ void StreamChecker::evalFprintf(const FnDescription *Desc,
   // position indicator for the stream is indeterminate.
   StateFailed = E.setStreamState(
       StateFailed, StreamState::getOpened(Desc, ErrorFError, true));
-  C.addTransition(StateFailed);
+  C.addTransition(StateFailed, E.getFailureNoteTag(this, C));
 }
 
 void StreamChecker::evalFscanf(const FnDescription *Desc, const CallEvent &Call,
@@ -1058,10 +1105,7 @@ void StreamChecker::evalFscanf(const FnDescription *Desc, const CallEvent &Call,
       E.isStreamEof() ? ErrorFEof : ErrorNone | ErrorFEof | ErrorFError;
   StateFailed = E.setStreamState(
       StateFailed, StreamState::getOpened(Desc, NewES, !NewES.isFEof()));
-  if (!E.isStreamEof())
-    C.addTransition(StateFailed, constructSetEofNoteTag(C, E.StreamSym));
-  else
-    C.addTransition(StateFailed);
+  C.addTransition(StateFailed, E.getFailureNoteTag(this, C));
 }
 
 void StreamChecker::evalUngetc(const FnDescription *Desc, const CallEvent &Call,
@@ -1129,10 +1173,7 @@ void StreamChecker::evalGetdelim(const FnDescription *Desc,
       E.isStreamEof() ? ErrorFEof : ErrorFEof | ErrorFError;
   StateFailed = E.setStreamState(
       StateFailed, StreamState::getOpened(Desc, NewES, !NewES.isFEof()));
-  if (E.isStreamEof())
-    C.addTransition(StateFailed, constructSetEofNoteTag(C, E.StreamSym));
-  else
-    C.addTransition(StateFailed);
+  C.addTransition(StateFailed, E.getFailureNoteTag(this, C));
 }
 
 void StreamChecker::preFseek(const FnDescription *Desc, const CallEvent &Call,
@@ -1184,7 +1225,7 @@ void StreamChecker::evalFseek(const FnDescription *Desc, const CallEvent &Call,
     NewErrS = NewErrS | ErrorFEof;
   StateFailed = E.setStreamState(StateFailed,
                                  StreamState::getOpened(Desc, NewErrS, true));
-  C.addTransition(StateFailed, constructSetEofNoteTag(C, E.StreamSym));
+  C.addTransition(StateFailed, E.getFailureNoteTag(this, C));
 }
 
 void StreamChecker::evalFgetpos(const FnDescription *Desc,
@@ -1228,7 +1269,7 @@ void StreamChecker::evalFsetpos(const FnDescription *Desc,
       StateFailed, StreamState::getOpened(Desc, ErrorNone | ErrorFError, true));
 
   C.addTransition(StateNotFailed);
-  C.addTransition(StateFailed);
+  C.addTransition(StateFailed, E.getFailureNoteTag(this, C));
 }
 
 void StreamChecker::evalFtell(const FnDescription *Desc, const CallEvent &Call,
@@ -1541,18 +1582,22 @@ ProgramStateRef StreamChecker::ensureNoFilePositionIndeterminate(
       if (!N)
         return nullptr;
 
-      C.emitReport(std::make_unique(
-          BT_IndeterminatePosition, BugMessage, N));
+      auto R = std::make_unique(
+          BT_IndeterminatePosition, BugMessage, N);
+      R->markInteresting(Sym);
+      C.emitReport(std::move(R));
       return State->set(
           Sym, StreamState::getOpened(SS->LastOperation, ErrorFEof, false));
     }
 
     // Known or unknown error state without FEOF possible.
     // Stop analysis, report error.
-    ExplodedNode *N = C.generateErrorNode(State);
-    if (N)
-      C.emitReport(std::make_unique(
-          BT_IndeterminatePosition, BugMessage, N));
+    if (ExplodedNode *N = C.generateErrorNode(State)) {
+      auto R = std::make_unique(
+          BT_IndeterminatePosition, BugMessage, N);
+      R->markInteresting(Sym);
+      C.emitReport(std::move(R));
+    }
 
     return nullptr;
   }
diff --git a/clang/lib/StaticAnalyzer/Core/CallDescription.cpp b/clang/lib/StaticAnalyzer/Core/CallDescription.cpp
index 94b2fde0a6f39..459e854cd44d9 100644
--- a/clang/lib/StaticAnalyzer/Core/CallDescription.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallDescription.cpp
@@ -35,13 +35,13 @@ static MaybeCount readRequiredParams(MaybeCount RequiredArgs,
   return std::nullopt;
 }
 
-ento::CallDescription::CallDescription(CallDescriptionFlags Flags,
+ento::CallDescription::CallDescription(Mode MatchAs,
                                        ArrayRef QualifiedName,
                                        MaybeCount RequiredArgs /*= None*/,
                                        MaybeCount RequiredParams /*= None*/)
     : RequiredArgs(RequiredArgs),
       RequiredParams(readRequiredParams(RequiredArgs, RequiredParams)),
-      Flags(Flags) {
+      MatchAs(MatchAs) {
   assert(!QualifiedName.empty());
   this->QualifiedName.reserve(QualifiedName.size());
   llvm::transform(QualifiedName, std::back_inserter(this->QualifiedName),
@@ -52,7 +52,8 @@ ento::CallDescription::CallDescription(CallDescriptionFlags Flags,
 ento::CallDescription::CallDescription(ArrayRef QualifiedName,
                                        MaybeCount RequiredArgs /*= None*/,
                                        MaybeCount RequiredParams /*= None*/)
-    : CallDescription(CDF_None, QualifiedName, RequiredArgs, RequiredParams) {}
+    : CallDescription(Mode::Unspecified, QualifiedName, RequiredArgs,
+                      RequiredParams) {}
 
 bool ento::CallDescription::matches(const CallEvent &Call) const {
   // FIXME: Add ObjC Message support.
@@ -74,14 +75,20 @@ bool ento::CallDescription::matchesAsWritten(const CallExpr &CE) const {
   return matchesImpl(FD, CE.getNumArgs(), FD->param_size());
 }
 
-bool ento::CallDescription::matchesImpl(const FunctionDecl *Callee,
-                                        size_t ArgCount,
+bool ento::CallDescription::matchesImpl(const FunctionDecl *FD, size_t ArgCount,
                                         size_t ParamCount) const {
-  const auto *FD = Callee;
   if (!FD)
     return false;
 
-  if (Flags & CDF_MaybeBuiltin) {
+  const bool isMethod = isa(FD);
+
+  if (MatchAs == Mode::SimpleFunc && isMethod)
+    return false;
+
+  if (MatchAs == Mode::CXXMethod && !isMethod)
+    return false;
+
+  if (MatchAs == Mode::CLibrary) {
     return CheckerContext::isCLibraryFunction(FD, getFunctionName()) &&
            (!RequiredArgs || *RequiredArgs <= ArgCount) &&
            (!RequiredParams || *RequiredParams <= ParamCount);
diff --git a/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp b/clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
index d3499e7a917d3..141d0cb320bff 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/Tooling/AllTUsExecution.cpp b/clang/lib/Tooling/AllTUsExecution.cpp
index f327d01399414..9cad8680447be 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/CMakeLists.txt b/clang/lib/Tooling/CMakeLists.txt
index aff39e4de13c0..91e6cbdcbc44f 100644
--- a/clang/lib/Tooling/CMakeLists.txt
+++ b/clang/lib/Tooling/CMakeLists.txt
@@ -135,4 +135,5 @@ add_clang_library(clangTooling
   clangRewrite
   clangSerialization
   clangToolingCore
+  ${LLVM_PTHREAD_LIB}
   )
diff --git a/clang/test/AST/Interp/arrays.cpp b/clang/test/AST/Interp/arrays.cpp
index e1af2e80e3ad7..4b112d7fdddfd 100644
--- a/clang/test/AST/Interp/arrays.cpp
+++ b/clang/test/AST/Interp/arrays.cpp
@@ -138,6 +138,8 @@ constexpr int dependent[4] = {
 static_assert(dependent[2] == dependent[0], "");
 static_assert(dependent[3] == dependent[1], "");
 
+union { char x[]; } r = {0};
+
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wc99-extensions"
 #pragma clang diagnostic ignored "-Winitializer-overrides"
@@ -564,3 +566,8 @@ namespace LocalVLA {
 #endif
   }
 }
+
+char melchizedek[2200000000];
+typedef decltype(melchizedek[1] - melchizedek[0]) ptrdiff_t;
+constexpr ptrdiff_t d1 = &melchizedek[0x7fffffff] - &melchizedek[0]; // ok
+constexpr ptrdiff_t d3 = &melchizedek[0] - &melchizedek[0x80000000u]; // ok
diff --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/Interp/builtin-functions.cpp
index 3701106e02f05..ab8abac4b36e3 100644
--- a/clang/test/AST/Interp/builtin-functions.cpp
+++ b/clang/test/AST/Interp/builtin-functions.cpp
@@ -34,6 +34,14 @@ namespace strcmp {
   static_assert(__builtin_strcmp(kFoobar, kFoobazfoobar + 6) == 0, ""); // both-error {{not an integral constant}} \
                                                                         // both-note {{dereferenced one-past-the-end}} \
                                                                         // expected-note {{in call to}}
+
+  /// Used to assert because we're passing a dummy pointer to
+  /// __builtin_strcmp() when evaluating the return statement.
+  constexpr bool char_memchr_mutable() {
+    char buffer[] = "mutable";
+    return __builtin_strcmp(buffer, "mutable") == 0;
+  }
+  static_assert(char_memchr_mutable(), "");
 }
 
 /// Copied from constant-expression-cxx11.cpp
diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c
index 2a72c24b43d1c..a5270172cfc7b 100644
--- a/clang/test/AST/Interp/c.c
+++ b/clang/test/AST/Interp/c.c
@@ -33,15 +33,15 @@ const int b = 3;
 _Static_assert(b == 3, ""); // pedantic-ref-warning {{not an integer constant expression}} \
                             // pedantic-expected-warning {{not an integer constant expression}}
 
-/// FIXME: The new interpreter is missing the "initializer of 'c' unknown" diagnostics.
-const int c; // ref-note {{declared here}} \
-             // pedantic-ref-note {{declared here}}
+const int c; // all-note {{declared here}}
 _Static_assert(c == 0, ""); // ref-error {{not an integral constant expression}} \
                             // ref-note {{initializer of 'c' is unknown}} \
                             // pedantic-ref-error {{not an integral constant expression}} \
                             // pedantic-ref-note {{initializer of 'c' is unknown}} \
                             // expected-error {{not an integral constant expression}} \
-                            // pedantic-expected-error {{not an integral constant expression}}
+                            // expected-note {{initializer of 'c' is unknown}} \
+                            // pedantic-expected-error {{not an integral constant expression}} \
+                            // pedantic-expected-note {{initializer of 'c' is unknown}}
 
 _Static_assert(&c != 0, ""); // ref-warning {{always true}} \
                              // pedantic-ref-warning {{always true}} \
@@ -95,7 +95,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.cpp b/clang/test/AST/Interp/complex.cpp
index b6091d90867a0..8acce7b734d85 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,16 @@ 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}}
+}
diff --git a/clang/test/AST/Interp/cxx11.cpp b/clang/test/AST/Interp/cxx11.cpp
index 0a1e0f3fd28e9..993e3618a3784 100644
--- a/clang/test/AST/Interp/cxx11.cpp
+++ b/clang/test/AST/Interp/cxx11.cpp
@@ -22,3 +22,11 @@ int array2[recurse2]; // both-warning {{variable length arrays in C++}} \
                       // both-note {{initializer of 'recurse2' is not a constant expression}} \
                       // expected-error {{variable length array declaration not allowed at file scope}} \
                       // ref-warning {{variable length array folded to constant array as an extension}}
+
+struct S {
+  int m;
+};
+constexpr S s = { 5 };
+constexpr const int *p = &s.m + 1;
+
+constexpr const int *np2 = &(*(int(*)[4])nullptr)[0]; // ok
diff --git a/clang/test/AST/Interp/cxx20.cpp b/clang/test/AST/Interp/cxx20.cpp
index 2c28e53784c5c..000ffe39eb94a 100644
--- a/clang/test/AST/Interp/cxx20.cpp
+++ b/clang/test/AST/Interp/cxx20.cpp
@@ -765,3 +765,12 @@ namespace FailingDestructor {
     f(); // both-error {{no matching function}}
   }
 }
+
+
+void overflowInSwitchCase(int n) {
+  switch (n) {
+  case (int)(float)1e300: // both-error {{constant expression}} \
+                          // both-note {{value +Inf is outside the range of representable values of type 'int'}}
+    break;
+  }
+}
diff --git a/clang/test/AST/Interp/cxx98.cpp b/clang/test/AST/Interp/cxx98.cpp
index 1acc74a8290a0..73e4537206633 100644
--- a/clang/test/AST/Interp/cxx98.cpp
+++ b/clang/test/AST/Interp/cxx98.cpp
@@ -18,12 +18,13 @@ template struct C;
 
 /// FIXME: This example does not get properly diagnosed in the new interpreter.
 extern const int recurse1;
-const int recurse2 = recurse1; // ref-note {{here}}
+const int recurse2 = recurse1; // both-note {{declared here}}
 const int recurse1 = 1;
 int array1[recurse1];
 int array2[recurse2]; // ref-warning 2{{variable length array}} \
                       // ref-note {{initializer of 'recurse2' is not a constant expression}} \
                       // expected-warning {{variable length array}} \
+                      // expected-note {{read of non-const variable 'recurse2'}} \
                       // expected-error {{variable length array}}
 
 int NCI; // both-note {{declared here}}
diff --git a/clang/test/AST/Interp/functions.cpp b/clang/test/AST/Interp/functions.cpp
index 9daf8722050f0..67fd9036d81e7 100644
--- a/clang/test/AST/Interp/functions.cpp
+++ b/clang/test/AST/Interp/functions.cpp
@@ -555,3 +555,23 @@ namespace Local {
     return t;
   }
 }
+
+namespace VariadicOperator {
+  struct Callable {
+    float& operator()(...);
+  };
+
+  void test_callable(Callable c) {
+    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/lambda.cpp b/clang/test/AST/Interp/lambda.cpp
index a5e0d0f1fd9f4..d056bb304eeb3 100644
--- a/clang/test/AST/Interp/lambda.cpp
+++ b/clang/test/AST/Interp/lambda.cpp
@@ -235,3 +235,16 @@ namespace LambdaToAPValue {
     static_assert(g() == f(), "");
   }
 }
+
+namespace ns2_capture_this_byval {
+  struct S {
+    int s;
+    constexpr S(int s) : s{s} { }
+    constexpr auto f(S o) {
+      return [*this,o] (auto a) { return s + o.s + a.s; };
+    }
+  };
+
+  constexpr auto L = S{5}.f(S{10});
+  static_assert(L(S{100}) == 115, "");
+} // end test_captures_1::ns2_capture_this_byval
diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index 8ea1c1155143e..d86609108ca44 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -1131,3 +1131,47 @@ namespace nullptrsub {
     f = (char *)((char *)0 - (char *)0);
   }
 }
+
+namespace incdecbool {
+#if __cplusplus >= 201402L
+  constexpr bool incb(bool c) {
+    if (!c)
+      ++c;
+    else {++c; c++; }
+#if __cplusplus >= 202002L
+    // both-error@-3 {{ISO C++17 does not allow incrementing expression of type bool}}
+    // both-error@-3 2{{ISO C++17 does not allow incrementing expression of type bool}}
+#else
+    // both-warning@-6 {{incrementing expression of type bool is deprecated and incompatible with C++17}}
+#endif
+    return c;
+  }
+  static_assert(incb(false), "");
+  static_assert(incb(true), "");
+  static_assert(incb(true) == 1, "");
+#endif
+
+
+#if __cplusplus == 201103L
+  constexpr bool foo() { // both-error {{never produces a constant expression}}
+    bool b = true; // both-warning {{variable declaration in a constexpr function is a C++14 extension}}
+    b++; // both-warning {{incrementing expression of type bool is deprecated and incompatible with C++17}} \
+         // both-warning {{use of this statement in a constexpr function is a C++14 extension}} \
+         // both-note 2{{subexpression not valid in a constant expression}}
+
+    return b;
+  }
+  static_assert(foo() == 1, ""); // both-error {{not an integral constant expression}} \
+                                 // both-note {{in call to}}
+#endif
+
+
+
+}
+
+#if __cplusplus >= 201402L
+constexpr int externvar1() { // both-error {{never produces a constant expression}}
+  extern char arr[]; // both-note {{declared here}}
+  return arr[0]; // both-note {{read of non-constexpr variable 'arr'}}
+}
+#endif
diff --git a/clang/test/Analysis/analyzer-config.c b/clang/test/Analysis/analyzer-config.c
index 373017f4b18bf..2167a2b32f596 100644
--- a/clang/test/Analysis/analyzer-config.c
+++ b/clang/test/Analysis/analyzer-config.c
@@ -129,7 +129,7 @@
 // CHECK-NEXT: unix.DynamicMemoryModeling:Optimistic = false
 // CHECK-NEXT: unix.Errno:AllowErrnoReadOutsideConditionExpressions = true
 // CHECK-NEXT: unix.StdCLibraryFunctions:DisplayLoadedSummaries = false
-// CHECK-NEXT: unix.StdCLibraryFunctions:ModelPOSIX = false
+// CHECK-NEXT: unix.StdCLibraryFunctions:ModelPOSIX = true
 // CHECK-NEXT: unroll-loops = false
 // CHECK-NEXT: verbose-report-filename = false
 // CHECK-NEXT: widen-loops = false
diff --git a/clang/test/Analysis/stack-addr-ps.c b/clang/test/Analysis/stack-addr-ps.c
index 26e1cc58350ca..e469396e1bb22 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/std-c-library-functions.c b/clang/test/Analysis/std-c-library-functions.c
index e6564e2bae761..b03a1a5656517 100644
--- a/clang/test/Analysis/std-c-library-functions.c
+++ b/clang/test/Analysis/std-c-library-functions.c
@@ -3,6 +3,7 @@
 // RUN:   -analyzer-checker=unix.StdCLibraryFunctions \
 // RUN:   -analyzer-checker=debug.ExprInspection \
 // RUN:   -analyzer-config eagerly-assume=false \
+// RUN:   -analyzer-config unix.StdCLibraryFunctions:ModelPOSIX=false \
 // RUN:   -triple i686-unknown-linux \
 // RUN:   -verify
 
@@ -11,6 +12,7 @@
 // RUN:   -analyzer-checker=unix.StdCLibraryFunctions \
 // RUN:   -analyzer-checker=debug.ExprInspection \
 // RUN:   -analyzer-config eagerly-assume=false \
+// RUN:   -analyzer-config unix.StdCLibraryFunctions:ModelPOSIX=false \
 // RUN:   -triple x86_64-unknown-linux \
 // RUN:   -verify
 
@@ -19,6 +21,7 @@
 // RUN:   -analyzer-checker=unix.StdCLibraryFunctions \
 // RUN:   -analyzer-checker=debug.ExprInspection \
 // RUN:   -analyzer-config eagerly-assume=false \
+// RUN:   -analyzer-config unix.StdCLibraryFunctions:ModelPOSIX=false \
 // RUN:   -triple armv7-a15-linux \
 // RUN:   -verify
 
@@ -27,6 +30,7 @@
 // RUN:   -analyzer-checker=unix.StdCLibraryFunctions \
 // RUN:   -analyzer-checker=debug.ExprInspection \
 // RUN:   -analyzer-config eagerly-assume=false \
+// RUN:   -analyzer-config unix.StdCLibraryFunctions:ModelPOSIX=false \
 // RUN:   -triple thumbv7-a15-linux \
 // RUN:   -verify
 
@@ -36,6 +40,7 @@
 // RUN:   -analyzer-config unix.StdCLibraryFunctions:DisplayLoadedSummaries=true \
 // RUN:   -analyzer-checker=debug.ExprInspection \
 // RUN:   -analyzer-config eagerly-assume=false \
+// RUN:   -analyzer-config unix.StdCLibraryFunctions:ModelPOSIX=false \
 // RUN:   -triple i686-unknown-linux 2>&1 | FileCheck %s
 
 //      CHECK: Loaded summary for: int isalnum(int)
diff --git a/clang/test/Analysis/stream-note.c b/clang/test/Analysis/stream-note.c
index abb4784c078aa..f77cd4aa62841 100644
--- a/clang/test/Analysis/stream-note.c
+++ b/clang/test/Analysis/stream-note.c
@@ -166,3 +166,70 @@ void check_eof_notes_feof_or_no_error(void) {
   }
   fclose(F);
 }
+
+void check_indeterminate_notes(void) {
+  FILE *F;
+  F = fopen("foo1.c", "r");
+  if (F == NULL)     // expected-note {{Taking false branch}} \
+                     // expected-note {{'F' is not equal to NULL}}
+    return;
+  int R = fgetc(F);  // no note
+  if (R >= 0) {      // expected-note {{Taking true branch}} \
+                     // expected-note {{'R' is >= 0}}
+    fgetc(F);        // expected-note {{Assuming this stream operation fails}}
+    if (ferror(F))   // expected-note {{Taking true branch}}
+      fgetc(F);      // expected-warning {{File position of the stream might be 'indeterminate' after a failed operation. Can cause undefined behavior}} \
+                     // expected-note {{File position of the stream might be 'indeterminate' after a failed operation. Can cause undefined behavior}}
+  }
+  fclose(F);
+}
+
+void check_indeterminate_after_clearerr(void) {
+  FILE *F;
+  char Buf[10];
+  F = fopen("foo1.c", "r");
+  if (F == NULL)          // expected-note {{Taking false branch}} \
+                          // expected-note {{'F' is not equal to NULL}}
+    return;
+  fread(Buf, 1, 1, F);    // expected-note {{Assuming this stream operation fails}}
+  if (ferror(F)) {        // expected-note {{Taking true branch}}
+    clearerr(F);
+    fread(Buf, 1, 1, F);  // expected-warning {{might be 'indeterminate' after a failed operation}} \
+                          // expected-note {{might be 'indeterminate' after a failed operation}}
+  }
+  fclose(F);
+}
+
+void check_indeterminate_eof(void) {
+  FILE *F;
+  char Buf[2];
+  F = fopen("foo1.c", "r");
+  if (F == NULL)               // expected-note {{Taking false branch}} \
+                               // expected-note {{'F' is not equal to NULL}} \
+                               // expected-note {{Taking false branch}} \
+                               // expected-note {{'F' is not equal to NULL}}
+    return;
+  fgets(Buf, sizeof(Buf), F);  // expected-note {{Assuming this stream operation fails}} \
+                               // expected-note {{Assuming stream reaches end-of-file here}}
+
+  fgets(Buf, sizeof(Buf), F);  // expected-warning {{might be 'indeterminate'}} \
+                               // expected-note {{might be 'indeterminate'}} \
+                               // expected-warning {{stream is in EOF state}} \
+                               // expected-note {{stream is in EOF state}}
+  fclose(F);
+}
+
+void check_indeterminate_fseek(void) {
+  FILE *F = fopen("file", "r");
+  if (!F)                           // expected-note {{Taking false branch}} \
+                                    // expected-note {{'F' is non-null}}
+    return;
+  int Ret = fseek(F, 1, SEEK_SET);  // expected-note {{Assuming this stream operation fails}}
+  if (Ret) {                        // expected-note {{Taking true branch}} \
+                                    // expected-note {{'Ret' is not equal to 0}}
+    char Buf[2];
+    fwrite(Buf, 1, 2, F);           // expected-warning {{might be 'indeterminate'}} \
+                                    // expected-note {{might be 'indeterminate'}}
+  }
+  fclose(F);
+}
diff --git a/clang/test/C/C2x/n3018.c b/clang/test/C/C2x/n3018.c
new file mode 100644
index 0000000000000..0d54d53b7499f
--- /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 d9c1fbe4ee40a..c93cfb63d604c 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 9c8d77518ab55..1b68b65acca6a 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/drs/dr18xx.cpp b/clang/test/CXX/drs/dr18xx.cpp
index a7cee4ef8902f..e78730e8992cf 100644
--- a/clang/test/CXX/drs/dr18xx.cpp
+++ b/clang/test/CXX/drs/dr18xx.cpp
@@ -282,6 +282,7 @@ namespace dr1837 { // dr1837: 3.3
   struct A {
     int f();
     bool b = [] {
+      // since-cxx11-warning@-1 {{address of lambda function pointer conversion operator will always evaluate to 'true'}}
       struct Local {
         static_assert(sizeof(this->f()) == sizeof(int), "");
       };
diff --git a/clang/test/CXX/drs/dr438.cpp b/clang/test/CXX/drs/dr438.cpp
new file mode 100644
index 0000000000000..a6ed39b88c242
--- /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 0000000000000..46960af93bb9a
--- /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 0000000000000..6504bba689d22
--- /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 0000000000000..2b268778ea10d
--- /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 0000000000000..f53f1cb541240
--- /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 612a152aec4c4..343c4ee6f3344 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/expr/expr.prim/expr.prim.lambda/blocks.mm b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm
index cb56f6816ad03..e93c37f3b9ae1 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.mm
@@ -65,10 +65,10 @@ void nesting() {
 
 namespace overloading {
   void bool_conversion() {
-    if ([](){}) {
+    if ([](){}) { // expected-warning{{address of lambda function pointer conversion operator will always evaluate to 'true'}}
     }
 
-    bool b = []{};
+    bool b = []{}; // expected-warning{{address of lambda function pointer conversion operator will always evaluate to 'true'}}
     b = (bool)[]{};
   }
 
@@ -108,8 +108,9 @@ void call_with_lambda() {
     using decltype(a)::operator id; // expected-note {{here}}
   } extern d;
 
-  bool r1 = c;
-  bool r2 = d; // expected-error {{private}}
+  bool r1 = c; // expected-warning{{address of lambda function pointer conversion operator will always evaluate to 'true'}}
+  bool r2 = d; // expected-error {{private}} \
+                  expected-warning{{address of lambda function pointer conversion operator will always evaluate to 'true'}}
 }
 
 namespace PR13117 {
diff --git a/clang/test/CXX/temp/temp.res/temp.local/p6.cpp b/clang/test/CXX/temp/temp.res/temp.local/p6.cpp
index e2aa0ff344291..00bb35813c39a 100644
--- a/clang/test/CXX/temp/temp.res/temp.local/p6.cpp
+++ b/clang/test/CXX/temp/temp.res/temp.local/p6.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -verify %s -fcxx-exceptions -std=c++1y
+// RUN: %clang_cc1 -verify %s -fcxx-exceptions -std=c++1y -Wno-error=strict-primary-template-shadow
 
 namespace N {}
 
@@ -127,16 +127,30 @@ template struct Z { // expected-note 16{{declared here}}
 template // expected-note {{declared here}}
 void f(int T) {} // expected-error {{declaration of 'T' shadows template parameter}}
 
-// FIXME: These are ill-formed: a template-parameter shall not have the same name as the template name.
 namespace A {
   template struct T {};  // expected-error{{declaration of 'T' shadows template parameter}}
                                      // expected-note@-1{{template parameter is declared here}}
+  template struct U {
+    template struct V {}; // expected-error{{declaration of 'V' shadows template parameter}}
+                                      // expected-note@-1{{template parameter is declared here}}
+  };
 }
 namespace B {
-  template void T() {}
+  template void T() {} // expected-warning{{declaration of 'T' shadows template parameter}}
+                                   // expected-note@-1{{template parameter is declared here}}
+
+  template struct U {
+    template void V(); // expected-warning{{declaration of 'V' shadows template parameter}}
+                                   // expected-note@-1{{template parameter is declared here}}
+  };
 }
 namespace C {
-  template int T;
+  template int T; // expected-warning{{declaration of 'T' shadows template parameter}}
+                              // expected-note@-1{{template parameter is declared here}}
+  template struct U {
+    template static int V; // expected-warning{{declaration of 'V' shadows template parameter}}
+                                       // expected-note@-1{{template parameter is declared here}}
+  };
 }
 
 namespace PR28023 {
diff --git a/clang/test/CodeGen/LoongArch/intrinsic-la32.c b/clang/test/CodeGen/LoongArch/intrinsic-la32.c
index 93d54f511a9cd..eb3f8cbe7ac4c 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 a740882eef541..50ec358f546ec 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/PowerPC/aix-tls-model.cpp b/clang/test/CodeGen/PowerPC/aix-tls-model.cpp
index 9fdd6855a89ee..cd0a08aa9a3b7 100644
--- a/clang/test/CodeGen/PowerPC/aix-tls-model.cpp
+++ b/clang/test/CodeGen/PowerPC/aix-tls-model.cpp
@@ -1,11 +1,11 @@
 // RUN: %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-GD
 // RUN: %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -ftls-model=global-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-GD
-// RUN: not %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -ftls-model=local-dynamic -emit-llvm 2>&1 | FileCheck %s -check-prefix=CHECK-LD-ERROR
+// RUN: %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -ftls-model=local-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-LD
 // RUN: %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -ftls-model=initial-exec -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-IE
 // RUN: %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -ftls-model=local-exec -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-LE
 // RUN: %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-GD
 // RUN: %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -ftls-model=global-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-GD
-// RUN: not %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -ftls-model=local-dynamic -emit-llvm 2>&1 | FileCheck %s -check-prefix=CHECK-LD-ERROR
+// RUN: %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -ftls-model=local-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-LD
 // RUN: %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -ftls-model=initial-exec -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-IE
 // RUN: %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -ftls-model=local-exec -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-LE
 
@@ -21,7 +21,10 @@ int f() {
 // CHECK-GD: @z2 ={{.*}} global i32 0
 // CHECK-GD: @x ={{.*}} thread_local global i32 0
 // CHECK-GD: @_ZZ1fvE1y = internal thread_local global i32 0
-// CHECK-LD-ERROR:  error: TLS model 'local-dynamic' is not yet supported on AIX
+// CHECK-LD: @z1 ={{.*}} global i32 0
+// CHECK-LD: @z2 ={{.*}} global i32 0
+// CHECK-LD: @x ={{.*}} thread_local(localdynamic) global i32 0
+// CHECK-LD: @_ZZ1fvE1y = internal thread_local(localdynamic) global i32 0
 // CHECK-IE: @z1 ={{.*}} global i32 0
 // CHECK-IE: @z2 ={{.*}} global i32 0
 // CHECK-IE: @x ={{.*}} thread_local(initialexec) global i32 0
diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-rotate.c b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-rotate.c
index d96bfb4621421..b218547c00d93 100644
--- a/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-rotate.c
+++ b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-rotate.c
@@ -16,11 +16,8 @@ void test_builtin_ppc_rldimi() {
   // CHECK:       %res = alloca i64, align 8
   // CHECK-NEXT:  [[RA:%[0-9]+]] = load i64, ptr @ull, align 8
   // CHECK-NEXT:  [[RB:%[0-9]+]] = load i64, ptr @ull, align 8
-  // CHECK-NEXT:  [[RC:%[0-9]+]] = call i64 @llvm.fshl.i64(i64 [[RA]], i64 [[RA]], i64 63)
-  // CHECK-NEXT:  [[RD:%[0-9]+]] = and i64 [[RC]], 72057593769492480
-  // CHECK-NEXT:  [[RE:%[0-9]+]] = and i64 [[RB]], -72057593769492481
-  // CHECK-NEXT:  [[RF:%[0-9]+]] = or i64 [[RD]], [[RE]]
-  // CHECK-NEXT:  store i64 [[RF]], ptr %res, align 8
+  // CHECK-NEXT:  [[RC:%[0-9]+]] = call i64 @llvm.ppc.rldimi(i64 [[RA]], i64 [[RB]], i32 63, i64 72057593769492480)
+  // CHECK-NEXT:  store i64 [[RC]], ptr %res, align 8
   // CHECK-NEXT:  ret void
 
   /*shift = 63, mask = 0x00FFFFFFF0000000 = 72057593769492480, ~mask = 0xFF0000000FFFFFFF = -72057593769492481*/
@@ -32,11 +29,8 @@ void test_builtin_ppc_rlwimi() {
   // CHECK:       %res = alloca i32, align 4
   // CHECK-NEXT:  [[RA:%[0-9]+]] = load i32, ptr @ui, align 4
   // CHECK-NEXT:  [[RB:%[0-9]+]] = load i32, ptr @ui, align 4
-  // CHECK-NEXT:  [[RC:%[0-9]+]] = call i32 @llvm.fshl.i32(i32 [[RA]], i32 [[RA]], i32 31)
-  // CHECK-NEXT:  [[RD:%[0-9]+]] = and i32 [[RC]], 16776960
-  // CHECK-NEXT:  [[RE:%[0-9]+]] = and i32 [[RB]], -16776961
-  // CHECK-NEXT:  [[RF:%[0-9]+]] = or i32 [[RD]], [[RE]]
-  // CHECK-NEXT:  store i32 [[RF]], ptr %res, align 4
+  // CHECK-NEXT:  [[RC:%[0-9]+]] = call i32 @llvm.ppc.rlwimi(i32 [[RA]], i32 [[RB]], i32 31, i32 16776960)
+  // CHECK-NEXT:  store i32 [[RC]], ptr %res, align 4
   // CHECK-NEXT:  ret void
 
   /*shift = 31, mask = 0xFFFF00 = 16776960, ~mask = 0xFFFFFFFFFF0000FF = -16776961*/
@@ -47,9 +41,8 @@ void test_builtin_ppc_rlwnm() {
   // CHECK-LABEL: test_builtin_ppc_rlwnm
   // CHECK:       %res = alloca i32, align 4
   // CHECK-NEXT:  [[RA:%[0-9]+]] = load i32, ptr @ui, align 4
-  // CHECK-NEXT:  [[RB:%[0-9]+]] = call i32 @llvm.fshl.i32(i32 [[RA]], i32 [[RA]], i32 31)
-  // CHECK-NEXT:  [[RC:%[0-9]+]] = and i32 [[RB]], 511
-  // CHECK-NEXT:  store i32 [[RC]], ptr %res, align 4
+  // CHECK-NEXT:  [[RB:%[0-9]+]] = call i32 @llvm.ppc.rlwnm(i32 [[RA]], i32 31, i32 511)
+  // CHECK-NEXT:  store i32 [[RB]], ptr %res, align 4
   // CHECK-NEXT:  ret void
 
   /*shift = 31, mask = 0x1FF = 511*/
@@ -63,9 +56,8 @@ void test_builtin_ppc_rlwnm2(unsigned int shift) {
   // CHECK-NEXT:  store i32 %shift, ptr %shift.addr, align 4
   // CHECK-NEXT:  [[RA:%[0-9]+]] = load i32, ptr @ui, align 4
   // CHECK-NEXT:  [[RB:%[0-9]+]] = load i32, ptr %shift.addr, align 4
-  // CHECK-NEXT:  [[RC:%[0-9]+]] = call i32 @llvm.fshl.i32(i32 [[RA]], i32 [[RA]], i32 [[RB]])
-  // CHECK-NEXT:  [[RD:%[0-9]+]] = and i32 [[RC]], 511
-  // CHECK-NEXT:  store i32 [[RD]], ptr %res, align 4
+  // CHECK-NEXT:  [[RC:%[0-9]+]] = call i32 @llvm.ppc.rlwnm(i32 [[RA]], i32 [[RB]], i32 511)
+  // CHECK-NEXT:  store i32 [[RC]], ptr %res, align 4
   // CHECK-NEXT:  ret void
 
   /*mask = 0x1FF = 511*/
diff --git a/clang/test/CodeGen/aarch64-cpu-supports.c b/clang/test/CodeGen/aarch64-cpu-supports.c
index 872fec6827ef1..c54b7475a3fd5 100644
--- a/clang/test/CodeGen/aarch64-cpu-supports.c
+++ b/clang/test/CodeGen/aarch64-cpu-supports.c
@@ -34,6 +34,11 @@
 // CHECK-NEXT:    store i32 3, ptr [[RETVAL]], align 4
 // CHECK-NEXT:    br label [[RETURN]]
 // CHECK:       if.end4:
+// CHECK-NEXT:    br i1 false, label [[IF_THEN5:%.*]], label [[IF_END6:%.*]]
+// CHECK:       if.then5:
+// CHECK-NEXT:    store i32 4, ptr [[RETVAL]], align 4
+// CHECK-NEXT:    br label [[RETURN]]
+// CHECK:       if.end6:
 // CHECK-NEXT:    store i32 0, ptr [[RETVAL]], align 4
 // CHECK-NEXT:    br label [[RETURN]]
 // CHECK:       return:
@@ -50,5 +55,8 @@ int main(void) {
   if (__builtin_cpu_supports("sme2+ls64_v+wfxt"))
     return 3;
 
+  if (__builtin_cpu_supports("avx2"))
+    return 4;
+
   return 0;
 }
diff --git a/clang/test/CodeGen/attr-target-clones-aarch64.c b/clang/test/CodeGen/attr-target-clones-aarch64.c
index 5ea3f4a9b0b11..276a7b87b7a1b 100644
--- a/clang/test/CodeGen/attr-target-clones-aarch64.c
+++ b/clang/test/CodeGen/attr-target-clones-aarch64.c
@@ -43,7 +43,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
 // CHECK: @ftc_inline3 = weak_odr ifunc i32 (), ptr @ftc_inline3.resolver
 //.
 // CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: @ftc._MlseMaes(
+// CHECK-LABEL: @ftc._MaesMlse(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 0
 //
@@ -69,7 +69,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
 // CHECK-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
 // CHECK-NEXT:    br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
 // CHECK:       resolver_return:
-// CHECK-NEXT:    ret ptr @ftc._MlseMaes
+// CHECK-NEXT:    ret ptr @ftc._MaesMlse
 // CHECK:       resolver_else:
 // CHECK-NEXT:    [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
 // CHECK-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 68719476736
@@ -89,7 +89,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: @ftc_def._Msha2Mmemtag2(
+// CHECK-LABEL: @ftc_def._Mmemtag2Msha2(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 1
 //
@@ -109,7 +109,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
 // CHECK-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
 // CHECK-NEXT:    br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
 // CHECK:       resolver_return:
-// CHECK-NEXT:    ret ptr @ftc_def._Msha2Mmemtag2
+// CHECK-NEXT:    ret ptr @ftc_def._Mmemtag2Msha2
 // CHECK:       resolver_else:
 // CHECK-NEXT:    [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
 // CHECK-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 4096
@@ -155,7 +155,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: @ftc_dup2._MdotprodMcrc(
+// CHECK-LABEL: @ftc_dup2._McrcMdotprod(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 3
 //
@@ -175,7 +175,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
 // CHECK-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
 // CHECK-NEXT:    br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
 // CHECK:       resolver_return:
-// CHECK-NEXT:    ret ptr @ftc_dup2._MdotprodMcrc
+// CHECK-NEXT:    ret ptr @ftc_dup2._McrcMdotprod
 // CHECK:       resolver_else:
 // CHECK-NEXT:    [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
 // CHECK-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 256
@@ -239,7 +239,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
 // CHECK-NEXT:    [[TMP7:%.*]] = and i1 true, [[TMP6]]
 // CHECK-NEXT:    br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
 // CHECK:       resolver_return1:
-// CHECK-NEXT:    ret ptr @ftc_inline1._MrcpcMpredres
+// CHECK-NEXT:    ret ptr @ftc_inline1._MpredresMrcpc
 // CHECK:       resolver_else2:
 // CHECK-NEXT:    [[TMP8:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
 // CHECK-NEXT:    [[TMP9:%.*]] = and i64 [[TMP8]], 513
@@ -283,7 +283,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
 // CHECK-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
 // CHECK-NEXT:    br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
 // CHECK:       resolver_return:
-// CHECK-NEXT:    ret ptr @ftc_inline3._MsveMsb
+// CHECK-NEXT:    ret ptr @ftc_inline3._MsbMsve
 // CHECK:       resolver_else:
 // CHECK-NEXT:    [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
 // CHECK-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 1125899906842624
@@ -303,7 +303,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: @ftc_inline1._MrcpcMpredres(
+// CHECK-LABEL: @ftc_inline1._MpredresMrcpc(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 1
 //
@@ -345,7 +345,7 @@ inline int __attribute__((target_clones("fp16", "sve2-bitperm+fcma", "default"))
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: @ftc_inline3._MsveMsb(
+// CHECK-LABEL: @ftc_inline3._MsbMsve(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 3
 //
diff --git a/clang/test/CodeGen/attr-target-version.c b/clang/test/CodeGen/attr-target-version.c
index c27d48f3ecf68..56a42499d0a7c 100644
--- a/clang/test/CodeGen/attr-target-version.c
+++ b/clang/test/CodeGen/attr-target-version.c
@@ -25,7 +25,7 @@ int foo() {
 }
 
 inline int __attribute__((target_version("sha1+pmull+f64mm"))) fmv_inline(void) { return 1; }
-inline int __attribute__((target_version("fp16+fcma+sme+ fp16 "))) fmv_inline(void) { return 2; }
+inline int __attribute__((target_version("fp16+fcma+rdma+sme+ fp16 "))) fmv_inline(void) { return 2; }
 inline int __attribute__((target_version("sha3+i8mm+f32mm"))) fmv_inline(void) { return 12; }
 inline int __attribute__((target_version("dit+sve-ebf16"))) fmv_inline(void) { return 8; }
 inline int __attribute__((target_version("dpb+rcpc2 "))) fmv_inline(void) { return 6; }
@@ -106,14 +106,14 @@ int hoo(void) {
 // CHECK: @fmv_c = weak_odr ifunc void (), ptr @fmv_c.resolver
 //.
 // CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: define {{[^@]+}}@fmv._MrngMflagmMfp16fml
+// CHECK-LABEL: define {{[^@]+}}@fmv._MflagmMfp16fmlMrng
 // CHECK-SAME: () #[[ATTR0:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 1
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: define {{[^@]+}}@fmv_one._MsimdMls64
+// CHECK-LABEL: define {{[^@]+}}@fmv_one._Mls64Msimd
 // CHECK-SAME: () #[[ATTR1:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 1
@@ -147,7 +147,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._MrngMflagmMfp16fml
+// CHECK-NEXT:    ret ptr @fmv._MflagmMfp16fmlMrng
 // CHECK:       resolver_else:
 // CHECK-NEXT:    [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
 // CHECK-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 72057594037927940
@@ -187,7 +187,7 @@ int hoo(void) {
 // CHECK-NEXT:    [[TMP23:%.*]] = and i1 true, [[TMP22]]
 // CHECK-NEXT:    br i1 [[TMP23]], label [[RESOLVER_RETURN9:%.*]], label [[RESOLVER_ELSE10:%.*]]
 // CHECK:       resolver_return9:
-// CHECK-NEXT:    ret ptr @fmv._MfpMaes
+// CHECK-NEXT:    ret ptr @fmv._MaesMfp
 // CHECK:       resolver_else10:
 // CHECK-NEXT:    [[TMP24:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
 // CHECK-NEXT:    [[TMP25:%.*]] = and i64 [[TMP24]], 4224
@@ -218,12 +218,12 @@ int hoo(void) {
 //
 // CHECK-LABEL: define {{[^@]+}}@fmv_one.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
-// CHECK-NEXT:    ret ptr @fmv_one._MsimdMls64
+// CHECK-NEXT:    ret ptr @fmv_one._Mls64Msimd
 //
 //
 // CHECK-LABEL: define {{[^@]+}}@fmv_two.resolver() comdat {
 // CHECK-NEXT:  resolver_entry:
-// CHECK-NEXT:    ret ptr @fmv_two._MsimdMfp16
+// CHECK-NEXT:    ret ptr @fmv_two._Mfp16Msimd
 //
 //
 // CHECK-LABEL: define {{[^@]+}}@fmv_e.resolver() comdat {
@@ -261,12 +261,12 @@ int hoo(void) {
 // 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]], 4398048608256
-// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 4398048608256
+// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 4398048608320
+// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 4398048608320
 // 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._Mfp16Mfp16MfcmaMsme
+// CHECK-NEXT:    ret ptr @fmv_inline._MfcmaMfp16Mfp16MrdmMsme
 // CHECK:       resolver_else:
 // CHECK-NEXT:    [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
 // CHECK-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 864726312827224064
@@ -274,7 +274,7 @@ int hoo(void) {
 // CHECK-NEXT:    [[TMP7:%.*]] = and i1 true, [[TMP6]]
 // CHECK-NEXT:    br i1 [[TMP7]], label [[RESOLVER_RETURN1:%.*]], label [[RESOLVER_ELSE2:%.*]]
 // CHECK:       resolver_return1:
-// CHECK-NEXT:    ret ptr @fmv_inline._Mrcpc3Mmemtag3Mmops
+// CHECK-NEXT:    ret ptr @fmv_inline._Mmemtag3MmopsMrcpc3
 // CHECK:       resolver_else2:
 // CHECK-NEXT:    [[TMP8:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
 // CHECK-NEXT:    [[TMP9:%.*]] = and i64 [[TMP8]], 893353197568
@@ -282,7 +282,7 @@ int hoo(void) {
 // CHECK-NEXT:    [[TMP11:%.*]] = and i1 true, [[TMP10]]
 // CHECK-NEXT:    br i1 [[TMP11]], label [[RESOLVER_RETURN3:%.*]], label [[RESOLVER_ELSE4:%.*]]
 // CHECK:       resolver_return3:
-// CHECK-NEXT:    ret ptr @fmv_inline._Msve2Msve2-pmull128Msve2-bitperm
+// CHECK-NEXT:    ret ptr @fmv_inline._Msve2Msve2-bitpermMsve2-pmull128
 // CHECK:       resolver_else4:
 // CHECK-NEXT:    [[TMP12:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
 // CHECK-NEXT:    [[TMP13:%.*]] = and i64 [[TMP12]], 34359773184
@@ -290,7 +290,7 @@ int hoo(void) {
 // CHECK-NEXT:    [[TMP15:%.*]] = and i1 true, [[TMP14]]
 // CHECK-NEXT:    br i1 [[TMP15]], label [[RESOLVER_RETURN5:%.*]], label [[RESOLVER_ELSE6:%.*]]
 // CHECK:       resolver_return5:
-// CHECK-NEXT:    ret ptr @fmv_inline._Msha1MpmullMf64mm
+// CHECK-NEXT:    ret ptr @fmv_inline._Mf64mmMpmullMsha1
 // CHECK:       resolver_else6:
 // CHECK-NEXT:    [[TMP16:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
 // CHECK-NEXT:    [[TMP17:%.*]] = and i64 [[TMP16]], 17246986240
@@ -298,7 +298,7 @@ int hoo(void) {
 // CHECK-NEXT:    [[TMP19:%.*]] = and i1 true, [[TMP18]]
 // CHECK-NEXT:    br i1 [[TMP19]], label [[RESOLVER_RETURN7:%.*]], label [[RESOLVER_ELSE8:%.*]]
 // CHECK:       resolver_return7:
-// CHECK-NEXT:    ret ptr @fmv_inline._Msha3Mi8mmMf32mm
+// CHECK-NEXT:    ret ptr @fmv_inline._Mf32mmMi8mmMsha3
 // CHECK:       resolver_else8:
 // CHECK-NEXT:    [[TMP20:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
 // CHECK-NEXT:    [[TMP21:%.*]] = and i64 [[TMP20]], 19791209299968
@@ -306,7 +306,7 @@ int hoo(void) {
 // CHECK-NEXT:    [[TMP23:%.*]] = and i1 true, [[TMP22]]
 // CHECK-NEXT:    br i1 [[TMP23]], label [[RESOLVER_RETURN9:%.*]], label [[RESOLVER_ELSE10:%.*]]
 // CHECK:       resolver_return9:
-// CHECK-NEXT:    ret ptr @fmv_inline._Msve2-sm4Mmemtag2
+// CHECK-NEXT:    ret ptr @fmv_inline._Mmemtag2Msve2-sm4
 // CHECK:       resolver_else10:
 // CHECK-NEXT:    [[TMP24:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
 // CHECK-NEXT:    [[TMP25:%.*]] = and i64 [[TMP24]], 1236950581248
@@ -338,7 +338,7 @@ int hoo(void) {
 // CHECK-NEXT:    [[TMP39:%.*]] = and i1 true, [[TMP38]]
 // CHECK-NEXT:    br i1 [[TMP39]], label [[RESOLVER_RETURN17:%.*]], label [[RESOLVER_ELSE18:%.*]]
 // CHECK:       resolver_return17:
-// CHECK-NEXT:    ret ptr @fmv_inline._MrcpcMfrintts
+// CHECK-NEXT:    ret ptr @fmv_inline._MfrinttsMrcpc
 // CHECK:       resolver_else18:
 // CHECK-NEXT:    [[TMP40:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
 // CHECK-NEXT:    [[TMP41:%.*]] = and i64 [[TMP40]], 8650752
@@ -362,7 +362,7 @@ int hoo(void) {
 // CHECK-NEXT:    [[TMP51:%.*]] = and i1 true, [[TMP50]]
 // CHECK-NEXT:    br i1 [[TMP51]], label [[RESOLVER_RETURN23:%.*]], label [[RESOLVER_ELSE24:%.*]]
 // CHECK:       resolver_return23:
-// CHECK-NEXT:    ret ptr @fmv_inline._MsimdMfp16fml
+// CHECK-NEXT:    ret ptr @fmv_inline._Mfp16fmlMsimd
 // CHECK:       resolver_else24:
 // CHECK-NEXT:    [[TMP52:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
 // CHECK-NEXT:    [[TMP53:%.*]] = and i64 [[TMP52]], 16400
@@ -370,7 +370,7 @@ int hoo(void) {
 // CHECK-NEXT:    [[TMP55:%.*]] = and i1 true, [[TMP54]]
 // CHECK-NEXT:    br i1 [[TMP55]], label [[RESOLVER_RETURN25:%.*]], label [[RESOLVER_ELSE26:%.*]]
 // CHECK:       resolver_return25:
-// CHECK-NEXT:    ret ptr @fmv_inline._MdotprodMaes
+// CHECK-NEXT:    ret ptr @fmv_inline._MaesMdotprod
 // CHECK:       resolver_else26:
 // CHECK-NEXT:    [[TMP56:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
 // CHECK-NEXT:    [[TMP57:%.*]] = and i64 [[TMP56]], 192
@@ -484,7 +484,7 @@ int hoo(void) {
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: define {{[^@]+}}@fmv._MfpMaes
+// CHECK-LABEL: define {{[^@]+}}@fmv._MaesMfp
 // CHECK-SAME: () #[[ATTR1]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 6
@@ -547,7 +547,7 @@ int hoo(void) {
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: define {{[^@]+}}@fmv_two._MsimdMfp16
+// CHECK-LABEL: define {{[^@]+}}@fmv_two._Mfp16Msimd
 // CHECK-SAME: () #[[ATTR1]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 4
@@ -568,21 +568,21 @@ int hoo(void) {
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: define {{[^@]+}}@fmv_inline._Msha1MpmullMf64mm
+// CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mf64mmMpmullMsha1
 // CHECK-SAME: () #[[ATTR12:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 1
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mfp16Mfp16MfcmaMsme
+// CHECK-LABEL: define {{[^@]+}}@fmv_inline._MfcmaMfp16Mfp16MrdmMsme
 // CHECK-SAME: () #[[ATTR13:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 2
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: define {{[^@]+}}@fmv_inline._Msha3Mi8mmMf32mm
+// CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mf32mmMi8mmMsha3
 // CHECK-SAME: () #[[ATTR14:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 12
@@ -610,7 +610,7 @@ int hoo(void) {
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: define {{[^@]+}}@fmv_inline._MrcpcMfrintts
+// CHECK-LABEL: define {{[^@]+}}@fmv_inline._MfrinttsMrcpc
 // CHECK-SAME: () #[[ATTR18:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 3
@@ -631,35 +631,35 @@ int hoo(void) {
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: define {{[^@]+}}@fmv_inline._Msve2Msve2-pmull128Msve2-bitperm
+// CHECK-LABEL: define {{[^@]+}}@fmv_inline._Msve2Msve2-bitpermMsve2-pmull128
 // CHECK-SAME: () #[[ATTR21:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 9
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: define {{[^@]+}}@fmv_inline._Msve2-sm4Mmemtag2
+// CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mmemtag2Msve2-sm4
 // CHECK-SAME: () #[[ATTR22:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 10
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mrcpc3Mmemtag3Mmops
+// CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mmemtag3MmopsMrcpc3
 // CHECK-SAME: () #[[ATTR23:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 11
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: define {{[^@]+}}@fmv_inline._MdotprodMaes
+// CHECK-LABEL: define {{[^@]+}}@fmv_inline._MaesMdotprod
 // CHECK-SAME: () #[[ATTR6]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 13
 //
 //
 // CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: define {{[^@]+}}@fmv_inline._MsimdMfp16fml
+// CHECK-LABEL: define {{[^@]+}}@fmv_inline._Mfp16fmlMsimd
 // CHECK-SAME: () #[[ATTR7]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 14
@@ -829,7 +829,7 @@ int hoo(void) {
 // CHECK: attributes #[[ATTR10]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+fullfp16,+ls64,+sme,+sme2" }
 // CHECK: attributes #[[ATTR11]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccpp,+fullfp16,+ls64" }
 // CHECK: attributes #[[ATTR12]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+aes,+f64mm,+fp-armv8,+fullfp16,+ls64,+neon,+sve" }
-// CHECK: attributes #[[ATTR13]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+complxnum,+fp-armv8,+fullfp16,+ls64,+neon,+sme" }
+// CHECK: attributes #[[ATTR13]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+complxnum,+fp-armv8,+fullfp16,+ls64,+neon,+rdm,+sme" }
 // CHECK: attributes #[[ATTR14]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+f32mm,+fp-armv8,+fullfp16,+i8mm,+ls64,+neon,+sha2,+sha3,+sve" }
 // CHECK: attributes #[[ATTR15]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+dit,+fp-armv8,+fullfp16,+ls64,+neon,+sve" }
 // CHECK: attributes #[[ATTR16]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccpp,+fullfp16,+ls64,+rcpc" }
diff --git a/clang/test/CodeGen/builtins-hexagon.c b/clang/test/CodeGen/builtins-hexagon.c
index 9a1b733da5cdb..52073f27ae70f 100644
--- a/clang/test/CodeGen/builtins-hexagon.c
+++ b/clang/test/CodeGen/builtins-hexagon.c
@@ -1,5 +1,5 @@
 // REQUIRES: hexagon-registered-target
-// RUN: %clang_cc1 -triple hexagon-unknown-elf -target-cpu hexagonv65 -target-feature +hvxv65 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple hexagon-unknown-elf -target-cpu hexagonv65 -target-feature +hvxv65 -target-feature +hvx-length128b -emit-llvm %s -o - | FileCheck %s
 
 void test() {
   int v64 __attribute__((__vector_size__(64)));
diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c
index 73866116e07e7..4f9641d357b7b 100644
--- a/clang/test/CodeGen/builtins.c
+++ b/clang/test/CodeGen/builtins.c
@@ -948,14 +948,14 @@ void test_builtin_popcountg(unsigned char uc, unsigned short us,
   volatile int pop;
   pop = __builtin_popcountg(uc);
   // CHECK: %1 = load i8, ptr %uc.addr, align 1
-  // CHECK-NEXT: %conv = zext i8 %1 to i32
-  // CHECK-NEXT: %2 = call i32 @llvm.ctpop.i32(i32 %conv)
-  // CHECK-NEXT: store volatile i32 %2, ptr %pop, align 4
+  // CHECK-NEXT: %2 = call i8 @llvm.ctpop.i8(i8 %1)
+  // CHECK-NEXT: %cast = sext i8 %2 to i32
+  // CHECK-NEXT: store volatile i32 %cast, ptr %pop, align 4
   pop = __builtin_popcountg(us);
   // CHECK-NEXT: %3 = load i16, ptr %us.addr, align 2
-  // CHECK-NEXT: %conv1 = zext i16 %3 to i32
-  // CHECK-NEXT: %4 = call i32 @llvm.ctpop.i32(i32 %conv1)
-  // CHECK-NEXT: store volatile i32 %4, ptr %pop, align 4
+  // CHECK-NEXT: %4 = call i16 @llvm.ctpop.i16(i16 %3)
+  // CHECK-NEXT: %cast1 = sext i16 %4 to i32
+  // CHECK-NEXT: store volatile i32 %cast1, ptr %pop, align 4
   pop = __builtin_popcountg(ui);
   // CHECK-NEXT: %5 = load i32, ptr %ui.addr, align 4
   // CHECK-NEXT: %6 = call i32 @llvm.ctpop.i32(i32 %5)
@@ -963,23 +963,23 @@ void test_builtin_popcountg(unsigned char uc, unsigned short us,
   pop = __builtin_popcountg(ul);
   // CHECK-NEXT: %7 = load i64, ptr %ul.addr, align 8
   // CHECK-NEXT: %8 = call i64 @llvm.ctpop.i64(i64 %7)
-  // CHECK-NEXT: %cast = trunc i64 %8 to i32
-  // CHECK-NEXT: store volatile i32 %cast, ptr %pop, align 4
+  // CHECK-NEXT: %cast2 = trunc i64 %8 to i32
+  // CHECK-NEXT: store volatile i32 %cast2, ptr %pop, align 4
   pop = __builtin_popcountg(ull);
   // CHECK-NEXT: %9 = load i64, ptr %ull.addr, align 8
   // CHECK-NEXT: %10 = call i64 @llvm.ctpop.i64(i64 %9)
-  // CHECK-NEXT: %cast2 = trunc i64 %10 to i32
-  // CHECK-NEXT: store volatile i32 %cast2, ptr %pop, align 4
+  // CHECK-NEXT: %cast3 = trunc i64 %10 to i32
+  // CHECK-NEXT: store volatile i32 %cast3, ptr %pop, align 4
   pop = __builtin_popcountg(ui128);
   // CHECK-NEXT: %11 = load i128, ptr %ui128.addr, align 16
   // CHECK-NEXT: %12 = call i128 @llvm.ctpop.i128(i128 %11)
-  // CHECK-NEXT: %cast3 = trunc i128 %12 to i32
-  // CHECK-NEXT: store volatile i32 %cast3, ptr %pop, align 4
+  // CHECK-NEXT: %cast4 = trunc i128 %12 to i32
+  // CHECK-NEXT: store volatile i32 %cast4, ptr %pop, align 4
   pop = __builtin_popcountg(ubi128);
   // CHECK-NEXT: %13 = load i128, ptr %ubi128.addr, align 8
   // CHECK-NEXT: %14 = call i128 @llvm.ctpop.i128(i128 %13)
-  // CHECK-NEXT: %cast4 = trunc i128 %14 to i32
-  // CHECK-NEXT: store volatile i32 %cast4, ptr %pop, align 4
+  // CHECK-NEXT: %cast5 = trunc i128 %14 to i32
+  // CHECK-NEXT: store volatile i32 %cast5, ptr %pop, align 4
   // CHECK-NEXT: ret void
 }
 
diff --git a/clang/test/CodeGen/fat-lto-objects.c b/clang/test/CodeGen/fat-lto-objects.c
index afce798c5c819..b50567c024fc8 100644
--- a/clang/test/CodeGen/fat-lto-objects.c
+++ b/clang/test/CodeGen/fat-lto-objects.c
@@ -11,10 +11,11 @@
 // RUN: llvm-objcopy --dump-section=.llvm.lto=%t.full.split.bc %t.full.split.o
 // RUN: llvm-dis %t.full.split.bc -o - | FileCheck %s --check-prefixes=FULL,SPLIT,NOUNIFIED
 
+/// Full LTO always sets EnableSplitLTOUnit when the summary is used.
 // RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=full -ffat-lto-objects -emit-obj < %s -o %t.full.nosplit.o
 // RUN: llvm-readelf -S %t.full.nosplit.o | FileCheck %s --check-prefixes=ELF
 // RUN: llvm-objcopy --dump-section=.llvm.lto=%t.full.nosplit.bc %t.full.nosplit.o
-// RUN: llvm-dis %t.full.nosplit.bc -o - | FileCheck %s --check-prefixes=FULL,NOSPLIT,NOUNIFIED
+// RUN: llvm-dis %t.full.nosplit.bc -o - | FileCheck %s --check-prefixes=FULL,SPLIT,NOUNIFIED
 
 // RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=thin -fsplit-lto-unit -ffat-lto-objects -emit-obj < %s -o %t.thin.split.o
 // RUN: llvm-readelf -S %t.thin.split.o | FileCheck %s --check-prefixes=ELF
@@ -34,6 +35,21 @@
 // RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=full -ffat-lto-objects -fsplit-lto-unit -S < %s -o - \
 // RUN: | FileCheck %s --check-prefixes=ASM
 
+/// Make sure that FatLTO generates .llvm.lto sections that are the same as the output from normal LTO compilations
+// RUN: %clang -O2 --target=x86_64-unknown-linux-gnu -fPIE -flto=full -ffat-lto-objects -c %s -o %t.fatlto.full.o
+// RUN: llvm-objcopy --dump-section=.llvm.lto=%t.fatlto.full.bc %t.fatlto.full.o
+// RUN: llvm-dis < %t.fatlto.full.bc -o %t.fatlto.full.ll
+// RUN: %clang -O2 --target=x86_64-unknown-linux-gnu -fPIE -flto=full -c %s -o %t.nofat.full.bc
+// RUN: llvm-dis < %t.nofat.full.bc -o %t.nofat.full.ll
+// RUN: diff %t.fatlto.full.ll %t.nofat.full.ll
+
+// RUN: %clang -O2 --target=x86_64-unknown-linux-gnu -fPIE -flto=thin -ffat-lto-objects -c %s -o %t.fatlto.thin.o
+// RUN: llvm-objcopy --dump-section=.llvm.lto=%t.fatlto.thin.bc %t.fatlto.thin.o
+// RUN: llvm-dis < %t.fatlto.thin.bc -o %t.fatlto.thin.ll
+// RUN: %clang -O2 --target=x86_64-unknown-linux-gnu -fPIE -flto=thin -c %s -o %t.nofat.thin.bc
+// RUN: llvm-dis < %t.nofat.thin.bc -o %t.nofat.thin.ll
+// RUN: diff %t.fatlto.thin.ll %t.nofat.thin.ll
+
 /// Be sure we enable split LTO units correctly under -ffat-lto-objects.
 //   SPLIT: ![[#]] = !{i32 1, !"EnableSplitLTOUnit", i32 1}
 // NOSPLIT: ![[#]] = !{i32 1, !"EnableSplitLTOUnit", i32 0}
@@ -51,6 +67,9 @@
 // ASM-NEXT:        .asciz  "BC
 // ASM-NEXT: .size   .Lllvm.embedded.object
 
+const char* foo = "foo";
+
 int test(void) {
+  const char* bar = "bar";
   return 0xabcd;
 }
diff --git a/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp b/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp
index 2d3f448947991..14963867798d3 100644
--- a/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp
+++ b/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp
@@ -36,22 +36,33 @@ void run_foo_tml() {
 }
 
 
+
+
+//.
 // CHECK: @__aarch64_cpu_features = external dso_local global { i64 }
+// CHECK: @_Z7foo_ovli.ifunc = weak_odr alias i32 (i32), ptr @_Z7foo_ovli
+// CHECK: @_Z7foo_ovlv.ifunc = weak_odr alias i32 (), ptr @_Z7foo_ovlv
+// CHECK: @_ZN7MyClassIssE7foo_tmlEv.ifunc = weak_odr alias i32 (ptr), ptr @_ZN7MyClassIssE7foo_tmlEv
+// CHECK: @_ZN7MyClassIisE7foo_tmlEv.ifunc = weak_odr alias i32 (ptr), ptr @_ZN7MyClassIisE7foo_tmlEv
 // CHECK: @_Z7foo_ovli = weak_odr ifunc i32 (i32), ptr @_Z7foo_ovli.resolver
 // CHECK: @_Z7foo_ovlv = weak_odr ifunc i32 (), ptr @_Z7foo_ovlv.resolver
 // CHECK: @_ZN7MyClassIssE7foo_tmlEv = weak_odr ifunc i32 (ptr), ptr @_ZN7MyClassIssE7foo_tmlEv.resolver
 // CHECK: @_ZN7MyClassIisE7foo_tmlEv = weak_odr ifunc i32 (ptr), ptr @_ZN7MyClassIisE7foo_tmlEv.resolver
-
+//.
 // CHECK-LABEL: @_Z7foo_ovli._Mfp16Mls64_v(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    [[DOTADDR:%.*]] = alloca i32, align 4
 // CHECK-NEXT:    store i32 [[TMP0:%.*]], ptr [[DOTADDR]], align 4
 // CHECK-NEXT:    ret i32 1
+//
+//
 // CHECK-LABEL: @_Z7foo_ovli.default(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    [[DOTADDR:%.*]] = alloca i32, align 4
 // CHECK-NEXT:    store i32 [[TMP0:%.*]], ptr [[DOTADDR]], align 4
 // CHECK-NEXT:    ret i32 1
+//
+//
 // CHECK-LABEL: @_Z7foo_ovli.resolver(
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
@@ -63,13 +74,19 @@ void run_foo_tml() {
 // CHECK:       resolver_return:
 // CHECK-NEXT:    ret ptr @_Z7foo_ovli._Mfp16Mls64_v
 // CHECK:       resolver_else:
-// CHECK-NEXT:    ret ptr @_Z7foo_ovli
+// CHECK-NEXT:    ret ptr @_Z7foo_ovli.default
+//
+//
 // CHECK-LABEL: @_Z7foo_ovlv._Mls64Mls64_accdata(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 2
+//
+//
 // CHECK-LABEL: @_Z7foo_ovlv.default(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 2
+//
+//
 // CHECK-LABEL: @_Z7foo_ovlv.resolver(
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
@@ -82,12 +99,16 @@ void run_foo_tml() {
 // CHECK-NEXT:    ret ptr @_Z7foo_ovlv._Mls64Mls64_accdata
 // CHECK:       resolver_else:
 // CHECK-NEXT:    ret ptr @_Z7foo_ovlv.default
+//
+//
 // CHECK-LABEL: @_Z3barv(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    [[CALL:%.*]] = call noundef i32 @_Z7foo_ovli(i32 noundef 1)
 // CHECK-NEXT:    [[CALL1:%.*]] = call noundef i32 @_Z7foo_ovlv()
 // CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[CALL]], [[CALL1]]
 // CHECK-NEXT:    ret i32 [[ADD]]
+//
+//
 // CHECK-LABEL: @_Z11run_foo_tmlv(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    [[MC1:%.*]] = alloca [[STRUCT_MYCLASS:%.*]], align 1
@@ -99,6 +120,8 @@ void run_foo_tml() {
 // CHECK-NEXT:    [[CALL2:%.*]] = call noundef i32 @_ZN7MyClassIfsE7foo_tmlEv(ptr noundef nonnull align 1 dereferenceable(1) [[MC3]])
 // CHECK-NEXT:    [[CALL3:%.*]] = call noundef i32 @_ZN7MyClassIdfE7foo_tmlEv(ptr noundef nonnull align 1 dereferenceable(1) [[MC4]])
 // CHECK-NEXT:    ret void
+//
+//
 // CHECK-LABEL: @_ZN7MyClassIssE7foo_tmlEv.resolver(
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
@@ -108,7 +131,7 @@ void run_foo_tml() {
 // 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 @_ZN7MyClassIssE7foo_tmlEv._MssbsMsme-f64f64
+// CHECK-NEXT:    ret ptr @_ZN7MyClassIssE7foo_tmlEv._Msme-f64f64Mssbs
 // CHECK:       resolver_else:
 // CHECK-NEXT:    [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
 // CHECK-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 16777216
@@ -118,7 +141,9 @@ void run_foo_tml() {
 // CHECK:       resolver_return1:
 // CHECK-NEXT:    ret ptr @_ZN7MyClassIssE7foo_tmlEv._Mfrintts
 // CHECK:       resolver_else2:
-// CHECK-NEXT:    ret ptr @_ZN7MyClassIssE7foo_tmlEv
+// CHECK-NEXT:    ret ptr @_ZN7MyClassIssE7foo_tmlEv.default
+//
+//
 // CHECK-LABEL: @_ZN7MyClassIisE7foo_tmlEv.resolver(
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
@@ -128,7 +153,7 @@ void run_foo_tml() {
 // 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 @_ZN7MyClassIisE7foo_tmlEv._MssbsMsme-f64f64
+// CHECK-NEXT:    ret ptr @_ZN7MyClassIisE7foo_tmlEv._Msme-f64f64Mssbs
 // CHECK:       resolver_else:
 // CHECK-NEXT:    [[TMP4:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
 // CHECK-NEXT:    [[TMP5:%.*]] = and i64 [[TMP4]], 16777216
@@ -138,58 +163,79 @@ void run_foo_tml() {
 // CHECK:       resolver_return1:
 // CHECK-NEXT:    ret ptr @_ZN7MyClassIisE7foo_tmlEv._Mfrintts
 // CHECK:       resolver_else2:
-// CHECK-NEXT:    ret ptr @_ZN7MyClassIisE7foo_tmlEv
+// CHECK-NEXT:    ret ptr @_ZN7MyClassIisE7foo_tmlEv.default
+//
+//
 // CHECK-LABEL: @_ZN7MyClassIfsE7foo_tmlEv(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
 // CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
 // CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
 // CHECK-NEXT:    ret i32 3
+//
+//
 // CHECK-LABEL: @_ZN7MyClassIdfE7foo_tmlEv(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
 // CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
 // CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
 // CHECK-NEXT:    ret i32 4
+//
+//
 // CHECK-LABEL: @_ZN7MyClassIssE7foo_tmlEv._Mfrintts(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
 // CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
 // CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
 // CHECK-NEXT:    ret i32 1
-// CHECK-LABEL: @_ZN7MyClassIssE7foo_tmlEv._MssbsMsme-f64f64(
+//
+//
+// CHECK-LABEL: @_ZN7MyClassIssE7foo_tmlEv._Msme-f64f64Mssbs(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
 // CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
 // CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
 // CHECK-NEXT:    ret i32 1
+//
+//
 // CHECK-LABEL: @_ZN7MyClassIssE7foo_tmlEv.default(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
 // CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
 // CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
 // CHECK-NEXT:    ret i32 1
+//
+//
 // CHECK-LABEL: @_ZN7MyClassIisE7foo_tmlEv._Mfrintts(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
 // CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
 // CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
 // CHECK-NEXT:    ret i32 2
-// CHECK-LABEL: @_ZN7MyClassIisE7foo_tmlEv._MssbsMsme-f64f64(
+//
+//
+// CHECK-LABEL: @_ZN7MyClassIisE7foo_tmlEv._Msme-f64f64Mssbs(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
 // CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
 // CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
 // CHECK-NEXT:    ret i32 2
+//
+//
 // CHECK-LABEL: @_ZN7MyClassIisE7foo_tmlEv.default(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
 // CHECK-NEXT:    store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
 // CHECK-NEXT:    [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
 // CHECK-NEXT:    ret i32 2
-
-// CHECK: attributes #0 = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" }
-// CHECK: attributes #1 = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
-// CHECK: attributes #2 = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ls64" }
-// CHECK: attributes #3 = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fptoint" }
-// CHECK: attributes #4 = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme,+sme-f64f64" }
+//
+//.
+// CHECK: attributes #[[ATTR0:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" }
+// CHECK: attributes #[[ATTR1:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+// CHECK: attributes #[[ATTR2:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ls64" }
+// CHECK: attributes #[[ATTR3:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fptoint" }
+// CHECK: attributes #[[ATTR4:[0-9]+]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme,+sme-f64f64" }
+//.
+// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
+// CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
+//.
diff --git a/clang/test/CodeGenCXX/attr-target-version.cpp b/clang/test/CodeGenCXX/attr-target-version.cpp
index b63815db7e40f..82a928a385e16 100644
--- a/clang/test/CodeGenCXX/attr-target-version.cpp
+++ b/clang/test/CodeGenCXX/attr-target-version.cpp
@@ -40,7 +40,7 @@ int bar() {
 // CHECK-NEXT:    ret i32 1
 //
 //
-// CHECK-LABEL: @_Z3foov._Msm4Mebf16(
+// CHECK-LABEL: @_Z3foov._Mebf16Msm4(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 3
 //
@@ -101,7 +101,7 @@ int bar() {
 // 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 @_Z3foov._Msm4Mebf16
+// CHECK-NEXT:    ret ptr @_Z3foov._Mebf16Msm4
 // CHECK:       resolver_else:
 // CHECK-NEXT:    ret ptr @_Z3foov.default
 //
diff --git a/clang/test/CodeGenHLSL/builtins/abs.hlsl b/clang/test/CodeGenHLSL/builtins/abs.hlsl
index 54c9d1a9dded4..ad65cab2721a2 100644
--- a/clang/test/CodeGenHLSL/builtins/abs.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/abs.hlsl
@@ -1,141 +1,93 @@
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -fnative-half-type \
-// RUN:   -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ 
+// RUN:   --check-prefixes=CHECK,NATIVE_HALF
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
-// RUN:   -o - | FileCheck %s --check-prefix=NO_HALF
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
 
 using hlsl::abs;
 
 #ifdef __HLSL_ENABLE_16_BIT
-// CHECK: define noundef i16 @
-// CHECK: call i16 @llvm.abs.i16(
-int16_t test_abs_int16_t ( int16_t p0 ) {
-  return abs ( p0 );
-}
-// CHECK: define noundef <2 x i16> @
-// CHECK: call <2 x i16> @llvm.abs.v2i16(
-int16_t2 test_abs_int16_t2 ( int16_t2 p0 ) {
-  return abs ( p0 );
-}
-// CHECK: define noundef <3 x i16> @
-// CHECK: call <3 x i16> @llvm.abs.v3i16(
-int16_t3 test_abs_int16_t3 ( int16_t3 p0 ) {
-  return abs ( p0 );
-}
-// CHECK: define noundef <4 x i16> @
-// CHECK: call <4 x i16> @llvm.abs.v4i16(
-int16_t4 test_abs_int16_t4 ( int16_t4 p0 ) {
-  return abs ( p0 );
-}
+// NATIVE_HALF: define noundef i16 @
+// NATIVE_HALF: call i16 @llvm.abs.i16(
+int16_t test_abs_int16_t(int16_t p0) { return abs(p0); }
+// NATIVE_HALF: define noundef <2 x i16> @
+// NATIVE_HALF: call <2 x i16> @llvm.abs.v2i16(
+int16_t2 test_abs_int16_t2(int16_t2 p0) { return abs(p0); }
+// NATIVE_HALF: define noundef <3 x i16> @
+// NATIVE_HALF: call <3 x i16> @llvm.abs.v3i16(
+int16_t3 test_abs_int16_t3(int16_t3 p0) { return abs(p0); }
+// NATIVE_HALF: define noundef <4 x i16> @
+// NATIVE_HALF: call <4 x i16> @llvm.abs.v4i16(
+int16_t4 test_abs_int16_t4(int16_t4 p0) { return abs(p0); }
 #endif // __HLSL_ENABLE_16_BIT
 
-// CHECK: define noundef half @
-// CHECK: call half @llvm.fabs.f16(
+// NATIVE_HALF: define noundef half @
+// NATIVE_HALF: call half @llvm.fabs.f16(
 // NO_HALF: define noundef float @"?test_abs_half@@YA$halff@$halff@@Z"(
 // NO_HALF: call float @llvm.fabs.f32(float %0)
-half test_abs_half ( half p0 ) {
-  return abs ( p0 );
-}
-// CHECK: define noundef <2 x half> @
-// CHECK: call <2 x half> @llvm.fabs.v2f16(
+half test_abs_half(half p0) { return abs(p0); }
+// NATIVE_HALF: define noundef <2 x half> @
+// NATIVE_HALF: call <2 x half> @llvm.fabs.v2f16(
 // NO_HALF: define noundef <2 x float> @"?test_abs_half2@@YAT?$__vector@$halff@$01@__clang@@T12@@Z"(
 // NO_HALF: call <2 x float> @llvm.fabs.v2f32(
-half2 test_abs_half2 ( half2 p0 ) {
-  return abs ( p0 );
-}
-// CHECK: define noundef <3 x half> @
-// CHECK: call <3 x half> @llvm.fabs.v3f16(
+half2 test_abs_half2(half2 p0) { return abs(p0); }
+// NATIVE_HALF: define noundef <3 x half> @
+// NATIVE_HALF: call <3 x half> @llvm.fabs.v3f16(
 // NO_HALF: define noundef <3 x float> @"?test_abs_half3@@YAT?$__vector@$halff@$02@__clang@@T12@@Z"(
 // NO_HALF: call <3 x float> @llvm.fabs.v3f32(
-half3 test_abs_half3 ( half3 p0 ) {
-  return abs ( p0 );
-}
-// CHECK: define noundef <4 x half> @
-// CHECK: call <4 x half> @llvm.fabs.v4f16(
+half3 test_abs_half3(half3 p0) { return abs(p0); }
+// NATIVE_HALF: define noundef <4 x half> @
+// NATIVE_HALF: call <4 x half> @llvm.fabs.v4f16(
 // NO_HALF: define noundef <4 x float> @"?test_abs_half4@@YAT?$__vector@$halff@$03@__clang@@T12@@Z"(
 // NO_HALF: call <4 x float> @llvm.fabs.v4f32(
-half4 test_abs_half4 ( half4 p0 ) {
-  return abs ( p0 );
-}
+half4 test_abs_half4(half4 p0) { return abs(p0); }
 // CHECK: define noundef i32 @
 // CHECK: call i32 @llvm.abs.i32(
-// NO_HALF: define noundef i32 @"?test_abs_int@@YAHH@Z"
-int test_abs_int ( int p0 ) {
-  return abs ( p0 );
-}
+int test_abs_int(int p0) { return abs(p0); }
 // CHECK: define noundef <2 x i32> @
 // CHECK: call <2 x i32> @llvm.abs.v2i32(
-int2 test_abs_int2 ( int2 p0 ) {
-  return abs ( p0 );
-}
+int2 test_abs_int2(int2 p0) { return abs(p0); }
 // CHECK: define noundef <3 x i32> @
 // CHECK: call <3 x i32> @llvm.abs.v3i32(
-int3 test_abs_int3 ( int3 p0 ) {
-  return abs ( p0 );
-}
+int3 test_abs_int3(int3 p0) { return abs(p0); }
 // CHECK: define noundef <4 x i32> @
 // CHECK: call <4 x i32> @llvm.abs.v4i32(
-int4 test_abs_int4 ( int4 p0 ) {
-  return abs ( p0 );
-}
+int4 test_abs_int4(int4 p0) { return abs(p0); }
 // CHECK: define noundef float @
 // CHECK: call float @llvm.fabs.f32(
-float test_abs_float ( float p0 ) {
-  return abs ( p0 );
-}
+float test_abs_float(float p0) { return abs(p0); }
 // CHECK: define noundef <2 x float> @
 // CHECK: call <2 x float> @llvm.fabs.v2f32(
-float2 test_abs_float2 ( float2 p0 ) {
-  return abs ( p0 );
-}
+float2 test_abs_float2(float2 p0) { return abs(p0); }
 // CHECK: define noundef <3 x float> @
 // CHECK: call <3 x float> @llvm.fabs.v3f32(
-float3 test_abs_float3 ( float3 p0 ) {
-  return abs ( p0 );
-}
+float3 test_abs_float3(float3 p0) { return abs(p0); }
 // CHECK: define noundef <4 x float> @
 // CHECK: call <4 x float> @llvm.fabs.v4f32(
-float4 test_abs_float4 ( float4 p0 ) {
-  return abs ( p0 );
-}
+float4 test_abs_float4(float4 p0) { return abs(p0); }
 // CHECK: define noundef i64 @
 // CHECK: call i64 @llvm.abs.i64(
-int64_t test_abs_int64_t ( int64_t p0 ) {
-  return abs ( p0 );
-}
+int64_t test_abs_int64_t(int64_t p0) { return abs(p0); }
 // CHECK: define noundef <2 x i64> @
 // CHECK: call <2 x i64> @llvm.abs.v2i64(
-int64_t2 test_abs_int64_t2 ( int64_t2 p0 ) {
-  return abs ( p0 );
-}
+int64_t2 test_abs_int64_t2(int64_t2 p0) { return abs(p0); }
 // CHECK: define noundef <3 x i64> @
 // CHECK: call <3 x i64> @llvm.abs.v3i64(
-int64_t3 test_abs_int64_t3 ( int64_t3 p0 ) {
-  return abs ( p0 );
-}
+int64_t3 test_abs_int64_t3(int64_t3 p0) { return abs(p0); }
 // CHECK: define noundef <4 x i64> @
 // CHECK: call <4 x i64> @llvm.abs.v4i64(
-int64_t4 test_abs_int64_t4 ( int64_t4 p0 ) {
-  return abs ( p0 );
-}
+int64_t4 test_abs_int64_t4(int64_t4 p0) { return abs(p0); }
 // CHECK: define noundef double @
 // CHECK: call double @llvm.fabs.f64(
-double test_abs_double ( double p0 ) {
-  return abs ( p0 );
-}
+double test_abs_double(double p0) { return abs(p0); }
 // CHECK: define noundef <2 x double> @
 // CHECK: call <2 x double> @llvm.fabs.v2f64(
-double2 test_abs_double2 ( double2 p0 ) {
-  return abs ( p0 );
-}
+double2 test_abs_double2(double2 p0) { return abs(p0); }
 // CHECK: define noundef <3 x double> @
 // CHECK: call <3 x double> @llvm.fabs.v3f64(
-double3 test_abs_double3 ( double3 p0 ) {
-  return abs ( p0 );
-}
+double3 test_abs_double3(double3 p0) { return abs(p0); }
 // CHECK: define noundef <4 x double> @
 // CHECK: call <4 x double> @llvm.fabs.v4f64(
-double4 test_abs_double4 ( double4 p0 ) {
-  return abs ( p0 );
-}
+double4 test_abs_double4(double4 p0) { return abs(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/any.hlsl b/clang/test/CodeGenHLSL/builtins/any.hlsl
new file mode 100644
index 0000000000000..ae348fec756b3
--- /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/ceil.hlsl b/clang/test/CodeGenHLSL/builtins/ceil.hlsl
index f1672816e72bc..06d0d4c2cf546 100644
--- a/clang/test/CodeGenHLSL/builtins/ceil.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/ceil.hlsl
@@ -1,79 +1,56 @@
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -fnative-half-type \
-// RUN:   -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ 
+// RUN:   --check-prefixes=CHECK,NATIVE_HALF
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
-// RUN:   -o - | FileCheck %s --check-prefix=NO_HALF
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
 
 using hlsl::ceil;
 
-// CHECK: define noundef half @
-// CHECK: call half @llvm.ceil.f16(
+// NATIVE_HALF: define noundef half @
+// NATIVE_HALF: call half @llvm.ceil.f16(
 // NO_HALF: define noundef float @"?test_ceil_half@@YA$halff@$halff@@Z"(
 // NO_HALF: call float @llvm.ceil.f32(float %0)
-half test_ceil_half ( half p0 ) {
-  return ceil ( p0 );
-}
-// CHECK: define noundef <2 x half> @
-// CHECK: call <2 x half> @llvm.ceil.v2f16(
+half test_ceil_half(half p0) { return ceil(p0); }
+// NATIVE_HALF: define noundef <2 x half> @
+// NATIVE_HALF: call <2 x half> @llvm.ceil.v2f16(
 // NO_HALF: define noundef <2 x float> @"?test_ceil_half2@@YAT?$__vector@$halff@$01@__clang@@T12@@Z"(
 // NO_HALF: call <2 x float> @llvm.ceil.v2f32(
-half2 test_ceil_half2 ( half2 p0 ) {
-  return ceil ( p0 );
-}
-// CHECK: define noundef <3 x half> @
-// CHECK: call <3 x half> @llvm.ceil.v3f16(
+half2 test_ceil_half2(half2 p0) { return ceil(p0); }
+// NATIVE_HALF: define noundef <3 x half> @
+// NATIVE_HALF: call <3 x half> @llvm.ceil.v3f16(
 // NO_HALF: define noundef <3 x float> @"?test_ceil_half3@@YAT?$__vector@$halff@$02@__clang@@T12@@Z"(
 // NO_HALF: call <3 x float> @llvm.ceil.v3f32(
-half3 test_ceil_half3 ( half3 p0 ) {
-  return ceil ( p0 );
-}
-// CHECK: define noundef <4 x half> @
-// CHECK: call <4 x half> @llvm.ceil.v4f16(
+half3 test_ceil_half3(half3 p0) { return ceil(p0); }
+// NATIVE_HALF: define noundef <4 x half> @
+// NATIVE_HALF: call <4 x half> @llvm.ceil.v4f16(
 // NO_HALF: define noundef <4 x float> @"?test_ceil_half4@@YAT?$__vector@$halff@$03@__clang@@T12@@Z"(
 // NO_HALF: call <4 x float> @llvm.ceil.v4f32(
-half4 test_ceil_half4 ( half4 p0 ) {
-  return ceil ( p0 );
-}
+half4 test_ceil_half4(half4 p0) { return ceil(p0); }
 
 // CHECK: define noundef float @
 // CHECK: call float @llvm.ceil.f32(
-float test_ceil_float ( float p0 ) {
-  return ceil ( p0 );
-}
+float test_ceil_float(float p0) { return ceil(p0); }
 // CHECK: define noundef <2 x float> @
 // CHECK: call <2 x float> @llvm.ceil.v2f32(
-float2 test_ceil_float2 ( float2 p0 ) {
-  return ceil ( p0 );
-}
+float2 test_ceil_float2(float2 p0) { return ceil(p0); }
 // CHECK: define noundef <3 x float> @
 // CHECK: call <3 x float> @llvm.ceil.v3f32(
-float3 test_ceil_float3 ( float3 p0 ) {
-  return ceil ( p0 );
-}
+float3 test_ceil_float3(float3 p0) { return ceil(p0); }
 // CHECK: define noundef <4 x float> @
 // CHECK: call <4 x float> @llvm.ceil.v4f32(
-float4 test_ceil_float4 ( float4 p0 ) {
-  return ceil ( p0 );
-}
+float4 test_ceil_float4(float4 p0) { return ceil(p0); }
 
 // CHECK: define noundef double @
 // CHECK: call double @llvm.ceil.f64(
-double test_ceil_double ( double p0 ) {
-  return ceil ( p0 );
-}
+double test_ceil_double(double p0) { return ceil(p0); }
 // CHECK: define noundef <2 x double> @
 // CHECK: call <2 x double> @llvm.ceil.v2f64(
-double2 test_ceil_double2 ( double2 p0 ) {
-  return ceil ( p0 );
-}
+double2 test_ceil_double2(double2 p0) { return ceil(p0); }
 // CHECK: define noundef <3 x double> @
 // CHECK: call <3 x double> @llvm.ceil.v3f64(
-double3 test_ceil_double3 ( double3 p0 ) {
-  return ceil ( p0 );
-}
+double3 test_ceil_double3(double3 p0) { return ceil(p0); }
 // CHECK: define noundef <4 x double> @
 // CHECK: call <4 x double> @llvm.ceil.v4f64(
-double4 test_ceil_double4 ( double4 p0 ) {
-  return ceil ( p0 );
-}
+double4 test_ceil_double4(double4 p0) { return ceil(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/cos.hlsl b/clang/test/CodeGenHLSL/builtins/cos.hlsl
index 2fc1571949b2c..fb416fcaa49d7 100644
--- a/clang/test/CodeGenHLSL/builtins/cos.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/cos.hlsl
@@ -1,56 +1,41 @@
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -fnative-half-type \
-// RUN:   -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ 
+// RUN:   --check-prefixes=CHECK,NATIVE_HALF
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
-// RUN:   -o - | FileCheck %s --check-prefix=NO_HALF
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
 
-// CHECK: define noundef half @
-// CHECK: call half @llvm.cos.f16(
-// NO_HALF: define noundef float @"?test_cos_half@@YA$halff@$halff@@Z"(
+// NATIVE_HALF: define noundef half @
+// NATIVE_HALF: call half @llvm.cos.f16(
+// NO_HALF: define noundef float @"?test_cos_half
 // NO_HALF: call float @llvm.cos.f32(
-half test_cos_half ( half p0 ) {
-  return cos ( p0 );
-}
-// CHECK: define noundef <2 x half> @
-// CHECK: call <2 x half> @llvm.cos.v2f16
-// NO_HALF: define noundef <2 x float> @"?test_cos_float2@@YAT?$__vector@M$01@__clang@@T12@@Z"(
+half test_cos_half(half p0) { return cos(p0); }
+// NATIVE_HALF: define noundef <2 x half> @
+// NATIVE_HALF: call <2 x half> @llvm.cos.v2f16
+// NO_HALF: define noundef <2 x float> @"?test_cos_half2
 // NO_HALF: call <2 x float> @llvm.cos.v2f32(
-half2 test_cos_half2 ( half2 p0 ) {
-  return cos ( p0 );
-}
-// CHECK: define noundef <3 x half> @
-// CHECK: call <3 x half> @llvm.cos.v3f16
-// NO_HALF: define noundef <3 x float> @"?test_cos_float3@@YAT?$__vector@M$02@__clang@@T12@@Z"(
+half2 test_cos_half2(half2 p0) { return cos(p0); }
+// NATIVE_HALF: define noundef <3 x half> @
+// NATIVE_HALF: call <3 x half> @llvm.cos.v3f16
+// NO_HALF: define noundef <3 x float> @"?test_cos_half3
 // NO_HALF: call <3 x float> @llvm.cos.v3f32(
-half3 test_cos_half3 ( half3 p0 ) {
-  return cos ( p0 );
-}
-// CHECK: define noundef <4 x half> @
-// CHECK: call <4 x half> @llvm.cos.v4f16
-// NO_HALF: define noundef <4 x float> @"?test_cos_float4@@YAT?$__vector@M$03@__clang@@T12@@Z"(
+half3 test_cos_half3(half3 p0) { return cos(p0); }
+// NATIVE_HALF: define noundef <4 x half> @
+// NATIVE_HALF: call <4 x half> @llvm.cos.v4f16
+// NO_HALF: define noundef <4 x float> @"?test_cos_half4
 // NO_HALF: call <4 x float> @llvm.cos.v4f32(
-half4 test_cos_half4 ( half4 p0 ) {
-  return cos ( p0 );
-}
+half4 test_cos_half4(half4 p0) { return cos(p0); }
 
-// CHECK: define noundef float @
+// CHECK: define noundef float @"?test_cos_float
 // CHECK: call float @llvm.cos.f32(
-float test_cos_float ( float p0 ) {
-  return cos ( p0 );
-}
-// CHECK: define noundef <2 x float> @
+float test_cos_float(float p0) { return cos(p0); }
+// CHECK: define noundef <2 x float> @"?test_cos_float2
 // CHECK: call <2 x float> @llvm.cos.v2f32
-float2 test_cos_float2 ( float2 p0 ) {
-  return cos ( p0 );
-}
-// CHECK: define noundef <3 x float> @
+float2 test_cos_float2(float2 p0) { return cos(p0); }
+// CHECK: define noundef <3 x float> @"?test_cos_float3
 // CHECK: call <3 x float> @llvm.cos.v3f32
-float3 test_cos_float3 ( float3 p0 ) {
-  return cos ( p0 );
-}
-// CHECK: define noundef <4 x float> @
+float3 test_cos_float3(float3 p0) { return cos(p0); }
+// CHECK: define noundef <4 x float> @"?test_cos_float4
 // CHECK: call <4 x float> @llvm.cos.v4f32
-float4 test_cos_float4 ( float4 p0 ) {
-  return cos ( p0 );
-}
+float4 test_cos_float4(float4 p0) { return cos(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/dot.hlsl b/clang/test/CodeGenHLSL/builtins/dot.hlsl
index b2c1bae31d13b..c064d118caf3e 100644
--- a/clang/test/CodeGenHLSL/builtins/dot.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/dot.hlsl
@@ -9,230 +9,160 @@
 #ifdef __HLSL_ENABLE_16_BIT
 // NATIVE_HALF: %dx.dot = mul i16 %0, %1
 // NATIVE_HALF: ret i16 %dx.dot
-int16_t test_dot_short ( int16_t p0, int16_t p1 ) {
-  return dot ( p0, p1 );
-}
+int16_t test_dot_short(int16_t p0, int16_t p1) { return dot(p0, p1); }
 
 // NATIVE_HALF: %dx.dot = call i16 @llvm.dx.dot.v2i16(<2 x i16> %0, <2 x i16> %1)
 // NATIVE_HALF: ret i16 %dx.dot
-int16_t test_dot_short2 ( int16_t2 p0, int16_t2 p1 ) {
-  return dot ( p0, p1 );
-}
+int16_t test_dot_short2(int16_t2 p0, int16_t2 p1) { return dot(p0, p1); }
 
 // NATIVE_HALF: %dx.dot = call i16 @llvm.dx.dot.v3i16(<3 x i16> %0, <3 x i16> %1)
 // NATIVE_HALF: ret i16 %dx.dot
-int16_t test_dot_short3 ( int16_t3 p0, int16_t3 p1 ) {
-  return dot ( p0, p1 );
-}
+int16_t test_dot_short3(int16_t3 p0, int16_t3 p1) { return dot(p0, p1); }
 
 // NATIVE_HALF: %dx.dot = call i16 @llvm.dx.dot.v4i16(<4 x i16> %0, <4 x i16> %1)
 // NATIVE_HALF: ret i16 %dx.dot
-int16_t test_dot_short4 ( int16_t4 p0, int16_t4 p1 ) {
-  return dot ( p0, p1 );
-}
+int16_t test_dot_short4(int16_t4 p0, int16_t4 p1) { return dot(p0, p1); }
 
 // NATIVE_HALF: %dx.dot = mul i16 %0, %1
 // NATIVE_HALF: ret i16 %dx.dot
-uint16_t test_dot_ushort ( uint16_t p0, uint16_t p1 ) {
-  return dot ( p0, p1 );
-}
+uint16_t test_dot_ushort(uint16_t p0, uint16_t p1) { return dot(p0, p1); }
 
 // NATIVE_HALF: %dx.dot = call i16 @llvm.dx.dot.v2i16(<2 x i16> %0, <2 x i16> %1)
 // NATIVE_HALF: ret i16 %dx.dot
-uint16_t test_dot_ushort2 ( uint16_t2 p0, uint16_t2 p1 ) {
-  return dot ( p0, p1 );
-}
+uint16_t test_dot_ushort2(uint16_t2 p0, uint16_t2 p1) { return dot(p0, p1); }
 
 // NATIVE_HALF: %dx.dot = call i16 @llvm.dx.dot.v3i16(<3 x i16> %0, <3 x i16> %1)
 // NATIVE_HALF: ret i16 %dx.dot
-uint16_t test_dot_ushort3 ( uint16_t3 p0, uint16_t3 p1 ) {
-  return dot ( p0, p1 );
-}
+uint16_t test_dot_ushort3(uint16_t3 p0, uint16_t3 p1) { return dot(p0, p1); }
 
 // NATIVE_HALF: %dx.dot = call i16 @llvm.dx.dot.v4i16(<4 x i16> %0, <4 x i16> %1)
 // NATIVE_HALF: ret i16 %dx.dot
-uint16_t test_dot_ushort4 ( uint16_t4 p0, uint16_t4 p1 ) {
-  return dot ( p0, p1 );
-}
+uint16_t test_dot_ushort4(uint16_t4 p0, uint16_t4 p1) { return dot(p0, p1); }
 #endif
 
 // CHECK: %dx.dot = mul i32 %0, %1
 // CHECK: ret i32 %dx.dot
-int test_dot_int ( int p0, int p1 ) {
-  return dot ( p0, p1 );
-}
+int test_dot_int(int p0, int p1) { return dot(p0, p1); }
 
 // CHECK: %dx.dot = call i32 @llvm.dx.dot.v2i32(<2 x i32> %0, <2 x i32> %1)
 // CHECK: ret i32 %dx.dot
-int test_dot_int2 ( int2 p0, int2 p1 ) {
-  return dot ( p0, p1 );
-}
+int test_dot_int2(int2 p0, int2 p1) { return dot(p0, p1); }
 
 // CHECK: %dx.dot = call i32 @llvm.dx.dot.v3i32(<3 x i32> %0, <3 x i32> %1)
 // CHECK: ret i32 %dx.dot
-int test_dot_int3 ( int3 p0, int3 p1 ) {
-  return dot ( p0, p1 );
-}
+int test_dot_int3(int3 p0, int3 p1) { return dot(p0, p1); }
 
 // CHECK: %dx.dot = call i32 @llvm.dx.dot.v4i32(<4 x i32> %0, <4 x i32> %1)
 // CHECK: ret i32 %dx.dot
-int test_dot_int4 ( int4 p0, int4 p1 ) {
-  return dot ( p0, p1 );
-}
+int test_dot_int4(int4 p0, int4 p1) { return dot(p0, p1); }
 
 // CHECK: %dx.dot = mul i32 %0, %1
 // CHECK: ret i32 %dx.dot
-uint test_dot_uint ( uint p0, uint p1 ) {
-  return dot ( p0, p1 );
-}
+uint test_dot_uint(uint p0, uint p1) { return dot(p0, p1); }
 
 // CHECK: %dx.dot = call i32 @llvm.dx.dot.v2i32(<2 x i32> %0, <2 x i32> %1)
 // CHECK: ret i32 %dx.dot
-uint test_dot_uint2 ( uint2 p0, uint2 p1 ) {
-  return dot ( p0, p1 );
-}
+uint test_dot_uint2(uint2 p0, uint2 p1) { return dot(p0, p1); }
 
 // CHECK: %dx.dot = call i32 @llvm.dx.dot.v3i32(<3 x i32> %0, <3 x i32> %1)
 // CHECK: ret i32 %dx.dot
-uint test_dot_uint3 ( uint3 p0, uint3 p1 ) {
-  return dot ( p0, p1 );
-}
+uint test_dot_uint3(uint3 p0, uint3 p1) { return dot(p0, p1); }
 
 // CHECK: %dx.dot = call i32 @llvm.dx.dot.v4i32(<4 x i32> %0, <4 x i32> %1)
 // CHECK: ret i32 %dx.dot
-uint test_dot_uint4 ( uint4 p0, uint4 p1 ) {
-  return dot ( p0, p1 );
-}
+uint test_dot_uint4(uint4 p0, uint4 p1) { return dot(p0, p1); }
 
 // CHECK: %dx.dot = mul i64 %0, %1
 // CHECK: ret i64 %dx.dot
-int64_t test_dot_long ( int64_t p0, int64_t p1 ) {
-  return dot ( p0, p1 );
-}
+int64_t test_dot_long(int64_t p0, int64_t p1) { return dot(p0, p1); }
 
 // CHECK: %dx.dot = call i64 @llvm.dx.dot.v2i64(<2 x i64> %0, <2 x i64> %1)
 // CHECK: ret i64 %dx.dot
-int64_t test_dot_long2 ( int64_t2 p0, int64_t2 p1 ) {
-  return dot ( p0, p1 );
-}
+int64_t test_dot_long2(int64_t2 p0, int64_t2 p1) { return dot(p0, p1); }
 
 // CHECK: %dx.dot = call i64 @llvm.dx.dot.v3i64(<3 x i64> %0, <3 x i64> %1)
 // CHECK: ret i64 %dx.dot
-int64_t test_dot_long3 ( int64_t3 p0, int64_t3 p1 ) {
-  return dot ( p0, p1 );
-}
+int64_t test_dot_long3(int64_t3 p0, int64_t3 p1) { return dot(p0, p1); }
 
 // CHECK: %dx.dot = call i64 @llvm.dx.dot.v4i64(<4 x i64> %0, <4 x i64> %1)
 // CHECK: ret i64 %dx.dot
-int64_t test_dot_long4 ( int64_t4 p0, int64_t4 p1 ) {
-  return dot ( p0, p1 );
-}
+int64_t test_dot_long4(int64_t4 p0, int64_t4 p1) { return dot(p0, p1); }
 
 // CHECK:  %dx.dot = mul i64 %0, %1
 // CHECK: ret i64 %dx.dot
-uint64_t test_dot_ulong ( uint64_t p0, uint64_t p1 ) {
-  return dot ( p0, p1 );
-}
+uint64_t test_dot_ulong(uint64_t p0, uint64_t p1) { return dot(p0, p1); }
 
 // CHECK: %dx.dot = call i64 @llvm.dx.dot.v2i64(<2 x i64> %0, <2 x i64> %1)
 // CHECK: ret i64 %dx.dot
-uint64_t test_dot_ulong2 ( uint64_t2 p0, uint64_t2 p1 ) {
-  return dot ( p0, p1 );
-}
+uint64_t test_dot_ulong2(uint64_t2 p0, uint64_t2 p1) { return dot(p0, p1); }
 
 // CHECK: %dx.dot = call i64 @llvm.dx.dot.v3i64(<3 x i64> %0, <3 x i64> %1)
 // CHECK: ret i64 %dx.dot
-uint64_t test_dot_ulong3 ( uint64_t3 p0, uint64_t3 p1 ) {
-  return dot ( p0, p1 );
-}
+uint64_t test_dot_ulong3(uint64_t3 p0, uint64_t3 p1) { return dot(p0, p1); }
 
 // CHECK: %dx.dot = call i64 @llvm.dx.dot.v4i64(<4 x i64> %0, <4 x i64> %1)
 // CHECK: ret i64 %dx.dot
-uint64_t test_dot_ulong4 ( uint64_t4 p0, uint64_t4 p1 ) {
-  return dot ( p0, p1 );
-}
+uint64_t test_dot_ulong4(uint64_t4 p0, uint64_t4 p1) { return dot(p0, p1); }
 
 // NATIVE_HALF: %dx.dot = fmul half %0, %1
 // NATIVE_HALF: ret half %dx.dot
 // NO_HALF: %dx.dot = fmul float %0, %1
 // NO_HALF: ret float %dx.dot
-half test_dot_half ( half p0, half p1 ) {
-  return dot ( p0, p1 );
-}
+half test_dot_half(half p0, half p1) { return dot(p0, p1); }
 
 // NATIVE_HALF: %dx.dot = call half @llvm.dx.dot.v2f16(<2 x half> %0, <2 x half> %1)
 // NATIVE_HALF: ret half %dx.dot
 // NO_HALF: %dx.dot = call float @llvm.dx.dot.v2f32(<2 x float> %0, <2 x float> %1)
 // NO_HALF: ret float %dx.dot
-half test_dot_half2 ( half2 p0, half2 p1 ) {
-  return dot ( p0, p1 );
-}
+half test_dot_half2(half2 p0, half2 p1) { return dot(p0, p1); }
 
 // NATIVE_HALF: %dx.dot = call half @llvm.dx.dot.v3f16(<3 x half> %0, <3 x half> %1)
 // NATIVE_HALF: ret half %dx.dot
 // NO_HALF: %dx.dot = call float @llvm.dx.dot.v3f32(<3 x float> %0, <3 x float> %1)
 // NO_HALF: ret float %dx.dot
-half test_dot_half3 ( half3 p0, half3 p1 ) {
-  return dot ( p0, p1 );
-}
+half test_dot_half3(half3 p0, half3 p1) { return dot(p0, p1); }
 
 // NATIVE_HALF: %dx.dot = call half @llvm.dx.dot.v4f16(<4 x half> %0, <4 x half> %1)
 // NATIVE_HALF: ret half %dx.dot
 // NO_HALF: %dx.dot = call float @llvm.dx.dot.v4f32(<4 x float> %0, <4 x float> %1)
 // NO_HALF: ret float %dx.dot
-half test_dot_half4 ( half4 p0, half4 p1 ) {
-  return dot ( p0, p1 );
-}
+half test_dot_half4(half4 p0, half4 p1) { return dot(p0, p1); }
 
 // CHECK: %dx.dot = fmul float %0, %1
 // CHECK: ret float %dx.dot
-float test_dot_float ( float p0, float p1 ) {
-  return dot ( p0, p1 );
-}
+float test_dot_float(float p0, float p1) { return dot(p0, p1); }
 
 // CHECK: %dx.dot = call float @llvm.dx.dot.v2f32(<2 x float> %0, <2 x float> %1)
 // CHECK: ret float %dx.dot
-float test_dot_float2 ( float2 p0, float2 p1 ) {
-  return dot ( p0, p1 );
-}
+float test_dot_float2(float2 p0, float2 p1) { return dot(p0, p1); }
 
 // CHECK: %dx.dot = call float @llvm.dx.dot.v3f32(<3 x float> %0, <3 x float> %1)
 // CHECK: ret float %dx.dot
-float test_dot_float3 ( float3 p0, float3 p1 ) {
-  return dot ( p0, p1 );
-}
+float test_dot_float3(float3 p0, float3 p1) { return dot(p0, p1); }
 
 // CHECK: %dx.dot = call float @llvm.dx.dot.v4f32(<4 x float> %0, <4 x float> %1)
 // CHECK: ret float %dx.dot
-float test_dot_float4 ( float4 p0, float4 p1) {
-  return dot ( p0, p1 );
-}
+float test_dot_float4(float4 p0, float4 p1) { return dot(p0, p1); }
 
 // CHECK:  %dx.dot = call float @llvm.dx.dot.v2f32(<2 x float> %splat.splat, <2 x float> %1)
 // CHECK: ret float %dx.dot
-float test_dot_float2_splat ( float p0, float2 p1 ) {
-  return dot( p0, p1 );
-}
+float test_dot_float2_splat(float p0, float2 p1) { return dot(p0, p1); }
 
 // CHECK:  %dx.dot = call float @llvm.dx.dot.v3f32(<3 x float> %splat.splat, <3 x float> %1)
 // CHECK: ret float %dx.dot
-float test_dot_float3_splat ( float p0, float3 p1 ) {
-  return dot( p0, p1 );
-}
+float test_dot_float3_splat(float p0, float3 p1) { return dot(p0, p1); }
 
 // CHECK:  %dx.dot = call float @llvm.dx.dot.v4f32(<4 x float> %splat.splat, <4 x float> %1)
 // CHECK: ret float %dx.dot
-float test_dot_float4_splat ( float p0, float4 p1 ) {
-  return dot( p0, p1 );
-}
+float test_dot_float4_splat(float p0, float4 p1) { return dot(p0, p1); }
 
 // CHECK: %conv = sitofp i32 %1 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.dot = call float @llvm.dx.dot.v2f32(<2 x float> %0, <2 x float> %splat.splat)
 // CHECK: ret float %dx.dot
-float test_builtin_dot_float2_int_splat ( float2 p0, int p1 ) {
-  return dot ( p0, p1 );
+float test_builtin_dot_float2_int_splat(float2 p0, int p1) {
+  return dot(p0, p1);
 }
 
 // CHECK: %conv = sitofp i32 %1 to float
@@ -240,26 +170,24 @@ float test_builtin_dot_float2_int_splat ( float2 p0, int p1 ) {
 // CHECK: %splat.splat = shufflevector <3 x float> %splat.splatinsert, <3 x float> poison, <3 x i32> zeroinitializer
 // CHECK: %dx.dot = call float @llvm.dx.dot.v3f32(<3 x float> %0, <3 x float> %splat.splat)
 // CHECK: ret float %dx.dot
-float test_builtin_dot_float3_int_splat ( float3 p0, int p1 ) {
-  return dot ( p0, p1 );
+float test_builtin_dot_float3_int_splat(float3 p0, int p1) {
+  return dot(p0, p1);
 }
 
 // CHECK: %dx.dot = fmul double %0, %1
 // CHECK: ret double %dx.dot
-double test_dot_double ( double p0, double p1 ) {
-  return dot ( p0, p1 );
-}
+double test_dot_double(double p0, double p1) { return dot(p0, p1); }
 
 // CHECK: %conv = zext i1 %tobool to i32
 // CHECK: %dx.dot = mul i32 %conv, %1
 // CHECK: ret i32 %dx.dot
-int test_dot_bool_scalar_arg0_type_promotion ( bool p0, int p1 ) {
-  return dot ( p0, p1 );
+int test_dot_bool_scalar_arg0_type_promotion(bool p0, int p1) {
+  return dot(p0, p1);
 }
 
 // CHECK: %conv = zext i1 %tobool to i32
 // CHECK: %dx.dot = mul i32 %0, %conv
 // CHECK: ret i32 %dx.dot
-int test_dot_bool_scalar_arg1_type_promotion ( int p0, bool p1 ) {
-  return dot ( p0, p1 );
+int test_dot_bool_scalar_arg1_type_promotion(int p0, bool p1) {
+  return dot(p0, p1);
 }
diff --git a/clang/test/CodeGenHLSL/builtins/exp.hlsl b/clang/test/CodeGenHLSL/builtins/exp.hlsl
new file mode 100644
index 0000000000000..773edbe3364fd
--- /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 0000000000000..f21cdd95774ab
--- /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/floor.hlsl b/clang/test/CodeGenHLSL/builtins/floor.hlsl
index 357661761b762..d2a2f6e52f1ec 100644
--- a/clang/test/CodeGenHLSL/builtins/floor.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/floor.hlsl
@@ -1,79 +1,56 @@
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -fnative-half-type \
-// RUN:   -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ 
+// RUN:   --check-prefixes=CHECK,NATIVE_HALF
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
-// RUN:   -o - | FileCheck %s --check-prefix=NO_HALF
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
 
 using hlsl::floor;
 
-// CHECK: define noundef half @
-// CHECK: call half @llvm.floor.f16(
+// NATIVE_HALF: define noundef half @
+// NATIVE_HALF: call half @llvm.floor.f16(
 // NO_HALF: define noundef float @"?test_floor_half@@YA$halff@$halff@@Z"(
 // NO_HALF: call float @llvm.floor.f32(float %0)
-half test_floor_half ( half p0 ) {
-  return floor ( p0 );
-}
-// CHECK: define noundef <2 x half> @
-// CHECK: call <2 x half> @llvm.floor.v2f16(
+half test_floor_half(half p0) { return floor(p0); }
+// NATIVE_HALF: define noundef <2 x half> @
+// NATIVE_HALF: call <2 x half> @llvm.floor.v2f16(
 // NO_HALF: define noundef <2 x float> @"?test_floor_half2@@YAT?$__vector@$halff@$01@__clang@@T12@@Z"(
 // NO_HALF: call <2 x float> @llvm.floor.v2f32(
-half2 test_floor_half2 ( half2 p0 ) {
-  return floor ( p0 );
-}
-// CHECK: define noundef <3 x half> @
-// CHECK: call <3 x half> @llvm.floor.v3f16(
+half2 test_floor_half2(half2 p0) { return floor(p0); }
+// NATIVE_HALF: define noundef <3 x half> @
+// NATIVE_HALF: call <3 x half> @llvm.floor.v3f16(
 // NO_HALF: define noundef <3 x float> @"?test_floor_half3@@YAT?$__vector@$halff@$02@__clang@@T12@@Z"(
 // NO_HALF: call <3 x float> @llvm.floor.v3f32(
-half3 test_floor_half3 ( half3 p0 ) {
-  return floor ( p0 );
-}
-// CHECK: define noundef <4 x half> @
-// CHECK: call <4 x half> @llvm.floor.v4f16(
+half3 test_floor_half3(half3 p0) { return floor(p0); }
+// NATIVE_HALF: define noundef <4 x half> @
+// NATIVE_HALF: call <4 x half> @llvm.floor.v4f16(
 // NO_HALF: define noundef <4 x float> @"?test_floor_half4@@YAT?$__vector@$halff@$03@__clang@@T12@@Z"(
 // NO_HALF: call <4 x float> @llvm.floor.v4f32(
-half4 test_floor_half4 ( half4 p0 ) {
-  return floor ( p0 );
-}
+half4 test_floor_half4(half4 p0) { return floor(p0); }
 
 // CHECK: define noundef float @
 // CHECK: call float @llvm.floor.f32(
-float test_floor_float ( float p0 ) {
-  return floor ( p0 );
-}
+float test_floor_float(float p0) { return floor(p0); }
 // CHECK: define noundef <2 x float> @
 // CHECK: call <2 x float> @llvm.floor.v2f32(
-float2 test_floor_float2 ( float2 p0 ) {
-  return floor ( p0 );
-}
+float2 test_floor_float2(float2 p0) { return floor(p0); }
 // CHECK: define noundef <3 x float> @
 // CHECK: call <3 x float> @llvm.floor.v3f32(
-float3 test_floor_float3 ( float3 p0 ) {
-  return floor ( p0 );
-}
+float3 test_floor_float3(float3 p0) { return floor(p0); }
 // CHECK: define noundef <4 x float> @
 // CHECK: call <4 x float> @llvm.floor.v4f32(
-float4 test_floor_float4 ( float4 p0 ) {
-  return floor ( p0 );
-}
+float4 test_floor_float4(float4 p0) { return floor(p0); }
 
 // CHECK: define noundef double @
 // CHECK: call double @llvm.floor.f64(
-double test_floor_double ( double p0 ) {
-  return floor ( p0 );
-}
+double test_floor_double(double p0) { return floor(p0); }
 // CHECK: define noundef <2 x double> @
 // CHECK: call <2 x double> @llvm.floor.v2f64(
-double2 test_floor_double2 ( double2 p0 ) {
-  return floor ( p0 );
-}
+double2 test_floor_double2(double2 p0) { return floor(p0); }
 // CHECK: define noundef <3 x double> @
 // CHECK: call <3 x double> @llvm.floor.v3f64(
-double3 test_floor_double3 ( double3 p0 ) {
-  return floor ( p0 );
-}
+double3 test_floor_double3(double3 p0) { return floor(p0); }
 // CHECK: define noundef <4 x double> @
 // CHECK: call <4 x double> @llvm.floor.v4f64(
-double4 test_floor_double4 ( double4 p0 ) {
-  return floor ( p0 );
-}
+double4 test_floor_double4(double4 p0) { return floor(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/frac.hlsl b/clang/test/CodeGenHLSL/builtins/frac.hlsl
new file mode 100644
index 0000000000000..7c4d1468e96d2
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/frac.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.frac = call half @llvm.dx.frac.f16(
+// NATIVE_HALF: ret half %dx.frac
+// NO_HALF: define noundef float @"?test_frac_half@@YA$halff@$halff@@Z"(
+// NO_HALF: %dx.frac = call float @llvm.dx.frac.f32(
+// NO_HALF: ret float %dx.frac
+half test_frac_half(half p0) { return frac(p0); }
+// NATIVE_HALF: define noundef <2 x half> @
+// NATIVE_HALF: %dx.frac = call <2 x half> @llvm.dx.frac.v2f16
+// NATIVE_HALF: ret <2 x half> %dx.frac
+// NO_HALF: define noundef <2 x float> @
+// NO_HALF: %dx.frac = call <2 x float> @llvm.dx.frac.v2f32(
+// NO_HALF: ret <2 x float> %dx.frac
+half2 test_frac_half2(half2 p0) { return frac(p0); }
+// NATIVE_HALF: define noundef <3 x half> @
+// NATIVE_HALF: %dx.frac = call <3 x half> @llvm.dx.frac.v3f16
+// NATIVE_HALF: ret <3 x half> %dx.frac
+// NO_HALF: define noundef <3 x float> @
+// NO_HALF: %dx.frac = call <3 x float> @llvm.dx.frac.v3f32(
+// NO_HALF: ret <3 x float> %dx.frac
+half3 test_frac_half3(half3 p0) { return frac(p0); }
+// NATIVE_HALF: define noundef <4 x half> @
+// NATIVE_HALF: %dx.frac = call <4 x half> @llvm.dx.frac.v4f16
+// NATIVE_HALF: ret <4 x half> %dx.frac
+// NO_HALF: define noundef <4 x float> @
+// NO_HALF: %dx.frac = call <4 x float> @llvm.dx.frac.v4f32(
+// NO_HALF: ret <4 x float> %dx.frac
+half4 test_frac_half4(half4 p0) { return frac(p0); }
+
+// CHECK: define noundef float @
+// CHECK: %dx.frac = call float @llvm.dx.frac.f32(
+// CHECK: ret float %dx.frac
+float test_frac_float(float p0) { return frac(p0); }
+// CHECK: define noundef <2 x float> @
+// CHECK: %dx.frac = call <2 x float> @llvm.dx.frac.v2f32
+// CHECK: ret <2 x float> %dx.frac
+float2 test_frac_float2(float2 p0) { return frac(p0); }
+// CHECK: define noundef <3 x float> @
+// CHECK: %dx.frac = call <3 x float> @llvm.dx.frac.v3f32
+// CHECK: ret <3 x float> %dx.frac
+float3 test_frac_float3(float3 p0) { return frac(p0); }
+// CHECK: define noundef <4 x float> @
+// CHECK: %dx.frac = call <4 x float> @llvm.dx.frac.v4f32
+// CHECK: ret <4 x float> %dx.frac
+float4 test_frac_float4(float4 p0) { return frac(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl b/clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl
new file mode 100644
index 0000000000000..1f16dec68212e
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/lerp-builtin.hlsl
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple dxil-pc-shadermodel6.3-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -o - | FileCheck %s
+
+
+
+// CHECK-LABEL: builtin_lerp_half_scalar
+// CHECK: %3 = fsub double %conv1, %conv
+// CHECK: %4 = fmul double %conv2, %3
+// CHECK: %dx.lerp = fadd double %conv, %4
+// CHECK: %conv3 = fptrunc double %dx.lerp to half
+// CHECK: ret half %conv3
+half builtin_lerp_half_scalar (half p0) {
+  return __builtin_hlsl_lerp ( p0, p0, p0 );
+}
+
+// CHECK-LABEL: builtin_lerp_float_scalar
+// CHECK: %3 = fsub double %conv1, %conv
+// CHECK: %4 = fmul double %conv2, %3
+// CHECK: %dx.lerp = fadd double %conv, %4
+// CHECK: %conv3 = fptrunc double %dx.lerp to float
+// CHECK: ret float %conv3
+float builtin_lerp_float_scalar ( float p0) {
+  return __builtin_hlsl_lerp ( p0, p0, p0 );
+}
+
+// CHECK-LABEL: builtin_lerp_half_vector
+// CHECK: %dx.lerp = call <3 x half> @llvm.dx.lerp.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2)
+// CHECK: ret <3 x half> %dx.lerp
+half3 builtin_lerp_half_vector (half3 p0) {
+  return __builtin_hlsl_lerp ( p0, p0, p0 );
+}
+
+// CHECK-LABEL: builtin_lerp_floar_vector
+// CHECK: %dx.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2)
+// CHECK: ret <2 x float> %dx.lerp
+float2 builtin_lerp_floar_vector ( float2 p0) {
+  return __builtin_hlsl_lerp ( p0, p0, p0 );
+}
diff --git a/clang/test/CodeGenHLSL/builtins/lerp.hlsl b/clang/test/CodeGenHLSL/builtins/lerp.hlsl
new file mode 100644
index 0000000000000..a6b3d9643d674
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/lerp.hlsl
@@ -0,0 +1,83 @@
+// 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: %3 = fsub half %1, %0
+// NATIVE_HALF: %4 = fmul half %2, %3
+// NATIVE_HALF: %dx.lerp = fadd half %0, %4
+// NATIVE_HALF: ret half %dx.lerp
+// NO_HALF: %3 = fsub float %1, %0
+// NO_HALF: %4 = fmul float %2, %3
+// NO_HALF: %dx.lerp = fadd float %0, %4
+// NO_HALF: ret float %dx.lerp
+half test_lerp_half(half p0) { return lerp(p0, p0, p0); }
+
+// NATIVE_HALF: %dx.lerp = call <2 x half> @llvm.dx.lerp.v2f16(<2 x half> %0, <2 x half> %1, <2 x half> %2)
+// NATIVE_HALF: ret <2 x half> %dx.lerp
+// NO_HALF: %dx.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2)
+// NO_HALF: ret <2 x float> %dx.lerp
+half2 test_lerp_half2(half2 p0, half2 p1) { return lerp(p0, p0, p0); }
+
+// NATIVE_HALF: %dx.lerp = call <3 x half> @llvm.dx.lerp.v3f16(<3 x half> %0, <3 x half> %1, <3 x half> %2)
+// NATIVE_HALF: ret <3 x half> %dx.lerp
+// NO_HALF: %dx.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2)
+// NO_HALF: ret <3 x float> %dx.lerp
+half3 test_lerp_half3(half3 p0, half3 p1) { return lerp(p0, p0, p0); }
+
+// NATIVE_HALF: %dx.lerp = call <4 x half> @llvm.dx.lerp.v4f16(<4 x half> %0, <4 x half> %1, <4 x half> %2)
+// NATIVE_HALF: ret <4 x half> %dx.lerp
+// NO_HALF: %dx.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2)
+// NO_HALF: ret <4 x float> %dx.lerp
+half4 test_lerp_half4(half4 p0, half4 p1) { return lerp(p0, p0, p0); }
+
+// CHECK: %3 = fsub float %1, %0
+// CHECK: %4 = fmul float %2, %3
+// CHECK: %dx.lerp = fadd float %0, %4
+// CHECK: ret float %dx.lerp
+float test_lerp_float(float p0, float p1) { return lerp(p0, p0, p0); }
+
+// CHECK: %dx.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %2)
+// CHECK: ret <2 x float> %dx.lerp
+float2 test_lerp_float2(float2 p0, float2 p1) { return lerp(p0, p0, p0); }
+
+// CHECK: %dx.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %2)
+// CHECK: ret <3 x float> %dx.lerp
+float3 test_lerp_float3(float3 p0, float3 p1) { return lerp(p0, p0, p0); }
+
+// CHECK: %dx.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %0, <4 x float> %1, <4 x float> %2)
+// CHECK: ret <4 x float> %dx.lerp
+float4 test_lerp_float4(float4 p0, float4 p1) { return lerp(p0, p0, p0); }
+
+// CHECK: %dx.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %splat.splat, <2 x float> %1, <2 x float> %2)
+// CHECK: ret <2 x float> %dx.lerp
+float2 test_lerp_float2_splat(float p0, float2 p1) { return lerp(p0, p1, p1); }
+
+// CHECK: %dx.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %splat.splat, <3 x float> %1, <3 x float> %2)
+// CHECK: ret <3 x float> %dx.lerp
+float3 test_lerp_float3_splat(float p0, float3 p1) { return lerp(p0, p1, p1); }
+
+// CHECK:  %dx.lerp = call <4 x float> @llvm.dx.lerp.v4f32(<4 x float> %splat.splat, <4 x float> %1, <4 x float> %2)
+// CHECK:  ret <4 x float> %dx.lerp
+float4 test_lerp_float4_splat(float p0, float4 p1) { return lerp(p0, p1, p1); }
+
+// 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.lerp = call <2 x float> @llvm.dx.lerp.v2f32(<2 x float> %0, <2 x float> %1, <2 x float> %splat.splat)
+// CHECK: ret <2 x float> %dx.lerp
+float2 test_lerp_float2_int_splat(float2 p0, int p1) {
+  return lerp(p0, p0, p1);
+}
+
+// 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.lerp = call <3 x float> @llvm.dx.lerp.v3f32(<3 x float> %0, <3 x float> %1, <3 x float> %splat.splat)
+// CHECK: ret <3 x float> %dx.lerp
+float3 test_lerp_float3_int_splat(float3 p0, int p1) {
+  return lerp(p0, p0, p1);
+}
diff --git a/clang/test/CodeGenHLSL/builtins/log.hlsl b/clang/test/CodeGenHLSL/builtins/log.hlsl
index 6a8e4ac2e5f29..ecbdf1e98ac34 100644
--- a/clang/test/CodeGenHLSL/builtins/log.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/log.hlsl
@@ -1,56 +1,41 @@
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -fnative-half-type \
-// RUN:   -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ 
+// RUN:   --check-prefixes=CHECK,NATIVE_HALF
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
-// RUN:   -o - | FileCheck %s --check-prefix=NO_HALF
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
 
-// CHECK: define noundef half @
-// CHECK: call half @llvm.log.f16(
+// NATIVE_HALF: define noundef half @
+// NATIVE_HALF: call half @llvm.log.f16(
 // NO_HALF: define noundef float @"?test_log_half@@YA$halff@$halff@@Z"(
 // NO_HALF: call float @llvm.log.f32(
-half test_log_half ( half p0 ) {
-  return log ( p0 );
-}
-// CHECK: define noundef <2 x half> @
-// CHECK: call <2 x half> @llvm.log.v2f16
-// NO_HALF: define noundef <2 x float> @"?test_log_float2@@YAT?$__vector@M$01@__clang@@T12@@Z"(
+half test_log_half(half p0) { return log(p0); }
+// NATIVE_HALF: define noundef <2 x half> @
+// NATIVE_HALF: call <2 x half> @llvm.log.v2f16
+// NO_HALF: define noundef <2 x float> @"?test_log_half2
 // NO_HALF: call <2 x float> @llvm.log.v2f32(
-half2 test_log_half2 ( half2 p0 ) {
-  return log ( p0 );
-}
-// CHECK: define noundef <3 x half> @
-// CHECK: call <3 x half> @llvm.log.v3f16
-// NO_HALF: define noundef <3 x float> @"?test_log_float3@@YAT?$__vector@M$02@__clang@@T12@@Z"(
+half2 test_log_half2(half2 p0) { return log(p0); }
+// NATIVE_HALF: define noundef <3 x half> @
+// NATIVE_HALF: call <3 x half> @llvm.log.v3f16
+// NO_HALF: define noundef <3 x float> @"?test_log_half3
 // NO_HALF: call <3 x float> @llvm.log.v3f32(
-half3 test_log_half3 ( half3 p0 ) {
-  return log ( p0 );
-}
-// CHECK: define noundef <4 x half> @
-// CHECK: call <4 x half> @llvm.log.v4f16
-// NO_HALF: define noundef <4 x float> @"?test_log_float4@@YAT?$__vector@M$03@__clang@@T12@@Z"(
+half3 test_log_half3(half3 p0) { return log(p0); }
+// NATIVE_HALF: define noundef <4 x half> @
+// NATIVE_HALF: call <4 x half> @llvm.log.v4f16
+// NO_HALF: define noundef <4 x float> @"?test_log_half4
 // NO_HALF: call <4 x float> @llvm.log.v4f32(
-half4 test_log_half4 ( half4 p0 ) {
-  return log ( p0 );
-}
+half4 test_log_half4(half4 p0) { return log(p0); }
 
-// CHECK: define noundef float @
+// CHECK: define noundef float @"?test_log_float
 // CHECK: call float @llvm.log.f32(
-float test_log_float ( float p0 ) {
-  return log ( p0 );
-}
-// CHECK: define noundef <2 x float> @
+float test_log_float(float p0) { return log(p0); }
+// CHECK: define noundef <2 x float> @"?test_log_float2
 // CHECK: call <2 x float> @llvm.log.v2f32
-float2 test_log_float2 ( float2 p0 ) {
-  return log ( p0 );
-}
-// CHECK: define noundef <3 x float> @
+float2 test_log_float2(float2 p0) { return log(p0); }
+// CHECK: define noundef <3 x float> @"?test_log_float3
 // CHECK: call <3 x float> @llvm.log.v3f32
-float3 test_log_float3 ( float3 p0 ) {
-  return log ( p0 );
-}
-// CHECK: define noundef <4 x float> @
+float3 test_log_float3(float3 p0) { return log(p0); }
+// CHECK: define noundef <4 x float> @"?test_log_float4
 // CHECK: call <4 x float> @llvm.log.v4f32
-float4 test_log_float4 ( float4 p0 ) {
-  return log ( p0 );
-}
+float4 test_log_float4(float4 p0) { return log(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/log10.hlsl b/clang/test/CodeGenHLSL/builtins/log10.hlsl
index 8ce24fd530dd3..638b86e8d5eaf 100644
--- a/clang/test/CodeGenHLSL/builtins/log10.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/log10.hlsl
@@ -1,56 +1,41 @@
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -fnative-half-type \
-// RUN:   -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ 
+// RUN:   --check-prefixes=CHECK,NATIVE_HALF
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
-// RUN:   -o - | FileCheck %s --check-prefix=NO_HALF
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
 
-// CHECK: define noundef half @
-// CHECK: call half @llvm.log10.f16(
-// NO_HALF: define noundef float @"?test_log10_half@@YA$halff@$halff@@Z"(
+// NATIVE_HALF: define noundef half @
+// NATIVE_HALF: call half @llvm.log10.f16(
+// NO_HALF: define noundef float @"?test_log10_half
 // NO_HALF: call float @llvm.log10.f32(
-half test_log10_half ( half p0 ) {
-  return log10 ( p0 );
-}
-// CHECK: define noundef <2 x half> @
-// CHECK: call <2 x half> @llvm.log10.v2f16
-// NO_HALF: define noundef <2 x float> @"?test_log10_float2@@YAT?$__vector@M$01@__clang@@T12@@Z"(
+half test_log10_half(half p0) { return log10(p0); }
+// NATIVE_HALF: define noundef <2 x half> @
+// NATIVE_HALF: call <2 x half> @llvm.log10.v2f16
+// NO_HALF: define noundef <2 x float> @"?test_log10_half2
 // NO_HALF: call <2 x float> @llvm.log10.v2f32(
-half2 test_log10_half2 ( half2 p0 ) {
-  return log10 ( p0 );
-}
-// CHECK: define noundef <3 x half> @
-// CHECK: call <3 x half> @llvm.log10.v3f16
-// NO_HALF: define noundef <3 x float> @"?test_log10_float3@@YAT?$__vector@M$02@__clang@@T12@@Z"(
+half2 test_log10_half2(half2 p0) { return log10(p0); }
+// NATIVE_HALF: define noundef <3 x half> @
+// NATIVE_HALF: call <3 x half> @llvm.log10.v3f16
+// NO_HALF: define noundef <3 x float> @"?test_log10_half3
 // NO_HALF: call <3 x float> @llvm.log10.v3f32(
-half3 test_log10_half3 ( half3 p0 ) {
-  return log10 ( p0 );
-}
-// CHECK: define noundef <4 x half> @
-// CHECK: call <4 x half> @llvm.log10.v4f16
-// NO_HALF: define noundef <4 x float> @"?test_log10_float4@@YAT?$__vector@M$03@__clang@@T12@@Z"(
+half3 test_log10_half3(half3 p0) { return log10(p0); }
+// NATIVE_HALF: define noundef <4 x half> @
+// NATIVE_HALF: call <4 x half> @llvm.log10.v4f16
+// NO_HALF: define noundef <4 x float> @"?test_log10_half4
 // NO_HALF: call <4 x float> @llvm.log10.v4f32(
-half4 test_log10_half4 ( half4 p0 ) {
-  return log10 ( p0 );
-}
+half4 test_log10_half4(half4 p0) { return log10(p0); }
 
-// CHECK: define noundef float @
+// CHECK: define noundef float @"?test_log10_float
 // CHECK: call float @llvm.log10.f32(
-float test_log10_float ( float p0 ) {
-  return log10 ( p0 );
-}
-// CHECK: define noundef <2 x float> @
+float test_log10_float(float p0) { return log10(p0); }
+// CHECK: define noundef <2 x float> @"?test_log10_float2
 // CHECK: call <2 x float> @llvm.log10.v2f32
-float2 test_log10_float2 ( float2 p0 ) {
-  return log10 ( p0 );
-}
-// CHECK: define noundef <3 x float> @
+float2 test_log10_float2(float2 p0) { return log10(p0); }
+// CHECK: define noundef <3 x float> @"?test_log10_float3
 // CHECK: call <3 x float> @llvm.log10.v3f32
-float3 test_log10_float3 ( float3 p0 ) {
-  return log10 ( p0 );
-}
-// CHECK: define noundef <4 x float> @
+float3 test_log10_float3(float3 p0) { return log10(p0); }
+// CHECK: define noundef <4 x float> @"?test_log10_float4
 // CHECK: call <4 x float> @llvm.log10.v4f32
-float4 test_log10_float4 ( float4 p0 ) {
-  return log10 ( p0 );
-}
+float4 test_log10_float4(float4 p0) { return log10(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/log2.hlsl b/clang/test/CodeGenHLSL/builtins/log2.hlsl
index f0f0a6c7c50e8..9ed8185a06b04 100644
--- a/clang/test/CodeGenHLSL/builtins/log2.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/log2.hlsl
@@ -1,56 +1,41 @@
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -fnative-half-type \
-// RUN:   -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ 
+// RUN:   --check-prefixes=CHECK,NATIVE_HALF
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
-// RUN:   -o - | FileCheck %s --check-prefix=NO_HALF
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
 
-// CHECK: define noundef half @
-// CHECK: call half @llvm.log2.f16(
-// NO_HALF: define noundef float @"?test_log2_half@@YA$halff@$halff@@Z"(
+// NATIVE_HALF: define noundef half @
+// NATIVE_HALF: call half @llvm.log2.f16(
+// NO_HALF: define noundef float @"?test_log2_half
 // NO_HALF: call float @llvm.log2.f32(
-half test_log2_half ( half p0 ) {
-  return log2 ( p0 );
-}
-// CHECK: define noundef <2 x half> @
-// CHECK: call <2 x half> @llvm.log2.v2f16
-// NO_HALF: define noundef <2 x float> @"?test_log2_float2@@YAT?$__vector@M$01@__clang@@T12@@Z"(
+half test_log2_half(half p0) { return log2(p0); }
+// NATIVE_HALF: define noundef <2 x half> @
+// NATIVE_HALF: call <2 x half> @llvm.log2.v2f16
+// NO_HALF: define noundef <2 x float> @"?test_log2_half2
 // NO_HALF: call <2 x float> @llvm.log2.v2f32(
-half2 test_log2_half2 ( half2 p0 ) {
-  return log2 ( p0 );
-}
-// CHECK: define noundef <3 x half> @
-// CHECK: call <3 x half> @llvm.log2.v3f16
-// NO_HALF: define noundef <3 x float> @"?test_log2_float3@@YAT?$__vector@M$02@__clang@@T12@@Z"(
+half2 test_log2_half2(half2 p0) { return log2(p0); }
+// NATIVE_HALF: define noundef <3 x half> @
+// NATIVE_HALF: call <3 x half> @llvm.log2.v3f16
+// NO_HALF: define noundef <3 x float> @"?test_log2_half3
 // NO_HALF: call <3 x float> @llvm.log2.v3f32(
-half3 test_log2_half3 ( half3 p0 ) {
-  return log2 ( p0 );
-}
-// CHECK: define noundef <4 x half> @
-// CHECK: call <4 x half> @llvm.log2.v4f16
-// NO_HALF: define noundef <4 x float> @"?test_log2_float4@@YAT?$__vector@M$03@__clang@@T12@@Z"(
+half3 test_log2_half3(half3 p0) { return log2(p0); }
+// NATIVE_HALF: define noundef <4 x half> @
+// NATIVE_HALF: call <4 x half> @llvm.log2.v4f16
+// NO_HALF: define noundef <4 x float> @"?test_log2_half4
 // NO_HALF: call <4 x float> @llvm.log2.v4f32(
-half4 test_log2_half4 ( half4 p0 ) {
-  return log2 ( p0 );
-}
+half4 test_log2_half4(half4 p0) { return log2(p0); }
 
-// CHECK: define noundef float @
+// CHECK: define noundef float @"?test_log2_float
 // CHECK: call float @llvm.log2.f32(
-float test_log2_float ( float p0 ) {
-  return log2 ( p0 );
-}
-// CHECK: define noundef <2 x float> @
+float test_log2_float(float p0) { return log2(p0); }
+// CHECK: define noundef <2 x float> @"?test_log2_float2
 // CHECK: call <2 x float> @llvm.log2.v2f32
-float2 test_log2_float2 ( float2 p0 ) {
-  return log2 ( p0 );
-}
-// CHECK: define noundef <3 x float> @
+float2 test_log2_float2(float2 p0) { return log2(p0); }
+// CHECK: define noundef <3 x float> @"?test_log2_float3
 // CHECK: call <3 x float> @llvm.log2.v3f32
-float3 test_log2_float3 ( float3 p0 ) {
-  return log2 ( p0 );
-}
-// CHECK: define noundef <4 x float> @
+float3 test_log2_float3(float3 p0) { return log2(p0); }
+// CHECK: define noundef <4 x float> @"?test_log2_float4
 // CHECK: call <4 x float> @llvm.log2.v4f32
-float4 test_log2_float4 ( float4 p0 ) {
-  return log2 ( p0 );
-}
+float4 test_log2_float4(float4 p0) { return log2(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/mad.hlsl b/clang/test/CodeGenHLSL/builtins/mad.hlsl
new file mode 100644
index 0000000000000..749eac6d64736
--- /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/max.hlsl b/clang/test/CodeGenHLSL/builtins/max.hlsl
index d8879c3332fb8..272d1e8a10bd7 100644
--- a/clang/test/CodeGenHLSL/builtins/max.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/max.hlsl
@@ -1,206 +1,134 @@
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -fnative-half-type \
-// RUN:   -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ 
+// RUN:   --check-prefixes=CHECK,NATIVE_HALF
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
-// RUN:   -o - | FileCheck %s --check-prefix=NO_HALF
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
 
 #ifdef __HLSL_ENABLE_16_BIT
-// CHECK: define noundef i16 @
-// CHECK: call i16 @llvm.smax.i16(
-int16_t test_max_short ( int16_t p0, int16_t p1 ) {
-  return max ( p0, p1 );
-}
-// CHECK: define noundef <2 x i16> @
-// CHECK: call <2 x i16> @llvm.smax.v2i16(
-int16_t2 test_max_short2 ( int16_t2 p0, int16_t2 p1 ) {
-  return max ( p0, p1 );
-}
-// CHECK: define noundef <3 x i16> @
-// CHECK: call <3 x i16> @llvm.smax.v3i16
-int16_t3 test_max_short3 ( int16_t3 p0, int16_t3 p1 ) {
-  return max ( p0, p1 );
-}
-// CHECK: define noundef <4 x i16> @
-// CHECK: call <4 x i16> @llvm.smax.v4i16
-int16_t4 test_max_short4 ( int16_t4 p0, int16_t4 p1 ) {
-  return max ( p0, p1 );
-}
+// NATIVE_HALF: define noundef i16 @
+// NATIVE_HALF: call i16 @llvm.smax.i16(
+int16_t test_max_short(int16_t p0, int16_t p1) { return max(p0, p1); }
+// NATIVE_HALF: define noundef <2 x i16> @
+// NATIVE_HALF: call <2 x i16> @llvm.smax.v2i16(
+int16_t2 test_max_short2(int16_t2 p0, int16_t2 p1) { return max(p0, p1); }
+// NATIVE_HALF: define noundef <3 x i16> @
+// NATIVE_HALF: call <3 x i16> @llvm.smax.v3i16
+int16_t3 test_max_short3(int16_t3 p0, int16_t3 p1) { return max(p0, p1); }
+// NATIVE_HALF: define noundef <4 x i16> @
+// NATIVE_HALF: call <4 x i16> @llvm.smax.v4i16
+int16_t4 test_max_short4(int16_t4 p0, int16_t4 p1) { return max(p0, p1); }
 
-// CHECK: define noundef i16 @
-// CHECK: call i16 @llvm.umax.i16(
-uint16_t test_max_ushort ( uint16_t p0, uint16_t p1 ) {
-  return max ( p0, p1 );
-}
-// CHECK: define noundef <2 x i16> @
-// CHECK: call <2 x i16> @llvm.umax.v2i16
-uint16_t2 test_max_ushort2 ( uint16_t2 p0, uint16_t2 p1 ) {
-  return max ( p0, p1 );
-}
-// CHECK: define noundef <3 x i16> @
-// CHECK: call <3 x i16> @llvm.umax.v3i16
-uint16_t3 test_max_ushort3 ( uint16_t3 p0, uint16_t3 p1 ) {
-  return max ( p0, p1 );
-}
-// CHECK: define noundef <4 x i16> @
-// CHECK: call <4 x i16> @llvm.umax.v4i16
-uint16_t4 test_max_ushort4 ( uint16_t4 p0, uint16_t4 p1 ) {
-  return max ( p0, p1 );
-}
+// NATIVE_HALF: define noundef i16 @
+// NATIVE_HALF: call i16 @llvm.umax.i16(
+uint16_t test_max_ushort(uint16_t p0, uint16_t p1) { return max(p0, p1); }
+// NATIVE_HALF: define noundef <2 x i16> @
+// NATIVE_HALF: call <2 x i16> @llvm.umax.v2i16
+uint16_t2 test_max_ushort2(uint16_t2 p0, uint16_t2 p1) { return max(p0, p1); }
+// NATIVE_HALF: define noundef <3 x i16> @
+// NATIVE_HALF: call <3 x i16> @llvm.umax.v3i16
+uint16_t3 test_max_ushort3(uint16_t3 p0, uint16_t3 p1) { return max(p0, p1); }
+// NATIVE_HALF: define noundef <4 x i16> @
+// NATIVE_HALF: call <4 x i16> @llvm.umax.v4i16
+uint16_t4 test_max_ushort4(uint16_t4 p0, uint16_t4 p1) { return max(p0, p1); }
 #endif
 
 // CHECK: define noundef i32 @
 // CHECK: call i32 @llvm.smax.i32(
-int test_max_int ( int p0, int p1 ) {
-  return max ( p0, p1 );
-}
+int test_max_int(int p0, int p1) { return max(p0, p1); }
 // CHECK: define noundef <2 x i32> @
 // CHECK: call <2 x i32> @llvm.smax.v2i32
-int2 test_max_int2 ( int2 p0, int2 p1 ) {
-  return max ( p0, p1 );
-}
+int2 test_max_int2(int2 p0, int2 p1) { return max(p0, p1); }
 // CHECK: define noundef <3 x i32> @
 // CHECK: call <3 x i32> @llvm.smax.v3i32
-int3 test_max_int3 ( int3 p0, int3 p1 ) {
-  return max ( p0, p1 );
-}
+int3 test_max_int3(int3 p0, int3 p1) { return max(p0, p1); }
 // CHECK: define noundef <4 x i32> @
 // CHECK: call <4 x i32> @llvm.smax.v4i32
-int4 test_max_int4 ( int4 p0, int4 p1) {
-  return max ( p0, p1 );
-}
+int4 test_max_int4(int4 p0, int4 p1) { return max(p0, p1); }
 
 // CHECK: define noundef i32 @
 // CHECK: call i32 @llvm.umax.i32(
-int test_max_uint ( uint p0, uint p1 ) {
-  return max ( p0, p1 );
-}
+int test_max_uint(uint p0, uint p1) { return max(p0, p1); }
 // CHECK: define noundef <2 x i32> @
 // CHECK: call <2 x i32> @llvm.umax.v2i32
-uint2 test_max_uint2 ( uint2 p0, uint2 p1 ) {
-  return max ( p0, p1 );
-}
+uint2 test_max_uint2(uint2 p0, uint2 p1) { return max(p0, p1); }
 // CHECK: define noundef <3 x i32> @
 // CHECK: call <3 x i32> @llvm.umax.v3i32
-uint3 test_max_uint3 ( uint3 p0, uint3 p1 ) {
-  return max ( p0, p1 );
-}
+uint3 test_max_uint3(uint3 p0, uint3 p1) { return max(p0, p1); }
 // CHECK: define noundef <4 x i32> @
 // CHECK: call <4 x i32> @llvm.umax.v4i32
-uint4 test_max_uint4 ( uint4 p0, uint4 p1) {
-  return max ( p0, p1 );
-}
+uint4 test_max_uint4(uint4 p0, uint4 p1) { return max(p0, p1); }
 
 // CHECK: define noundef i64 @
 // CHECK: call i64 @llvm.smax.i64(
-int64_t test_max_long ( int64_t p0, int64_t p1 ) {
-  return max ( p0, p1 );
-}
+int64_t test_max_long(int64_t p0, int64_t p1) { return max(p0, p1); }
 // CHECK: define noundef <2 x i64> @
 // CHECK: call <2 x i64> @llvm.smax.v2i64
-int64_t2 test_max_long2 ( int64_t2 p0, int64_t2 p1 ) {
-  return max ( p0, p1 );
-}
+int64_t2 test_max_long2(int64_t2 p0, int64_t2 p1) { return max(p0, p1); }
 // CHECK: define noundef <3 x i64> @
 // CHECK: call <3 x i64> @llvm.smax.v3i64
-int64_t3 test_max_long3 ( int64_t3 p0, int64_t3 p1 ) {
-  return max ( p0, p1 );
-}
+int64_t3 test_max_long3(int64_t3 p0, int64_t3 p1) { return max(p0, p1); }
 // CHECK: define noundef <4 x i64> @
 // CHECK: call <4 x i64> @llvm.smax.v4i64
-int64_t4 test_max_long4 ( int64_t4 p0, int64_t4 p1) {
-  return max ( p0, p1 );
-}
+int64_t4 test_max_long4(int64_t4 p0, int64_t4 p1) { return max(p0, p1); }
 
 // CHECK: define noundef i64 @
 // CHECK: call i64 @llvm.umax.i64(
-uint64_t test_max_long ( uint64_t p0, uint64_t p1 ) {
-  return max ( p0, p1 );
-}
+uint64_t test_max_long(uint64_t p0, uint64_t p1) { return max(p0, p1); }
 // CHECK: define noundef <2 x i64> @
 // CHECK: call <2 x i64> @llvm.umax.v2i64
-uint64_t2 test_max_long2 ( uint64_t2 p0, uint64_t2 p1 ) {
-  return max ( p0, p1 );
-}
+uint64_t2 test_max_long2(uint64_t2 p0, uint64_t2 p1) { return max(p0, p1); }
 // CHECK: define noundef <3 x i64> @
 // CHECK: call <3 x i64> @llvm.umax.v3i64
-uint64_t3 test_max_long3 ( uint64_t3 p0, uint64_t3 p1 ) {
-  return max ( p0, p1 );
-}
+uint64_t3 test_max_long3(uint64_t3 p0, uint64_t3 p1) { return max(p0, p1); }
 // CHECK: define noundef <4 x i64> @
 // CHECK: call <4 x i64> @llvm.umax.v4i64
-uint64_t4 test_max_long4 ( uint64_t4 p0, uint64_t4 p1) {
-  return max ( p0, p1 );
-}
+uint64_t4 test_max_long4(uint64_t4 p0, uint64_t4 p1) { return max(p0, p1); }
 
-
-// CHECK: define noundef half @
-// CHECK: call half @llvm.maxnum.f16(
-// NO_HALF: define noundef float @"?test_max_half@@YA$halff@$halff@0@Z"(
+// NATIVE_HALF: define noundef half @
+// NATIVE_HALF: call half @llvm.maxnum.f16(
+// NO_HALF: define noundef float @"?test_max_half
 // NO_HALF: call float @llvm.maxnum.f32(
-half test_max_half ( half p0, half p1 ) {
-  return max ( p0, p1 );
-}
-// CHECK: define noundef <2 x half> @
-// CHECK: call <2 x half> @llvm.maxnum.v2f16
-// NO_HALF: define noundef <2 x float> @"?test_max_float2@@YAT?$__vector@M$01@__clang@@T12@0@Z"(
+half test_max_half(half p0, half p1) { return max(p0, p1); }
+// NATIVE_HALF: define noundef <2 x half> @
+// NATIVE_HALF: call <2 x half> @llvm.maxnum.v2f16
+// NO_HALF: define noundef <2 x float> @"?test_max_half2
 // NO_HALF: call <2 x float> @llvm.maxnum.v2f32(
-half2 test_max_half2 ( half2 p0, half2 p1 ) {
-  return max ( p0, p1 );
-}
-// CHECK: define noundef <3 x half> @
-// CHECK: call <3 x half> @llvm.maxnum.v3f16
-// NO_HALF: define noundef <3 x float> @"?test_max_float3@@YAT?$__vector@M$02@__clang@@T12@0@Z"(
+half2 test_max_half2(half2 p0, half2 p1) { return max(p0, p1); }
+// NATIVE_HALF: define noundef <3 x half> @
+// NATIVE_HALF: call <3 x half> @llvm.maxnum.v3f16
+// NO_HALF: define noundef <3 x float> @"?test_max_half3
 // NO_HALF: call <3 x float> @llvm.maxnum.v3f32(
-half3 test_max_half3 ( half3 p0, half3 p1 ) {
-  return max ( p0, p1 );
-}
-// CHECK: define noundef <4 x half> @
-// CHECK: call <4 x half> @llvm.maxnum.v4f16
-// NO_HALF: define noundef <4 x float> @"?test_max_float4@@YAT?$__vector@M$03@__clang@@T12@0@Z"(
+half3 test_max_half3(half3 p0, half3 p1) { return max(p0, p1); }
+// NATIVE_HALF: define noundef <4 x half> @
+// NATIVE_HALF: call <4 x half> @llvm.maxnum.v4f16
+// NO_HALF: define noundef <4 x float> @"?test_max_half4
 // NO_HALF: call <4 x float> @llvm.maxnum.v4f32(
-half4 test_max_half4 ( half4 p0, half4 p1 ) {
-  return max ( p0, p1 );
-}
+half4 test_max_half4(half4 p0, half4 p1) { return max(p0, p1); }
 
-// CHECK: define noundef float @
+// CHECK: define noundef float @"?test_max_float
 // CHECK: call float @llvm.maxnum.f32(
-float test_max_float ( float p0, float p1 ) {
-  return max ( p0, p1 );
-}
-// CHECK: define noundef <2 x float> @
+float test_max_float(float p0, float p1) { return max(p0, p1); }
+// CHECK: define noundef <2 x float> @"?test_max_float2
 // CHECK: call <2 x float> @llvm.maxnum.v2f32
-float2 test_max_float2 ( float2 p0, float2 p1 ) {
-  return max ( p0, p1 );
-}
-// CHECK: define noundef <3 x float> @
+float2 test_max_float2(float2 p0, float2 p1) { return max(p0, p1); }
+// CHECK: define noundef <3 x float> @"?test_max_float3
 // CHECK: call <3 x float> @llvm.maxnum.v3f32
-float3 test_max_float3 ( float3 p0, float3 p1 ) {
-  return max ( p0, p1 );
-}
-// CHECK: define noundef <4 x float> @
+float3 test_max_float3(float3 p0, float3 p1) { return max(p0, p1); }
+// CHECK: define noundef <4 x float> @"?test_max_float4
 // CHECK: call <4 x float> @llvm.maxnum.v4f32
-float4 test_max_float4 ( float4 p0, float4 p1) {
-  return max ( p0, p1 );
-}
+float4 test_max_float4(float4 p0, float4 p1) { return max(p0, p1); }
 
 // CHECK: define noundef double @
 // CHECK: call double @llvm.maxnum.f64(
-double test_max_double ( double p0, double p1 ) {
-  return max ( p0, p1 );
-}
+double test_max_double(double p0, double p1) { return max(p0, p1); }
 // CHECK: define noundef <2 x double> @
 // CHECK: call <2 x double> @llvm.maxnum.v2f64
-double2 test_max_double2 ( double2 p0, double2 p1 ) {
-  return max ( p0, p1 );
-}
+double2 test_max_double2(double2 p0, double2 p1) { return max(p0, p1); }
 // CHECK: define noundef <3 x double> @
 // CHECK: call <3 x double> @llvm.maxnum.v3f64
-double3 test_max_double3 ( double3 p0, double3 p1 ) {
-  return max ( p0, p1 );
-}
+double3 test_max_double3(double3 p0, double3 p1) { return max(p0, p1); }
 // CHECK: define noundef <4 x double> @
 // CHECK: call <4 x double> @llvm.maxnum.v4f64
-double4 test_max_double4 ( double4 p0, double4 p1) {
-  return max ( p0, p1 );
-}
+double4 test_max_double4(double4 p0, double4 p1) { return max(p0, p1); }
diff --git a/clang/test/CodeGenHLSL/builtins/min.hlsl b/clang/test/CodeGenHLSL/builtins/min.hlsl
index 743053cbdd262..a0c233dac4d5f 100644
--- a/clang/test/CodeGenHLSL/builtins/min.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/min.hlsl
@@ -1,207 +1,134 @@
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -fnative-half-type \
-// RUN:   -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ 
+// RUN:   --check-prefixes=CHECK,NATIVE_HALF
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
-// RUN:   -o - | FileCheck %s --check-prefix=NO_HALF
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
 
 #ifdef __HLSL_ENABLE_16_BIT
-// CHECK: define noundef i16 @
-// CHECK: call i16 @llvm.smin.i16(
-int16_t test_min_short ( int16_t p0, int16_t p1 ) {
-  return min ( p0, p1 );
-}
-// CHECK: define noundef <2 x i16> @
-// CHECK: call <2 x i16> @llvm.smin.v2i16(
-int16_t2 test_min_short2 ( int16_t2 p0, int16_t2 p1 ) {
-  return min ( p0, p1 );
-}
-// CHECK: define noundef <3 x i16> @
-// CHECK: call <3 x i16> @llvm.smin.v3i16
-int16_t3 test_min_short3 ( int16_t3 p0, int16_t3 p1 ) {
-  return min ( p0, p1 );
-}
-// CHECK: define noundef <4 x i16> @
-// CHECK: call <4 x i16> @llvm.smin.v4i16
-int16_t4 test_min_short4 ( int16_t4 p0, int16_t4 p1 ) {
-  return min ( p0, p1 );
-}
+// NATIVE_HALF: define noundef i16 @
+// NATIVE_HALF: call i16 @llvm.smin.i16(
+int16_t test_min_short(int16_t p0, int16_t p1) { return min(p0, p1); }
+// NATIVE_HALF: define noundef <2 x i16> @
+// NATIVE_HALF: call <2 x i16> @llvm.smin.v2i16(
+int16_t2 test_min_short2(int16_t2 p0, int16_t2 p1) { return min(p0, p1); }
+// NATIVE_HALF: define noundef <3 x i16> @
+// NATIVE_HALF: call <3 x i16> @llvm.smin.v3i16
+int16_t3 test_min_short3(int16_t3 p0, int16_t3 p1) { return min(p0, p1); }
+// NATIVE_HALF: define noundef <4 x i16> @
+// NATIVE_HALF: call <4 x i16> @llvm.smin.v4i16
+int16_t4 test_min_short4(int16_t4 p0, int16_t4 p1) { return min(p0, p1); }
 
-
-// CHECK: define noundef i16 @
-// CHECK: call i16 @llvm.umin.i16(
-uint16_t test_min_ushort ( uint16_t p0, uint16_t p1 ) {
-  return min ( p0, p1 );
-}
-// CHECK: define noundef <2 x i16> @
-// CHECK: call <2 x i16> @llvm.umin.v2i16
-uint16_t2 test_min_ushort2 ( uint16_t2 p0, uint16_t2 p1 ) {
-  return min ( p0, p1 );
-}
-// CHECK: define noundef <3 x i16> @
-// CHECK: call <3 x i16> @llvm.umin.v3i16
-uint16_t3 test_min_ushort3 ( uint16_t3 p0, uint16_t3 p1 ) {
-  return min ( p0, p1 );
-}
-// CHECK: define noundef <4 x i16> @
-// CHECK: call <4 x i16> @llvm.umin.v4i16
-uint16_t4 test_min_ushort4 ( uint16_t4 p0, uint16_t4 p1 ) {
-  return min ( p0, p1 );
-}
+// NATIVE_HALF: define noundef i16 @
+// NATIVE_HALF: call i16 @llvm.umin.i16(
+uint16_t test_min_ushort(uint16_t p0, uint16_t p1) { return min(p0, p1); }
+// NATIVE_HALF: define noundef <2 x i16> @
+// NATIVE_HALF: call <2 x i16> @llvm.umin.v2i16
+uint16_t2 test_min_ushort2(uint16_t2 p0, uint16_t2 p1) { return min(p0, p1); }
+// NATIVE_HALF: define noundef <3 x i16> @
+// NATIVE_HALF: call <3 x i16> @llvm.umin.v3i16
+uint16_t3 test_min_ushort3(uint16_t3 p0, uint16_t3 p1) { return min(p0, p1); }
+// NATIVE_HALF: define noundef <4 x i16> @
+// NATIVE_HALF: call <4 x i16> @llvm.umin.v4i16
+uint16_t4 test_min_ushort4(uint16_t4 p0, uint16_t4 p1) { return min(p0, p1); }
 #endif
 
 // CHECK: define noundef i32 @
 // CHECK: call i32 @llvm.smin.i32(
-int test_min_int ( int p0, int p1 ) {
-  return min ( p0, p1 );
-}
+int test_min_int(int p0, int p1) { return min(p0, p1); }
 // CHECK: define noundef <2 x i32> @
 // CHECK: call <2 x i32> @llvm.smin.v2i32
-int2 test_min_int2 ( int2 p0, int2 p1 ) {
-  return min ( p0, p1 );
-}
+int2 test_min_int2(int2 p0, int2 p1) { return min(p0, p1); }
 // CHECK: define noundef <3 x i32> @
 // CHECK: call <3 x i32> @llvm.smin.v3i32
-int3 test_min_int3 ( int3 p0, int3 p1 ) {
-  return min ( p0, p1 );
-}
+int3 test_min_int3(int3 p0, int3 p1) { return min(p0, p1); }
 // CHECK: define noundef <4 x i32> @
 // CHECK: call <4 x i32> @llvm.smin.v4i32
-int4 test_min_int4 ( int4 p0, int4 p1) {
-  return min ( p0, p1 );
-}
+int4 test_min_int4(int4 p0, int4 p1) { return min(p0, p1); }
 
 // CHECK: define noundef i32 @
 // CHECK: call i32 @llvm.umin.i32(
-int test_min_uint ( uint p0, uint p1 ) {
-  return min ( p0, p1 );
-}
+int test_min_uint(uint p0, uint p1) { return min(p0, p1); }
 // CHECK: define noundef <2 x i32> @
 // CHECK: call <2 x i32> @llvm.umin.v2i32
-uint2 test_min_uint2 ( uint2 p0, uint2 p1 ) {
-  return min ( p0, p1 );
-}
+uint2 test_min_uint2(uint2 p0, uint2 p1) { return min(p0, p1); }
 // CHECK: define noundef <3 x i32> @
 // CHECK: call <3 x i32> @llvm.umin.v3i32
-uint3 test_min_uint3 ( uint3 p0, uint3 p1 ) {
-  return min ( p0, p1 );
-}
+uint3 test_min_uint3(uint3 p0, uint3 p1) { return min(p0, p1); }
 // CHECK: define noundef <4 x i32> @
 // CHECK: call <4 x i32> @llvm.umin.v4i32
-uint4 test_min_uint4 ( uint4 p0, uint4 p1) {
-  return min ( p0, p1 );
-}
+uint4 test_min_uint4(uint4 p0, uint4 p1) { return min(p0, p1); }
 
 // CHECK: define noundef i64 @
 // CHECK: call i64 @llvm.smin.i64(
-int64_t test_min_long ( int64_t p0, int64_t p1 ) {
-  return min ( p0, p1 );
-}
+int64_t test_min_long(int64_t p0, int64_t p1) { return min(p0, p1); }
 // CHECK: define noundef <2 x i64> @
 // CHECK: call <2 x i64> @llvm.smin.v2i64
-int64_t2 test_min_long2 ( int64_t2 p0, int64_t2 p1 ) {
-  return min ( p0, p1 );
-}
+int64_t2 test_min_long2(int64_t2 p0, int64_t2 p1) { return min(p0, p1); }
 // CHECK: define noundef <3 x i64> @
 // CHECK: call <3 x i64> @llvm.smin.v3i64
-int64_t3 test_min_long3 ( int64_t3 p0, int64_t3 p1 ) {
-  return min ( p0, p1 );
-}
+int64_t3 test_min_long3(int64_t3 p0, int64_t3 p1) { return min(p0, p1); }
 // CHECK: define noundef <4 x i64> @
 // CHECK: call <4 x i64> @llvm.smin.v4i64
-int64_t4 test_min_long4 ( int64_t4 p0, int64_t4 p1) {
-  return min ( p0, p1 );
-}
+int64_t4 test_min_long4(int64_t4 p0, int64_t4 p1) { return min(p0, p1); }
 
 // CHECK: define noundef i64 @
 // CHECK: call i64 @llvm.umin.i64(
-uint64_t test_min_long ( uint64_t p0, uint64_t p1 ) {
-  return min ( p0, p1 );
-}
+uint64_t test_min_long(uint64_t p0, uint64_t p1) { return min(p0, p1); }
 // CHECK: define noundef <2 x i64> @
 // CHECK: call <2 x i64> @llvm.umin.v2i64
-uint64_t2 test_min_long2 ( uint64_t2 p0, uint64_t2 p1 ) {
-  return min ( p0, p1 );
-}
+uint64_t2 test_min_long2(uint64_t2 p0, uint64_t2 p1) { return min(p0, p1); }
 // CHECK: define noundef <3 x i64> @
 // CHECK: call <3 x i64> @llvm.umin.v3i64
-uint64_t3 test_min_long3 ( uint64_t3 p0, uint64_t3 p1 ) {
-  return min ( p0, p1 );
-}
+uint64_t3 test_min_long3(uint64_t3 p0, uint64_t3 p1) { return min(p0, p1); }
 // CHECK: define noundef <4 x i64> @
 // CHECK: call <4 x i64> @llvm.umin.v4i64
-uint64_t4 test_min_long4 ( uint64_t4 p0, uint64_t4 p1) {
-  return min ( p0, p1 );
-}
-
+uint64_t4 test_min_long4(uint64_t4 p0, uint64_t4 p1) { return min(p0, p1); }
 
-// CHECK: define noundef half @
-// CHECK: call half @llvm.minnum.f16(
-// NO_HALF: define noundef float @"?test_min_half@@YA$halff@$halff@0@Z"(
+// NATIVE_HALF: define noundef half @
+// NATIVE_HALF: call half @llvm.minnum.f16(
+// NO_HALF: define noundef float @"?test_min_half
 // NO_HALF: call float @llvm.minnum.f32(
-half test_min_half ( half p0, half p1 ) {
-  return min ( p0, p1 );
-}
-// CHECK: define noundef <2 x half> @
-// CHECK: call <2 x half> @llvm.minnum.v2f16
-// NO_HALF: define noundef <2 x float> @"?test_min_float2@@YAT?$__vector@M$01@__clang@@T12@0@Z"(
+half test_min_half(half p0, half p1) { return min(p0, p1); }
+// NATIVE_HALF: define noundef <2 x half> @
+// NATIVE_HALF: call <2 x half> @llvm.minnum.v2f16
+// NO_HALF: define noundef <2 x float> @"?test_min_half2
 // NO_HALF: call <2 x float> @llvm.minnum.v2f32(
-half2 test_min_half2 ( half2 p0, half2 p1 ) {
-  return min ( p0, p1 );
-}
-// CHECK: define noundef <3 x half> @
-// CHECK: call <3 x half> @llvm.minnum.v3f16
-// NO_HALF: define noundef <3 x float> @"?test_min_float3@@YAT?$__vector@M$02@__clang@@T12@0@Z"(
+half2 test_min_half2(half2 p0, half2 p1) { return min(p0, p1); }
+// NATIVE_HALF: define noundef <3 x half> @
+// NATIVE_HALF: call <3 x half> @llvm.minnum.v3f16
+// NO_HALF: define noundef <3 x float> @"?test_min_half3
 // NO_HALF: call <3 x float> @llvm.minnum.v3f32(
-half3 test_min_half3 ( half3 p0, half3 p1 ) {
-  return min ( p0, p1 );
-}
-// CHECK: define noundef <4 x half> @
-// CHECK: call <4 x half> @llvm.minnum.v4f16
-// NO_HALF: define noundef <4 x float> @"?test_min_float4@@YAT?$__vector@M$03@__clang@@T12@0@Z"(
+half3 test_min_half3(half3 p0, half3 p1) { return min(p0, p1); }
+// NATIVE_HALF: define noundef <4 x half> @
+// NATIVE_HALF: call <4 x half> @llvm.minnum.v4f16
+// NO_HALF: define noundef <4 x float> @"?test_min_half4
 // NO_HALF: call <4 x float> @llvm.minnum.v4f32(
-half4 test_min_half4 ( half4 p0, half4 p1 ) {
-  return min ( p0, p1 );
-}
+half4 test_min_half4(half4 p0, half4 p1) { return min(p0, p1); }
 
 // CHECK: define noundef float @
 // CHECK: call float @llvm.minnum.f32(
-float test_min_float ( float p0, float p1 ) {
-  return min ( p0, p1 );
-}
+float test_min_float(float p0, float p1) { return min(p0, p1); }
 // CHECK: define noundef <2 x float> @
 // CHECK: call <2 x float> @llvm.minnum.v2f32
-float2 test_min_float2 ( float2 p0, float2 p1 ) {
-  return min ( p0, p1 );
-}
+float2 test_min_float2(float2 p0, float2 p1) { return min(p0, p1); }
 // CHECK: define noundef <3 x float> @
 // CHECK: call <3 x float> @llvm.minnum.v3f32
-float3 test_min_float3 ( float3 p0, float3 p1 ) {
-  return min ( p0, p1 );
-}
+float3 test_min_float3(float3 p0, float3 p1) { return min(p0, p1); }
 // CHECK: define noundef <4 x float> @
 // CHECK: call <4 x float> @llvm.minnum.v4f32
-float4 test_min_float4 ( float4 p0, float4 p1) {
-  return min ( p0, p1 );
-}
+float4 test_min_float4(float4 p0, float4 p1) { return min(p0, p1); }
 
 // CHECK: define noundef double @
 // CHECK: call double @llvm.minnum.f64(
-double test_min_double ( double p0, double p1 ) {
-  return min ( p0, p1 );
-}
+double test_min_double(double p0, double p1) { return min(p0, p1); }
 // CHECK: define noundef <2 x double> @
 // CHECK: call <2 x double> @llvm.minnum.v2f64
-double2 test_min_double2 ( double2 p0, double2 p1 ) {
-  return min ( p0, p1 );
-}
+double2 test_min_double2(double2 p0, double2 p1) { return min(p0, p1); }
 // CHECK: define noundef <3 x double> @
 // CHECK: call <3 x double> @llvm.minnum.v3f64
-double3 test_min_double3 ( double3 p0, double3 p1 ) {
-  return min ( p0, p1 );
-}
+double3 test_min_double3(double3 p0, double3 p1) { return min(p0, p1); }
 // CHECK: define noundef <4 x double> @
 // CHECK: call <4 x double> @llvm.minnum.v4f64
-double4 test_min_double4 ( double4 p0, double4 p1) {
-  return min ( p0, p1 );
-}
+double4 test_min_double4(double4 p0, double4 p1) { return min(p0, p1); }
diff --git a/clang/test/CodeGenHLSL/builtins/pow.hlsl b/clang/test/CodeGenHLSL/builtins/pow.hlsl
index 86bfe98058a6e..e996ca2f33641 100644
--- a/clang/test/CodeGenHLSL/builtins/pow.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/pow.hlsl
@@ -1,89 +1,54 @@
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -fnative-half-type \
-// RUN:   -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ 
+// RUN:   --check-prefixes=CHECK,NATIVE_HALF
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
-// RUN:   -o - | FileCheck %s --check-prefix=NO_HALF
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
 
-// CHECK: define noundef half @
-// CHECK: call half @llvm.pow.f16(
-// NO_HALF: define noundef float @"?test_pow_half@@YA$halff@$halff@0@Z"(
+// NATIVE_HALF: define noundef half @
+// NATIVE_HALF: call half @llvm.pow.f16(
+// NO_HALF: define noundef float @"?test_pow_half
 // NO_HALF: call float @llvm.pow.f32(
-half test_pow_half(half p0, half p1)
-{
-    return pow(p0, p1);
-}
-// CHECK: define noundef <2 x half> @"?test_pow_half2@@YAT?$__vector@$f16@$01@__clang@@T12@0@Z"(
-// CHECK: call <2 x half> @llvm.pow.v2f16
-// NO_HALF: define noundef <2 x float> @"?test_pow_float2@@YAT?$__vector@M$01@__clang@@T12@0@Z"(
+half test_pow_half(half p0, half p1) { return pow(p0, p1); }
+// NATIVE_HALF: define noundef <2 x half> @"?test_pow_half2
+// NATIVE_HALF: call <2 x half> @llvm.pow.v2f16
+// NO_HALF: define noundef <2 x float> @"?test_pow_half2
 // NO_HALF: call <2 x float> @llvm.pow.v2f32(
-half2 test_pow_half2(half2 p0, half2 p1)
-{
-    return pow(p0, p1);
-}
-// CHECK: define noundef <3 x half> @"?test_pow_half3@@YAT?$__vector@$f16@$02@__clang@@T12@0@Z"(
-// CHECK: call <3 x half> @llvm.pow.v3f16
-// NO_HALF: define noundef <3 x float> @"?test_pow_float3@@YAT?$__vector@M$02@__clang@@T12@0@Z"(
+half2 test_pow_half2(half2 p0, half2 p1) { return pow(p0, p1); }
+// NATIVE_HALF: define noundef <3 x half> @"?test_pow_half3
+// NATIVE_HALF: call <3 x half> @llvm.pow.v3f16
+// NO_HALF: define noundef <3 x float> @"?test_pow_half3
 // NO_HALF: call <3 x float> @llvm.pow.v3f32(
-half3 test_pow_half3(half3 p0, half3 p1)
-{
-    return pow(p0, p1);
-}
-// CHECK: define noundef <4 x half> @"?test_pow_half4@@YAT?$__vector@$f16@$03@__clang@@T12@0@Z"(
-// CHECK: call <4 x half> @llvm.pow.v4f16
-// NO_HALF: define noundef <4 x float> @"?test_pow_float4@@YAT?$__vector@M$03@__clang@@T12@0@Z"(
+half3 test_pow_half3(half3 p0, half3 p1) { return pow(p0, p1); }
+// NATIVE_HALF: define noundef <4 x half> @"?test_pow_half4
+// NATIVE_HALF: call <4 x half> @llvm.pow.v4f16
+// NO_HALF: define noundef <4 x float> @"?test_pow_half4
 // NO_HALF: call <4 x float> @llvm.pow.v4f32(
-half4 test_pow_half4(half4 p0, half4 p1)
-{
-    return pow(p0, p1);
-}
+half4 test_pow_half4(half4 p0, half4 p1) { return pow(p0, p1); }
 
-// CHECK: define noundef float @"?test_pow_float@@YAMMM@Z"(
+// CHECK: define noundef float @"?test_pow_float
 // CHECK: call float @llvm.pow.f32(
-float test_pow_float(float p0, float p1)
-{
-    return pow(p0, p1);
-}
-// CHECK: define noundef <2 x float> @"?test_pow_float2@@YAT?$__vector@M$01@__clang@@T12@0@Z"(
+float test_pow_float(float p0, float p1) { return pow(p0, p1); }
+// CHECK: define noundef <2 x float> @"?test_pow_float2
 // CHECK: call <2 x float> @llvm.pow.v2f32
-float2 test_pow_float2(float2 p0, float2 p1)
-{
-    return pow(p0, p1);
-}
-// CHECK: define noundef <3 x float> @"?test_pow_float3@@YAT?$__vector@M$02@__clang@@T12@0@Z"(
+float2 test_pow_float2(float2 p0, float2 p1) { return pow(p0, p1); }
+// CHECK: define noundef <3 x float> @"?test_pow_float3
 // CHECK: call <3 x float> @llvm.pow.v3f32
-float3 test_pow_float3(float3 p0, float3 p1)
-{
-    return pow(p0, p1);
-}
-// CHECK: define noundef <4 x float> @"?test_pow_float4@@YAT?$__vector@M$03@__clang@@T12@0@Z"(
+float3 test_pow_float3(float3 p0, float3 p1) { return pow(p0, p1); }
+// CHECK: define noundef <4 x float> @"?test_pow_float4
 // CHECK: call <4 x float> @llvm.pow.v4f32
-float4 test_pow_float4(float4 p0, float4 p1)
-{
-    return pow(p0, p1);
-}
+float4 test_pow_float4(float4 p0, float4 p1) { return pow(p0, p1); }
 
 // CHECK: define noundef double @"?test_pow_double@@YANNN@Z"(
 // CHECK: call double @llvm.pow.f64(
-double test_pow_double(double p0, double p1)
-{
-    return pow(p0, p1);
-}
+double test_pow_double(double p0, double p1) { return pow(p0, p1); }
 // CHECK: define noundef <2 x double> @"?test_pow_double2@@YAT?$__vector@N$01@__clang@@T12@0@Z"(
 // CHECK: call <2 x double> @llvm.pow.v2f64
-double2 test_pow_double2(double2 p0, double2 p1)
-{
-    return pow(p0, p1);
-}
+double2 test_pow_double2(double2 p0, double2 p1) { return pow(p0, p1); }
 // CHECK: define noundef <3 x double> @"?test_pow_double3@@YAT?$__vector@N$02@__clang@@T12@0@Z"(
 // CHECK: call <3 x double> @llvm.pow.v3f64
-double3 test_pow_double3(double3 p0, double3 p1)
-{
-    return pow(p0, p1);
-}
+double3 test_pow_double3(double3 p0, double3 p1) { return pow(p0, p1); }
 // CHECK: define noundef <4 x double> @"?test_pow_double4@@YAT?$__vector@N$03@__clang@@T12@0@Z"(
 // CHECK: call <4 x double> @llvm.pow.v4f64
-double4 test_pow_double4(double4 p0, double4 p1)
-{
-    return pow(p0, p1);
-}
+double4 test_pow_double4(double4 p0, double4 p1) { return pow(p0, p1); }
diff --git a/clang/test/CodeGenHLSL/builtins/rcp.hlsl b/clang/test/CodeGenHLSL/builtins/rcp.hlsl
new file mode 100644
index 0000000000000..9b8406e1f0b60
--- /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/builtins/round.hlsl b/clang/test/CodeGenHLSL/builtins/round.hlsl
new file mode 100644
index 0000000000000..b9f35bd3712d1
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/round.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.round = call half @llvm.round.f16(
+// NATIVE_HALF: ret half %elt.round
+// NO_HALF: define noundef float @"?test_round_half@@YA$halff@$halff@@Z"(
+// NO_HALF: %elt.round = call float @llvm.round.f32(
+// NO_HALF: ret float %elt.round
+half test_round_half(half p0) { return round(p0); }
+// NATIVE_HALF: define noundef <2 x half> @
+// NATIVE_HALF: %elt.round = call <2 x half> @llvm.round.v2f16
+// NATIVE_HALF: ret <2 x half> %elt.round
+// NO_HALF: define noundef <2 x float> @
+// NO_HALF: %elt.round = call <2 x float> @llvm.round.v2f32(
+// NO_HALF: ret <2 x float> %elt.round
+half2 test_round_half2(half2 p0) { return round(p0); }
+// NATIVE_HALF: define noundef <3 x half> @
+// NATIVE_HALF: %elt.round = call <3 x half> @llvm.round.v3f16
+// NATIVE_HALF: ret <3 x half> %elt.round
+// NO_HALF: define noundef <3 x float> @
+// NO_HALF: %elt.round = call <3 x float> @llvm.round.v3f32(
+// NO_HALF: ret <3 x float> %elt.round
+half3 test_round_half3(half3 p0) { return round(p0); }
+// NATIVE_HALF: define noundef <4 x half> @
+// NATIVE_HALF: %elt.round = call <4 x half> @llvm.round.v4f16
+// NATIVE_HALF: ret <4 x half> %elt.round
+// NO_HALF: define noundef <4 x float> @
+// NO_HALF: %elt.round = call <4 x float> @llvm.round.v4f32(
+// NO_HALF: ret <4 x float> %elt.round
+half4 test_round_half4(half4 p0) { return round(p0); }
+
+// CHECK: define noundef float @
+// CHECK: %elt.round = call float @llvm.round.f32(
+// CHECK: ret float %elt.round
+float test_round_float(float p0) { return round(p0); }
+// CHECK: define noundef <2 x float> @
+// CHECK: %elt.round = call <2 x float> @llvm.round.v2f32
+// CHECK: ret <2 x float> %elt.round
+float2 test_round_float2(float2 p0) { return round(p0); }
+// CHECK: define noundef <3 x float> @
+// CHECK: %elt.round = call <3 x float> @llvm.round.v3f32
+// CHECK: ret <3 x float> %elt.round
+float3 test_round_float3(float3 p0) { return round(p0); }
+// CHECK: define noundef <4 x float> @
+// CHECK: %elt.round = call <4 x float> @llvm.round.v4f32
+// CHECK: ret <4 x float> %elt.round
+float4 test_round_float4(float4 p0) { return round(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/sin.hlsl b/clang/test/CodeGenHLSL/builtins/sin.hlsl
index 2445e6063a705..ffb5221491388 100644
--- a/clang/test/CodeGenHLSL/builtins/sin.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/sin.hlsl
@@ -1,56 +1,41 @@
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -fnative-half-type \
-// RUN:   -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s
+// RUN:   -emit-llvm -disable-llvm-passes  -o - | FileCheck %s \
+// RUN:   --check-prefixes=CHECK,NATIVE_HALF
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
-// RUN:   -o - | FileCheck %s --check-prefix=NO_HALF
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
 
-// CHECK: define noundef half @
-// CHECK: call half @llvm.sin.f16(
+// NATIVE_HALF: define noundef half @
+// NATIVE_HALF: call half @llvm.sin.f16(
 // NO_HALF: define noundef float @"?test_sin_half@@YA$halff@$halff@@Z"(
 // NO_HALF: call float @llvm.sin.f32(
-half test_sin_half ( half p0 ) {
-  return sin ( p0 );
-}
-// CHECK: define noundef <2 x half> @
-// CHECK: call <2 x half> @llvm.sin.v2f16
-// NO_HALF: define noundef <2 x float> @"?test_sin_float2@@YAT?$__vector@M$01@__clang@@T12@@Z"(
+half test_sin_half(half p0) { return sin(p0); }
+// NATIVE_HALF: define noundef <2 x half> @
+// NATIVE_HALF: call <2 x half> @llvm.sin.v2f16
+// NO_HALF: define noundef <2 x float> @"?test_sin_half2
 // NO_HALF: call <2 x float> @llvm.sin.v2f32(
-half2 test_sin_half2 ( half2 p0 ) {
-  return sin ( p0 );
-}
-// CHECK: define noundef <3 x half> @
-// CHECK: call <3 x half> @llvm.sin.v3f16
-// NO_HALF: define noundef <3 x float> @"?test_sin_float3@@YAT?$__vector@M$02@__clang@@T12@@Z"(
+half2 test_sin_half2(half2 p0) { return sin(p0); }
+// NATIVE_HALF: define noundef <3 x half> @
+// NATIVE_HALF: call <3 x half> @llvm.sin.v3f16
+// NO_HALF: define noundef <3 x float> @"?test_sin_half3
 // NO_HALF: call <3 x float> @llvm.sin.v3f32(
-half3 test_sin_half3 ( half3 p0 ) {
-  return sin ( p0 );
-}
-// CHECK: define noundef <4 x half> @
-// CHECK: call <4 x half> @llvm.sin.v4f16
-// NO_HALF: define noundef <4 x float> @"?test_sin_float4@@YAT?$__vector@M$03@__clang@@T12@@Z"(
+half3 test_sin_half3(half3 p0) { return sin(p0); }
+// NATIVE_HALF: define noundef <4 x half> @
+// NATIVE_HALF: call <4 x half> @llvm.sin.v4f16
+// NO_HALF: define noundef <4 x float> @"?test_sin_half4
 // NO_HALF: call <4 x float> @llvm.sin.v4f32(
-half4 test_sin_half4 ( half4 p0 ) {
-  return sin ( p0 );
-}
+half4 test_sin_half4(half4 p0) { return sin(p0); }
 
 // CHECK: define noundef float @
 // CHECK: call float @llvm.sin.f32(
-float test_sin_float ( float p0 ) {
-  return sin ( p0 );
-}
+float test_sin_float(float p0) { return sin(p0); }
 // CHECK: define noundef <2 x float> @
 // CHECK: call <2 x float> @llvm.sin.v2f32
-float2 test_sin_float2 ( float2 p0 ) {
-  return sin ( p0 );
-}
+float2 test_sin_float2(float2 p0) { return sin(p0); }
 // CHECK: define noundef <3 x float> @
 // CHECK: call <3 x float> @llvm.sin.v3f32
-float3 test_sin_float3 ( float3 p0 ) {
-  return sin ( p0 );
-}
+float3 test_sin_float3(float3 p0) { return sin(p0); }
 // CHECK: define noundef <4 x float> @
 // CHECK: call <4 x float> @llvm.sin.v4f32
-float4 test_sin_float4 ( float4 p0 ) {
-  return sin ( p0 );
-}
+float4 test_sin_float4(float4 p0) { return sin(p0); }
diff --git a/clang/test/CodeGenHLSL/builtins/trunc.hlsl b/clang/test/CodeGenHLSL/builtins/trunc.hlsl
index 4ae3cd20257ec..6078aae5f873f 100644
--- a/clang/test/CodeGenHLSL/builtins/trunc.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/trunc.hlsl
@@ -1,56 +1,47 @@
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -fnative-half-type \
-// RUN:   -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s
+// RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ 
+// RUN:   --check-prefixes=CHECK,NATIVE_HALF
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
-// RUN:   -o - | FileCheck %s --check-prefix=NO_HALF
+// RUN:   -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
 
-// CHECK: define noundef half @
-// CHECK: call half @llvm.trunc.f16(
-// NO_HALF: define noundef float @"?test_trunc_half@@YA$halff@$halff@@Z"(
+// NATIVE_HALF: define noundef half @"?test_trunc_half
+// NATIVE_HALF: call half @llvm.trunc.f16(
+// NO_HALF: define noundef float @"?test_trunc_half
 // NO_HALF: call float @llvm.trunc.f32(
-half test_trunc_half ( half p0 ) {
-  return trunc ( p0 );
-}
-// CHECK: define noundef <2 x half> @
-// CHECK: call <2 x half> @llvm.trunc.v2f16
-// NO_HALF: define noundef <2 x float> @"?test_trunc_float2@@YAT?$__vector@M$01@__clang@@T12@@Z"(
+half test_trunc_half(half p0) { return trunc(p0); }
+
+// NATIVE_HALF: define noundef <2 x half> @"?test_trunc_half2
+// NATIVE_HALF: call <2 x half> @llvm.trunc.v2f16
+// NO_HALF: define noundef <2 x float> @"?test_trunc_half2
 // NO_HALF: call <2 x float> @llvm.trunc.v2f32(
-half2 test_trunc_half2 ( half2 p0 ) {
-  return trunc ( p0 );
-}
-// CHECK: define noundef <3 x half> @
-// CHECK: call <3 x half> @llvm.trunc.v3f16
-// NO_HALF: define noundef <3 x float> @"?test_trunc_float3@@YAT?$__vector@M$02@__clang@@T12@@Z"(
+half2 test_trunc_half2(half2 p0) { return trunc(p0); }
+
+// NATIVE_HALF: define noundef <3 x half> @"?test_trunc_half3
+// NATIVE_HALF: call <3 x half> @llvm.trunc.v3f16
+// NO_HALF: define noundef <3 x float> @"?test_trunc_half3
 // NO_HALF: call <3 x float> @llvm.trunc.v3f32(
-half3 test_trunc_half3 ( half3 p0 ) {
-  return trunc ( p0 );
-}
-// CHECK: define noundef <4 x half> @
-// CHECK: call <4 x half> @llvm.trunc.v4f16
-// NO_HALF: define noundef <4 x float> @"?test_trunc_float4@@YAT?$__vector@M$03@__clang@@T12@@Z"(
+half3 test_trunc_half3(half3 p0) { return trunc(p0); }
+
+// NATIVE_HALF: define noundef <4 x half> @"?test_trunc_half4
+// NATIVE_HALF: call <4 x half> @llvm.trunc.v4f16
+// NO_HALF: define noundef <4 x float> @"?test_trunc_half4
 // NO_HALF: call <4 x float> @llvm.trunc.v4f32(
-half4 test_trunc_half4 ( half4 p0 ) {
-  return trunc ( p0 );
-}
+half4 test_trunc_half4(half4 p0) { return trunc(p0); }
 
-// CHECK: define noundef float @
+// CHECK: define noundef float @"?test_trunc_float
 // CHECK: call float @llvm.trunc.f32(
-float test_trunc_float ( float p0 ) {
-  return trunc ( p0 );
-}
-// CHECK: define noundef <2 x float> @
+float test_trunc_float(float p0) { return trunc(p0); }
+
+// CHECK: define noundef <2 x float> @"?test_trunc_float2
 // CHECK: call <2 x float> @llvm.trunc.v2f32
-float2 test_trunc_float2 ( float2 p0 ) {
-  return trunc ( p0 );
-}
-// CHECK: define noundef <3 x float> @
+float2 test_trunc_float2(float2 p0) { return trunc(p0); }
+
+// CHECK: define noundef <3 x float> @"?test_trunc_float3
 // CHECK: call <3 x float> @llvm.trunc.v3f32
-float3 test_trunc_float3 ( float3 p0 ) {
-  return trunc ( p0 );
-}
-// CHECK: define noundef <4 x float> @
+float3 test_trunc_float3(float3 p0) { return trunc(p0); }
+
+// CHECK: define noundef <4 x float> @"?test_trunc_float4
 // CHECK: call <4 x float> @llvm.trunc.v4f32
-float4 test_trunc_float4 ( float4 p0 ) {
-  return trunc ( p0 );
-}
+float4 test_trunc_float4(float4 p0) { return trunc(p0); }
diff --git a/clang/test/CodeGenHLSL/semantics/DispatchThreadID.hlsl b/clang/test/CodeGenHLSL/semantics/DispatchThreadID.hlsl
index e285f74a822d5..3efc36baa35b1 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 788b3220af306..8d55e6c7d2308 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 @@ @interface StaticLayout : NSObject
 @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 @@ @interface NotStaticLayout : NotNSObject
 @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/Driver/aarch64-rdm.c b/clang/test/Driver/aarch64-rdm.c
index f2542b381e7c2..62e1a4def4ce1 100644
--- a/clang/test/Driver/aarch64-rdm.c
+++ b/clang/test/Driver/aarch64-rdm.c
@@ -1,13 +1,16 @@
 // RUN: %clang --target=aarch64-none-elf -march=armv8a+rdm -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-RDM %s
+// RUN: %clang --target=aarch64-none-elf -march=armv8a+rdma -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-RDM %s
 // RUN: %clang --target=aarch64-none-elf -mcpu=generic+rdm -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-RDM %s
 // RUN: %clang --target=aarch64-none-elf -mcpu=falkor -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-RDM %s
 // RUN: %clang --target=aarch64-none-elf -mcpu=thunderx2t99 -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-RDM %s
 // CHECK-RDM: "-target-feature" "+rdm"
 
 // RUN: %clang --target=aarch64-none-elf -march=armv8a+nordm -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-NORDM %s
+// RUN: %clang --target=aarch64-none-elf -march=armv8a+nordma -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-NORDM %s
 // RUN: %clang --target=aarch64-none-elf -mcpu=generic+nordm -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-NORDM %s
 // CHECK-NORDM-NOT: "-target-feature" "+rdm"
 //
 // RUN: %clang --target=aarch64-none-elf -march=armv8.1a -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-RDM %s
 // RUN: %clang --target=aarch64-none-elf -march=armv8.1a+nordm -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-NORDM-DEFAULT %s
+// RUN: %clang --target=aarch64-none-elf -march=armv8.1a+nordma -### -c %s 2>&1 | FileCheck --check-prefix=CHECK-NORDM-DEFAULT %s
 // CHECK-NORDM-DEFAULT: "-target-feature" "-rdm"
diff --git a/clang/test/Driver/android-link.cpp b/clang/test/Driver/android-link.cpp
index fa9cbc5d0c7a5..f9bdd00507d7b 100644
--- a/clang/test/Driver/android-link.cpp
+++ b/clang/test/Driver/android-link.cpp
@@ -17,9 +17,10 @@
 //
 // RUN: %clang -target aarch64-none-linux-android \
 // RUN:   -### -v %s 2> %t
-// RUN: FileCheck -check-prefix=MAX-PAGE-SIZE < %t %s
+// RUN: FileCheck -check-prefix=MAX-PAGE-SIZE-AARCH64 < %t %s
 //
 // GENERIC-ARM: --fix-cortex-a53-843419
 // CORTEX-A53: --fix-cortex-a53-843419
 // CORTEX-A57-NOT: --fix-cortex-a53-843419
 // MAX-PAGE-SIZE: "-z" "max-page-size=4096"
+// MAX-PAGE-SIZE-AARCH64: "-z" "max-page-size=16384"
diff --git a/clang/test/Driver/cuda-detect.cu b/clang/test/Driver/cuda-detect.cu
index 077d555a3128f..49e58004e672c 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-march.cu b/clang/test/Driver/cuda-march.cu
index 7003e9fd4198c..25fd6f3a10f2a 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 77cfa6925e387..8e1bb2e496c74 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 ad892b7839b96..8999a6618fe1f 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-ptxas-path.cu b/clang/test/Driver/cuda-ptxas-path.cu
index 09c6014a91a2e..87b19d9d4d616 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/darwin-header-search-libcxx.cpp b/clang/test/Driver/darwin-header-search-libcxx.cpp
index 70cc06090a993..5695f53683bab 100644
--- a/clang/test/Driver/darwin-header-search-libcxx.cpp
+++ b/clang/test/Driver/darwin-header-search-libcxx.cpp
@@ -193,7 +193,7 @@
 // RUN: ln -sf %t/install/bin/clang %t/symlinked1/bin/clang
 // RUN: mkdir -p %t/symlinked1/include/c++/v1
 
-// RUN: %t/symlinked1/bin/clang -### %s -fsyntax-only 2>&1 \
+// RUN: %t/symlinked1/bin/clang -### %s -no-canonical-prefixes -fsyntax-only 2>&1 \
 // RUN:     --target=x86_64-apple-darwin \
 // RUN:     -stdlib=libc++ \
 // RUN:     -isysroot %S/Inputs/basic_darwin_sdk_usr_cxx_v1 \
diff --git a/clang/test/Driver/dwarf-target-version-clamp.cu b/clang/test/Driver/dwarf-target-version-clamp.cu
index ec0386afbc57e..d9dbbe62cfb2f 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 e1ce8889459f9..10fe155fee874 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 ca53f0d107a00..c67f7f8c005b3 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 e907c34b29b99..060a56b3c70e5 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/mingw-sysroot.cpp b/clang/test/Driver/mingw-sysroot.cpp
index 50152b2ca210d..5d512e6669709 100644
--- a/clang/test/Driver/mingw-sysroot.cpp
+++ b/clang/test/Driver/mingw-sysroot.cpp
@@ -50,10 +50,12 @@
 // CHECK_TESTROOT_GCC_EXPLICIT: "-internal-isystem" "{{[^"]+}}/testroot-gcc{{/|\\\\}}include"
 
 
-// If there's a matching sysroot next to the clang binary itself, prefer that
+// If -no-canonical-prefixes and there's a matching sysroot next to the clang binary itself, prefer that
 // over a gcc in the path:
 
-// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %T/testroot-clang/bin/x86_64-w64-mingw32-clang -target x86_64-w64-mingw32 -rtlib=compiler-rt -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_CLANG %s
+// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %T/testroot-clang/bin/x86_64-w64-mingw32-clang --target=x86_64-w64-mingw32 -rtlib=compiler-rt -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_GCC2 %s
+// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %T/testroot-clang/bin/x86_64-w64-mingw32-clang --target=x86_64-w64-mingw32 -rtlib=compiler-rt -stdlib=libstdc++ --sysroot="" -c -### %s -no-canonical-prefixes 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_CLANG %s
+// CHECK_TESTROOT_GCC2: "{{[^"]+}}/testroot-gcc{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}include"
 // CHECK_TESTROOT_CLANG: "{{[^"]+}}/testroot-clang{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}include"
 
 
@@ -82,7 +84,7 @@
 // that indicates that we did choose the right base, even if this particular directory
 // actually doesn't exist here.
 
-// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %T/testroot-clang-native/bin/clang -target x86_64-w64-mingw32 -rtlib=compiler-rt -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_CLANG_NATIVE %s
+// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %T/testroot-clang-native/bin/clang -no-canonical-prefixes --target=x86_64-w64-mingw32 -rtlib=compiler-rt -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_CLANG_NATIVE %s
 // CHECK_TESTROOT_CLANG_NATIVE: "{{[^"]+}}/testroot-clang-native{{/|\\\\}}x86_64-w64-mingw32{{/|\\\\}}include"
 
 
@@ -93,12 +95,12 @@
 // that defaults to x86_64 mingw, but it's easier to test this in cross setups
 // with symlinks, like the other tests here.)
 
-// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %T/testroot-clang/bin/x86_64-w64-mingw32-clang --target=x86_64-w64-mingw32 -m32 -rtlib=compiler-rt -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_CLANG_I686 %s
+// RUN: env "PATH=%T/testroot-gcc/bin:%PATH%" %T/testroot-clang/bin/x86_64-w64-mingw32-clang -no-canonical-prefixes --target=x86_64-w64-mingw32 -m32 -rtlib=compiler-rt -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_CLANG_I686 %s
 // CHECK_TESTROOT_CLANG_I686: "{{[^"]+}}/testroot-clang{{/|\\\\}}i686-w64-mingw32{{/|\\\\}}include"
 
 
 // If the user calls clang with a custom literal triple, make sure this maps
 // to sysroots with the matching spelling.
 
-// RUN: %T/testroot-custom-triple/bin/clang --target=x86_64-w64-mingw32foo -rtlib=compiler-rt -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_CUSTOM_TRIPLE %s
+// RUN: %T/testroot-custom-triple/bin/clang -no-canonical-prefixes --target=x86_64-w64-mingw32foo -rtlib=compiler-rt -stdlib=libstdc++ --sysroot="" -c -### %s 2>&1 | FileCheck -check-prefix=CHECK_TESTROOT_CUSTOM_TRIPLE %s
 // CHECK_TESTROOT_CUSTOM_TRIPLE: "{{[^"]+}}/testroot-custom-triple{{/|\\\\}}x86_64-w64-mingw32foo{{/|\\\\}}include"
diff --git a/clang/test/Driver/netbsd.c b/clang/test/Driver/netbsd.c
index 73777e7a3e38f..1b7c674e18af6 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/no-canonical-prefixes.c b/clang/test/Driver/no-canonical-prefixes.c
index fb54f85f959ae..669e56639284a 100644
--- a/clang/test/Driver/no-canonical-prefixes.c
+++ b/clang/test/Driver/no-canonical-prefixes.c
@@ -26,7 +26,7 @@
 // RUN:     | FileCheck --check-prefix=NON-CANONICAL %s
 //
 // FIXME: This should really be '.real'.
-// CANONICAL: InstalledDir: {{.*}}.fake
+// CANONICAL: InstalledDir: {{.*}}bin
 // CANONICAL: {{[/|\\]*}}clang{{.*}}" -cc1
 //
 // NON-CANONICAL: InstalledDir: .{{$}}
diff --git a/clang/test/Driver/openbsd.c b/clang/test/Driver/openbsd.c
index 68d33c5dd01e2..672cd3adf44a6 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 19b892126c70a..91782316a4e22 100644
--- a/clang/test/Driver/openmp-offload-gpu.c
+++ b/clang/test/Driver/openmp-offload-gpu.c
@@ -156,21 +156,6 @@
 
 /// ###########################################################################
 
-/// Check that the warning is thrown when the libomptarget bitcode library is not found.
-/// Libomptarget requires sm_52 or newer so an sm_52 bitcode library should never exist.
-// RUN:   not %clang -### -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda \
-// RUN:   -Xopenmp-target -march=sm_52 --cuda-path=%S/Inputs/CUDA_102/usr/local/cuda \
-// RUN:   -fopenmp-relocatable-target -save-temps %s 2>&1 \
-// RUN:   | FileCheck -check-prefix=CHK-BCLIB-WARN %s
-
-// CHK-BCLIB-WARN: no library 'libomptarget-nvptx-sm_52.bc' found in the default clang lib directory or in LIBRARY_PATH; use '--libomptarget-nvptx-bc-path' to specify nvptx bitcode library
-
-/// ###########################################################################
-
-/// Check -Xopenmp-target triggers error when an option requiring arguments is passed to it.
-// RUN:  not %clang -### -fopenmp=libomp -fopenmp-targets=powerpc64le-ibm-linux-gnu -Xopenmp-target -Xopenmp-target -mcpu=pwr8 %s 2>&1 \
-// RUN:   | FileCheck -check-prefix=CHK-FOPENMP-TARGET-NESTED-ERROR %s
-
 /// Check that the error is thrown when the libomptarget bitcode library does not exist.
 // RUN:   not %clang -### -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda \
 // RUN:   -Xopenmp-target -march=sm_52 --cuda-path=%S/Inputs/CUDA_102/usr/local/cuda \
diff --git a/clang/test/Driver/program-path-priority.c b/clang/test/Driver/program-path-priority.c
index ee931dd7a9a35..c940c4ced9442 100644
--- a/clang/test/Driver/program-path-priority.c
+++ b/clang/test/Driver/program-path-priority.c
@@ -36,7 +36,7 @@
 // RUN: touch %t/notreal-none-elf-gcc && chmod +x %t/notreal-none-elf-gcc
 // RUN: env "PATH=" %t/clang -### -target notreal-none-elf %s 2>&1 | \
 // RUN:   FileCheck --check-prefix=PROG_PATH_NOTREAL_GCC %s
-// PROG_PATH_NOTREAL_GCC: notreal-none-elf-gcc"
+// PROG_PATH_NOTREAL_GCC: notreal-none-unknown-elf
 
 /// -gcc on the PATH is found
 // RUN: mkdir -p %t/env
@@ -57,7 +57,7 @@
 // RUN: touch %t/gcc && chmod +x %t/gcc
 // RUN: env "PATH=" %t/clang -### -target notreal-none-elf %s 2>&1 | \
 // RUN:   FileCheck --check-prefix=NOTREAL_GCC_PREFERRED %s
-// NOTREAL_GCC_PREFERRED: notreal-none-elf-gcc"
+// NOTREAL_GCC_PREFERRED: notreal-none-unknown-elf"
 // NOTREAL_GCC_PREFERRED-NOT: /gcc"
 
 /// -gcc on the PATH is preferred to gcc in program path
@@ -125,6 +125,9 @@
 /// Only if there is nothing in the prefix will we search other paths
 /// -f in case $DEFAULT_TRIPLE == %target_triple
 // RUN: rm -f %t/prefix/$DEFAULT_TRIPLE-gcc %t/prefix/%target_triple-gcc %t/prefix/gcc
-// RUN: env "PATH=" %t/clang -### -target notreal-none-elf %s -B %t/prefix 2>&1 | \
-// RUN:   FileCheck --check-prefix=EMPTY_PREFIX_DIR %s
-// EMPTY_PREFIX_DIR: notreal-none-elf-gcc"
+// RUN: env "PATH=" %t/clang -### -canonical-prefixes --target=notreal-none-elf %s -B %t/prefix 2>&1 | \
+// RUN:   FileCheck --check-prefix=EMPTY_PREFIX_DIR1 %s
+// EMPTY_PREFIX_DIR1: gcc"
+// RUN: env "PATH=" %t/clang -### -no-canonical-prefixes --target=notreal-none-elf %s -B %t/prefix 2>&1 | \
+// RUN:   FileCheck --check-prefix=EMPTY_PREFIX_DIR2 %s
+// EMPTY_PREFIX_DIR2: notreal-none-elf-gcc"
diff --git a/clang/test/Driver/riscv-arch.c b/clang/test/Driver/riscv-arch.c
index c9e984e07cbea..8399b4e97f86d 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/rocm-detect.hip b/clang/test/Driver/rocm-detect.hip
index 0db994af556f3..8b15c322e3fb3 100644
--- a/clang/test/Driver/rocm-detect.hip
+++ b/clang/test/Driver/rocm-detect.hip
@@ -102,7 +102,7 @@
 // RUN: rm -rf %t/rocm-spack
 // RUN: cp -r %S/Inputs/rocm-spack %t
 // RUN: ln -fs %clang %t/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/bin/clang
-// RUN: %t/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/bin/clang -### -v \
+// RUN: %t/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/bin/clang -### -no-canonical-prefixes -v \
 // RUN:   -resource-dir=%t/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/lib/clang \
 // RUN:   -target x86_64-linux-gnu --cuda-gpu-arch=gfx900 --print-rocm-search-dirs %s 2>&1 \
 // RUN:   | FileCheck -check-prefixes=SPACK %s
@@ -111,7 +111,7 @@
 // ROCm release. --hip-path and --rocm-device-lib-path can be used to specify them.
 
 // RUN: cp -r %t/rocm-spack/hip-* %t/rocm-spack/hip-4.0.0-abcd
-// RUN: %t/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/bin/clang -### -v \
+// RUN: %t/rocm-spack/llvm-amdgpu-4.0.0-ieagcs7inf7runpyfvepqkurasoglq4z/bin/clang -### -no-canonical-prefixes -v \
 // RUN:   -target x86_64-linux-gnu --cuda-gpu-arch=gfx900 \
 // RUN:   --hip-path=%t/rocm-spack/hip-4.0.0-abcd \
 // RUN:    %s 2>&1 | FileCheck -check-prefixes=SPACK-SET %s
diff --git a/clang/test/InstallAPI/basic.test b/clang/test/InstallAPI/basic.test
index 22b04792ca2c3..5b41ccd517b0a 100644
--- a/clang/test/InstallAPI/basic.test
+++ b/clang/test/InstallAPI/basic.test
@@ -16,6 +16,11 @@
 // CHECK-NOT: warning:  
 
 //--- basic_inputs.json
+{
+  "headers": [
+  ],
+  "version": "3"
+}
 
 //--- expected.tbd
 {
diff --git a/clang/test/InstallAPI/objcclasses.test b/clang/test/InstallAPI/objcclasses.test
new file mode 100644
index 0000000000000..7b73dffbe9208
--- /dev/null
+++ b/clang/test/InstallAPI/objcclasses.test
@@ -0,0 +1,144 @@
+// 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: -F%t -install_name /System/Library/Frameworks/Foo.framework/Foo \
+// RUN: %t/inputs.json -o %t/outputs.tbd -v 2>&1 | FileCheck %s --check-prefix=VERBOSE
+// RUN: llvm-readtapi -compare %t/outputs.tbd %t/expected.tbd 2>&1 | FileCheck %s --allow-empty
+
+// VERBOSE:       Public Headers: 
+// VERBOSE-NEXT:  #import  
+// CHECK-NOT:     error:  
+// CHECK-NOT:     warning:  
+
+//--- Foo.framework/Headers/Foo.h
+// Ignore forward declaration. 
+@class NSObject;
+
+@interface Visible 
+@end
+
+__attribute__((visibility("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"
+}
+
+//--- expected.tbd
+{
+  "main_library": {
+    "compatibility_versions": [
+      {
+        "version": "0"
+      }
+    ],
+    "current_versions": [
+      {
+        "version": "0"
+      }
+    ],
+    "exported_symbols": [
+      {
+        "data": {
+          "objc_class": [
+            "PublicClass",
+            "Exception",
+            "Visible",
+            "ClassWithIvars"
+          ],
+          "objc_eh_type": [
+            "Exception"
+          ],
+          "objc_ivar": [
+            "Exception._ivarFromExtension",
+            "ClassWithIvars._ivar2",
+            "PublicClass._external",
+            "ClassWithIvars._ivar1",
+            "ClassWithIvars._externalIVar",
+            "PublicClass._public"
+          ]
+        }
+      }
+    ],
+    "flags": [
+      {
+        "attributes": [
+          "not_app_extension_safe"
+        ]
+      }
+    ],
+    "install_names": [
+      {
+        "name": "/System/Library/Frameworks/Foo.framework/Foo"
+      }
+    ],
+    "target_info": [
+      {
+        "min_deployment": "13.1",
+        "target": "arm64-macos"
+      }
+    ]
+  },
+  "tapi_tbd_version": 5
+}
diff --git a/clang/test/InstallAPI/variables.test b/clang/test/InstallAPI/variables.test
new file mode 100644
index 0000000000000..6272867911f18
--- /dev/null
+++ b/clang/test/InstallAPI/variables.test
@@ -0,0 +1,63 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: sed -e "s|SRC_DIR|%/t|g" %t/vars_inputs.json.in > %t/vars_inputs.json
+
+/// Check multiple targets are captured.
+// RUN: clang-installapi -target arm64-apple-macos13.1 -target arm64e-apple-macos13.1 \
+// RUN: -fapplication-extension -install_name /usr/lib/vars.dylib \
+// RUN: %t/vars_inputs.json -o %t/vars.tbd 2>&1 | FileCheck %s --allow-empty
+// RUN: llvm-readtapi -compare %t/vars.tbd %t/expected.tbd 2>&1 | FileCheck %s --allow-empty
+
+// CHECK-NOT: error:  
+// CHECK-NOT: warning:  
+
+//--- vars.h
+extern int foo;
+
+//--- vars_inputs.json.in
+{
+  "headers": [ {
+    "path" : "SRC_DIR/vars.h",
+    "type" : "public"
+  }],
+  "version": "3"
+}
+
+//--- expected.tbd
+{
+  "main_library": {
+    "compatibility_versions": [
+      {
+        "version": "0"
+      }],
+    "current_versions": [
+      {
+        "version": "0"
+      }],
+    "install_names": [
+      {
+        "name": "/usr/lib/vars.dylib"
+      }
+    ],
+    "exported_symbols": [
+      {
+        "data": {
+          "global": [
+            "_foo"
+          ]
+        }
+      }
+    ],
+    "target_info": [
+      {
+        "min_deployment": "13.1",
+        "target": "arm64-macos"
+      },
+      {
+        "min_deployment": "13.1",
+        "target": "arm64e-macos"
+      }
+    ]
+  },
+  "tapi_tbd_version": 5
+}
diff --git a/clang/test/Layout/dump-complete-invalid.cpp b/clang/test/Layout/dump-complete-invalid.cpp
new file mode 100644
index 0000000000000..d3ec1b382ce7c
--- /dev/null
+++ b/clang/test/Layout/dump-complete-invalid.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -verify -fsyntax-only -fdump-record-layouts-complete %s
+
+struct Incomplete; // expected-note {{forward declaration}}
+
+// Check we don't crash on trying to print out an invalid declaration.
+struct Invalid : Incomplete {}; // expected-error {{base class has incomplete type}}
diff --git a/clang/test/Layout/dump-complete.cpp b/clang/test/Layout/dump-complete.cpp
index 9ccbf477c7052..728f133a0eb64 100644
--- a/clang/test/Layout/dump-complete.cpp
+++ b/clang/test/Layout/dump-complete.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm-only -fdump-record-layouts-complete %s | FileCheck %s
+// RUN: %clang_cc1 -fsyntax-only -fdump-record-layouts-complete %s | FileCheck %s
 
 struct a {
   int x;
@@ -12,7 +12,62 @@ class c {};
 
 class d;
 
+template 
+struct s {
+  int x;
+};
+
+template 
+struct ts {
+  T x;
+};
+
+template <>
+struct ts {
+  float f;
+};
+
+void f() {
+  ts a;
+  ts b;
+  ts c;
+}
+
+namespace gh83671 {
+template 
+struct integral_constant {
+  static constexpr const _Tp value = __v;
+  typedef integral_constant type;
+};
+
+template 
+using _BoolConstant = integral_constant;
+
+template 
+struct is_same : _BoolConstant<__is_same(_Tp, _Up)> {};
+
+template < class _Tp >
+class numeric_limits {};
+
+template < class _Tp >
+class numeric_limits< const _Tp > : public numeric_limits< _Tp > {};
+}
+
+namespace gh83684 {
+template 
+struct AllocationResult {
+  Pointer ptr = nullptr;
+  int count = 0;
+};
+}
+
 // CHECK:          0 | struct a
 // CHECK:          0 | struct b
 // CHECK:          0 | class c
+// CHECK:          0 | struct ts
+// CHECK-NEXT:     0 |   float
+// CHECK:          0 | struct ts
+// CHECK:          0 | struct ts
 // CHECK-NOT:      0 | class d
+// CHECK-NOT:      0 | struct s
+// CHECK-NOT:      0 | struct AllocationResult
diff --git a/clang/test/Misc/warning-flags.c b/clang/test/Misc/warning-flags.c
index 9d4cac9e39b42..bb3c7d816d2f0 100644
--- a/clang/test/Misc/warning-flags.c
+++ b/clang/test/Misc/warning-flags.c
@@ -18,7 +18,7 @@ This test serves two purposes:
 
 The list of warnings below should NEVER grow.  It should gradually shrink to 0.
 
-CHECK: Warnings without flags (66):
+CHECK: Warnings without flags (67):
 
 CHECK-NEXT:   ext_expected_semi_decl_list
 CHECK-NEXT:   ext_explicit_specialization_storage_class
@@ -58,6 +58,7 @@ CHECK-NEXT:   warn_ignoring_ftabstop_value
 CHECK-NEXT:   warn_implements_nscopying
 CHECK-NEXT:   warn_incompatible_qualified_id
 CHECK-NEXT:   warn_invalid_asm_cast_lvalue
+CHECK-NEXT:   warn_invalid_cpu_supports
 CHECK-NEXT:   warn_maynot_respond
 CHECK-NEXT:   warn_method_param_redefinition
 CHECK-NEXT:   warn_missing_case_for_condition
diff --git a/clang/test/Modules/Inputs/config.h b/clang/test/Modules/Inputs/config.h
deleted file mode 100644
index 4c124b0bf82b7..0000000000000
--- 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 e7cb4b27bc08b..47f6c5c1010d7 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/config_macros.m b/clang/test/Modules/config_macros.m
index 15e2c16606ba2..adb2a8f6e5ce3 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 @@
 #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/transitive-import.cppm b/clang/test/Modules/transitive-import.cppm
new file mode 100644
index 0000000000000..0eed8cfe2f0ae
--- /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/interop_codegen.cpp b/clang/test/OpenMP/interop_codegen.cpp
new file mode 100644
index 0000000000000..31df2f1ba58c5
--- /dev/null
+++ b/clang/test/OpenMP/interop_codegen.cpp
@@ -0,0 +1,45 @@
+// expected-no-diagnostics
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fopenmp-targets=amdgcn-amd-amdhsa -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1  -verify -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - | FileCheck %s
+
+#ifndef HEADER
+#define HEADER
+
+typedef void *omp_interop_t;
+#define omp_interop_none 0
+#define omp_ipr_fr_id -1
+typedef long omp_intptr_t;
+#define NULL 0
+
+extern omp_intptr_t omp_get_interop_int(const omp_interop_t, int, int *);
+
+int main() {
+  omp_interop_t obj1 = omp_interop_none;
+  omp_interop_t obj2 = omp_interop_none;
+  omp_interop_t i1 = omp_interop_none;
+  omp_interop_t i2 = omp_interop_none;
+  omp_interop_t i3 = omp_interop_none;
+  omp_interop_t i4 = omp_interop_none;
+  omp_interop_t i5 = omp_interop_none;
+
+  #pragma omp interop init(targetsync: obj1) init(targetsync: obj2)
+  int id = (int )omp_get_interop_int(obj1, omp_ipr_fr_id, NULL);
+  int id1 = (int )omp_get_interop_int(obj2, omp_ipr_fr_id, NULL);
+
+  #pragma omp interop init(target,targetsync: i1) use(i2) use(i3) destroy(i4) destroy(i5)
+  int id2 = (int )omp_get_interop_int(i1, omp_ipr_fr_id, NULL);
+  int id3 = (int )omp_get_interop_int(i2, omp_ipr_fr_id, NULL);
+
+
+}
+#endif
+
+// CHECK-LABEL: define {{.+}}main{{.+}}
+// CHECK: call {{.+}}__tgt_interop_init({{.+}}obj1{{.*}})
+// CHECK: call {{.+}}__tgt_interop_init({{.+}}obj2{{.*}})
+// CHECK: call {{.+}}__tgt_interop_init({{.+}}i1{{.*}})
+// CHECK: call {{.+}}__tgt_interop_destroy({{.+}}i4{{.*}})
+// CHECK: call {{.+}}__tgt_interop_destroy({{.+}}i5{{.*}})
+// CHECK: call {{.+}}__tgt_interop_use({{.+}}i2{{.*}})
+// CHECK: call {{.+}}__tgt_interop_use({{.+}}i3{{.*}})
diff --git a/clang/test/OpenMP/scan_ast_print.cpp b/clang/test/OpenMP/scan_ast_print.cpp
index 3bbd3b60c3e8c..82cb13eb6e70f 100644
--- a/clang/test/OpenMP/scan_ast_print.cpp
+++ b/clang/test/OpenMP/scan_ast_print.cpp
@@ -17,6 +17,10 @@ T tmain(T argc) {
   static T a;
 #pragma omp for reduction(inscan, +: a)
   for (int i = 0; i < 10; ++i) {
+#pragma omp scan inclusive(a)
+  }
+#pragma omp parallel for reduction(inscan, +:a)
+  for (int i = 0; i < 10; ++i) {
 #pragma omp scan inclusive(a)
   }
   return a + argc;
@@ -25,15 +29,29 @@ T tmain(T argc) {
 // CHECK-NEXT: #pragma omp for reduction(inscan, +: a)
 // CHECK-NEXT: for (int i = 0; i < 10; ++i) {
 // CHECK-NEXT: #pragma omp scan inclusive(a){{$}}
+
+// CHECK: #pragma omp parallel for reduction(inscan, +: a)
+// CHECK-NEXT: for (int i = 0; i < 10; ++i) {
+// CHECK-NEXT: #pragma omp scan inclusive(a){{$}}
+
 // CHECK:      static int a;
 // CHECK-NEXT: #pragma omp for reduction(inscan, +: a)
 // CHECK-NEXT: for (int i = 0; i < 10; ++i) {
 // CHECK-NEXT: #pragma omp scan inclusive(a)
+
+// CHECK: #pragma omp parallel for reduction(inscan, +: a)
+// CHECK-NEXT: for (int i = 0; i < 10; ++i) {
+// CHECK-NEXT: #pragma omp scan inclusive(a)
+
 // CHECK:      static char a;
 // CHECK-NEXT: #pragma omp for reduction(inscan, +: a)
 // CHECK-NEXT: for (int i = 0; i < 10; ++i) {
 // CHECK-NEXT: #pragma omp scan inclusive(a)
 
+// CHECK: #pragma omp parallel for reduction(inscan, +: a)
+// CHECK-NEXT: for (int i = 0; i < 10; ++i) {
+// CHECK-NEXT: #pragma omp scan inclusive(a)
+
 int main(int argc, char **argv) {
   static int a;
 // CHECK: static int a;
diff --git a/clang/test/Parser/c23-constexpr.c b/clang/test/Parser/c23-constexpr.c
new file mode 100644
index 0000000000000..156128fa0745c
--- /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 0000000000000..3b989a659db56
--- /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/ParserOpenACC/parse-clauses.c b/clang/test/ParserOpenACC/parse-clauses.c
index fb2f51890d7d7..a82c3662f2ad9 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 adb5e3c7c7552..ecedfd9e9e6d6 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/has_attribute.cpp b/clang/test/Preprocessor/has_attribute.cpp
index 33546dbb175f6..00ec57615c84b 100644
--- a/clang/test/Preprocessor/has_attribute.cpp
+++ b/clang/test/Preprocessor/has_attribute.cpp
@@ -1,4 +1,6 @@
+// RUN: %clang_cc1 -triple i386-unknown-unknown -fms-compatibility -std=c++03 -E -P %s -o - | FileCheck %s --check-prefixes=CHECK,ITANIUM --implicit-check-not=:
 // RUN: %clang_cc1 -triple i386-unknown-unknown -fms-compatibility -std=c++11 -E -P %s -o - | FileCheck %s --check-prefixes=CHECK,ITANIUM --implicit-check-not=:
+// RUN: %clang_cc1 -triple i386-windows -fms-compatibility -std=c++03 -E -P %s -o - | FileCheck %s --check-prefixes=CHECK,WINDOWS --implicit-check-not=:
 // RUN: %clang_cc1 -triple i386-windows -fms-compatibility -std=c++11 -E -P %s -o - | FileCheck %s --check-prefixes=CHECK,WINDOWS --implicit-check-not=:
 
 #define CXX11(x) x: __has_cpp_attribute(x)
@@ -65,7 +67,7 @@ CXX11(unlikely)
 // CHECK: likely: 201803L
 // CHECK: maybe_unused: 201603L
 // ITANIUM: no_unique_address: 201803L
-// WINDOWS: no_unique_address: 0 
+// WINDOWS: no_unique_address: 0
 // ITANIUM: msvc::no_unique_address: 0
 // WINDOWS: msvc::no_unique_address: 201803L
 // CHECK: nodiscard: 201907L
diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c
index ea81c66204430..1a15be1c6e4dc 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 {{.*$}}
@@ -74,6 +75,7 @@
 // CHECK-NOT: __riscv_xventanacondops {{.*$}}
 // CHECK-NOT: __riscv_za128rs {{.*$}}
 // CHECK-NOT: __riscv_za64rs {{.*$}}
+// CHECK-NOT: __riscv_zacas {{.*$}}
 // CHECK-NOT: __riscv_zawrs {{.*$}}
 // CHECK-NOT: __riscv_zba {{.*$}}
 // CHECK-NOT: __riscv_zbb {{.*$}}
@@ -166,7 +168,6 @@
 // CHECK-NOT: __riscv_ssqosid{{.*$}}
 // CHECK-NOT: __riscv_supm{{.*$}}
 // CHECK-NOT: __riscv_zaamo {{.*$}}
-// CHECK-NOT: __riscv_zacas {{.*$}}
 // CHECK-NOT: __riscv_zalasr {{.*$}}
 // CHECK-NOT: __riscv_zalrsc {{.*$}}
 // CHECK-NOT: __riscv_zcmop {{.*$}}
@@ -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
@@ -660,6 +669,14 @@
 // RUN:   -o - | FileCheck --check-prefix=CHECK-ZA64RS-EXT %s
 // CHECK-ZA64RS-EXT: __riscv_za64rs 1000000{{$}}
 
+// RUN: %clang --target=riscv32 \
+// RUN:   -march=rv32i_zacas1p0 -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-ZACAS-EXT %s
+// RUN: %clang --target=riscv64 \
+// RUN:   -march=rv64i_zacas1p0 -E -dM %s \
+// RUN:   -o - | FileCheck --check-prefix=CHECK-ZACAS-EXT %s
+// CHECK-ZACAS-EXT: __riscv_zacas 1000000{{$}}
+
 // RUN: %clang --target=riscv32-unknown-linux-gnu \
 // RUN:   -march=rv32izawrs -E -dM %s \
 // RUN:   -o - | FileCheck --check-prefix=CHECK-ZAWRS-EXT %s
@@ -1485,14 +1502,6 @@
 // RUN:   -o - | FileCheck --check-prefix=CHECK-ZAAMO-EXT %s
 // CHECK-ZAAMO-EXT: __riscv_zaamo 2000{{$}}
 
-// RUN: %clang --target=riscv32 -menable-experimental-extensions \
-// RUN:   -march=rv32i_zacas1p0 -E -dM %s \
-// RUN:   -o - | FileCheck --check-prefix=CHECK-ZACAS-EXT %s
-// RUN: %clang --target=riscv64 -menable-experimental-extensions \
-// RUN:   -march=rv64i_zacas1p0 -E -dM %s \
-// RUN:   -o - | FileCheck --check-prefix=CHECK-ZACAS-EXT %s
-// CHECK-ZACAS-EXT: __riscv_zacas 1000000{{$}}
-
 // RUN: %clang --target=riscv32 -menable-experimental-extensions \
 // RUN:   -march=rv32i_zalasr0p1 -E -dM %s \
 // RUN:   -o - | FileCheck --check-prefix=CHECK-ZALASR-EXT %s
diff --git a/clang/test/Sema/aarch64-cpu-supports.c b/clang/test/Sema/aarch64-cpu-supports.c
index 24aae9542dbc4..ddeed7c5bc9e9 100644
--- a/clang/test/Sema/aarch64-cpu-supports.c
+++ b/clang/test/Sema/aarch64-cpu-supports.c
@@ -5,19 +5,19 @@ int test_aarch64_features(void) {
   // expected-error@+1 {{expression is not a string literal}}
   if (__builtin_cpu_supports(ssbs2))
     return 1;
-  // expected-error@+1 {{invalid cpu feature string}}
+  // expected-warning@+1 {{invalid cpu feature string}}
   if (__builtin_cpu_supports(""))
     return 2;
-  // expected-error@+1 {{invalid cpu feature string}}
+  // expected-warning@+1 {{invalid cpu feature string}}
   if (__builtin_cpu_supports("pmull128"))
     return 3;
-  // expected-error@+1 {{invalid cpu feature string}}
+  // expected-warning@+1 {{invalid cpu feature string}}
   if (__builtin_cpu_supports("sve2,rpres"))
     return 4;
-  // expected-error@+1 {{invalid cpu feature string}}
+  // expected-warning@+1 {{invalid cpu feature string}}
   if (__builtin_cpu_supports("dgh+sve2-pmull"))
     return 5;
-  // expected-error@+1 {{invalid cpu feature string}}
+  // expected-warning@+1 {{invalid cpu feature string}}
   if (__builtin_cpu_supports("default"))
     return 6;
   if (__builtin_cpu_supports(" ssbs + bti "))
diff --git a/clang/test/Sema/aix-attr-tls_model.c b/clang/test/Sema/aix-attr-tls_model.c
index 9c22d6cceed81..7c2047bced939 100644
--- a/clang/test/Sema/aix-attr-tls_model.c
+++ b/clang/test/Sema/aix-attr-tls_model.c
@@ -6,6 +6,6 @@
 #endif
 
 static __thread int y __attribute((tls_model("global-dynamic"))); // no-warning
-static __thread int y __attribute((tls_model("local-dynamic"))); // expected-error {{TLS model 'local-dynamic' is not yet supported on AIX}}
+static __thread int y __attribute((tls_model("local-dynamic"))); // expected-no-diagnostics
 static __thread int y __attribute((tls_model("initial-exec"))); // no-warning
 static __thread int y __attribute((tls_model("local-exec"))); // no-warning
diff --git a/clang/test/Sema/attr-target-clones-aarch64.c b/clang/test/Sema/attr-target-clones-aarch64.c
index 4054b7c837ec9..0ce277f41884c 100644
--- a/clang/test/Sema/attr-target-clones-aarch64.c
+++ b/clang/test/Sema/attr-target-clones-aarch64.c
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -triple aarch64-linux-gnu  -fsyntax-only -verify %s
 
-void __attribute__((target_clones("fp16+sve2-aes", "sb+sve2-sha3+rcpc3+mops"))) no_def(void);
+void __attribute__((target_clones("fp16+sve2-aes", "sb+sve2-sha3+rcpc3+mops", "rdma"))) no_def(void);
 
 // expected-warning@+1 {{unsupported 'default' in the 'target_clones' attribute string; 'target_clones' attribute ignored}}
 void __attribute__((target_clones("default+sha3"))) warn1(void);
diff --git a/clang/test/Sema/builtin-cpu-supports.c b/clang/test/Sema/builtin-cpu-supports.c
index 733d797f3ff8f..51ee9661807f8 100644
--- a/clang/test/Sema/builtin-cpu-supports.c
+++ b/clang/test/Sema/builtin-cpu-supports.c
@@ -7,7 +7,7 @@ extern const char *str;
 
 int main(void) {
 #ifdef __x86_64__
-  if (__builtin_cpu_supports("ss")) // expected-error {{invalid cpu feature string}}
+  if (__builtin_cpu_supports("ss")) // expected-warning {{invalid cpu feature string}}
     a("sse4.2");
 
   if (__builtin_cpu_supports(str)) // expected-error {{expression is not a string literal}}
@@ -25,9 +25,9 @@ int main(void) {
   (void)__builtin_cpu_supports("x86-64-v2");
   (void)__builtin_cpu_supports("x86-64-v3");
   (void)__builtin_cpu_supports("x86-64-v4");
-  (void)__builtin_cpu_supports("x86-64-v5"); // expected-error {{invalid cpu feature string for builtin}}
+  (void)__builtin_cpu_supports("x86-64-v5"); // expected-warning {{invalid cpu feature string for builtin}}
 #else
-  if (__builtin_cpu_supports("neon")) // expected-error {{invalid cpu feature string for builtin}}
+  if (__builtin_cpu_supports("neon")) // expected-warning {{invalid cpu feature string for builtin}}
     a("vsx");
 
   if (__builtin_cpu_is("cortex-x3")) // expected-error {{builtin is not supported on this target}}
diff --git a/clang/test/Sema/builtin-popcountg.c b/clang/test/Sema/builtin-popcountg.c
index e18b910046ff0..9d095927d24e1 100644
--- a/clang/test/Sema/builtin-popcountg.c
+++ b/clang/test/Sema/builtin-popcountg.c
@@ -1,14 +1,23 @@
-// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only -verify -Wpedantic %s
+// RUN: %clang_cc1 -std=c23 -triple=x86_64-pc-linux-gnu -fsyntax-only -verify -Wpedantic %s
 
 typedef int int2 __attribute__((ext_vector_type(2)));
 
-void test_builtin_popcountg(int i, double d, int2 i2) {
+void test_builtin_popcountg(short s, int i, __int128 i128, _BitInt(128) bi128,
+                            double d, int2 i2) {
   __builtin_popcountg();
   // expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
   __builtin_popcountg(i, i);
   // expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
+  __builtin_popcountg(s);
+  // expected-error@-1 {{1st argument must be a type of unsigned integer (was 'short')}}
+  __builtin_popcountg(i);
+  // expected-error@-1 {{1st argument must be a type of unsigned integer (was 'int')}}
+  __builtin_popcountg(i128);
+  // expected-error@-1 {{1st argument must be a type of unsigned integer (was '__int128')}}
+  __builtin_popcountg(bi128);
+  // expected-error@-1 {{1st argument must be a type of unsigned integer (was '_BitInt(128)')}}
   __builtin_popcountg(d);
-  // expected-error@-1 {{1st argument must be a type of integer (was 'double')}}
+  // expected-error@-1 {{1st argument must be a type of unsigned integer (was 'double')}}
   __builtin_popcountg(i2);
-  // expected-error@-1 {{1st argument must be a type of integer (was 'int2' (vector of 2 'int' values))}}
+  // expected-error@-1 {{1st argument must be a type of unsigned integer (was 'int2' (vector of 2 'int' values))}}
 }
diff --git a/clang/test/Sema/constexpr.c b/clang/test/Sema/constexpr.c
new file mode 100644
index 0000000000000..8286cd2107d2f
--- /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 cf822f346e8b2..220fc1bed515a 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/riscv-vector-float64-check.c b/clang/test/Sema/riscv-vector-float64-check.c
index ee7db32663959..f21ae5c0c7040 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 4e9e6b7ee558b..ae5e8076e0bed 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 95e64748fb1fb..09221990ac11d 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/SemaCXX/GH83461.cpp b/clang/test/SemaCXX/GH83461.cpp
new file mode 100644
index 0000000000000..509535e883e6d
--- /dev/null
+++ b/clang/test/SemaCXX/GH83461.cpp
@@ -0,0 +1,60 @@
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+
+struct S {
+  template
+  friend void foo(auto){}
+
+  template
+  friend void foo2(){}
+};
+
+template
+struct TemplS {
+  template
+  friend void foo3(auto){}
+
+  template
+  friend void foo4(){}
+};
+
+void Inst() {
+  TemplS();
+}
+// expected-error@+2{{template parameter missing a default argument}}
+// expected-note@+1{{previous default template argument defined here}}
+template
+struct ClassTempl{};
+
+struct HasFriendClassTempl {
+  // expected-error@+1{{default template argument not permitted on a friend template}}
+  template
+  friend struct Friend;
+
+  // expected-error@+3{{cannot define a type in a friend declaration}}
+  // expected-error@+1{{default template argument not permitted on a friend template}}
+  template
+  friend struct Friend2{};
+};
+
+template
+struct HasFriendClassTempl2 {
+  // expected-error@+3{{template parameter missing a default argument}}
+  // expected-note@+2{{previous default template argument defined here}}
+  // expected-note@#INST2{{in instantiation of template class}}
+  template
+  friend struct Friend;
+};
+
+void Inst2() {
+  HasFriendClassTempl2(); // #INST2
+}
+
+// expected-error@+2{{template parameter missing a default argument}}
+// expected-note@+1{{previous default template argument defined here}}
+template
+static constexpr U VarTempl;
+
+// expected-error@+2{{template parameter missing a default argument}}
+// expected-note@+1{{previous default template argument defined here}}
+template
+using TypeAlias = U;
diff --git a/clang/test/SemaCXX/attr-declspec-ignored.cpp b/clang/test/SemaCXX/attr-declspec-ignored.cpp
index dfea8cc4d47c8..98e0ffd1a1afd 100644
--- a/clang/test/SemaCXX/attr-declspec-ignored.cpp
+++ b/clang/test/SemaCXX/attr-declspec-ignored.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 %s -verify -fsyntax-only
+// RUN: %clang_cc1 %s -std=c++03 -Wno-c++11-extensions -verify -fsyntax-only
 
 namespace test1 {
   __attribute__((visibility("hidden")))  __attribute__((aligned)) class A; // expected-warning{{attribute 'visibility' is ignored, place it after "class" to apply attribute to type declaration}} \
@@ -28,7 +29,7 @@ namespace test1 {
     // expected-warning{{attribute 'aligned' is ignored, place it after "enum class" to apply attribute to type declaration}}
     __attribute__((visibility("hidden")))  __attribute__((aligned)) enum struct ES {}; // expected-warning{{attribute 'visibility' is ignored, place it after "enum struct" to apply attribute to type declaration}} \
     // expected-warning{{attribute 'aligned' is ignored, place it after "enum struct" to apply attribute to type declaration}}
-  
+
     // Also test [[]] attribute syntax. (On a non-nested declaration, these
     // generate a hard "misplaced attributes" error, which we test for
     // elsewhere.)
diff --git a/clang/test/SemaCXX/attr-gnu.cpp b/clang/test/SemaCXX/attr-gnu.cpp
index c257c2b029127..941d01a2e611a 100644
--- a/clang/test/SemaCXX/attr-gnu.cpp
+++ b/clang/test/SemaCXX/attr-gnu.cpp
@@ -1,7 +1,8 @@
-// RUN: %clang_cc1 -std=gnu++17 -fsyntax-only -fms-compatibility -verify %s
-
-void f() {
-  // GNU-style attributes are prohibited in this position.
+// RUN: %clang_cc1 -std=gnu++03 -fsyntax-only -fms-compatibility -Wno-c++11-extensions -Wno-c++17-extensions -verify %s
+// RUN: %clang_cc1 -std=gnu++17 -fsyntax-only -fms-compatibility -verify %s
+
+void f() {
+  // GNU-style attributes are prohibited in this position.
   auto P = new int * __attribute__((vector_size(8))); // expected-error {{an attribute list cannot appear here}} \
                                                       // expected-error {{invalid vector element type 'int *'}}
 
@@ -47,13 +48,13 @@ void tuTest1(Tu u); // expected-note {{candidate function not viable: no kn
 void tuTest2(Tu3 u); // expected-note {{candidate function not viable: no known conversion from 'int' to 'Tu3' for 1st argument}}
 void tu() {
   int x = 2;
-  tuTest1(x); // expected-error {{no matching function for call to 'tuTest1'}}
-  tuTest2(x); // expected-error {{no matching function for call to 'tuTest2'}}
-}
-
-[[gnu::__const__]] int f2() { return 12; }
-[[__gnu__::__const__]] int f3() { return 12; }
-[[using __gnu__ : __const__]] int f4() { return 12; }
-
-static_assert(__has_cpp_attribute(gnu::__const__));
-static_assert(__has_cpp_attribute(__gnu__::__const__));
+  tuTest1(x); // expected-error {{no matching function for call to 'tuTest1'}}
+  tuTest2(x); // expected-error {{no matching function for call to 'tuTest2'}}
+}
+
+[[gnu::__const__]] int f2() { return 12; }
+[[__gnu__::__const__]] int f3() { return 12; }
+[[using __gnu__ : __const__]] int f4() { return 12; }
+
+static_assert(__has_cpp_attribute(gnu::__const__));
+static_assert(__has_cpp_attribute(__gnu__::__const__));
diff --git a/clang/test/SemaCXX/attr-target-version.cpp b/clang/test/SemaCXX/attr-target-version.cpp
index 5c542ad2e2dca..0bd710c4e282a 100644
--- a/clang/test/SemaCXX/attr-target-version.cpp
+++ b/clang/test/SemaCXX/attr-target-version.cpp
@@ -7,6 +7,7 @@ void __attribute__((target_version("dotprod"))) no_def(void);
 void __attribute__((target_version("rdm+fp"))) no_def(void);
 void __attribute__((target_version("rcpc3"))) no_def(void);
 void __attribute__((target_version("mops"))) no_def(void);
+void __attribute__((target_version("rdma"))) no_def(void);
 
 // expected-error@+1 {{no matching function for call to 'no_def'}}
 void foo(void) { no_def(); }
diff --git a/clang/test/SemaCXX/bool.cpp b/clang/test/SemaCXX/bool.cpp
index 33e22c8f6d36f..57cdba1b1a830 100644
--- a/clang/test/SemaCXX/bool.cpp
+++ b/clang/test/SemaCXX/bool.cpp
@@ -2,6 +2,11 @@
 // RUN: %clang_cc1 %std_cxx98-14 -fsyntax-only -verify=expected,precxx17 -Wno-constant-conversion -Wno-deprecated -Wdeprecated-increment-bool %s
 // RUN: %clang_cc1 %std_cxx17- -fsyntax-only -verify=expected,cxx17 -Wno-constant-conversion -Wno-deprecated -Wdeprecated-increment-bool %s
 
+// RUN: %clang_cc1 %std_cxx98-14 -fsyntax-only -verify=expected,precxx17 -Wno-constant-conversion %s -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 %std_cxx98-14 -fsyntax-only -verify=expected,precxx17 -Wno-constant-conversion -Wno-deprecated -Wdeprecated-increment-bool %s -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 %std_cxx17- -fsyntax-only -verify=expected,cxx17 -Wno-constant-conversion -Wno-deprecated -Wdeprecated-increment-bool %s -fexperimental-new-constant-interpreter
+
+
 // Bool literals can be enum values.
 enum {
   ReadWrite = false,
diff --git a/clang/test/SemaCXX/cxx03-cxx11-attr.cpp b/clang/test/SemaCXX/cxx03-cxx11-attr.cpp
new file mode 100644
index 0000000000000..5a273c8fe2534
--- /dev/null
+++ b/clang/test/SemaCXX/cxx03-cxx11-attr.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -std=c++03 -fsyntax-only %s
+
+// Ensure that __has_cpp_attribute and argument parsing work in C++03
+
+#if !__has_cpp_attribute(nodiscard)
+#  error
+#endif
+
+[[gnu::assume_aligned(4)]] void* g() { return __nullptr; }
diff --git a/clang/test/SemaCXX/cxx2a-consteval-default-params.cpp b/clang/test/SemaCXX/cxx2a-consteval-default-params.cpp
index be8f7cc788589..e4b13725b2dac 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-initializer-aggregates.cpp b/clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp
index 510ace58c35a6..1e9c5fa082d07 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/enum.cpp b/clang/test/SemaCXX/enum.cpp
index fc65fd16f8c30..c482b3c571ab4 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 0e8ad050aa14d..6049458b93bbd 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/restrict-this.cpp b/clang/test/SemaCXX/restrict-this.cpp
new file mode 100644
index 0000000000000..e78c8e0d56e2f
--- /dev/null
+++ b/clang/test/SemaCXX/restrict-this.cpp
@@ -0,0 +1,69 @@
+// RUN: %clang_cc1 -verify -fsyntax-only %s
+// expected-no-diagnostics
+
+struct C {
+  void f() __restrict {
+    static_assert(__is_same(decltype(this), C *__restrict));
+    (void) [this]() {
+      static_assert(__is_same(decltype(this), C *__restrict));
+      (void) [this]() { static_assert(__is_same(decltype(this), C *__restrict)); };
+
+      // By-value capture means 'this' is now a different object; do not
+      // make it __restrict.
+      (void) [*this]() { static_assert(__is_same(decltype(this), const C *)); };
+      (void) [*this]() mutable { static_assert(__is_same(decltype(this), C *)); };
+    };
+  }
+};
+
+template  struct TC {
+  void f() __restrict {
+    static_assert(__is_same(decltype(this), TC *__restrict));
+    (void) [this]() {
+      static_assert(__is_same(decltype(this), TC *__restrict));
+      (void) [this]() { static_assert(__is_same(decltype(this), TC *__restrict)); };
+
+      // By-value capture means 'this' is now a different object; do not
+      // make it __restrict.
+      (void) [*this]() { static_assert(__is_same(decltype(this), const TC *)); };
+      (void) [*this]() mutable { static_assert(__is_same(decltype(this), TC *)); };
+    };
+  }
+};
+
+void f() {
+  TC{}.f();
+}
+
+namespace gh18121 {
+struct Foo {
+  void member() __restrict {
+    Foo *__restrict This = this;
+  }
+};
+}
+
+namespace gh42411 {
+struct foo {
+    int v;
+    void f() const __restrict {
+        static_assert(__is_same(decltype((v)), const int&));
+        (void) [this]() { static_assert(__is_same(decltype((v)), const int&)); };
+    }
+};
+}
+
+namespace gh82941 {
+void f(int& x) {
+    (void)x;
+}
+
+class C {
+    int x;
+    void g() __restrict;
+};
+
+void C::g() __restrict {
+    f(this->x);
+}
+}
diff --git a/clang/test/SemaCXX/source_location.cpp b/clang/test/SemaCXX/source_location.cpp
index e92fb35b653a8..1699f54e4830b 100644
--- a/clang/test/SemaCXX/source_location.cpp
+++ b/clang/test/SemaCXX/source_location.cpp
@@ -805,3 +805,21 @@ static_assert(S(0).j == S{0}.j);
 static_assert(S(0).j == S{0}.i);
 }
 #endif
+
+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 c9e3c30e5533d..5f7c20cc2e11c 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/undefined-internal.cpp b/clang/test/SemaCXX/undefined-internal.cpp
index 790c96c9fe451..054e71b92f93d 100644
--- a/clang/test/SemaCXX/undefined-internal.cpp
+++ b/clang/test/SemaCXX/undefined-internal.cpp
@@ -2,11 +2,21 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -Wbind-to-temporary-copy -std=c++98 %s
 // RUN: %clang_cc1 -fsyntax-only -verify -Wbind-to-temporary-copy -std=c++11 %s
 
+// RUN: %clang_cc1 -fsyntax-only -verify -Wbind-to-temporary-copy %s -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -fsyntax-only -verify -Wbind-to-temporary-copy -std=c++98 %s -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -fsyntax-only -verify -Wbind-to-temporary-copy -std=c++11 %s -fexperimental-new-constant-interpreter
+
+
 // Make sure we don't produce invalid IR.
 // RUN: %clang_cc1 -emit-llvm-only %s
 // RUN: %clang_cc1 -emit-llvm-only -std=c++98 %s
 // RUN: %clang_cc1 -emit-llvm-only -std=c++11 %s
 
+// RUN: %clang_cc1 -emit-llvm-only %s -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -emit-llvm-only -std=c++98 %s -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -emit-llvm-only -std=c++11 %s -fexperimental-new-constant-interpreter
+
+
 namespace test1 {
   static void foo(); // expected-warning {{function 'test1::foo' has internal linkage but is not defined}}
   template  static void bar(); // expected-warning {{function 'test1::bar' has internal linkage but is not defined}}
diff --git a/clang/test/SemaCXX/warn-bool-conversion.cpp b/clang/test/SemaCXX/warn-bool-conversion.cpp
index c81d52d864f2d..18c35776b17bc 100644
--- a/clang/test/SemaCXX/warn-bool-conversion.cpp
+++ b/clang/test/SemaCXX/warn-bool-conversion.cpp
@@ -81,6 +81,33 @@ struct S2 {
 
 bool f5();
 bool f6(int);
+#if __cplusplus >= 201103L
+auto f7 = []{};
+auto f8 = [](){};
+
+void foo() {
+  bool b;
+  b = f7; // expected-warning {{address of lambda function pointer conversion operator will always evaluate to 'true'}}
+  b = f8; // expected-warning {{address of lambda function pointer conversion operator will always evaluate to 'true'}}
+  bool is_true = [](){ return true; };
+  // expected-warning@-1{{address of lambda function pointer conversion operator will always evaluate to 'true'}}
+}
+
+template 
+static bool IsFalse(const Ts&...) { return false; }
+template 
+static bool IsFalse(const T& p) {
+  bool b;
+  b = f7; // expected-warning {{address of lambda function pointer conversion operator will always evaluate to 'true'}}
+  // Intentionally not warned on because p could be a lambda type in one
+  // instantiation, but a pointer type in another.
+  return p ? false : true;
+}
+
+bool use_instantiation() {
+  return IsFalse([]() { return 0; });
+}
+#endif
 
 void bar() {
   bool b;
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 0000000000000..5aeeb45f81e22
--- /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/SemaCXX/warn-unused-variables.cpp b/clang/test/SemaCXX/warn-unused-variables.cpp
index b649c7d808935..29e8d08d37d8c 100644
--- a/clang/test/SemaCXX/warn-unused-variables.cpp
+++ b/clang/test/SemaCXX/warn-unused-variables.cpp
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify %s
-// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify -std=gnu++11 %s
+// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify=expected,cxx98-14 -std=gnu++11 %s
+// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify=expected,cxx98-14 -std=gnu++14 %s
+// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -Wunused-label -Wno-c++1y-extensions -verify -std=gnu++17 %s
 template void f() {
   T t;
   t = 17;
@@ -183,7 +185,8 @@ void foo(int size) {
   NonTriviallyDestructible array[2];  // no warning
   NonTriviallyDestructible nestedArray[2][2]; // no warning
 
-  Foo fooScalar = 1; // expected-warning {{unused variable 'fooScalar'}}
+  // Copy initialzation gives warning before C++17
+  Foo fooScalar = 1; // cxx98-14-warning {{unused variable 'fooScalar'}}
   Foo fooArray[] = {1,2}; // expected-warning {{unused variable 'fooArray'}}
   Foo fooNested[2][2] = { {1,2}, {3,4} }; // expected-warning {{unused variable 'fooNested'}}
 }
@@ -297,3 +300,29 @@ void RAIIWrapperTest() {
 }
 
 } // namespace gh54489
+
+// Ensure that -Wunused-variable does not emit warning
+// on copy constructors with side effects (C++17 and later)
+#if __cplusplus >= 201703L
+namespace gh79518 {
+
+struct S {
+    S(int);
+};
+
+// With an initializer list
+struct A {
+  int x;
+  A(int x) : x(x) {}
+};
+
+void foo() {
+    S s(0); // no warning
+    S s2 = 0; // no warning
+    S s3{0}; // no warning
+
+    A a = 1; // no warning
+}
+
+} // namespace gh79518
+#endif
diff --git a/clang/test/SemaHLSL/BuiltIns/any-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/any-errors.hlsl
new file mode 100644
index 0000000000000..862b946520731
--- /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/dot-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl
index 54d093aa7ce3a..59eb9482b9ef9 100644
--- a/clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/dot-errors.hlsl
@@ -1,109 +1,110 @@
 // 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_no_second_arg ( float2 p0) {
-  return __builtin_hlsl_dot ( p0 );
+float test_no_second_arg(float2 p0) {
+  return __builtin_hlsl_dot(p0);
   // expected-error@-1 {{too few arguments to function call, expected 2, have 1}}
 }
 
-float test_too_many_arg ( float2 p0) {
-  return __builtin_hlsl_dot ( p0, p0, p0 );
+float test_too_many_arg(float2 p0) {
+  return __builtin_hlsl_dot(p0, p0, p0);
   // expected-error@-1 {{too many arguments to function call, expected 2, have 3}}
 }
 
-float test_dot_no_second_arg ( float2 p0) {
-  return dot ( p0 );
+float test_dot_no_second_arg(float2 p0) {
+  return dot(p0);
   // expected-error@-1 {{no matching function for call to 'dot'}}
 }
 
-float test_dot_vector_size_mismatch ( float3 p0, float2 p1 ) {
-  return dot ( p0, p1 );
+float test_dot_vector_size_mismatch(float3 p0, float2 p1) {
+  return dot(p0, p1);
   // expected-warning@-1 {{implicit conversion truncates vector: 'float3' (aka 'vector') to 'float __attribute__((ext_vector_type(2)))' (vector of 2 'float' values)}}
 }
 
-float test_dot_builtin_vector_size_mismatch ( float3 p0, float2 p1 ) {
-  return __builtin_hlsl_dot ( p0, p1 );
-  // expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must have the same type}}
+float test_dot_builtin_vector_size_mismatch(float3 p0, float2 p1) {
+  return __builtin_hlsl_dot(p0, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_dot' must have the same type}}
 }
 
-float test_dot_scalar_mismatch ( float p0, int p1 ) {
-  return dot ( p0, p1 );
+float test_dot_scalar_mismatch(float p0, int p1) {
+  return dot(p0, p1);
   // expected-error@-1 {{call to 'dot' is ambiguous}}
 }
 
-float test_dot_element_type_mismatch ( int2 p0, float2 p1 ) {
-  return dot ( p0, p1 );
+float test_dot_element_type_mismatch(int2 p0, float2 p1) {
+  return dot(p0, p1);
   // expected-error@-1 {{call to 'dot' is ambiguous}}
 }
 
 //NOTE: for all the *_promotion we are intentionally not handling type promotion in builtins
-float test_builtin_dot_vec_int_to_float_promotion ( int2 p0, float2 p1 ) {
-  return __builtin_hlsl_dot ( p0, p1 );
-  // expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must have the same type}}
+float test_builtin_dot_vec_int_to_float_promotion(int2 p0, float2 p1) {
+  return __builtin_hlsl_dot(p0, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_dot' must have the same type}}
 }
 
-int64_t test_builtin_dot_vec_int_to_int64_promotion( int64_t2 p0, int2 p1 ) {
-  return __builtin_hlsl_dot( p0, p1 );
-  // expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must have the same type}}
+int64_t test_builtin_dot_vec_int_to_int64_promotion(int64_t2 p0, int2 p1) {
+  return __builtin_hlsl_dot(p0, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_dot' must have the same type}}
 }
 
-float test_builtin_dot_vec_half_to_float_promotion( float2 p0, half2 p1 ) {
-  return __builtin_hlsl_dot( p0, p1 );
-  // expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must have the same type}}
+float test_builtin_dot_vec_half_to_float_promotion(float2 p0, half2 p1) {
+  return __builtin_hlsl_dot(p0, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_dot' must have the same type}}
 }
 
 #ifdef __HLSL_ENABLE_16_BIT
-float test_builtin_dot_vec_int16_to_float_promotion( float2 p0, int16_t2 p1 ) {
-  return __builtin_hlsl_dot( p0, p1 );
-  // expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must have the same type}}
+float test_builtin_dot_vec_int16_to_float_promotion(float2 p0, int16_t2 p1) {
+  return __builtin_hlsl_dot(p0, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_dot' must have the same type}}
 }
 
-half test_builtin_dot_vec_int16_to_half_promotion( half2 p0, int16_t2 p1 ) {
-  return __builtin_hlsl_dot( p0, p1 );
-  // expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must have the same type}}
+half test_builtin_dot_vec_int16_to_half_promotion(half2 p0, int16_t2 p1) {
+  return __builtin_hlsl_dot(p0, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_dot' must have the same type}}
 }
 
-int test_builtin_dot_vec_int16_to_int_promotion( int2 p0, int16_t2 p1 ) {
-  return __builtin_hlsl_dot( p0, p1 );
-  // expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must have the same type}}
+int test_builtin_dot_vec_int16_to_int_promotion(int2 p0, int16_t2 p1) {
+  return __builtin_hlsl_dot(p0, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_dot' must have the same type}}
 }
 
-int64_t test_builtin_dot_vec_int16_to_int64_promotion( int64_t2 p0, int16_t2 p1 ) {
-  return __builtin_hlsl_dot( p0, p1 );
-  // expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must have the same type}}
+int64_t test_builtin_dot_vec_int16_to_int64_promotion(int64_t2 p0,
+                                                      int16_t2 p1) {
+  return __builtin_hlsl_dot(p0, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_dot' must have the same type}}
 }
 #endif
 
-float test_builtin_dot_float2_splat ( float p0, float2 p1 ) {
-  return __builtin_hlsl_dot( p0, p1 );
-  // expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must be vectors}}
+float test_builtin_dot_float2_splat(float p0, float2 p1) {
+  return __builtin_hlsl_dot(p0, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_dot' must be vectors}}
 }
 
-float test_builtin_dot_float3_splat ( float p0, float3 p1 ) {
-  return __builtin_hlsl_dot( p0, p1 );
-  // expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must be vectors}}
+float test_builtin_dot_float3_splat(float p0, float3 p1) {
+  return __builtin_hlsl_dot(p0, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_dot' must be vectors}}
 }
 
-float test_builtin_dot_float4_splat ( float p0, float4 p1 ) {
-  return __builtin_hlsl_dot( p0, p1 );
-  // expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must be vectors}}
+float test_builtin_dot_float4_splat(float p0, float4 p1) {
+  return __builtin_hlsl_dot(p0, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_dot' must be vectors}}
 }
 
-float test_dot_float2_int_splat ( float2 p0, int p1 ) {
-  return __builtin_hlsl_dot ( p0, p1 );
-  // expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must be vectors}}
+float test_dot_float2_int_splat(float2 p0, int p1) {
+  return __builtin_hlsl_dot(p0, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_dot' must be vectors}}
 }
 
-float test_dot_float3_int_splat ( float3 p0, int p1 ) {
-  return __builtin_hlsl_dot ( p0, p1 );
-  // expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must be vectors}}
+float test_dot_float3_int_splat(float3 p0, int p1) {
+  return __builtin_hlsl_dot(p0, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_dot' must be vectors}}
 }
 
-float test_builtin_dot_int_vect_to_float_vec_promotion ( int2 p0, float p1 ) {
-  return __builtin_hlsl_dot ( p0, p1 );
-  // expected-error@-1 {{first two arguments to '__builtin_hlsl_dot' must be vectors}}
+float test_builtin_dot_int_vect_to_float_vec_promotion(int2 p0, float p1) {
+  return __builtin_hlsl_dot(p0, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_dot' must be vectors}}
 }
 
-int test_builtin_dot_bool_type_promotion ( bool p0, bool p1 ) {
-  return __builtin_hlsl_dot ( p0, p1 );
+int test_builtin_dot_bool_type_promotion(bool p0, bool p1) {
+  return __builtin_hlsl_dot(p0, p1);
   // expected-error@-1 {{1st argument must be a vector, integer or floating point type (was 'bool')}}
 }
diff --git a/clang/test/SemaHLSL/BuiltIns/exp-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/exp-errors.hlsl
new file mode 100644
index 0000000000000..e2e79abb74a32
--- /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/frac-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/frac-errors.hlsl
new file mode 100644
index 0000000000000..06dbdf0a68dfc
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/frac-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_frac();
+  // expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+float2 test_too_many_arg(float2 p0) {
+  return __builtin_hlsl_elementwise_frac(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_frac(p1);
+  // expected-error@-1 {{1st argument must be a vector, integer or floating point type (was 'bool')}}
+}
+
+float builtin_frac_int_to_float_promotion(int p1) {
+  return __builtin_hlsl_elementwise_frac(p1);
+  // expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}}
+}
+
+float2 builtin_frac_int2_to_float2_promotion(int2 p1) {
+  return __builtin_hlsl_elementwise_frac(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/SemaHLSL/BuiltIns/lerp-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl
new file mode 100644
index 0000000000000..f6ce87e7c33e3
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/lerp-errors.hlsl
@@ -0,0 +1,96 @@
+// 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_lerp(p0);
+  // expected-error@-1 {{too few arguments to function call, expected 3, have 1}}
+}
+
+float2 test_no_third_arg(float2 p0) {
+  return __builtin_hlsl_lerp(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_lerp(p0, p0, p0, p0);
+  // expected-error@-1 {{too many arguments to function call, expected 3, have 4}}
+}
+
+float2 test_lerp_no_second_arg(float2 p0) {
+  return lerp(p0);
+  // expected-error@-1 {{no matching function for call to 'lerp'}}
+}
+
+float2 test_lerp_vector_size_mismatch(float3 p0, float2 p1) {
+  return lerp(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_lerp_builtin_vector_size_mismatch(float3 p0, float2 p1) {
+  return __builtin_hlsl_lerp(p0, p1, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must have the same type}}
+}
+
+float test_lerp_scalar_mismatch(float p0, half p1) {
+  return lerp(p1, p0, p1);
+  // expected-error@-1 {{call to 'lerp' is ambiguous}}
+}
+
+float2 test_lerp_element_type_mismatch(half2 p0, float2 p1) {
+  return lerp(p1, p0, p1);
+  // expected-error@-1 {{call to 'lerp' is ambiguous}}
+}
+
+float2 test_builtin_lerp_float2_splat(float p0, float2 p1) {
+  return __builtin_hlsl_lerp(p0, p1, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must be vectors}}
+}
+
+float3 test_builtin_lerp_float3_splat(float p0, float3 p1) {
+  return __builtin_hlsl_lerp(p0, p1, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must be vectors}}
+}
+
+float4 test_builtin_lerp_float4_splat(float p0, float4 p1) {
+  return __builtin_hlsl_lerp(p0, p1, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must be vectors}}
+}
+
+float2 test_lerp_float2_int_splat(float2 p0, int p1) {
+  return __builtin_hlsl_lerp(p0, p1, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must be vectors}}
+}
+
+float3 test_lerp_float3_int_splat(float3 p0, int p1) {
+  return __builtin_hlsl_lerp(p0, p1, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must be vectors}}
+}
+
+float2 test_builtin_lerp_int_vect_to_float_vec_promotion(int2 p0, float p1) {
+  return __builtin_hlsl_lerp(p0, p1, p1);
+  // expected-error@-1 {{all arguments to '__builtin_hlsl_lerp' must be vectors}}
+}
+
+float test_builtin_lerp_bool_type_promotion(bool p0) {
+  return __builtin_hlsl_lerp(p0, p0, p0);
+  // expected-error@-1 {{1st argument must be a floating point type (was 'bool')}}
+}
+
+float builtin_bool_to_float_type_promotion(float p0, bool p1) {
+  return __builtin_hlsl_lerp(p0, p0, p1);
+  // expected-error@-1 {{3rd argument must be a floating point type (was 'bool')}}
+}
+
+float builtin_bool_to_float_type_promotion2(bool p0, float p1) {
+  return __builtin_hlsl_lerp(p1, p0, p1);
+  // expected-error@-1 {{2nd argument must be a floating point type (was 'bool')}}
+}
+
+float builtin_lerp_int_to_float_promotion(float p0, int p1) {
+  return __builtin_hlsl_lerp(p0, p0, p1);
+  // expected-error@-1 {{3rd argument must be a floating point type (was 'int')}}
+}
+
+float4 test_lerp_int4(int4 p0, int4 p1, int4 p2) {
+  return __builtin_hlsl_lerp(p0, p1, p2);
+   // expected-error@-1 {{1st argument must be a floating point type (was 'int4' (aka 'vector'))}}
+}
\ No newline at end of file
diff --git a/clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/mad-errors.hlsl
new file mode 100644
index 0000000000000..0b6843591455b
--- /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 0000000000000..dc4501dbd6d15
--- /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/SemaHLSL/BuiltIns/round-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/round-errors.hlsl
new file mode 100644
index 0000000000000..fed4573063acb
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/round-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_elementwise_round();
+  // expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+float2 test_too_many_arg(float2 p0) {
+  return __builtin_elementwise_round(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_elementwise_round(p1);
+  // expected-error@-1 {{1st argument must be a vector, integer or floating point type (was 'bool')}}
+}
+
+float builtin_round_int_to_float_promotion(int p1) {
+  return __builtin_elementwise_round(p1);
+  // expected-error@-1 {{1st argument must be a floating point type (was 'int')}}
+}
+
+float2 builtin_round_int2_to_float2_promotion(int2 p1) {
+  return __builtin_elementwise_round(p1);
+  // expected-error@-1 {{1st argument must be a floating point type (was 'int2' (aka 'vector'))}}
+}
diff --git a/clang/test/SemaHLSL/OverloadResolutionBugs.hlsl b/clang/test/SemaHLSL/OverloadResolutionBugs.hlsl
index 8464f1c1a7c2c..c13cb299127aa 100644
--- a/clang/test/SemaHLSL/OverloadResolutionBugs.hlsl
+++ b/clang/test/SemaHLSL/OverloadResolutionBugs.hlsl
@@ -7,73 +7,67 @@
 void Fn3(double2 D);
 void Fn3(float2 F);
 
-void Call3(half2 H) {
-  Fn3(H);
-}
+void Call3(half2 H) { Fn3(H); }
 
 void Fn5(double2 D);
 
-void Call5(half2 H) {
-  Fn5(H);
-}
+void Call5(half2 H) { Fn5(H); }
 
 void Fn4(int64_t2 L);
 void Fn4(int2 I);
 
-void Call4(int16_t H) {
-  Fn4(H);
-}
+void Call4(int16_t H) { Fn4(H); }
 
-int test_builtin_dot_bool_type_promotion ( bool p0, bool p1 ) {
-  return dot ( p0, p1 );
+int test_builtin_dot_bool_type_promotion(bool p0, bool p1) {
+  return dot(p0, p1);
 }
 
-float test_dot_scalar_mismatch ( float p0, int p1 ) {
-  return dot ( p0, p1 );
-}
+float test_dot_scalar_mismatch(float p0, int p1) { return dot(p0, p1); }
 
-float test_dot_element_type_mismatch ( int2 p0, float2 p1 ) {
-  return dot ( p0, p1 );
-}
+float test_dot_element_type_mismatch(int2 p0, float2 p1) { return dot(p0, p1); }
 
-float test_builtin_dot_vec_int_to_float_promotion ( int2 p0, float2 p1 ) {
-  return dot ( p0, p1 );
+float test_builtin_dot_vec_int_to_float_promotion(int2 p0, float2 p1) {
+  return dot(p0, p1);
 }
 
-int64_t test_builtin_dot_vec_int_to_int64_promotion( int64_t2 p0, int2 p1 ) {
-  return dot ( p0, p1 );
+int64_t test_builtin_dot_vec_int_to_int64_promotion(int64_t2 p0, int2 p1) {
+  return dot(p0, p1);
 }
 
-float test_builtin_dot_vec_half_to_float_promotion( float2 p0, half2 p1 ) {
-  return dot( p0, p1 );
+float test_builtin_dot_vec_half_to_float_promotion(float2 p0, half2 p1) {
+  return dot(p0, p1);
 }
 
-float test_builtin_dot_vec_int16_to_float_promotion( float2 p0, int16_t2 p1 ) {
-  return dot( p0, p1 );
+float test_builtin_dot_vec_int16_to_float_promotion(float2 p0, int16_t2 p1) {
+  return dot(p0, p1);
 }
 
-half test_builtin_dot_vec_int16_to_half_promotion( half2 p0, int16_t2 p1 ) {
-  return dot( p0, p1 );
+half test_builtin_dot_vec_int16_to_half_promotion(half2 p0, int16_t2 p1) {
+  return dot(p0, p1);
 }
 
-int test_builtin_dot_vec_int16_to_int_promotion( int2 p0, int16_t2 p1 ) {
-  return dot( p0, p1 );
+int test_builtin_dot_vec_int16_to_int_promotion(int2 p0, int16_t2 p1) {
+  return dot(p0, p1);
 }
 
-int64_t test_builtin_dot_vec_int16_to_int64_promotion( int64_t2 p0, int16_t2 p1 ) {
-  return dot( p0, p1 );
+int64_t test_builtin_dot_vec_int16_to_int64_promotion(int64_t2 p0,
+                                                      int16_t2 p1) {
+  return dot(p0, p1);
 }
 
+float4 test_frac_int4(int4 p0) { return frac(p0); }
+
+float test_frac_int(int p0) { return frac(p0); }
+
+float test_frac_bool(bool p0) { return frac(p0); }
+
 // https://github.com/llvm/llvm-project/issues/81049
 
 // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \
 // RUN:   dxil-pc-shadermodel6.2-library %s -emit-llvm -disable-llvm-passes \
 // RUN:   -o - | FileCheck %s --check-prefix=NO_HALF
 
-half sqrt_h(half x)
-{
-  return sqrt(x);
-}
+half sqrt_h(half x) { return sqrt(x); }
 
 // NO_HALF: define noundef float @"?sqrt_h@@YA$halff@$halff@@Z"(
 // NO_HALF: call float @llvm.sqrt.f32(float %0)
diff --git a/clang/test/SemaHLSL/VectorOverloadResolution.hlsl b/clang/test/SemaHLSL/VectorOverloadResolution.hlsl
index 81fedc2de3157..2ea7d14e80eeb 100644
--- a/clang/test/SemaHLSL/VectorOverloadResolution.hlsl
+++ b/clang/test/SemaHLSL/VectorOverloadResolution.hlsl
@@ -40,7 +40,7 @@ void Fn3( int64_t2 p0);
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'half2':'half __attribute__((ext_vector_type(2)))' 
 // CHECK-NEXT: DeclRefExpr {{.*}} 'half2':'half __attribute__((ext_vector_type(2)))' lvalue ParmVar {{.*}} 'p0' 'half2':'half __attribute__((ext_vector_type(2)))'
 // CHECKIR-LABEL: Call3
-// CHECKIR: %conv = fptosi <2 x half> {{.*}} to <2 x i64>
+// CHECKIR: {{.*}} = fptosi <2 x half> {{.*}} to <2 x i64>
 void Call3(half2 p0) {
   Fn3(p0);
 }
diff --git a/clang/test/SemaObjC/integer-overflow.m b/clang/test/SemaObjC/integer-overflow.m
index 6d82e2951c1e6..255142729f8d5 100644
--- a/clang/test/SemaObjC/integer-overflow.m
+++ b/clang/test/SemaObjC/integer-overflow.m
@@ -9,10 +9,10 @@ - (int)add:(int)a with:(int)b {
 }
 
 - (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 aa7dc955fb5fe..a6c098947b0b2 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 351fd1c3e0ee5..0d1d0b2665736 100644
--- a/clang/test/SemaOpenACC/compute-construct-ast.cpp
+++ b/clang/test/SemaOpenACC/compute-construct-ast.cpp
@@ -15,6 +15,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 +48,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 +68,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 +87,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 {
diff --git a/clang/test/SemaOpenACC/no-branch-in-out.c b/clang/test/SemaOpenACC/no-branch-in-out.c
index f8fb40a1ca8f7..5fff18eb7cdd7 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
   {
     {
@@ -113,3 +135,271 @@ void Return() {
     }
   }
 }
+
+void Goto() {
+  int j;
+#pragma acc parallel // expected-note{{invalid branch out of OpenACC Compute Construct}}
+  while(j) {
+    if (j <3)
+      goto LABEL; // expected-error{{cannot jump from this goto statement to its label}}
+  }
+
+LABEL:
+  {}
+
+  goto LABEL_IN; // expected-error{{cannot jump from this goto statement to its label}}
+
+#pragma acc parallel // expected-note{{invalid branch into OpenACC Compute Construct}}
+  for(int i = 0; i < 5; ++i) {
+LABEL_IN:
+    {}
+  }
+
+#pragma acc parallel
+  for(int i = 0; i < 5; ++i) {
+LABEL_NOT_CALLED:
+    {}
+  }
+
+#pragma acc parallel
+  {
+    goto ANOTHER_LOOP; // expected-error{{cannot jump from this goto statement to its label}}
+
+  }
+#pragma acc parallel// expected-note{{invalid branch into OpenACC Compute Construct}}
+
+  {
+ANOTHER_LOOP:
+    {}
+  }
+
+#pragma acc parallel
+  {
+  while (j) {
+    --j;
+    if (j < 3)
+      goto LABEL2;
+
+    if (j > 4)
+      break;
+  }
+LABEL2:
+  {}
+  }
+
+#pragma acc parallel
+  do {
+    if (j < 3)
+      goto LABEL3;
+
+    if (j > 4)
+      break; // expected-error{{invalid branch out of OpenACC Compute Construct}}
+
+LABEL3:
+  {}
+  } while (j);
+
+LABEL4:
+  {}
+#pragma acc parallel// expected-note{{invalid branch out of OpenACC Compute Construct}}
+  {
+    goto LABEL4;// expected-error{{cannot jump from this goto statement to its label}}
+  }
+
+#pragma acc parallel// expected-note{{invalid branch into OpenACC Compute Construct}}
+
+  {
+LABEL5:
+    {}
+  }
+
+  {
+    goto LABEL5;// expected-error{{cannot jump from this goto statement to its label}}
+  }
+
+#pragma acc parallel
+  {
+LABEL6:
+    {}
+    goto LABEL6;
+
+  }
+
+#pragma acc parallel
+  goto LABEL7; // expected-error{{cannot jump from this goto statement to its label}}
+#pragma acc parallel// expected-note{{invalid branch into OpenACC Compute Construct}}
+  {
+LABEL7:{}
+  }
+
+#pragma acc parallel
+  LABEL8:{}
+#pragma acc parallel// expected-note{{invalid branch out of OpenACC Compute Construct}}
+  {
+    goto LABEL8;// expected-error{{cannot jump from this goto statement to its label}}
+  }
+
+
+#pragma acc parallel// expected-note{{invalid branch into OpenACC Compute Construct}}
+  {
+LABEL9:{}
+  }
+
+  ({goto LABEL9;});// expected-error{{cannot jump from this goto statement to its label}}
+
+#pragma acc parallel// expected-note{{invalid branch out of OpenACC Compute Construct}}
+  {
+  ({goto LABEL10;});// expected-error{{cannot jump from this goto statement to its label}}
+  }
+
+LABEL10:{}
+
+  ({goto LABEL11;});// expected-error{{cannot jump from this goto statement to its label}}
+#pragma acc parallel// expected-note{{invalid branch into OpenACC Compute Construct}}
+  {
+LABEL11:{}
+  }
+
+LABEL12:{}
+#pragma acc parallel// expected-note{{invalid branch out of OpenACC Compute Construct}}
+  {
+  ({goto LABEL12;});// expected-error{{cannot jump from this goto statement to its label}}
+  }
+
+#pragma acc parallel
+  {
+  ({goto LABEL13;});
+LABEL13:{}
+  }
+
+#pragma acc parallel
+  {
+  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() {
+  void* ptr;
+#pragma acc parallel
+  {
+LABEL1:{}
+    ptr = &&LABEL1;
+
+    goto *ptr;
+
+  }
+}
+
+void IndirectGoto2() {
+  void* ptr;
+LABEL2:{} // #GOTOLBL2
+    ptr = &&LABEL2;
+#pragma acc parallel // #GOTOPAR2
+  {
+// expected-error@+3{{cannot jump from this indirect goto statement to one of its possible targets}}
+// expected-note@#GOTOLBL2{{possible target of indirect goto statement}}
+// expected-note@#GOTOPAR2{{invalid branch out of OpenACC Compute Construct}}
+    goto *ptr;
+  }
+}
+
+void IndirectGoto3() {
+  void* ptr;
+#pragma acc parallel // #GOTOPAR3
+  {
+LABEL3:{} // #GOTOLBL3
+    ptr = &&LABEL3;
+  }
+// expected-error@+3{{cannot jump from this indirect goto statement to one of its possible targets}}
+// expected-note@#GOTOLBL3{{possible target of indirect goto statement}}
+// expected-note@#GOTOPAR3{{invalid branch into OpenACC Compute Construct}}
+  goto *ptr;
+}
+
+void IndirectGoto4() {
+  void* ptr;
+#pragma acc parallel // #GOTOPAR4
+  {
+LABEL4:{}
+    ptr = &&LABEL4;
+// expected-error@+3{{cannot jump from this indirect goto statement to one of its possible targets}}
+// expected-note@#GOTOLBL5{{possible target of indirect goto statement}}
+// expected-note@#GOTOPAR4{{invalid branch out of OpenACC Compute Construct}}
+    goto *ptr;
+  }
+LABEL5:// #GOTOLBL5
+
+  ptr=&&LABEL5;
+}
+
+void DuffsDevice() {
+  int j;
+  switch (j) {
+#pragma acc parallel
+  for(int i =0; i < 5; ++i) {
+    case 0: // expected-error{{invalid branch into OpenACC Compute Construct}}
+      {}
+  }
+  }
+
+  switch (j) {
+#pragma acc parallel
+  for(int i =0; i < 5; ++i) {
+    default: // expected-error{{invalid branch into OpenACC Compute Construct}}
+      {}
+  }
+  }
+
+  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) {
+    case 'a' ... 'z': // expected-error{{invalid branch into OpenACC Compute Construct}}
+      {}
+  }
+  }
+
+  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 232e372cedd35..bc559f1898f1b 100644
--- a/clang/test/SemaOpenACC/no-branch-in-out.cpp
+++ b/clang/test/SemaOpenACC/no-branch-in-out.cpp
@@ -15,3 +15,199 @@ void ReturnTest() {
     }
   }
 }
+
+template
+void BreakContinue() {
+#pragma acc parallel
+  for(int i =0; i < 5; ++i) {
+    switch(i) {
+      case 0:
+      break; // leaves switch, not 'for'.
+      default:
+      i +=2;
+      break;
+    }
+    if (i == 2)
+      continue;
+
+    break;  // expected-error{{invalid branch out of OpenACC Compute Construct}}
+  }
+
+  int j;
+  switch(j) {
+    case 0:
+#pragma acc parallel
+    {
+      break; // expected-error{{invalid branch out of OpenACC Compute Construct}}
+    }
+    case 1:
+#pragma acc parallel
+    {
+    }
+    break;
+  }
+
+#pragma acc parallel
+  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:
+      break;
+  }
+
+#pragma acc parallel
+  {
+    for(int i = 1; i < 100; i++) {
+      if (i > 4)
+        break;
+    }
+  }
+
+  for (int i =0; i < 5; ++i) {
+#pragma acc parallel
+    {
+      continue; // expected-error{{invalid branch out of OpenACC Compute Construct}}
+    }
+  }
+
+#pragma acc parallel
+  for (int i =0; i < 5; ++i) {
+    continue;
+  }
+
+#pragma acc parallel
+  for (int i =0; i < 5; ++i) {
+    {
+      continue;
+    }
+  }
+
+  for (int i =0; i < 5; ++i) {
+#pragma acc parallel
+    {
+      break; // expected-error{{invalid branch out of OpenACC Compute Construct}}
+    }
+  }
+
+#pragma acc parallel
+  while (j) {
+    --j;
+    if (j > 4)
+      break; // expected-error{{invalid branch out of OpenACC Compute Construct}}
+  }
+
+#pragma acc parallel
+  do {
+    --j;
+    if (j > 4)
+      break; // expected-error{{invalid branch out of OpenACC Compute Construct}}
+  } while (j );
+}
+
+template
+void DuffsDevice() {
+  int j;
+  switch (j) {
+#pragma acc parallel
+  for(int i =0; i < 5; ++i) {
+    case 0: // expected-error{{invalid branch into OpenACC Compute Construct}}
+      {}
+  }
+  }
+
+  switch (j) {
+#pragma acc parallel
+  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) {
+    case 'a' ... 'z': // expected-error{{invalid branch into OpenACC Compute Construct}}
+      {}
+  }
+  }
+}
+
+void Exceptions() {
+#pragma acc parallel
+  for(int i = 0; i < 5; ++i) {
+    throw 5; // expected-error{{invalid throw out of OpenACC Compute Construct}}
+  }
+
+#pragma acc parallel
+  for(int i = 0; i < 5; ++i) {
+    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 {
+    throw 5;
+    } catch(float f) {
+    }
+  }
+
+#pragma acc parallel
+  for(int i = 0; i < 5; ++i) {
+    try {
+    throw 5;
+    } catch(int f) {
+    }
+  }
+
+#pragma acc parallel
+  for(int i = 0; i < 5; ++i) {
+    try {
+    throw 5;
+    } catch(...) {
+    }
+  }
+#pragma acc parallel
+  for(int i = 0; i < 5; ++i) {
+    try {
+    throw;
+    } catch(...) {
+    }
+  }
+
+#pragma acc parallel
+  for(int i = 0; i < 5; ++i) {
+    try {
+    throw;
+    } catch(...) {
+      throw; // expected-error{{invalid throw out of OpenACC Compute Construct}}
+    }
+  }
+#pragma acc parallel
+  for(int i = 0; i < 5; ++i) {
+    try {
+    throw;
+    } catch(int f) {
+      throw; // expected-error{{invalid throw out of OpenACC Compute Construct}}
+    }
+  }
+}
+
+void Instantiate() {
+  BreakContinue();
+  DuffsDevice();
+}
diff --git a/clang/test/SemaOpenACC/parallel-assoc-stmt-inst.cpp b/clang/test/SemaOpenACC/parallel-assoc-stmt-inst.cpp
index 0464e164a754e..f533baa4c0e68 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 5189a6aa44f04..ba29f6da8ba25 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/SemaTemplate/unqual-unresolved-using-value.cpp b/clang/test/SemaTemplate/unqual-unresolved-using-value.cpp
new file mode 100644
index 0000000000000..688e7a0a10b77
--- /dev/null
+++ b/clang/test/SemaTemplate/unqual-unresolved-using-value.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+
+template
+struct A : T {
+  using T::f;
+  using T::g;
+  using T::h;
+
+  void f();
+  void g();
+
+  void i() {
+    f();
+    g(); // expected-error{{no member named 'g' in 'A'}}
+    h(); // expected-error{{expected '(' for function-style cast or type construction}}
+              // expected-error@-1{{expected expression}}
+  }
+};
+
+struct B {
+  template
+  void f();
+
+  void g();
+
+  template
+  void h();
+};
+
+template struct A; // expected-note{{in instantiation of member function 'A::i' requested here}}
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 0000000000000..3d6c92341ac43
--- /dev/null
+++ b/clang/test/TableGen/target-builtins-prototype-parser.td
@@ -0,0 +1,115 @@
+// RUN: clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins | FileCheck %s
+// RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_LANES 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_LANES
+// RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_COMMA 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_COMMA
+// RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_TYPE 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_TYPE
+// RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_A 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_A
+// RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_B 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_B
+// RUN: not clang-tblgen -I %p/../../../clang/include/ %s --gen-clang-builtins -DERROR_EXPECTED_C 2>&1 | FileCheck %s --check-prefix=ERROR_EXPECTED_C
+// RUN: not clang-tblgen -I %p/../../../clang/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-installapi/CMakeLists.txt b/clang/tools/clang-installapi/CMakeLists.txt
index b8384c92c104f..e05f4eac3ad19 100644
--- a/clang/tools/clang-installapi/CMakeLists.txt
+++ b/clang/tools/clang-installapi/CMakeLists.txt
@@ -14,6 +14,7 @@ add_clang_tool(clang-installapi
 
 clang_target_link_libraries(clang-installapi
   PRIVATE
+  clangAST
   clangInstallAPI
   clangBasic
   clangDriver
diff --git a/clang/tools/clang-installapi/ClangInstallAPI.cpp b/clang/tools/clang-installapi/ClangInstallAPI.cpp
index fc23ffd7ae6b9..c6da1c80a673f 100644
--- a/clang/tools/clang-installapi/ClangInstallAPI.cpp
+++ b/clang/tools/clang-installapi/ClangInstallAPI.cpp
@@ -12,12 +12,14 @@
 //===----------------------------------------------------------------------===//
 
 #include "Options.h"
-#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticFrontend.h"
 #include "clang/Driver/Driver.h"
 #include "clang/Driver/DriverDiagnostic.h"
-#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Driver/Tool.h"
 #include "clang/Frontend/TextDiagnosticPrinter.h"
-#include "clang/InstallAPI/Context.h"
+#include "clang/InstallAPI/Frontend.h"
+#include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/CommandLine.h"
@@ -27,7 +29,9 @@
 #include "llvm/Support/Process.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/TargetParser/Host.h"
+#include "llvm/TextAPI/RecordVisitor.h"
 #include "llvm/TextAPI/TextAPIWriter.h"
+#include 
 
 using namespace clang;
 using namespace clang::installapi;
@@ -35,6 +39,36 @@ using namespace clang::driver::options;
 using namespace llvm::opt;
 using namespace llvm::MachO;
 
+static bool runFrontend(StringRef ProgName, bool Verbose,
+                        InstallAPIContext &Ctx,
+                        llvm::vfs::InMemoryFileSystem *FS,
+                        const ArrayRef InitialArgs) {
+
+  std::unique_ptr ProcessedInput = createInputBuffer(Ctx);
+  // Skip invoking cc1 when there are no header inputs.
+  if (!ProcessedInput)
+    return true;
+
+  if (Verbose)
+    llvm::errs() << getName(Ctx.Type) << " Headers:\n"
+                 << ProcessedInput->getBuffer() << "\n\n";
+
+  std::string InputFile = ProcessedInput->getBufferIdentifier().str();
+  FS->addFile(InputFile, /*ModTime=*/0, std::move(ProcessedInput));
+  // Reconstruct arguments with unique values like target triple or input
+  // headers.
+  std::vector Args = {ProgName.data(), "-target",
+                                   Ctx.Slice->getTriple().str().c_str()};
+  llvm::copy(InitialArgs, std::back_inserter(Args));
+  Args.push_back(InputFile);
+
+  // Create & run invocation.
+  clang::tooling::ToolInvocation Invocation(
+      std::move(Args), std::make_unique(Ctx), Ctx.FM);
+
+  return Invocation.run();
+}
+
 static bool run(ArrayRef Args, const char *ProgName) {
   // Setup Diagnostics engine.
   IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions();
@@ -48,15 +82,20 @@ static bool run(ArrayRef Args, const char *ProgName) {
       new clang::DiagnosticIDs(), DiagOpts.get(),
       new clang::TextDiagnosticPrinter(llvm::errs(), DiagOpts.get()));
 
-  // Create file manager for all file operations.
+  // Create file manager for all file operations and holding in-memory generated
+  // inputs.
+  llvm::IntrusiveRefCntPtr OverlayFileSystem(
+      new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem()));
+  llvm::IntrusiveRefCntPtr InMemoryFileSystem(
+      new llvm::vfs::InMemoryFileSystem);
+  OverlayFileSystem->pushOverlay(InMemoryFileSystem);
   IntrusiveRefCntPtr FM(
-      new FileManager(clang::FileSystemOptions()));
+      new FileManager(clang::FileSystemOptions(), OverlayFileSystem));
 
   // Set up driver to parse input arguments.
   auto DriverArgs = llvm::ArrayRef(Args).slice(1);
   clang::driver::Driver Driver(ProgName, llvm::sys::getDefaultTargetTriple(),
                                *Diag, "clang installapi tool");
-  Driver.setInstalledDir(llvm::sys::path::parent_path(ProgName));
   auto TargetAndMode =
       clang::driver::ToolChain::getTargetAndModeFromProgramName(ProgName);
   Driver.setTargetAndMode(TargetAndMode);
@@ -71,7 +110,10 @@ static bool run(ArrayRef Args, const char *ProgName) {
   Options Opts(*Diag, FM.get(), ArgList);
   if (Diag->hasErrorOccurred())
     return EXIT_FAILURE;
+
   InstallAPIContext Ctx = Opts.createContext();
+  if (Diag->hasErrorOccurred())
+    return EXIT_FAILURE;
 
   // Set up compilation.
   std::unique_ptr CI(new CompilerInstance());
@@ -80,6 +122,23 @@ static bool run(ArrayRef Args, const char *ProgName) {
   if (!CI->hasDiagnostics())
     return EXIT_FAILURE;
 
+  // Execute and gather AST results.
+  // An invocation is ran for each unique target triple and for each header
+  // access level.
+  llvm::MachO::Records FrontendResults;
+  for (const auto &[Targ, Trip] : Opts.DriverOpts.Targets) {
+    for (const HeaderType Type :
+         {HeaderType::Public, HeaderType::Private, HeaderType::Project}) {
+      Ctx.Slice = std::make_shared(Trip);
+      Ctx.Type = Type;
+      if (!runFrontend(ProgName, Opts.DriverOpts.Verbose, Ctx,
+                       InMemoryFileSystem.get(), Opts.getClangFrontendArgs()))
+        return EXIT_FAILURE;
+      FrontendResults.emplace_back(std::move(Ctx.Slice));
+    }
+  }
+
+  // After symbols have been collected, prepare to write output.
   auto Out = CI->createOutputFile(Ctx.OutputLoc, /*Binary=*/false,
                                   /*RemoveFileOnSignal=*/false,
                                   /*UseTemporary=*/false,
@@ -88,7 +147,13 @@ static bool run(ArrayRef Args, const char *ProgName) {
     return EXIT_FAILURE;
 
   // Assign attributes for serialization.
-  InterfaceFile IF;
+  auto Symbols = std::make_unique();
+  for (const auto &FR : FrontendResults) {
+    SymbolConverter Converter(Symbols.get(), FR->getTarget());
+    FR->visit(Converter);
+  }
+
+  InterfaceFile IF(std::move(Symbols));
   for (const auto &TargetInfo : Opts.DriverOpts.Targets) {
     IF.addTarget(TargetInfo.first);
     IF.setFromBinaryAttrs(Ctx.BA, TargetInfo.first);
diff --git a/clang/tools/clang-installapi/Options.cpp b/clang/tools/clang-installapi/Options.cpp
index 562a643edfcf4..7d45e999448d9 100644
--- a/clang/tools/clang-installapi/Options.cpp
+++ b/clang/tools/clang-installapi/Options.cpp
@@ -9,6 +9,7 @@
 #include "Options.h"
 #include "clang/Driver/Driver.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/InstallAPI/FileList.h"
 #include "llvm/Support/Program.h"
 #include "llvm/TargetParser/Host.h"
 
@@ -68,6 +69,8 @@ bool Options::processDriverOptions(InputArgList &Args) {
     }
   }
 
+  DriverOpts.Verbose = Args.hasArgNoClaim(OPT_v);
+
   return true;
 }
 
@@ -104,10 +107,21 @@ Options::Options(DiagnosticsEngine &Diag, FileManager *FM,
 
   if (!processLinkerOptions(ArgList))
     return;
+
+  /// Any remaining 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.push_back("-fsyntax-only");
 }
 
 InstallAPIContext Options::createContext() {
   InstallAPIContext Ctx;
+  Ctx.FM = FM;
+  Ctx.Diags = Diags;
+
   // InstallAPI requires two level namespacing.
   Ctx.BA.TwoLevelNamespace = true;
 
@@ -116,6 +130,21 @@ InstallAPIContext Options::createContext() {
   Ctx.BA.AppExtensionSafe = LinkerOpts.AppExtensionSafe;
   Ctx.FT = DriverOpts.OutFT;
   Ctx.OutputLoc = DriverOpts.OutputPath;
+
+  // Process inputs.
+  for (const std::string &ListPath : DriverOpts.FileLists) {
+    auto Buffer = FM->getBufferForFile(ListPath);
+    if (auto Err = Buffer.getError()) {
+      Diags->Report(diag::err_cannot_open_file) << ListPath;
+      return Ctx;
+    }
+    if (auto Err = FileListReader::loadHeaders(std::move(Buffer.get()),
+                                               Ctx.InputHeaders)) {
+      Diags->Report(diag::err_cannot_open_file) << ListPath;
+      return Ctx;
+    }
+  }
+
   return Ctx;
 }
 
diff --git a/clang/tools/clang-installapi/Options.h b/clang/tools/clang-installapi/Options.h
index 4a84166a6c91b..f68addf197288 100644
--- a/clang/tools/clang-installapi/Options.h
+++ b/clang/tools/clang-installapi/Options.h
@@ -43,6 +43,9 @@ struct DriverOptions {
 
   /// \brief File encoding to print.
   llvm::MachO::FileType OutFT = llvm::MachO::FileType::TBD_V5;
+
+  /// \brief Print verbose output.
+  bool Verbose = false;
 };
 
 struct LinkerOptions {
@@ -78,9 +81,14 @@ class Options {
   Options(clang::DiagnosticsEngine &Diag, FileManager *FM,
           llvm::opt::InputArgList &Args);
 
+  /// \brief Get CC1 arguments after extracting out the irrelevant
+  /// ones.
+  std::vector &getClangFrontendArgs() { return FrontendArgs; }
+
 private:
   DiagnosticsEngine *Diags;
   FileManager *FM;
+  std::vector FrontendArgs;
 };
 
 } // namespace installapi
diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
index 9811d2a875335..d042fecc3dbe6 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/driver/driver.cpp b/clang/tools/driver/driver.cpp
index 0dfb512adb0cc..376025e3605be 100644
--- a/clang/tools/driver/driver.cpp
+++ b/clang/tools/driver/driver.cpp
@@ -323,28 +323,6 @@ static void FixupDiagPrefixExeName(TextDiagnosticPrinter *DiagClient,
   DiagClient->setPrefix(std::string(ExeBasename));
 }
 
-static void SetInstallDir(SmallVectorImpl &argv,
-                          Driver &TheDriver, bool CanonicalPrefixes) {
-  // Attempt to find the original path used to invoke the driver, to determine
-  // the installed path. We do this manually, because we want to support that
-  // path being a symlink.
-  SmallString<128> InstalledPath(argv[0]);
-
-  // Do a PATH lookup, if there are no directory components.
-  if (llvm::sys::path::filename(InstalledPath) == InstalledPath)
-    if (llvm::ErrorOr Tmp = llvm::sys::findProgramByName(
-            llvm::sys::path::filename(InstalledPath.str())))
-      InstalledPath = *Tmp;
-
-  // FIXME: We don't actually canonicalize this, we just make it absolute.
-  if (CanonicalPrefixes)
-    llvm::sys::fs::make_absolute(InstalledPath);
-
-  StringRef InstalledPathParent(llvm::sys::path::parent_path(InstalledPath));
-  if (llvm::sys::fs::exists(InstalledPathParent))
-    TheDriver.setInstalledDir(InstalledPathParent);
-}
-
 static int ExecuteCC1Tool(SmallVectorImpl &ArgV,
                           const llvm::ToolContext &ToolContext) {
   // If we call the cc1 tool from the clangDriver library (through
@@ -484,7 +462,6 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) {
   ProcessWarningOptions(Diags, *DiagOpts, /*ReportDiags=*/false);
 
   Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags);
-  SetInstallDir(Args, TheDriver, CanonicalPrefixes);
   auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(ProgName);
   TheDriver.setTargetAndMode(TargetAndMode);
   // If -canonical-prefixes is set, GetExecutablePath will have resolved Path
diff --git a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
index 0d36d2802897f..b7cf6cc966edb 100644
--- a/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
+++ b/clang/unittests/Analysis/FlowSensitive/TestingSupport.h
@@ -432,6 +432,8 @@ llvm::Error checkDataflowWithNoopAnalysis(
         {});
 
 /// Returns the `ValueDecl` for the given identifier.
+/// The returned pointer is guaranteed to be non-null; the function asserts if
+/// no `ValueDecl` with the given name is found.
 ///
 /// Requirements:
 ///
@@ -475,6 +477,15 @@ ValueT &getValueForDecl(ASTContext &ASTCtx, const Environment &Env,
   return *cast(Env.getValue(*VD));
 }
 
+/// Returns the storage location for the field called `Name` of `Loc`.
+/// Optionally casts the field storage location to `T`.
+template 
+std::enable_if_t, T &>
+getFieldLoc(const RecordStorageLocation &Loc, llvm::StringRef Name,
+            ASTContext &ASTCtx) {
+  return *cast(Loc.getChild(*findValueDecl(ASTCtx, Name)));
+}
+
 /// Returns the value of a `Field` on the record referenced by `Loc.`
 /// Returns null if `Loc` is null.
 inline Value *getFieldValue(const RecordStorageLocation *Loc,
@@ -487,6 +498,14 @@ inline Value *getFieldValue(const RecordStorageLocation *Loc,
   return Env.getValue(*FieldLoc);
 }
 
+/// Returns the value of a `Field` on the record referenced by `Loc.`
+/// Returns null if `Loc` is null.
+inline Value *getFieldValue(const RecordStorageLocation *Loc,
+                            llvm::StringRef Name, ASTContext &ASTCtx,
+                            const Environment &Env) {
+  return getFieldValue(Loc, *findValueDecl(ASTCtx, Name), Env);
+}
+
 /// Creates and owns constraints which are boolean values.
 class ConstraintContext {
   unsigned NextAtom = 0;
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index 2be899f5b6da9..f534ccb125470 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -2392,14 +2392,92 @@ TEST(TransferTest, InitListExprAsUnion) {
       } F;
 
      public:
-      constexpr target() : F{nullptr} {}
+      constexpr target() : F{nullptr} {
+        int *null = nullptr;
+        F.b;  // Make sure we reference 'b' so it is modeled.
+        // [[p]]
+      }
     };
   )cc";
   runDataflow(
       Code,
       [](const llvm::StringMap> &Results,
          ASTContext &ASTCtx) {
-        // Just verify that it doesn't crash.
+        const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
+
+        auto &FLoc = getFieldLoc(
+            *Env.getThisPointeeStorageLocation(), "F", ASTCtx);
+        auto *AVal = cast(getFieldValue(&FLoc, "a", ASTCtx, Env));
+        EXPECT_EQ(AVal, &getValueForDecl(ASTCtx, Env, "null"));
+        EXPECT_EQ(getFieldValue(&FLoc, "b", ASTCtx, Env), nullptr);
+      });
+}
+
+TEST(TransferTest, EmptyInitListExprForUnion) {
+  // This is a crash repro.
+  std::string Code = R"cc(
+    class target {
+      union {
+        int *a;
+        bool *b;
+      } F;
+
+     public:
+      // Empty initializer list means that `F` is aggregate-initialized.
+      // For a union, this has the effect that the first member of the union
+      // is copy-initialized from an empty initializer list; in this specific
+      // case, this has the effect of initializing `a` with null.
+      constexpr target() : F{} {
+        int *null = nullptr;
+        F.b;  // Make sure we reference 'b' so it is modeled.
+        // [[p]]
+      }
+    };
+  )cc";
+  runDataflow(
+      Code,
+      [](const llvm::StringMap> &Results,
+         ASTContext &ASTCtx) {
+        const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
+
+        auto &FLoc = getFieldLoc(
+            *Env.getThisPointeeStorageLocation(), "F", ASTCtx);
+        auto *AVal = cast(getFieldValue(&FLoc, "a", ASTCtx, Env));
+        EXPECT_EQ(AVal, &getValueForDecl(ASTCtx, Env, "null"));
+        EXPECT_EQ(getFieldValue(&FLoc, "b", ASTCtx, Env), nullptr);
+      });
+}
+
+TEST(TransferTest, EmptyInitListExprForStruct) {
+  std::string Code = R"cc(
+    class target {
+      struct {
+        int *a;
+        bool *b;
+      } F;
+
+     public:
+      constexpr target() : F{} {
+        int *NullIntPtr = nullptr;
+        bool *NullBoolPtr = nullptr;
+        // [[p]]
+      }
+    };
+  )cc";
+  runDataflow(
+      Code,
+      [](const llvm::StringMap> &Results,
+         ASTContext &ASTCtx) {
+        const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
+
+        auto &FLoc = getFieldLoc(
+            *Env.getThisPointeeStorageLocation(), "F", ASTCtx);
+        auto *AVal = cast(getFieldValue(&FLoc, "a", ASTCtx, Env));
+        EXPECT_EQ(AVal,
+                  &getValueForDecl(ASTCtx, Env, "NullIntPtr"));
+        auto *BVal = cast(getFieldValue(&FLoc, "b", ASTCtx, Env));
+        EXPECT_EQ(BVal,
+                  &getValueForDecl(ASTCtx, Env, "NullBoolPtr"));
       });
 }
 
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index d9752c73e34e7..fc367a7a5a898 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -11159,10 +11159,8 @@ TEST_F(FormatTest, UnderstandsOverloadedOperators) {
   verifyFormat("void f() { a.operator*(b & b); }");
   verifyFormat("void f() { a->operator&(a * b); }");
   verifyFormat("void f() { NS::a.operator+(*b * *b); }");
-  // TODO: Calling an operator as a non-member function is hard to distinguish.
-  // https://llvm.org/PR50629
-  // verifyFormat("void f() { operator*(a & a); }");
-  // verifyFormat("void f() { operator&(a, b * b); }");
+  verifyFormat("void f() { operator*(a & a); }");
+  verifyFormat("void f() { operator&(a, b * b); }");
 
   verifyFormat("void f() { return operator()(x) * b; }");
   verifyFormat("void f() { return operator[](x) * b; }");
@@ -16551,9 +16549,8 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
   verifyFormat("static_assert (sizeof (char) == 1, \"Impossible!\");", Space);
   verifyFormat("int f () throw (Deprecated);", Space);
   verifyFormat("typedef void (*cb) (int);", Space);
-  // FIXME these tests regressed behaviour.
-  // verifyFormat("T A::operator() ();", Space);
-  // verifyFormat("X A::operator++ (T);", Space);
+  verifyFormat("T A::operator() ();", Space);
+  verifyFormat("X A::operator++ (T);", Space);
   verifyFormat("auto lambda = [] () { return 0; };", Space);
   verifyFormat("int x = int (y);", Space);
   verifyFormat("#define F(...) __VA_OPT__ (__VA_ARGS__)", Space);
@@ -16612,8 +16609,7 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
   verifyFormat("int f() throw (Deprecated);", SomeSpace);
   verifyFormat("typedef void (*cb) (int);", SomeSpace);
   verifyFormat("T A::operator()();", SomeSpace);
-  // FIXME these tests regressed behaviour.
-  // verifyFormat("X A::operator++ (T);", SomeSpace);
+  verifyFormat("X A::operator++ (T);", SomeSpace);
   verifyFormat("int x = int (y);", SomeSpace);
   verifyFormat("auto lambda = []() { return 0; };", SomeSpace);
 
@@ -16671,9 +16667,8 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
                SpaceFuncDecl);
   verifyFormat("int f () throw(Deprecated);", SpaceFuncDecl);
   verifyFormat("typedef void (*cb)(int);", SpaceFuncDecl);
-  // FIXME these tests regressed behaviour.
-  // verifyFormat("T A::operator() ();", SpaceFuncDecl);
-  // verifyFormat("X A::operator++ (T);", SpaceFuncDecl);
+  verifyFormat("T A::operator()();", SpaceFuncDecl);
+  verifyFormat("X A::operator++(T);", SpaceFuncDecl);
   verifyFormat("T A::operator()() {}", SpaceFuncDecl);
   verifyFormat("auto lambda = []() { return 0; };", SpaceFuncDecl);
   verifyFormat("int x = int(y);", SpaceFuncDecl);
@@ -16710,7 +16705,7 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
   verifyFormat("typedef void (*cb)(int);", SpaceFuncDef);
   verifyFormat("T A::operator()();", SpaceFuncDef);
   verifyFormat("X A::operator++(T);", SpaceFuncDef);
-  // verifyFormat("T A::operator() () {}", SpaceFuncDef);
+  verifyFormat("T A::operator()() {}", SpaceFuncDef);
   verifyFormat("auto lambda = [] () { return 0; };", SpaceFuncDef);
   verifyFormat("int x = int(y);", SpaceFuncDef);
   verifyFormat("M(std::size_t R, std::size_t C) : C(C), data(R) {}",
@@ -16797,7 +16792,7 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
   verifyFormat("int f() throw (Deprecated);", SomeSpace2);
   verifyFormat("typedef void (*cb) (int);", SomeSpace2);
   verifyFormat("T A::operator()();", SomeSpace2);
-  // verifyFormat("X A::operator++ (T);", SomeSpace2);
+  verifyFormat("X A::operator++ (T);", SomeSpace2);
   verifyFormat("int x = int (y);", SomeSpace2);
   verifyFormat("auto lambda = []() { return 0; };", SomeSpace2);
 
diff --git a/clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp b/clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp
index e8b237b891ca8..3aac1f81f523d 100644
--- a/clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp
+++ b/clang/unittests/StaticAnalyzer/CallDescriptionTest.cpp
@@ -488,11 +488,10 @@ TEST(CallDescription, NegativeMatchQualifiedNames) {
 }
 
 TEST(CallDescription, MatchBuiltins) {
-  // Test CDF_MaybeBuiltin - a flag that allows matching weird builtins.
+  // Test CDM::CLibrary - a flag that allows matching weird builtins.
   EXPECT_TRUE(tooling::runToolOnCode(
       std::unique_ptr(new CallDescriptionAction<>(
-          {{{{"memset"}, 3}, false},
-           {{CDF_MaybeBuiltin, {"memset"}, 3}, true}})),
+          {{{{"memset"}, 3}, false}, {{CDM::CLibrary, {"memset"}, 3}, true}})),
       "void foo() {"
       "  int x;"
       "  __builtin___memset_chk(&x, 0, sizeof(x),"
@@ -503,8 +502,8 @@ TEST(CallDescription, MatchBuiltins) {
     SCOPED_TRACE("multiple similar builtins");
     EXPECT_TRUE(tooling::runToolOnCode(
         std::unique_ptr(new CallDescriptionAction<>(
-            {{{CDF_MaybeBuiltin, {"memcpy"}, 3}, false},
-             {{CDF_MaybeBuiltin, {"wmemcpy"}, 3}, true}})),
+            {{{CDM::CLibrary, {"memcpy"}, 3}, false},
+             {{CDM::CLibrary, {"wmemcpy"}, 3}, true}})),
         R"(void foo(wchar_t *x, wchar_t *y) {
             __builtin_wmemcpy(x, y, sizeof(wchar_t));
           })"));
@@ -513,8 +512,8 @@ TEST(CallDescription, MatchBuiltins) {
     SCOPED_TRACE("multiple similar builtins reversed order");
     EXPECT_TRUE(tooling::runToolOnCode(
         std::unique_ptr(new CallDescriptionAction<>(
-            {{{CDF_MaybeBuiltin, {"wmemcpy"}, 3}, true},
-             {{CDF_MaybeBuiltin, {"memcpy"}, 3}, false}})),
+            {{{CDM::CLibrary, {"wmemcpy"}, 3}, true},
+             {{CDM::CLibrary, {"memcpy"}, 3}, false}})),
         R"(void foo(wchar_t *x, wchar_t *y) {
             __builtin_wmemcpy(x, y, sizeof(wchar_t));
           })"));
@@ -522,8 +521,8 @@ TEST(CallDescription, MatchBuiltins) {
   {
     SCOPED_TRACE("lookbehind and lookahead mismatches");
     EXPECT_TRUE(tooling::runToolOnCode(
-        std::unique_ptr(new CallDescriptionAction<>(
-            {{{CDF_MaybeBuiltin, {"func"}}, false}})),
+        std::unique_ptr(
+            new CallDescriptionAction<>({{{CDM::CLibrary, {"func"}}, false}})),
         R"(
           void funcXXX();
           void XXXfunc();
@@ -537,8 +536,8 @@ TEST(CallDescription, MatchBuiltins) {
   {
     SCOPED_TRACE("lookbehind and lookahead matches");
     EXPECT_TRUE(tooling::runToolOnCode(
-        std::unique_ptr(new CallDescriptionAction<>(
-            {{{CDF_MaybeBuiltin, {"func"}}, true}})),
+        std::unique_ptr(
+            new CallDescriptionAction<>({{{CDM::CLibrary, {"func"}}, true}})),
         R"(
           void func();
           void func_XXX();
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index a31904dac642d..6322c72f62ef3 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -3588,10 +3588,6 @@ static void GenerateHasAttrSpellingStringSwitch(
       const Record *R = Attr->getValueAsDef("Target");
       std::vector Arches = R->getValueAsListOfStrings("Arches");
       GenerateTargetSpecificAttrChecks(R, Arches, Test, nullptr);
-
-      // If this is the C++11 variety, also add in the LangOpts test.
-      if (Variety == "CXX11")
-        Test += " && LangOpts.CPlusPlus11";
     } else if (!Attr->getValueAsListOfDefs("TargetSpecificSpellings").empty()) {
       // Add target checks if this spelling is target-specific.
       const std::vector TargetSpellings =
@@ -3609,13 +3605,7 @@ static void GenerateHasAttrSpellingStringSwitch(
           }
         }
       }
-
-      if (Variety == "CXX11")
-        Test += " && LangOpts.CPlusPlus11";
-    } else if (Variety == "CXX11")
-      // C++11 mode should be checked against LangOpts, which is presumed to be
-      // present in the caller.
-      Test = "LangOpts.CPlusPlus11";
+    }
 
     std::string TestStr = !Test.empty()
                               ? Test + " ? " + llvm::itostr(Version) + " : 0"
diff --git a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
index 48f55b8af97e4..94f12a08164fd 100644
--- a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
+++ b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
@@ -47,9 +47,47 @@ class PrototypeParser {
     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 @@ class PrototypeParser {
       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/www/c_status.html b/clang/www/c_status.html
index 3955a1d796397..7bf5e29f0639c 100644
--- a/clang/www/c_status.html
+++ b/clang/www/c_status.html
@@ -1201,7 +1201,7 @@ 

C23 implementation status

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 8b638e06f4aab..b13401625a6fb 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -2668,13 +2668,13 @@

C++ defect report implementation status

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 @@

C++ defect report implementation status

441 CD1 Ordering of static reference initialization - Unknown + Clang 2.7 442 @@ -2812,7 +2812,7 @@

C++ defect report implementation status

462 CD3 Lifetime of temporaries bound to comma expressions - Unknown + Clang 2.7 463 @@ -2992,7 +2992,7 @@

C++ defect report implementation status

492 CD1 typeid constness inconsistent with example - Unknown + Clang 2.7 493 diff --git a/compiler-rt/cmake/Modules/CompilerRTCompile.cmake b/compiler-rt/cmake/Modules/CompilerRTCompile.cmake index 64e7acb9afd83..2bf115973a49b 100644 --- a/compiler-rt/cmake/Modules/CompilerRTCompile.cmake +++ b/compiler-rt/cmake/Modules/CompilerRTCompile.cmake @@ -70,9 +70,14 @@ function(clang_compile object_file source) if (TARGET CompilerRTUnitTestCheckCxx) list(APPEND SOURCE_DEPS CompilerRTUnitTestCheckCxx) endif() + string(REGEX MATCH "[.](cc|cpp)$" is_cxx ${source_rpath}) + if (is_cxx) + set(compiler ${COMPILER_RT_TEST_COMPILER}) + else() + set(compiler ${COMPILER_RT_TEST_CXX_COMPILER}) + endif() if(COMPILER_RT_STANDALONE_BUILD) # Only add global flags in standalone build. - string(REGEX MATCH "[.](cc|cpp)$" is_cxx ${source_rpath}) if(is_cxx) string(REPLACE " " ";" global_flags "${CMAKE_CXX_FLAGS}") else() @@ -102,7 +107,7 @@ function(clang_compile object_file source) add_custom_command( OUTPUT ${object_file} - COMMAND ${COMPILER_RT_TEST_COMPILER} ${compile_flags} -c + COMMAND ${compiler} ${compile_flags} -c -o "${object_file}" ${source_rpath} MAIN_DEPENDENCY ${source} diff --git a/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake b/compiler-rt/cmake/Modules/CompilerRTDarwinUtils.cmake index 6a62d3bf7adce..1882893ad42c0 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/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt index 83f7697a4a2b4..3f2c0f0436393 100644 --- a/compiler-rt/lib/builtins/CMakeLists.txt +++ b/compiler-rt/lib/builtins/CMakeLists.txt @@ -190,6 +190,7 @@ set(GENERIC_SOURCES # We only build BF16 files when "__bf16" is available. set(BF16_SOURCES + extendbfsf2.c truncdfbf2.c truncsfbf2.c ) diff --git a/libc/src/math/nvptx/lround.cpp b/compiler-rt/lib/builtins/extendbfsf2.c similarity index 50% rename from libc/src/math/nvptx/lround.cpp rename to compiler-rt/lib/builtins/extendbfsf2.c index 51e8f2245af8e..e159d7997f655 100644 --- a/libc/src/math/nvptx/lround.cpp +++ b/compiler-rt/lib/builtins/extendbfsf2.c @@ -1,4 +1,4 @@ -//===-- Implementation of the GPU lround function -------------------------===// +//===-- lib/extendbfsf2.c - bfloat -> single 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. @@ -6,11 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "src/math/lround.h" -#include "src/__support/common.h" +#define SRC_BFLOAT16 +#define DST_SINGLE +#include "fp_extend_impl.inc" -namespace LIBC_NAMESPACE { - -LLVM_LIBC_FUNCTION(long, lround, (double x)) { return __builtin_lround(x); } - -} // namespace LIBC_NAMESPACE +COMPILER_RT_ABI float __extendbfsf2(src_t a) { return __extendXfYf2__(a); } diff --git a/compiler-rt/lib/builtins/fp_extend.h b/compiler-rt/lib/builtins/fp_extend.h index 95ea2a7ac4b2c..7637417649e62 100644 --- a/compiler-rt/lib/builtins/fp_extend.h +++ b/compiler-rt/lib/builtins/fp_extend.h @@ -81,6 +81,21 @@ static inline int src_rep_t_clz_impl(src_rep_t a) { #define src_rep_t_clz src_rep_t_clz_impl +#elif defined SRC_BFLOAT16 +#ifdef COMPILER_RT_HAS_BFLOAT16 +typedef __bf16 src_t; +#else +typedef uint16_t src_t; +#endif +typedef uint16_t src_rep_t; +#define SRC_REP_C UINT16_C +static const int srcBits = sizeof(src_t) * CHAR_BIT; +static const int srcSigFracBits = 7; +// -1 accounts for the sign bit. +// srcBits - srcSigFracBits - 1 +static const int srcExpBits = 8; +#define src_rep_t_clz __builtin_clz + #else #error Source should be half, single, or double precision! #endif // end source precision diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp index 38f968d533b14..4940062eeae47 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.cpp @@ -475,6 +475,8 @@ CHECK_TYPE_SIZE(nfds_t); CHECK_TYPE_SIZE(sigset_t); COMPILER_CHECK(sizeof(__sanitizer_sigaction) == sizeof(struct sigaction)); +COMPILER_CHECK(sizeof(__sanitizer_siginfo) == sizeof(siginfo_t)); +CHECK_SIZE_AND_OFFSET(siginfo_t, si_value); // Can't write checks for sa_handler and sa_sigaction due to them being // preprocessor macros. CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_mask); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h index 43b8a38f39be1..8ce73f206fd88 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_freebsd.h @@ -301,11 +301,29 @@ struct __sanitizer_sigset_t { typedef __sanitizer_sigset_t __sanitizer_kernel_sigset_t; +union __sanitizer_sigval { + int sival_int; + void *sival_ptr; +}; + struct __sanitizer_siginfo { - // The size is determined by looking at sizeof of real siginfo_t on linux. - u64 opaque[128 / sizeof(u64)]; + int si_signo; + int si_errno; + int si_code; + pid_t si_pid; + u32 si_uid; + int si_status; + void *si_addr; + union __sanitizer_sigval si_value; +# if SANITIZER_WORDSIZE == 64 + char data[40]; +# else + char data[32]; +# endif }; +typedef __sanitizer_siginfo __sanitizer_siginfo_t; + using __sanitizer_sighandler_ptr = void (*)(int sig); using __sanitizer_sigactionhandler_ptr = void (*)(int sig, __sanitizer_siginfo *siginfo, diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp index e88e654eec5a1..ef1fc35497439 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cpp @@ -91,12 +91,12 @@ static rlim_t getlim(int res) { static void setlim(int res, rlim_t lim) { struct rlimit rlim; - if (getrlimit(res, const_cast(&rlim))) { + if (getrlimit(res, &rlim)) { Report("ERROR: %s getrlimit() failed %d\n", SanitizerToolName, errno); Die(); } rlim.rlim_cur = lim; - if (setrlimit(res, const_cast(&rlim))) { + if (setrlimit(res, &rlim)) { Report("ERROR: %s setrlimit() failed %d\n", SanitizerToolName, errno); Die(); } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_bsd.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_bsd.cpp index dcfd94fe3225c..7c2d8e6f17313 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_bsd.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_procmaps_bsd.cpp @@ -30,17 +30,17 @@ namespace __sanitizer { #if SANITIZER_FREEBSD void GetMemoryProfile(fill_profile_f cb, uptr *stats) { - const int Mib[] = { - CTL_KERN, - KERN_PROC, - KERN_PROC_PID, - getpid() - }; - - struct kinfo_proc InfoProc; - uptr Len = sizeof(InfoProc); - CHECK_EQ(internal_sysctl(Mib, ARRAY_SIZE(Mib), nullptr, (uptr *)&InfoProc, &Len, 0), 0); - cb(0, InfoProc.ki_rssize * GetPageSizeCached(), false, stats); + const int Mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()}; + + struct kinfo_proc *InfoProc; + uptr Len = sizeof(*InfoProc); + uptr Size = Len; + InfoProc = (struct kinfo_proc *)MmapOrDie(Size, "GetMemoryProfile()"); + CHECK_EQ( + internal_sysctl(Mib, ARRAY_SIZE(Mib), nullptr, (uptr *)InfoProc, &Len, 0), + 0); + cb(0, InfoProc->ki_rssize * GetPageSizeCached(), false, stats); + UnmapOrDie(InfoProc, Size, true); } #endif diff --git a/compiler-rt/lib/scudo/standalone/allocator_common.h b/compiler-rt/lib/scudo/standalone/allocator_common.h index 95f4776ac596d..2b77516ad11ca 100644 --- a/compiler-rt/lib/scudo/standalone/allocator_common.h +++ b/compiler-rt/lib/scudo/standalone/allocator_common.h @@ -40,6 +40,7 @@ template struct TransferBatch { B->Count = static_cast(B->Count - N); } void clear() { Count = 0; } + bool empty() { return Count == 0; } void add(CompactPtrT P) { DCHECK_LT(Count, MaxNumCached); Batch[Count++] = P; @@ -48,6 +49,12 @@ template struct TransferBatch { memcpy(Array, Batch, sizeof(Batch[0]) * Count); clear(); } + + void moveNToArray(CompactPtrT *Array, u16 N) { + DCHECK_LE(N, Count); + memcpy(Array, Batch + Count - N, sizeof(Batch[0]) * N); + Count = static_cast(Count - N); + } u16 getCount() const { return Count; } bool isEmpty() const { return Count == 0U; } CompactPtrT get(u16 I) const { diff --git a/compiler-rt/lib/scudo/standalone/checksum.cpp b/compiler-rt/lib/scudo/standalone/checksum.cpp index 2c277391a2ec1..efa4055bcbc1e 100644 --- a/compiler-rt/lib/scudo/standalone/checksum.cpp +++ b/compiler-rt/lib/scudo/standalone/checksum.cpp @@ -19,6 +19,8 @@ #else #include #endif +#elif defined(__loongarch__) +#include #endif namespace scudo { @@ -75,6 +77,20 @@ bool hasHardwareCRC32() { return !!(getauxval(AT_HWCAP) & HWCAP_CRC32); #endif // SCUDO_FUCHSIA } +#elif defined(__loongarch__) +// The definition is only pulled in by since glibc 2.38, so +// supply it if missing. +#ifndef HWCAP_LOONGARCH_CRC32 +#define HWCAP_LOONGARCH_CRC32 (1 << 6) +#endif +// Query HWCAP for platform capability, according to *Software Development and +// Build Convention for LoongArch Architectures* v0.1, Section 9.1. +// +// Link: +// https://github.com/loongson/la-softdev-convention/blob/v0.1/la-softdev-convention.adoc#kernel-development +bool hasHardwareCRC32() { + return !!(getauxval(AT_HWCAP) & HWCAP_LOONGARCH_CRC32); +} #else // No hardware CRC32 implemented in Scudo for other architectures. bool hasHardwareCRC32() { return false; } diff --git a/compiler-rt/lib/scudo/standalone/checksum.h b/compiler-rt/lib/scudo/standalone/checksum.h index f8eda81fd9128..32ca372b097f6 100644 --- a/compiler-rt/lib/scudo/standalone/checksum.h +++ b/compiler-rt/lib/scudo/standalone/checksum.h @@ -30,6 +30,10 @@ #include #define CRC32_INTRINSIC FIRST_32_SECOND_64(__crc32cw, __crc32cd) #endif +#ifdef __loongarch__ +#include +#define CRC32_INTRINSIC FIRST_32_SECOND_64(__crcc_w_w_w, __crcc_w_d_w) +#endif namespace scudo { diff --git a/compiler-rt/lib/scudo/standalone/crc32_hw.cpp b/compiler-rt/lib/scudo/standalone/crc32_hw.cpp index 73f2ae000c63d..910cf9460313f 100644 --- a/compiler-rt/lib/scudo/standalone/crc32_hw.cpp +++ b/compiler-rt/lib/scudo/standalone/crc32_hw.cpp @@ -17,4 +17,13 @@ u32 computeHardwareCRC32(u32 Crc, uptr Data) { #endif // defined(__CRC32__) || defined(__SSE4_2__) || // defined(__ARM_FEATURE_CRC32) +#if defined(__loongarch__) +u32 computeHardwareCRC32(u32 Crc, uptr Data) { + // The LoongArch CRC intrinsics have the two input arguments swapped, and + // expect them to be signed. + return static_cast( + CRC32_INTRINSIC(static_cast(Data), static_cast(Crc))); +} +#endif // defined(__loongarch__) + } // namespace scudo diff --git a/compiler-rt/lib/scudo/standalone/primary32.h b/compiler-rt/lib/scudo/standalone/primary32.h index 4d03b282d000d..c86e75b8fd66a 100644 --- a/compiler-rt/lib/scudo/standalone/primary32.h +++ b/compiler-rt/lib/scudo/standalone/primary32.h @@ -191,38 +191,21 @@ template class SizeClassAllocator32 { return BlockSize > PageSize; } - // Note that the `MaxBlockCount` will be used when we support arbitrary blocks - // count. Now it's the same as the number of blocks stored in the - // `TransferBatch`. u16 popBlocks(CacheT *C, uptr ClassId, CompactPtrT *ToArray, - UNUSED const u16 MaxBlockCount) { - TransferBatchT *B = popBatch(C, ClassId); - if (!B) - return 0; - - const u16 Count = B->getCount(); - DCHECK_GT(Count, 0U); - B->moveToArray(ToArray); - - if (ClassId != SizeClassMap::BatchClassId) - C->deallocate(SizeClassMap::BatchClassId, B); - - return Count; - } - - TransferBatchT *popBatch(CacheT *C, uptr ClassId) { + const u16 MaxBlockCount) { DCHECK_LT(ClassId, NumClasses); SizeClassInfo *Sci = getSizeClassInfo(ClassId); ScopedLock L(Sci->Mutex); - TransferBatchT *B = popBatchImpl(C, ClassId, Sci); - if (UNLIKELY(!B)) { + + u16 PopCount = popBlocksImpl(C, ClassId, Sci, ToArray, MaxBlockCount); + if (UNLIKELY(PopCount == 0)) { if (UNLIKELY(!populateFreeList(C, ClassId, Sci))) - return nullptr; - B = popBatchImpl(C, ClassId, Sci); - // if `populateFreeList` succeeded, we are supposed to get free blocks. - DCHECK_NE(B, nullptr); + return 0U; + PopCount = popBlocksImpl(C, ClassId, Sci, ToArray, MaxBlockCount); + DCHECK_NE(PopCount, 0U); } - return B; + + return PopCount; } // Push the array of free blocks to the designated batch group. @@ -510,7 +493,7 @@ template class SizeClassAllocator32 { // by TransferBatch is also free for use. We don't need to recycle the // TransferBatch. Note that the correctness is maintained by the invariant, // - // The unit of each popBatch() request is entire TransferBatch. Return + // Each popBlocks() request returns the entire TransferBatch. Returning // part of the blocks in a TransferBatch is invalid. // // This ensures that TransferBatch won't leak the address itself while it's @@ -634,7 +617,7 @@ template class SizeClassAllocator32 { BG->Batches.push_front(TB); BG->PushedBlocks = 0; BG->BytesInBGAtLastCheckpoint = 0; - BG->MaxCachedPerBatch = CacheT::getMaxCached(getSizeByClassId(ClassId)); + BG->MaxCachedPerBatch = TransferBatchT::MaxNumCached; return BG; }; @@ -726,14 +709,11 @@ template class SizeClassAllocator32 { InsertBlocks(Cur, Array + Size - Count, Count); } - // Pop one TransferBatch from a BatchGroup. The BatchGroup with the smallest - // group id will be considered first. - // - // The region mutex needs to be held while calling this method. - TransferBatchT *popBatchImpl(CacheT *C, uptr ClassId, SizeClassInfo *Sci) + u16 popBlocksImpl(CacheT *C, uptr ClassId, SizeClassInfo *Sci, + CompactPtrT *ToArray, const u16 MaxBlockCount) REQUIRES(Sci->Mutex) { if (Sci->FreeListInfo.BlockList.empty()) - return nullptr; + return 0U; SinglyLinkedList &Batches = Sci->FreeListInfo.BlockList.front()->Batches; @@ -746,33 +726,57 @@ template class SizeClassAllocator32 { // Block used by `BatchGroup` is from BatchClassId. Turn the block into // `TransferBatch` with single block. TransferBatchT *TB = reinterpret_cast(BG); - TB->clear(); - TB->add( - compactPtr(SizeClassMap::BatchClassId, reinterpret_cast(TB))); + ToArray[0] = + compactPtr(SizeClassMap::BatchClassId, reinterpret_cast(TB)); Sci->FreeListInfo.PoppedBlocks += 1; - return TB; + return 1U; } + // So far, instead of always filling the blocks to `MaxBlockCount`, we only + // examine single `TransferBatch` to minimize the time spent on the primary + // allocator. Besides, the sizes of `TransferBatch` and + // `CacheT::getMaxCached()` may also impact the time spent on accessing the + // primary allocator. + // TODO(chiahungduan): Evaluate if we want to always prepare `MaxBlockCount` + // blocks and/or adjust the size of `TransferBatch` according to + // `CacheT::getMaxCached()`. TransferBatchT *B = Batches.front(); - Batches.pop_front(); DCHECK_NE(B, nullptr); DCHECK_GT(B->getCount(), 0U); - if (Batches.empty()) { - BatchGroupT *BG = Sci->FreeListInfo.BlockList.front(); - Sci->FreeListInfo.BlockList.pop_front(); - - // We don't keep BatchGroup with zero blocks to avoid empty-checking while - // allocating. Note that block used by constructing BatchGroup is recorded - // as free blocks in the last element of BatchGroup::Batches. Which means, - // once we pop the last TransferBatch, the block is implicitly - // deallocated. + // BachClassId should always take all blocks in the TransferBatch. Read the + // comment in `pushBatchClassBlocks()` for more details. + const u16 PopCount = ClassId == SizeClassMap::BatchClassId + ? B->getCount() + : Min(MaxBlockCount, B->getCount()); + B->moveNToArray(ToArray, PopCount); + + // TODO(chiahungduan): The deallocation of unused BatchClassId blocks can be + // done without holding `Mutex`. + if (B->empty()) { + Batches.pop_front(); + // `TransferBatch` of BatchClassId is self-contained, no need to + // deallocate. Read the comment in `pushBatchClassBlocks()` for more + // details. if (ClassId != SizeClassMap::BatchClassId) - C->deallocate(SizeClassMap::BatchClassId, BG); + C->deallocate(SizeClassMap::BatchClassId, B); + + if (Batches.empty()) { + BatchGroupT *BG = Sci->FreeListInfo.BlockList.front(); + Sci->FreeListInfo.BlockList.pop_front(); + + // We don't keep BatchGroup with zero blocks to avoid empty-checking + // while allocating. Note that block used for constructing BatchGroup is + // recorded as free blocks in the last element of BatchGroup::Batches. + // Which means, once we pop the last TransferBatch, the block is + // implicitly deallocated. + if (ClassId != SizeClassMap::BatchClassId) + C->deallocate(SizeClassMap::BatchClassId, BG); + } } - Sci->FreeListInfo.PoppedBlocks += B->getCount(); - return B; + Sci->FreeListInfo.PoppedBlocks += PopCount; + return PopCount; } NOINLINE bool populateFreeList(CacheT *C, uptr ClassId, SizeClassInfo *Sci) diff --git a/compiler-rt/lib/scudo/standalone/primary64.h b/compiler-rt/lib/scudo/standalone/primary64.h index 9a642d23620e1..d89a2e6a4e5c8 100644 --- a/compiler-rt/lib/scudo/standalone/primary64.h +++ b/compiler-rt/lib/scudo/standalone/primary64.h @@ -12,6 +12,7 @@ #include "allocator_common.h" #include "bytemap.h" #include "common.h" +#include "condition_variable.h" #include "list.h" #include "local_cache.h" #include "mem_map.h" @@ -22,8 +23,6 @@ #include "string_utils.h" #include "thread_annotations.h" -#include "condition_variable.h" - namespace scudo { // SizeClassAllocator64 is an allocator tuned for 64-bit address space. @@ -221,41 +220,24 @@ template class SizeClassAllocator64 { DCHECK_EQ(BlocksInUse, BatchClassUsedInFreeLists); } - // Note that the `MaxBlockCount` will be used when we support arbitrary blocks - // count. Now it's the same as the number of blocks stored in the - // `TransferBatch`. u16 popBlocks(CacheT *C, uptr ClassId, CompactPtrT *ToArray, - UNUSED const u16 MaxBlockCount) { - TransferBatchT *B = popBatch(C, ClassId); - if (!B) - return 0; - - const u16 Count = B->getCount(); - DCHECK_GT(Count, 0U); - B->moveToArray(ToArray); - - if (ClassId != SizeClassMap::BatchClassId) - C->deallocate(SizeClassMap::BatchClassId, B); - - return Count; - } - - TransferBatchT *popBatch(CacheT *C, uptr ClassId) { + const u16 MaxBlockCount) { DCHECK_LT(ClassId, NumClasses); RegionInfo *Region = getRegionInfo(ClassId); + u16 PopCount = 0; { ScopedLock L(Region->FLLock); - TransferBatchT *B = popBatchImpl(C, ClassId, Region); - if (LIKELY(B)) - return B; + PopCount = popBlocksImpl(C, ClassId, Region, ToArray, MaxBlockCount); + if (PopCount != 0U) + return PopCount; } bool ReportRegionExhausted = false; - TransferBatchT *B = nullptr; if (conditionVariableEnabled()) { - B = popBatchWithCV(C, ClassId, Region, ReportRegionExhausted); + PopCount = popBlocksWithCV(C, ClassId, Region, ToArray, MaxBlockCount, + ReportRegionExhausted); } else { while (true) { // When two threads compete for `Region->MMLock`, we only want one of @@ -264,13 +246,15 @@ template class SizeClassAllocator64 { ScopedLock ML(Region->MMLock); { ScopedLock FL(Region->FLLock); - if ((B = popBatchImpl(C, ClassId, Region))) - break; + PopCount = popBlocksImpl(C, ClassId, Region, ToArray, MaxBlockCount); + if (PopCount != 0U) + return PopCount; } const bool RegionIsExhausted = Region->Exhausted; if (!RegionIsExhausted) - B = populateFreeListAndPopBatch(C, ClassId, Region); + PopCount = populateFreeListAndPopBlocks(C, ClassId, Region, ToArray, + MaxBlockCount); ReportRegionExhausted = !RegionIsExhausted && Region->Exhausted; break; } @@ -286,7 +270,7 @@ template class SizeClassAllocator64 { reportOutOfBatchClass(); } - return B; + return PopCount; } // Push the array of free blocks to the designated batch group. @@ -640,7 +624,7 @@ template class SizeClassAllocator64 { // by TransferBatch is also free for use. We don't need to recycle the // TransferBatch. Note that the correctness is maintained by the invariant, // - // The unit of each popBatch() request is entire TransferBatch. Return + // Each popBlocks() request returns the entire TransferBatch. Returning // part of the blocks in a TransferBatch is invalid. // // This ensures that TransferBatch won't leak the address itself while it's @@ -763,7 +747,7 @@ template class SizeClassAllocator64 { BG->Batches.push_front(TB); BG->PushedBlocks = 0; BG->BytesInBGAtLastCheckpoint = 0; - BG->MaxCachedPerBatch = CacheT::getMaxCached(getSizeByClassId(ClassId)); + BG->MaxCachedPerBatch = TransferBatchT::MaxNumCached; return BG; }; @@ -855,9 +839,10 @@ template class SizeClassAllocator64 { InsertBlocks(Cur, Array + Size - Count, Count); } - TransferBatchT *popBatchWithCV(CacheT *C, uptr ClassId, RegionInfo *Region, - bool &ReportRegionExhausted) { - TransferBatchT *B = nullptr; + u16 popBlocksWithCV(CacheT *C, uptr ClassId, RegionInfo *Region, + CompactPtrT *ToArray, const u16 MaxBlockCount, + bool &ReportRegionExhausted) { + u16 PopCount = 0; while (true) { // We only expect one thread doing the freelist refillment and other @@ -878,7 +863,8 @@ template class SizeClassAllocator64 { const bool RegionIsExhausted = Region->Exhausted; if (!RegionIsExhausted) - B = populateFreeListAndPopBatch(C, ClassId, Region); + PopCount = populateFreeListAndPopBlocks(C, ClassId, Region, ToArray, + MaxBlockCount); ReportRegionExhausted = !RegionIsExhausted && Region->Exhausted; { @@ -905,7 +891,8 @@ template class SizeClassAllocator64 { // blocks were used up right after the refillment. Therefore, we have to // check if someone is still populating the freelist. ScopedLock FL(Region->FLLock); - if (LIKELY(B = popBatchImpl(C, ClassId, Region))) + PopCount = popBlocksImpl(C, ClassId, Region, ToArray, MaxBlockCount); + if (PopCount != 0U) break; if (!Region->isPopulatingFreeList) @@ -918,21 +905,19 @@ template class SizeClassAllocator64 { // `pushBatchClassBlocks()` and `mergeGroupsToReleaseBack()`. Region->FLLockCV.wait(Region->FLLock); - if (LIKELY(B = popBatchImpl(C, ClassId, Region))) + PopCount = popBlocksImpl(C, ClassId, Region, ToArray, MaxBlockCount); + if (PopCount != 0U) break; } - return B; + return PopCount; } - // Pop one TransferBatch from a BatchGroup. The BatchGroup with the smallest - // group id will be considered first. - // - // The region mutex needs to be held while calling this method. - TransferBatchT *popBatchImpl(CacheT *C, uptr ClassId, RegionInfo *Region) + u16 popBlocksImpl(CacheT *C, uptr ClassId, RegionInfo *Region, + CompactPtrT *ToArray, const u16 MaxBlockCount) REQUIRES(Region->FLLock) { if (Region->FreeListInfo.BlockList.empty()) - return nullptr; + return 0U; SinglyLinkedList &Batches = Region->FreeListInfo.BlockList.front()->Batches; @@ -945,39 +930,64 @@ template class SizeClassAllocator64 { // Block used by `BatchGroup` is from BatchClassId. Turn the block into // `TransferBatch` with single block. TransferBatchT *TB = reinterpret_cast(BG); - TB->clear(); - TB->add( - compactPtr(SizeClassMap::BatchClassId, reinterpret_cast(TB))); + ToArray[0] = + compactPtr(SizeClassMap::BatchClassId, reinterpret_cast(TB)); Region->FreeListInfo.PoppedBlocks += 1; - return TB; + return 1U; } + // So far, instead of always filling blocks to `MaxBlockCount`, we only + // examine single `TransferBatch` to minimize the time spent in the primary + // allocator. Besides, the sizes of `TransferBatch` and + // `CacheT::getMaxCached()` may also impact the time spent on accessing the + // primary allocator. + // TODO(chiahungduan): Evaluate if we want to always prepare `MaxBlockCount` + // blocks and/or adjust the size of `TransferBatch` according to + // `CacheT::getMaxCached()`. TransferBatchT *B = Batches.front(); - Batches.pop_front(); DCHECK_NE(B, nullptr); DCHECK_GT(B->getCount(), 0U); - if (Batches.empty()) { - BatchGroupT *BG = Region->FreeListInfo.BlockList.front(); - Region->FreeListInfo.BlockList.pop_front(); - - // We don't keep BatchGroup with zero blocks to avoid empty-checking while - // allocating. Note that block used by constructing BatchGroup is recorded - // as free blocks in the last element of BatchGroup::Batches. Which means, - // once we pop the last TransferBatch, the block is implicitly - // deallocated. + // BachClassId should always take all blocks in the TransferBatch. Read the + // comment in `pushBatchClassBlocks()` for more details. + const u16 PopCount = ClassId == SizeClassMap::BatchClassId + ? B->getCount() + : Min(MaxBlockCount, B->getCount()); + B->moveNToArray(ToArray, PopCount); + + // TODO(chiahungduan): The deallocation of unused BatchClassId blocks can be + // done without holding `FLLock`. + if (B->empty()) { + Batches.pop_front(); + // `TransferBatch` of BatchClassId is self-contained, no need to + // deallocate. Read the comment in `pushBatchClassBlocks()` for more + // details. if (ClassId != SizeClassMap::BatchClassId) - C->deallocate(SizeClassMap::BatchClassId, BG); + C->deallocate(SizeClassMap::BatchClassId, B); + + if (Batches.empty()) { + BatchGroupT *BG = Region->FreeListInfo.BlockList.front(); + Region->FreeListInfo.BlockList.pop_front(); + + // We don't keep BatchGroup with zero blocks to avoid empty-checking + // while allocating. Note that block used for constructing BatchGroup is + // recorded as free blocks in the last element of BatchGroup::Batches. + // Which means, once we pop the last TransferBatch, the block is + // implicitly deallocated. + if (ClassId != SizeClassMap::BatchClassId) + C->deallocate(SizeClassMap::BatchClassId, BG); + } } - Region->FreeListInfo.PoppedBlocks += B->getCount(); + Region->FreeListInfo.PoppedBlocks += PopCount; - return B; + return PopCount; } - // Refill the freelist and return one batch. - NOINLINE TransferBatchT *populateFreeListAndPopBatch(CacheT *C, uptr ClassId, - RegionInfo *Region) + NOINLINE u16 populateFreeListAndPopBlocks(CacheT *C, uptr ClassId, + RegionInfo *Region, + CompactPtrT *ToArray, + const u16 MaxBlockCount) REQUIRES(Region->MMLock) EXCLUDES(Region->FLLock) { const uptr Size = getSizeByClassId(ClassId); const u16 MaxCount = CacheT::getMaxCached(Size); @@ -994,7 +1004,7 @@ template class SizeClassAllocator64 { const uptr RegionBase = RegionBeg - getRegionBaseByClassId(ClassId); if (UNLIKELY(RegionBase + MappedUser + MapSize > RegionSize)) { Region->Exhausted = true; - return nullptr; + return 0U; } if (UNLIKELY(!Region->MemMapInfo.MemMap.remap( @@ -1002,7 +1012,7 @@ template class SizeClassAllocator64 { MAP_ALLOWNOMEM | MAP_RESIZABLE | (useMemoryTagging(Options.load()) ? MAP_MEMTAG : 0)))) { - return nullptr; + return 0U; } Region->MemMapInfo.MappedUser += MapSize; C->getStats().add(StatMapped, MapSize); @@ -1049,8 +1059,9 @@ template class SizeClassAllocator64 { pushBatchClassBlocks(Region, ShuffleArray, NumberOfBlocks); } - TransferBatchT *B = popBatchImpl(C, ClassId, Region); - DCHECK_NE(B, nullptr); + const u16 PopCount = + popBlocksImpl(C, ClassId, Region, ToArray, MaxBlockCount); + DCHECK_NE(PopCount, 0U); // Note that `PushedBlocks` and `PoppedBlocks` are supposed to only record // the requests from `PushBlocks` and `PopBatch` which are external @@ -1062,7 +1073,7 @@ template class SizeClassAllocator64 { C->getStats().add(StatFree, AllocatedUser); Region->MemMapInfo.AllocatedUser += AllocatedUser; - return B; + return PopCount; } void getStats(ScopedString *Str, uptr ClassId, RegionInfo *Region) @@ -1186,7 +1197,7 @@ template class SizeClassAllocator64 { } // Note that we have extracted the `GroupsToRelease` from region freelist. - // It's safe to let pushBlocks()/popBatches() access the remaining region + // It's safe to let pushBlocks()/popBlocks() access the remaining region // freelist. In the steps 3 and 4, we will temporarily release the FLLock // and lock it again before step 5. diff --git a/compiler-rt/lib/scudo/standalone/secondary.h b/compiler-rt/lib/scudo/standalone/secondary.h index f52a4188bcf3a..732fd307ed2f4 100644 --- a/compiler-rt/lib/scudo/standalone/secondary.h +++ b/compiler-rt/lib/scudo/standalone/secondary.h @@ -122,7 +122,29 @@ bool mapSecondary(const Options &Options, uptr CommitBase, uptr CommitSize, Flags |= MAP_RESIZABLE; Flags |= MAP_ALLOWNOMEM; - const uptr MaxUnusedCacheBytes = MaxUnusedCachePages * getPageSizeCached(); + const uptr PageSize = getPageSizeCached(); + if (SCUDO_TRUSTY) { + /* + * On Trusty we need AllocPos to be usable for shared memory, which cannot + * cross multiple mappings. This means we need to split around AllocPos + * and not over it. We can only do this if the address is page-aligned. + */ + const uptr TaggedSize = AllocPos - CommitBase; + if (useMemoryTagging(Options) && isAligned(TaggedSize, PageSize)) { + DCHECK_GT(TaggedSize, 0); + return MemMap.remap(CommitBase, TaggedSize, "scudo:secondary", + MAP_MEMTAG | Flags) && + MemMap.remap(AllocPos, CommitSize - TaggedSize, "scudo:secondary", + Flags); + } else { + const uptr RemapFlags = + (useMemoryTagging(Options) ? MAP_MEMTAG : 0) | Flags; + return MemMap.remap(CommitBase, CommitSize, "scudo:secondary", + RemapFlags); + } + } + + const uptr MaxUnusedCacheBytes = MaxUnusedCachePages * PageSize; if (useMemoryTagging(Options) && CommitSize > MaxUnusedCacheBytes) { const uptr UntaggedPos = Max(AllocPos, CommitBase + MaxUnusedCacheBytes); return MemMap.remap(CommitBase, UntaggedPos - CommitBase, "scudo:secondary", diff --git a/compiler-rt/lib/scudo/standalone/tests/primary_test.cpp b/compiler-rt/lib/scudo/standalone/tests/primary_test.cpp index 18171511758a1..f64a5143b30d4 100644 --- a/compiler-rt/lib/scudo/standalone/tests/primary_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/primary_test.cpp @@ -237,7 +237,6 @@ struct SmallRegionsConfig { // For the 32-bit one, it requires actually exhausting memory, so we skip it. TEST(ScudoPrimaryTest, Primary64OOM) { using Primary = scudo::SizeClassAllocator64; - using TransferBatch = Primary::TransferBatchT; Primary Allocator; Allocator.init(/*ReleaseToOsInterval=*/-1); typename Primary::CacheT Cache; @@ -245,29 +244,26 @@ TEST(ScudoPrimaryTest, Primary64OOM) { Stats.init(); Cache.init(&Stats, &Allocator); bool AllocationFailed = false; - std::vector Batches; + std::vector Blocks; const scudo::uptr ClassId = Primary::SizeClassMap::LargestClassId; const scudo::uptr Size = Primary::getSizeByClassId(ClassId); - typename Primary::CacheT::CompactPtrT Blocks[TransferBatch::MaxNumCached]; + const scudo::u16 MaxCachedBlockCount = Primary::CacheT::getMaxCached(Size); for (scudo::uptr I = 0; I < 10000U; I++) { - TransferBatch *B = Allocator.popBatch(&Cache, ClassId); - if (!B) { - AllocationFailed = true; - break; + for (scudo::uptr J = 0; J < MaxCachedBlockCount; ++J) { + void *Ptr = Cache.allocate(ClassId); + if (Ptr == nullptr) { + AllocationFailed = true; + break; + } + memset(Ptr, 'B', Size); + Blocks.push_back(Ptr); } - for (scudo::u16 J = 0; J < B->getCount(); J++) - memset(Allocator.decompactPtr(ClassId, B->get(J)), 'B', Size); - Batches.push_back(B); - } - while (!Batches.empty()) { - TransferBatch *B = Batches.back(); - Batches.pop_back(); - const scudo::u16 Count = B->getCount(); - B->moveToArray(Blocks); - Allocator.pushBlocks(&Cache, ClassId, Blocks, Count); - Cache.deallocate(Primary::SizeClassMap::BatchClassId, B); } + + for (auto *Ptr : Blocks) + Cache.deallocate(ClassId, Ptr); + Cache.destroy(nullptr); Allocator.releaseToOS(scudo::ReleaseToOS::Force); scudo::ScopedString Str; @@ -342,7 +338,7 @@ SCUDO_TYPED_TEST(ScudoPrimaryTest, PrimaryThreaded) { V.push_back(std::make_pair(ClassId, P)); } - // Try to interleave pushBlocks(), popBatch() and releaseToOS(). + // Try to interleave pushBlocks(), popBlocks() and releaseToOS(). Allocator->releaseToOS(scudo::ReleaseToOS::Force); while (!V.empty()) { diff --git a/compiler-rt/test/dfsan/reaches_function.c b/compiler-rt/test/dfsan/reaches_function.c index 9e2bcee935b2a..a00654e7ae132 100644 --- a/compiler-rt/test/dfsan/reaches_function.c +++ b/compiler-rt/test/dfsan/reaches_function.c @@ -32,11 +32,11 @@ void my_dfsan_reaches_function_callback(dfsan_label label, dfsan_origin origin, __attribute__((noinline)) uint64_t add(uint64_t *a, uint64_t *b) { return *a + *b; - // CHECK: {{.*}}compiler-rt/test/dfsan/reaches_function.c:[[# @LINE - 1]] add.dfsan + // CHECK: reaches_function.c:[[# @LINE - 1]] add.dfsan // CHECK-ORIGIN-TRACKING: Origin value: 0x10000002, Taint value was stored to memory at - // CHECK-ORIGIN-TRACKING: #0 {{.*}} in add.dfsan {{.*}}compiler-rt/test/dfsan/reaches_function.c:[[# @LINE - 3]]:{{.*}} + // CHECK-ORIGIN-TRACKING: #0 {{.*}} in add.dfsan {{.*}}reaches_function.c:[[# @LINE - 3]]:{{.*}} // CHECK-ORIGIN-TRACKING: Origin value: 0x1, Taint value was created at - // CHECK-ORIGIN-TRACKING: #0 {{.*}} in main {{.*}}compiler-rt/test/dfsan/reaches_function.c:{{.*}} + // CHECK-ORIGIN-TRACKING: #0 {{.*}} in main {{.*}}reaches_function.c:{{.*}} } extern void my_dfsan_reaches_function_callback(dfsan_label label, @@ -54,11 +54,11 @@ int main(int argc, char *argv[]) { dfsan_set_label(8, &a, sizeof(a)); uint64_t c = add(&a, &b); - // CHECK: {{.*}}compiler-rt/test/dfsan/reaches_function.c:[[# @LINE - 1]] main + // CHECK: reaches_function.c:[[# @LINE - 1]] main // CHECK-ORIGIN-TRACKING: Origin value: 0x10000002, Taint value was stored to memory at - // CHECK-ORIGIN-TRACKING: #0 {{.*}} in add.dfsan {{.*}}compiler-rt/test/dfsan/reaches_function.c:{{.*}} + // CHECK-ORIGIN-TRACKING: #0 {{.*}} in add.dfsan {{.*}}reaches_function.c:{{.*}} // CHECK-ORIGIN-TRACKING: Origin value: 0x1, Taint value was created at - // CHECK-ORIGIN-TRACKING: #0 {{.*}} in main {{.*}}compiler-rt/test/dfsan/reaches_function.c:[[# @LINE - 6]]:{{.*}} + // CHECK-ORIGIN-TRACKING: #0 {{.*}} in main {{.*}}reaches_function.c:[[# @LINE - 6]]:{{.*}} return c; } diff --git a/compiler-rt/test/hwasan/TestCases/longjmp-out-of-range.c b/compiler-rt/test/hwasan/TestCases/longjmp-out-of-range.c new file mode 100644 index 0000000000000..2d7ed2ab5ee24 --- /dev/null +++ b/compiler-rt/test/hwasan/TestCases/longjmp-out-of-range.c @@ -0,0 +1,20 @@ +// RUN: %clang_hwasan -O0 %s -o %t && %run %t 2>&1 | FileCheck %s + +// REQUIRES: pointer-tagging +#include +#include +#include + +__attribute__((noinline)) int f(void *caller_frame) { + int z = 0; + int *volatile p = &z; + // Tag of local is never zero. + assert(__hwasan_tag_pointer(p, 0) != p); + __hwasan_handle_longjmp(NULL); + return p[0]; +} + +int main() { + return f(__builtin_frame_address(0)); + // CHECK: HWASan is ignoring requested __hwasan_handle_longjmp: +} diff --git a/flang/docs/Directives.md b/flang/docs/Directives.md index 134de36f884d7..fe08b4f855f23 100644 --- a/flang/docs/Directives.md +++ b/flang/docs/Directives.md @@ -30,3 +30,9 @@ A list of non-standard directives supported by Flang end end interface ``` +* `!dir$ assume_aligned desginator:alignment`, where designator is a variable, + maybe with array indices, and alignment is what the compiler should assume the + alignment to be. E.g A:64 or B(1,1,1):128. The alignment should be a power of 2, + and is limited to 256. + [This directive is currently recognised by the parser, but not + handled by the other parts of the compiler]. diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md index 46ef8f07b4a8b..697bd131c04c7 100644 --- a/flang/docs/Extensions.md +++ b/flang/docs/Extensions.md @@ -481,6 +481,11 @@ end * Many compilers disallow a `VALUE` assumed-length character dummy argument, which has been standard since F'2008. We accept this usage with an optional portability warning. +* The `ASYNCHRONOUS` attribute can be implied by usage in data + transfer I/O statements. Only one other compiler supports this + correctly. This compiler does, apart from objects in asynchronous + NAMELIST I/O, for which an actual asynchronous runtime implementation + seems unlikely. ## Behavior in cases where the standard is ambiguous or indefinite @@ -687,6 +692,35 @@ end essentially ignored unless there are some unmasked array entries and *all* of them are NaNs. +* When `INDEX` is used as an unrestricted specific intrinsic function + in the context of an actual procedure, as the explicit interface in + a `PROCEDURE` declaration statement, or as the target of a procedure + pointer assignment, its interface has exactly two dummy arguments + (`STRING=` and `SUBSTRING=`), and includes neither `BACK=` nor + `KIND=`. + This is how `INDEX` as an unrestricted specific intrinsic function was + documented in FORTRAN '77 and Fortran '90; later revisions of the + standard deleted the argument information from the section on + unrestricted specific intrinsic functions. + At least one other compiler (XLF) seems to expect that the interface for + `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 0000000000000..d29a46807e1ea --- /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/conf.py b/flang/docs/conf.py index a34f7bf4a2100..48f7b69f5d750 100644 --- a/flang/docs/conf.py +++ b/flang/docs/conf.py @@ -22,13 +22,24 @@ # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ - "myst_parser", "sphinx.ext.todo", "sphinx.ext.mathjax", "sphinx.ext.intersphinx", "sphinx.ext.autodoc", ] +# When building man pages, we do not use the markdown pages, +# So, we can continue without the myst_parser dependencies. +# Doing so reduces dependencies of some packaged llvm distributions. +try: + import myst_parser + + extensions.append("myst_parser") +except ImportError: + if not tags.has("builder-man"): + raise + + # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] myst_heading_anchors = 6 diff --git a/flang/docs/index.md b/flang/docs/index.md index d974a3628b01d..b4dbdc87fdf68 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/characteristics.h b/flang/include/flang/Evaluate/characteristics.h index 04a0d71e1adeb..f2f37866ecde8 100644 --- a/flang/include/flang/Evaluate/characteristics.h +++ b/flang/include/flang/Evaluate/characteristics.h @@ -381,8 +381,8 @@ struct Procedure { int FindPassIndex(std::optional) const; bool CanBeCalledViaImplicitInterface(std::string *whyNot = nullptr) const; bool CanOverride(const Procedure &, std::optional passIndex) const; - bool IsCompatibleWith(const Procedure &, std::string *whyNot = nullptr, - const SpecificIntrinsic * = nullptr, + bool IsCompatibleWith(const Procedure &, bool ignoreImplicitVsExplicit, + std::string *whyNot = nullptr, const SpecificIntrinsic * = nullptr, std::optional *warning = nullptr) const; llvm::raw_ostream &Dump(llvm::raw_ostream &) const; diff --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h index d257da1a70964..53896072675ab 100644 --- a/flang/include/flang/Evaluate/tools.h +++ b/flang/include/flang/Evaluate/tools.h @@ -1094,7 +1094,7 @@ std::optional CheckProcCompatibility(bool isCall, const std::optional &lhsProcedure, const characteristics::Procedure *rhsProcedure, const SpecificIntrinsic *specificIntrinsic, std::string &whyNotCompatible, - std::optional &warning); + std::optional &warning, bool ignoreImplicitVsExplicit); // Scalar constant expansion class ScalarConstantExpander { diff --git a/flang/include/flang/Lower/AbstractConverter.h b/flang/include/flang/Lower/AbstractConverter.h index e2af59e0aaa19..32e7a5e2b0406 100644 --- a/flang/include/flang/Lower/AbstractConverter.h +++ b/flang/include/flang/Lower/AbstractConverter.h @@ -53,6 +53,7 @@ class DerivedTypeSpec; namespace lower { class SymMap; +struct SymbolBox; namespace pft { struct Variable; } @@ -299,6 +300,11 @@ class AbstractConverter { return loweringOptions; } + /// Find the symbol in one level up of symbol map such as for host-association + /// in OpenMP code or return null. + virtual Fortran::lower::SymbolBox + lookupOneLevelUpSymbol(const Fortran::semantics::Symbol &sym) = 0; + private: /// Options controlling lowering behavior. const Fortran::lower::LoweringOptions &loweringOptions; diff --git a/flang/include/flang/Lower/LoweringOptions.def b/flang/include/flang/Lower/LoweringOptions.def index 503acdac869c7..9de69ac5c80f5 100644 --- a/flang/include/flang/Lower/LoweringOptions.def +++ b/flang/include/flang/Lower/LoweringOptions.def @@ -24,8 +24,8 @@ LOWERINGOPT(Name, Bits, Default) /// If true, lower transpose without a runtime call. ENUM_LOWERINGOPT(OptimizeTranspose, unsigned, 1, 1) -/// If true, enable polymorphic type lowering feature. Off by default. -ENUM_LOWERINGOPT(PolymorphicTypeImpl, unsigned, 1, 0) +/// If true, enable polymorphic type lowering feature. On by default. +ENUM_LOWERINGOPT(PolymorphicTypeImpl, unsigned, 1, 1) /// If true, lower to High level FIR before lowering to FIR. On by default. ENUM_LOWERINGOPT(LowerToHighLevelFIR, unsigned, 1, 1) diff --git a/flang/include/flang/Lower/OpenMP.h b/flang/include/flang/Lower/OpenMP.h index e6fe7fb2276de..3b22a652d1fc1 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 39821f1036c63..bd9b67b14b966 100644 --- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h +++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h @@ -688,6 +688,9 @@ fir::BoxValue createBoxValue(fir::FirOpBuilder &builder, mlir::Location loc, /// Generate Null BoxProc for procedure pointer null initialization. mlir::Value createNullBoxProc(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type boxType); + +/// Set internal linkage attribute on a function. +void setInternalLinkage(mlir::func::FuncOp); } // namespace fir::factory #endif // FORTRAN_OPTIMIZER_BUILDER_FIRBUILDER_H diff --git a/flang/include/flang/Optimizer/CodeGen/CodeGen.h b/flang/include/flang/Optimizer/CodeGen/CodeGen.h index 5ea96c900bc63..cbf02ec391236 100644 --- a/flang/include/flang/Optimizer/CodeGen/CodeGen.h +++ b/flang/include/flang/Optimizer/CodeGen/CodeGen.h @@ -18,6 +18,8 @@ namespace fir { +class LLVMTypeConverter; + struct NameUniquer; #define GEN_PASS_DECL_FIRTOLLVMLOWERING @@ -80,6 +82,11 @@ std::unique_ptr createLLVMDialectToLLVMPass( std::unique_ptr createBoxedProcedurePass(); std::unique_ptr createBoxedProcedurePass(bool useThunks); +/// Populate the given list with patterns that convert from FIR to LLVM. +void populateFIRToLLVMConversionPatterns(fir::LLVMTypeConverter &converter, + mlir::RewritePatternSet &patterns, + fir::FIRToLLVMPassOptions &options); + // declarative passes #define GEN_PASS_REGISTRATION #include "flang/Optimizer/CodeGen/CGPasses.h.inc" diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index d067a7273540f..048008a8d80c7 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -205,6 +205,7 @@ class ParseTreeDumper { NODE(parser, CompilerDirective) NODE(CompilerDirective, IgnoreTKR) NODE(CompilerDirective, LoopCount) + NODE(CompilerDirective, AssumeAligned) NODE(CompilerDirective, NameValue) NODE(parser, ComplexLiteralConstant) NODE(parser, ComplexPart) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index e9bfb728a2bef..f7b72c3af0916 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -551,7 +551,9 @@ struct ExecutionPartConstruct { }; // R509 execution-part -> executable-construct [execution-part-construct]... -WRAPPER_CLASS(ExecutionPart, std::list); +// R1101 block -> [execution-part-construct]... +using Block = std::list; +WRAPPER_CLASS(ExecutionPart, Block); // R502 program-unit -> // main-program | external-subprogram | module | submodule | block-data @@ -2115,9 +2117,6 @@ struct ForallConstruct { t; }; -// R1101 block -> [execution-part-construct]... -using Block = std::list; - // R1105 selector -> expr | variable struct Selector { UNION_CLASS_BOILERPLATE(Selector); @@ -3309,12 +3308,18 @@ struct CompilerDirective { struct LoopCount { WRAPPER_CLASS_BOILERPLATE(LoopCount, std::list); }; + struct AssumeAligned { + TUPLE_CLASS_BOILERPLATE(AssumeAligned); + std::tuple, uint64_t> t; + }; struct NameValue { TUPLE_CLASS_BOILERPLATE(NameValue); std::tuple> t; }; CharBlock source; - std::variant, LoopCount, std::list> u; + std::variant, LoopCount, std::list, + std::list> + u; }; // (CUDA) ATTRIBUTE(attribute) [::] name-list diff --git a/flang/include/flang/Parser/provenance.h b/flang/include/flang/Parser/provenance.h index a5a5211144285..73d500f32831b 100644 --- a/flang/include/flang/Parser/provenance.h +++ b/flang/include/flang/Parser/provenance.h @@ -151,6 +151,7 @@ class AllSources { void ClearSearchPath(); void AppendSearchPathDirectory(std::string); // new last directory + const SourceFile *OpenPath(std::string path, llvm::raw_ostream &error); const SourceFile *Open(std::string path, llvm::raw_ostream &error, std::optional &&prependPath = std::nullopt); const SourceFile *ReadStandardInput(llvm::raw_ostream &error); diff --git a/flang/include/flang/Parser/source.h b/flang/include/flang/Parser/source.h index f0ae97a3ef048..a6efdf9546c7f 100644 --- a/flang/include/flang/Parser/source.h +++ b/flang/include/flang/Parser/source.h @@ -36,6 +36,8 @@ namespace Fortran::parser { std::string DirectoryName(std::string path); std::optional LocateSourceFile( std::string name, const std::list &searchPath); +std::vector LocateSourceFileAll( + std::string name, const std::vector &searchPath); class SourceFile; diff --git a/flang/include/flang/Runtime/reduction.h b/flang/include/flang/Runtime/reduction.h index 6d62f4016937e..5b60776585752 100644 --- a/flang/include/flang/Runtime/reduction.h +++ b/flang/include/flang/Runtime/reduction.h @@ -364,9 +364,12 @@ double RTDECL(Norm2_8)( #if LDBL_MANT_DIG == 64 long double RTDECL(Norm2_10)( const Descriptor &, const char *source, int line, int dim = 0); -#elif LDBL_MANT_DIG == 113 +#endif +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 long double RTDECL(Norm2_16)( const Descriptor &, const char *source, int line, int dim = 0); +void RTDECL(Norm2DimReal16)( + Descriptor &, const Descriptor &, int dim, const char *source, int line); #endif void RTDECL(Norm2Dim)( Descriptor &, const Descriptor &, int dim, const char *source, int line); diff --git a/flang/include/flang/Semantics/expression.h b/flang/include/flang/Semantics/expression.h index a330e241c2cda..a224b08da21da 100644 --- a/flang/include/flang/Semantics/expression.h +++ b/flang/include/flang/Semantics/expression.h @@ -506,9 +506,18 @@ class ExprChecker { } bool Pre(const parser::ComponentDefStmt &) { - // Already analyzed in name resolution and PDT instantiation; - // do not attempt to re-analyze now without type parameters. - return false; + inComponentDefStmt_ = true; + return true; + } + void Post(const parser::ComponentDefStmt &) { inComponentDefStmt_ = false; } + bool Pre(const parser::Initialization &x) { + // Default component initialization expressions (but not DATA-like ones + // as in DEC STRUCTUREs) were already analyzed in name resolution + // and PDT instantiation; do not attempt to re-analyze them without + // type parameters. + return !inComponentDefStmt_ || + std::holds_alternative< + std::list>>(x.u); } template bool Pre(const parser::Scalar &x) { @@ -538,6 +547,7 @@ class ExprChecker { SemanticsContext &context_; evaluate::ExpressionAnalyzer exprAnalyzer_{context_}; int whereDepth_{0}; // nesting of WHERE statements & constructs + bool inComponentDefStmt_{false}; }; } // namespace Fortran::semantics #endif // FORTRAN_SEMANTICS_EXPRESSION_H_ diff --git a/flang/include/flang/Semantics/module-dependences.h b/flang/include/flang/Semantics/module-dependences.h new file mode 100644 index 0000000000000..29813a19a4b1b --- /dev/null +++ b/flang/include/flang/Semantics/module-dependences.h @@ -0,0 +1,51 @@ +//===-- include/flang/Semantics/module-dependences.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_SEMANTICS_MODULE_DEPENDENCES_H_ +#define FORTRAN_SEMANTICS_MODULE_DEPENDENCES_H_ + +#include +#include +#include +#include + +namespace Fortran::semantics { + +using ModuleCheckSumType = std::uint64_t; + +class ModuleDependences { +public: + void AddDependence( + std::string &&name, bool intrinsic, ModuleCheckSumType hash) { + if (intrinsic) { + intrinsicMap_.emplace(std::move(name), hash); + } else { + nonIntrinsicMap_.emplace(std::move(name), hash); + } + } + std::optional GetRequiredHash( + const std::string &name, bool intrinsic) { + if (intrinsic) { + if (auto iter{intrinsicMap_.find(name)}; iter != intrinsicMap_.end()) { + return iter->second; + } + } else { + if (auto iter{nonIntrinsicMap_.find(name)}; + iter != nonIntrinsicMap_.end()) { + return iter->second; + } + } + return std::nullopt; + } + +private: + std::map intrinsicMap_, nonIntrinsicMap_; +}; + +} // namespace Fortran::semantics +#endif // FORTRAN_SEMANTICS_MODULE_DEPENDENCES_H_ diff --git a/flang/include/flang/Semantics/semantics.h b/flang/include/flang/Semantics/semantics.h index 4e8b71fa652f5..c8ee71945d8bd 100644 --- a/flang/include/flang/Semantics/semantics.h +++ b/flang/include/flang/Semantics/semantics.h @@ -16,6 +16,7 @@ #include "flang/Evaluate/intrinsics.h" #include "flang/Evaluate/target.h" #include "flang/Parser/message.h" +#include "flang/Semantics/module-dependences.h" #include #include #include @@ -108,6 +109,7 @@ class SemanticsContext { parser::Messages &messages() { return messages_; } evaluate::FoldingContext &foldingContext() { return foldingContext_; } parser::AllCookedSources &allCookedSources() { return allCookedSources_; } + ModuleDependences &moduleDependences() { return moduleDependences_; } SemanticsContext &set_location( const std::optional &location) { @@ -293,6 +295,7 @@ class SemanticsContext { const Scope *ppcBuiltinsScope_{nullptr}; // module __ppc_intrinsics std::list modFileParseTrees_; std::unique_ptr commonBlockMap_; + ModuleDependences moduleDependences_; }; class Semantics { diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h index 4535a92ce3dd8..c3175a5d1a111 100644 --- a/flang/include/flang/Semantics/symbol.h +++ b/flang/include/flang/Semantics/symbol.h @@ -14,6 +14,7 @@ #include "flang/Common/enum-set.h" #include "flang/Common/reference.h" #include "flang/Common/visit.h" +#include "flang/Semantics/module-dependences.h" #include "llvm/ADT/DenseMapInfo.h" #include @@ -86,11 +87,16 @@ class ModuleDetails : public WithOmpDeclarative { void set_scope(const Scope *); bool isDefaultPrivate() const { return isDefaultPrivate_; } void set_isDefaultPrivate(bool yes = true) { isDefaultPrivate_ = yes; } + std::optional moduleFileHash() const { + return moduleFileHash_; + } + void set_moduleFileHash(ModuleCheckSumType x) { moduleFileHash_ = x; } private: bool isSubmodule_; bool isDefaultPrivate_{false}; const Scope *scope_{nullptr}; + std::optional moduleFileHash_; }; class MainProgramDetails : public WithOmpDeclarative { @@ -411,9 +417,12 @@ class ProcEntityDetails : public EntityDetails, public WithPassArg { 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; } - bool IsInterfaceSet() { return procInterface_ || type(); } + void set_procInterfaces(const Symbol &raw, const Symbol &resolved) { + rawProcInterface_ = &raw; + procInterface_ = &resolved; + } inline bool HasExplicitInterface() const; // Be advised: !init().has_value() => uninitialized pointer, @@ -425,6 +434,7 @@ class ProcEntityDetails : public EntityDetails, public WithPassArg { void set_isCUDAKernel(bool yes = true) { isCUDAKernel_ = yes; } private: + const Symbol *rawProcInterface_{nullptr}; const Symbol *procInterface_{nullptr}; std::optional init_; bool isCUDAKernel_{false}; @@ -1035,7 +1045,7 @@ struct SymbolAddressCompare { // Symbol comparison is usually based on the order of cooked source // stream creation and, when both are from the same cooked source, // their positions in that cooked source stream. -// Don't use this comparator or OrderedSymbolSet to hold +// Don't use this comparator or SourceOrderedSymbolSet to hold // Symbols that might be subject to ReplaceName(). struct SymbolSourcePositionCompare { // These functions are implemented in Evaluate/tools.cpp to diff --git a/flang/include/flang/Semantics/type.h b/flang/include/flang/Semantics/type.h index 8965d29d8889d..5520b02e6790d 100644 --- a/flang/include/flang/Semantics/type.h +++ b/flang/include/flang/Semantics/type.h @@ -306,7 +306,7 @@ class DerivedTypeSpec { } // 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/Decimal/decimal-to-binary.cpp b/flang/lib/Decimal/decimal-to-binary.cpp index d38af0f9b8005..c5cdb72e355f6 100644 --- a/flang/lib/Decimal/decimal-to-binary.cpp +++ b/flang/lib/Decimal/decimal-to-binary.cpp @@ -14,6 +14,7 @@ #include #include #include +#include namespace Fortran::decimal { @@ -275,7 +276,12 @@ ConversionToBinaryResult IntermediateFloat::ToBinary( if (guard != 0) { flags |= Underflow; } - return {Binary{}, static_cast(flags)}; + Binary zero; + if (isNegative) { + zero.Negate(); + } + return { + std::move(zero), static_cast(flags)}; } } } else { diff --git a/flang/lib/Evaluate/characteristics.cpp b/flang/lib/Evaluate/characteristics.cpp index 80b0f346c32d3..688a856220a11 100644 --- a/flang/lib/Evaluate/characteristics.cpp +++ b/flang/lib/Evaluate/characteristics.cpp @@ -25,6 +25,7 @@ using namespace Fortran::parser::literals; namespace Fortran::evaluate::characteristics { // Copy attributes from a symbol to dst based on the mapping in pairs. +// An ASYNCHRONOUS attribute counts even if it is implied. template static void CopyAttrs(const semantics::Symbol &src, A &dst, const std::initializer_list> &pairs) { @@ -533,7 +534,8 @@ bool DummyProcedure::IsCompatibleWith( } return false; } - if (!procedure.value().IsCompatibleWith(actual.procedure.value(), whyNot)) { + if (!procedure.value().IsCompatibleWith(actual.procedure.value(), + /*ignoreImplicitVsExplicit=*/false, whyNot)) { if (whyNot) { *whyNot = "incompatible dummy procedure interfaces: "s + *whyNot; } @@ -1206,7 +1208,8 @@ bool FunctionResult::IsCompatibleWith( CHECK(ifaceProc != nullptr); if (const auto *actualProc{ std::get_if>(&actual.u)}) { - if (ifaceProc->value().IsCompatibleWith(actualProc->value(), whyNot)) { + if (ifaceProc->value().IsCompatibleWith(actualProc->value(), + /*ignoreImplicitVsExplicit=*/false, whyNot)) { return true; } if (whyNot) { @@ -1251,7 +1254,8 @@ bool Procedure::operator==(const Procedure &that) const { cudaSubprogramAttrs == that.cudaSubprogramAttrs; } -bool Procedure::IsCompatibleWith(const Procedure &actual, std::string *whyNot, +bool Procedure::IsCompatibleWith(const Procedure &actual, + bool ignoreImplicitVsExplicit, std::string *whyNot, const SpecificIntrinsic *specificIntrinsic, std::optional *warning) const { // 15.5.2.9(1): if dummy is not pure, actual need not be. @@ -1265,6 +1269,9 @@ bool Procedure::IsCompatibleWith(const Procedure &actual, std::string *whyNot, } Attrs differences{attrs ^ actualAttrs}; differences.reset(Attr::Subroutine); // dealt with specifically later + if (ignoreImplicitVsExplicit) { + differences.reset(Attr::ImplicitInterface); + } if (!differences.empty()) { if (whyNot) { auto sep{": "s}; diff --git a/flang/lib/Evaluate/check-expression.cpp b/flang/lib/Evaluate/check-expression.cpp index 14abac5ff9ba8..0e7d97900328b 100644 --- a/flang/lib/Evaluate/check-expression.cpp +++ b/flang/lib/Evaluate/check-expression.cpp @@ -250,6 +250,8 @@ class IsInitialDataTargetHelper } } return false; + } else if (!CheckVarOrComponent(ultimate)) { + return false; } else if (!ultimate.attrs().test(semantics::Attr::TARGET)) { if (messages_) { messages_->Say( @@ -267,7 +269,7 @@ class IsInitialDataTargetHelper } return false; } else { - return CheckVarOrComponent(ultimate); + return true; } } bool operator()(const StaticDataObject &) const { return false; } @@ -318,24 +320,23 @@ class IsInitialDataTargetHelper 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/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp index 61bf0f2b48ad8..9b98d22cc58e5 100644 --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -1120,6 +1120,12 @@ static const SpecificIntrinsicInterface specificIntrinsicFunction[]{ {{"iiabs", {{"a", TypePattern{IntType, KindCode::exactKind, 2}}}, TypePattern{IntType, KindCode::exactKind, 2}}, "abs"}, + // The definition of the unrestricted specific intrinsic function INDEX + // in F'77 and F'90 has only two arguments; later standards omit the + // argument information for all unrestricted specific intrinsic + // procedures. No compiler supports an implementation that allows + // INDEX with BACK= to work when associated as an actual procedure or + // procedure pointer target. {{"index", {{"string", DefaultChar}, {"substring", DefaultChar}}, DefaultInt}}, {{"isign", {{"a", DefaultInt}, {"b", DefaultInt}}, DefaultInt}, "sign"}, @@ -2505,6 +2511,8 @@ class IntrinsicProcTable::Implementation { std::multimap subroutines_; const semantics::Scope *builtinsScope_{nullptr}; std::map aliases_; + semantics::ParamValue assumedLen_{ + semantics::ParamValue::Assumed(common::TypeParamAttr::Len)}; }; bool IntrinsicProcTable::Implementation::IsIntrinsicFunction( @@ -2627,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, @@ -2668,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); @@ -3241,6 +3262,10 @@ DynamicType IntrinsicProcTable::Implementation::GetSpecificType( TypeCategory category{set.LeastElement().value()}; if (pattern.kindCode == KindCode::doublePrecision) { return DynamicType{category, defaults_.doublePrecisionKind()}; + } else if (category == TypeCategory::Character) { + // All character arguments to specific intrinsic functions are + // assumed-length. + return DynamicType{defaults_.GetDefaultKind(category), assumedLen_}; } else { return DynamicType{category, defaults_.GetDefaultKind(category)}; } diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp index 131bbd97ce163..e7fc651b9173f 100644 --- a/flang/lib/Evaluate/tools.cpp +++ b/flang/lib/Evaluate/tools.cpp @@ -1083,7 +1083,7 @@ std::optional CheckProcCompatibility(bool isCall, const std::optional &lhsProcedure, const characteristics::Procedure *rhsProcedure, const SpecificIntrinsic *specificIntrinsic, std::string &whyNotCompatible, - std::optional &warning) { + std::optional &warning, bool ignoreImplicitVsExplicit) { std::optional msg; if (!lhsProcedure) { msg = "In assignment to object %s, the target '%s' is a procedure" @@ -1097,8 +1097,9 @@ std::optional CheckProcCompatibility(bool isCall, *rhsProcedure->functionResult, &whyNotCompatible)) { msg = "Function %s associated with incompatible function designator '%s': %s"_err_en_US; - } else if (lhsProcedure->IsCompatibleWith(*rhsProcedure, &whyNotCompatible, - specificIntrinsic, &warning)) { + } else if (lhsProcedure->IsCompatibleWith(*rhsProcedure, + ignoreImplicitVsExplicit, &whyNotCompatible, specificIntrinsic, + &warning)) { // OK } else if (isCall) { msg = "Procedure %s associated with result of reference to function '%s'" diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index f865b53f74deb..8048693119b4c 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -1000,6 +1000,17 @@ class FirConverter : public Fortran::lower::AbstractConverter { if (sym.detailsIf()) return symMap->lookupSymbol(sym); + // For symbols to be privatized in OMP, the symbol is mapped to an + // instance of `SymbolBox::Intrinsic` (i.e. a direct mapping to an MLIR + // SSA value). This MLIR SSA value is the block argument to the + // `omp.private`'s `alloc` block. If this is the case, we return this + // `SymbolBox::Intrinsic` value. + if (Fortran::lower::SymbolBox v = symMap->lookupSymbol(sym)) + return v.match( + [&](const Fortran::lower::SymbolBox::Intrinsic &) + -> Fortran::lower::SymbolBox { return v; }, + [](const auto &) -> Fortran::lower::SymbolBox { return {}; }); + return {}; } if (Fortran::lower::SymbolBox v = symMap->lookupSymbol(sym)) @@ -1018,7 +1029,7 @@ class FirConverter : public Fortran::lower::AbstractConverter { /// Find the symbol in one level up of symbol map such as for host-association /// in OpenMP code or return null. Fortran::lower::SymbolBox - lookupOneLevelUpSymbol(const Fortran::semantics::Symbol &sym) { + lookupOneLevelUpSymbol(const Fortran::semantics::Symbol &sym) override { if (Fortran::lower::SymbolBox v = localSymbols.lookupOneLevelUpSymbol(sym)) return v; return {}; @@ -2622,6 +2633,9 @@ class FirConverter : public Fortran::lower::AbstractConverter { 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); @@ -4477,7 +4491,16 @@ class FirConverter : public Fortran::lower::AbstractConverter { assert(builder && "FirOpBuilder did not instantiate"); builder->setFastMathFlags(bridge.getLoweringOptions().getMathOptions()); builder->setInsertionPointToStart(&func.front()); - func.setVisibility(mlir::SymbolTable::Visibility::Public); + if (funit.parent.isA()) { + // Give internal linkage to internal functions. There are no name clash + // risks, but giving global linkage to internal procedure will break the + // static link register in shared libraries because of the system calls. + // Also, it should be possible to eliminate the procedure code if all the + // uses have been inlined. + fir::factory::setInternalLinkage(func); + } else { + func.setVisibility(mlir::SymbolTable::Visibility::Public); + } assert(blockId == 0 && "invalid blockId"); assert(activeConstructStack.empty() && "invalid construct stack state"); @@ -5151,6 +5174,13 @@ class FirConverter : public Fortran::lower::AbstractConverter { /// 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(), @@ -5207,6 +5237,13 @@ class FirConverter : public Fortran::lower::AbstractConverter { /// 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 baf08b58a91b3..6e3ce101ef1af 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 68ecaa19d2d5d..731c5072c45c5 100644 --- a/flang/lib/Lower/ConvertExprToHLFIR.cpp +++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp @@ -1844,6 +1844,16 @@ class HlfirBuilder { 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/HostAssociations.cpp b/flang/lib/Lower/HostAssociations.cpp index 44cc0e74e3b52..b9e13ccad1c92 100644 --- a/flang/lib/Lower/HostAssociations.cpp +++ b/flang/lib/Lower/HostAssociations.cpp @@ -376,9 +376,9 @@ class CapturedArrays : public CapturedSymbols { const Fortran::semantics::Symbol &sym) { mlir::Type type = converter.genType(sym); bool isPolymorphic = Fortran::semantics::IsPolymorphic(sym); - assert(type.isa() || - (isPolymorphic && type.isa()) && - "must be a sequence type"); + assert((type.isa() || + (isPolymorphic && type.isa())) && + "must be a sequence type"); if (isPolymorphic) return type; return fir::BoxType::get(type); diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp index 136bda0b582ee..717b8cc0276a3 100644 --- a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp +++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp @@ -14,6 +14,7 @@ #include "Utils.h" #include "flang/Lower/PFTBuilder.h" +#include "flang/Lower/SymbolMap.h" #include "flang/Optimizer/Builder/Todo.h" #include "flang/Semantics/tools.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" @@ -66,9 +67,10 @@ void DataSharingProcessor::cloneSymbol(const Fortran::semantics::Symbol *sym) { } void DataSharingProcessor::copyFirstPrivateSymbol( - const Fortran::semantics::Symbol *sym) { + const Fortran::semantics::Symbol *sym, + mlir::OpBuilder::InsertPoint *copyAssignIP) { if (sym->test(Fortran::semantics::Symbol::Flag::OmpFirstPrivate)) - converter.copyHostAssociateVar(*sym); + converter.copyHostAssociateVar(*sym, copyAssignIP); } void DataSharingProcessor::copyLastPrivateSymbol( @@ -307,14 +309,10 @@ void DataSharingProcessor::privatize() { for (const Fortran::semantics::Symbol *sym : privatizedSymbols) { if (const auto *commonDet = sym->detailsIf()) { - for (const auto &mem : commonDet->objects()) { - cloneSymbol(&*mem); - copyFirstPrivateSymbol(&*mem); - } - } else { - cloneSymbol(sym); - copyFirstPrivateSymbol(sym); - } + for (const auto &mem : commonDet->objects()) + doPrivatize(&*mem); + } else + doPrivatize(sym); } } @@ -338,11 +336,95 @@ void DataSharingProcessor::defaultPrivatize() { !sym->GetUltimate().has() && !symbolsInNestedRegions.contains(sym) && !symbolsInParentRegions.contains(sym) && - !privatizedSymbols.contains(sym)) { + !privatizedSymbols.contains(sym)) + doPrivatize(sym); + } +} + +void DataSharingProcessor::doPrivatize(const Fortran::semantics::Symbol *sym) { + if (!useDelayedPrivatization) { + cloneSymbol(sym); + copyFirstPrivateSymbol(sym); + return; + } + + Fortran::lower::SymbolBox hsb = converter.lookupOneLevelUpSymbol(*sym); + assert(hsb && "Host symbol box not found"); + + mlir::Type symType = hsb.getAddr().getType(); + mlir::Location symLoc = hsb.getAddr().getLoc(); + std::string privatizerName = sym->name().ToString() + ".privatizer"; + bool isFirstPrivate = + sym->test(Fortran::semantics::Symbol::Flag::OmpFirstPrivate); + + mlir::omp::PrivateClauseOp privatizerOp = [&]() { + auto moduleOp = firOpBuilder.getModule(); + auto uniquePrivatizerName = fir::getTypeAsString( + symType, converter.getKindMap(), + converter.mangleName(*sym) + + (isFirstPrivate ? "_firstprivate" : "_private")); + + if (auto existingPrivatizer = + moduleOp.lookupSymbol( + uniquePrivatizerName)) + return existingPrivatizer; + + auto ip = firOpBuilder.saveInsertionPoint(); + firOpBuilder.setInsertionPoint(&moduleOp.getBodyRegion().front(), + moduleOp.getBodyRegion().front().begin()); + auto result = firOpBuilder.create( + symLoc, uniquePrivatizerName, symType, + isFirstPrivate ? mlir::omp::DataSharingClauseType::FirstPrivate + : mlir::omp::DataSharingClauseType::Private); + + symTable->pushScope(); + + // Populate the `alloc` region. + { + mlir::Region &allocRegion = result.getAllocRegion(); + mlir::Block *allocEntryBlock = firOpBuilder.createBlock( + &allocRegion, /*insertPt=*/{}, symType, symLoc); + + firOpBuilder.setInsertionPointToEnd(allocEntryBlock); + symTable->addSymbol(*sym, allocRegion.getArgument(0)); + symTable->pushScope(); cloneSymbol(sym); - copyFirstPrivateSymbol(sym); + firOpBuilder.create( + hsb.getAddr().getLoc(), + symTable->shallowLookupSymbol(*sym).getAddr()); + symTable->popScope(); } - } + + // Populate the `copy` region if this is a `firstprivate`. + if (isFirstPrivate) { + mlir::Region ©Region = result.getCopyRegion(); + // First block argument corresponding to the original/host value while + // second block argument corresponding to the privatized value. + mlir::Block *copyEntryBlock = firOpBuilder.createBlock( + ©Region, /*insertPt=*/{}, {symType, symType}, {symLoc, symLoc}); + firOpBuilder.setInsertionPointToEnd(copyEntryBlock); + symTable->addSymbol(*sym, copyRegion.getArgument(0), + /*force=*/true); + symTable->pushScope(); + symTable->addSymbol(*sym, copyRegion.getArgument(1)); + auto ip = firOpBuilder.saveInsertionPoint(); + copyFirstPrivateSymbol(sym, &ip); + + firOpBuilder.create( + hsb.getAddr().getLoc(), + symTable->shallowLookupSymbol(*sym).getAddr()); + symTable->popScope(); + } + + symTable->popScope(); + firOpBuilder.restoreInsertionPoint(ip); + return result; + }(); + + delayedPrivatizationInfo.privatizers.push_back( + mlir::SymbolRefAttr::get(privatizerOp)); + delayedPrivatizationInfo.originalAddresses.push_back(hsb.getAddr()); + delayedPrivatizationInfo.symbols.push_back(sym); } } // namespace omp diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.h b/flang/lib/Lower/OpenMP/DataSharingProcessor.h index 10c0a30c09c39..9f7301df07598 100644 --- a/flang/lib/Lower/OpenMP/DataSharingProcessor.h +++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.h @@ -23,6 +23,24 @@ namespace lower { namespace omp { class DataSharingProcessor { +public: + /// Collects all the information needed for delayed privatization. This can be + /// used by ops with data-sharing clauses to properly generate their regions + /// (e.g. add region arguments) and map the original SSA values to their + /// corresponding OMP region operands. + struct DelayedPrivatizationInfo { + // The list of symbols referring to delayed privatizer ops (i.e. + // `omp.private` ops). + llvm::SmallVector privatizers; + // SSA values that correspond to "original" values being privatized. + // "Original" here means the SSA value outside the OpenMP region from which + // a clone is created inside the region. + llvm::SmallVector originalAddresses; + // Fortran symbols corresponding to the above SSA values. + llvm::SmallVector symbols; + }; + +private: bool hasLastPrivateOp; mlir::OpBuilder::InsertPoint lastPrivIP; mlir::OpBuilder::InsertPoint insPt; @@ -36,6 +54,9 @@ class DataSharingProcessor { fir::FirOpBuilder &firOpBuilder; const Fortran::parser::OmpClauseList &opClauseList; Fortran::lower::pft::Evaluation &eval; + bool useDelayedPrivatization; + Fortran::lower::SymMap *symTable; + DelayedPrivatizationInfo delayedPrivatizationInfo; bool needBarrier(); void collectSymbols(Fortran::semantics::Symbol::Flag flag); @@ -47,10 +68,13 @@ class DataSharingProcessor { void collectDefaultSymbols(); void privatize(); void defaultPrivatize(); + void doPrivatize(const Fortran::semantics::Symbol *sym); void copyLastPrivatize(mlir::Operation *op); void insertLastPrivateCompare(mlir::Operation *op); void cloneSymbol(const Fortran::semantics::Symbol *sym); - void copyFirstPrivateSymbol(const Fortran::semantics::Symbol *sym); + void + copyFirstPrivateSymbol(const Fortran::semantics::Symbol *sym, + mlir::OpBuilder::InsertPoint *copyAssignIP = nullptr); void copyLastPrivateSymbol(const Fortran::semantics::Symbol *sym, mlir::OpBuilder::InsertPoint *lastPrivIP); void insertDeallocs(); @@ -58,10 +82,14 @@ class DataSharingProcessor { public: DataSharingProcessor(Fortran::lower::AbstractConverter &converter, const Fortran::parser::OmpClauseList &opClauseList, - Fortran::lower::pft::Evaluation &eval) + Fortran::lower::pft::Evaluation &eval, + bool useDelayedPrivatization = false, + Fortran::lower::SymMap *symTable = nullptr) : hasLastPrivateOp(false), converter(converter), firOpBuilder(converter.getFirOpBuilder()), opClauseList(opClauseList), - eval(eval) {} + eval(eval), useDelayedPrivatization(useDelayedPrivatization), + symTable(symTable) {} + // Privatisation is split into two steps. // Step1 performs cloning of all privatisation clauses and copying for // firstprivates. Step1 is performed at the place where process/processStep1 @@ -80,6 +108,10 @@ class DataSharingProcessor { assert(!loopIV && "Loop iteration variable already set"); loopIV = iv; } + + const DelayedPrivatizationInfo &getDelayedPrivatizationInfo() const { + return delayedPrivatizationInfo; + } }; } // namespace omp diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 7953bf83cba0f..185e0316870e9 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -558,6 +558,7 @@ genOrderedRegionOp(Fortran::lower::AbstractConverter &converter, static mlir::omp::ParallelOp genParallelOp(Fortran::lower::AbstractConverter &converter, + Fortran::lower::SymMap &symTable, Fortran::semantics::SemanticsContext &semaCtx, Fortran::lower::pft::Evaluation &eval, bool genNested, mlir::Location currentLocation, @@ -590,8 +591,8 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, auto reductionCallback = [&](mlir::Operation *op) { llvm::SmallVector locs(reductionVars.size(), currentLocation); - auto block = converter.getFirOpBuilder().createBlock(&op->getRegion(0), {}, - reductionTypes, locs); + auto *block = converter.getFirOpBuilder().createBlock(&op->getRegion(0), {}, + reductionTypes, locs); for (auto [arg, prv] : llvm::zip_equal(reductionSymbols, block->getArguments())) { converter.bindSymbol(*arg, prv); @@ -599,13 +600,78 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, return reductionSymbols; }; - return genOpWithBody( + OpWithBodyGenInfo genInfo = OpWithBodyGenInfo(converter, semaCtx, currentLocation, eval) .setGenNested(genNested) .setOuterCombined(outerCombined) .setClauses(&clauseList) .setReductions(&reductionSymbols, &reductionTypes) - .setGenRegionEntryCb(reductionCallback), + .setGenRegionEntryCb(reductionCallback); + + if (!enableDelayedPrivatization) { + return genOpWithBody( + genInfo, + /*resultTypes=*/mlir::TypeRange(), ifClauseOperand, + numThreadsClauseOperand, allocateOperands, allocatorOperands, + reductionVars, + reductionDeclSymbols.empty() + ? nullptr + : mlir::ArrayAttr::get(converter.getFirOpBuilder().getContext(), + reductionDeclSymbols), + procBindKindAttr, /*private_vars=*/llvm::SmallVector{}, + /*privatizers=*/nullptr); + } + + bool privatize = !outerCombined; + DataSharingProcessor dsp(converter, clauseList, eval, + /*useDelayedPrivatization=*/true, &symTable); + + if (privatize) + dsp.processStep1(); + + const auto &delayedPrivatizationInfo = dsp.getDelayedPrivatizationInfo(); + + auto genRegionEntryCB = [&](mlir::Operation *op) { + auto parallelOp = llvm::cast(op); + + llvm::SmallVector reductionLocs(reductionVars.size(), + currentLocation); + + mlir::OperandRange privateVars = parallelOp.getPrivateVars(); + mlir::Region ®ion = parallelOp.getRegion(); + + llvm::SmallVector privateVarTypes = reductionTypes; + privateVarTypes.reserve(privateVarTypes.size() + privateVars.size()); + llvm::transform(privateVars, std::back_inserter(privateVarTypes), + [](mlir::Value v) { return v.getType(); }); + + llvm::SmallVector privateVarLocs = reductionLocs; + privateVarLocs.reserve(privateVarLocs.size() + privateVars.size()); + llvm::transform(privateVars, std::back_inserter(privateVarLocs), + [](mlir::Value v) { return v.getLoc(); }); + + converter.getFirOpBuilder().createBlock(®ion, /*insertPt=*/{}, + privateVarTypes, privateVarLocs); + + llvm::SmallVector allSymbols = + reductionSymbols; + allSymbols.append(delayedPrivatizationInfo.symbols); + for (auto [arg, prv] : llvm::zip_equal(allSymbols, region.getArguments())) { + converter.bindSymbol(*arg, prv); + } + + return allSymbols; + }; + + // TODO Merge with the reduction CB. + genInfo.setGenRegionEntryCb(genRegionEntryCB).setDataSharingProcessor(&dsp); + + llvm::SmallVector privatizers( + delayedPrivatizationInfo.privatizers.begin(), + delayedPrivatizationInfo.privatizers.end()); + + return genOpWithBody( + genInfo, /*resultTypes=*/mlir::TypeRange(), ifClauseOperand, numThreadsClauseOperand, allocateOperands, allocatorOperands, reductionVars, @@ -613,8 +679,11 @@ genParallelOp(Fortran::lower::AbstractConverter &converter, ? nullptr : mlir::ArrayAttr::get(converter.getFirOpBuilder().getContext(), reductionDeclSymbols), - procBindKindAttr, /*private_vars=*/llvm::SmallVector{}, - /*privatizers=*/nullptr); + procBindKindAttr, delayedPrivatizationInfo.originalAddresses, + delayedPrivatizationInfo.privatizers.empty() + ? nullptr + : mlir::ArrayAttr::get(converter.getFirOpBuilder().getContext(), + privatizers)); } static mlir::omp::SectionOp @@ -771,7 +840,8 @@ genEnterExitUpdateDataOp(Fortran::lower::AbstractConverter &converter, llvm::SmallVector dependTypeOperands; Fortran::parser::OmpIfClause::DirectiveNameModifier directiveName; - llvm::omp::Directive directive; + // GCC 9.3.0 emits a (probably) bogus warning about an unused variable. + [[maybe_unused]] llvm::omp::Directive directive; if constexpr (std::is_same_v) { directiveName = Fortran::parser::OmpIfClause::DirectiveNameModifier::TargetEnterData; @@ -1168,6 +1238,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, @@ -1175,7 +1270,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); @@ -1183,10 +1278,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; } @@ -1621,7 +1716,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, if ((llvm::omp::allParallelSet & llvm::omp::loopConstructSet) .test(ompDirective)) { validDirective = true; - genParallelOp(converter, semaCtx, eval, /*genNested=*/false, + genParallelOp(converter, symTable, semaCtx, eval, /*genNested=*/false, currentLocation, loopOpClauseList, /*outerCombined=*/true); } @@ -1711,8 +1806,8 @@ genOMP(Fortran::lower::AbstractConverter &converter, currentLocation); break; case llvm::omp::Directive::OMPD_parallel: - genParallelOp(converter, semaCtx, eval, /*genNested=*/true, currentLocation, - beginClauseList); + genParallelOp(converter, symTable, semaCtx, eval, /*genNested=*/true, + currentLocation, beginClauseList); break; case llvm::omp::Directive::OMPD_single: genSingleOp(converter, semaCtx, eval, /*genNested=*/true, currentLocation, @@ -1740,7 +1835,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; @@ -1769,13 +1868,14 @@ genOMP(Fortran::lower::AbstractConverter &converter, .test(directive.v)) { bool outerCombined = directive.v != llvm::omp::Directive::OMPD_target_parallel; - genParallelOp(converter, semaCtx, eval, /*genNested=*/false, + genParallelOp(converter, symTable, semaCtx, eval, /*genNested=*/false, currentLocation, beginClauseList, outerCombined); combinedDirective = true; } 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) @@ -1852,7 +1952,7 @@ genOMP(Fortran::lower::AbstractConverter &converter, // Parallel wrapper of PARALLEL SECTIONS construct if (dir == llvm::omp::Directive::OMPD_parallel_sections) { - genParallelOp(converter, semaCtx, eval, + genParallelOp(converter, symTable, semaCtx, eval, /*genNested=*/false, currentLocation, sectionsClauseList, /*outerCombined=*/true); } else { @@ -1932,56 +2032,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); } } @@ -2440,6 +2540,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, @@ -2458,6 +2576,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.cpp b/flang/lib/Lower/OpenMP/Utils.cpp index 31b15257d1868..49517f62895df 100644 --- a/flang/lib/Lower/OpenMP/Utils.cpp +++ b/flang/lib/Lower/OpenMP/Utils.cpp @@ -24,6 +24,12 @@ llvm::cl::opt treatIndexAsSection( llvm::cl::desc("In the OpenMP data clauses treat `a(N)` as `a(N:N)`."), llvm::cl::init(true)); +llvm::cl::opt enableDelayedPrivatization( + "openmp-enable-delayed-privatization", + llvm::cl::desc( + "Emit `[first]private` variables as clauses on the MLIR ops."), + llvm::cl::init(false)); + namespace Fortran { namespace lower { namespace omp { diff --git a/flang/lib/Lower/OpenMP/Utils.h b/flang/lib/Lower/OpenMP/Utils.h index c346f891f0797..76a15e8bcaab9 100644 --- a/flang/lib/Lower/OpenMP/Utils.h +++ b/flang/lib/Lower/OpenMP/Utils.h @@ -15,6 +15,7 @@ #include "llvm/Support/CommandLine.h" extern llvm::cl::opt treatIndexAsSection; +extern llvm::cl::opt enableDelayedPrivatization; namespace fir { class FirOpBuilder; @@ -39,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 3cce39f5b8c78..788c99e40105a 100644 --- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp +++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp @@ -18,6 +18,7 @@ #include "flang/Optimizer/Dialect/FIROpsSupport.h" #include "flang/Optimizer/Support/FatalError.h" #include "flang/Optimizer/Support/InternalNames.h" +#include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/Dialect/OpenACC/OpenACC.h" #include "mlir/Dialect/OpenMP/OpenMPDialect.h" #include "llvm/ADT/ArrayRef.h" @@ -1533,3 +1534,10 @@ mlir::Value fir::factory::createNullBoxProc(fir::FirOpBuilder &builder, mlir::Value initVal{builder.create(loc, boxEleTy)}; return builder.create(loc, boxTy, initVal); } + +void fir::factory::setInternalLinkage(mlir::func::FuncOp func) { + auto internalLinkage = mlir::LLVM::linkage::Linkage::Internal; + auto linkage = + mlir::LLVM::LinkageAttr::get(func->getContext(), internalLinkage); + func->setAttr("llvm.linkage", linkage); +} diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index c84fb27cb38da..25598ed168316 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -689,22 +689,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 +926,10 @@ 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>>; static constexpr MathOperation mathOperations[] = { {"abs", "fabsf", genFuncType, Ty::Real<4>>, @@ -944,6 +948,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 +957,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 +980,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 +989,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 +998,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 +1013,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 +1054,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 +1100,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 +1153,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 +1202,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}, @@ -1222,11 +1248,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 +1266,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 +1277,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 +1288,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. @@ -1834,10 +1870,7 @@ mlir::func::FuncOp IntrinsicLibrary::getWrapper(GeneratorType generator, // First time this wrapper is needed, build it. function = builder.createFunction(loc, wrapperName, funcType); function->setAttr("fir.intrinsic", builder.getUnitAttr()); - auto internalLinkage = mlir::LLVM::linkage::Linkage::Internal; - auto linkage = - mlir::LLVM::LinkageAttr::get(builder.getContext(), internalLinkage); - function->setAttr("llvm.linkage", linkage); + fir::factory::setInternalLinkage(function); function.addEntryBlock(); // Create local context to emit code into the newly created function @@ -4198,39 +4231,45 @@ mlir::Value IntrinsicLibrary::genIeeeLogb(mlir::Type resultType, builder.create(loc, intType, realVal); mlir::Type i1Ty = builder.getI1Type(); - int exponentBias, significandSize; + int exponentBias, significandSize, nonSignificandSize; switch (bitWidth) { case 16: if (realType.isF16()) { // kind=2: 1 sign bit, 5 exponent bits, 10 significand bits exponentBias = (1 << (5 - 1)) - 1; // 15 significandSize = 10; + nonSignificandSize = 6; break; } assert(realType.isBF16() && "unknown 16-bit real type"); // kind=3: 1 sign bit, 8 exponent bits, 7 significand bits exponentBias = (1 << (8 - 1)) - 1; // 127 significandSize = 7; + nonSignificandSize = 9; break; case 32: // kind=4: 1 sign bit, 8 exponent bits, 23 significand bits exponentBias = (1 << (8 - 1)) - 1; // 127 significandSize = 23; + nonSignificandSize = 9; break; case 64: // kind=8: 1 sign bit, 11 exponent bits, 52 significand bits exponentBias = (1 << (11 - 1)) - 1; // 1023 significandSize = 52; + nonSignificandSize = 12; break; case 80: // kind=10: 1 sign bit, 15 exponent bits, 1+63 significand bits exponentBias = (1 << (15 - 1)) - 1; // 16383 significandSize = 64; + nonSignificandSize = 16 + 1; break; case 128: // kind=16: 1 sign bit, 15 exponent bits, 112 significand bits exponentBias = (1 << (15 - 1)) - 1; // 16383 significandSize = 112; + nonSignificandSize = 16; break; default: llvm_unreachable("unknown real type"); @@ -4262,6 +4301,11 @@ mlir::Value IntrinsicLibrary::genIeeeLogb(mlir::Type resultType, /*withElseRegion=*/true); // X is non-zero finite -- result is unbiased exponent of X builder.setInsertionPointToStart(&innerIfOp.getThenRegion().front()); + mlir::Value isNormal = genIsFPClass(i1Ty, args, normalTest); + auto normalIfOp = builder.create(loc, resultType, isNormal, + /*withElseRegion=*/true); + // X is normal + builder.setInsertionPointToStart(&normalIfOp.getThenRegion().front()); mlir::Value biasedExponent = builder.create( loc, shiftLeftOne, builder.createIntegerConstant(loc, intType, significandSize + 1)); @@ -4271,6 +4315,23 @@ mlir::Value IntrinsicLibrary::genIeeeLogb(mlir::Type resultType, result = builder.create(loc, resultType, result); builder.create(loc, result); + // X is denormal -- result is (-exponentBias - ctlz(significand)) + builder.setInsertionPointToStart(&normalIfOp.getElseRegion().front()); + mlir::Value significand = builder.create( + loc, intVal, + builder.createIntegerConstant(loc, intType, nonSignificandSize)); + mlir::Value ctlz = + builder.create(loc, significand); + mlir::Type i32Ty = builder.getI32Type(); + result = builder.create( + loc, builder.createIntegerConstant(loc, i32Ty, -exponentBias), + builder.create(loc, i32Ty, ctlz)); + result = builder.create(loc, resultType, result); + builder.create(loc, result); + + builder.setInsertionPointToEnd(&innerIfOp.getThenRegion().front()); + builder.create(loc, normalIfOp.getResult(0)); + // X is infinity or NaN -- result is +infinity or NaN builder.setInsertionPointToStart(&innerIfOp.getElseRegion().front()); result = builder.create(loc, shiftLeftOne, one); diff --git a/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp b/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp index fabbff818b6f0..66fbaddcbda1a 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Reduction.cpp @@ -149,6 +149,22 @@ struct ForcedNorm2Real16 { } }; +/// Placeholder for real*16 version of Norm2Dim Intrinsic +struct ForcedNorm2DimReal16 { + static constexpr const char *name = ExpandAndQuoteKey(RTNAME(Norm2DimReal16)); + static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() { + return [](mlir::MLIRContext *ctx) { + auto boxTy = + fir::runtime::getModel()(ctx); + auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8)); + auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int)); + return mlir::FunctionType::get( + ctx, {fir::ReferenceType::get(boxTy), boxTy, intTy, strTy, intTy}, + mlir::NoneType::get(ctx)); + }; + } +}; + /// Placeholder for real*10 version of Product Intrinsic struct ForcedProductReal10 { static constexpr const char *name = ExpandAndQuoteKey(RTNAME(ProductReal10)); @@ -876,7 +892,14 @@ mlir::Value fir::runtime::genMinval(fir::FirOpBuilder &builder, void fir::runtime::genNorm2Dim(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value resultBox, mlir::Value arrayBox, mlir::Value dim) { - auto func = fir::runtime::getRuntimeFunc(loc, builder); + mlir::func::FuncOp func; + auto ty = arrayBox.getType(); + auto arrTy = fir::dyn_cast_ptrOrBoxEleTy(ty); + auto eleTy = arrTy.cast().getEleTy(); + if (eleTy.isF128()) + func = fir::runtime::getRuntimeFunc(loc, builder); + else + func = fir::runtime::getRuntimeFunc(loc, builder); auto fTy = func.getFunctionType(); auto sourceFile = fir::factory::locationToFilename(builder, loc); auto sourceLine = diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index 7fdf39a1af731..f81a08388da72 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -3937,30 +3937,7 @@ class FIRToLLVMLowering options.applyTBAA || applyTBAA, options.forceUnifiedTBAATree, *dl}; mlir::RewritePatternSet pattern(context); - pattern.insert< - AbsentOpConversion, AddcOpConversion, AddrOfOpConversion, - AllocaOpConversion, AllocMemOpConversion, BoxAddrOpConversion, - BoxCharLenOpConversion, BoxDimsOpConversion, BoxEleSizeOpConversion, - BoxIsAllocOpConversion, BoxIsArrayOpConversion, BoxIsPtrOpConversion, - BoxOffsetOpConversion, BoxProcHostOpConversion, BoxRankOpConversion, - BoxTypeCodeOpConversion, BoxTypeDescOpConversion, CallOpConversion, - CmpcOpConversion, ConstcOpConversion, ConvertOpConversion, - CoordinateOpConversion, DTEntryOpConversion, DivcOpConversion, - EmboxOpConversion, EmboxCharOpConversion, EmboxProcOpConversion, - ExtractValueOpConversion, FieldIndexOpConversion, FirEndOpConversion, - FreeMemOpConversion, GlobalLenOpConversion, GlobalOpConversion, - HasValueOpConversion, InsertOnRangeOpConversion, - InsertValueOpConversion, IsPresentOpConversion, - LenParamIndexOpConversion, LoadOpConversion, MulcOpConversion, - NegcOpConversion, NoReassocOpConversion, SelectCaseOpConversion, - SelectOpConversion, SelectRankOpConversion, SelectTypeOpConversion, - ShapeOpConversion, ShapeShiftOpConversion, ShiftOpConversion, - SliceOpConversion, StoreOpConversion, StringLitOpConversion, - SubcOpConversion, TypeDescOpConversion, TypeInfoOpConversion, - UnboxCharOpConversion, UnboxProcOpConversion, UndefOpConversion, - UnreachableOpConversion, UnrealizedConversionCastOpConversion, - XArrayCoorOpConversion, XEmboxOpConversion, XReboxOpConversion, - ZeroOpConversion>(typeConverter, options); + fir::populateFIRToLLVMConversionPatterns(typeConverter, pattern, options); mlir::populateFuncToLLVMConversionPatterns(typeConverter, pattern); mlir::populateOpenMPToLLVMConversionPatterns(typeConverter, pattern); mlir::arith::populateArithToLLVMConversionPatterns(typeConverter, pattern); @@ -4072,3 +4049,32 @@ fir::createLLVMDialectToLLVMPass(llvm::raw_ostream &output, fir::LLVMIRLoweringPrinter printer) { return std::make_unique(output, printer); } + +void fir::populateFIRToLLVMConversionPatterns( + fir::LLVMTypeConverter &converter, mlir::RewritePatternSet &patterns, + fir::FIRToLLVMPassOptions &options) { + patterns.insert< + AbsentOpConversion, AddcOpConversion, AddrOfOpConversion, + AllocaOpConversion, AllocMemOpConversion, BoxAddrOpConversion, + BoxCharLenOpConversion, BoxDimsOpConversion, BoxEleSizeOpConversion, + BoxIsAllocOpConversion, BoxIsArrayOpConversion, BoxIsPtrOpConversion, + BoxOffsetOpConversion, BoxProcHostOpConversion, BoxRankOpConversion, + BoxTypeCodeOpConversion, BoxTypeDescOpConversion, CallOpConversion, + CmpcOpConversion, ConstcOpConversion, ConvertOpConversion, + CoordinateOpConversion, DTEntryOpConversion, DivcOpConversion, + EmboxOpConversion, EmboxCharOpConversion, EmboxProcOpConversion, + ExtractValueOpConversion, FieldIndexOpConversion, FirEndOpConversion, + FreeMemOpConversion, GlobalLenOpConversion, GlobalOpConversion, + HasValueOpConversion, InsertOnRangeOpConversion, InsertValueOpConversion, + IsPresentOpConversion, LenParamIndexOpConversion, LoadOpConversion, + MulcOpConversion, NegcOpConversion, NoReassocOpConversion, + SelectCaseOpConversion, SelectOpConversion, SelectRankOpConversion, + SelectTypeOpConversion, ShapeOpConversion, ShapeShiftOpConversion, + ShiftOpConversion, SliceOpConversion, StoreOpConversion, + StringLitOpConversion, SubcOpConversion, TypeDescOpConversion, + TypeInfoOpConversion, UnboxCharOpConversion, UnboxProcOpConversion, + UndefOpConversion, UnreachableOpConversion, + UnrealizedConversionCastOpConversion, XArrayCoorOpConversion, + XEmboxOpConversion, XReboxOpConversion, ZeroOpConversion>(converter, + options); +} diff --git a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIRIntrinsics.cpp b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIRIntrinsics.cpp index 314e4264c17e8..0142fb0cfb0bb 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIRIntrinsics.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIRIntrinsics.cpp @@ -18,12 +18,12 @@ #include "flang/Optimizer/HLFIR/HLFIROps.h" #include "flang/Optimizer/HLFIR/Passes.h" #include "mlir/IR/BuiltinDialect.h" +#include "mlir/IR/MLIRContext.h" #include "mlir/IR/PatternMatch.h" #include "mlir/Pass/Pass.h" #include "mlir/Pass/PassManager.h" #include "mlir/Support/LogicalResult.h" -#include "mlir/Transforms/DialectConversion.h" -#include +#include "mlir/Transforms/GreedyPatternRewriteDriver.h" #include namespace hlfir { @@ -176,7 +176,7 @@ class HlfirIntrinsicConversion : public mlir::OpRewritePattern { rewriter.eraseOp(use); } } - rewriter.replaceAllUsesWith(op->getResults(), {base}); + rewriter.replaceOp(op, base); } }; @@ -484,19 +484,19 @@ class LowerHLFIRIntrinsics ProductOpConversion, TransposeOpConversion, CountOpConversion, DotProductOpConversion, MaxvalOpConversion, MinvalOpConversion, MinlocOpConversion, MaxlocOpConversion>(context); - mlir::ConversionTarget target(*context); - target.addLegalDialect(); - target.addIllegalOp(); - target.markUnknownOpDynamicallyLegal( - [](mlir::Operation *) { return true; }); - if (mlir::failed( - mlir::applyFullConversion(module, target, std::move(patterns)))) { + + // While conceptually this pass is performing dialect conversion, we use + // pattern rewrites here instead of dialect conversion because this pass + // looses array bounds from some of the expressions e.g. + // !hlfir.expr<2xi32> -> !hlfir.expr + // MLIR thinks this is a different type so dialect conversion fails. + // Pattern rewriting only requires that the resulting IR is still valid + mlir::GreedyRewriteConfig config; + // Prevent the pattern driver from merging blocks + config.enableRegionSimplification = false; + + if (mlir::failed(mlir::applyPatternsAndFoldGreedily( + module, std::move(patterns), config))) { mlir::emitError(mlir::UnknownLoc::get(context), "failure in HLFIR intrinsic lowering"); signalPassFailure(); diff --git a/flang/lib/Optimizer/Transforms/MemoryAllocation.cpp b/flang/lib/Optimizer/Transforms/MemoryAllocation.cpp index f0e201402fa79..166a6b10def29 100644 --- a/flang/lib/Optimizer/Transforms/MemoryAllocation.cpp +++ b/flang/lib/Optimizer/Transforms/MemoryAllocation.cpp @@ -200,7 +200,8 @@ class MemoryAllocationOpt return keepStackAllocation(alloca, &func.front(), options); }); - patterns.insert(context, analysis.getReturns(func)); + llvm::SmallVector returnOps = analysis.getReturns(func); + patterns.insert(context, returnOps); if (mlir::failed( mlir::applyPartialConversion(func, target, std::move(patterns)))) { mlir::emitError(func.getLoc(), diff --git a/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp b/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp index f483651a68dc1..a11aa38c771bd 100644 --- a/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp +++ b/flang/lib/Optimizer/Transforms/SimplifyIntrinsics.cpp @@ -656,7 +656,7 @@ static void genRuntimeMinMaxlocBody(fir::FirOpBuilder &builder, unsigned rank, int maskRank, mlir::Type elementType, mlir::Type maskElemType, - mlir::Type resultElemTy) { + mlir::Type resultElemTy, bool isDim) { auto init = [isMax](fir::FirOpBuilder builder, mlir::Location loc, mlir::Type elementType) { if (auto ty = elementType.dyn_cast()) { @@ -858,16 +858,27 @@ static void genRuntimeMinMaxlocBody(fir::FirOpBuilder &builder, maskElemType, resultArr, maskRank == 0); // Store newly created output array to the reference passed in - fir::SequenceType::Shape resultShape(1, rank); - mlir::Type outputArrTy = fir::SequenceType::get(resultShape, resultElemTy); - mlir::Type outputHeapTy = fir::HeapType::get(outputArrTy); - mlir::Type outputBoxTy = fir::BoxType::get(outputHeapTy); - mlir::Type outputRefTy = builder.getRefType(outputBoxTy); - mlir::Value outputArr = builder.create( - loc, outputRefTy, funcOp.front().getArgument(0)); - - // Store nearly created array to output array - builder.create(loc, resultArr, outputArr); + if (isDim) { + mlir::Type resultBoxTy = + fir::BoxType::get(fir::HeapType::get(resultElemTy)); + mlir::Value outputArr = builder.create( + loc, builder.getRefType(resultBoxTy), funcOp.front().getArgument(0)); + mlir::Value resultArrScalar = builder.create( + loc, fir::HeapType::get(resultElemTy), resultArrInit); + mlir::Value resultBox = + builder.create(loc, resultBoxTy, resultArrScalar); + builder.create(loc, resultBox, outputArr); + } else { + fir::SequenceType::Shape resultShape(1, rank); + mlir::Type outputArrTy = fir::SequenceType::get(resultShape, resultElemTy); + mlir::Type outputHeapTy = fir::HeapType::get(outputArrTy); + mlir::Type outputBoxTy = fir::BoxType::get(outputHeapTy); + mlir::Type outputRefTy = builder.getRefType(outputBoxTy); + mlir::Value outputArr = builder.create( + loc, outputRefTy, funcOp.front().getArgument(0)); + builder.create(loc, resultArr, outputArr); + } + builder.create(loc); } @@ -1146,11 +1157,14 @@ void SimplifyIntrinsicsPass::simplifyMinMaxlocReduction( mlir::Operation::operand_range args = call.getArgs(); - mlir::Value back = args[6]; + mlir::SymbolRefAttr callee = call.getCalleeAttr(); + mlir::StringRef funcNameBase = callee.getLeafReference().getValue(); + bool isDim = funcNameBase.ends_with("Dim"); + mlir::Value back = args[isDim ? 7 : 6]; if (isTrueOrNotConstant(back)) return; - mlir::Value mask = args[5]; + mlir::Value mask = args[isDim ? 6 : 5]; mlir::Value maskDef = findMaskDef(mask); // maskDef is set to NULL when the defining op is not one we accept. @@ -1159,10 +1173,8 @@ void SimplifyIntrinsicsPass::simplifyMinMaxlocReduction( if (maskDef == NULL) return; - mlir::SymbolRefAttr callee = call.getCalleeAttr(); - mlir::StringRef funcNameBase = callee.getLeafReference().getValue(); unsigned rank = getDimCount(args[1]); - if (funcNameBase.ends_with("Dim") || !(rank > 0)) + if ((isDim && rank != 1) || !(rank > 0)) return; fir::FirOpBuilder builder{getSimplificationBuilder(call, kindMap)}; @@ -1203,22 +1215,24 @@ void SimplifyIntrinsicsPass::simplifyMinMaxlocReduction( llvm::raw_string_ostream nameOS(funcName); outType.print(nameOS); + if (isDim) + nameOS << '_' << inputType; nameOS << '_' << fmfString; auto typeGenerator = [rank](fir::FirOpBuilder &builder) { return genRuntimeMinlocType(builder, rank); }; auto bodyGenerator = [rank, maskRank, inputType, logicalElemType, outType, - isMax](fir::FirOpBuilder &builder, - mlir::func::FuncOp &funcOp) { + isMax, isDim](fir::FirOpBuilder &builder, + mlir::func::FuncOp &funcOp) { genRuntimeMinMaxlocBody(builder, funcOp, isMax, rank, maskRank, inputType, - logicalElemType, outType); + logicalElemType, outType, isDim); }; mlir::func::FuncOp newFunc = getOrCreateFunction(builder, funcName, typeGenerator, bodyGenerator); builder.create(loc, newFunc, - mlir::ValueRange{args[0], args[1], args[5]}); + mlir::ValueRange{args[0], args[1], mask}); call->dropAllReferences(); call->erase(); } diff --git a/flang/lib/Parser/Fortran-parsers.cpp b/flang/lib/Parser/Fortran-parsers.cpp index 0dd95d69d3c66..fc81a477897a3 100644 --- a/flang/lib/Parser/Fortran-parsers.cpp +++ b/flang/lib/Parser/Fortran-parsers.cpp @@ -1268,9 +1268,13 @@ constexpr auto ignore_tkr{ constexpr auto loopCount{ "DIR$ LOOP COUNT" >> construct( parenthesized(nonemptyList(digitString64)))}; +constexpr auto assumeAligned{"DIR$ ASSUME_ALIGNED" >> + optionalList(construct( + indirect(designator), ":"_tok >> digitString64))}; TYPE_PARSER(beginDirective >> sourced(construct(ignore_tkr) || construct(loopCount) || + construct(assumeAligned) || construct( "DIR$" >> many(construct(name, maybe(("="_tok || ":"_tok) >> digitString64))))) / diff --git a/flang/lib/Parser/provenance.cpp b/flang/lib/Parser/provenance.cpp index 3f185ffeb1b11..55ef67fd6288d 100644 --- a/flang/lib/Parser/provenance.cpp +++ b/flang/lib/Parser/provenance.cpp @@ -167,6 +167,16 @@ void AllSources::AppendSearchPathDirectory(std::string directory) { searchPath_.push_back(directory); } +const SourceFile *AllSources::OpenPath( + std::string path, llvm::raw_ostream &error) { + std::unique_ptr source{std::make_unique(encoding_)}; + if (source->Open(path, error)) { + return ownedSourceFiles_.emplace_back(std::move(source)).get(); + } else { + return nullptr; + } +} + const SourceFile *AllSources::Open(std::string path, llvm::raw_ostream &error, std::optional &&prependPath) { std::unique_ptr source{std::make_unique(encoding_)}; @@ -180,12 +190,10 @@ const SourceFile *AllSources::Open(std::string path, llvm::raw_ostream &error, if (prependPath) { searchPath_.pop_front(); } - if (!found) { - error << "Source file '" << path << "' was not found"; - return nullptr; - } else if (source->Open(*found, error)) { - return ownedSourceFiles_.emplace_back(std::move(source)).get(); + if (found) { + return OpenPath(*found, error); } else { + error << "Source file '" << path << "' was not found"; return nullptr; } } diff --git a/flang/lib/Parser/source.cpp b/flang/lib/Parser/source.cpp index 4b4fed64a1a40..ae834dc241652 100644 --- a/flang/lib/Parser/source.cpp +++ b/flang/lib/Parser/source.cpp @@ -75,6 +75,24 @@ std::optional LocateSourceFile( return std::nullopt; } +std::vector LocateSourceFileAll( + std::string name, const std::vector &searchPath) { + if (name == "-" || llvm::sys::path::is_absolute(name)) { + return {name}; + } + std::vector result; + for (const std::string &dir : searchPath) { + llvm::SmallString<128> path{dir}; + llvm::sys::path::append(path, name); + bool isDir{false}; + auto er = llvm::sys::fs::is_directory(path, isDir); + if (!er && !isDir) { + result.emplace_back(path.str().str()); + } + } + return result; +} + std::size_t RemoveCarriageReturns(llvm::MutableArrayRef buf) { std::size_t wrote{0}; char *buffer{buf.data()}; diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 1df49a688a12a..600aa01999dab 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -1819,6 +1819,11 @@ class UnparseVisitor { [&](const CompilerDirective::LoopCount &lcount) { Walk("!DIR$ LOOP COUNT (", lcount.v, ", ", ")"); }, + [&](const std::list + &assumeAligned) { + Word("!DIR$ ASSUME_ALIGNED "); + Walk(" ", assumeAligned, ", "); + }, [&](const std::list &names) { Walk("!DIR$ ", names, " "); }, @@ -1841,6 +1846,11 @@ class UnparseVisitor { Walk(std::get(x.t)); Walk("=", std::get>(x.t)); } + void Unparse(const CompilerDirective::AssumeAligned &x) { + Walk(std::get>(x.t)); + Put(":"); + Walk(std::get(x.t)); + } // OpenACC Directives & Clauses void Unparse(const AccAtomicCapture &x) { diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp index fdf7805beab7e..3adbd7cc41774 100644 --- a/flang/lib/Semantics/check-call.cpp +++ b/flang/lib/Semantics/check-call.cpp @@ -674,7 +674,7 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, !(dummyIsAssumedShape || dummyIsAssumedRank || (actualIsPointer && dummyIsPointer))) { // C1539 & C1540 messages.Say( - "ASYNCHRONOUS or VOLATILE actual argument that is not simply contiguous may not be associated with a contiguous %s"_err_en_US, + "ASYNCHRONOUS or VOLATILE actual argument that is not simply contiguous may not be associated with a contiguous ASYNCHRONOUS or VOLATILE %s"_err_en_US, dummyName); } } @@ -912,7 +912,7 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy, static void CheckProcedureArg(evaluate::ActualArgument &arg, const characteristics::Procedure &proc, const characteristics::DummyProcedure &dummy, const std::string &dummyName, - SemanticsContext &context) { + SemanticsContext &context, bool ignoreImplicitVsExplicit) { evaluate::FoldingContext &foldingContext{context.foldingContext()}; parser::ContextualMessages &messages{foldingContext.messages()}; auto restorer{ @@ -975,7 +975,8 @@ static void CheckProcedureArg(evaluate::ActualArgument &arg, if (interface.HasExplicitInterface()) { std::string whyNot; std::optional warning; - if (!interface.IsCompatibleWith(argInterface, &whyNot, + if (!interface.IsCompatibleWith(argInterface, + ignoreImplicitVsExplicit, &whyNot, /*specificIntrinsic=*/nullptr, &warning)) { // 15.5.2.9(1): Explicit interfaces must match if (argInterface.HasExplicitInterface()) { @@ -1081,7 +1082,8 @@ static void CheckExplicitInterfaceArg(evaluate::ActualArgument &arg, const characteristics::DummyArgument &dummy, const characteristics::Procedure &proc, SemanticsContext &context, const Scope *scope, const evaluate::SpecificIntrinsic *intrinsic, - bool allowActualArgumentConversions, bool extentErrors) { + bool allowActualArgumentConversions, bool extentErrors, + bool ignoreImplicitVsExplicit) { evaluate::FoldingContext &foldingContext{context.foldingContext()}; auto &messages{foldingContext.messages()}; std::string dummyName{"dummy argument"}; @@ -1185,7 +1187,8 @@ static void CheckExplicitInterfaceArg(evaluate::ActualArgument &arg, }, [&](const characteristics::DummyProcedure &dummy) { if (!checkActualArgForLabel(arg)) { - CheckProcedureArg(arg, proc, dummy, dummyName, context); + CheckProcedureArg(arg, proc, dummy, dummyName, context, + ignoreImplicitVsExplicit); } }, [&](const characteristics::AlternateReturn &) { @@ -1371,7 +1374,8 @@ static void CheckAssociated(evaluate::ActualArguments &arguments, : nullptr}; std::optional msg{ CheckProcCompatibility(isCall, pointerProc, &*targetProc, - specificIntrinsic, whyNot, warning)}; + specificIntrinsic, whyNot, warning, + /*ignoreImplicitVsExplicit=*/false)}; if (!msg && warning && semanticsContext.ShouldWarn( common::UsageWarning::ProcDummyArgShapes)) { @@ -1740,7 +1744,8 @@ static parser::Messages CheckExplicitInterface( const characteristics::Procedure &proc, evaluate::ActualArguments &actuals, SemanticsContext &context, const Scope *scope, const evaluate::SpecificIntrinsic *intrinsic, - bool allowActualArgumentConversions, bool extentErrors) { + bool allowActualArgumentConversions, bool extentErrors, + bool ignoreImplicitVsExplicit) { evaluate::FoldingContext &foldingContext{context.foldingContext()}; parser::ContextualMessages &messages{foldingContext.messages()}; parser::Messages buffer; @@ -1754,7 +1759,8 @@ static parser::Messages CheckExplicitInterface( const auto &dummy{proc.dummyArguments.at(index++)}; if (actual) { CheckExplicitInterfaceArg(*actual, dummy, proc, context, scope, intrinsic, - allowActualArgumentConversions, extentErrors); + allowActualArgumentConversions, extentErrors, + ignoreImplicitVsExplicit); } else if (!dummy.IsOptional()) { if (dummy.name.empty()) { messages.Say( @@ -1783,7 +1789,8 @@ bool CheckInterfaceForGeneric(const characteristics::Procedure &proc, bool allowActualArgumentConversions) { return proc.HasExplicitInterface() && !CheckExplicitInterface(proc, actuals, context, nullptr, nullptr, - allowActualArgumentConversions, false /*extentErrors*/) + allowActualArgumentConversions, /*extentErrors=*/false, + /*ignoreImplicitVsExplicit=*/false) .AnyFatalError(); } @@ -1876,6 +1883,7 @@ bool CheckPPCIntrinsic(const Symbol &generic, const Symbol &specific, bool CheckArguments(const characteristics::Procedure &proc, evaluate::ActualArguments &actuals, SemanticsContext &context, const Scope &scope, bool treatingExternalAsImplicit, + bool ignoreImplicitVsExplicit, const evaluate::SpecificIntrinsic *intrinsic) { bool explicitInterface{proc.HasExplicitInterface()}; evaluate::FoldingContext foldingContext{context.foldingContext()}; @@ -1898,8 +1906,9 @@ bool CheckArguments(const characteristics::Procedure &proc, } } if (explicitInterface) { - auto buffer{CheckExplicitInterface( - proc, actuals, context, &scope, intrinsic, true, true)}; + auto buffer{CheckExplicitInterface(proc, actuals, context, &scope, + intrinsic, /*allowArgumentConversions=*/true, /*extentErrors=*/true, + ignoreImplicitVsExplicit)}; if (!buffer.empty()) { if (treatingExternalAsImplicit) { if (auto *msg{messages.Say( diff --git a/flang/lib/Semantics/check-call.h b/flang/lib/Semantics/check-call.h index 4275606225eb8..8553f3a31efb5 100644 --- a/flang/lib/Semantics/check-call.h +++ b/flang/lib/Semantics/check-call.h @@ -35,7 +35,7 @@ class SemanticsContext; // messages were created, true if all is well. bool CheckArguments(const evaluate::characteristics::Procedure &, evaluate::ActualArguments &, SemanticsContext &, const Scope &, - bool treatingExternalAsImplicit, + bool treatingExternalAsImplicit, bool ignoreImplicitVsExplicit, const evaluate::SpecificIntrinsic *intrinsic); bool CheckPPCIntrinsic(const Symbol &generic, const Symbol &specific, diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index e9adc086402d6..431cef2079350 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) || @@ -1481,7 +1479,8 @@ void CheckHelper::CheckExternal(const Symbol &symbol) { if (auto globalChars{Characterize(*global)}) { if (chars->HasExplicitInterface()) { std::string whyNot; - if (!chars->IsCompatibleWith(*globalChars, &whyNot)) { + if (!chars->IsCompatibleWith(*globalChars, + /*ignoreImplicitVsExplicit=*/false, &whyNot)) { msg = WarnIfNotInModuleFile( "The global subprogram '%s' is not compatible with its local procedure declaration (%s)"_warn_en_US, global->name(), whyNot); @@ -1507,7 +1506,8 @@ void CheckHelper::CheckExternal(const Symbol &symbol) { if (auto chars{Characterize(symbol)}) { if (auto previousChars{Characterize(previous)}) { std::string whyNot; - if (!chars->IsCompatibleWith(*previousChars, &whyNot)) { + if (!chars->IsCompatibleWith(*previousChars, + /*ignoreImplicitVsExplicit=*/false, &whyNot)) { if (auto *msg{WarnIfNotInModuleFile( "The external interface '%s' is not compatible with an earlier definition (%s)"_warn_en_US, symbol.name(), whyNot)}) { @@ -3234,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 6515cf25e0d7d..94d16a719277a 100644 --- a/flang/lib/Semantics/check-select-type.cpp +++ b/flang/lib/Semantics/check-select-type.cpp @@ -120,31 +120,25 @@ class TypeCaseValues { 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/data-to-inits.cpp b/flang/lib/Semantics/data-to-inits.cpp index c12af1bb0165c..fa22d49867905 100644 --- a/flang/lib/Semantics/data-to-inits.cpp +++ b/flang/lib/Semantics/data-to-inits.cpp @@ -524,7 +524,7 @@ static const DerivedTypeSpec *HasDefaultInitialization(const Symbol &symbol) { directs.begin(), directs.end(), [](const Symbol &component) { return !IsAllocatable(component) && HasDeclarationInitializer(component); - })) { + }) != directs.end()) { return derived; } } diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp index 8d817f077880b..54bfe0f2e1563 100644 --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -973,7 +973,8 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::Name &n) { } } if (!isWholeAssumedSizeArrayOk_ && - semantics::IsAssumedSizeArray(*n.symbol)) { // C1002, C1014, C1231 + semantics::IsAssumedSizeArray( + ResolveAssociations(*n.symbol))) { // C1002, C1014, C1231 AttachDeclaration( SayAt(n, "Whole assumed-size array '%s' may not appear here without subscripts"_err_en_US, @@ -1329,15 +1330,29 @@ std::optional ExpressionAnalyzer::CreateComponent(DataRef &&base, // Derived type component references and type parameter inquiries MaybeExpr ExpressionAnalyzer::Analyze(const parser::StructureComponent &sc) { - MaybeExpr base{Analyze(sc.base)}; Symbol *sym{sc.component.symbol}; - if (!base || !sym || context_.HasError(sym)) { + if (context_.HasError(sym)) { + return std::nullopt; + } + const auto *misc{sym->detailsIf()}; + bool isTypeParamInquiry{sym->has() || + (misc && + (misc->kind() == semantics::MiscDetails::Kind::KindParamInquiry || + misc->kind() == semantics::MiscDetails::Kind::LenParamInquiry))}; + MaybeExpr base; + if (isTypeParamInquiry) { + auto restorer{AllowWholeAssumedSizeArray()}; + base = Analyze(sc.base); + } else { + base = Analyze(sc.base); + } + if (!base) { return std::nullopt; } const auto &name{sc.component.source}; if (auto *dtExpr{UnwrapExpr>(*base)}) { const auto *dtSpec{GetDerivedTypeSpec(dtExpr->GetType())}; - if (sym->detailsIf()) { + if (isTypeParamInquiry) { if (auto *designator{UnwrapExpr>(*dtExpr)}) { if (std::optional dyType{DynamicType::From(*sym)}) { if (dyType->category() == TypeCategory::Integer) { @@ -1350,8 +1365,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::StructureComponent &sc) { Say(name, "Type parameter is not INTEGER"_err_en_US); } else { Say(name, - "A type parameter inquiry must be applied to " - "a designator"_err_en_US); + "A type parameter inquiry must be applied to a designator"_err_en_US); } } else if (!dtSpec || !dtSpec->scope()) { CHECK(context_.AnyFatalError() || !foldingContext_.messages().empty()); @@ -1393,8 +1407,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::StructureComponent &sc) { return AsGenericExpr(std::move(realExpr)); } } - } else if (kind == MiscKind::KindParamInquiry || - kind == MiscKind::LenParamInquiry) { + } else if (isTypeParamInquiry) { // %kind or %len ActualArgument arg{std::move(*base)}; SetArgSourceLocation(arg, name); return MakeFunctionRef(name, ActualArguments{std::move(arg)}); @@ -3129,7 +3142,8 @@ std::optional ExpressionAnalyzer::CheckCall( if (auto iter{implicitInterfaces_.find(name)}; iter != implicitInterfaces_.end()) { std::string whyNot; - if (!chars->IsCompatibleWith(iter->second.second, &whyNot)) { + if (!chars->IsCompatibleWith(iter->second.second, + /*ignoreImplicitVsExplicit=*/false, &whyNot)) { if (auto *msg{Say(callSite, "Reference to the procedure '%s' has an implicit interface that is distinct from another reference: %s"_warn_en_US, name, whyNot)}) { @@ -3169,7 +3183,7 @@ std::optional ExpressionAnalyzer::CheckCall( } ok &= semantics::CheckArguments(*chars, arguments, context_, context_.FindScope(callSite), treatExternalAsImplicit, - specificIntrinsic); + /*ignoreImplicitVsExplicit=*/false, specificIntrinsic); } if (procSymbol && !IsPureProcedure(*procSymbol)) { if (const semantics::Scope * @@ -3188,7 +3202,8 @@ std::optional ExpressionAnalyzer::CheckCall( if (auto globalChars{characteristics::Procedure::Characterize( *global, context_.foldingContext())}) { semantics::CheckArguments(*globalChars, arguments, context_, - context_.FindScope(callSite), true, + context_.FindScope(callSite), /*treatExternalAsImplicit=*/true, + /*ignoreImplicitVsExplicit=*/false, nullptr /*not specific intrinsic*/); } } @@ -3741,9 +3756,12 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::Selector &selector) { } } } + // Not a Variable -> FunctionReference + auto restorer{AllowWholeAssumedSizeArray()}; + return Analyze(selector.u); + } else { // Expr + return Analyze(selector.u); } - // Not a Variable -> FunctionReference; handle normally as Variable or Expr - return Analyze(selector.u); } MaybeExpr ExpressionAnalyzer::Analyze(const parser::DataStmtConstant &x) { @@ -3999,6 +4017,7 @@ void ArgumentAnalyzer::Analyze( const parser::ActualArgSpec &arg, bool isSubroutine) { // TODO: C1534: Don't allow a "restricted" specific intrinsic to be passed. std::optional actual; + auto restorer{context_.AllowWholeAssumedSizeArray()}; common::visit( common::visitors{ [&](const common::Indirection &x) { @@ -4613,8 +4632,9 @@ evaluate::Expr AnalyzeKindSelector( SemanticsContext &context, common::TypeCategory category, const std::optional &selector) { evaluate::ExpressionAnalyzer analyzer{context}; + CHECK(context.location().has_value()); auto restorer{ - analyzer.GetContextualMessages().SetLocation(context.location().value())}; + analyzer.GetContextualMessages().SetLocation(*context.location())}; return analyzer.AnalyzeKindSelector(category, selector); } diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp index 7072ddee18ebe..b4df7216a33e2 100644 --- a/flang/lib/Semantics/mod-file.cpp +++ b/flang/lib/Semantics/mod-file.cpp @@ -41,11 +41,13 @@ struct ModHeader { static constexpr const char magic[magicLen + 1]{"!mod$ v1 sum:"}; static constexpr char terminator{'\n'}; static constexpr int len{magicLen + 1 + sumLen}; + static constexpr int needLen{7}; + static constexpr const char need[needLen + 1]{"!need$ "}; }; static std::optional GetSubmoduleParent(const parser::Program &); static void CollectSymbols(const Scope &, SymbolVector &, SymbolVector &, - std::map &); + std::map &, UnorderedSymbolSet &); static void PutPassName(llvm::raw_ostream &, const std::optional &); static void PutInit(llvm::raw_ostream &, const Symbol &, const MaybeExpr &, const parser::Expr *, const std::map &); @@ -58,11 +60,12 @@ static void PutShape( static llvm::raw_ostream &PutAttr(llvm::raw_ostream &, Attr); static llvm::raw_ostream &PutType(llvm::raw_ostream &, const DeclTypeSpec &); static llvm::raw_ostream &PutLower(llvm::raw_ostream &, std::string_view); -static std::error_code WriteFile( - const std::string &, const std::string &, bool = true); +static std::error_code WriteFile(const std::string &, const std::string &, + ModuleCheckSumType &, bool debug = true); static bool FileContentsMatch( const std::string &, const std::string &, const std::string &); -static std::string CheckSum(const std::string_view &); +static ModuleCheckSumType ComputeCheckSum(const std::string_view &); +static std::string CheckSumString(ModuleCheckSumType); // Collect symbols needed for a subprogram interface class SubprogramSymbolCollector { @@ -129,17 +132,23 @@ static std::string ModFileName(const SourceName &name, // Write the module file for symbol, which must be a module or submodule. void ModFileWriter::Write(const Symbol &symbol) { - auto *ancestor{symbol.get().ancestor()}; + auto &module{symbol.get()}; + if (module.moduleFileHash()) { + return; // already written + } + auto *ancestor{module.ancestor()}; isSubmodule_ = ancestor != nullptr; auto ancestorName{ancestor ? ancestor->GetName().value().ToString() : ""s}; auto path{context_.moduleDirectory() + '/' + ModFileName(symbol.name(), ancestorName, context_.moduleFileSuffix())}; PutSymbols(DEREF(symbol.scope())); - if (std::error_code error{ - WriteFile(path, GetAsString(symbol), context_.debugModuleWriter())}) { + ModuleCheckSumType checkSum; + if (std::error_code error{WriteFile( + path, GetAsString(symbol), checkSum, context_.debugModuleWriter())}) { context_.Say( symbol.name(), "Error writing %s: %s"_err_en_US, path, error.message()); } + const_cast(module).set_moduleFileHash(checkSum); } // Return the entire body of the module file @@ -147,6 +156,8 @@ void ModFileWriter::Write(const Symbol &symbol) { std::string ModFileWriter::GetAsString(const Symbol &symbol) { std::string buf; llvm::raw_string_ostream all{buf}; + all << needs_.str(); + needs_.str().clear(); auto &details{symbol.get()}; if (!details.isSubmodule()) { all << "module " << symbol.name(); @@ -258,7 +269,17 @@ void ModFileWriter::PutSymbols(const Scope &scope) { SymbolVector sorted; SymbolVector uses; PrepareRenamings(scope); - CollectSymbols(scope, sorted, uses, renamings_); + UnorderedSymbolSet modules; + CollectSymbols(scope, sorted, uses, renamings_, modules); + // Write module files for dependencies first so that their + // hashes are known. + for (auto ref : modules) { + Write(*ref); + needs_ << ModHeader::need + << CheckSumString(ref->get().moduleFileHash().value()) + << (ref->owner().IsIntrinsicModules() ? " i " : " n ") + << ref->name().ToString() << '\n'; + } std::string buf; // stuff after CONTAINS in derived type llvm::raw_string_ostream typeBindings{buf}; for (const Symbol &symbol : sorted) { @@ -730,16 +751,26 @@ static inline SourceName NameInModuleFile(const Symbol &symbol) { // Collect the symbols of this scope sorted by their original order, not name. // Generics and namelists are exceptions: they are sorted after other symbols. void CollectSymbols(const Scope &scope, SymbolVector &sorted, - SymbolVector &uses, std::map &renamings) { + SymbolVector &uses, std::map &renamings, + UnorderedSymbolSet &modules) { SymbolVector namelist, generics; auto symbols{scope.GetSymbols()}; std::size_t commonSize{scope.commonBlocks().size()}; sorted.reserve(symbols.size() + commonSize); for (SymbolRef symbol : symbols) { + const auto *generic{symbol->detailsIf()}; + if (generic) { + uses.insert(uses.end(), generic->uses().begin(), generic->uses().end()); + for (auto ref : generic->uses()) { + modules.insert(GetUsedModule(ref->get())); + } + } else if (const auto *use{symbol->detailsIf()}) { + modules.insert(GetUsedModule(*use)); + } if (symbol->test(Symbol::Flag::ParentComp)) { } else if (symbol->has()) { namelist.push_back(symbol); - } else if (const auto *generic{symbol->detailsIf()}) { + } else if (generic) { if (generic->specific() && &generic->specific()->owner() == &symbol->owner()) { sorted.push_back(*generic->specific()); @@ -751,9 +782,6 @@ void CollectSymbols(const Scope &scope, SymbolVector &sorted, } else { sorted.push_back(symbol); } - if (const auto *details{symbol->detailsIf()}) { - uses.insert(uses.end(), details->uses().begin(), details->uses().end()); - } } // Sort most symbols by name: use of Symbol::ReplaceName ensures the source // location of a symbol's name is the first "real" use. @@ -896,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()); } @@ -1100,10 +1128,11 @@ static llvm::ErrorOr MkTemp(const std::string &path) { // Write the module file at path, prepending header. If an error occurs, // return errno, otherwise 0. -static std::error_code WriteFile( - const std::string &path, const std::string &contents, bool debug) { +static std::error_code WriteFile(const std::string &path, + const std::string &contents, ModuleCheckSumType &checkSum, bool debug) { + checkSum = ComputeCheckSum(contents); auto header{std::string{ModHeader::bom} + ModHeader::magic + - CheckSum(contents) + ModHeader::terminator}; + CheckSumString(checkSum) + ModHeader::terminator}; if (debug) { llvm::dbgs() << "Processing module " << path << ": "; } @@ -1155,12 +1184,16 @@ static bool FileContentsMatch(const std::string &path, // Compute a simple hash of the contents of a module file and // return it as a string of hex digits. // This uses the Fowler-Noll-Vo hash function. -static std::string CheckSum(const std::string_view &contents) { - std::uint64_t hash{0xcbf29ce484222325ull}; +static ModuleCheckSumType ComputeCheckSum(const std::string_view &contents) { + ModuleCheckSumType hash{0xcbf29ce484222325ull}; for (char c : contents) { hash ^= c & 0xff; hash *= 0x100000001b3; } + return hash; +} + +static std::string CheckSumString(ModuleCheckSumType hash) { static const char *digits = "0123456789abcdef"; std::string result(ModHeader::sumLen, '0'); for (size_t i{ModHeader::sumLen}; hash != 0; hash >>= 4) { @@ -1169,18 +1202,74 @@ static std::string CheckSum(const std::string_view &contents) { return result; } -static bool VerifyHeader(llvm::ArrayRef content) { +std::optional ExtractCheckSum(const std::string_view &str) { + if (str.size() == ModHeader::sumLen) { + ModuleCheckSumType hash{0}; + for (size_t j{0}; j < ModHeader::sumLen; ++j) { + hash <<= 4; + char ch{str.at(j)}; + if (ch >= '0' && ch <= '9') { + hash += ch - '0'; + } else if (ch >= 'a' && ch <= 'f') { + hash += ch - 'a' + 10; + } else { + return std::nullopt; + } + } + return hash; + } + return std::nullopt; +} + +static std::optional VerifyHeader( + llvm::ArrayRef content) { std::string_view sv{content.data(), content.size()}; if (sv.substr(0, ModHeader::magicLen) != ModHeader::magic) { - return false; + return std::nullopt; } + ModuleCheckSumType checkSum{ComputeCheckSum(sv.substr(ModHeader::len))}; std::string_view expectSum{sv.substr(ModHeader::magicLen, ModHeader::sumLen)}; - std::string actualSum{CheckSum(sv.substr(ModHeader::len))}; - return expectSum == actualSum; + if (auto extracted{ExtractCheckSum(expectSum)}; + extracted && *extracted == checkSum) { + return checkSum; + } else { + return std::nullopt; + } } -Scope *ModFileReader::Read(const SourceName &name, - std::optional isIntrinsic, Scope *ancestor, bool silent) { +static void GetModuleDependences( + ModuleDependences &dependences, llvm::ArrayRef content) { + std::size_t limit{content.size()}; + std::string_view str{content.data(), limit}; + for (std::size_t j{ModHeader::len}; + str.substr(j, ModHeader::needLen) == ModHeader::need;) { + j += 7; + auto checkSum{ExtractCheckSum(str.substr(j, ModHeader::sumLen))}; + if (!checkSum) { + break; + } + j += ModHeader::sumLen; + bool intrinsic{false}; + if (str.substr(j, 3) == " i ") { + intrinsic = true; + } else if (str.substr(j, 3) != " n ") { + break; + } + j += 3; + std::size_t start{j}; + for (; j < limit && str.at(j) != '\n'; ++j) { + } + if (j > start && j < limit && str.at(j) == '\n') { + dependences.AddDependence( + std::string{str.substr(start, j - start)}, intrinsic, *checkSum); + } else { + break; + } + } +} + +Scope *ModFileReader::Read(SourceName name, std::optional isIntrinsic, + Scope *ancestor, bool silent) { std::string ancestorName; // empty for module Symbol *notAModule{nullptr}; bool fatalError{false}; @@ -1190,12 +1279,26 @@ Scope *ModFileReader::Read(const SourceName &name, } ancestorName = ancestor->GetName().value().ToString(); } + auto requiredHash{context_.moduleDependences().GetRequiredHash( + name.ToString(), isIntrinsic.value_or(false))}; if (!isIntrinsic.value_or(false) && !ancestor) { // Already present in the symbol table as a usable non-intrinsic module? auto it{context_.globalScope().find(name)}; if (it != context_.globalScope().end()) { Scope *scope{it->second->scope()}; if (scope->kind() == Scope::Kind::Module) { + if (requiredHash) { + if (const Symbol * foundModule{scope->symbol()}) { + if (const auto *module{foundModule->detailsIf()}; + module && module->moduleFileHash() && + *requiredHash != *module->moduleFileHash()) { + Say(name, ancestorName, + "Multiple versions of the module '%s' cannot be required by the same compilation"_err_en_US, + name.ToString()); + return nullptr; + } + } + } return scope; } else { notAModule = scope->symbol(); @@ -1249,7 +1352,50 @@ Scope *ModFileReader::Read(const SourceName &name, for (const auto &dir : context_.intrinsicModuleDirectories()) { options.searchDirectories.push_back(dir); } + if (!requiredHash) { + requiredHash = + context_.moduleDependences().GetRequiredHash(name.ToString(), true); + } } + + // Look for the right module file if its hash is known + if (requiredHash && !fatalError) { + std::vector misses; + for (const std::string &maybe : + parser::LocateSourceFileAll(path, options.searchDirectories)) { + if (const auto *srcFile{context_.allCookedSources().allSources().OpenPath( + maybe, llvm::errs())}) { + if (auto checkSum{VerifyHeader(srcFile->content())}) { + if (*checkSum == *requiredHash) { + path = maybe; + if (!misses.empty()) { + auto &msg{context_.Say(name, + "Module file for '%s' appears later in the module search path than conflicting modules with different checksums"_warn_en_US, + name.ToString())}; + for (const std::string &m : misses) { + msg.Attach( + name, "Module file with a conflicting name: '%s'"_en_US, m); + } + } + misses.clear(); + break; + } else { + misses.emplace_back(maybe); + } + } + } + } + if (!misses.empty()) { + auto &msg{Say(name, ancestorName, + "Could not find a module file for '%s' in the module search path with the expected checksum"_err_en_US, + name.ToString())}; + for (const std::string &m : misses) { + msg.Attach(name, "Module file with different checksum: '%s'"_en_US, m); + } + return nullptr; + } + } + const auto *sourceFile{fatalError ? nullptr : parsing.Prescan(path, options)}; if (fatalError || parsing.messages().AnyFatalError()) { if (!silent) { @@ -1270,10 +1416,17 @@ Scope *ModFileReader::Read(const SourceName &name, return nullptr; } CHECK(sourceFile); - if (!VerifyHeader(sourceFile->content())) { + std::optional checkSum{ + VerifyHeader(sourceFile->content())}; + if (!checkSum) { Say(name, ancestorName, "File has invalid checksum: %s"_warn_en_US, sourceFile->path()); return nullptr; + } else if (requiredHash && *requiredHash != *checkSum) { + Say(name, ancestorName, + "File is not the right module file for %s"_warn_en_US, + "'"s + name.ToString() + "': "s + sourceFile->path()); + return nullptr; } llvm::raw_null_ostream NullStream; parsing.Parse(NullStream); @@ -1316,6 +1469,7 @@ Scope *ModFileReader::Read(const SourceName &name, // Process declarations from the module file bool wasInModuleFile{context_.foldingContext().inModuleFile()}; context_.foldingContext().set_inModuleFile(true); + GetModuleDependences(context_.moduleDependences(), sourceFile->content()); ResolveNames(context_, parseTree, topScope); context_.foldingContext().set_inModuleFile(wasInModuleFile); if (!moduleSymbol) { @@ -1331,8 +1485,8 @@ Scope *ModFileReader::Read(const SourceName &name, } } if (moduleSymbol) { - CHECK(moduleSymbol->has()); CHECK(moduleSymbol->test(Symbol::Flag::ModFile)); + moduleSymbol->get().set_moduleFileHash(checkSum.value()); if (isIntrinsic.value_or(false)) { moduleSymbol->attrs().set(Attr::INTRINSIC); } @@ -1342,7 +1496,7 @@ Scope *ModFileReader::Read(const SourceName &name, } } -parser::Message &ModFileReader::Say(const SourceName &name, +parser::Message &ModFileReader::Say(SourceName name, const std::string &ancestor, parser::MessageFixedText &&msg, const std::string &arg) { return context_.Say(name, "Cannot read module file for %s: %s"_err_en_US, @@ -1468,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/mod-file.h b/flang/lib/Semantics/mod-file.h index 5be117153dd4d..b4ece4018c054 100644 --- a/flang/lib/Semantics/mod-file.h +++ b/flang/lib/Semantics/mod-file.h @@ -38,7 +38,8 @@ class ModFileWriter { private: SemanticsContext &context_; - // Buffer to use with raw_string_ostream + // Buffers to use with raw_string_ostream + std::string needsBuf_; std::string usesBuf_; std::string useExtraAttrsBuf_; std::string declsBuf_; @@ -46,6 +47,7 @@ class ModFileWriter { // Tracks nested DEC structures and fields of that type UnorderedSymbolSet emittedDECStructures_, emittedDECFields_; + llvm::raw_string_ostream needs_{needsBuf_}; llvm::raw_string_ostream uses_{usesBuf_}; llvm::raw_string_ostream useExtraAttrs_{ useExtraAttrsBuf_}; // attrs added to used entity @@ -83,18 +85,17 @@ class ModFileWriter { class ModFileReader { public: - // directories specifies where to search for module files ModFileReader(SemanticsContext &context) : context_{context} {} // Find and read the module file for a module or submodule. // If ancestor is specified, look for a submodule of that module. // Return the Scope for that module/submodule or nullptr on error. - Scope *Read(const SourceName &, std::optional isIntrinsic, - Scope *ancestor, bool silent = false); + Scope *Read(SourceName, std::optional isIntrinsic, Scope *ancestor, + bool silent); private: SemanticsContext &context_; - parser::Message &Say(const SourceName &, const std::string &, + parser::Message &Say(SourceName, const std::string &, parser::MessageFixedText &&, const std::string &); }; diff --git a/flang/lib/Semantics/pointer-assignment.cpp b/flang/lib/Semantics/pointer-assignment.cpp index 4c293e85cf9de..58155a29da1ee 100644 --- a/flang/lib/Semantics/pointer-assignment.cpp +++ b/flang/lib/Semantics/pointer-assignment.cpp @@ -362,7 +362,8 @@ bool PointerAssignmentChecker::Check(parser::CharBlock rhsName, bool isCall, std::optional warning; CharacterizeProcedure(); if (std::optional msg{evaluate::CheckProcCompatibility( - isCall, procedure_, rhsProcedure, specific, whyNot, warning)}) { + isCall, procedure_, rhsProcedure, specific, whyNot, warning, + /*ignoreImplicitVsExplicit=*/isCall)}) { Say(std::move(*msg), description_, rhsName, whyNot); return false; } diff --git a/flang/lib/Semantics/resolve-names-utils.cpp b/flang/lib/Semantics/resolve-names-utils.cpp index b901080e2860c..801473876e7e2 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 0cbe0b492fa44..67392a02cf186 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1118,7 +1118,6 @@ class DeclarationVisitor : public ArraySpecVisitor, // Set when walking DATA & array constructor implied DO loop bounds // to warn about use of the implied DO intex therein. std::optional checkIndexUseInOwnBounds_; - bool hasBindCName_{false}; bool isVectorType_{false}; UnorderedSymbolSet mustBeScalar_; @@ -1225,8 +1224,7 @@ class ConstructVisitor : public virtual DeclarationVisitor { void Post(const parser::ForallConstruct &); bool Pre(const parser::ForallStmt &); void Post(const parser::ForallStmt &); - bool Pre(const parser::BlockStmt &); - bool Pre(const parser::EndBlockStmt &); + bool Pre(const parser::BlockConstruct &); void Post(const parser::Selector &); void Post(const parser::AssociateStmt &); void Post(const parser::EndAssociateStmt &); @@ -1283,6 +1281,8 @@ class ConstructVisitor : public virtual DeclarationVisitor { void Post(const parser::CycleStmt &x) { CheckRef(x.v); } void Post(const parser::ExitStmt &x) { CheckRef(x.v); } + void HandleImpliedAsynchronousInScope(const parser::Block &); + private: // R1105 selector -> expr | variable // expr is set in either case unless there were errors @@ -3375,7 +3375,8 @@ void ModuleVisitor::BeginModule(const parser::Name &name, bool isSubmodule) { Scope *ModuleVisitor::FindModule(const parser::Name &name, std::optional isIntrinsic, Scope *ancestor) { ModFileReader reader{context()}; - Scope *scope{reader.Read(name.source, isIntrinsic, ancestor)}; + Scope *scope{ + reader.Read(name.source, isIntrinsic, ancestor, /*silent=*/false)}; if (!scope) { return nullptr; } @@ -3709,13 +3710,17 @@ bool SubprogramVisitor::Pre(const parser::Suffix &suffix) { bool SubprogramVisitor::Pre(const parser::PrefixSpec &x) { // Save this to process after UseStmt and ImplicitPart if (const auto *parsedType{std::get_if(&x.u)}) { - FuncResultStack::FuncInfo &info{DEREF(funcResultStack().Top())}; - if (info.parsedType) { // C1543 - Say(currStmtSource().value(), - "FUNCTION prefix cannot specify the type more than once"_err_en_US); + if (FuncResultStack::FuncInfo * info{funcResultStack().Top()}) { + if (info->parsedType) { // C1543 + Say(currStmtSource().value(), + "FUNCTION prefix cannot specify the type more than once"_err_en_US); + } else { + info->parsedType = parsedType; + info->source = currStmtSource(); + } } else { - info.parsedType = parsedType; - info.source = currStmtSource(); + Say(currStmtSource().value(), + "SUBROUTINE prefix cannot specify a type"_err_en_US); } return false; } else { @@ -4216,7 +4221,12 @@ bool SubprogramVisitor::BeginMpSubprogram(const parser::Name &name) { EraseSymbol(name); Symbol &newSymbol{MakeSymbol(name, SubprogramDetails{})}; PushScope(Scope::Kind::Subprogram, &newSymbol); - newSymbol.get().set_moduleInterface(*symbol); + auto &newSubprogram{newSymbol.get()}; + newSubprogram.set_moduleInterface(*symbol); + auto &subprogram{symbol->get()}; + if (const auto *name{subprogram.bindName()}) { + newSubprogram.set_bindName(std::string{*name}); + } newSymbol.attrs() |= symbol->attrs(); newSymbol.set(symbol->test(Symbol::Flag::Subroutine) ? Symbol::Flag::Subroutine @@ -4965,15 +4975,16 @@ Symbol &DeclarationVisitor::DeclareProcEntity( const parser::Name &name, Attrs attrs, const Symbol *interface) { Symbol &symbol{DeclareEntity(name, attrs)}; if (auto *details{symbol.detailsIf()}) { - if (details->IsInterfaceSet()) { - SayWithDecl(name, symbol, - "The interface for procedure '%s' has already been " - "declared"_err_en_US); - context().SetError(symbol); + if (context().HasError(symbol)) { } else if (HasCycle(symbol, interface)) { return symbol; + } else if (interface && (details->procInterface() || details->type())) { + SayWithDecl(name, symbol, + "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)) { @@ -5578,7 +5589,10 @@ bool DeclarationVisitor::Pre(const parser::ProcedureDeclarationStmt &x) { for (const parser::ProcAttrSpec &procAttr : procAttrSpec) { if (auto *bindC{std::get_if(&procAttr.u)}) { if (bindC->v.has_value()) { - hasBindCName_ = true; + if (std::get>(x.t).size() > 1) { + Say(context().location().value(), + "A procedure declaration statement with a binding name may not declare multiple procedures"_err_en_US); + } break; } } @@ -5587,7 +5601,6 @@ bool DeclarationVisitor::Pre(const parser::ProcedureDeclarationStmt &x) { } void DeclarationVisitor::Post(const parser::ProcedureDeclarationStmt &) { interfaceName_ = nullptr; - hasBindCName_ = false; EndDecl(); } bool DeclarationVisitor::Pre(const parser::DataComponentDefStmt &x) { @@ -5646,12 +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_) { - procInterface = interfaceName_->symbol->has() - ? interfaceName_->symbol->get().specific() - : 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()}) { @@ -6027,7 +6038,7 @@ void DeclarationVisitor::Post(const parser::BasedPointer &bp) { if (const auto *derived{pointeeType->AsDerived()}) { if (!IsSequenceOrBindCType(derived)) { Say(pointeeName, - "Type of Cray pointee '%s' is a derived type that is neither SEQUENCE nor BIND(C)"_err_en_US); + "Type of Cray pointee '%s' is a derived type that is neither SEQUENCE nor BIND(C)"_warn_en_US); } } } @@ -6614,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()); } } @@ -6956,14 +6966,17 @@ bool ConstructVisitor::Pre(const parser::ForallStmt &) { } void ConstructVisitor::Post(const parser::ForallStmt &) { PopScope(); } -bool ConstructVisitor::Pre(const parser::BlockStmt &x) { - CheckDef(x.v); +bool ConstructVisitor::Pre(const parser::BlockConstruct &x) { + const auto &[blockStmt, specPart, execPart, endBlockStmt] = x.t; + Walk(blockStmt); + CheckDef(blockStmt.statement.v); PushScope(Scope::Kind::BlockConstruct, nullptr); - return false; -} -bool ConstructVisitor::Pre(const parser::EndBlockStmt &x) { + Walk(specPart); + HandleImpliedAsynchronousInScope(execPart); + Walk(execPart); + Walk(endBlockStmt); PopScope(); - CheckRef(x.v); + CheckRef(endBlockStmt.statement.v); return false; } @@ -7337,6 +7350,224 @@ const DeclTypeSpec &ConstructVisitor::ToDeclTypeSpec( } } +class ExecutionPartSkimmerBase { +public: + template bool Pre(const A &) { return true; } + template void Post(const A &) {} + + bool InNestedBlockConstruct() const { return blockDepth_ > 0; } + + bool Pre(const parser::AssociateConstruct &) { + PushScope(); + return true; + } + void Post(const parser::AssociateConstruct &) { PopScope(); } + bool Pre(const parser::Association &x) { + Hide(std::get(x.t)); + return true; + } + bool Pre(const parser::BlockConstruct &) { + PushScope(); + ++blockDepth_; + return true; + } + void Post(const parser::BlockConstruct &) { + --blockDepth_; + PopScope(); + } + bool Pre(const parser::EntityDecl &x) { + Hide(std::get(x.t)); + return true; + } + void Post(const parser::ImportStmt &x) { + if (x.kind == common::ImportKind::None || + x.kind == common::ImportKind::Only) { + if (!nestedScopes_.front().importOnly.has_value()) { + nestedScopes_.front().importOnly.emplace(); + } + for (const auto &name : x.names) { + nestedScopes_.front().importOnly->emplace(name.source); + } + } else { + // no special handling needed for explicit names or IMPORT, ALL + } + } + void Post(const parser::UseStmt &x) { + if (const auto *onlyList{std::get_if>(&x.u)}) { + for (const auto &only : *onlyList) { + if (const auto *name{std::get_if(&only.u)}) { + Hide(*name); + } else if (const auto *rename{std::get_if(&only.u)}) { + if (const auto *names{ + std::get_if(&rename->u)}) { + Hide(std::get<0>(names->t)); + } + } + } + } else { + // USE may or may not shadow symbols in host scopes + nestedScopes_.front().hasUseWithoutOnly = true; + } + } + bool Pre(const parser::DerivedTypeStmt &x) { + Hide(std::get(x.t)); + PushScope(); + return true; + } + void Post(const parser::DerivedTypeDef &) { PopScope(); } + bool Pre(const parser::SelectTypeConstruct &) { + PushScope(); + return true; + } + void Post(const parser::SelectTypeConstruct &) { PopScope(); } + bool Pre(const parser::SelectTypeStmt &x) { + if (const auto &maybeName{std::get<1>(x.t)}) { + Hide(*maybeName); + } + return true; + } + bool Pre(const parser::SelectRankConstruct &) { + PushScope(); + return true; + } + void Post(const parser::SelectRankConstruct &) { PopScope(); } + bool Pre(const parser::SelectRankStmt &x) { + if (const auto &maybeName{std::get<1>(x.t)}) { + Hide(*maybeName); + } + return true; + } + +protected: + bool IsHidden(SourceName name) { + for (const auto &scope : nestedScopes_) { + if (scope.locals.find(name) != scope.locals.end()) { + return true; // shadowed by nested declaration + } + if (scope.hasUseWithoutOnly) { + break; + } + if (scope.importOnly && + scope.importOnly->find(name) == scope.importOnly->end()) { + return true; // not imported + } + } + return false; + } + + void EndWalk() { CHECK(nestedScopes_.empty()); } + +private: + void PushScope() { nestedScopes_.emplace_front(); } + void PopScope() { nestedScopes_.pop_front(); } + void Hide(const parser::Name &name) { + nestedScopes_.front().locals.emplace(name.source); + } + + int blockDepth_{0}; + struct NestedScopeInfo { + bool hasUseWithoutOnly{false}; + std::set locals; + std::optional> importOnly; + }; + std::list nestedScopes_; +}; + +class ExecutionPartAsyncIOSkimmer : public ExecutionPartSkimmerBase { +public: + explicit ExecutionPartAsyncIOSkimmer(SemanticsContext &context) + : context_{context} {} + + void Walk(const parser::Block &block) { + parser::Walk(block, *this); + EndWalk(); + } + + const std::set asyncIONames() const { return asyncIONames_; } + + using ExecutionPartSkimmerBase::Post; + using ExecutionPartSkimmerBase::Pre; + + bool Pre(const parser::IoControlSpec::Asynchronous &async) { + if (auto folded{evaluate::Fold( + context_.foldingContext(), AnalyzeExpr(context_, async.v))}) { + if (auto str{ + evaluate::GetScalarConstantValue(*folded)}) { + for (char ch : *str) { + if (ch != ' ') { + inAsyncIO_ = ch == 'y' || ch == 'Y'; + break; + } + } + } + } + return true; + } + void Post(const parser::ReadStmt &) { inAsyncIO_ = false; } + void Post(const parser::WriteStmt &) { inAsyncIO_ = false; } + void Post(const parser::IoControlSpec::Size &size) { + if (const auto *designator{ + std::get_if>( + &size.v.thing.thing.u)}) { + NoteAsyncIODesignator(designator->value()); + } + } + void Post(const parser::InputItem &x) { + if (const auto *var{std::get_if(&x.u)}) { + if (const auto *designator{ + std::get_if>(&var->u)}) { + NoteAsyncIODesignator(designator->value()); + } + } + } + void Post(const parser::OutputItem &x) { + if (const auto *expr{std::get_if(&x.u)}) { + if (const auto *designator{ + std::get_if>(&expr->u)}) { + NoteAsyncIODesignator(designator->value()); + } + } + } + +private: + void NoteAsyncIODesignator(const parser::Designator &designator) { + if (inAsyncIO_ && !InNestedBlockConstruct()) { + const parser::Name &name{parser::GetFirstName(designator)}; + if (!IsHidden(name.source)) { + asyncIONames_.insert(name.source); + } + } + } + + SemanticsContext &context_; + bool inAsyncIO_{false}; + std::set asyncIONames_; +}; + +// Any data list item or SIZE= specifier of an I/O data transfer statement +// with ASYNCHRONOUS="YES" implicitly has the ASYNCHRONOUS attribute in the +// local scope. +void ConstructVisitor::HandleImpliedAsynchronousInScope( + const parser::Block &block) { + ExecutionPartAsyncIOSkimmer skimmer{context()}; + skimmer.Walk(block); + for (auto name : skimmer.asyncIONames()) { + if (Symbol * symbol{currScope().FindSymbol(name)}) { + if (!symbol->attrs().test(Attr::ASYNCHRONOUS)) { + if (&symbol->owner() != &currScope()) { + symbol = &*currScope() + .try_emplace(name, HostAssocDetails{*symbol}) + .first->second; + } + if (symbol->has()) { + symbol = const_cast(&GetAssociationRoot(*symbol)); + } + SetImplicitAttr(*symbol, Attr::ASYNCHRONOUS); + } + } + } +} + // ResolveNamesVisitor implementation bool ResolveNamesVisitor::Pre(const parser::FunctionReference &x) { @@ -8216,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)) { @@ -8231,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); } @@ -8247,6 +8470,7 @@ void ResolveNamesVisitor::FinishSpecificationPart( if (const auto *statement{std::get_if< parser::Statement>>( &decl.u)}) { + messageHandler().set_currStmtSource(statement->source); AnalyzeStmtFunctionStmt(statement->statement.value()); } } @@ -8362,16 +8586,25 @@ bool ResolveNamesVisitor::Pre(const parser::PointerAssignmentStmt &x) { const auto &bounds{std::get(x.t)}; const auto &expr{std::get(x.t)}; ResolveDataRef(dataRef); + Symbol *ptrSymbol{parser::GetLastName(dataRef).symbol}; Walk(bounds); // Resolve unrestricted specific intrinsic procedures as in "p => cos". if (const parser::Name * name{parser::Unwrap(expr)}) { if (NameIsKnownOrIntrinsic(*name)) { - // If the name is known because it is an object entity from a host - // procedure, create a host associated symbol. - if (Symbol * symbol{name->symbol}; symbol && - symbol->GetUltimate().has() && - IsUplevelReference(*symbol)) { - MakeHostAssocSymbol(*name, *symbol); + if (Symbol * symbol{name->symbol}) { + if (IsProcedurePointer(ptrSymbol) && + !ptrSymbol->test(Symbol::Flag::Function) && + !ptrSymbol->test(Symbol::Flag::Subroutine)) { + if (symbol->test(Symbol::Flag::Function)) { + ApplyImplicitRules(*ptrSymbol); + } + } + // If the name is known because it is an object entity from a host + // procedure, create a host associated symbol. + if (symbol->GetUltimate().has() && + IsUplevelReference(*symbol)) { + MakeHostAssocSymbol(*name, *symbol); + } } return false; } @@ -8667,138 +8900,38 @@ bool ResolveNamesVisitor::Pre(const parser::Program &x) { // References to procedures need to record that their symbols are known // to be procedures, so that they don't get converted to objects by default. -class ExecutionPartSkimmer { +class ExecutionPartCallSkimmer : public ExecutionPartSkimmerBase { public: - explicit ExecutionPartSkimmer(ResolveNamesVisitor &resolver) + explicit ExecutionPartCallSkimmer(ResolveNamesVisitor &resolver) : resolver_{resolver} {} - void Walk(const parser::ExecutionPart *exec) { - if (exec) { - parser::Walk(*exec, *this); - CHECK(nestedScopes_.empty()); - } + void Walk(const parser::ExecutionPart &exec) { + parser::Walk(exec, *this); + EndWalk(); } - template bool Pre(const A &) { return true; } - template void Post(const A &) {} + using ExecutionPartSkimmerBase::Post; + using ExecutionPartSkimmerBase::Pre; + void Post(const parser::FunctionReference &fr) { NoteCall(Symbol::Flag::Function, fr.v, false); } void Post(const parser::CallStmt &cs) { NoteCall(Symbol::Flag::Subroutine, cs.call, cs.chevrons.has_value()); } - bool Pre(const parser::AssociateConstruct &) { - PushScope(); - return true; - } - void Post(const parser::AssociateConstruct &) { PopScope(); } - bool Pre(const parser::Association &x) { - Hide(std::get(x.t)); - return true; - } - bool Pre(const parser::BlockConstruct &) { - PushScope(); - return true; - } - void Post(const parser::BlockConstruct &) { PopScope(); } - bool Pre(const parser::EntityDecl &x) { - Hide(std::get(x.t)); - return true; - } - void Post(const parser::ImportStmt &x) { - if (x.kind == common::ImportKind::None || - x.kind == common::ImportKind::Only) { - if (!nestedScopes_.front().importOnly.has_value()) { - nestedScopes_.front().importOnly.emplace(); - } - for (const auto &name : x.names) { - nestedScopes_.front().importOnly->emplace(name.source); - } - } else { - // no special handling needed for explicit names or IMPORT, ALL - } - } - void Post(const parser::UseStmt &x) { - if (const auto *onlyList{std::get_if>(&x.u)}) { - for (const auto &only : *onlyList) { - if (const auto *name{std::get_if(&only.u)}) { - Hide(*name); - } else if (const auto *rename{std::get_if(&only.u)}) { - if (const auto *names{ - std::get_if(&rename->u)}) { - Hide(std::get<0>(names->t)); - } - } - } - } else { - // USE may or may not shadow symbols in host scopes - nestedScopes_.front().hasUseWithoutOnly = true; - } - } - bool Pre(const parser::DerivedTypeStmt &x) { - Hide(std::get(x.t)); - PushScope(); - return true; - } - void Post(const parser::DerivedTypeDef &) { PopScope(); } - bool Pre(const parser::SelectTypeConstruct &) { - PushScope(); - return true; - } - void Post(const parser::SelectTypeConstruct &) { PopScope(); } - bool Pre(const parser::SelectTypeStmt &x) { - if (const auto &maybeName{std::get<1>(x.t)}) { - Hide(*maybeName); - } - return true; - } - bool Pre(const parser::SelectRankConstruct &) { - PushScope(); - return true; - } - void Post(const parser::SelectRankConstruct &) { PopScope(); } - bool Pre(const parser::SelectRankStmt &x) { - if (const auto &maybeName{std::get<1>(x.t)}) { - Hide(*maybeName); - } - return true; - } private: void NoteCall( Symbol::Flag flag, const parser::Call &call, bool hasCUDAChevrons) { auto &designator{std::get(call.t)}; if (const auto *name{std::get_if(&designator.u)}) { - for (const auto &scope : nestedScopes_) { - if (scope.locals.find(name->source) != scope.locals.end()) { - return; // shadowed by nested declaration - } - if (scope.hasUseWithoutOnly) { - break; - } - if (scope.importOnly && - scope.importOnly->find(name->source) == scope.importOnly->end()) { - return; // not imported - } + if (!IsHidden(name->source)) { + resolver_.NoteExecutablePartCall(flag, name->source, hasCUDAChevrons); } - resolver_.NoteExecutablePartCall(flag, name->source, hasCUDAChevrons); } } - void PushScope() { nestedScopes_.emplace_front(); } - void PopScope() { nestedScopes_.pop_front(); } - void Hide(const parser::Name &name) { - nestedScopes_.front().locals.emplace(name.source); - } - ResolveNamesVisitor &resolver_; - - struct NestedScopeInfo { - bool hasUseWithoutOnly{false}; - std::set locals; - std::optional> importOnly; - }; - std::list nestedScopes_; }; // Build the scope tree and resolve names in the specification parts of this @@ -8843,11 +8976,24 @@ void ResolveNamesVisitor::ResolveSpecificationParts(ProgramTree &node) { for (auto &child : node.children()) { ResolveSpecificationParts(child); } - ExecutionPartSkimmer{*this}.Walk(node.exec()); + if (node.exec()) { + ExecutionPartCallSkimmer{*this}.Walk(*node.exec()); + HandleImpliedAsynchronousInScope(node.exec()->v); + } 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); } } @@ -8950,6 +9096,8 @@ void ResolveNamesVisitor::EndScopeForNode(const ProgramTree &node) { // pointers, are deferred until all of the pertinent specification parts // have been visited. This deferred processing enables the use of forward // references in these circumstances. +// Data statement objects with implicit derived types are finally +// resolved here. class DeferredCheckVisitor { public: explicit DeferredCheckVisitor(ResolveNamesVisitor &resolver) @@ -8965,21 +9113,20 @@ class DeferredCheckVisitor { if (Symbol * symbol{name.symbol}) { if (Scope * scope{symbol->scope()}) { if (scope->IsDerivedType()) { - resolver_.PushScope(*scope); - pushedScope_ = true; + CHECK(outerScope_ == nullptr); + outerScope_ = &resolver_.currScope(); + resolver_.SetScope(*scope); } } } } void Post(const parser::EndTypeStmt &) { - if (pushedScope_) { - resolver_.PopScope(); - pushedScope_ = false; + if (outerScope_) { + resolver_.SetScope(*outerScope_); + outerScope_ = nullptr; } } - bool Pre(const parser::BlockConstruct &x) { return true; } - void Post(const parser::ProcInterface &pi) { if (const auto *name{std::get_if(&pi.u)}) { resolver_.CheckExplicitInterface(*name); @@ -9006,10 +9153,20 @@ class DeferredCheckVisitor { resolver_.CheckExplicitInterface(tbps.interfaceName); } void Post(const parser::TypeBoundProcedureStmt::WithoutInterface &tbps) { - if (pushedScope_) { + if (outerScope_) { resolver_.CheckBindings(tbps); } } + bool Pre(const parser::DataStmtObject &) { + ++dataStmtObjectNesting_; + return true; + } + void Post(const parser::DataStmtObject &) { --dataStmtObjectNesting_; } + void Post(const parser::Designator &x) { + if (dataStmtObjectNesting_ > 0) { + resolver_.ResolveDesignator(x); + } + } private: void Init(const parser::Name &name, @@ -9031,7 +9188,8 @@ class DeferredCheckVisitor { } ResolveNamesVisitor &resolver_; - bool pushedScope_{false}; + Scope *outerScope_{nullptr}; + int dataStmtObjectNesting_{0}; }; // Perform checks and completions that need to happen after all of diff --git a/flang/lib/Semantics/resolve-names.h b/flang/lib/Semantics/resolve-names.h index 78fdc2edc54a9..a6797b4563593 100644 --- a/flang/lib/Semantics/resolve-names.h +++ b/flang/lib/Semantics/resolve-names.h @@ -9,10 +9,6 @@ #ifndef FORTRAN_SEMANTICS_RESOLVE_NAMES_H_ #define FORTRAN_SEMANTICS_RESOLVE_NAMES_H_ -#include -#include -#include - namespace llvm { class raw_ostream; } diff --git a/flang/lib/Semantics/semantics.cpp b/flang/lib/Semantics/semantics.cpp index a76c42ae4f44f..e58a8f3b22c06 100644 --- a/flang/lib/Semantics/semantics.cpp +++ b/flang/lib/Semantics/semantics.cpp @@ -515,7 +515,7 @@ bool SemanticsContext::IsTempName(const std::string &name) { Scope *SemanticsContext::GetBuiltinModule(const char *name) { return ModFileReader{*this}.Read(SourceName{name, std::strlen(name)}, - true /*intrinsic*/, nullptr, true /*silence errors*/); + true /*intrinsic*/, nullptr, /*silent=*/true); } void SemanticsContext::UseFortranBuiltinsModule() { diff --git a/flang/lib/Semantics/symbol.cpp b/flang/lib/Semantics/symbol.cpp index 2ab3189cf4064..381905b89fb2d 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 f931ae0707201..bf999b090419c 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 e812283fc6f19..44e49673300bf 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 ac89184a7cbff..7dd60b5edcd5f 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 8d276e8f12272..980356131b680 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,14 +24,16 @@ set(sources atan.cpp atan2.cpp atanh.cpp - cabs.cpp ceil.cpp + complex-math.c cos.cpp cosh.cpp erf.cpp erfc.cpp exp.cpp + exponent.cpp floor.cpp + fraction.cpp hypot.cpp j0.cpp j1.cpp @@ -69,10 +43,18 @@ set(sources log.cpp log10.cpp lround.cpp + mod-real.cpp + modulo-real.cpp + nearest.cpp + norm2.cpp pow.cpp round.cpp + rrspacing.cpp + scale.cpp + set-exponent.cpp sin.cpp sinh.cpp + spacing.cpp sqrt.cpp tan.cpp tanh.cpp @@ -84,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/acos.cpp b/flang/runtime/Float128Math/acos.cpp index 531c79c7444bd..14ff694485684 100644 --- a/flang/runtime/Float128Math/acos.cpp +++ b/flang/runtime/Float128Math/acos.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(AcosF128)( CppTypeFor x) { - return Acos::invoke(x); + return Acos::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/acosh.cpp b/flang/runtime/Float128Math/acosh.cpp index 1495120edd1a0..9d70804e44a47 100644 --- a/flang/runtime/Float128Math/acosh.cpp +++ b/flang/runtime/Float128Math/acosh.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(AcoshF128)( CppTypeFor x) { - return Acosh::invoke(x); + return Acosh::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/asin.cpp b/flang/runtime/Float128Math/asin.cpp index 2fb8c6c5e97d7..6781b23f0363d 100644 --- a/flang/runtime/Float128Math/asin.cpp +++ b/flang/runtime/Float128Math/asin.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(AsinF128)( CppTypeFor x) { - return Asin::invoke(x); + return Asin::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/asinh.cpp b/flang/runtime/Float128Math/asinh.cpp index 3630a77be42b2..1310bc61c1de0 100644 --- a/flang/runtime/Float128Math/asinh.cpp +++ b/flang/runtime/Float128Math/asinh.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(AsinhF128)( CppTypeFor x) { - return Asinh::invoke(x); + return Asinh::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/atan.cpp b/flang/runtime/Float128Math/atan.cpp index 4609343e9d127..f01382df90c0e 100644 --- a/flang/runtime/Float128Math/atan.cpp +++ b/flang/runtime/Float128Math/atan.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(AtanF128)( CppTypeFor x) { - return Atan::invoke(x); + return Atan::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/atan2.cpp b/flang/runtime/Float128Math/atan2.cpp index c0175e67ec71b..dd646b0452b11 100644 --- a/flang/runtime/Float128Math/atan2.cpp +++ b/flang/runtime/Float128Math/atan2.cpp @@ -15,7 +15,7 @@ extern "C" { CppTypeFor RTDEF(Atan2F128)( CppTypeFor x, CppTypeFor y) { - return Atan2::invoke(x, y); + return Atan2::invoke(x, y); } #endif diff --git a/flang/runtime/Float128Math/atanh.cpp b/flang/runtime/Float128Math/atanh.cpp index bfacb967117d7..5fc5ba5debc81 100644 --- a/flang/runtime/Float128Math/atanh.cpp +++ b/flang/runtime/Float128Math/atanh.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(AtanhF128)( CppTypeFor x) { - return Atanh::invoke(x); + return Atanh::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/ceil.cpp b/flang/runtime/Float128Math/ceil.cpp index a53a2c27c616b..ed4d164a62bed 100644 --- a/flang/runtime/Float128Math/ceil.cpp +++ b/flang/runtime/Float128Math/ceil.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(CeilF128)( CppTypeFor x) { - return Ceil::invoke(x); + return Ceil::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/complex-math.c b/flang/runtime/Float128Math/complex-math.c new file mode 100644 index 0000000000000..d0180c63a0d7b --- /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 0000000000000..81dd53a175d1a --- /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/cos.cpp b/flang/runtime/Float128Math/cos.cpp index 845c970bd8e63..b93c92f275f79 100644 --- a/flang/runtime/Float128Math/cos.cpp +++ b/flang/runtime/Float128Math/cos.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(CosF128)( CppTypeFor x) { - return Cos::invoke(x); + return Cos::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/cosh.cpp b/flang/runtime/Float128Math/cosh.cpp index acf6ff4130ee3..a3662a826dcb1 100644 --- a/flang/runtime/Float128Math/cosh.cpp +++ b/flang/runtime/Float128Math/cosh.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(CoshF128)( CppTypeFor x) { - return Cosh::invoke(x); + return Cosh::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/erf.cpp b/flang/runtime/Float128Math/erf.cpp index 862f3b9741187..631f71c76effe 100644 --- a/flang/runtime/Float128Math/erf.cpp +++ b/flang/runtime/Float128Math/erf.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(ErfF128)( CppTypeFor x) { - return Erf::invoke(x); + return Erf::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/erfc.cpp b/flang/runtime/Float128Math/erfc.cpp index 0ac0b94556374..ea3cd646d8c4b 100644 --- a/flang/runtime/Float128Math/erfc.cpp +++ b/flang/runtime/Float128Math/erfc.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(ErfcF128)( CppTypeFor x) { - return Erfc::invoke(x); + return Erfc::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/exp.cpp b/flang/runtime/Float128Math/exp.cpp index 50386fdbfb644..b1161b0f29294 100644 --- a/flang/runtime/Float128Math/exp.cpp +++ b/flang/runtime/Float128Math/exp.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(ExpF128)( CppTypeFor x) { - return Exp::invoke(x); + return Exp::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/exponent.cpp b/flang/runtime/Float128Math/exponent.cpp new file mode 100644 index 0000000000000..1be1dd0d0ac8b --- /dev/null +++ b/flang/runtime/Float128Math/exponent.cpp @@ -0,0 +1,26 @@ +//===-- runtime/Float128Math/exponent.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" +#include "numeric-template-specs.h" + +namespace Fortran::runtime { +extern "C" { + +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +// EXPONENT (16.9.75) +CppTypeFor RTDEF(Exponent16_4)(F128Type x) { + return Exponent>(x); +} +CppTypeFor RTDEF(Exponent16_8)(F128Type x) { + return Exponent>(x); +} +#endif + +} // extern "C" +} // namespace Fortran::runtime diff --git a/flang/runtime/Float128Math/floor.cpp b/flang/runtime/Float128Math/floor.cpp index 48cf4e0144807..78a94984cac8a 100644 --- a/flang/runtime/Float128Math/floor.cpp +++ b/flang/runtime/Float128Math/floor.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(FloorF128)( CppTypeFor x) { - return Floor::invoke(x); + return Floor::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/fraction.cpp b/flang/runtime/Float128Math/fraction.cpp new file mode 100644 index 0000000000000..8c9889b7f6871 --- /dev/null +++ b/flang/runtime/Float128Math/fraction.cpp @@ -0,0 +1,21 @@ +//===-- runtime/Float128Math/fraction.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" +#include "numeric-template-specs.h" + +namespace Fortran::runtime { +extern "C" { + +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +// FRACTION (16.9.80) +F128Type RTDEF(Fraction16)(F128Type x) { return Fraction(x); } +#endif + +} // extern "C" +} // namespace Fortran::runtime diff --git a/flang/runtime/Float128Math/hypot.cpp b/flang/runtime/Float128Math/hypot.cpp index 33c83a1654993..b4fa1d66bcfa6 100644 --- a/flang/runtime/Float128Math/hypot.cpp +++ b/flang/runtime/Float128Math/hypot.cpp @@ -15,7 +15,7 @@ extern "C" { CppTypeFor RTDEF(HypotF128)( CppTypeFor x, CppTypeFor y) { - return Hypot::invoke(x, y); + return Hypot::invoke(x, y); } #endif diff --git a/flang/runtime/Float128Math/j0.cpp b/flang/runtime/Float128Math/j0.cpp index f8f3fe71d8a61..9390a7eeb3c60 100644 --- a/flang/runtime/Float128Math/j0.cpp +++ b/flang/runtime/Float128Math/j0.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(J0F128)( CppTypeFor x) { - return J0::invoke(x); + return J0::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/j1.cpp b/flang/runtime/Float128Math/j1.cpp index 9a51b973e1cf8..c54927123388c 100644 --- a/flang/runtime/Float128Math/j1.cpp +++ b/flang/runtime/Float128Math/j1.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(J1F128)( CppTypeFor x) { - return J1::invoke(x); + return J1::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/jn.cpp b/flang/runtime/Float128Math/jn.cpp index 644a66863c0d2..15afd83400c32 100644 --- a/flang/runtime/Float128Math/jn.cpp +++ b/flang/runtime/Float128Math/jn.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(JnF128)( int n, CppTypeFor x) { - return Jn::invoke(n, x); + return Jn::invoke(n, x); } #endif diff --git a/flang/runtime/Float128Math/lgamma.cpp b/flang/runtime/Float128Math/lgamma.cpp index fff7dfcb9c15d..ac31c89a912b3 100644 --- a/flang/runtime/Float128Math/lgamma.cpp +++ b/flang/runtime/Float128Math/lgamma.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(LgammaF128)( CppTypeFor x) { - return Lgamma::invoke(x); + return Lgamma::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/llround.cpp b/flang/runtime/Float128Math/llround.cpp index 00c62818af19d..b77281c507fe7 100644 --- a/flang/runtime/Float128Math/llround.cpp +++ b/flang/runtime/Float128Math/llround.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(LlroundF128)( CppTypeFor x) { - return Llround::invoke(x); + return Llround::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/log.cpp b/flang/runtime/Float128Math/log.cpp index 0cfe329c6f7f5..38e6b581fd849 100644 --- a/flang/runtime/Float128Math/log.cpp +++ b/flang/runtime/Float128Math/log.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(LogF128)( CppTypeFor x) { - return Log::invoke(x); + return Log::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/log10.cpp b/flang/runtime/Float128Math/log10.cpp index cd8bf27fcb121..3c89c0e707774 100644 --- a/flang/runtime/Float128Math/log10.cpp +++ b/flang/runtime/Float128Math/log10.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(Log10F128)( CppTypeFor x) { - return Log10::invoke(x); + return Log10::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/lround.cpp b/flang/runtime/Float128Math/lround.cpp index 6ced66a1b2d3a..ce7a228038a1d 100644 --- a/flang/runtime/Float128Math/lround.cpp +++ b/flang/runtime/Float128Math/lround.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(LroundF128)( CppTypeFor x) { - return Lround::invoke(x); + return Lround::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/math-entries.h b/flang/runtime/Float128Math/math-entries.h index 83298674c4971..1eab7c86f2ed7 100644 --- a/flang/runtime/Float128Math/math-entries.h +++ b/flang/runtime/Float128Math/math-entries.h @@ -13,36 +13,40 @@ #include "flang/Common/float128.h" #include "flang/Runtime/entry-names.h" #include +#include #include +namespace { +using namespace Fortran::runtime; +using F128RetType = CppTypeFor; +using I32RetType = CppTypeFor; +using I64RetType = CppTypeFor; +} // namespace + namespace Fortran::runtime { // Define a class template to gracefully fail, when // there is no specialized template that implements // the required function via using the third-party // implementation. -#define DEFINE_FALLBACK(caller) \ - template struct caller { \ - template \ - [[noreturn]] static std::invoke_result_t invoke( \ - ATs... args) { \ +#define DEFINE_FALLBACK(caller, ret_type) \ + template struct caller { \ + template [[noreturn]] static RT invoke(ATs... args) { \ Terminator terminator{__FILE__, __LINE__}; \ terminator.Crash("Float128 variant of '%s' is unsupported", #caller); \ } \ }; // Define template specialization that is calling the third-party -// implementation. The template is specialized by a function pointer -// that is the FortranFloat128Math entry point. The signatures -// of the caller and the callee must match. +// implementation. // // Defining the specialization for any target library requires // adding the generic template via DEFINE_FALLBACK, so that // a build with another target library that does not define // the same alias can gracefully fail in runtime. #define DEFINE_SIMPLE_ALIAS(caller, callee) \ - template struct caller

{ \ - static RT invoke(ATs... args) { \ + template struct caller { \ + template static RT invoke(ATs... args) { \ static_assert(std::is_invocable_r_v()...))(ATs...), ATs...>); \ if constexpr (std::is_same_v) { \ @@ -54,51 +58,111 @@ namespace Fortran::runtime { }; // Define fallback callers. -DEFINE_FALLBACK(Acos) -DEFINE_FALLBACK(Acosh) -DEFINE_FALLBACK(Asin) -DEFINE_FALLBACK(Asinh) -DEFINE_FALLBACK(Atan) -DEFINE_FALLBACK(Atan2) -DEFINE_FALLBACK(Atanh) -DEFINE_FALLBACK(Ceil) -DEFINE_FALLBACK(Cos) -DEFINE_FALLBACK(Cosh) -DEFINE_FALLBACK(Erf) -DEFINE_FALLBACK(Erfc) -DEFINE_FALLBACK(Exp) -DEFINE_FALLBACK(Floor) -DEFINE_FALLBACK(Hypot) -DEFINE_FALLBACK(J0) -DEFINE_FALLBACK(J1) -DEFINE_FALLBACK(Jn) -DEFINE_FALLBACK(Lgamma) -DEFINE_FALLBACK(Llround) -DEFINE_FALLBACK(Lround) -DEFINE_FALLBACK(Log) -DEFINE_FALLBACK(Log10) -DEFINE_FALLBACK(Pow) -DEFINE_FALLBACK(Round) -DEFINE_FALLBACK(Sin) -DEFINE_FALLBACK(Sinh) -DEFINE_FALLBACK(Sqrt) -DEFINE_FALLBACK(Tan) -DEFINE_FALLBACK(Tanh) -DEFINE_FALLBACK(Tgamma) -DEFINE_FALLBACK(Trunc) -DEFINE_FALLBACK(Y0) -DEFINE_FALLBACK(Y1) -DEFINE_FALLBACK(Yn) +#define DEFINE_FALLBACK_F128(caller) DEFINE_FALLBACK(caller, ::F128RetType) +#define DEFINE_FALLBACK_I32(caller) DEFINE_FALLBACK(caller, ::I32RetType) +#define DEFINE_FALLBACK_I64(caller) DEFINE_FALLBACK(caller, ::I64RetType) + +DEFINE_FALLBACK_F128(Abs) +DEFINE_FALLBACK_F128(Acos) +DEFINE_FALLBACK_F128(Acosh) +DEFINE_FALLBACK_F128(Asin) +DEFINE_FALLBACK_F128(Asinh) +DEFINE_FALLBACK_F128(Atan) +DEFINE_FALLBACK_F128(Atan2) +DEFINE_FALLBACK_F128(Atanh) +DEFINE_FALLBACK_F128(Ceil) +DEFINE_FALLBACK_F128(Cos) +DEFINE_FALLBACK_F128(Cosh) +DEFINE_FALLBACK_F128(Erf) +DEFINE_FALLBACK_F128(Erfc) +DEFINE_FALLBACK_F128(Exp) +DEFINE_FALLBACK_F128(Floor) +DEFINE_FALLBACK_F128(Frexp) +DEFINE_FALLBACK_F128(Hypot) +DEFINE_FALLBACK_I32(Ilogb) +DEFINE_FALLBACK_I32(Isinf) +DEFINE_FALLBACK_I32(Isnan) +DEFINE_FALLBACK_F128(J0) +DEFINE_FALLBACK_F128(J1) +DEFINE_FALLBACK_F128(Jn) +DEFINE_FALLBACK_F128(Ldexp) +DEFINE_FALLBACK_F128(Lgamma) +DEFINE_FALLBACK_I64(Llround) +DEFINE_FALLBACK_F128(Log) +DEFINE_FALLBACK_F128(Log10) +DEFINE_FALLBACK_I32(Lround) +DEFINE_FALLBACK_F128(Nextafter) +DEFINE_FALLBACK_F128(Pow) +DEFINE_FALLBACK_F128(Qnan) +DEFINE_FALLBACK_F128(Round) +DEFINE_FALLBACK_F128(Sin) +DEFINE_FALLBACK_F128(Sinh) +DEFINE_FALLBACK_F128(Sqrt) +DEFINE_FALLBACK_F128(Tan) +DEFINE_FALLBACK_F128(Tanh) +DEFINE_FALLBACK_F128(Tgamma) +DEFINE_FALLBACK_F128(Trunc) +DEFINE_FALLBACK_F128(Y0) +DEFINE_FALLBACK_F128(Y1) +DEFINE_FALLBACK_F128(Yn) + +#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) -#if HAS_LIBM +// 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. -#include -#include +#include -#if LDBL_MANT_DIG == 113 // 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. +DEFINE_SIMPLE_ALIAS(Abs, std::abs) DEFINE_SIMPLE_ALIAS(Acos, std::acos) DEFINE_SIMPLE_ALIAS(Acosh, std::acosh) DEFINE_SIMPLE_ALIAS(Asin, std::asin) @@ -106,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) @@ -116,15 +177,21 @@ DEFINE_SIMPLE_ALIAS(Erf, std::erf) DEFINE_SIMPLE_ALIAS(Erfc, std::erfc) DEFINE_SIMPLE_ALIAS(Exp, std::exp) DEFINE_SIMPLE_ALIAS(Floor, std::floor) +DEFINE_SIMPLE_ALIAS(Frexp, std::frexp) DEFINE_SIMPLE_ALIAS(Hypot, std::hypot) +DEFINE_SIMPLE_ALIAS(Ilogb, std::ilogb) +DEFINE_SIMPLE_ALIAS(Isinf, std::isinf) +DEFINE_SIMPLE_ALIAS(Isnan, std::isnan) DEFINE_SIMPLE_ALIAS(J0, j0l) DEFINE_SIMPLE_ALIAS(J1, j1l) DEFINE_SIMPLE_ALIAS(Jn, jnl) +DEFINE_SIMPLE_ALIAS(Ldexp, std::ldexp) DEFINE_SIMPLE_ALIAS(Lgamma, std::lgamma) DEFINE_SIMPLE_ALIAS(Llround, std::llround) -DEFINE_SIMPLE_ALIAS(Lround, std::lround) DEFINE_SIMPLE_ALIAS(Log, std::log) DEFINE_SIMPLE_ALIAS(Log10, std::log10) +DEFINE_SIMPLE_ALIAS(Lround, std::lround) +DEFINE_SIMPLE_ALIAS(Nextafter, std::nextafter) DEFINE_SIMPLE_ALIAS(Pow, std::pow) DEFINE_SIMPLE_ALIAS(Round, std::round) DEFINE_SIMPLE_ALIAS(Sin, std::sin) @@ -137,60 +204,19 @@ DEFINE_SIMPLE_ALIAS(Trunc, std::trunc) DEFINE_SIMPLE_ALIAS(Y0, y0l) DEFINE_SIMPLE_ALIAS(Y1, y1l) DEFINE_SIMPLE_ALIAS(Yn, ynl) -#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 +// Use numeric_limits to produce infinity of the right type. +#define F128_RT_INFINITY \ + (std::numeric_limits>::infinity()) +#define F128_RT_QNAN \ + (std::numeric_limits>::quiet_NaN()) +#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(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(Hypot, hypotq) -DEFINE_SIMPLE_ALIAS(J0, j0q) -DEFINE_SIMPLE_ALIAS(J1, j1q) -DEFINE_SIMPLE_ALIAS(Jn, jnq) -DEFINE_SIMPLE_ALIAS(Lgamma, lgammaq) -DEFINE_SIMPLE_ALIAS(Llround, llroundq) -DEFINE_SIMPLE_ALIAS(Lround, lroundq) -DEFINE_SIMPLE_ALIAS(Log, logq) -DEFINE_SIMPLE_ALIAS(Log10, log10q) -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) +#error "Float128Math build with glibc>=2.26 is unsupported yet" #endif + } // namespace Fortran::runtime #endif // FORTRAN_RUNTIME_FLOAT128MATH_MATH_ENTRIES_H_ diff --git a/flang/runtime/Float128Math/cabs.cpp b/flang/runtime/Float128Math/mod-real.cpp similarity index 57% rename from flang/runtime/Float128Math/cabs.cpp rename to flang/runtime/Float128Math/mod-real.cpp index 827b197a6a81a..42e6ce76e2fa1 100644 --- a/flang/runtime/Float128Math/cabs.cpp +++ b/flang/runtime/Float128Math/mod-real.cpp @@ -1,4 +1,4 @@ -//===-- runtime/Float128Math/cabs.cpp -------------------------------------===// +//===-- runtime/Float128Math/mod-real.cpp ---------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -7,18 +7,18 @@ //===----------------------------------------------------------------------===// #include "math-entries.h" +#include "numeric-template-specs.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); +// MOD (16.9.135) +F128Type RTDEF(ModReal16)( + F128Type x, F128Type p, const char *sourceFile, int sourceLine) { + return RealMod(x, p, sourceFile, sourceLine); } #endif -#endif + } // extern "C" } // namespace Fortran::runtime diff --git a/flang/runtime/Float128Math/modulo-real.cpp b/flang/runtime/Float128Math/modulo-real.cpp new file mode 100644 index 0000000000000..13000aba8c832 --- /dev/null +++ b/flang/runtime/Float128Math/modulo-real.cpp @@ -0,0 +1,24 @@ +//===-- runtime/Float128Math/modulo-real.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" +#include "numeric-template-specs.h" + +namespace Fortran::runtime { +extern "C" { + +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +// MODULO (16.9.136) +F128Type RTDEF(ModuloReal16)( + F128Type x, F128Type p, const char *sourceFile, int sourceLine) { + return RealMod(x, p, sourceFile, sourceLine); +} +#endif + +} // extern "C" +} // namespace Fortran::runtime diff --git a/flang/runtime/Float128Math/nearest.cpp b/flang/runtime/Float128Math/nearest.cpp new file mode 100644 index 0000000000000..148ac4ef83916 --- /dev/null +++ b/flang/runtime/Float128Math/nearest.cpp @@ -0,0 +1,23 @@ +//===-- runtime/Float128Math/nearest.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 LDBL_MANT_DIG == 113 || HAS_FLOAT128 +CppTypeFor RTDEF(Nearest16)( + CppTypeFor x, bool positive) { + return Nextafter::invoke( + x, positive ? F128_RT_INFINITY : -F128_RT_INFINITY); +} +#endif + +} // extern "C" +} // namespace Fortran::runtime diff --git a/flang/runtime/Float128Math/norm2.cpp b/flang/runtime/Float128Math/norm2.cpp new file mode 100644 index 0000000000000..15c482f7f007c --- /dev/null +++ b/flang/runtime/Float128Math/norm2.cpp @@ -0,0 +1,35 @@ +//===-- runtime/Float128Math/norm2.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" +#include "numeric-template-specs.h" +#include "reduction-templates.h" + +namespace Fortran::runtime { +extern "C" { + +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +CppTypeFor RTDEF(Norm2_16)( + const Descriptor &x, const char *source, int line, int dim) { + return GetTotalReduction( + x, source, line, dim, nullptr, Norm2Accumulator<16>{x}, "NORM2"); +} + +void RTDEF(Norm2DimReal16)(Descriptor &result, const Descriptor &x, int dim, + const char *source, int line) { + Terminator terminator{source, line}; + auto type{x.type().GetCategoryAndKind()}; + RUNTIME_CHECK(terminator, type); + RUNTIME_CHECK( + terminator, type->first == TypeCategory::Real && type->second == 16); + Norm2Helper<16>{}(result, x, dim, nullptr, terminator); +} +#endif + +} // extern "C" +} // namespace Fortran::runtime diff --git a/flang/runtime/Float128Math/numeric-template-specs.h b/flang/runtime/Float128Math/numeric-template-specs.h new file mode 100644 index 0000000000000..a0a77230c3e9e --- /dev/null +++ b/flang/runtime/Float128Math/numeric-template-specs.h @@ -0,0 +1,55 @@ +//===-- runtime/Float128Math/numeric-template-specs.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_NUMERIC_TEMPLATE_SPECS_H_ +#define FORTRAN_RUNTIME_FLOAT128MATH_NUMERIC_TEMPLATE_SPECS_H_ + +#include "math-entries.h" +#include "numeric-templates.h" + +namespace Fortran::runtime { +using F128Type = CppTypeFor; + +template <> struct ABSTy { + static F128Type compute(F128Type x) { return Abs::invoke(x); } +}; + +template <> struct FREXPTy { + static F128Type compute(F128Type x, int *e) { + return Frexp::invoke(x, e); + } +}; + +template <> struct ILOGBTy { + static int compute(F128Type x) { return Ilogb::invoke(x); } +}; + +template <> struct ISINFTy { + static bool compute(F128Type x) { return Isinf::invoke(x); } +}; + +template <> struct ISNANTy { + static bool compute(F128Type x) { return Isnan::invoke(x); } +}; + +template <> struct LDEXPTy { + template static F128Type compute(F128Type x, ET p) { + return Ldexp::invoke(x, p); + } +}; + +template <> struct QNANTy { + static F128Type compute() { return F128_RT_QNAN; } +}; + +template <> struct SQRTTy { + static F128Type compute(F128Type x) { return Sqrt::invoke(x); } +}; + +} // namespace Fortran::runtime +#endif // FORTRAN_RUNTIME_FLOAT128MATH_NUMERIC_TEMPLATE_SPECS_H_ diff --git a/flang/runtime/Float128Math/pow.cpp b/flang/runtime/Float128Math/pow.cpp index 02958a890e522..7a48828ee3e76 100644 --- a/flang/runtime/Float128Math/pow.cpp +++ b/flang/runtime/Float128Math/pow.cpp @@ -15,7 +15,7 @@ extern "C" { CppTypeFor RTDEF(PowF128)( CppTypeFor x, CppTypeFor y) { - return Pow::invoke(x, y); + return Pow::invoke(x, y); } #endif diff --git a/flang/runtime/Float128Math/round.cpp b/flang/runtime/Float128Math/round.cpp index 43ab57768cb77..6420c1bc9cd25 100644 --- a/flang/runtime/Float128Math/round.cpp +++ b/flang/runtime/Float128Math/round.cpp @@ -18,7 +18,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(RoundF128)( CppTypeFor x) { - return Round::invoke(x); + return Round::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/rrspacing.cpp b/flang/runtime/Float128Math/rrspacing.cpp new file mode 100644 index 0000000000000..feddac418eec3 --- /dev/null +++ b/flang/runtime/Float128Math/rrspacing.cpp @@ -0,0 +1,21 @@ +//===-- runtime/Float128Math/rrspacing.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" +#include "numeric-template-specs.h" + +namespace Fortran::runtime { +extern "C" { + +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +// FRACTION (16.9.80) +F128Type RTDEF(RRSpacing16)(F128Type x) { return RRSpacing<113>(x); } +#endif + +} // extern "C" +} // namespace Fortran::runtime diff --git a/flang/runtime/Float128Math/scale.cpp b/flang/runtime/Float128Math/scale.cpp new file mode 100644 index 0000000000000..0be958bd9f2a7 --- /dev/null +++ b/flang/runtime/Float128Math/scale.cpp @@ -0,0 +1,28 @@ +//===-- runtime/Float128Math/scale.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" +#include "numeric-template-specs.h" +#include + +namespace Fortran::runtime { +extern "C" { + +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +F128Type RTDEF(Scale16)(F128Type x, std::int64_t p) { + auto ip{static_cast(p)}; + if (ip != p) { + ip = p < 0 ? std::numeric_limits::min() + : std::numeric_limits::max(); + } + return LDEXPTy::compute(x, ip); +} +#endif + +} // extern "C" +} // namespace Fortran::runtime diff --git a/flang/runtime/Float128Math/set-exponent.cpp b/flang/runtime/Float128Math/set-exponent.cpp new file mode 100644 index 0000000000000..99c34af7962b9 --- /dev/null +++ b/flang/runtime/Float128Math/set-exponent.cpp @@ -0,0 +1,23 @@ +//===-- runtime/Float128Math/set-exponent.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" +#include "numeric-template-specs.h" + +namespace Fortran::runtime { +extern "C" { + +#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); +} +#endif + +} // extern "C" +} // namespace Fortran::runtime diff --git a/flang/runtime/Float128Math/sin.cpp b/flang/runtime/Float128Math/sin.cpp index 013eb9d119a6a..8ebc3f9881586 100644 --- a/flang/runtime/Float128Math/sin.cpp +++ b/flang/runtime/Float128Math/sin.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(SinF128)( CppTypeFor x) { - return Sin::invoke(x); + return Sin::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/sinh.cpp b/flang/runtime/Float128Math/sinh.cpp index 9c907041fd7eb..aa716a3e51ef5 100644 --- a/flang/runtime/Float128Math/sinh.cpp +++ b/flang/runtime/Float128Math/sinh.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(SinhF128)( CppTypeFor x) { - return Sinh::invoke(x); + return Sinh::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/spacing.cpp b/flang/runtime/Float128Math/spacing.cpp new file mode 100644 index 0000000000000..a86c0b30e567a --- /dev/null +++ b/flang/runtime/Float128Math/spacing.cpp @@ -0,0 +1,21 @@ +//===-- runtime/Float128Math/spacing.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" +#include "numeric-template-specs.h" + +namespace Fortran::runtime { +extern "C" { + +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +// SPACING (16.9.180) +F128Type RTDEF(Spacing16)(F128Type x) { return Spacing<113>(x); } +#endif + +} // extern "C" +} // namespace Fortran::runtime diff --git a/flang/runtime/Float128Math/sqrt.cpp b/flang/runtime/Float128Math/sqrt.cpp index aafbd850ca973..83165a4c62319 100644 --- a/flang/runtime/Float128Math/sqrt.cpp +++ b/flang/runtime/Float128Math/sqrt.cpp @@ -7,15 +7,13 @@ //===----------------------------------------------------------------------===// #include "math-entries.h" +#include "numeric-template-specs.h" namespace Fortran::runtime { extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 -CppTypeFor RTDEF(SqrtF128)( - CppTypeFor x) { - return Sqrt::invoke(x); -} +F128Type RTDEF(SqrtF128)(F128Type x) { return SQRTTy::compute(x); } #endif } // extern "C" diff --git a/flang/runtime/Float128Math/tan.cpp b/flang/runtime/Float128Math/tan.cpp index 01d3c7bdd2e85..8f4b723ca977b 100644 --- a/flang/runtime/Float128Math/tan.cpp +++ b/flang/runtime/Float128Math/tan.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(TanF128)( CppTypeFor x) { - return Tan::invoke(x); + return Tan::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/tanh.cpp b/flang/runtime/Float128Math/tanh.cpp index fedc1a4120caf..b43a89520b679 100644 --- a/flang/runtime/Float128Math/tanh.cpp +++ b/flang/runtime/Float128Math/tanh.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(TanhF128)( CppTypeFor x) { - return Tanh::invoke(x); + return Tanh::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/tgamma.cpp b/flang/runtime/Float128Math/tgamma.cpp index 329defff38cf9..93f97800bdc96 100644 --- a/flang/runtime/Float128Math/tgamma.cpp +++ b/flang/runtime/Float128Math/tgamma.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(TgammaF128)( CppTypeFor x) { - return Tgamma::invoke(x); + return Tgamma::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/trunc.cpp b/flang/runtime/Float128Math/trunc.cpp index 3cab219ce31c2..ca15a739c030e 100644 --- a/flang/runtime/Float128Math/trunc.cpp +++ b/flang/runtime/Float128Math/trunc.cpp @@ -18,7 +18,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(TruncF128)( CppTypeFor x) { - return Trunc::invoke(x); + return Trunc::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/y0.cpp b/flang/runtime/Float128Math/y0.cpp index f3e2ee454aeab..d6f39aac1053a 100644 --- a/flang/runtime/Float128Math/y0.cpp +++ b/flang/runtime/Float128Math/y0.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(Y0F128)( CppTypeFor x) { - return Y0::invoke(x); + return Y0::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/y1.cpp b/flang/runtime/Float128Math/y1.cpp index c117bbcb2b5a8..477d36a9ea3c6 100644 --- a/flang/runtime/Float128Math/y1.cpp +++ b/flang/runtime/Float128Math/y1.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(Y1F128)( CppTypeFor x) { - return Y1::invoke(x); + return Y1::invoke(x); } #endif diff --git a/flang/runtime/Float128Math/yn.cpp b/flang/runtime/Float128Math/yn.cpp index 237bc2866a0d5..3a040cc885897 100644 --- a/flang/runtime/Float128Math/yn.cpp +++ b/flang/runtime/Float128Math/yn.cpp @@ -14,7 +14,7 @@ extern "C" { #if LDBL_MANT_DIG == 113 || HAS_FLOAT128 CppTypeFor RTDEF(YnF128)( int n, CppTypeFor x) { - return Yn::invoke(n, x); + return Yn::invoke(n, x); } #endif diff --git a/flang/runtime/extrema.cpp b/flang/runtime/extrema.cpp index 3fdc8e159866d..61afb0458430d 100644 --- a/flang/runtime/extrema.cpp +++ b/flang/runtime/extrema.cpp @@ -424,62 +424,6 @@ RT_EXT_API_GROUP_END // MAXVAL and MINVAL -template -struct MaxOrMinIdentity { - using Type = CppTypeFor; - static constexpr RT_API_ATTRS Type Value() { - return IS_MAXVAL ? std::numeric_limits::lowest() - : std::numeric_limits::max(); - } -}; - -// std::numeric_limits<> may not know int128_t -template -struct MaxOrMinIdentity { - using Type = CppTypeFor; - static constexpr RT_API_ATTRS Type Value() { - return IS_MAXVAL ? Type{1} << 127 : ~Type{0} >> 1; - } -}; - -#if HAS_FLOAT128 -// std::numeric_limits<> may not support __float128. -// -// Usage of GCC quadmath.h's FLT128_MAX is complicated by the fact that -// even GCC complains about 'Q' literal suffix under -Wpedantic. -// We just recreate FLT128_MAX ourselves. -// -// This specialization must engage only when -// CppTypeFor is __float128. -template -struct MaxOrMinIdentity, __float128>>> { - using Type = __float128; - static RT_API_ATTRS Type Value() { - // Create a buffer to store binary representation of __float128 constant. - constexpr std::size_t alignment = - std::max(alignof(Type), alignof(std::uint64_t)); - alignas(alignment) char data[sizeof(Type)]; - - // First, verify that our interpretation of __float128 format is correct, - // e.g. by checking at least one known constant. - *reinterpret_cast(data) = Type(1.0); - if (*reinterpret_cast(data) != 0 || - *(reinterpret_cast(data) + 1) != 0x3FFF000000000000) { - Terminator terminator{__FILE__, __LINE__}; - terminator.Crash("not yet implemented: no full support for __float128"); - } - - // Recreate FLT128_MAX. - *reinterpret_cast(data) = 0xFFFFFFFFFFFFFFFF; - *(reinterpret_cast(data) + 1) = 0x7FFEFFFFFFFFFFFF; - Type max = *reinterpret_cast(data); - return IS_MAXVAL ? -max : max; - } -}; -#endif // HAS_FLOAT128 - template class NumericExtremumAccumulator { public: @@ -528,35 +472,6 @@ inline RT_API_ATTRS CppTypeFor TotalNumericMaxOrMin( NumericExtremumAccumulator{x}, intrinsic); } -template -static RT_API_ATTRS void DoMaxMinNorm2(Descriptor &result, const Descriptor &x, - int dim, const Descriptor *mask, const char *intrinsic, - Terminator &terminator) { - using Type = CppTypeFor; - ACCUMULATOR accumulator{x}; - if (dim == 0 || x.rank() == 1) { - // Total reduction - - // Element size of the destination descriptor is the same - // as the element size of the source. - result.Establish(x.type(), x.ElementBytes(), nullptr, 0, nullptr, - CFI_attribute_allocatable); - if (int stat{result.Allocate()}) { - terminator.Crash( - "%s: could not allocate memory for result; STAT=%d", intrinsic, stat); - } - DoTotalReduction(x, dim, mask, accumulator, intrinsic, terminator); - accumulator.GetResult(result.OffsetElement()); - } else { - // Partial reduction - - // Element size of the destination descriptor is the same - // as the element size of the source. - PartialReduction(result, x, x.ElementBytes(), dim, - mask, terminator, intrinsic, accumulator); - } -} - template struct MaxOrMinHelper { template struct Functor { RT_API_ATTRS void operator()(Descriptor &result, const Descriptor &x, @@ -802,70 +717,6 @@ RT_EXT_API_GROUP_END // NORM2 -RT_VAR_GROUP_BEGIN - -// Use at least double precision for accumulators. -// Don't use __float128, it doesn't work with abs() or sqrt() yet. -static constexpr RT_CONST_VAR_ATTRS int largestLDKind { -#if LDBL_MANT_DIG == 113 - 16 -#elif LDBL_MANT_DIG == 64 - 10 -#else - 8 -#endif -}; - -RT_VAR_GROUP_END - -template class Norm2Accumulator { -public: - using Type = CppTypeFor; - using AccumType = - CppTypeFor; - explicit RT_API_ATTRS Norm2Accumulator(const Descriptor &array) - : array_{array} {} - RT_API_ATTRS void Reinitialize() { max_ = sum_ = 0; } - template - RT_API_ATTRS void GetResult(A *p, int /*zeroBasedDim*/ = -1) const { - // m * sqrt(1 + sum((others(:)/m)**2)) - *p = static_cast(max_ * std::sqrt(1 + sum_)); - } - RT_API_ATTRS bool Accumulate(Type x) { - auto absX{std::abs(static_cast(x))}; - if (!max_) { - max_ = absX; - } else if (absX > max_) { - auto t{max_ / absX}; // < 1.0 - auto tsq{t * t}; - sum_ *= tsq; // scale sum to reflect change to the max - sum_ += tsq; // include a term for the previous max - max_ = absX; - } else { // absX <= max_ - auto t{absX / max_}; - sum_ += t * t; - } - return true; - } - template - RT_API_ATTRS bool AccumulateAt(const SubscriptValue at[]) { - return Accumulate(*array_.Element(at)); - } - -private: - const Descriptor &array_; - AccumType max_{0}; // value (m) with largest magnitude - AccumType sum_{0}; // sum((others(:)/m)**2) -}; - -template struct Norm2Helper { - RT_API_ATTRS void operator()(Descriptor &result, const Descriptor &x, int dim, - const Descriptor *mask, Terminator &terminator) const { - DoMaxMinNorm2>( - result, x, dim, mask, "NORM2", terminator); - } -}; - extern "C" { RT_EXT_API_GROUP_BEGIN @@ -887,13 +738,6 @@ CppTypeFor RTDEF(Norm2_10)( x, source, line, dim, nullptr, Norm2Accumulator<10>{x}, "NORM2"); } #endif -#if LDBL_MANT_DIG == 113 -CppTypeFor RTDEF(Norm2_16)( - const Descriptor &x, const char *source, int line, int dim) { - return GetTotalReduction( - x, source, line, dim, nullptr, Norm2Accumulator<16>{x}, "NORM2"); -} -#endif void RTDEF(Norm2Dim)(Descriptor &result, const Descriptor &x, int dim, const char *source, int line) { @@ -901,7 +745,7 @@ void RTDEF(Norm2Dim)(Descriptor &result, const Descriptor &x, int dim, auto type{x.type().GetCategoryAndKind()}; RUNTIME_CHECK(terminator, type); if (type->first == TypeCategory::Real) { - ApplyFloatingPointKind( + ApplyFloatingPointKind( type->second, terminator, result, x, dim, nullptr, terminator); } else { terminator.Crash("NORM2: bad type code %d", x.type().raw()); diff --git a/flang/runtime/numeric-templates.h b/flang/runtime/numeric-templates.h new file mode 100644 index 0000000000000..ecc3b2654d965 --- /dev/null +++ b/flang/runtime/numeric-templates.h @@ -0,0 +1,340 @@ +//===-- runtime/numeric-templates.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 +// +//===----------------------------------------------------------------------===// + +// Generic class and function templates used for implementing +// various numeric intrinsics (EXPONENT, FRACTION, etc.). +// +// This header file also defines generic templates for "basic" +// math operations like abs, isnan, etc. The Float128Math +// library provides specializations for these templates +// for the data type corresponding to CppTypeFor +// on the target. + +#ifndef FORTRAN_RUNTIME_NUMERIC_TEMPLATES_H_ +#define FORTRAN_RUNTIME_NUMERIC_TEMPLATES_H_ + +#include "terminator.h" +#include "tools.h" +#include "flang/Common/float128.h" +#include "flang/Runtime/api-attrs.h" +#include +#include + +namespace Fortran::runtime { + +// MAX/MIN/LOWEST values for different data types. + +// MaxOrMinIdentity returns MAX or LOWEST value of the given type. +template +struct MaxOrMinIdentity { + using Type = CppTypeFor; + static constexpr RT_API_ATTRS Type Value() { + return IS_MAXVAL ? std::numeric_limits::lowest() + : std::numeric_limits::max(); + } +}; + +// std::numeric_limits<> may not know int128_t +template +struct MaxOrMinIdentity { + using Type = CppTypeFor; + static constexpr RT_API_ATTRS Type Value() { + return IS_MAXVAL ? Type{1} << 127 : ~Type{0} >> 1; + } +}; + +#if HAS_FLOAT128 +// std::numeric_limits<> may not support __float128. +// +// Usage of GCC quadmath.h's FLT128_MAX is complicated by the fact that +// even GCC complains about 'Q' literal suffix under -Wpedantic. +// We just recreate FLT128_MAX ourselves. +// +// This specialization must engage only when +// CppTypeFor is __float128. +template +struct MaxOrMinIdentity, __float128>>> { + using Type = __float128; + static RT_API_ATTRS Type Value() { + // Create a buffer to store binary representation of __float128 constant. + constexpr std::size_t alignment = + std::max(alignof(Type), alignof(std::uint64_t)); + alignas(alignment) char data[sizeof(Type)]; + + // First, verify that our interpretation of __float128 format is correct, + // e.g. by checking at least one known constant. + *reinterpret_cast(data) = Type(1.0); + if (*reinterpret_cast(data) != 0 || + *(reinterpret_cast(data) + 1) != 0x3FFF000000000000) { + Terminator terminator{__FILE__, __LINE__}; + terminator.Crash("not yet implemented: no full support for __float128"); + } + + // Recreate FLT128_MAX. + *reinterpret_cast(data) = 0xFFFFFFFFFFFFFFFF; + *(reinterpret_cast(data) + 1) = 0x7FFEFFFFFFFFFFFF; + Type max = *reinterpret_cast(data); + return IS_MAXVAL ? -max : max; + } +}; +#endif // HAS_FLOAT128 + +// Minimum finite representable value. +// For floating-point types, returns minimum positive normalized value. +template struct MinValue { + static RT_API_ATTRS T get() { return std::numeric_limits::min(); } +}; + +#if HAS_FLOAT128 +template <> struct MinValue> { + using Type = CppTypeFor; + static RT_API_ATTRS Type get() { + // Create a buffer to store binary representation of __float128 constant. + constexpr std::size_t alignment = + std::max(alignof(Type), alignof(std::uint64_t)); + alignas(alignment) char data[sizeof(Type)]; + + // First, verify that our interpretation of __float128 format is correct, + // e.g. by checking at least one known constant. + *reinterpret_cast(data) = Type(1.0); + if (*reinterpret_cast(data) != 0 || + *(reinterpret_cast(data) + 1) != 0x3FFF000000000000) { + Terminator terminator{__FILE__, __LINE__}; + terminator.Crash("not yet implemented: no full support for __float128"); + } + + // Recreate FLT128_MIN. + *reinterpret_cast(data) = 0; + *(reinterpret_cast(data) + 1) = 0x1000000000000; + return *reinterpret_cast(data); + } +}; +#endif // HAS_FLOAT128 + +template struct ABSTy { + static constexpr RT_API_ATTRS T compute(T x) { return std::abs(x); } +}; + +template struct FREXPTy { + static constexpr RT_API_ATTRS T compute(T x, int *e) { + return std::frexp(x, e); + } +}; + +template struct ILOGBTy { + static constexpr RT_API_ATTRS int compute(T x) { return std::ilogb(x); } +}; + +template struct ISINFTy { + static constexpr RT_API_ATTRS bool compute(T x) { return std::isinf(x); } +}; + +template struct ISNANTy { + static constexpr RT_API_ATTRS bool compute(T x) { return std::isnan(x); } +}; + +template struct LDEXPTy { + template static constexpr RT_API_ATTRS T compute(T x, ET e) { + return std::ldexp(x, e); + } +}; + +template struct MAXTy { + static constexpr RT_API_ATTRS T compute() { + return std::numeric_limits::max(); + } +}; + +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 +template <> struct MAXTy> { + static CppTypeFor compute() { + return MaxOrMinIdentity::Value(); + } +}; +#endif + +template struct MINTy { + static constexpr RT_API_ATTRS T compute() { return MinValue::get(); } +}; + +template struct QNANTy { + static constexpr RT_API_ATTRS T compute() { + return std::numeric_limits::quiet_NaN(); + } +}; + +template struct SQRTTy { + static constexpr RT_API_ATTRS T compute(T x) { return std::sqrt(x); } +}; + +// EXPONENT (16.9.75) +template +inline RT_API_ATTRS RESULT Exponent(ARG x) { + if (ISINFTy::compute(x) || ISNANTy::compute(x)) { + return MAXTy::compute(); // +/-Inf, NaN -> HUGE(0) + } else if (x == 0) { + return 0; // 0 -> 0 + } else { + return ILOGBTy::compute(x) + 1; + } +} + +// Suppress the warnings about calling __host__-only std::frexp, +// defined in C++ STD header files, from __device__ code. +RT_DIAG_PUSH +RT_DIAG_DISABLE_CALL_HOST_FROM_DEVICE_WARN + +// FRACTION (16.9.80) +template inline RT_API_ATTRS T Fraction(T x) { + if (ISNANTy::compute(x)) { + return x; // NaN -> same NaN + } else if (ISINFTy::compute(x)) { + return QNANTy::compute(); // +/-Inf -> NaN + } else if (x == 0) { + return x; // 0 -> same 0 + } else { + int ignoredExp; + return FREXPTy::compute(x, &ignoredExp); + } +} + +RT_DIAG_POP + +// SET_EXPONENT (16.9.171) +template inline RT_API_ATTRS T SetExponent(T x, std::int64_t p) { + if (ISNANTy::compute(x)) { + return x; // NaN -> same NaN + } else if (ISINFTy::compute(x)) { + return QNANTy::compute(); // +/-Inf -> NaN + } else if (x == 0) { + return x; // return negative zero if x is negative zero + } else { + int expo{ILOGBTy::compute(x) + 1}; + auto ip{static_cast(p - expo)}; + if (ip != p - expo) { + ip = p < 0 ? std::numeric_limits::min() + : std::numeric_limits::max(); + } + return LDEXPTy::compute(x, ip); // x*2**(p-e) + } +} + +// MOD & MODULO (16.9.135, .136) +template +inline RT_API_ATTRS T RealMod( + T a, T p, const char *sourceFile, int sourceLine) { + if (p == 0) { + Terminator{sourceFile, sourceLine}.Crash( + IS_MODULO ? "MODULO with P==0" : "MOD with P==0"); + } + if (ISNANTy::compute(a) || ISNANTy::compute(p) || + ISINFTy::compute(a)) { + return QNANTy::compute(); + } else if (ISINFTy::compute(p)) { + return a; + } + T aAbs{ABSTy::compute(a)}; + T pAbs{ABSTy::compute(p)}; + if (aAbs <= static_cast(std::numeric_limits::max()) && + pAbs <= static_cast(std::numeric_limits::max())) { + if (auto aInt{static_cast(a)}; a == aInt) { + if (auto pInt{static_cast(p)}; p == pInt) { + // Fast exact case for integer operands + auto mod{aInt - (aInt / pInt) * pInt}; + if (IS_MODULO && (aInt > 0) != (pInt > 0)) { + mod += pInt; + } + return static_cast(mod); + } + } + } + if constexpr (std::is_same_v || std::is_same_v || + std::is_same_v) { + // std::fmod() semantics on signed operands seems to match + // the requirements of MOD(). MODULO() needs adjustment. + T result{std::fmod(a, p)}; + if constexpr (IS_MODULO) { + if ((a < 0) != (p < 0)) { + if (result == 0.) { + result = -result; + } else { + result += p; + } + } + } + return result; + } else { + // The standard defines MOD(a,p)=a-AINT(a/p)*p and + // MODULO(a,p)=a-FLOOR(a/p)*p, but those definitions lose + // precision badly due to cancellation when ABS(a) is + // much larger than ABS(p). + // Insights: + // - MOD(a,p)=MOD(a-n*p,p) when a>0, p>0, integer n>0, and a>=n*p + // - when n is a power of two, n*p is exact + // - as a>=n*p, a-n*p does not round. + // So repeatedly reduce a by all n*p in decreasing order of n; + // what's left is the desired remainder. This is basically + // the same algorithm as arbitrary precision binary long division, + // discarding the quotient. + T tmp{aAbs}; + for (T adj{SetExponent(pAbs, Exponent(aAbs))}; tmp >= pAbs; adj /= 2) { + if (tmp >= adj) { + tmp -= adj; + if (tmp == 0) { + break; + } + } + } + if (a < 0) { + tmp = -tmp; + } + if constexpr (IS_MODULO) { + if ((a < 0) != (p < 0)) { + tmp += p; + } + } + return tmp; + } +} + +// RRSPACING (16.9.164) +template inline RT_API_ATTRS T RRSpacing(T x) { + if (ISNANTy::compute(x)) { + return x; // NaN -> same NaN + } else if (ISINFTy::compute(x)) { + return QNANTy::compute(); // +/-Inf -> NaN + } else if (x == 0) { + return 0; // 0 -> 0 + } else { + return LDEXPTy::compute( + ABSTy::compute(x), PREC - (ILOGBTy::compute(x) + 1)); + } +} + +// SPACING (16.9.180) +template inline RT_API_ATTRS T Spacing(T x) { + if (ISNANTy::compute(x)) { + return x; // NaN -> same NaN + } else if (ISINFTy::compute(x)) { + return QNANTy::compute(); // +/-Inf -> NaN + } else if (x == 0) { + // The standard-mandated behavior seems broken, since TINY() can't be + // subnormal. + return MINTy::compute(); // 0 -> TINY(x) + } else { + T result{LDEXPTy::compute( + static_cast(1.0), ILOGBTy::compute(x) + 1 - PREC)}; // 2**(e-p) + return result == 0 ? /*TINY(x)*/ MINTy::compute() : result; + } +} + +} // namespace Fortran::runtime + +#endif // FORTRAN_RUNTIME_NUMERIC_TEMPLATES_H_ diff --git a/flang/runtime/numeric.cpp b/flang/runtime/numeric.cpp index ede00d69f20e2..abd3e500029fe 100644 --- a/flang/runtime/numeric.cpp +++ b/flang/runtime/numeric.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "flang/Runtime/numeric.h" +#include "numeric-templates.h" #include "terminator.h" #include "flang/Common/float128.h" #include @@ -68,58 +69,6 @@ inline RT_API_ATTRS RESULT Floor(ARG x) { return std::floor(x); } -// EXPONENT (16.9.75) -template -inline RT_API_ATTRS RESULT Exponent(ARG x) { - if (std::isinf(x) || std::isnan(x)) { - return std::numeric_limits::max(); // +/-Inf, NaN -> HUGE(0) - } else if (x == 0) { - return 0; // 0 -> 0 - } else { - return std::ilogb(x) + 1; - } -} - -// Suppress the warnings about calling __host__-only std::frexp, -// defined in C++ STD header files, from __device__ code. -RT_DIAG_PUSH -RT_DIAG_DISABLE_CALL_HOST_FROM_DEVICE_WARN - -// FRACTION (16.9.80) -template inline RT_API_ATTRS T Fraction(T x) { - if (std::isnan(x)) { - return x; // NaN -> same NaN - } else if (std::isinf(x)) { - return std::numeric_limits::quiet_NaN(); // +/-Inf -> NaN - } else if (x == 0) { - return x; // 0 -> same 0 - } else { - int ignoredExp; - return std::frexp(x, &ignoredExp); - } -} - -RT_DIAG_POP - -// SET_EXPONENT (16.9.171) -template inline RT_API_ATTRS T SetExponent(T x, std::int64_t p) { - if (std::isnan(x)) { - return x; // NaN -> same NaN - } else if (std::isinf(x)) { - return std::numeric_limits::quiet_NaN(); // +/-Inf -> NaN - } else if (x == 0) { - return x; // return negative zero if x is negative zero - } else { - int expo{std::ilogb(x) + 1}; - auto ip{static_cast(p - expo)}; - if (ip != p - expo) { - ip = p < 0 ? std::numeric_limits::min() - : std::numeric_limits::max(); - } - return std::ldexp(x, ip); // x*2**(p-e) - } -} - // MOD & MODULO (16.9.135, .136) template inline RT_API_ATTRS T IntMod(T x, T p, const char *sourceFile, int sourceLine) { @@ -133,94 +82,6 @@ inline RT_API_ATTRS T IntMod(T x, T p, const char *sourceFile, int sourceLine) { } return mod; } -template -inline RT_API_ATTRS T RealMod( - T a, T p, const char *sourceFile, int sourceLine) { - if (p == 0) { - Terminator{sourceFile, sourceLine}.Crash( - IS_MODULO ? "MODULO with P==0" : "MOD with P==0"); - } - if (std::isnan(a) || std::isnan(p) || std::isinf(a)) { - return std::numeric_limits::quiet_NaN(); - } else if (std::isinf(p)) { - return a; - } - T aAbs{std::abs(a)}; - T pAbs{std::abs(p)}; - if (aAbs <= static_cast(std::numeric_limits::max()) && - pAbs <= static_cast(std::numeric_limits::max())) { - if (auto aInt{static_cast(a)}; a == aInt) { - if (auto pInt{static_cast(p)}; p == pInt) { - // Fast exact case for integer operands - auto mod{aInt - (aInt / pInt) * pInt}; - if (IS_MODULO && (aInt > 0) != (pInt > 0)) { - mod += pInt; - } - return static_cast(mod); - } - } - } - if constexpr (std::is_same_v || std::is_same_v || - std::is_same_v) { - // std::fmod() semantics on signed operands seems to match - // the requirements of MOD(). MODULO() needs adjustment. - T result{std::fmod(a, p)}; - if constexpr (IS_MODULO) { - if ((a < 0) != (p < 0)) { - if (result == 0.) { - result = -result; - } else { - result += p; - } - } - } - return result; - } else { - // The standard defines MOD(a,p)=a-AINT(a/p)*p and - // MODULO(a,p)=a-FLOOR(a/p)*p, but those definitions lose - // precision badly due to cancellation when ABS(a) is - // much larger than ABS(p). - // Insights: - // - MOD(a,p)=MOD(a-n*p,p) when a>0, p>0, integer n>0, and a>=n*p - // - when n is a power of two, n*p is exact - // - as a>=n*p, a-n*p does not round. - // So repeatedly reduce a by all n*p in decreasing order of n; - // what's left is the desired remainder. This is basically - // the same algorithm as arbitrary precision binary long division, - // discarding the quotient. - T tmp{aAbs}; - for (T adj{SetExponent(pAbs, Exponent(aAbs))}; tmp >= pAbs; adj /= 2) { - if (tmp >= adj) { - tmp -= adj; - if (tmp == 0) { - break; - } - } - } - if (a < 0) { - tmp = -tmp; - } - if constexpr (IS_MODULO) { - if ((a < 0) != (p < 0)) { - tmp += p; - } - } - return tmp; - } -} - -// RRSPACING (16.9.164) -template inline RT_API_ATTRS T RRSpacing(T x) { - if (std::isnan(x)) { - return x; // NaN -> same NaN - } else if (std::isinf(x)) { - return std::numeric_limits::quiet_NaN(); // +/-Inf -> NaN - } else if (x == 0) { - return 0; // 0 -> 0 - } else { - return std::ldexp(std::abs(x), PREC - (std::ilogb(x) + 1)); - } -} // SCALE (16.9.166) template inline RT_API_ATTRS T Scale(T x, std::int64_t p) { @@ -229,7 +90,7 @@ template inline RT_API_ATTRS T Scale(T x, std::int64_t p) { ip = p < 0 ? std::numeric_limits::min() : std::numeric_limits::max(); } - return std::ldexp(x, p); // x*2**p + return std::ldexp(x, ip); // x*2**p } // SELECTED_INT_KIND (16.9.169) @@ -300,23 +161,6 @@ inline RT_API_ATTRS CppTypeFor SelectedRealKind( return error ? error : kind; } -// SPACING (16.9.180) -template inline RT_API_ATTRS T Spacing(T x) { - if (std::isnan(x)) { - return x; // NaN -> same NaN - } else if (std::isinf(x)) { - return std::numeric_limits::quiet_NaN(); // +/-Inf -> NaN - } else if (x == 0) { - // The standard-mandated behavior seems broken, since TINY() can't be - // subnormal. - return std::numeric_limits::min(); // 0 -> TINY(x) - } else { - T result{ - std::ldexp(static_cast(1.0), std::ilogb(x) + 1 - PREC)}; // 2**(e-p) - return result == 0 ? /*TINY(x)*/ std::numeric_limits::min() : result; - } -} - // NEAREST (16.9.139) template inline RT_API_ATTRS T Nearest(T x, bool positive) { @@ -480,15 +324,6 @@ CppTypeFor RTDEF(Exponent10_8)( CppTypeFor x) { return Exponent>(x); } -#elif LDBL_MANT_DIG == 113 -CppTypeFor RTDEF(Exponent16_4)( - CppTypeFor x) { - return Exponent>(x); -} -CppTypeFor RTDEF(Exponent16_8)( - CppTypeFor x) { - return Exponent>(x); -} #endif CppTypeFor RTDEF(Floor4_1)( @@ -596,11 +431,6 @@ CppTypeFor RTDEF(Fraction10)( CppTypeFor x) { return Fraction(x); } -#elif LDBL_MANT_DIG == 113 -CppTypeFor RTDEF(Fraction16)( - CppTypeFor x) { - return Fraction(x); -} #endif bool RTDEF(IsFinite4)(CppTypeFor x) { @@ -683,12 +513,6 @@ CppTypeFor RTDEF(ModReal10)( const char *sourceFile, int sourceLine) { return RealMod(x, p, sourceFile, sourceLine); } -#elif LDBL_MANT_DIG == 113 -CppTypeFor RTDEF(ModReal16)( - CppTypeFor x, CppTypeFor p, - const char *sourceFile, int sourceLine) { - return RealMod(x, p, sourceFile, sourceLine); -} #endif CppTypeFor RTDEF(ModuloInteger1)( @@ -739,12 +563,6 @@ CppTypeFor RTDEF(ModuloReal10)( const char *sourceFile, int sourceLine) { return RealMod(x, p, sourceFile, sourceLine); } -#elif LDBL_MANT_DIG == 113 -CppTypeFor RTDEF(ModuloReal16)( - CppTypeFor x, CppTypeFor p, - const char *sourceFile, int sourceLine) { - return RealMod(x, p, sourceFile, sourceLine); -} #endif CppTypeFor RTDEF(Nearest4)( @@ -760,11 +578,6 @@ CppTypeFor RTDEF(Nearest10)( CppTypeFor x, bool positive) { return Nearest<64>(x, positive); } -#elif LDBL_MANT_DIG == 113 -CppTypeFor RTDEF(Nearest16)( - CppTypeFor x, bool positive) { - return Nearest<113>(x, positive); -} #endif CppTypeFor RTDEF(Nint4_1)( @@ -872,11 +685,6 @@ CppTypeFor RTDEF(RRSpacing10)( CppTypeFor x) { return RRSpacing<64>(x); } -#elif LDBL_MANT_DIG == 113 -CppTypeFor RTDEF(RRSpacing16)( - CppTypeFor x) { - return RRSpacing<113>(x); -} #endif CppTypeFor RTDEF(SetExponent4)( @@ -892,11 +700,6 @@ CppTypeFor RTDEF(SetExponent10)( CppTypeFor x, std::int64_t p) { return SetExponent(x, p); } -#elif LDBL_MANT_DIG == 113 -CppTypeFor RTDEF(SetExponent16)( - CppTypeFor x, std::int64_t p) { - return SetExponent(x, p); -} #endif CppTypeFor RTDEF(Scale4)( @@ -912,11 +715,6 @@ CppTypeFor RTDEF(Scale10)( CppTypeFor x, std::int64_t p) { return Scale(x, p); } -#elif LDBL_MANT_DIG == 113 -CppTypeFor RTDEF(Scale16)( - CppTypeFor x, std::int64_t p) { - return Scale(x, p); -} #endif // SELECTED_INT_KIND @@ -971,11 +769,6 @@ CppTypeFor RTDEF(Spacing10)( CppTypeFor x) { return Spacing<64>(x); } -#elif LDBL_MANT_DIG == 113 -CppTypeFor RTDEF(Spacing16)( - CppTypeFor x) { - return Spacing<113>(x); -} #endif CppTypeFor RTDEF(FPow4i)( diff --git a/flang/runtime/reduction-templates.h b/flang/runtime/reduction-templates.h index 7d0f82d59a084..5b793deb2a123 100644 --- a/flang/runtime/reduction-templates.h +++ b/flang/runtime/reduction-templates.h @@ -1,4 +1,4 @@ -//===-- runtime/reduction-templates.h -------------------------------------===// +//===-- runtime/reduction-templates.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. @@ -21,10 +21,12 @@ #ifndef FORTRAN_RUNTIME_REDUCTION_TEMPLATES_H_ #define FORTRAN_RUNTIME_REDUCTION_TEMPLATES_H_ +#include "numeric-templates.h" #include "terminator.h" #include "tools.h" #include "flang/Runtime/cpp-type.h" #include "flang/Runtime/descriptor.h" +#include namespace Fortran::runtime { @@ -332,5 +334,104 @@ template struct PartialLocationHelper { }; }; +// NORM2 templates + +RT_VAR_GROUP_BEGIN + +// Use at least double precision for accumulators. +// Don't use __float128, it doesn't work with abs() or sqrt() yet. +static constexpr RT_CONST_VAR_ATTRS int Norm2LargestLDKind { +#if LDBL_MANT_DIG == 113 || HAS_FLOAT128 + 16 +#elif LDBL_MANT_DIG == 64 + 10 +#else + 8 +#endif +}; + +RT_VAR_GROUP_END + +template +inline RT_API_ATTRS void DoMaxMinNorm2(Descriptor &result, const Descriptor &x, + int dim, const Descriptor *mask, const char *intrinsic, + Terminator &terminator) { + using Type = CppTypeFor; + ACCUMULATOR accumulator{x}; + if (dim == 0 || x.rank() == 1) { + // Total reduction + + // Element size of the destination descriptor is the same + // as the element size of the source. + result.Establish(x.type(), x.ElementBytes(), nullptr, 0, nullptr, + CFI_attribute_allocatable); + if (int stat{result.Allocate()}) { + terminator.Crash( + "%s: could not allocate memory for result; STAT=%d", intrinsic, stat); + } + DoTotalReduction(x, dim, mask, accumulator, intrinsic, terminator); + accumulator.GetResult(result.OffsetElement()); + } else { + // Partial reduction + + // Element size of the destination descriptor is the same + // as the element size of the source. + PartialReduction(result, x, x.ElementBytes(), dim, + mask, terminator, intrinsic, accumulator); + } +} + +// The data type used by Norm2Accumulator. +template +using Norm2AccumType = + CppTypeFor; + +template class Norm2Accumulator { +public: + using Type = CppTypeFor; + using AccumType = Norm2AccumType; + explicit RT_API_ATTRS Norm2Accumulator(const Descriptor &array) + : array_{array} {} + RT_API_ATTRS void Reinitialize() { max_ = sum_ = 0; } + template + RT_API_ATTRS void GetResult(A *p, int /*zeroBasedDim*/ = -1) const { + // m * sqrt(1 + sum((others(:)/m)**2)) + *p = static_cast(max_ * SQRTTy::compute(1 + sum_)); + } + RT_API_ATTRS bool Accumulate(Type x) { + auto absX{ABSTy::compute(static_cast(x))}; + if (!max_) { + max_ = absX; + } else if (absX > max_) { + auto t{max_ / absX}; // < 1.0 + auto tsq{t * t}; + sum_ *= tsq; // scale sum to reflect change to the max + sum_ += tsq; // include a term for the previous max + max_ = absX; + } else { // absX <= max_ + auto t{absX / max_}; + sum_ += t * t; + } + return true; + } + template + RT_API_ATTRS bool AccumulateAt(const SubscriptValue at[]) { + return Accumulate(*array_.Element(at)); + } + +private: + const Descriptor &array_; + AccumType max_{0}; // value (m) with largest magnitude + AccumType sum_{0}; // sum((others(:)/m)**2) +}; + +template struct Norm2Helper { + RT_API_ATTRS void operator()(Descriptor &result, const Descriptor &x, int dim, + const Descriptor *mask, Terminator &terminator) const { + DoMaxMinNorm2>( + result, x, dim, mask, "NORM2", terminator); + } +}; + } // namespace Fortran::runtime #endif // FORTRAN_RUNTIME_REDUCTION_TEMPLATES_H_ diff --git a/flang/runtime/tools.h b/flang/runtime/tools.h index 89e5069995748..c1f89cadca06e 100644 --- a/flang/runtime/tools.h +++ b/flang/runtime/tools.h @@ -266,7 +266,8 @@ inline RT_API_ATTRS RESULT ApplyIntegerKind( } } -template