diff --git a/.github/workflows/sync-release-repo.yml b/.github/workflows/sync-release-repo.yml new file mode 100644 index 0000000000000..4643294cd7ca2 --- /dev/null +++ b/.github/workflows/sync-release-repo.yml @@ -0,0 +1,17 @@ +name: Sync Release Repositories +permissions: + contents: write +on: + workflow_dispatch +env: + RELEASE_BRANCH: release/17.x + GH_TOKEN: ${{ secrets.RELEASE_WORKFLOW_PUSH_SECRET }} +jobs: + sync: + runs-on: ubuntu-latest + steps: + - name: Fetch LLVM sources + uses: actions/checkout@v3 + - name: Run Sync Script + run: | + llvm/utils/git/sync-release-repo.sh diff --git a/bolt/README.md b/bolt/README.md index eed46fff848f1..fe54bd82a356a 100644 --- a/bolt/README.md +++ b/bolt/README.md @@ -30,14 +30,6 @@ compiler option. Since GCC8 enables this option by default, you have to explicitly disable it by adding `-fno-reorder-blocks-and-partition` flag if you are compiling with GCC8 or above. -NOTE2: DWARF v5 is the new debugging format generated by the latest LLVM and GCC -compilers. It offers several benefits over the previous DWARF v4. Currently, the -support for v5 is a work in progress for BOLT. While you will be able to -optimize binaries produced by the latest compilers, until the support is -complete, you will not be able to update the debug info with -`-update-debug-sections`. To temporarily work around the issue, we recommend -compiling binaries with `-gdwarf-4` option that forces DWARF v4 output. - PIE and .so support has been added recently. Please report bugs if you encounter any issues. diff --git a/bolt/include/bolt/Core/AddressMap.h b/bolt/include/bolt/Core/AddressMap.h new file mode 100644 index 0000000000000..16c2727b6943f --- /dev/null +++ b/bolt/include/bolt/Core/AddressMap.h @@ -0,0 +1,59 @@ +//===- bolt/Core/AddressMap.h - Input-output address map --------*- 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 +// +//===----------------------------------------------------------------------===// +// +// Helper class to create a mapping from input to output addresses needed for +// updating debugging symbols and BAT. We emit an MCSection containing +// pairs to the object file and JITLink will +// transform this in pairs. The linker output +// can then be parsed and used to establish the mapping. +// +//===----------------------------------------------------------------------===// +// +#ifndef BOLT_CORE_ADDRESS_MAP_H +#define BOLT_CORE_ADDRESS_MAP_H + +#include "llvm/ADT/StringRef.h" + +#include +#include + +namespace llvm { + +class MCStreamer; + +namespace bolt { + +class BinaryContext; + +class AddressMap { + using MapTy = std::unordered_multimap; + MapTy Map; + +public: + static const char *const SectionName; + + static void emit(MCStreamer &Streamer, BinaryContext &BC); + static AddressMap parse(StringRef Buffer, const BinaryContext &BC); + + std::optional lookup(uint64_t InputAddress) const { + auto It = Map.find(InputAddress); + if (It != Map.end()) + return It->second; + return std::nullopt; + } + + std::pair + lookupAll(uint64_t InputAddress) const { + return Map.equal_range(InputAddress); + } +}; + +} // namespace bolt +} // namespace llvm + +#endif diff --git a/bolt/include/bolt/Core/BinaryBasicBlock.h b/bolt/include/bolt/Core/BinaryBasicBlock.h index 02be9c1d4f118..bc95e2c4de3a1 100644 --- a/bolt/include/bolt/Core/BinaryBasicBlock.h +++ b/bolt/include/bolt/Core/BinaryBasicBlock.h @@ -100,16 +100,6 @@ class BinaryBasicBlock { using LocSymsTy = std::vector>; std::unique_ptr LocSyms; - /// After output/codegen, map output offsets of instructions in this basic - /// block to instruction offsets in the original function. Note that the - /// output basic block could be different from the input basic block. - /// We only map instruction of interest, such as calls and markers. - /// - /// We store the offset array in a basic block to facilitate BAT tables - /// generation. Otherwise, the mapping could be done at function level. - using OffsetTranslationTableTy = std::vector>; - std::unique_ptr OffsetTranslationTable; - /// Alignment requirements for the block. uint32_t Alignment{1}; @@ -828,8 +818,7 @@ class BinaryBasicBlock { return OutputAddressRange; } - /// Update addresses of special instructions inside this basic block. - void updateOutputValues(const MCAsmLayout &Layout); + bool hasLocSyms() const { return LocSyms != nullptr; } /// Return mapping of input offsets to symbols in the output. LocSymsTy &getLocSyms() { @@ -841,19 +830,6 @@ class BinaryBasicBlock { return const_cast(this)->getLocSyms(); } - /// Return offset translation table for the basic block. - OffsetTranslationTableTy &getOffsetTranslationTable() { - return OffsetTranslationTable - ? *OffsetTranslationTable - : *(OffsetTranslationTable = - std::make_unique()); - } - - /// Return offset translation table for the basic block. - const OffsetTranslationTableTy &getOffsetTranslationTable() const { - return const_cast(this)->getOffsetTranslationTable(); - } - /// Return size of the basic block in the output binary. uint64_t getOutputSize() const { return OutputAddressRange.second - OutputAddressRange.first; diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h index 7bbfb2fc33eef..ef57ff3541dc8 100644 --- a/bolt/include/bolt/Core/BinaryContext.h +++ b/bolt/include/bolt/Core/BinaryContext.h @@ -13,6 +13,7 @@ #ifndef BOLT_CORE_BINARY_CONTEXT_H #define BOLT_CORE_BINARY_CONTEXT_H +#include "bolt/Core/AddressMap.h" #include "bolt/Core/BinaryData.h" #include "bolt/Core/BinarySection.h" #include "bolt/Core/DebugData.h" @@ -221,6 +222,9 @@ class BinaryContext { bool ContainsDwarf5{false}; bool ContainsDwarfLegacy{false}; + /// Mapping from input to output addresses. + std::optional IOAddressMap; + /// Preprocess DWO debug information. void preprocessDWODebugInfo(); @@ -1343,6 +1347,12 @@ class BinaryContext { /* DWARFMustBeAtTheEnd */ false)); return Streamer; } + + void setIOAddressMap(AddressMap Map) { IOAddressMap = std::move(Map); } + const AddressMap &getIOAddressMap() const { + assert(IOAddressMap && "Address map not set yet"); + return *IOAddressMap; + } }; template > diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h index bbb5f99556d9c..9b45467a6a8fb 100644 --- a/bolt/include/bolt/Core/BinaryFunction.h +++ b/bolt/include/bolt/Core/BinaryFunction.h @@ -366,14 +366,15 @@ class BinaryFunction { std::string ColdCodeSectionName; /// Parent function fragment for split function fragments. - SmallPtrSet ParentFragments; + using FragmentsSetTy = SmallPtrSet; + FragmentsSetTy ParentFragments; /// Indicate if the function body was folded into another function. /// Used by ICF optimization. BinaryFunction *FoldedIntoFunction{nullptr}; /// All fragments for a parent function. - SmallPtrSet Fragments; + FragmentsSetTy Fragments; /// The profile data for the number of times the function was executed. uint64_t ExecutionCount{COUNT_NO_PROFILE}; @@ -576,9 +577,6 @@ class BinaryFunction { /// Count the number of functions created. static uint64_t Count; - /// Map offsets of special instructions to addresses in the output. - InputOffsetToAddressMapTy InputOffsetToAddressMap; - /// Register alternative function name. void addAlternativeName(std::string NewName) { Aliases.push_back(std::move(NewName)); @@ -1225,13 +1223,6 @@ class BinaryFunction { /// Update output values of the function based on the final \p Layout. void updateOutputValues(const MCAsmLayout &Layout); - /// Return mapping of input to output addresses. Most users should call - /// translateInputToOutputAddress() for address translation. - InputOffsetToAddressMapTy &getInputOffsetToAddressMap() { - assert(isEmitted() && "cannot use address mapping before code emission"); - return InputOffsetToAddressMap; - } - /// Register relocation type \p RelType at a given \p Address in the function /// against \p Symbol. /// Assert if the \p Address is not inside this function. @@ -1779,6 +1770,15 @@ class BinaryFunction { return llvm::is_contained(Fragments, &Other); } + /// Return the child fragment form parent function + iterator_range getFragments() const { + return iterator_range(Fragments.begin(), + Fragments.end()); + } + + /// Return the parent function for split function fragments. + FragmentsSetTy *getParentFragments() { return &ParentFragments; } + /// Returns if this function is a parent or child of \p Other function. bool isParentOrChildOf(const BinaryFunction &Other) const { return isChildOf(Other) || isParentOf(Other); @@ -2170,6 +2170,11 @@ class BinaryFunction { /// its code emission. bool requiresAddressTranslation() const; + /// Return true if the linker needs to generate an address map for this + /// function. Used for keeping track of the mapping from input to out + /// addresses of basic blocks. + bool requiresAddressMap() const; + /// Adjust branch instructions to match the CFG. /// /// As it comes to internal branches, the CFG represents "the ultimate source diff --git a/bolt/include/bolt/Core/BinarySection.h b/bolt/include/bolt/Core/BinarySection.h index f1041777926fd..326d088d1f046 100644 --- a/bolt/include/bolt/Core/BinarySection.h +++ b/bolt/include/bolt/Core/BinarySection.h @@ -97,6 +97,8 @@ class BinarySection { mutable bool IsReordered{false}; // Have the contents been reordered? bool IsAnonymous{false}; // True if the name should not be included // in the output file. + bool IsLinkOnly{false}; // True if the section should not be included + // in the output file. uint64_t hash(const BinaryData &BD, std::map &Cache) const; @@ -452,6 +454,8 @@ class BinarySection { void setIndex(uint32_t I) { Index = I; } void setOutputName(const Twine &Name) { OutputName = Name.str(); } void setAnonymous(bool Flag) { IsAnonymous = Flag; } + bool isLinkOnly() const { return IsLinkOnly; } + void setLinkOnly() { IsLinkOnly = true; } /// Emit the section as data, possibly with relocations. /// Use name \p SectionName for the section during the emission. diff --git a/bolt/include/bolt/Core/DIEBuilder.h b/bolt/include/bolt/Core/DIEBuilder.h index 4034cb4ac118a..fb86e59468b83 100644 --- a/bolt/include/bolt/Core/DIEBuilder.h +++ b/bolt/include/bolt/Core/DIEBuilder.h @@ -21,12 +21,12 @@ #include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/ErrorHandling.h" #include #include #include #include +#include #include namespace llvm { @@ -113,6 +113,7 @@ class DIEBuilder { std::vector LocWithReferencesToProcess; BumpPtrAllocator DIEAlloc; ProcessingType Type; + std::unordered_set DWARFDieAddressesParsed; }; std::unique_ptr BuilderState; diff --git a/bolt/include/bolt/Core/DebugData.h b/bolt/include/bolt/Core/DebugData.h index d4611e8f6ca4a..3fdc0534c000a 100644 --- a/bolt/include/bolt/Core/DebugData.h +++ b/bolt/include/bolt/Core/DebugData.h @@ -313,9 +313,6 @@ class DebugAddrWriter { /// Adds Address to map. uint32_t getIndexFromAddress(uint64_t Address, DWARFUnit &CU); - /// Adds {\p Address, \p Index} to \p CU. - void addIndexAddress(uint64_t Address, uint32_t Index, DWARFUnit &CU); - /// Write out entries in to .debug_addr section for CUs. virtual void update(DIEBuilder &DIEBlder, DWARFUnit &CUs); diff --git a/bolt/lib/Core/AddressMap.cpp b/bolt/lib/Core/AddressMap.cpp new file mode 100644 index 0000000000000..76c5378a3eb15 --- /dev/null +++ b/bolt/lib/Core/AddressMap.cpp @@ -0,0 +1,63 @@ +#include "bolt/Core/AddressMap.h" +#include "bolt/Core/BinaryContext.h" +#include "bolt/Core/BinaryFunction.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Support/DataExtractor.h" + +namespace llvm { +namespace bolt { + +const char *const AddressMap::SectionName = ".bolt.address_map"; + +static void emitLabel(MCStreamer &Streamer, uint64_t InputAddress, + const MCSymbol *OutputLabel) { + Streamer.emitIntValue(InputAddress, 8); + Streamer.emitSymbolValue(OutputLabel, 8); +} + +void AddressMap::emit(MCStreamer &Streamer, BinaryContext &BC) { + Streamer.switchSection(BC.getDataSection(SectionName)); + + for (const auto &[BFAddress, BF] : BC.getBinaryFunctions()) { + if (!BF.requiresAddressMap()) + continue; + + for (const auto &BB : BF) { + if (!BB.getLabel()->isDefined()) + continue; + + emitLabel(Streamer, BFAddress + BB.getInputAddressRange().first, + BB.getLabel()); + + if (!BB.hasLocSyms()) + continue; + + for (auto [Offset, Symbol] : BB.getLocSyms()) + emitLabel(Streamer, BFAddress + Offset, Symbol); + } + } +} + +AddressMap AddressMap::parse(StringRef Buffer, const BinaryContext &BC) { + const auto EntrySize = 2 * BC.AsmInfo->getCodePointerSize(); + assert(Buffer.size() % EntrySize == 0 && "Unexpected address map size"); + + DataExtractor DE(Buffer, BC.AsmInfo->isLittleEndian(), + BC.AsmInfo->getCodePointerSize()); + DataExtractor::Cursor Cursor(0); + + AddressMap Parsed; + Parsed.Map.reserve(Buffer.size() / EntrySize); + + while (Cursor && !DE.eof(Cursor)) { + const auto Input = DE.getAddress(Cursor); + const auto Output = DE.getAddress(Cursor); + Parsed.Map.insert({Input, Output}); + } + + assert(Cursor && "Error reading address map section"); + return Parsed; +} + +} // namespace bolt +} // namespace llvm diff --git a/bolt/lib/Core/BinaryBasicBlock.cpp b/bolt/lib/Core/BinaryBasicBlock.cpp index b271b86ec6992..d764a874d08ce 100644 --- a/bolt/lib/Core/BinaryBasicBlock.cpp +++ b/bolt/lib/Core/BinaryBasicBlock.cpp @@ -613,27 +613,5 @@ BinaryBasicBlock *BinaryBasicBlock::splitAt(iterator II) { return NewBlock; } -void BinaryBasicBlock::updateOutputValues(const MCAsmLayout &Layout) { - if (!LocSyms) - return; - - const uint64_t BBAddress = getOutputAddressRange().first; - const uint64_t BBOffset = Layout.getSymbolOffset(*getLabel()); - for (const auto &LocSymKV : *LocSyms) { - const uint32_t InputFunctionOffset = LocSymKV.first; - const uint32_t OutputOffset = static_cast( - Layout.getSymbolOffset(*LocSymKV.second) - BBOffset); - getOffsetTranslationTable().emplace_back( - std::make_pair(OutputOffset, InputFunctionOffset)); - - // Update reverse (relative to BAT) address lookup table for function. - if (getFunction()->requiresAddressTranslation()) { - getFunction()->getInputOffsetToAddressMap().emplace( - std::make_pair(InputFunctionOffset, OutputOffset + BBAddress)); - } - } - LocSyms.reset(nullptr); -} - } // namespace bolt } // namespace llvm diff --git a/bolt/lib/Core/BinaryEmitter.cpp b/bolt/lib/Core/BinaryEmitter.cpp index c4129615ac32d..63446575f4b27 100644 --- a/bolt/lib/Core/BinaryEmitter.cpp +++ b/bolt/lib/Core/BinaryEmitter.cpp @@ -214,6 +214,10 @@ void BinaryEmitter::emitAll(StringRef OrgSecPrefix) { } emitDataSections(OrgSecPrefix); + + // TODO Enable for Mach-O once BinaryContext::getDataSection supports it. + if (BC.isELF()) + AddressMap::emit(Streamer, BC); } void BinaryEmitter::emitFunctions() { diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp index f6146d9749f59..9ae0c63031082 100644 --- a/bolt/lib/Core/BinaryFunction.cpp +++ b/bolt/lib/Core/BinaryFunction.cpp @@ -182,9 +182,9 @@ static SMLoc findDebugLineInformationForInstructionAt( // We use the pointer in SMLoc to store an instance of DebugLineTableRowRef, // which occupies 64 bits. Thus, we can only proceed if the struct fits into // the pointer itself. - assert(sizeof(decltype(SMLoc().getPointer())) >= - sizeof(DebugLineTableRowRef) && - "Cannot fit instruction debug line information into SMLoc's pointer"); + static_assert( + sizeof(decltype(SMLoc().getPointer())) >= sizeof(DebugLineTableRowRef), + "Cannot fit instruction debug line information into SMLoc's pointer"); SMLoc NullResult = DebugLineTableRowRef::NULL_ROW.toSMLoc(); uint32_t RowIndex = LineTable->lookupAddress( @@ -2855,6 +2855,14 @@ bool BinaryFunction::requiresAddressTranslation() const { return opts::EnableBAT || hasSDTMarker() || hasPseudoProbe(); } +bool BinaryFunction::requiresAddressMap() const { + if (isInjected()) + return false; + + return opts::UpdateDebugSections || isMultiEntry() || + requiresAddressTranslation(); +} + uint64_t BinaryFunction::getInstructionCount() const { uint64_t Count = 0; for (const BinaryBasicBlock &BB : blocks()) @@ -4120,15 +4128,13 @@ void BinaryFunction::updateOutputValues(const MCAsmLayout &Layout) { assert(FragmentBaseAddress == getOutputAddress()); } - const uint64_t BBOffset = Layout.getSymbolOffset(*BB->getLabel()); - const uint64_t BBAddress = FragmentBaseAddress + BBOffset; + const uint64_t BBAddress = + *BC.getIOAddressMap().lookup(BB->getInputOffset() + getAddress()); BB->setOutputStartAddress(BBAddress); if (PrevBB) PrevBB->setOutputEndAddress(BBAddress); PrevBB = BB; - - BB->updateOutputValues(Layout); } PrevBB->setOutputEndAddress(PrevBB->isSplit() @@ -4181,9 +4187,8 @@ uint64_t BinaryFunction::translateInputToOutputAddress(uint64_t Address) const { // Check if the address is associated with an instruction that is tracked // by address translation. - auto KV = InputOffsetToAddressMap.find(Address - getAddress()); - if (KV != InputOffsetToAddressMap.end()) - return KV->second; + if (auto OutputAddress = BC.getIOAddressMap().lookup(Address)) + return *OutputAddress; // FIXME: #18950828 - we rely on relative offsets inside basic blocks to stay // intact. Instead we can use pseudo instructions and/or annotations. diff --git a/bolt/lib/Core/CMakeLists.txt b/bolt/lib/Core/CMakeLists.txt index a4612fb93f8c3..c913179ebcc51 100644 --- a/bolt/lib/Core/CMakeLists.txt +++ b/bolt/lib/Core/CMakeLists.txt @@ -11,6 +11,7 @@ set(LLVM_LINK_COMPONENTS ) add_llvm_library(LLVMBOLTCore + AddressMap.cpp BinaryBasicBlock.cpp BinaryContext.cpp BinaryData.cpp diff --git a/bolt/lib/Core/DIEBuilder.cpp b/bolt/lib/Core/DIEBuilder.cpp index 90405680acf73..223ae714440d9 100644 --- a/bolt/lib/Core/DIEBuilder.cpp +++ b/bolt/lib/Core/DIEBuilder.cpp @@ -39,6 +39,9 @@ #undef DEBUG_TYPE #define DEBUG_TYPE "bolt" +namespace opts { +extern cl::opt Verbosity; +} namespace llvm { namespace bolt { @@ -105,6 +108,14 @@ uint32_t DIEBuilder::allocDIE(const DWARFUnit &DU, const DWARFDie &DDie, return DWARFUnitInfo.DIEIDMap[DDieOffset]; DIE *Die = DIE::get(Alloc, dwarf::Tag(DDie.getTag())); + // This handles the case where there is a DIE ref which points to + // invalid DIE. This prevents assert when IR is written out. + // Also it makes debugging easier. + // DIE dump is not very useful. + // It's nice to know original offset from which this DIE was constructed. + Die->setOffset(DDie.getOffset()); + if (opts::Verbosity >= 1) + getState().DWARFDieAddressesParsed.insert(DDie.getOffset()); const uint32_t DId = DWARFUnitInfo.DieInfoVector.size(); DWARFUnitInfo.DIEIDMap[DDieOffset] = DId; DWARFUnitInfo.DieInfoVector.emplace_back( @@ -290,10 +301,6 @@ DIE *DIEBuilder::constructDIEFast(DWARFDie &DDie, DWARFUnit &U, DIEInfo &DieInfo = getDIEInfo(UnitId, *Idx); uint64_t Offset = DDie.getOffset(); - // Just for making debugging easier. - // DIE dump is not very useful. - // It's nice to know original offset from which this DIE was constructed. - DieInfo.Die->setOffset(Offset); uint64_t NextOffset = Offset; DWARFDataExtractor Data = U.getDebugInfoExtractor(); DWARFDebugInfoEntry DDIEntry; @@ -369,6 +376,7 @@ getUnitForOffset(DIEBuilder &Builder, DWARFContext &DWCtx, uint32_t DIEBuilder::computeDIEOffset(const DWARFUnit &CU, DIE &Die, uint32_t &CurOffset) { + getState().DWARFDieAddressesParsed.erase(Die.getOffset()); uint32_t CurSize = 0; Die.setOffset(CurOffset); for (DIEValue &Val : Die.values()) @@ -421,6 +429,13 @@ void DIEBuilder::finish() { continue; computeOffset(*CU, UnitSize); } + if (opts::Verbosity >= 1) { + if (!getState().DWARFDieAddressesParsed.empty()) + dbgs() << "Referenced DIE offsets not in .debug_info\n"; + for (const uint64_t Address : getState().DWARFDieAddressesParsed) { + dbgs() << Twine::utohexstr(Address) << "\n"; + } + } updateReferences(); } @@ -457,11 +472,20 @@ DWARFDie DIEBuilder::resolveDIEReference( allocDIE(*RefCU, RefDie, getState().DIEAlloc, *UnitId); return RefDie; } + errs() << "BOLT-WARNING: [internal-dwarf-error]: invalid referenced DIE " + "at offset: " + << Twine::utohexstr(RefOffset) << ".\n"; + + } else { + errs() << "BOLT-WARNING: [internal-dwarf-error]: could not parse " + "referenced DIE at offset: " + << Twine::utohexstr(RefOffset) << ".\n"; } + } else { + errs() << "BOLT-WARNING: [internal-dwarf-error]: could not find referenced " + "CU. Referenced DIE offset: " + << Twine::utohexstr(RefOffset) << ".\n"; } - - errs() << "BOLT-WARNING: [internal-dwarf-error]: could not find referenced " - "CU.\n"; return DWARFDie(); } diff --git a/bolt/lib/Core/DebugData.cpp b/bolt/lib/Core/DebugData.cpp index 28b3977c6edc5..8d24c9281b8f2 100644 --- a/bolt/lib/Core/DebugData.cpp +++ b/bolt/lib/Core/DebugData.cpp @@ -414,25 +414,6 @@ uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, DWARFUnit &CU) { return Entry->second; } -// Case1) Address is not in map insert in to AddresToIndex and IndexToAddres -// Case2) Address is in the map but Index is higher or equal. Need to update -// IndexToAddrss. Case3) Address is in the map but Index is lower. Need to -// update AddressToIndex and IndexToAddress -void DebugAddrWriter::addIndexAddress(uint64_t Address, uint32_t Index, - DWARFUnit &CU) { - std::lock_guard Lock(WriterMutex); - const uint64_t CUID = getCUID(CU); - AddressForDWOCU &Map = AddressMaps[CUID]; - auto Entry = Map.find(Address); - if (Entry != Map.end()) { - if (Entry->second > Index) - Map.updateAddressToIndex(Address, Index); - Map.updateIndexToAddrss(Address, Index); - } else { - Map.insert(Address, Index); - } -} - static void updateAddressBase(DIEBuilder &DIEBlder, DebugAddrWriter &AddrWriter, DWARFUnit &CU, const uint64_t Offset) { DIE *Die = DIEBlder.getUnitDIEbyUnit(CU); diff --git a/bolt/lib/Passes/RegReAssign.cpp b/bolt/lib/Passes/RegReAssign.cpp index 19e1a84c48d1b..0efd27f0910b4 100644 --- a/bolt/lib/Passes/RegReAssign.cpp +++ b/bolt/lib/Passes/RegReAssign.cpp @@ -140,7 +140,7 @@ void RegReAssign::rankRegisters(BinaryFunction &Function) { std::fill(RegScore.begin(), RegScore.end(), 0); std::fill(RankedRegs.begin(), RankedRegs.end(), 0); - for (BinaryBasicBlock &BB : Function) { + auto countRegScore = [&](BinaryBasicBlock &BB) { for (MCInst &Inst : BB) { const bool CannotUseREX = BC.MIB->cannotUseREX(Inst); const MCInstrDesc &Desc = BC.MII->get(Inst.getOpcode()); @@ -191,7 +191,15 @@ void RegReAssign::rankRegisters(BinaryFunction &Function) { RegScore[RegEC] += BB.getKnownExecutionCount(); } } + }; + for (BinaryBasicBlock &BB : Function) + countRegScore(BB); + + for (BinaryFunction *ChildFrag : Function.getFragments()) { + for (BinaryBasicBlock &BB : *ChildFrag) + countRegScore(BB); } + std::iota(RankedRegs.begin(), RankedRegs.end(), 0); // 0, 1, 2, 3... llvm::sort(RankedRegs, [&](size_t A, size_t B) { return RegScore[A] > RegScore[B]; }); @@ -213,6 +221,17 @@ void RegReAssign::aggressivePassOverFunction(BinaryFunction &Function) { BinaryContext &BC = Function.getBinaryContext(); rankRegisters(Function); + // If there is a situation where function: + // A() -> A.cold() + // A.localalias() -> A.cold() + // simply swapping these two calls can cause issues. + for (BinaryFunction *ChildFrag : Function.getFragments()) { + if (ChildFrag->getParentFragments()->size() > 1) + return; + if (ChildFrag->empty()) + return; + } + // Bail early if our registers are all black listed, before running expensive // analysis passes bool Bail = true; @@ -304,6 +323,10 @@ void RegReAssign::aggressivePassOverFunction(BinaryFunction &Function) { << " with " << BC.MRI->getName(ExtReg) << "\n\n"); swap(Function, ClassicReg, ExtReg); FuncsChanged.insert(&Function); + for (BinaryFunction *ChildFrag : Function.getFragments()) { + swap(*ChildFrag, ClassicReg, ExtReg); + FuncsChanged.insert(ChildFrag); + } ++Begin; if (Begin == End) break; @@ -315,6 +338,13 @@ bool RegReAssign::conservativePassOverFunction(BinaryFunction &Function) { BinaryContext &BC = Function.getBinaryContext(); rankRegisters(Function); + for (BinaryFunction *ChildFrag : Function.getFragments()) { + if (ChildFrag->getParentFragments()->size() > 1) + return false; + if (ChildFrag->empty()) + return false; + } + // Try swapping R12, R13, R14 or R15 with RBX (we work with all callee-saved // regs except RBP) MCPhysReg Candidate = 0; @@ -345,6 +375,10 @@ bool RegReAssign::conservativePassOverFunction(BinaryFunction &Function) { (void)BC; swap(Function, RBX, Candidate); FuncsChanged.insert(&Function); + for (BinaryFunction *ChildFrag : Function.getFragments()) { + swap(*ChildFrag, RBX, Candidate); + FuncsChanged.insert(ChildFrag); + } return true; } @@ -404,7 +438,7 @@ void RegReAssign::runOnFunctions(BinaryContext &BC) { for (auto &I : BC.getBinaryFunctions()) { BinaryFunction &Function = I.second; - if (!Function.isSimple() || Function.isIgnored()) + if (!Function.isSimple() || Function.isIgnored() || Function.isFragment()) continue; LLVM_DEBUG(dbgs() << "====================================\n"); diff --git a/bolt/lib/Passes/ReorderFunctions.cpp b/bolt/lib/Passes/ReorderFunctions.cpp index 678c3d8fe6a90..72d58a4327eb8 100644 --- a/bolt/lib/Passes/ReorderFunctions.cpp +++ b/bolt/lib/Passes/ReorderFunctions.cpp @@ -284,27 +284,37 @@ void ReorderFunctions::runOnFunctions(BinaryContext &BC) { break; case RT_EXEC_COUNT: { std::vector SortedFunctions(BFs.size()); - uint32_t Index = 0; llvm::transform(llvm::make_second_range(BFs), SortedFunctions.begin(), [](BinaryFunction &BF) { return &BF; }); - llvm::stable_sort(SortedFunctions, [&](const BinaryFunction *A, - const BinaryFunction *B) { - if (A->isIgnored()) - return false; - const size_t PadA = opts::padFunction(*A); - const size_t PadB = opts::padFunction(*B); - if (!PadA || !PadB) { - if (PadA) - return true; - if (PadB) - return false; - } - return !A->hasProfile() && (B->hasProfile() || (A->getExecutionCount() > - B->getExecutionCount())); - }); + llvm::stable_sort(SortedFunctions, + [&](const BinaryFunction *A, const BinaryFunction *B) { + if (A->isIgnored()) + return false; + if (B->isIgnored()) + return true; + const size_t PadA = opts::padFunction(*A); + const size_t PadB = opts::padFunction(*B); + if (!PadA || !PadB) { + if (PadA) + return true; + if (PadB) + return false; + } + if (!A->hasProfile()) + return false; + if (!B->hasProfile()) + return true; + return A->getExecutionCount() > B->getExecutionCount(); + }); + uint32_t Index = 0; for (BinaryFunction *BF : SortedFunctions) - if (BF->hasProfile()) + if (BF->hasProfile()) { BF->setIndex(Index++); + LLVM_DEBUG(if (opts::Verbosity > 1) { + dbgs() << "BOLT-INFO: hot func " << BF->getPrintName() << " (" + << BF->getExecutionCount() << ")\n"; + }); + } } break; case RT_HFSORT: Clusters = clusterize(Cg); diff --git a/bolt/lib/Profile/BoltAddressTranslation.cpp b/bolt/lib/Profile/BoltAddressTranslation.cpp index 57a850eb17234..e004309e0e213 100644 --- a/bolt/lib/Profile/BoltAddressTranslation.cpp +++ b/bolt/lib/Profile/BoltAddressTranslation.cpp @@ -46,9 +46,14 @@ void BoltAddressTranslation::writeEntriesForBB(MapTy &Map, // allowing it to overwrite the previously inserted key in the map. Map[BBOutputOffset] = BBInputOffset; - for (const auto &IOPair : BB.getOffsetTranslationTable()) { - const uint64_t OutputOffset = IOPair.first + BBOutputOffset; - const uint32_t InputOffset = IOPair.second; + const auto &IOAddressMap = + BB.getFunction()->getBinaryContext().getIOAddressMap(); + + for (const auto &[InputOffset, Sym] : BB.getLocSyms()) { + const auto InputAddress = BB.getFunction()->getAddress() + InputOffset; + const auto OutputAddress = IOAddressMap.lookup(InputAddress); + assert(OutputAddress && "Unknown instruction address"); + const auto OutputOffset = *OutputAddress - FuncAddress; // Is this the first instruction in the BB? No need to duplicate the entry. if (OutputOffset == BBOutputOffset) diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp index 2262115d97000..a638d97fdb030 100644 --- a/bolt/lib/Rewrite/DWARFRewriter.cpp +++ b/bolt/lib/Rewrite/DWARFRewriter.cpp @@ -57,7 +57,6 @@ #undef DEBUG_TYPE #define DEBUG_TYPE "bolt" -LLVM_ATTRIBUTE_UNUSED static void printDie(const DWARFDie &DIE) { DIDumpOptions DumpOpts; DumpOpts.ShowForm = true; @@ -67,6 +66,28 @@ static void printDie(const DWARFDie &DIE) { DIE.dump(dbgs(), 0, DumpOpts); } +/// Lazily parse DWARF DIE and print it out. +LLVM_ATTRIBUTE_UNUSED +static void printDie(DWARFUnit &DU, uint64_t DIEOffset) { + uint64_t OriginalOffsets = DIEOffset; + uint64_t NextCUOffset = DU.getNextUnitOffset(); + DWARFDataExtractor DebugInfoData = DU.getDebugInfoExtractor(); + DWARFDebugInfoEntry DIEEntry; + if (DIEEntry.extractFast(DU, &DIEOffset, DebugInfoData, NextCUOffset, 0)) { + if (const DWARFAbbreviationDeclaration *AbbrDecl = + DIEEntry.getAbbreviationDeclarationPtr()) { + DWARFDie DDie(&DU, &DIEEntry); + printDie(DDie); + } else { + dbgs() << "Failed to extract abbreviation for" + << Twine::utohexstr(OriginalOffsets) << "\n"; + } + } else { + dbgs() << "Failed to extract DIE for " << Twine::utohexstr(OriginalOffsets) + << " \n"; + } +} + namespace llvm { namespace bolt { /// Emits debug information into .debug_info or .debug_types section. @@ -521,32 +542,34 @@ void DWARFRewriter::updateDebugInfo() { DebugLoclistWriter::setAddressWriter(AddrWriter.get()); - size_t CUIndex = 0; - for (std::unique_ptr &CU : BC.DwCtx->compile_units()) { - const uint16_t DwarfVersion = CU->getVersion(); + uint32_t CUIndex = 0; + std::mutex AccessMutex; + // Needs to be invoked in the same order as CUs are processed. + auto createRangeLocList = [&](DWARFUnit &CU) -> DebugLocWriter * { + std::lock_guard Lock(AccessMutex); + const uint16_t DwarfVersion = CU.getVersion(); if (DwarfVersion >= 5) { LocListWritersByCU[CUIndex] = - std::make_unique(*CU.get(), DwarfVersion, false); + std::make_unique(CU, DwarfVersion, false); - if (std::optional DWOId = CU->getDWOId()) { + if (std::optional DWOId = CU.getDWOId()) { assert(RangeListsWritersByCU.count(*DWOId) == 0 && "RangeLists writer for DWO unit already exists."); auto RangeListsSectionWriter = std::make_unique(); - RangeListsSectionWriter->initSection(*CU.get()); + RangeListsSectionWriter->initSection(CU); RangeListsWritersByCU[*DWOId] = std::move(RangeListsSectionWriter); } } else { LocListWritersByCU[CUIndex] = std::make_unique(); } - ++CUIndex; - } + return LocListWritersByCU[CUIndex++].get(); + }; // Unordered maps to handle name collision if output DWO directory is // specified. std::unordered_map NameToIndexMap; - std::mutex AccessMutex; auto updateDWONameCompDir = [&](DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &UnitDIE) -> std::string { @@ -576,8 +599,7 @@ void DWARFRewriter::updateDebugInfo() { DWPState State; if (opts::WriteDWP) initDWPState(State); - auto processUnitDIE = [&](size_t CUIndex, DWARFUnit *Unit, - DIEBuilder *DIEBlder) { + auto processUnitDIE = [&](DWARFUnit *Unit, DIEBuilder *DIEBlder) { // Check if the unit is a skeleton and we need special updates for it and // its matching split/DWO CU. std::optional SplitCU; @@ -587,8 +609,7 @@ void DWARFRewriter::updateDebugInfo() { Unit->getStringOffsetsTableContribution()); if (DWOId) SplitCU = BC.getDWOCU(*DWOId); - - DebugLocWriter *DebugLocWriter = nullptr; + DebugLocWriter *DebugLocWriter = createRangeLocList(*Unit); DebugRangesSectionWriter *RangesSectionWriter = Unit->getVersion() >= 5 ? RangeListsSectionWriter.get() : LegacyRangesSectionWriter.get(); @@ -624,12 +645,6 @@ void DWARFRewriter::updateDebugInfo() { DebugLocDWoWriter); } - { - std::lock_guard Lock(AccessMutex); - auto LocListWriterIter = LocListWritersByCU.find(CUIndex); - if (LocListWriterIter != LocListWritersByCU.end()) - DebugLocWriter = LocListWriterIter->second.get(); - } if (Unit->getVersion() >= 5) { RangesBase = RangesSectionWriter->getSectionOffset() + getDWARF5RngListLocListHeaderSize(); @@ -645,7 +660,6 @@ void DWARFRewriter::updateDebugInfo() { AddrWriter->update(*DIEBlder, *Unit); }; - CUIndex = 0; DIEBuilder DIEBlder(BC.DwCtx.get()); DIEBlder.buildTypeUnits(); SmallVector OutBuffer; @@ -666,17 +680,15 @@ void DWARFRewriter::updateDebugInfo() { for (std::vector &Vec : PartVec) { DIEBlder.buildCompileUnits(Vec); for (DWARFUnit *CU : DIEBlder.getProcessedCUs()) - processUnitDIE(CUIndex++, CU, &DIEBlder); + processUnitDIE(CU, &DIEBlder); finalizeCompileUnits(DIEBlder, *Streamer, OffsetMap, DIEBlder.getProcessedCUs()); } } else { // Update unit debug info in parallel ThreadPool &ThreadPool = ParallelUtilities::getThreadPool(); - for (std::unique_ptr &CU : BC.DwCtx->compile_units()) { - ThreadPool.async(processUnitDIE, CUIndex, CU.get(), &DIEBlder); - CUIndex++; - } + for (std::unique_ptr &CU : BC.DwCtx->compile_units()) + ThreadPool.async(processUnitDIE, CU.get(), &DIEBlder); ThreadPool.wait(); } @@ -1102,46 +1114,31 @@ void DWARFRewriter::updateUnitDebugInfo( DIEBldr.addValue(NewAttr, *Itr); std::advance(Itr, 1); } - PrevOffset = CurEndOffset; - continue; - } - - const uint64_t Index = Expr.getRawOperand(0); - std::optional EntryAddress = - Unit.getAddrOffsetSectionItem(Index); - assert(EntryAddress && "Address is not found."); - assert(Index <= std::numeric_limits::max() && - "Invalid Operand Index."); - if (Expr.getCode() == dwarf::DW_OP_addrx) { - const uint32_t Index = AddrWriter->getIndexFromAddress( + } else { + const uint64_t Index = Expr.getRawOperand(0); + std::optional EntryAddress = + Unit.getAddrOffsetSectionItem(Index); + assert(EntryAddress && "Address is not found."); + assert(Index <= std::numeric_limits::max() && + "Invalid Operand Index."); + const uint32_t AddrIndex = AddrWriter->getIndexFromAddress( EntryAddress->Address, Unit); - // update Index for DW_AT_location. The Size field is not stored - // in IR, we need to minus 1 in offset for each expr. + // update Index into .debug_address section for DW_AT_location. + // The Size field is not stored in IR, we need to minus 1 in + // offset for each expr. SmallString<8> Tmp; raw_svector_ostream OSE(Tmp); - encodeULEB128(Index, OSE); + encodeULEB128(AddrIndex, OSE); DIEBldr.addValue(NewAttr, static_cast(0), dwarf::DW_FORM_data1, - DIEInteger(dwarf::DW_OP_addrx)); + DIEInteger(Expr.getCode())); NewExprSize += 1; for (uint8_t Byte : Tmp) { DIEBldr.addValue(NewAttr, static_cast(0), dwarf::DW_FORM_data1, DIEInteger(Byte)); NewExprSize += 1; } - } else { - // TODO: Re-do this as DWARF5. - auto Itr = AttrLocValList->values().begin(); - std::advance(Itr, PrevOffset); - uint32_t CopyNum = CurEndOffset - PrevOffset; - NewExprSize += CopyNum; - while (CopyNum--) { - DIEBldr.addValue(NewAttr, *Itr); - std::advance(Itr, 1); - } - AddrWriter->addIndexAddress(EntryAddress->Address, - static_cast(Index), Unit); } PrevOffset = CurEndOffset; } @@ -1175,18 +1172,8 @@ void DWARFRewriter::updateUnitDebugInfo( assert(Form != dwarf::DW_FORM_LLVM_addrx_offset && "DW_FORM_LLVM_addrx_offset is not supported"); std::lock_guard Lock(DWARFRewriterMutex); - if (Form == dwarf::DW_FORM_GNU_addr_index) { - // If there is no new address, storing old address. - // Re-using Index to make implementation easier. - // DW_FORM_GNU_addr_index is variable lenght encoding - // so we either have to create indices of same sizes, or use same - // index. - // TODO: We can now re-write .debug_info. This can be simplified to - // just getting a new index and creating a patch. - const uint64_t Index = *Result; - AddrWriter->addIndexAddress(NewAddress ? NewAddress : Address, - Index, Unit); - } else if (Form == dwarf::DW_FORM_addrx) { + if (Form == dwarf::DW_FORM_addrx || + Form == dwarf::DW_FORM_GNU_addr_index) { const uint32_t Index = AddrWriter->getIndexFromAddress( NewAddress ? NewAddress : Address, Unit); DIEBldr.replaceValue(Die, LowPCAttrInfo.getAttribute(), diff --git a/bolt/lib/Rewrite/PseudoProbeRewriter.cpp b/bolt/lib/Rewrite/PseudoProbeRewriter.cpp index 64b8a8b6d400f..316b83cfbd38a 100644 --- a/bolt/lib/Rewrite/PseudoProbeRewriter.cpp +++ b/bolt/lib/Rewrite/PseudoProbeRewriter.cpp @@ -183,9 +183,7 @@ void PseudoProbeRewriter::updatePseudoProbes() { // A call probe may be duplicated due to ICP // Go through output of InputOffsetToAddressMap to collect all related // probes - const InputOffsetToAddressMapTy &Offset2Addr = - F->getInputOffsetToAddressMap(); - auto CallOutputAddresses = Offset2Addr.equal_range(Offset); + auto CallOutputAddresses = BC.getIOAddressMap().lookupAll(AP.first); auto CallOutputAddress = CallOutputAddresses.first; if (CallOutputAddress == CallOutputAddresses.second) { Probe->setAddress(INT64_MAX); diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index 551527f4c678f..31babd2de802c 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "bolt/Rewrite/RewriteInstance.h" +#include "bolt/Core/AddressMap.h" #include "bolt/Core/BinaryContext.h" #include "bolt/Core/BinaryEmitter.h" #include "bolt/Core/BinaryFunction.h" @@ -3170,6 +3171,9 @@ void RewriteInstance::preregisterSections() { ROFlags); BC->registerOrUpdateSection(getNewSecPrefix() + ".rodata.cold", ELF::SHT_PROGBITS, ROFlags); + BC->registerOrUpdateSection(AddressMap::SectionName, ELF::SHT_PROGBITS, + ROFlags) + .setLinkOnly(); } void RewriteInstance::emitAndLink() { @@ -3575,6 +3579,9 @@ void RewriteInstance::mapAllocatableSections( } for (BinarySection &Section : BC->allocatableSections()) { + if (Section.isLinkOnly()) + continue; + if (!Section.hasValidSectionID()) continue; @@ -3637,6 +3644,12 @@ void RewriteInstance::mapAllocatableSections( } void RewriteInstance::updateOutputValues(const MCAsmLayout &Layout) { + if (auto MapSection = BC->getUniqueSectionByName(AddressMap::SectionName)) { + auto Map = AddressMap::parse(MapSection->getOutputContents(), *BC); + BC->setIOAddressMap(std::move(Map)); + BC->deregisterSection(*MapSection); + } + for (BinaryFunction *Function : BC->getAllBinaryFunctions()) Function->updateOutputValues(Layout); } @@ -5282,6 +5295,8 @@ void RewriteInstance::rewriteFile() { for (BinarySection &Section : BC->allocatableSections()) { if (!Section.isFinalized() || !Section.getOutputData()) continue; + if (Section.isLinkOnly()) + continue; if (opts::Verbosity >= 1) outs() << "BOLT: writing new section " << Section.getName() diff --git a/bolt/test/X86/Inputs/dwarf4-cross-cu-with-loclist.s b/bolt/test/X86/Inputs/dwarf4-cross-cu-with-loclist.s new file mode 100644 index 0000000000000..3d3b43103bded --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf4-cross-cu-with-loclist.s @@ -0,0 +1,550 @@ +# clang++ main.cpp -O1 -g2 -gdwarf-4 -emit-llvm -c -o mainLL.o +# clang++ helper1.cpp -O1 -g2 -gdwarf-4 -emit-llvm -c -o helper1LL.o +# llvm-link mainLL.o helper1LL.o -S -o linked.ll +# clang++ -O1 linked.ll -g2 -gdwarf-4 -S -o combinedTest.s + +# main.cpp +# struct Foo { +# int x; +# int y; +# }; +# inline __attribute__((always_inline)) +# static int helper(Foo &f) { +# return f.x + 3; +# } +# int main(int argc, char *argv[]) { +# Foo foo; +# foo.x = argc; +# foo.y = 3; +# return helper(foo) + foo.x + foo.y; +# } +# helper1.cpp +# struct Foo2 { +# int x; +# int y; +# }; +# inline __attribute__((always_inline)) +# static int helper(Foo2 &f) { +# return f.x + 3; +# } +# int foo2(int i) { +# Foo2 foo; +# foo.x = i; +# foo.y = 3; +# return helper(foo); +# } + + .text + .file "llvm-link" + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin0: + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: main:argc <- $edi + #DEBUG_VALUE: main:argv <- $rsi + #DEBUG_VALUE: main:foo <- [DW_OP_LLVM_fragment 0 32] $edi + # kill: def $edi killed $edi def $rdi + #DEBUG_VALUE: main:foo <- [DW_OP_LLVM_fragment 32 32] 3 + .file 1 "/dwarf4CrossCULocList" "main.cpp" + .loc 1 13 30 prologue_end # main.cpp:13:30 + leal 6(,%rdi,2), %eax + .loc 1 13 3 is_stmt 0 # main.cpp:13:3 + retq +.Ltmp0: +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + # -- End function + .globl _Z4foo2i # -- Begin function _Z4foo2i + .p2align 4, 0x90 + .type _Z4foo2i,@function +_Z4foo2i: # @_Z4foo2i +.Lfunc_begin1: + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: foo2:i <- $edi + #DEBUG_VALUE: foo2:foo <- [DW_OP_LLVM_fragment 0 32] $edi + # kill: def $edi killed $edi def $rdi + #DEBUG_VALUE: foo2:foo <- [DW_OP_LLVM_fragment 32 32] 3 + .file 2 "/dwarf4CrossCULocList" "helper1.cpp" + .loc 2 7 14 prologue_end is_stmt 1 # helper1.cpp:7:14 + leal 3(%rdi), %eax +.Ltmp1: + .loc 2 13 3 # helper1.cpp:13:3 + retq +.Ltmp2: +.Lfunc_end1: + .size _Z4foo2i, .Lfunc_end1-_Z4foo2i + .cfi_endproc + # -- End function + .section .debug_loc,"",@progbits +.Ldebug_loc0: + .quad .Lfunc_begin0-.Lfunc_begin0 + .quad .Lfunc_end0-.Lfunc_begin0 + .short 7 # Loc expr size + .byte 85 # super-register DW_OP_reg5 + .byte 147 # DW_OP_piece + .byte 4 # 4 + .byte 51 # DW_OP_lit3 + .byte 159 # DW_OP_stack_value + .byte 147 # DW_OP_piece + .byte 4 # 4 + .quad 0 + .quad 0 +.Ldebug_loc1: + .quad .Lfunc_begin1-.Lfunc_begin1 + .quad .Lfunc_end1-.Lfunc_begin1 + .short 7 # Loc expr size + .byte 85 # super-register DW_OP_reg5 + .byte 147 # DW_OP_piece + .byte 4 # 4 + .byte 51 # DW_OP_lit3 + .byte 159 # DW_OP_stack_value + .byte 147 # DW_OP_piece + .byte 4 # 4 + .quad 0 + .quad 0 + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 14 # DW_FORM_strp + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .ascii "\227B" # DW_AT_GNU_all_call_sites + .byte 25 # DW_FORM_flag_present + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 16 # DW_FORM_ref_addr + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 16 # DW_FORM_ref_addr + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 23 # DW_FORM_sec_offset + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 73 # DW_AT_type + .byte 16 # DW_FORM_ref_addr + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 10 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 110 # DW_AT_linkage_name + .byte 14 # DW_FORM_strp + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 32 # DW_AT_inline + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 11 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 12 # Abbreviation Code + .byte 16 # DW_TAG_reference_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 13 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 14 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .ascii "\227B" # DW_AT_GNU_all_call_sites + .byte 25 # DW_FORM_flag_present + .byte 110 # DW_AT_linkage_name + .byte 14 # DW_FORM_strp + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 15 # Abbreviation Code + .byte 29 # DW_TAG_inlined_subroutine + .byte 0 # DW_CHILDREN_no + .byte 49 # DW_AT_abstract_origin + .byte 19 # DW_FORM_ref4 + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 88 # DW_AT_call_file + .byte 11 # DW_FORM_data1 + .byte 89 # DW_AT_call_line + .byte 11 # DW_FORM_data1 + .byte 87 # DW_AT_call_column + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x96 DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 33 # DW_AT_language + .long .Linfo_string1 # DW_AT_name + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Linfo_string2 # DW_AT_comp_dir + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 2 # Abbrev [2] 0x2a:0x43 DW_TAG_subprogram + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_GNU_all_call_sites + .long .Linfo_string11 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .long .debug_info+231 # DW_AT_type + # DW_AT_external + .byte 3 # Abbrev [3] 0x43:0xd DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 85 + .long .Linfo_string14 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .long .debug_info+231 # DW_AT_type + .byte 4 # Abbrev [4] 0x50:0xd DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 84 + .long .Linfo_string15 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .long 109 # DW_AT_type + .byte 5 # Abbrev [5] 0x5d:0xf DW_TAG_variable + .long .Ldebug_loc0 # DW_AT_location + .long .Linfo_string17 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 10 # DW_AT_decl_line + .long 126 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 6 # Abbrev [6] 0x6d:0x5 DW_TAG_pointer_type + .long 114 # DW_AT_type + .byte 6 # Abbrev [6] 0x72:0x5 DW_TAG_pointer_type + .long 119 # DW_AT_type + .byte 7 # Abbrev [7] 0x77:0x7 DW_TAG_base_type + .long .Linfo_string16 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 8 # Abbrev [8] 0x7e:0x22 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .long .Linfo_string18 # DW_AT_name + .byte 8 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 9 # Abbrev [9] 0x87:0xc DW_TAG_member + .long .Linfo_string8 # DW_AT_name + .long .debug_info+231 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 9 # Abbrev [9] 0x93:0xc DW_TAG_member + .long .Linfo_string9 # DW_AT_name + .long .debug_info+231 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .byte 4 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark +.Ldebug_info_end0: +.Lcu_begin1: + .long .Ldebug_info_end1-.Ldebug_info_start1 # Length of Unit +.Ldebug_info_start1: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0xb8 DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 33 # DW_AT_language + .long .Linfo_string3 # DW_AT_name + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Linfo_string2 # DW_AT_comp_dir + .quad .Lfunc_begin1 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .byte 10 # Abbrev [10] 0x2a:0x1c DW_TAG_subprogram + .long .Linfo_string4 # DW_AT_linkage_name + .long .Linfo_string5 # DW_AT_name + .byte 2 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 70 # DW_AT_type + .byte 1 # DW_AT_inline + .byte 11 # Abbrev [11] 0x3a:0xb DW_TAG_formal_parameter + .long .Linfo_string7 # DW_AT_name + .byte 2 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 77 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 7 # Abbrev [7] 0x46:0x7 DW_TAG_base_type + .long .Linfo_string6 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 12 # Abbrev [12] 0x4d:0x5 DW_TAG_reference_type + .long 82 # DW_AT_type + .byte 8 # Abbrev [8] 0x52:0x22 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .long .Linfo_string10 # DW_AT_name + .byte 8 # DW_AT_byte_size + .byte 2 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 13 # Abbrev [13] 0x5b:0xc DW_TAG_member + .long .Linfo_string8 # DW_AT_name + .long 70 # DW_AT_type + .byte 2 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 13 # Abbrev [13] 0x67:0xc DW_TAG_member + .long .Linfo_string9 # DW_AT_name + .long 70 # DW_AT_type + .byte 2 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .byte 4 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 14 # Abbrev [14] 0x74:0x4e DW_TAG_subprogram + .quad .Lfunc_begin1 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_GNU_all_call_sites + .long .Linfo_string12 # DW_AT_linkage_name + .long .Linfo_string13 # DW_AT_name + .byte 2 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .long 70 # DW_AT_type + # DW_AT_external + .byte 4 # Abbrev [4] 0x91:0xd DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 85 + .long .Linfo_string19 # DW_AT_name + .byte 2 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .long 70 # DW_AT_type + .byte 5 # Abbrev [5] 0x9e:0xf DW_TAG_variable + .long .Ldebug_loc1 # DW_AT_location + .long .Linfo_string17 # DW_AT_name + .byte 2 # DW_AT_decl_file + .byte 10 # DW_AT_decl_line + .long 82 # DW_AT_type + .byte 15 # Abbrev [15] 0xad:0x14 DW_TAG_inlined_subroutine + .long 42 # DW_AT_abstract_origin + .quad .Lfunc_begin1 # DW_AT_low_pc + .long .Ltmp1-.Lfunc_begin1 # DW_AT_high_pc + .byte 2 # DW_AT_call_file + .byte 13 # DW_AT_call_line + .byte 10 # DW_AT_call_column + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark +.Ldebug_info_end1: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 37d6c1cc7d4dd3a8a47ba62254bc88521bd50d66)" # string offset=0 +.Linfo_string1: + .asciz "main.cpp" # string offset=101 +.Linfo_string2: + .asciz "/dwarf4CrossCULocList" # string offset=110 +.Linfo_string3: + .asciz "helper1.cpp" # string offset=169 +.Linfo_string4: + .asciz "_ZL6helperR4Foo2" # string offset=181 +.Linfo_string5: + .asciz "helper" # string offset=198 +.Linfo_string6: + .asciz "int" # string offset=205 +.Linfo_string7: + .asciz "f" # string offset=209 +.Linfo_string8: + .asciz "x" # string offset=211 +.Linfo_string9: + .asciz "y" # string offset=213 +.Linfo_string10: + .asciz "Foo2" # string offset=215 +.Linfo_string11: + .asciz "main" # string offset=220 +.Linfo_string12: + .asciz "_Z4foo2i" # string offset=225 +.Linfo_string13: + .asciz "foo2" # string offset=234 +.Linfo_string14: + .asciz "argc" # string offset=239 +.Linfo_string15: + .asciz "argv" # string offset=244 +.Linfo_string16: + .asciz "char" # string offset=249 +.Linfo_string17: + .asciz "foo" # string offset=254 +.Linfo_string18: + .asciz "Foo" # string offset=258 +.Linfo_string19: + .asciz "i" # string offset=262 + .ident "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 37d6c1cc7d4dd3a8a47ba62254bc88521bd50d66)" + .ident "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 37d6c1cc7d4dd3a8a47ba62254bc88521bd50d66)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/Inputs/dwarf4-df-call-site-change-low-pc-helper.s b/bolt/test/X86/Inputs/dwarf4-df-call-site-change-low-pc-helper.s new file mode 100644 index 0000000000000..75ffbf00d6fca --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf4-df-call-site-change-low-pc-helper.s @@ -0,0 +1,352 @@ +# clang++ -O2 -g -gdwarf-4 -gsplit-dwarf +# int z = 0; +# int d = 0; +# int helper(int z_, int d_) { +# z += z_; +# d += d_; +# return z * d; +# } + + .text + .file "helper.cpp" + .file 1 "." "helper.cpp" + .globl _Z6helperii # -- Begin function _Z6helperii + .p2align 4, 0x90 + .type _Z6helperii,@function +_Z6helperii: # @_Z6helperii +.Lfunc_begin0: + .loc 1 3 0 # helper.cpp:3:0 + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: helper:z_ <- $edi + #DEBUG_VALUE: helper:d_ <- $esi + movl %esi, %eax +.Ltmp0: + .loc 1 4 4 prologue_end # helper.cpp:4:4 + addl z(%rip), %edi +.Ltmp1: + #DEBUG_VALUE: helper:z_ <- [DW_OP_LLVM_entry_value 1] $edi + .loc 1 5 4 # helper.cpp:5:4 + addl d(%rip), %eax + .loc 1 4 4 # helper.cpp:4:4 + movl %edi, z(%rip) + .loc 1 5 4 # helper.cpp:5:4 + movl %eax, d(%rip) + .loc 1 6 11 # helper.cpp:6:11 + imull %edi, %eax + .loc 1 6 2 is_stmt 0 # helper.cpp:6:2 + retq +.Ltmp2: +.Lfunc_end0: + .size _Z6helperii, .Lfunc_end0-_Z6helperii + .cfi_endproc + # -- End function + .type z,@object # @z + .bss + .globl z + .p2align 2, 0x0 +z: + .long 0 # 0x0 + .size z, 4 + + .type d,@object # @d + .globl d + .p2align 2, 0x0 +d: + .long 0 # 0x0 + .size d, 4 + + .section .debug_loc.dwo,"e",@progbits +.Ldebug_loc0: + .byte 3 + .byte 2 + .long .Ltmp1-.Lfunc_begin0 + .short 1 # Loc expr size + .byte 85 # super-register DW_OP_reg5 + .byte 3 + .byte 3 + .long .Lfunc_end0-.Ltmp1 + .short 4 # Loc expr size + .byte 243 # DW_OP_GNU_entry_value + .byte 1 # 1 + .byte 85 # super-register DW_OP_reg5 + .byte 159 # DW_OP_stack_value + .byte 0 + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 0 # DW_CHILDREN_no + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .ascii "\264B" # DW_AT_GNU_pubnames + .byte 25 # DW_FORM_flag_present + .ascii "\260B" # DW_AT_GNU_dwo_name + .byte 14 # DW_FORM_strp + .ascii "\261B" # DW_AT_GNU_dwo_id + .byte 7 # DW_FORM_data8 + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .ascii "\263B" # DW_AT_GNU_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x25 DW_TAG_compile_unit + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lskel_string0 # DW_AT_comp_dir + # DW_AT_GNU_pubnames + .long .Lskel_string1 # DW_AT_GNU_dwo_name + .quad -7229095317601456558 # DW_AT_GNU_dwo_id + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_GNU_addr_base +.Ldebug_info_end0: + .section .debug_str,"MS",@progbits,1 +.Lskel_string0: + .asciz "." # string offset=0 +.Lskel_string1: + .asciz "helper.dwo" # string offset=47 + .section .debug_str.dwo,"eMS",@progbits,1 +.Linfo_string0: + .asciz "z" # string offset=0 +.Linfo_string1: + .asciz "int" # string offset=2 +.Linfo_string2: + .asciz "d" # string offset=6 +.Linfo_string3: + .asciz "_Z6helperii" # string offset=8 +.Linfo_string4: + .asciz "helper" # string offset=20 +.Linfo_string5: + .asciz "z_" # string offset=27 +.Linfo_string6: + .asciz "d_" # string offset=30 +.Linfo_string7: + .asciz "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 3a8db0f4bfb57348f49d9603119fa157114bbf8e)" # string offset=33 +.Linfo_string8: + .asciz "helper.cpp" # string offset=134 +.Linfo_string9: + .asciz "helper.dwo" # string offset=145 + .section .debug_str_offsets.dwo,"e",@progbits + .long 0 + .long 2 + .long 6 + .long 8 + .long 20 + .long 27 + .long 30 + .long 33 + .long 134 + .long 145 + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit +.Ldebug_info_dwo_start0: + .short 4 # DWARF version number + .long 0 # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x50 DW_TAG_compile_unit + .byte 7 # DW_AT_producer + .short 33 # DW_AT_language + .byte 8 # DW_AT_name + .byte 9 # DW_AT_GNU_dwo_name + .quad -7229095317601456558 # DW_AT_GNU_dwo_id + .byte 2 # Abbrev [2] 0x19:0xb DW_TAG_variable + .byte 0 # DW_AT_name + .long 36 # DW_AT_type + # DW_AT_external + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 251 + .byte 0 + .byte 3 # Abbrev [3] 0x24:0x4 DW_TAG_base_type + .byte 1 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 2 # Abbrev [2] 0x28:0xb DW_TAG_variable + .byte 2 # DW_AT_name + .long 36 # DW_AT_type + # DW_AT_external + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 251 + .byte 1 + .byte 4 # Abbrev [4] 0x33:0x27 DW_TAG_subprogram + .byte 2 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_GNU_all_call_sites + .byte 3 # DW_AT_linkage_name + .byte 4 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .long 36 # DW_AT_type + # DW_AT_external + .byte 5 # Abbrev [5] 0x43:0xc DW_TAG_formal_parameter + .long .Ldebug_loc0-.debug_loc.dwo # DW_AT_location + .byte 5 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .long 36 # DW_AT_type + .byte 6 # Abbrev [6] 0x4f:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 84 + .byte 6 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .long 36 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end0: + .section .debug_abbrev.dwo,"e",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .ascii "\260B" # DW_AT_GNU_dwo_name + .ascii "\202>" # DW_FORM_GNU_str_index + .ascii "\261B" # DW_AT_GNU_dwo_id + .byte 7 # DW_FORM_data8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .ascii "\201>" # DW_FORM_GNU_addr_index + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .ascii "\227B" # DW_AT_GNU_all_call_sites + .byte 25 # DW_FORM_flag_present + .byte 110 # DW_AT_linkage_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 23 # DW_FORM_sec_offset + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_addr,"",@progbits +.Laddr_table_base0: + .quad z + .quad d + .quad .Lfunc_begin0 + .quad .Ltmp1 + .section .debug_gnu_pubnames,"",@progbits + .long .LpubNames_end0-.LpubNames_start0 # Length of Public Names Info +.LpubNames_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 48 # Compilation Unit Length + .long 25 # DIE offset + .byte 32 # Attributes: VARIABLE, EXTERNAL + .asciz "z" # External Name + .long 40 # DIE offset + .byte 32 # Attributes: VARIABLE, EXTERNAL + .asciz "d" # External Name + .long 51 # DIE offset + .byte 48 # Attributes: FUNCTION, EXTERNAL + .asciz "helper" # External Name + .long 0 # End Mark +.LpubNames_end0: + .section .debug_gnu_pubtypes,"",@progbits + .long .LpubTypes_end0-.LpubTypes_start0 # Length of Public Types Info +.LpubTypes_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 48 # Compilation Unit Length + .long 36 # DIE offset + .byte 144 # Attributes: TYPE, STATIC + .asciz "int" # External Name + .long 0 # End Mark +.LpubTypes_end0: + .ident "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 3a8db0f4bfb57348f49d9603119fa157114bbf8e)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/Inputs/dwarf4-df-call-site-change-low-pc-main.s b/bolt/test/X86/Inputs/dwarf4-df-call-site-change-low-pc-main.s new file mode 100644 index 0000000000000..36cb91b4d276a --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf4-df-call-site-change-low-pc-main.s @@ -0,0 +1,513 @@ +# clang++ -O2 -g -gdwarf-4 -gsplit-dwarf +# void use(int * x, int * y) { +# *x += 4; +# *y -= 2; +# } +# +# int helper(int z_, int d_); +# int x = 0; +# int y = 1; +# int main(int argc, char *argv[]) { +# x = argc; +# y = argc + 3; +# //use(&x, &y); +# return helper(x, y); +# } + + .text + .file "main.cpp" + .file 1 "." "main.cpp" + .globl _Z3usePiS_ # -- Begin function _Z3usePiS_ + .p2align 4, 0x90 + .type _Z3usePiS_,@function +_Z3usePiS_: # @_Z3usePiS_ +.Lfunc_begin0: + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: use:x <- $rdi + #DEBUG_VALUE: use:y <- $rsi + .loc 1 2 5 prologue_end # main.cpp:2:5 + addl $4, (%rdi) + .loc 1 3 5 # main.cpp:3:5 + addl $-2, (%rsi) + .loc 1 4 1 # main.cpp:4:1 + retq +.Ltmp0: +.Lfunc_end0: + .size _Z3usePiS_, .Lfunc_end0-_Z3usePiS_ + .cfi_endproc + # -- End function + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin1: + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: main:argc <- $edi + #DEBUG_VALUE: main:argv <- $rsi + # kill: def $edi killed $edi def $rdi + .loc 1 10 6 prologue_end # main.cpp:10:6 + movl %edi, x(%rip) + .loc 1 11 13 # main.cpp:11:13 + leal 3(%rdi), %esi +.Ltmp1: + #DEBUG_VALUE: main:argv <- [DW_OP_LLVM_entry_value 1] $rsi + .loc 1 11 6 is_stmt 0 # main.cpp:11:6 + movl %esi, y(%rip) + # kill: def $edi killed $edi killed $rdi +.Ltmp2: + .loc 1 13 11 is_stmt 1 # main.cpp:13:11 + jmp _Z6helperii@PLT # TAILCALL +.Ltmp3: +.Lfunc_end1: + .size main, .Lfunc_end1-main + .cfi_endproc + # -- End function + .type x,@object # @x + .bss + .globl x + .p2align 2, 0x0 +x: + .long 0 # 0x0 + .size x, 4 + + .type y,@object # @y + .data + .globl y + .p2align 2, 0x0 +y: + .long 1 # 0x1 + .size y, 4 + + .section .debug_loc.dwo,"e",@progbits +.Ldebug_loc0: + .byte 3 + .byte 3 + .long .Ltmp1-.Lfunc_begin1 + .short 1 # Loc expr size + .byte 84 # DW_OP_reg4 + .byte 3 + .byte 5 + .long .Lfunc_end1-.Ltmp1 + .short 4 # Loc expr size + .byte 243 # DW_OP_GNU_entry_value + .byte 1 # 1 + .byte 84 # DW_OP_reg4 + .byte 159 # DW_OP_stack_value + .byte 0 + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 0 # DW_CHILDREN_no + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .ascii "\264B" # DW_AT_GNU_pubnames + .byte 25 # DW_FORM_flag_present + .ascii "\260B" # DW_AT_GNU_dwo_name + .byte 14 # DW_FORM_strp + .ascii "\261B" # DW_AT_GNU_dwo_id + .byte 7 # DW_FORM_data8 + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .ascii "\263B" # DW_AT_GNU_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x25 DW_TAG_compile_unit + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lskel_string0 # DW_AT_comp_dir + # DW_AT_GNU_pubnames + .long .Lskel_string1 # DW_AT_GNU_dwo_name + .quad -3308548803209949056 # DW_AT_GNU_dwo_id + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_GNU_addr_base +.Ldebug_info_end0: + .section .debug_str,"MS",@progbits,1 +.Lskel_string0: + .asciz "." # string offset=0 +.Lskel_string1: + .asciz "main.dwo" # string offset=47 + .section .debug_str.dwo,"eMS",@progbits,1 +.Linfo_string0: + .asciz "x" # string offset=0 +.Linfo_string1: + .asciz "int" # string offset=2 +.Linfo_string2: + .asciz "y" # string offset=6 +.Linfo_string3: + .asciz "_Z6helperii" # string offset=8 +.Linfo_string4: + .asciz "helper" # string offset=20 +.Linfo_string5: + .asciz "_Z3usePiS_" # string offset=27 +.Linfo_string6: + .asciz "use" # string offset=38 +.Linfo_string7: + .asciz "main" # string offset=42 +.Linfo_string8: + .asciz "argc" # string offset=47 +.Linfo_string9: + .asciz "argv" # string offset=52 +.Linfo_string10: + .asciz "char" # string offset=57 +.Linfo_string11: + .asciz "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 3a8db0f4bfb57348f49d9603119fa157114bbf8e)" # string offset=62 +.Linfo_string12: + .asciz "main.cpp" # string offset=163 +.Linfo_string13: + .asciz "main.dwo" # string offset=172 + .section .debug_str_offsets.dwo,"e",@progbits + .long 0 + .long 2 + .long 6 + .long 8 + .long 20 + .long 27 + .long 38 + .long 42 + .long 47 + .long 52 + .long 57 + .long 62 + .long 163 + .long 172 + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit +.Ldebug_info_dwo_start0: + .short 4 # DWARF version number + .long 0 # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x9d DW_TAG_compile_unit + .byte 11 # DW_AT_producer + .short 33 # DW_AT_language + .byte 12 # DW_AT_name + .byte 13 # DW_AT_GNU_dwo_name + .quad -3308548803209949056 # DW_AT_GNU_dwo_id + .byte 2 # Abbrev [2] 0x19:0xb DW_TAG_variable + .byte 0 # DW_AT_name + .long 36 # DW_AT_type + # DW_AT_external + .byte 1 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 251 + .byte 0 + .byte 3 # Abbrev [3] 0x24:0x4 DW_TAG_base_type + .byte 1 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 2 # Abbrev [2] 0x28:0xb DW_TAG_variable + .byte 2 # DW_AT_name + .long 36 # DW_AT_type + # DW_AT_external + .byte 1 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 251 + .byte 1 + .byte 4 # Abbrev [4] 0x33:0x21 DW_TAG_subprogram + .byte 2 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_GNU_all_call_sites + .byte 5 # DW_AT_linkage_name + .byte 6 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + # DW_AT_external + .byte 5 # Abbrev [5] 0x3f:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 85 + .byte 0 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .long 148 # DW_AT_type + .byte 5 # Abbrev [5] 0x49:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 84 + .byte 2 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .long 148 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 6 # Abbrev [6] 0x54:0x2c DW_TAG_subprogram + .byte 3 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_GNU_all_call_sites + .byte 7 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .long 36 # DW_AT_type + # DW_AT_external + .byte 5 # Abbrev [5] 0x63:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 85 + .byte 8 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .long 36 # DW_AT_type + .byte 7 # Abbrev [7] 0x6d:0xc DW_TAG_formal_parameter + .long .Ldebug_loc0-.debug_loc.dwo # DW_AT_location + .byte 9 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .long 153 # DW_AT_type + .byte 8 # Abbrev [8] 0x79:0x6 DW_TAG_GNU_call_site + .long 128 # DW_AT_abstract_origin + # DW_AT_GNU_tail_call + .byte 4 # DW_AT_low_pc + .byte 0 # End Of Children Mark + .byte 9 # Abbrev [9] 0x80:0x14 DW_TAG_subprogram + .byte 3 # DW_AT_linkage_name + .byte 4 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 36 # DW_AT_type + # DW_AT_declaration + # DW_AT_external + .byte 10 # Abbrev [10] 0x89:0x5 DW_TAG_formal_parameter + .long 36 # DW_AT_type + .byte 10 # Abbrev [10] 0x8e:0x5 DW_TAG_formal_parameter + .long 36 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 11 # Abbrev [11] 0x94:0x5 DW_TAG_pointer_type + .long 36 # DW_AT_type + .byte 11 # Abbrev [11] 0x99:0x5 DW_TAG_pointer_type + .long 158 # DW_AT_type + .byte 11 # Abbrev [11] 0x9e:0x5 DW_TAG_pointer_type + .long 163 # DW_AT_type + .byte 3 # Abbrev [3] 0xa3:0x4 DW_TAG_base_type + .byte 10 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end0: + .section .debug_abbrev.dwo,"e",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .ascii "\260B" # DW_AT_GNU_dwo_name + .ascii "\202>" # DW_FORM_GNU_str_index + .ascii "\261B" # DW_AT_GNU_dwo_id + .byte 7 # DW_FORM_data8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .ascii "\201>" # DW_FORM_GNU_addr_index + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .ascii "\227B" # DW_AT_GNU_all_call_sites + .byte 25 # DW_FORM_flag_present + .byte 110 # DW_AT_linkage_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .ascii "\201>" # DW_FORM_GNU_addr_index + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .ascii "\227B" # DW_AT_GNU_all_call_sites + .byte 25 # DW_FORM_flag_present + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 23 # DW_FORM_sec_offset + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .ascii "\211\202\001" # DW_TAG_GNU_call_site + .byte 0 # DW_CHILDREN_no + .byte 49 # DW_AT_abstract_origin + .byte 19 # DW_FORM_ref4 + .ascii "\225B" # DW_AT_GNU_tail_call + .byte 25 # DW_FORM_flag_present + .byte 17 # DW_AT_low_pc + .ascii "\201>" # DW_FORM_GNU_addr_index + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 110 # DW_AT_linkage_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 10 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 11 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_addr,"",@progbits +.Laddr_table_base0: + .quad x + .quad y + .quad .Lfunc_begin0 + .quad .Lfunc_begin1 + .quad .Ltmp3 + .quad .Ltmp1 + .section .debug_gnu_pubnames,"",@progbits + .long .LpubNames_end0-.LpubNames_start0 # Length of Public Names Info +.LpubNames_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 48 # Compilation Unit Length + .long 25 # DIE offset + .byte 32 # Attributes: VARIABLE, EXTERNAL + .asciz "x" # External Name + .long 40 # DIE offset + .byte 32 # Attributes: VARIABLE, EXTERNAL + .asciz "y" # External Name + .long 51 # DIE offset + .byte 48 # Attributes: FUNCTION, EXTERNAL + .asciz "use" # External Name + .long 84 # DIE offset + .byte 48 # Attributes: FUNCTION, EXTERNAL + .asciz "main" # External Name + .long 0 # End Mark +.LpubNames_end0: + .section .debug_gnu_pubtypes,"",@progbits + .long .LpubTypes_end0-.LpubTypes_start0 # Length of Public Types Info +.LpubTypes_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 48 # Compilation Unit Length + .long 36 # DIE offset + .byte 144 # Attributes: TYPE, STATIC + .asciz "int" # External Name + .long 163 # DIE offset + .byte 144 # Attributes: TYPE, STATIC + .asciz "char" # External Name + .long 0 # End Mark +.LpubTypes_end0: + .ident "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 3a8db0f4bfb57348f49d9603119fa157114bbf8e)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/Inputs/dwarf4-df-change-in-dw-op-gnu-addr-index-main.s b/bolt/test/X86/Inputs/dwarf4-df-change-in-dw-op-gnu-addr-index-main.s new file mode 100644 index 0000000000000..6817057c2ac2b --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf4-df-change-in-dw-op-gnu-addr-index-main.s @@ -0,0 +1,734 @@ +# clang++ -O2 -g -gdwarf-4 -gsplit-dwarf main.cpp +# void use(int * x, int * y) { +# static int Foo = *y + *x; +# *x += 4; +# *y -= Foo; +# } +# +# int x = 0; +# int y = 1; +# int main(int argc, char *argv[]) { +# x = argc; +# y = argc + 3; +# use(&x, &y); +# return 0; +# } + + .text + .file "main.cpp" + .file 1 "." "main.cpp" + .globl _Z3usePiS_ # -- Begin function _Z3usePiS_ + .p2align 4, 0x90 + .type _Z3usePiS_,@function +_Z3usePiS_: # @_Z3usePiS_ +.Lfunc_begin0: + .loc 1 1 0 # main.cpp:1:0 + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: use:x <- $rdi + #DEBUG_VALUE: use:y <- $rsi + pushq %r14 + .cfi_def_cfa_offset 16 + pushq %rbx + .cfi_def_cfa_offset 24 + pushq %rax + .cfi_def_cfa_offset 32 + .cfi_offset %rbx, -24 + .cfi_offset %r14, -16 + movq %rsi, %rbx + movq %rdi, %r14 +.Ltmp0: + .loc 1 2 2 prologue_end # main.cpp:2:2 + movzbl _ZGVZ3usePiS_E3Foo(%rip), %eax + testb %al, %al + je .LBB0_1 +.Ltmp1: +.LBB0_3: # %init.end + #DEBUG_VALUE: use:x <- $r14 + #DEBUG_VALUE: use:y <- $rbx + .loc 1 3 5 # main.cpp:3:5 + addl $4, (%r14) + .loc 1 4 8 # main.cpp:4:8 + movl _ZZ3usePiS_E3Foo(%rip), %eax + .loc 1 4 5 is_stmt 0 # main.cpp:4:5 + subl %eax, (%rbx) + .loc 1 5 1 epilogue_begin is_stmt 1 # main.cpp:5:1 + addq $8, %rsp + .cfi_def_cfa_offset 24 + popq %rbx +.Ltmp2: + #DEBUG_VALUE: use:y <- [DW_OP_LLVM_entry_value 1] $rsi + .cfi_def_cfa_offset 16 + popq %r14 +.Ltmp3: + #DEBUG_VALUE: use:x <- [DW_OP_LLVM_entry_value 1] $rdi + .cfi_def_cfa_offset 8 + retq +.Ltmp4: +.LBB0_1: # %init.check + .cfi_def_cfa_offset 32 + #DEBUG_VALUE: use:x <- $r14 + #DEBUG_VALUE: use:y <- $rbx + .loc 1 2 2 # main.cpp:2:2 + leaq _ZGVZ3usePiS_E3Foo(%rip), %rdi + callq __cxa_guard_acquire@PLT +.Ltmp5: + testl %eax, %eax + je .LBB0_3 +.Ltmp6: +# %bb.2: # %init + #DEBUG_VALUE: use:x <- $r14 + #DEBUG_VALUE: use:y <- $rbx + .loc 1 2 24 is_stmt 0 # main.cpp:2:24 + movl (%r14), %eax + .loc 1 2 22 # main.cpp:2:22 + addl (%rbx), %eax + .loc 1 2 2 # main.cpp:2:2 + movl %eax, _ZZ3usePiS_E3Foo(%rip) + leaq _ZGVZ3usePiS_E3Foo(%rip), %rdi + callq __cxa_guard_release@PLT +.Ltmp7: + .loc 1 0 2 # main.cpp:0:2 + jmp .LBB0_3 +.Ltmp8: +.Lfunc_end0: + .size _Z3usePiS_, .Lfunc_end0-_Z3usePiS_ + .cfi_endproc + # -- End function + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin1: + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: main:argc <- $edi + #DEBUG_VALUE: main:argv <- $rsi + .loc 1 10 6 prologue_end is_stmt 1 # main.cpp:10:6 + movl %edi, x(%rip) + .loc 1 11 13 # main.cpp:11:13 + addl $3, %edi +.Ltmp9: + #DEBUG_VALUE: main:argc <- [DW_OP_LLVM_entry_value 1] $edi + .loc 1 11 6 is_stmt 0 # main.cpp:11:6 + movl %edi, y(%rip) +.Ltmp10: + #DEBUG_VALUE: use:y <- undef + #DEBUG_VALUE: use:x <- undef + .loc 1 2 2 is_stmt 1 # main.cpp:2:2 + movzbl _ZGVZ3usePiS_E3Foo(%rip), %eax + testb %al, %al + je .LBB1_1 +.Ltmp11: +.LBB1_4: # %_Z3usePiS_.exit + #DEBUG_VALUE: main:argc <- [DW_OP_LLVM_entry_value 1] $edi + #DEBUG_VALUE: main:argv <- [DW_OP_LLVM_entry_value 1] $rsi + .loc 1 3 5 # main.cpp:3:5 + addl $4, x(%rip) + .loc 1 4 8 # main.cpp:4:8 + movl _ZZ3usePiS_E3Foo(%rip), %eax + .loc 1 4 5 is_stmt 0 # main.cpp:4:5 + subl %eax, y(%rip) +.Ltmp12: + .loc 1 13 4 is_stmt 1 # main.cpp:13:4 + xorl %eax, %eax + retq +.Ltmp13: +.LBB1_1: # %init.check.i + #DEBUG_VALUE: main:argc <- [DW_OP_LLVM_entry_value 1] $edi + #DEBUG_VALUE: main:argv <- $rsi + pushq %rax + .cfi_def_cfa_offset 16 +.Ltmp14: + .loc 1 2 2 # main.cpp:2:2 + leaq _ZGVZ3usePiS_E3Foo(%rip), %rdi + callq __cxa_guard_acquire@PLT +.Ltmp15: + #DEBUG_VALUE: main:argv <- [DW_OP_LLVM_entry_value 1] $rsi + testl %eax, %eax + je .LBB1_3 +.Ltmp16: +# %bb.2: # %init.i + #DEBUG_VALUE: main:argc <- [DW_OP_LLVM_entry_value 1] $edi + #DEBUG_VALUE: main:argv <- [DW_OP_LLVM_entry_value 1] $rsi + .loc 1 2 24 is_stmt 0 # main.cpp:2:24 + movl x(%rip), %eax + .loc 1 2 22 # main.cpp:2:22 + addl y(%rip), %eax + .loc 1 2 2 # main.cpp:2:2 + movl %eax, _ZZ3usePiS_E3Foo(%rip) + leaq _ZGVZ3usePiS_E3Foo(%rip), %rdi + callq __cxa_guard_release@PLT +.Ltmp17: +.LBB1_3: + #DEBUG_VALUE: main:argc <- [DW_OP_LLVM_entry_value 1] $edi + #DEBUG_VALUE: main:argv <- [DW_OP_LLVM_entry_value 1] $rsi + .loc 1 0 2 # main.cpp:0:2 + addq $8, %rsp + .cfi_def_cfa_offset 8 + jmp .LBB1_4 +.Lfunc_end1: + .size main, .Lfunc_end1-main + .cfi_endproc + # -- End function + .type _ZZ3usePiS_E3Foo,@object # @_ZZ3usePiS_E3Foo + .local _ZZ3usePiS_E3Foo + .comm _ZZ3usePiS_E3Foo,4,4 + .type _ZGVZ3usePiS_E3Foo,@object # @_ZGVZ3usePiS_E3Foo + .local _ZGVZ3usePiS_E3Foo + .comm _ZGVZ3usePiS_E3Foo,8,8 + .type x,@object # @x + .bss + .globl x + .p2align 2, 0x0 +x: + .long 0 # 0x0 + .size x, 4 + + .type y,@object # @y + .data + .globl y + .p2align 2, 0x0 +y: + .long 1 # 0x1 + .size y, 4 + + .section .debug_loc.dwo,"e",@progbits +.Ldebug_loc0: + .byte 3 + .byte 3 + .long .Ltmp1-.Lfunc_begin0 + .short 1 # Loc expr size + .byte 85 # DW_OP_reg5 + .byte 3 + .byte 5 + .long .Ltmp3-.Ltmp1 + .short 1 # Loc expr size + .byte 94 # DW_OP_reg14 + .byte 3 + .byte 6 + .long .Ltmp4-.Ltmp3 + .short 4 # Loc expr size + .byte 243 # DW_OP_GNU_entry_value + .byte 1 # 1 + .byte 85 # DW_OP_reg5 + .byte 159 # DW_OP_stack_value + .byte 3 + .byte 7 + .long .Lfunc_end0-.Ltmp4 + .short 1 # Loc expr size + .byte 94 # DW_OP_reg14 + .byte 0 +.Ldebug_loc1: + .byte 3 + .byte 3 + .long .Ltmp1-.Lfunc_begin0 + .short 1 # Loc expr size + .byte 84 # DW_OP_reg4 + .byte 3 + .byte 5 + .long .Ltmp2-.Ltmp1 + .short 1 # Loc expr size + .byte 83 # DW_OP_reg3 + .byte 3 + .byte 8 + .long .Ltmp4-.Ltmp2 + .short 4 # Loc expr size + .byte 243 # DW_OP_GNU_entry_value + .byte 1 # 1 + .byte 84 # DW_OP_reg4 + .byte 159 # DW_OP_stack_value + .byte 3 + .byte 7 + .long .Lfunc_end0-.Ltmp4 + .short 1 # Loc expr size + .byte 83 # DW_OP_reg3 + .byte 0 +.Ldebug_loc2: + .byte 3 + .byte 4 + .long .Ltmp9-.Lfunc_begin1 + .short 1 # Loc expr size + .byte 85 # super-register DW_OP_reg5 + .byte 3 + .byte 9 + .long .Lfunc_end1-.Ltmp9 + .short 4 # Loc expr size + .byte 243 # DW_OP_GNU_entry_value + .byte 1 # 1 + .byte 85 # super-register DW_OP_reg5 + .byte 159 # DW_OP_stack_value + .byte 0 +.Ldebug_loc3: + .byte 3 + .byte 4 + .long .Ltmp11-.Lfunc_begin1 + .short 1 # Loc expr size + .byte 84 # DW_OP_reg4 + .byte 3 + .byte 10 + .long .Ltmp13-.Ltmp11 + .short 4 # Loc expr size + .byte 243 # DW_OP_GNU_entry_value + .byte 1 # 1 + .byte 84 # DW_OP_reg4 + .byte 159 # DW_OP_stack_value + .byte 3 + .byte 11 + .long .Ltmp15-.Ltmp13 + .short 1 # Loc expr size + .byte 84 # DW_OP_reg4 + .byte 3 + .byte 12 + .long .Lfunc_end1-.Ltmp15 + .short 4 # Loc expr size + .byte 243 # DW_OP_GNU_entry_value + .byte 1 # 1 + .byte 84 # DW_OP_reg4 + .byte 159 # DW_OP_stack_value + .byte 0 + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 0 # DW_CHILDREN_no + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .ascii "\264B" # DW_AT_GNU_pubnames + .byte 25 # DW_FORM_flag_present + .ascii "\260B" # DW_AT_GNU_dwo_name + .byte 14 # DW_FORM_strp + .ascii "\261B" # DW_AT_GNU_dwo_id + .byte 7 # DW_FORM_data8 + .ascii "\262B" # DW_AT_GNU_ranges_base + .byte 23 # DW_FORM_sec_offset + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .ascii "\263B" # DW_AT_GNU_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0x29 DW_TAG_compile_unit + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lskel_string0 # DW_AT_comp_dir + # DW_AT_GNU_pubnames + .long .Lskel_string1 # DW_AT_GNU_dwo_name + .quad -3506999759942021708 # DW_AT_GNU_dwo_id + .long .debug_ranges # DW_AT_GNU_ranges_base + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_GNU_addr_base +.Ldebug_info_end0: + .section .debug_ranges,"",@progbits +.Ldebug_ranges0: + .quad .Ltmp10-.Lfunc_begin0 + .quad .Ltmp12-.Lfunc_begin0 + .quad .Ltmp14-.Lfunc_begin0 + .quad .Ltmp17-.Lfunc_begin0 + .quad 0 + .quad 0 + .section .debug_str,"MS",@progbits,1 +.Lskel_string0: + .asciz "." # string offset=0 +.Lskel_string1: + .asciz "main.dwo" # string offset=38 + .section .debug_str.dwo,"eMS",@progbits,1 +.Linfo_string0: + .asciz "Foo" # string offset=0 +.Linfo_string1: + .asciz "int" # string offset=4 +.Linfo_string2: + .asciz "x" # string offset=8 +.Linfo_string3: + .asciz "y" # string offset=10 +.Linfo_string4: + .asciz "_Z3usePiS_" # string offset=12 +.Linfo_string5: + .asciz "use" # string offset=23 +.Linfo_string6: + .asciz "main" # string offset=27 +.Linfo_string7: + .asciz "argc" # string offset=32 +.Linfo_string8: + .asciz "argv" # string offset=37 +.Linfo_string9: + .asciz "char" # string offset=42 +.Linfo_string10: + .asciz "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 3a8db0f4bfb57348f49d9603119fa157114bbf8e)" # string offset=47 +.Linfo_string11: + .asciz "main.cpp" # string offset=148 +.Linfo_string12: + .asciz "main.dwo" # string offset=157 + .section .debug_str_offsets.dwo,"e",@progbits + .long 0 + .long 4 + .long 8 + .long 10 + .long 12 + .long 23 + .long 27 + .long 32 + .long 37 + .long 42 + .long 47 + .long 148 + .long 157 + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit +.Ldebug_info_dwo_start0: + .short 4 # DWARF version number + .long 0 # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0xb1 DW_TAG_compile_unit + .byte 10 # DW_AT_producer + .short 33 # DW_AT_language + .byte 11 # DW_AT_name + .byte 12 # DW_AT_GNU_dwo_name + .quad -3506999759942021708 # DW_AT_GNU_dwo_id + .byte 2 # Abbrev [2] 0x19:0x2a DW_TAG_subprogram + .byte 3 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_GNU_all_call_sites + .long 93 # DW_AT_abstract_origin + .byte 3 # Abbrev [3] 0x25:0xb DW_TAG_variable + .byte 0 # DW_AT_name + .long 67 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 251 + .byte 0 + .byte 4 # Abbrev [4] 0x30:0x9 DW_TAG_formal_parameter + .long .Ldebug_loc0-.debug_loc.dwo # DW_AT_location + .long 99 # DW_AT_abstract_origin + .byte 4 # Abbrev [4] 0x39:0x9 DW_TAG_formal_parameter + .long .Ldebug_loc1-.debug_loc.dwo # DW_AT_location + .long 107 # DW_AT_abstract_origin + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x43:0x4 DW_TAG_base_type + .byte 1 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 6 # Abbrev [6] 0x47:0xb DW_TAG_variable + .byte 2 # DW_AT_name + .long 67 # DW_AT_type + # DW_AT_external + .byte 1 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 251 + .byte 1 + .byte 6 # Abbrev [6] 0x52:0xb DW_TAG_variable + .byte 3 # DW_AT_name + .long 67 # DW_AT_type + # DW_AT_external + .byte 1 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 251 + .byte 2 + .byte 7 # Abbrev [7] 0x5d:0x17 DW_TAG_subprogram + .byte 4 # DW_AT_linkage_name + .byte 5 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + # DW_AT_external + .byte 1 # DW_AT_inline + .byte 8 # Abbrev [8] 0x63:0x8 DW_TAG_formal_parameter + .byte 2 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .long 116 # DW_AT_type + .byte 8 # Abbrev [8] 0x6b:0x8 DW_TAG_formal_parameter + .byte 3 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .long 116 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 9 # Abbrev [9] 0x74:0x5 DW_TAG_pointer_type + .long 67 # DW_AT_type + .byte 10 # Abbrev [10] 0x79:0x34 DW_TAG_subprogram + .byte 4 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_GNU_all_call_sites + .byte 6 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .long 67 # DW_AT_type + # DW_AT_external + .byte 11 # Abbrev [11] 0x88:0xc DW_TAG_formal_parameter + .long .Ldebug_loc2-.debug_loc.dwo # DW_AT_location + .byte 7 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .long 67 # DW_AT_type + .byte 11 # Abbrev [11] 0x94:0xc DW_TAG_formal_parameter + .long .Ldebug_loc3-.debug_loc.dwo # DW_AT_location + .byte 8 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .long 173 # DW_AT_type + .byte 12 # Abbrev [12] 0xa0:0xc DW_TAG_inlined_subroutine + .long 93 # DW_AT_abstract_origin + .long .Ldebug_ranges0-.debug_ranges # DW_AT_ranges + .byte 1 # DW_AT_call_file + .byte 12 # DW_AT_call_line + .byte 4 # DW_AT_call_column + .byte 0 # End Of Children Mark + .byte 9 # Abbrev [9] 0xad:0x5 DW_TAG_pointer_type + .long 178 # DW_AT_type + .byte 9 # Abbrev [9] 0xb2:0x5 DW_TAG_pointer_type + .long 183 # DW_AT_type + .byte 5 # Abbrev [5] 0xb7:0x4 DW_TAG_base_type + .byte 9 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end0: + .section .debug_abbrev.dwo,"e",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .ascii "\260B" # DW_AT_GNU_dwo_name + .ascii "\202>" # DW_FORM_GNU_str_index + .ascii "\261B" # DW_AT_GNU_dwo_id + .byte 7 # DW_FORM_data8 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .ascii "\201>" # DW_FORM_GNU_addr_index + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .ascii "\227B" # DW_AT_GNU_all_call_sites + .byte 25 # DW_FORM_flag_present + .byte 49 # DW_AT_abstract_origin + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 23 # DW_FORM_sec_offset + .byte 49 # DW_AT_abstract_origin + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 110 # DW_AT_linkage_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 32 # DW_AT_inline + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 10 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .ascii "\201>" # DW_FORM_GNU_addr_index + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .ascii "\227B" # DW_AT_GNU_all_call_sites + .byte 25 # DW_FORM_flag_present + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 11 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 23 # DW_FORM_sec_offset + .byte 3 # DW_AT_name + .ascii "\202>" # DW_FORM_GNU_str_index + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 12 # Abbreviation Code + .byte 29 # DW_TAG_inlined_subroutine + .byte 0 # DW_CHILDREN_no + .byte 49 # DW_AT_abstract_origin + .byte 19 # DW_FORM_ref4 + .byte 85 # DW_AT_ranges + .byte 23 # DW_FORM_sec_offset + .byte 88 # DW_AT_call_file + .byte 11 # DW_FORM_data1 + .byte 89 # DW_AT_call_line + .byte 11 # DW_FORM_data1 + .byte 87 # DW_AT_call_column + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_addr,"",@progbits +.Laddr_table_base0: + .quad _ZZ3usePiS_E3Foo + .quad x + .quad y + .quad .Lfunc_begin0 + .quad .Lfunc_begin1 + .quad .Ltmp1 + .quad .Ltmp3 + .quad .Ltmp4 + .quad .Ltmp2 + .quad .Ltmp9 + .quad .Ltmp11 + .quad .Ltmp13 + .quad .Ltmp15 + .section .debug_gnu_pubnames,"",@progbits + .long .LpubNames_end0-.LpubNames_start0 # Length of Public Names Info +.LpubNames_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 52 # Compilation Unit Length + .long 37 # DIE offset + .byte 160 # Attributes: VARIABLE, STATIC + .asciz "use::Foo" # External Name + .long 71 # DIE offset + .byte 32 # Attributes: VARIABLE, EXTERNAL + .asciz "x" # External Name + .long 82 # DIE offset + .byte 32 # Attributes: VARIABLE, EXTERNAL + .asciz "y" # External Name + .long 93 # DIE offset + .byte 48 # Attributes: FUNCTION, EXTERNAL + .asciz "use" # External Name + .long 121 # DIE offset + .byte 48 # Attributes: FUNCTION, EXTERNAL + .asciz "main" # External Name + .long 0 # End Mark +.LpubNames_end0: + .section .debug_gnu_pubtypes,"",@progbits + .long .LpubTypes_end0-.LpubTypes_start0 # Length of Public Types Info +.LpubTypes_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 52 # Compilation Unit Length + .long 67 # DIE offset + .byte 144 # Attributes: TYPE, STATIC + .asciz "int" # External Name + .long 183 # DIE offset + .byte 144 # Attributes: TYPE, STATIC + .asciz "char" # External Name + .long 0 # End Mark +.LpubTypes_end0: + .ident "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 3a8db0f4bfb57348f49d9603119fa157114bbf8e)" + .section ".note.GNU-stack","",@progbits + .addrsig + .addrsig_sym _ZGVZ3usePiS_E3Foo + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/Inputs/dwarf4-two-entries-loclist.s b/bolt/test/X86/Inputs/dwarf4-two-entries-loclist.s new file mode 100644 index 0000000000000..d2df94ce16f88 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf4-two-entries-loclist.s @@ -0,0 +1,390 @@ +# clang++ helper2.cpp -O2 -g2 -gdwarf-4 -S -o helper2.s +# int z1 = 0; +# int d1 = 0; +# +# int helper31(int z_, int d_) { +# z1 += z_; +# d1 += d_; +# return z1 * d1; +# } +# +# +# int z = 0; +# int d = 0; +# +# int helper3(int z_, int d_) { +# z += z_; +# d += d_; +# return z * d; +# } + + .text + .file "helper2.cpp" + .file 1 "/dwarf4CrossCULocList" "helper2.cpp" + .globl _Z8helper31ii # -- Begin function _Z8helper31ii + .p2align 4, 0x90 + .type _Z8helper31ii,@function +_Z8helper31ii: # @_Z8helper31ii +.Lfunc_begin0: + .loc 1 4 0 # helper2.cpp:4:0 + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: helper31:z_ <- $edi + #DEBUG_VALUE: helper31:d_ <- $esi + movl %esi, %eax +.Ltmp0: + .loc 1 5 5 prologue_end # helper2.cpp:5:5 + addl z1(%rip), %edi +.Ltmp1: + #DEBUG_VALUE: helper31:z_ <- [DW_OP_LLVM_entry_value 1] $edi + .loc 1 6 5 # helper2.cpp:6:5 + addl d1(%rip), %eax + .loc 1 5 5 # helper2.cpp:5:5 + movl %edi, z1(%rip) + .loc 1 6 5 # helper2.cpp:6:5 + movl %eax, d1(%rip) + .loc 1 7 12 # helper2.cpp:7:12 + imull %edi, %eax + .loc 1 7 2 is_stmt 0 # helper2.cpp:7:2 + retq +.Ltmp2: +.Lfunc_end0: + .size _Z8helper31ii, .Lfunc_end0-_Z8helper31ii + .cfi_endproc + # -- End function + .globl _Z7helper3ii # -- Begin function _Z7helper3ii + .p2align 4, 0x90 + .type _Z7helper3ii,@function +_Z7helper3ii: # @_Z7helper3ii +.Lfunc_begin1: + .loc 1 14 0 is_stmt 1 # helper2.cpp:14:0 + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: helper3:z_ <- $edi + #DEBUG_VALUE: helper3:d_ <- $esi + movl %esi, %eax +.Ltmp3: + .loc 1 15 4 prologue_end # helper2.cpp:15:4 + addl z(%rip), %edi +.Ltmp4: + #DEBUG_VALUE: helper3:z_ <- [DW_OP_LLVM_entry_value 1] $edi + .loc 1 16 4 # helper2.cpp:16:4 + addl d(%rip), %eax + .loc 1 15 4 # helper2.cpp:15:4 + movl %edi, z(%rip) + .loc 1 16 4 # helper2.cpp:16:4 + movl %eax, d(%rip) + .loc 1 17 11 # helper2.cpp:17:11 + imull %edi, %eax + .loc 1 17 2 is_stmt 0 # helper2.cpp:17:2 + retq +.Ltmp5: +.Lfunc_end1: + .size _Z7helper3ii, .Lfunc_end1-_Z7helper3ii + .cfi_endproc + # -- End function + .type z1,@object # @z1 + .bss + .globl z1 + .p2align 2, 0x0 +z1: + .long 0 # 0x0 + .size z1, 4 + + .type d1,@object # @d1 + .globl d1 + .p2align 2, 0x0 +d1: + .long 0 # 0x0 + .size d1, 4 + + .type z,@object # @z + .globl z + .p2align 2, 0x0 +z: + .long 0 # 0x0 + .size z, 4 + + .type d,@object # @d + .globl d + .p2align 2, 0x0 +d: + .long 0 # 0x0 + .size d, 4 + + .section .debug_loc,"",@progbits +.Ldebug_loc0: + .quad .Lfunc_begin0-.Lfunc_begin0 + .quad .Ltmp1-.Lfunc_begin0 + .short 1 # Loc expr size + .byte 85 # super-register DW_OP_reg5 + .quad .Ltmp1-.Lfunc_begin0 + .quad .Lfunc_end0-.Lfunc_begin0 + .short 4 # Loc expr size + .byte 243 # DW_OP_GNU_entry_value + .byte 1 # 1 + .byte 85 # super-register DW_OP_reg5 + .byte 159 # DW_OP_stack_value + .quad 0 + .quad 0 +.Ldebug_loc1: + .quad .Lfunc_begin1-.Lfunc_begin0 + .quad .Ltmp4-.Lfunc_begin0 + .short 1 # Loc expr size + .byte 85 # super-register DW_OP_reg5 + .quad .Ltmp4-.Lfunc_begin0 + .quad .Lfunc_end1-.Lfunc_begin0 + .short 4 # Loc expr size + .byte 243 # DW_OP_GNU_entry_value + .byte 1 # 1 + .byte 85 # super-register DW_OP_reg5 + .byte 159 # DW_OP_stack_value + .quad 0 + .quad 0 + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 14 # DW_FORM_strp + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .ascii "\227B" # DW_AT_GNU_all_call_sites + .byte 25 # DW_FORM_flag_present + .byte 110 # DW_AT_linkage_name + .byte 14 # DW_FORM_strp + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 23 # DW_FORM_sec_offset + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0xef DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 33 # DW_AT_language + .long .Linfo_string1 # DW_AT_name + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Linfo_string2 # DW_AT_comp_dir + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin0 # DW_AT_high_pc + .byte 2 # Abbrev [2] 0x2a:0x15 DW_TAG_variable + .long .Linfo_string3 # DW_AT_name + .long 63 # DW_AT_type + # DW_AT_external + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 9 # DW_AT_location + .byte 3 + .quad z1 + .byte 3 # Abbrev [3] 0x3f:0x7 DW_TAG_base_type + .long .Linfo_string4 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 2 # Abbrev [2] 0x46:0x15 DW_TAG_variable + .long .Linfo_string5 # DW_AT_name + .long 63 # DW_AT_type + # DW_AT_external + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 9 # DW_AT_location + .byte 3 + .quad d1 + .byte 2 # Abbrev [2] 0x5b:0x15 DW_TAG_variable + .long .Linfo_string6 # DW_AT_name + .long 63 # DW_AT_type + # DW_AT_external + .byte 1 # DW_AT_decl_file + .byte 11 # DW_AT_decl_line + .byte 9 # DW_AT_location + .byte 3 + .quad z + .byte 2 # Abbrev [2] 0x70:0x15 DW_TAG_variable + .long .Linfo_string7 # DW_AT_name + .long 63 # DW_AT_type + # DW_AT_external + .byte 1 # DW_AT_decl_file + .byte 12 # DW_AT_decl_line + .byte 9 # DW_AT_location + .byte 3 + .quad d + .byte 4 # Abbrev [4] 0x85:0x3a DW_TAG_subprogram + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_GNU_all_call_sites + .long .Linfo_string8 # DW_AT_linkage_name + .long .Linfo_string9 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .long 63 # DW_AT_type + # DW_AT_external + .byte 5 # Abbrev [5] 0xa2:0xf DW_TAG_formal_parameter + .long .Ldebug_loc0 # DW_AT_location + .long .Linfo_string12 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .long 63 # DW_AT_type + .byte 6 # Abbrev [6] 0xb1:0xd DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 84 + .long .Linfo_string13 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 4 # DW_AT_decl_line + .long 63 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0xbf:0x3a DW_TAG_subprogram + .quad .Lfunc_begin1 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_GNU_all_call_sites + .long .Linfo_string10 # DW_AT_linkage_name + .long .Linfo_string11 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 14 # DW_AT_decl_line + .long 63 # DW_AT_type + # DW_AT_external + .byte 5 # Abbrev [5] 0xdc:0xf DW_TAG_formal_parameter + .long .Ldebug_loc1 # DW_AT_location + .long .Linfo_string12 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 14 # DW_AT_decl_line + .long 63 # DW_AT_type + .byte 6 # Abbrev [6] 0xeb:0xd DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 84 + .long .Linfo_string13 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 14 # DW_AT_decl_line + .long 63 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 37d6c1cc7d4dd3a8a47ba62254bc88521bd50d66)" # string offset=0 +.Linfo_string1: + .asciz "helper2.cpp" # string offset=101 +.Linfo_string2: + .asciz "/dwarf4CrossCULocList" # string offset=113 +.Linfo_string3: + .asciz "z1" # string offset=172 +.Linfo_string4: + .asciz "int" # string offset=175 +.Linfo_string5: + .asciz "d1" # string offset=179 +.Linfo_string6: + .asciz "z" # string offset=182 +.Linfo_string7: + .asciz "d" # string offset=184 +.Linfo_string8: + .asciz "_Z8helper31ii" # string offset=186 +.Linfo_string9: + .asciz "helper31" # string offset=200 +.Linfo_string10: + .asciz "_Z7helper3ii" # string offset=209 +.Linfo_string11: + .asciz "helper3" # string offset=222 +.Linfo_string12: + .asciz "z_" # string offset=230 +.Linfo_string13: + .asciz "d_" # string offset=233 + .ident "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 37d6c1cc7d4dd3a8a47ba62254bc88521bd50d66)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/Inputs/dwarf5-df-call-site-change-low-pc-helper.s b/bolt/test/X86/Inputs/dwarf5-df-call-site-change-low-pc-helper.s new file mode 100644 index 0000000000000..fd63c7cf33e61 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf5-df-call-site-change-low-pc-helper.s @@ -0,0 +1,380 @@ +# clang++ -O2 -g -gdwarf-4 -gsplit-dwarf +# int z = 0; +# int d = 0; +# int helper(int z_, int d_) { +# z += z_; +# d += d_; +# return z * d; +# } + .text + .file "helper.cpp" + .file 0 "." "helper.cpp" md5 0xb012cefec76132f29ac48b29c7580352 + .globl _Z6helperii # -- Begin function _Z6helperii + .p2align 4, 0x90 + .type _Z6helperii,@function +_Z6helperii: # @_Z6helperii +.Lfunc_begin0: + .loc 0 3 0 # helper.cpp:3:0 + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: helper:z_ <- $edi + #DEBUG_VALUE: helper:d_ <- $esi + movl %esi, %eax +.Ltmp0: + .loc 0 4 4 prologue_end # helper.cpp:4:4 + addl z(%rip), %edi +.Ltmp1: + #DEBUG_VALUE: helper:z_ <- [DW_OP_LLVM_entry_value 1] $edi + .loc 0 5 4 # helper.cpp:5:4 + addl d(%rip), %eax + .loc 0 4 4 # helper.cpp:4:4 + movl %edi, z(%rip) + .loc 0 5 4 # helper.cpp:5:4 + movl %eax, d(%rip) + .loc 0 6 11 # helper.cpp:6:11 + imull %edi, %eax + .loc 0 6 2 is_stmt 0 # helper.cpp:6:2 + retq +.Ltmp2: +.Lfunc_end0: + .size _Z6helperii, .Lfunc_end0-_Z6helperii + .cfi_endproc + # -- End function + .type z,@object # @z + .bss + .globl z + .p2align 2, 0x0 +z: + .long 0 # 0x0 + .size z, 4 + + .type d,@object # @d + .globl d + .p2align 2, 0x0 +d: + .long 0 # 0x0 + .size d, 4 + + .section .debug_loclists.dwo,"e",@progbits + .long .Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length +.Ldebug_list_header_start0: + .short 5 # Version + .byte 8 # Address size + .byte 0 # Segment selector size + .long 1 # Offset entry count +.Lloclists_table_base0: + .long .Ldebug_loc0-.Lloclists_table_base0 +.Ldebug_loc0: + .byte 1 # DW_LLE_base_addressx + .byte 2 # base address index + .byte 4 # DW_LLE_offset_pair + .uleb128 .Lfunc_begin0-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp1-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 85 # super-register DW_OP_reg5 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp1-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end0-.Lfunc_begin0 # ending offset + .byte 4 # Loc expr size + .byte 163 # DW_OP_entry_value + .byte 1 # 1 + .byte 85 # super-register DW_OP_reg5 + .byte 159 # DW_OP_stack_value + .byte 0 # DW_LLE_end_of_list +.Ldebug_list_header_end0: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 74 # DW_TAG_skeleton_unit + .byte 0 # DW_CHILDREN_no + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .ascii "\264B" # DW_AT_GNU_pubnames + .byte 25 # DW_FORM_flag_present + .byte 118 # DW_AT_dwo_name + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 4 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad 6512974040646495267 + .byte 1 # Abbrev [1] 0x14:0x14 DW_TAG_skeleton_unit + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 0 # DW_AT_comp_dir + # DW_AT_GNU_pubnames + .byte 1 # DW_AT_dwo_name + .byte 2 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base +.Ldebug_info_end0: + .section .debug_str_offsets,"",@progbits + .long 12 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Lskel_string0: + .asciz "." # string offset=0 +.Lskel_string1: + .asciz "helper.dwo" # string offset=47 + .section .debug_str_offsets,"",@progbits + .long .Lskel_string0 + .long .Lskel_string1 + .section .debug_str_offsets.dwo,"e",@progbits + .long 44 # Length of String Offsets Set + .short 5 + .short 0 + .section .debug_str.dwo,"eMS",@progbits,1 +.Linfo_string0: + .asciz "z" # string offset=0 +.Linfo_string1: + .asciz "int" # string offset=2 +.Linfo_string2: + .asciz "d" # string offset=6 +.Linfo_string3: + .asciz "_Z6helperii" # string offset=8 +.Linfo_string4: + .asciz "helper" # string offset=20 +.Linfo_string5: + .asciz "z_" # string offset=27 +.Linfo_string6: + .asciz "d_" # string offset=30 +.Linfo_string7: + .asciz "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 3a8db0f4bfb57348f49d9603119fa157114bbf8e)" # string offset=33 +.Linfo_string8: + .asciz "helper.cpp" # string offset=134 +.Linfo_string9: + .asciz "helper.dwo" # string offset=145 + .section .debug_str_offsets.dwo,"e",@progbits + .long 0 + .long 2 + .long 6 + .long 8 + .long 20 + .long 27 + .long 30 + .long 33 + .long 134 + .long 145 + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit +.Ldebug_info_dwo_start0: + .short 5 # DWARF version number + .byte 5 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long 0 # Offset Into Abbrev. Section + .quad 6512974040646495267 + .byte 1 # Abbrev [1] 0x14:0x45 DW_TAG_compile_unit + .byte 7 # DW_AT_producer + .short 33 # DW_AT_language + .byte 8 # DW_AT_name + .byte 9 # DW_AT_dwo_name + .byte 2 # Abbrev [2] 0x1a:0xb DW_TAG_variable + .byte 0 # DW_AT_name + .long 37 # DW_AT_type + # DW_AT_external + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 0 + .byte 3 # Abbrev [3] 0x25:0x4 DW_TAG_base_type + .byte 1 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 2 # Abbrev [2] 0x29:0xb DW_TAG_variable + .byte 2 # DW_AT_name + .long 37 # DW_AT_type + # DW_AT_external + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 1 + .byte 4 # Abbrev [4] 0x34:0x24 DW_TAG_subprogram + .byte 2 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_call_all_calls + .byte 3 # DW_AT_linkage_name + .byte 4 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .long 37 # DW_AT_type + # DW_AT_external + .byte 5 # Abbrev [5] 0x44:0x9 DW_TAG_formal_parameter + .byte 0 # DW_AT_location + .byte 5 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .long 37 # DW_AT_type + .byte 6 # Abbrev [6] 0x4d:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 84 + .byte 6 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .long 37 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end0: + .section .debug_abbrev.dwo,"e",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 118 # DW_AT_dwo_name + .byte 37 # DW_FORM_strx1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .byte 110 # DW_AT_linkage_name + .byte 37 # DW_FORM_strx1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 34 # DW_FORM_loclistx + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad z + .quad d + .quad .Lfunc_begin0 +.Ldebug_addr_end0: + .section .debug_gnu_pubnames,"",@progbits + .long .LpubNames_end0-.LpubNames_start0 # Length of Public Names Info +.LpubNames_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 40 # Compilation Unit Length + .long 26 # DIE offset + .byte 32 # Attributes: VARIABLE, EXTERNAL + .asciz "z" # External Name + .long 41 # DIE offset + .byte 32 # Attributes: VARIABLE, EXTERNAL + .asciz "d" # External Name + .long 52 # DIE offset + .byte 48 # Attributes: FUNCTION, EXTERNAL + .asciz "helper" # External Name + .long 0 # End Mark +.LpubNames_end0: + .section .debug_gnu_pubtypes,"",@progbits + .long .LpubTypes_end0-.LpubTypes_start0 # Length of Public Types Info +.LpubTypes_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 40 # Compilation Unit Length + .long 37 # DIE offset + .byte 144 # Attributes: TYPE, STATIC + .asciz "int" # External Name + .long 0 # End Mark +.LpubTypes_end0: + .ident "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 3a8db0f4bfb57348f49d9603119fa157114bbf8e)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/Inputs/dwarf5-df-call-site-change-low-pc-main.s b/bolt/test/X86/Inputs/dwarf5-df-call-site-change-low-pc-main.s new file mode 100644 index 0000000000000..ad4ab64659e4d --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf5-df-call-site-change-low-pc-main.s @@ -0,0 +1,552 @@ +# clang++ -O2 -g -gdwarf-4 -gsplit-dwarf +# void use(int * x, int * y) { +# *x += 4; +# *y -= 2; +# } +# +# int helper(int z_, int d_); +# int x = 0; +# int y = 1; +# int main(int argc, char *argv[]) { +# x = argc; +# y = argc + 3; +# //use(&x, &y); +# return helper(x, y); +# } + .text + .file "main.cpp" + .file 0 "." "main.cpp" md5 0x1a68208241c6577e68c7b707538826da + .globl _Z3usePiS_ # -- Begin function _Z3usePiS_ + .p2align 4, 0x90 + .type _Z3usePiS_,@function +_Z3usePiS_: # @_Z3usePiS_ +.Lfunc_begin0: + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: use:x <- $rdi + #DEBUG_VALUE: use:y <- $rsi + .loc 0 2 5 prologue_end # main.cpp:2:5 + addl $4, (%rdi) + .loc 0 3 5 # main.cpp:3:5 + addl $-2, (%rsi) + .loc 0 4 1 # main.cpp:4:1 + retq +.Ltmp0: +.Lfunc_end0: + .size _Z3usePiS_, .Lfunc_end0-_Z3usePiS_ + .cfi_endproc + # -- End function + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin1: + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: main:argc <- $edi + #DEBUG_VALUE: main:argv <- $rsi + # kill: def $edi killed $edi def $rdi + .loc 0 10 6 prologue_end # main.cpp:10:6 + movl %edi, x(%rip) + .loc 0 11 13 # main.cpp:11:13 + leal 3(%rdi), %esi +.Ltmp1: + #DEBUG_VALUE: main:argv <- [DW_OP_LLVM_entry_value 1] $rsi + .loc 0 11 6 is_stmt 0 # main.cpp:11:6 + movl %esi, y(%rip) + # kill: def $edi killed $edi killed $rdi +.Ltmp2: + .loc 0 13 11 is_stmt 1 # main.cpp:13:11 + jmp _Z6helperii@PLT # TAILCALL +.Ltmp3: +.Lfunc_end1: + .size main, .Lfunc_end1-main + .cfi_endproc + # -- End function + .type x,@object # @x + .bss + .globl x + .p2align 2, 0x0 +x: + .long 0 # 0x0 + .size x, 4 + + .type y,@object # @y + .data + .globl y + .p2align 2, 0x0 +y: + .long 1 # 0x1 + .size y, 4 + + .section .debug_loclists.dwo,"e",@progbits + .long .Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length +.Ldebug_list_header_start0: + .short 5 # Version + .byte 8 # Address size + .byte 0 # Segment selector size + .long 1 # Offset entry count +.Lloclists_table_base0: + .long .Ldebug_loc0-.Lloclists_table_base0 +.Ldebug_loc0: + .byte 1 # DW_LLE_base_addressx + .byte 2 # base address index + .byte 4 # DW_LLE_offset_pair + .uleb128 .Lfunc_begin1-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp1-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 84 # DW_OP_reg4 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp1-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end1-.Lfunc_begin0 # ending offset + .byte 4 # Loc expr size + .byte 163 # DW_OP_entry_value + .byte 1 # 1 + .byte 84 # DW_OP_reg4 + .byte 159 # DW_OP_stack_value + .byte 0 # DW_LLE_end_of_list +.Ldebug_list_header_end0: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 74 # DW_TAG_skeleton_unit + .byte 0 # DW_CHILDREN_no + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .ascii "\264B" # DW_AT_GNU_pubnames + .byte 25 # DW_FORM_flag_present + .byte 118 # DW_AT_dwo_name + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 4 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad 1538385283627936656 + .byte 1 # Abbrev [1] 0x14:0x14 DW_TAG_skeleton_unit + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 0 # DW_AT_comp_dir + # DW_AT_GNU_pubnames + .byte 1 # DW_AT_dwo_name + .byte 2 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base +.Ldebug_info_end0: + .section .debug_str_offsets,"",@progbits + .long 12 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Lskel_string0: + .asciz "." # string offset=0 +.Lskel_string1: + .asciz "main.dwo" # string offset=47 + .section .debug_str_offsets,"",@progbits + .long .Lskel_string0 + .long .Lskel_string1 + .section .debug_str_offsets.dwo,"e",@progbits + .long 60 # Length of String Offsets Set + .short 5 + .short 0 + .section .debug_str.dwo,"eMS",@progbits,1 +.Linfo_string0: + .asciz "x" # string offset=0 +.Linfo_string1: + .asciz "int" # string offset=2 +.Linfo_string2: + .asciz "y" # string offset=6 +.Linfo_string3: + .asciz "_Z6helperii" # string offset=8 +.Linfo_string4: + .asciz "helper" # string offset=20 +.Linfo_string5: + .asciz "_Z3usePiS_" # string offset=27 +.Linfo_string6: + .asciz "use" # string offset=38 +.Linfo_string7: + .asciz "main" # string offset=42 +.Linfo_string8: + .asciz "argc" # string offset=47 +.Linfo_string9: + .asciz "argv" # string offset=52 +.Linfo_string10: + .asciz "char" # string offset=57 +.Linfo_string11: + .asciz "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 3a8db0f4bfb57348f49d9603119fa157114bbf8e)" # string offset=62 +.Linfo_string12: + .asciz "main.cpp" # string offset=163 +.Linfo_string13: + .asciz "main.dwo" # string offset=172 + .section .debug_str_offsets.dwo,"e",@progbits + .long 0 + .long 2 + .long 6 + .long 8 + .long 20 + .long 27 + .long 38 + .long 42 + .long 47 + .long 52 + .long 57 + .long 62 + .long 163 + .long 172 + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit +.Ldebug_info_dwo_start0: + .short 5 # DWARF version number + .byte 5 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long 0 # Offset Into Abbrev. Section + .quad 1538385283627936656 + .byte 1 # Abbrev [1] 0x14:0x8e DW_TAG_compile_unit + .byte 11 # DW_AT_producer + .short 33 # DW_AT_language + .byte 12 # DW_AT_name + .byte 13 # DW_AT_dwo_name + .byte 2 # Abbrev [2] 0x1a:0xb DW_TAG_variable + .byte 0 # DW_AT_name + .long 37 # DW_AT_type + # DW_AT_external + .byte 0 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 0 + .byte 3 # Abbrev [3] 0x25:0x4 DW_TAG_base_type + .byte 1 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 2 # Abbrev [2] 0x29:0xb DW_TAG_variable + .byte 2 # DW_AT_name + .long 37 # DW_AT_type + # DW_AT_external + .byte 0 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 1 + .byte 4 # Abbrev [4] 0x34:0x21 DW_TAG_subprogram + .byte 2 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_call_all_calls + .byte 5 # DW_AT_linkage_name + .byte 6 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + # DW_AT_external + .byte 5 # Abbrev [5] 0x40:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 85 + .byte 0 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .long 142 # DW_AT_type + .byte 5 # Abbrev [5] 0x4a:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 84 + .byte 2 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .long 142 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 6 # Abbrev [6] 0x55:0x25 DW_TAG_subprogram + .byte 0 # DW_AT_ranges + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_call_all_calls + .byte 7 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .long 37 # DW_AT_type + # DW_AT_external + .byte 5 # Abbrev [5] 0x60:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 85 + .byte 8 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .long 37 # DW_AT_type + .byte 7 # Abbrev [7] 0x6a:0x9 DW_TAG_formal_parameter + .byte 0 # DW_AT_location + .byte 9 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .long 147 # DW_AT_type + .byte 8 # Abbrev [8] 0x73:0x6 DW_TAG_call_site + .long 122 # DW_AT_call_origin + # DW_AT_call_tail_call + .byte 3 # DW_AT_call_pc + .byte 0 # End Of Children Mark + .byte 9 # Abbrev [9] 0x7a:0x14 DW_TAG_subprogram + .byte 3 # DW_AT_linkage_name + .byte 4 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 37 # DW_AT_type + # DW_AT_declaration + # DW_AT_external + .byte 10 # Abbrev [10] 0x83:0x5 DW_TAG_formal_parameter + .long 37 # DW_AT_type + .byte 10 # Abbrev [10] 0x88:0x5 DW_TAG_formal_parameter + .long 37 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 11 # Abbrev [11] 0x8e:0x5 DW_TAG_pointer_type + .long 37 # DW_AT_type + .byte 11 # Abbrev [11] 0x93:0x5 DW_TAG_pointer_type + .long 152 # DW_AT_type + .byte 11 # Abbrev [11] 0x98:0x5 DW_TAG_pointer_type + .long 157 # DW_AT_type + .byte 3 # Abbrev [3] 0x9d:0x4 DW_TAG_base_type + .byte 10 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end0: + .section .debug_abbrev.dwo,"e",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 118 # DW_AT_dwo_name + .byte 37 # DW_FORM_strx1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .byte 110 # DW_AT_linkage_name + .byte 37 # DW_FORM_strx1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 85 # DW_AT_ranges + .byte 35 # DW_FORM_rnglistx + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 34 # DW_FORM_loclistx + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 72 # DW_TAG_call_site + .byte 0 # DW_CHILDREN_no + .byte 127 # DW_AT_call_origin + .byte 19 # DW_FORM_ref4 + .ascii "\202\001" # DW_AT_call_tail_call + .byte 25 # DW_FORM_flag_present + .ascii "\201\001" # DW_AT_call_pc + .byte 27 # DW_FORM_addrx + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 110 # DW_AT_linkage_name + .byte 37 # DW_FORM_strx1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 60 # DW_AT_declaration + .byte 25 # DW_FORM_flag_present + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 10 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 11 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_rnglists.dwo,"e",@progbits + .long .Ldebug_list_header_end1-.Ldebug_list_header_start1 # Length +.Ldebug_list_header_start1: + .short 5 # Version + .byte 8 # Address size + .byte 0 # Segment selector size + .long 1 # Offset entry count +.Lrnglists_dwo_table_base0: + .long .Ldebug_ranges0-.Lrnglists_dwo_table_base0 +.Ldebug_ranges0: + .byte 4 # DW_RLE_offset_pair + .uleb128 .Lfunc_begin1-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end1-.Lfunc_begin0 # ending offset + .byte 0 # DW_RLE_end_of_list +.Ldebug_list_header_end1: + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad x + .quad y + .quad .Lfunc_begin0 + .quad .Ltmp2 +.Ldebug_addr_end0: + .section .debug_gnu_pubnames,"",@progbits + .long .LpubNames_end0-.LpubNames_start0 # Length of Public Names Info +.LpubNames_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 40 # Compilation Unit Length + .long 26 # DIE offset + .byte 32 # Attributes: VARIABLE, EXTERNAL + .asciz "x" # External Name + .long 41 # DIE offset + .byte 32 # Attributes: VARIABLE, EXTERNAL + .asciz "y" # External Name + .long 52 # DIE offset + .byte 48 # Attributes: FUNCTION, EXTERNAL + .asciz "use" # External Name + .long 85 # DIE offset + .byte 48 # Attributes: FUNCTION, EXTERNAL + .asciz "main" # External Name + .long 0 # End Mark +.LpubNames_end0: + .section .debug_gnu_pubtypes,"",@progbits + .long .LpubTypes_end0-.LpubTypes_start0 # Length of Public Types Info +.LpubTypes_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 40 # Compilation Unit Length + .long 37 # DIE offset + .byte 144 # Attributes: TYPE, STATIC + .asciz "int" # External Name + .long 157 # DIE offset + .byte 144 # Attributes: TYPE, STATIC + .asciz "char" # External Name + .long 0 # End Mark +.LpubTypes_end0: + .ident "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 3a8db0f4bfb57348f49d9603119fa157114bbf8e)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/Inputs/dwarf5-df-change-in-dw-op-gnu-addr-index-main.s b/bolt/test/X86/Inputs/dwarf5-df-change-in-dw-op-gnu-addr-index-main.s new file mode 100644 index 0000000000000..1b0154f740b65 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf5-df-change-in-dw-op-gnu-addr-index-main.s @@ -0,0 +1,774 @@ +# clang++ -O2 -g -gdwarf-5 -gsplit-dwarf main.cpp +# void use(int * x, int * y) { +# static int Foo = *y + *x; +# *x += 4; +# *y -= Foo; +# } +# +# int x = 0; +# int y = 1; +# int main(int argc, char *argv[]) { +# x = argc; +# y = argc + 3; +# use(&x, &y); +# return 0; +# } + .text + .file "main.cpp" + .file 0 "." "main.cpp" md5 0x4f704c611bdcbf8d7a62eb17d439188e + .globl _Z3usePiS_ # -- Begin function _Z3usePiS_ + .p2align 4, 0x90 + .type _Z3usePiS_,@function +_Z3usePiS_: # @_Z3usePiS_ +.Lfunc_begin0: + .loc 0 1 0 # main.cpp:1:0 + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: use:x <- $rdi + #DEBUG_VALUE: use:y <- $rsi + pushq %r14 + .cfi_def_cfa_offset 16 + pushq %rbx + .cfi_def_cfa_offset 24 + pushq %rax + .cfi_def_cfa_offset 32 + .cfi_offset %rbx, -24 + .cfi_offset %r14, -16 + movq %rsi, %rbx + movq %rdi, %r14 +.Ltmp0: + .loc 0 2 2 prologue_end # main.cpp:2:2 + movzbl _ZGVZ3usePiS_E3Foo(%rip), %eax + testb %al, %al + je .LBB0_1 +.Ltmp1: +.LBB0_3: # %init.end + #DEBUG_VALUE: use:x <- $r14 + #DEBUG_VALUE: use:y <- $rbx + .loc 0 3 5 # main.cpp:3:5 + addl $4, (%r14) + .loc 0 4 8 # main.cpp:4:8 + movl _ZZ3usePiS_E3Foo(%rip), %eax + .loc 0 4 5 is_stmt 0 # main.cpp:4:5 + subl %eax, (%rbx) + .loc 0 5 1 epilogue_begin is_stmt 1 # main.cpp:5:1 + addq $8, %rsp + .cfi_def_cfa_offset 24 + popq %rbx +.Ltmp2: + #DEBUG_VALUE: use:y <- [DW_OP_LLVM_entry_value 1] $rsi + .cfi_def_cfa_offset 16 + popq %r14 +.Ltmp3: + #DEBUG_VALUE: use:x <- [DW_OP_LLVM_entry_value 1] $rdi + .cfi_def_cfa_offset 8 + retq +.Ltmp4: +.LBB0_1: # %init.check + .cfi_def_cfa_offset 32 + #DEBUG_VALUE: use:x <- $r14 + #DEBUG_VALUE: use:y <- $rbx + .loc 0 2 2 # main.cpp:2:2 + leaq _ZGVZ3usePiS_E3Foo(%rip), %rdi + callq __cxa_guard_acquire@PLT +.Ltmp5: + testl %eax, %eax + je .LBB0_3 +.Ltmp6: +# %bb.2: # %init + #DEBUG_VALUE: use:x <- $r14 + #DEBUG_VALUE: use:y <- $rbx + .loc 0 2 24 is_stmt 0 # main.cpp:2:24 + movl (%r14), %eax + .loc 0 2 22 # main.cpp:2:22 + addl (%rbx), %eax + .loc 0 2 2 # main.cpp:2:2 + movl %eax, _ZZ3usePiS_E3Foo(%rip) + leaq _ZGVZ3usePiS_E3Foo(%rip), %rdi + callq __cxa_guard_release@PLT +.Ltmp7: + .loc 0 0 2 # main.cpp:0:2 + jmp .LBB0_3 +.Ltmp8: +.Lfunc_end0: + .size _Z3usePiS_, .Lfunc_end0-_Z3usePiS_ + .cfi_endproc + # -- End function + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin1: + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: main:argc <- $edi + #DEBUG_VALUE: main:argv <- $rsi + .loc 0 10 6 prologue_end is_stmt 1 # main.cpp:10:6 + movl %edi, x(%rip) + .loc 0 11 13 # main.cpp:11:13 + addl $3, %edi +.Ltmp9: + #DEBUG_VALUE: main:argc <- [DW_OP_LLVM_entry_value 1] $edi + .loc 0 11 6 is_stmt 0 # main.cpp:11:6 + movl %edi, y(%rip) +.Ltmp10: + #DEBUG_VALUE: use:y <- undef + #DEBUG_VALUE: use:x <- undef + .loc 0 2 2 is_stmt 1 # main.cpp:2:2 + movzbl _ZGVZ3usePiS_E3Foo(%rip), %eax + testb %al, %al + je .LBB1_1 +.Ltmp11: +.LBB1_4: # %_Z3usePiS_.exit + #DEBUG_VALUE: main:argc <- [DW_OP_LLVM_entry_value 1] $edi + #DEBUG_VALUE: main:argv <- [DW_OP_LLVM_entry_value 1] $rsi + .loc 0 3 5 # main.cpp:3:5 + addl $4, x(%rip) + .loc 0 4 8 # main.cpp:4:8 + movl _ZZ3usePiS_E3Foo(%rip), %eax + .loc 0 4 5 is_stmt 0 # main.cpp:4:5 + subl %eax, y(%rip) +.Ltmp12: + .loc 0 13 4 is_stmt 1 # main.cpp:13:4 + xorl %eax, %eax + retq +.Ltmp13: +.LBB1_1: # %init.check.i + #DEBUG_VALUE: main:argc <- [DW_OP_LLVM_entry_value 1] $edi + #DEBUG_VALUE: main:argv <- $rsi + pushq %rax + .cfi_def_cfa_offset 16 +.Ltmp14: + .loc 0 2 2 # main.cpp:2:2 + leaq _ZGVZ3usePiS_E3Foo(%rip), %rdi + callq __cxa_guard_acquire@PLT +.Ltmp15: + #DEBUG_VALUE: main:argv <- [DW_OP_LLVM_entry_value 1] $rsi + testl %eax, %eax + je .LBB1_3 +.Ltmp16: +# %bb.2: # %init.i + #DEBUG_VALUE: main:argc <- [DW_OP_LLVM_entry_value 1] $edi + #DEBUG_VALUE: main:argv <- [DW_OP_LLVM_entry_value 1] $rsi + .loc 0 2 24 is_stmt 0 # main.cpp:2:24 + movl x(%rip), %eax + .loc 0 2 22 # main.cpp:2:22 + addl y(%rip), %eax + .loc 0 2 2 # main.cpp:2:2 + movl %eax, _ZZ3usePiS_E3Foo(%rip) + leaq _ZGVZ3usePiS_E3Foo(%rip), %rdi + callq __cxa_guard_release@PLT +.Ltmp17: +.LBB1_3: + #DEBUG_VALUE: main:argc <- [DW_OP_LLVM_entry_value 1] $edi + #DEBUG_VALUE: main:argv <- [DW_OP_LLVM_entry_value 1] $rsi + .loc 0 0 2 # main.cpp:0:2 + addq $8, %rsp + .cfi_def_cfa_offset 8 + jmp .LBB1_4 +.Lfunc_end1: + .size main, .Lfunc_end1-main + .cfi_endproc + # -- End function + .type _ZZ3usePiS_E3Foo,@object # @_ZZ3usePiS_E3Foo + .local _ZZ3usePiS_E3Foo + .comm _ZZ3usePiS_E3Foo,4,4 + .type _ZGVZ3usePiS_E3Foo,@object # @_ZGVZ3usePiS_E3Foo + .local _ZGVZ3usePiS_E3Foo + .comm _ZGVZ3usePiS_E3Foo,8,8 + .type x,@object # @x + .bss + .globl x + .p2align 2, 0x0 +x: + .long 0 # 0x0 + .size x, 4 + + .type y,@object # @y + .data + .globl y + .p2align 2, 0x0 +y: + .long 1 # 0x1 + .size y, 4 + + .section .debug_loclists.dwo,"e",@progbits + .long .Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length +.Ldebug_list_header_start0: + .short 5 # Version + .byte 8 # Address size + .byte 0 # Segment selector size + .long 4 # Offset entry count +.Lloclists_table_base0: + .long .Ldebug_loc0-.Lloclists_table_base0 + .long .Ldebug_loc1-.Lloclists_table_base0 + .long .Ldebug_loc2-.Lloclists_table_base0 + .long .Ldebug_loc3-.Lloclists_table_base0 +.Ldebug_loc0: + .byte 1 # DW_LLE_base_addressx + .byte 3 # base address index + .byte 4 # DW_LLE_offset_pair + .uleb128 .Lfunc_begin0-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp1-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 85 # DW_OP_reg5 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp1-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp3-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 94 # DW_OP_reg14 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp3-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp4-.Lfunc_begin0 # ending offset + .byte 4 # Loc expr size + .byte 163 # DW_OP_entry_value + .byte 1 # 1 + .byte 85 # DW_OP_reg5 + .byte 159 # DW_OP_stack_value + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp4-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end0-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 94 # DW_OP_reg14 + .byte 0 # DW_LLE_end_of_list +.Ldebug_loc1: + .byte 1 # DW_LLE_base_addressx + .byte 3 # base address index + .byte 4 # DW_LLE_offset_pair + .uleb128 .Lfunc_begin0-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp1-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 84 # DW_OP_reg4 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp1-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp2-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 83 # DW_OP_reg3 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp2-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp4-.Lfunc_begin0 # ending offset + .byte 4 # Loc expr size + .byte 163 # DW_OP_entry_value + .byte 1 # 1 + .byte 84 # DW_OP_reg4 + .byte 159 # DW_OP_stack_value + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp4-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end0-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 83 # DW_OP_reg3 + .byte 0 # DW_LLE_end_of_list +.Ldebug_loc2: + .byte 1 # DW_LLE_base_addressx + .byte 3 # base address index + .byte 4 # DW_LLE_offset_pair + .uleb128 .Lfunc_begin1-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp9-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 85 # super-register DW_OP_reg5 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp9-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end1-.Lfunc_begin0 # ending offset + .byte 4 # Loc expr size + .byte 163 # DW_OP_entry_value + .byte 1 # 1 + .byte 85 # super-register DW_OP_reg5 + .byte 159 # DW_OP_stack_value + .byte 0 # DW_LLE_end_of_list +.Ldebug_loc3: + .byte 1 # DW_LLE_base_addressx + .byte 3 # base address index + .byte 4 # DW_LLE_offset_pair + .uleb128 .Lfunc_begin1-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp11-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 84 # DW_OP_reg4 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp11-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp13-.Lfunc_begin0 # ending offset + .byte 4 # Loc expr size + .byte 163 # DW_OP_entry_value + .byte 1 # 1 + .byte 84 # DW_OP_reg4 + .byte 159 # DW_OP_stack_value + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp13-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp15-.Lfunc_begin0 # ending offset + .byte 1 # Loc expr size + .byte 84 # DW_OP_reg4 + .byte 4 # DW_LLE_offset_pair + .uleb128 .Ltmp15-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end1-.Lfunc_begin0 # ending offset + .byte 4 # Loc expr size + .byte 163 # DW_OP_entry_value + .byte 1 # 1 + .byte 84 # DW_OP_reg4 + .byte 159 # DW_OP_stack_value + .byte 0 # DW_LLE_end_of_list +.Ldebug_list_header_end0: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 74 # DW_TAG_skeleton_unit + .byte 0 # DW_CHILDREN_no + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .ascii "\264B" # DW_AT_GNU_pubnames + .byte 25 # DW_FORM_flag_present + .byte 118 # DW_AT_dwo_name + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 4 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .quad -3440409667494789237 + .byte 1 # Abbrev [1] 0x14:0x14 DW_TAG_skeleton_unit + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .byte 0 # DW_AT_comp_dir + # DW_AT_GNU_pubnames + .byte 1 # DW_AT_dwo_name + .byte 3 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base +.Ldebug_info_end0: + .section .debug_str_offsets,"",@progbits + .long 12 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Lskel_string0: + .asciz "." # string offset=0 +.Lskel_string1: + .asciz "main.dwo" # string offset=38 + .section .debug_str_offsets,"",@progbits + .long .Lskel_string0 + .long .Lskel_string1 + .section .debug_str_offsets.dwo,"e",@progbits + .long 56 # Length of String Offsets Set + .short 5 + .short 0 + .section .debug_str.dwo,"eMS",@progbits,1 +.Linfo_string0: + .asciz "Foo" # string offset=0 +.Linfo_string1: + .asciz "int" # string offset=4 +.Linfo_string2: + .asciz "x" # string offset=8 +.Linfo_string3: + .asciz "y" # string offset=10 +.Linfo_string4: + .asciz "_Z3usePiS_" # string offset=12 +.Linfo_string5: + .asciz "use" # string offset=23 +.Linfo_string6: + .asciz "main" # string offset=27 +.Linfo_string7: + .asciz "argc" # string offset=32 +.Linfo_string8: + .asciz "argv" # string offset=37 +.Linfo_string9: + .asciz "char" # string offset=42 +.Linfo_string10: + .asciz "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 3a8db0f4bfb57348f49d9603119fa157114bbf8e)" # string offset=47 +.Linfo_string11: + .asciz "main.cpp" # string offset=148 +.Linfo_string12: + .asciz "main.dwo" # string offset=157 + .section .debug_str_offsets.dwo,"e",@progbits + .long 0 + .long 4 + .long 8 + .long 10 + .long 12 + .long 23 + .long 27 + .long 32 + .long 37 + .long 42 + .long 47 + .long 148 + .long 157 + .section .debug_info.dwo,"e",@progbits + .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 # Length of Unit +.Ldebug_info_dwo_start0: + .short 5 # DWARF version number + .byte 5 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long 0 # Offset Into Abbrev. Section + .quad -3440409667494789237 + .byte 1 # Abbrev [1] 0x14:0x95 DW_TAG_compile_unit + .byte 10 # DW_AT_producer + .short 33 # DW_AT_language + .byte 11 # DW_AT_name + .byte 12 # DW_AT_dwo_name + .byte 2 # Abbrev [2] 0x1a:0x24 DW_TAG_subprogram + .byte 3 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_call_all_calls + .long 88 # DW_AT_abstract_origin + .byte 3 # Abbrev [3] 0x26:0xb DW_TAG_variable + .byte 0 # DW_AT_name + .long 62 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 0 + .byte 4 # Abbrev [4] 0x31:0x6 DW_TAG_formal_parameter + .byte 0 # DW_AT_location + .long 93 # DW_AT_abstract_origin + .byte 4 # Abbrev [4] 0x37:0x6 DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .long 101 # DW_AT_abstract_origin + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x3e:0x4 DW_TAG_base_type + .byte 1 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 6 # Abbrev [6] 0x42:0xb DW_TAG_variable + .byte 2 # DW_AT_name + .long 62 # DW_AT_type + # DW_AT_external + .byte 0 # DW_AT_decl_file + .byte 7 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 1 + .byte 6 # Abbrev [6] 0x4d:0xb DW_TAG_variable + .byte 3 # DW_AT_name + .long 62 # DW_AT_type + # DW_AT_external + .byte 0 # DW_AT_decl_file + .byte 8 # DW_AT_decl_line + .byte 2 # DW_AT_location + .byte 161 + .byte 2 + .byte 7 # Abbrev [7] 0x58:0x16 DW_TAG_subprogram + .byte 4 # DW_AT_linkage_name + .byte 5 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + # DW_AT_external + # DW_AT_inline + .byte 8 # Abbrev [8] 0x5d:0x8 DW_TAG_formal_parameter + .byte 2 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .long 110 # DW_AT_type + .byte 8 # Abbrev [8] 0x65:0x8 DW_TAG_formal_parameter + .byte 3 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .long 110 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 9 # Abbrev [9] 0x6e:0x5 DW_TAG_pointer_type + .long 62 # DW_AT_type + .byte 10 # Abbrev [10] 0x73:0x27 DW_TAG_subprogram + .byte 0 # DW_AT_ranges + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_call_all_calls + .byte 6 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .long 62 # DW_AT_type + # DW_AT_external + .byte 11 # Abbrev [11] 0x7e:0x9 DW_TAG_formal_parameter + .byte 2 # DW_AT_location + .byte 7 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .long 62 # DW_AT_type + .byte 11 # Abbrev [11] 0x87:0x9 DW_TAG_formal_parameter + .byte 3 # DW_AT_location + .byte 8 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .long 154 # DW_AT_type + .byte 12 # Abbrev [12] 0x90:0x9 DW_TAG_inlined_subroutine + .long 88 # DW_AT_abstract_origin + .byte 1 # DW_AT_ranges + .byte 0 # DW_AT_call_file + .byte 12 # DW_AT_call_line + .byte 4 # DW_AT_call_column + .byte 0 # End Of Children Mark + .byte 9 # Abbrev [9] 0x9a:0x5 DW_TAG_pointer_type + .long 159 # DW_AT_type + .byte 9 # Abbrev [9] 0x9f:0x5 DW_TAG_pointer_type + .long 164 # DW_AT_type + .byte 5 # Abbrev [5] 0xa4:0x4 DW_TAG_base_type + .byte 9 # DW_AT_name + .byte 6 # DW_AT_encoding + .byte 1 # DW_AT_byte_size + .byte 0 # End Of Children Mark +.Ldebug_info_dwo_end0: + .section .debug_abbrev.dwo,"e",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 118 # DW_AT_dwo_name + .byte 37 # DW_FORM_strx1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .byte 49 # DW_AT_abstract_origin + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 34 # DW_FORM_loclistx + .byte 49 # DW_AT_abstract_origin + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 110 # DW_AT_linkage_name + .byte 37 # DW_FORM_strx1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 32 # DW_AT_inline + .byte 33 # DW_FORM_implicit_const + .byte 1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 15 # DW_TAG_pointer_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 10 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 85 # DW_AT_ranges + .byte 35 # DW_FORM_rnglistx + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 11 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 34 # DW_FORM_loclistx + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 12 # Abbreviation Code + .byte 29 # DW_TAG_inlined_subroutine + .byte 0 # DW_CHILDREN_no + .byte 49 # DW_AT_abstract_origin + .byte 19 # DW_FORM_ref4 + .byte 85 # DW_AT_ranges + .byte 35 # DW_FORM_rnglistx + .byte 88 # DW_AT_call_file + .byte 11 # DW_FORM_data1 + .byte 89 # DW_AT_call_line + .byte 11 # DW_FORM_data1 + .byte 87 # DW_AT_call_column + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_rnglists.dwo,"e",@progbits + .long .Ldebug_list_header_end1-.Ldebug_list_header_start1 # Length +.Ldebug_list_header_start1: + .short 5 # Version + .byte 8 # Address size + .byte 0 # Segment selector size + .long 2 # Offset entry count +.Lrnglists_dwo_table_base0: + .long .Ldebug_ranges0-.Lrnglists_dwo_table_base0 + .long .Ldebug_ranges1-.Lrnglists_dwo_table_base0 +.Ldebug_ranges0: + .byte 4 # DW_RLE_offset_pair + .uleb128 .Lfunc_begin1-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end1-.Lfunc_begin0 # ending offset + .byte 0 # DW_RLE_end_of_list +.Ldebug_ranges1: + .byte 4 # DW_RLE_offset_pair + .uleb128 .Ltmp10-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp12-.Lfunc_begin0 # ending offset + .byte 4 # DW_RLE_offset_pair + .uleb128 .Ltmp14-.Lfunc_begin0 # starting offset + .uleb128 .Ltmp17-.Lfunc_begin0 # ending offset + .byte 0 # DW_RLE_end_of_list +.Ldebug_list_header_end1: + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad _ZZ3usePiS_E3Foo + .quad x + .quad y + .quad .Lfunc_begin0 +.Ldebug_addr_end0: + .section .debug_gnu_pubnames,"",@progbits + .long .LpubNames_end0-.LpubNames_start0 # Length of Public Names Info +.LpubNames_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 40 # Compilation Unit Length + .long 38 # DIE offset + .byte 160 # Attributes: VARIABLE, STATIC + .asciz "use::Foo" # External Name + .long 66 # DIE offset + .byte 32 # Attributes: VARIABLE, EXTERNAL + .asciz "x" # External Name + .long 77 # DIE offset + .byte 32 # Attributes: VARIABLE, EXTERNAL + .asciz "y" # External Name + .long 88 # DIE offset + .byte 48 # Attributes: FUNCTION, EXTERNAL + .asciz "use" # External Name + .long 115 # DIE offset + .byte 48 # Attributes: FUNCTION, EXTERNAL + .asciz "main" # External Name + .long 0 # End Mark +.LpubNames_end0: + .section .debug_gnu_pubtypes,"",@progbits + .long .LpubTypes_end0-.LpubTypes_start0 # Length of Public Types Info +.LpubTypes_start0: + .short 2 # DWARF Version + .long .Lcu_begin0 # Offset of Compilation Unit Info + .long 40 # Compilation Unit Length + .long 62 # DIE offset + .byte 144 # Attributes: TYPE, STATIC + .asciz "int" # External Name + .long 164 # DIE offset + .byte 144 # Attributes: TYPE, STATIC + .asciz "char" # External Name + .long 0 # End Mark +.LpubTypes_end0: + .ident "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 3a8db0f4bfb57348f49d9603119fa157114bbf8e)" + .section ".note.GNU-stack","",@progbits + .addrsig + .addrsig_sym _ZGVZ3usePiS_E3Foo + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/Inputs/dwarf5-loclist.s b/bolt/test/X86/Inputs/dwarf5-loclist.s new file mode 100644 index 0000000000000..972c62146d357 --- /dev/null +++ b/bolt/test/X86/Inputs/dwarf5-loclist.s @@ -0,0 +1,393 @@ +# helper.cpp -O1 -g2 -gdwarf-5 -S -o helper.s +# struct Foo1 { +# int x; +# int y; +# }; +# inline __attribute__((always_inline)) +# static int helper(Foo1 &f) { +# return f.x + 3; +# } +# int foo(int i) { +# Foo1 foo; +# foo.x = i; +# foo.y = 3; +# return helper(foo); +# } + + .text + .file "helper.cpp" + .globl _Z3fooi # -- Begin function _Z3fooi + .p2align 4, 0x90 + .type _Z3fooi,@function +_Z3fooi: # @_Z3fooi +.Lfunc_begin0: + .file 0 "/dwarf4CrossCULocList" "helper.cpp" md5 0xc9271b4999165863c559e42d691423d1 + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: foo:i <- $edi + #DEBUG_VALUE: foo:foo <- [DW_OP_LLVM_fragment 0 32] $edi + # kill: def $edi killed $edi def $rdi + #DEBUG_VALUE: foo:foo <- [DW_OP_LLVM_fragment 32 32] 3 + .loc 0 7 14 prologue_end # helper.cpp:7:14 + leal 3(%rdi), %eax +.Ltmp0: + .loc 0 13 3 # helper.cpp:13:3 + retq +.Ltmp1: +.Lfunc_end0: + .size _Z3fooi, .Lfunc_end0-_Z3fooi + .cfi_endproc + # -- End function + .section .debug_loclists,"",@progbits + .long .Ldebug_list_header_end0-.Ldebug_list_header_start0 # Length +.Ldebug_list_header_start0: + .short 5 # Version + .byte 8 # Address size + .byte 0 # Segment selector size + .long 1 # Offset entry count +.Lloclists_table_base0: + .long .Ldebug_loc0-.Lloclists_table_base0 +.Ldebug_loc0: + .byte 4 # DW_LLE_offset_pair + .uleb128 .Lfunc_begin0-.Lfunc_begin0 # starting offset + .uleb128 .Lfunc_end0-.Lfunc_begin0 # ending offset + .byte 7 # Loc expr size + .byte 85 # super-register DW_OP_reg5 + .byte 147 # DW_OP_piece + .byte 4 # 4 + .byte 51 # DW_OP_lit3 + .byte 159 # DW_OP_stack_value + .byte 147 # DW_OP_piece + .byte 4 # 4 + .byte 0 # DW_LLE_end_of_list +.Ldebug_list_header_end0: + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 114 # DW_AT_str_offsets_base + .byte 23 # DW_FORM_sec_offset + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 115 # DW_AT_addr_base + .byte 23 # DW_FORM_sec_offset + .ascii "\214\001" # DW_AT_loclists_base + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 110 # DW_AT_linkage_name + .byte 37 # DW_FORM_strx1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 32 # DW_AT_inline + .byte 33 # DW_FORM_implicit_const + .byte 1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 16 # DW_TAG_reference_type + .byte 0 # DW_CHILDREN_no + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .byte 122 # DW_AT_call_all_calls + .byte 25 # DW_FORM_flag_present + .byte 110 # DW_AT_linkage_name + .byte 37 # DW_FORM_strx1 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 10 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 34 # DW_FORM_loclistx + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 11 # Abbreviation Code + .byte 29 # DW_TAG_inlined_subroutine + .byte 0 # DW_CHILDREN_no + .byte 49 # DW_AT_abstract_origin + .byte 19 # DW_FORM_ref4 + .byte 17 # DW_AT_low_pc + .byte 27 # DW_FORM_addrx + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 88 # DW_AT_call_file + .byte 11 # DW_FORM_data1 + .byte 89 # DW_AT_call_line + .byte 11 # DW_FORM_data1 + .byte 87 # DW_AT_call_column + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 1 # Abbrev [1] 0xc:0x81 DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 33 # DW_AT_language + .byte 1 # DW_AT_name + .long .Lstr_offsets_base0 # DW_AT_str_offsets_base + .long .Lline_table_start0 # DW_AT_stmt_list + .byte 2 # DW_AT_comp_dir + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .long .Laddr_table_base0 # DW_AT_addr_base + .long .Lloclists_table_base0 # DW_AT_loclists_base + .byte 2 # Abbrev [2] 0x27:0x12 DW_TAG_subprogram + .byte 3 # DW_AT_linkage_name + .byte 4 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 57 # DW_AT_type + # DW_AT_inline + .byte 3 # Abbrev [3] 0x30:0x8 DW_TAG_formal_parameter + .byte 6 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 61 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 4 # Abbrev [4] 0x39:0x4 DW_TAG_base_type + .byte 5 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 5 # Abbrev [5] 0x3d:0x5 DW_TAG_reference_type + .long 66 # DW_AT_type + .byte 6 # Abbrev [6] 0x42:0x19 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .byte 9 # DW_AT_name + .byte 8 # DW_AT_byte_size + .byte 0 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 7 # Abbrev [7] 0x48:0x9 DW_TAG_member + .byte 7 # DW_AT_name + .long 57 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 7 # Abbrev [7] 0x51:0x9 DW_TAG_member + .byte 8 # DW_AT_name + .long 57 # DW_AT_type + .byte 0 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .byte 4 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 8 # Abbrev [8] 0x5b:0x31 DW_TAG_subprogram + .byte 0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_call_all_calls + .byte 10 # DW_AT_linkage_name + .byte 11 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .long 57 # DW_AT_type + # DW_AT_external + .byte 9 # Abbrev [9] 0x6b:0xa DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 85 + .byte 12 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 9 # DW_AT_decl_line + .long 57 # DW_AT_type + .byte 10 # Abbrev [10] 0x75:0x9 DW_TAG_variable + .byte 0 # DW_AT_location + .byte 11 # DW_AT_name + .byte 0 # DW_AT_decl_file + .byte 10 # DW_AT_decl_line + .long 66 # DW_AT_type + .byte 11 # Abbrev [11] 0x7e:0xd DW_TAG_inlined_subroutine + .long 39 # DW_AT_abstract_origin + .byte 0 # DW_AT_low_pc + .long .Ltmp0-.Lfunc_begin0 # DW_AT_high_pc + .byte 0 # DW_AT_call_file + .byte 13 # DW_AT_call_line + .byte 10 # DW_AT_call_column + .byte 0 # End Of Children Mark + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_str_offsets,"",@progbits + .long 56 # Length of String Offsets Set + .short 5 + .short 0 +.Lstr_offsets_base0: + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 37d6c1cc7d4dd3a8a47ba62254bc88521bd50d66)" # string offset=0 +.Linfo_string1: + .asciz "helper.cpp" # string offset=101 +.Linfo_string2: + .asciz "/dwarf4CrossCULocList" # string offset=112 +.Linfo_string3: + .asciz "_ZL6helperR4Foo1" # string offset=171 +.Linfo_string4: + .asciz "helper" # string offset=188 +.Linfo_string5: + .asciz "int" # string offset=195 +.Linfo_string6: + .asciz "f" # string offset=199 +.Linfo_string7: + .asciz "x" # string offset=201 +.Linfo_string8: + .asciz "y" # string offset=203 +.Linfo_string9: + .asciz "Foo1" # string offset=205 +.Linfo_string10: + .asciz "_Z3fooi" # string offset=210 +.Linfo_string11: + .asciz "foo" # string offset=218 +.Linfo_string12: + .asciz "i" # string offset=222 + .section .debug_str_offsets,"",@progbits + .long .Linfo_string0 + .long .Linfo_string1 + .long .Linfo_string2 + .long .Linfo_string3 + .long .Linfo_string4 + .long .Linfo_string5 + .long .Linfo_string6 + .long .Linfo_string7 + .long .Linfo_string8 + .long .Linfo_string9 + .long .Linfo_string10 + .long .Linfo_string11 + .long .Linfo_string12 + .section .debug_addr,"",@progbits + .long .Ldebug_addr_end0-.Ldebug_addr_start0 # Length of contribution +.Ldebug_addr_start0: + .short 5 # DWARF version number + .byte 8 # Address size + .byte 0 # Segment selector size +.Laddr_table_base0: + .quad .Lfunc_begin0 +.Ldebug_addr_end0: + .ident "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 37d6c1cc7d4dd3a8a47ba62254bc88521bd50d66)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/bug-function-layout-execount.s b/bolt/test/X86/bug-function-layout-execount.s new file mode 100644 index 0000000000000..540b6790d01e9 --- /dev/null +++ b/bolt/test/X86/bug-function-layout-execount.s @@ -0,0 +1,73 @@ +# Verifies that llvm-bolt correctly sorts functions by their execution counts. + +# REQUIRES: x86_64-linux, asserts + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o +# RUN: link_fdata %s %t.o %t.fdata +# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q +# RUN: llvm-bolt %t.exe --data %t.fdata --lite --reorder-functions=exec-count \ +# RUN: -v=2 --debug-only=hfsort -o /dev/null 2>&1 | FileCheck %s + +# CHECK: Starting pass: reorder-functions +# CHECK-NEXT: hot func func2 (1500) +# CHECK-NEXT: hot func func1 (500) +# CHECK-NEXT: hot func main (400) +# CHECK-NEXT: hot func func5 (110) +# CHECK-NEXT: hot func func3 (100) +# CHECK-NEXT: hot func func4 (99) + + .text + .globl main + .type main, %function +main: +# FDATA: 0 [unknown] 0 1 main 0 1 400 + .cfi_startproc + call func1 + retq + .size _start, .-_start + .cfi_endproc + + .globl func1 + .type func1,@function +func1: +# FDATA: 0 [unknown] 0 1 func1 0 1 500 + .cfi_startproc + retq + .size func1, .-func1 + .cfi_endproc + + .globl func2 + .type func2,@function +func2: +# FDATA: 0 [unknown] 0 1 func2 0 1 1500 + .cfi_startproc + retq + .size func2, .-func2 + .cfi_endproc + + .globl func3 + .type func3,@function +func3: +# FDATA: 0 [unknown] 0 1 func3 0 1 100 + .cfi_startproc + retq + .size func3, .-func3 + .cfi_endproc + + .globl func4 + .type func4,@function +func4: +# FDATA: 0 [unknown] 0 1 func4 0 1 99 + .cfi_startproc + retq + .size func4, .-func4 + .cfi_endproc + + .globl func5 + .type func5,@function +func5: +# FDATA: 0 [unknown] 0 1 func5 0 1 110 + .cfi_startproc + retq + .size func5, .-func5 + .cfi_endproc diff --git a/bolt/test/X86/dwarf4-cross-cu-loclist-dwarf4-loclist--dwarf5-loclist.test b/bolt/test/X86/dwarf4-cross-cu-loclist-dwarf4-loclist--dwarf5-loclist.test new file mode 100644 index 0000000000000..581ce2cffcfd4 --- /dev/null +++ b/bolt/test/X86/dwarf4-cross-cu-loclist-dwarf4-loclist--dwarf5-loclist.test @@ -0,0 +1,60 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf4-cross-cu-with-loclist.s -o %t.o +# RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-loclist.s -o %t1.o +# RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf4-two-entries-loclist.s -o %t2.o +# RUN: %clang %cflags %t1.o %t2.o %t.o -o %t.exe +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections +# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s +# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt | FileCheck --check-prefix=POSTCHECK %s + +# Tests that BOLT correctly handles location list with DWARF5/DWARF4 when order of CUs is not the same as in input. + +# PRECHECK: version = 0x0005 +# PRECHECK: version = 0x0004 +# PRECHECK: version = 0x0004 +# PRECHECK: version = 0x0004 + +# POSTCHECK: version = 0x0004 +# POSTCHECK: DW_TAG_formal_parameter +# POSTCHECK-NEXT: DW_AT_location +# POSTCHECK-NEXT: DW_AT_name +# POSTCHECK-NEXT: DW_AT_decl_file +# POSTCHECK-NEXT: DW_AT_decl_line +# POSTCHECK-NEXT: DW_AT_type [DW_FORM_ref_addr] +# POSTCHECK-SAME: "int") + +# POSTCHECK: DW_TAG_variable +# POSTCHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] +# POSTCHECK-NEXT: [0x[[#%.16x,ADDR1:]] +# POSTCHECK-SAME: 0x[[#ADDR1 + 0x8]]): +# POSTCHECK-SAME: DW_OP_reg5 RDI, DW_OP_piece 0x4, DW_OP_lit3, DW_OP_stack_value, DW_OP_piece 0x4) + +# POSTCHECK: version = 0x0004 +# POSTCHECK: DW_TAG_variable +# POSTCHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] +# POSTCHECK-NEXT: [0x[[#%.16x,ADDR2:]] +# POSTCHECK-SAME: 0x[[#ADDR2 + 0x4]]): +# POSTCHECK-SAME: DW_OP_reg5 RDI, DW_OP_piece 0x4, DW_OP_lit3, DW_OP_stack_value, DW_OP_piece 0x4) + +# POSTCHECK: version = 0x0005 +# POSTCHECK: DW_TAG_variable +# POSTCHECK-NEXT: DW_AT_location [DW_FORM_loclistx] (indexed (0x0) loclist +# POSTCHECK-NEXT: [0x[[#%.16x,ADDR3:]] +# POSTCHECK-SAME: 0x[[#ADDR3 + 0x4]]): +# POSTCHECK-SAME: DW_OP_reg5 RDI, DW_OP_piece 0x4, DW_OP_lit3, DW_OP_stack_value, DW_OP_piece 0x4) + +# POSTCHECK: version = 0x0004 +# POSTCHECK: DW_TAG_formal_parameter +# POSTCHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] +# POSTCHECK-NEXT: [0x[[#%.16x,ADDR4:]] +# POSTCHECK-SAME: 0x[[#ADDR4 + 0x8]]): DW_OP_reg5 RDI +# POSTCHECK-NEXT: [0x[[#%.16x,ADDR5:]] +# POSTCHECK-SAME: 0x[[#ADDR5 + 0x16]]): DW_OP_GNU_entry_value(DW_OP_reg5 RDI), DW_OP_stack_value) +# POSTCHECK: DW_TAG_formal_parameter +# POSTCHECK: DW_TAG_formal_parameter +# POSTCHECK-NEXT: DW_AT_location [DW_FORM_sec_offset] +# POSTCHECK-NEXT: [0x[[#%.16x,ADDR6:]] +# POSTCHECK-SAME: 0x[[#ADDR6 + 0x8]]): DW_OP_reg5 RDI +# POSTCHECK-NEXT: [0x[[#%.16x,ADDR7:]] +# POSTCHECK-SAME: 0x[[#ADDR7 + 0x16]]): DW_OP_GNU_entry_value(DW_OP_reg5 RDI), DW_OP_stack_value) diff --git a/bolt/test/X86/dwarf4-df-call-site-change-low-pc.test b/bolt/test/X86/dwarf4-df-call-site-change-low-pc.test new file mode 100644 index 0000000000000..e00958d106141 --- /dev/null +++ b/bolt/test/X86/dwarf4-df-call-site-change-low-pc.test @@ -0,0 +1,27 @@ +; RUN: rm -rf %t +; RUN: mkdir %t +; RUN: cd %t +; RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf4-df-call-site-change-low-pc-main.s \ +; RUN: -split-dwarf-file=main.dwo -o main.o +; RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf4-df-call-site-change-low-pc-helper.s \ +; RUN: -split-dwarf-file=helper.dwo -o helper.o +; RUN: %clang %cflags -gdwarf-4 -O2 -gsplit-dwarf=split main.o helper.o -o main.exe +; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.dwo &> %t/maindwo.txt +; RUN: cat %t/maindwo.txt | FileCheck -check-prefix=PRE-BOLT-DWO-MAIN %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.dwo.dwo &> %t/maindwodwo.txt +; RUN: cat %t/maindwodwo.txt | FileCheck -check-prefix=BOLT-DWO-MAIN %s + +; Tests that DW_AT_low_pc changes in DW_TAG_GNU_call_site. + +; PRE-BOLT-DWO-MAIN: version = 0x0004 +; PRE-BOLT-DWO-MAIN: DW_TAG_GNU_call_site +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_abstract_origin +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_GNU_tail_call +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_low_pc [DW_FORM_GNU_addr_index] (indexed (00000004) + +; BOLT-DWO-MAIN: version = 0x0004 +; BOLT-DWO-MAIN: DW_TAG_GNU_call_site +; BOLT-DWO-MAIN-NEXT: DW_AT_abstract_origin +; BOLT-DWO-MAIN-NEXT: DW_AT_GNU_tail_call +; BOLT-DWO-MAIN-NEXT: DW_AT_low_pc [DW_FORM_GNU_addr_index] (indexed (00000005) diff --git a/bolt/test/X86/dwarf4-df-change-in-dw-op-gnu-addr-index-main.test b/bolt/test/X86/dwarf4-df-change-in-dw-op-gnu-addr-index-main.test new file mode 100644 index 0000000000000..5173c890f66ab --- /dev/null +++ b/bolt/test/X86/dwarf4-df-change-in-dw-op-gnu-addr-index-main.test @@ -0,0 +1,23 @@ +; RUN: rm -rf %t +; RUN: mkdir %t +; RUN: cd %t +; RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf4-df-change-in-dw-op-gnu-addr-index-main.s \ +; RUN: -split-dwarf-file=main.dwo -o main.o +; RUN: %clang %cflags -gdwarf-5 -gsplit-dwarf=split main.o -o main.exe +; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections +; RUN: not llvm-dwarfdump --show-form --verbose --debug-info main.dwo &> %t/maindwo.txt +; RUN: cat %t/maindwo.txt | FileCheck -check-prefix=PRE-BOLT-DWO-MAIN %s +; RUN: not llvm-dwarfdump --show-form --verbose --debug-info main.dwo.dwo &> %t/maindwodwo.txt +; RUN: cat %t/maindwodwo.txt | FileCheck -check-prefix=BOLT-DWO-MAIN %s + +; Tests that new indices are assigned to DW_OP_GNU_addr_index. + +; PRE-BOLT-DWO-MAIN: version = 0x0004 +; PRE-BOLT-DWO-MAIN: DW_AT_location [DW_FORM_exprloc] (DW_OP_GNU_addr_index 0x0) +; PRE-BOLT-DWO-MAIN: DW_AT_location [DW_FORM_exprloc] (DW_OP_GNU_addr_index 0x1) +; PRE-BOLT-DWO-MAIN: DW_AT_location [DW_FORM_exprloc] (DW_OP_GNU_addr_index 0x2) + +; BOLT-DWO-MAIN: version = 0x0004 +; BOLT-DWO-MAIN: DW_AT_location [DW_FORM_exprloc] (DW_OP_GNU_addr_index 0x1) +; BOLT-DWO-MAIN: DW_AT_location [DW_FORM_exprloc] (DW_OP_GNU_addr_index 0x6) +; BOLT-DWO-MAIN: DW_AT_location [DW_FORM_exprloc] (DW_OP_GNU_addr_index 0x7) diff --git a/bolt/test/X86/dwarf4-invalid-reference-die-offset-no-internal-dwarf-error.s b/bolt/test/X86/dwarf4-invalid-reference-die-offset-no-internal-dwarf-error.s new file mode 100755 index 0000000000000..4cf0d3d0e2558 --- /dev/null +++ b/bolt/test/X86/dwarf4-invalid-reference-die-offset-no-internal-dwarf-error.s @@ -0,0 +1,408 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o +# RUN: %clang %cflags -dwarf-4 %t1.o -o %t.exe -Wl,-q +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections -v 1 &> %tlog.txt +# RUN: cat %tlog.txt | FileCheck --check-prefix=CHECKBOLT %s +# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=CHECK %s + +# Tests BOLT does not assert when DIE reference is invalid. + +# CHECKBOLT: Referenced DIE offsets not in .debug_info +# CHECKBOLT-NEXT: 91 +# CHECK: DW_TAG_variable +# CHECK-NEXT: DW_AT_name +# CHECK-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x0091 => {0x00000091}) + +# Assembly manually modified +# struct pair {int i; int j; }; +# static pair p; +# int load() { +# return p.i + p.j; +# } +# void store(int i, int j) { +# p.i = i; +# p.j = j; +# } +# int main() { +# return 0; +# } + + .text + .file "main.cpp" + .file 1 "/invalidWithin" "main.cpp" + .section .text._Z4loadv,"ax",@progbits + .globl _Z4loadv # -- Begin function _Z4loadv + .p2align 4, 0x90 + .type _Z4loadv,@function +_Z4loadv: # @_Z4loadv +.Lfunc_begin0: + .cfi_startproc +# %bb.0: # %entry + .loc 1 4 20 prologue_end # main.cpp:4:20 + movl _ZL1p.1(%rip), %eax + .loc 1 4 16 is_stmt 0 # main.cpp:4:16 + addl _ZL1p.0(%rip), %eax + .loc 1 4 5 # main.cpp:4:5 + retq +.Ltmp0: +.Lfunc_end0: + .size _Z4loadv, .Lfunc_end0-_Z4loadv + .cfi_endproc + # -- End function + .section .text._Z5storeii,"ax",@progbits + .globl _Z5storeii # -- Begin function _Z5storeii + .p2align 4, 0x90 + .type _Z5storeii,@function +_Z5storeii: # @_Z5storeii +.Lfunc_begin1: + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: store:i <- $edi + #DEBUG_VALUE: store:j <- $esi + .loc 1 7 9 prologue_end is_stmt 1 # main.cpp:7:9 + movl %edi, _ZL1p.0(%rip) + .loc 1 8 9 # main.cpp:8:9 + movl %esi, _ZL1p.1(%rip) + .loc 1 9 1 # main.cpp:9:1 + retq +.Ltmp1: +.Lfunc_end1: + .size _Z5storeii, .Lfunc_end1-_Z5storeii + .cfi_endproc + # -- End function + .section .text.main,"ax",@progbits + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin2: + .cfi_startproc +# %bb.0: # %entry + .loc 1 11 1 prologue_end # main.cpp:11:1 + xorl %eax, %eax + retq +.Ltmp2: +.Lfunc_end2: + .size main, .Lfunc_end2-main + .cfi_endproc + # -- End function + .type _ZL1p.0,@object # @_ZL1p.0 + .local _ZL1p.0 + .comm _ZL1p.0,4,4 + .type _ZL1p.1,@object # @_ZL1p.1 + .local _ZL1p.1 + .comm _ZL1p.1,4,4 + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 14 # DW_FORM_strp + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 85 # DW_AT_ranges + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 110 # DW_AT_linkage_name + .byte 14 # DW_FORM_strp + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 0 # DW_CHILDREN_no + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .ascii "\227B" # DW_AT_GNU_all_call_sites + .byte 25 # DW_FORM_flag_present + .byte 110 # DW_AT_linkage_name + .byte 14 # DW_FORM_strp + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .ascii "\227B" # DW_AT_GNU_all_call_sites + .byte 25 # DW_FORM_flag_present + .byte 110 # DW_AT_linkage_name + .byte 14 # DW_FORM_strp + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 0 # DW_CHILDREN_no + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .ascii "\227B" # DW_AT_GNU_all_call_sites + .byte 25 # DW_FORM_flag_present + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0xd9 DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 33 # DW_AT_language + .long .Linfo_string1 # DW_AT_name + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Linfo_string2 # DW_AT_comp_dir + .quad 0 # DW_AT_low_pc + .long .Ldebug_ranges0 # DW_AT_ranges + .byte 2 # Abbrev [2] 0x2a:0x26 DW_TAG_variable + .long .Linfo_string3 # DW_AT_name + .long 145 # DW_AT_type --> Modified manually s/80/145 + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 22 # DW_AT_location + .byte 3 + .quad _ZL1p.0 + .byte 147 + .byte 4 + .byte 3 + .quad _ZL1p.1 + .byte 147 + .byte 4 + .long .Linfo_string8 # DW_AT_linkage_name + .byte 3 # Abbrev [3] 0x50:0x22 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .long .Linfo_string7 # DW_AT_name + .byte 8 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 4 # Abbrev [4] 0x59:0xc DW_TAG_member + .long .Linfo_string4 # DW_AT_name + .long 114 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 4 # Abbrev [4] 0x65:0xc DW_TAG_member + .long .Linfo_string6 # DW_AT_name + .long 114 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 4 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x72:0x7 DW_TAG_base_type + .long .Linfo_string5 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 6 # Abbrev [6] 0x79:0x1d DW_TAG_subprogram + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_GNU_all_call_sites + .long .Linfo_string9 # DW_AT_linkage_name + .long .Linfo_string10 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .long 114 # DW_AT_type + # DW_AT_external + .byte 7 # Abbrev [7] 0x96:0x34 DW_TAG_subprogram + .quad .Lfunc_begin1 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_GNU_all_call_sites + .long .Linfo_string11 # DW_AT_linkage_name + .long .Linfo_string12 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + # DW_AT_external + .byte 8 # Abbrev [8] 0xaf:0xd DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 85 + .long .Linfo_string4 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 114 # DW_AT_type + .byte 8 # Abbrev [8] 0xbc:0xd DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 84 + .long .Linfo_string6 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 114 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 9 # Abbrev [9] 0xca:0x19 DW_TAG_subprogram + .quad .Lfunc_begin2 # DW_AT_low_pc + .long .Lfunc_end2-.Lfunc_begin2 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_GNU_all_call_sites + .long .Linfo_string13 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 10 # DW_AT_decl_line + .long 114 # DW_AT_type + # DW_AT_external + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_ranges,"",@progbits +.Ldebug_ranges0: + .quad .Lfunc_begin0 + .quad .Lfunc_end0 + .quad .Lfunc_begin1 + .quad .Lfunc_end1 + .quad .Lfunc_begin2 + .quad .Lfunc_end2 + .quad 0 + .quad 0 + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 37d6c1cc7d4dd3a8a47ba62254bc88521bd50d66)" # string offset=0 +.Linfo_string1: + .asciz "main.cpp" # string offset=101 +.Linfo_string2: + .asciz "/invalidWithin" # string offset=110 +.Linfo_string3: + .asciz "p" # string offset=162 +.Linfo_string4: + .asciz "i" # string offset=164 +.Linfo_string5: + .asciz "int" # string offset=166 +.Linfo_string6: + .asciz "j" # string offset=170 +.Linfo_string7: + .asciz "pair" # string offset=172 +.Linfo_string8: + .asciz "_ZL1p" # string offset=177 +.Linfo_string9: + .asciz "_Z4loadv" # string offset=183 +.Linfo_string10: + .asciz "load" # string offset=192 +.Linfo_string11: + .asciz "_Z5storeii" # string offset=197 +.Linfo_string12: + .asciz "store" # string offset=208 +.Linfo_string13: + .asciz "main" # string offset=214 + .ident "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 37d6c1cc7d4dd3a8a47ba62254bc88521bd50d66)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/dwarf4-invalid-reference-die-offset-with-internal-dwarf-error-cant-parse-die.s b/bolt/test/X86/dwarf4-invalid-reference-die-offset-with-internal-dwarf-error-cant-parse-die.s new file mode 100755 index 0000000000000..9d27c9cd9ff87 --- /dev/null +++ b/bolt/test/X86/dwarf4-invalid-reference-die-offset-with-internal-dwarf-error-cant-parse-die.s @@ -0,0 +1,408 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o +# RUN: %clang %cflags -dwarf-4 %t1.o -o %t.exe -Wl,-q +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections -v 1 &> %tlog.txt +# RUN: cat %tlog.txt | FileCheck --check-prefix=CHECKBOLT %s +# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=CHECK %s + +# Tests BOLT does not assert when DIE reference is invalid. + +# CHECKBOLT: BOLT-WARNING: [internal-dwarf-error]: could not parse referenced DIE at offset: +# CHECKBOLT-NOT: Referenced DIE offsets not in .debug_info +# CHECK: DW_TAG_variable +# CHECK-NEXT: DW_AT_name +# CHECK-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x008c => {0x0000008c}) + +# Assembly manually modified +# struct pair {int i; int j; }; +# static pair p; +# int load() { +# return p.i + p.j; +# } +# void store(int i, int j) { +# p.i = i; +# p.j = j; +# } +# int main() { +# return 0; +# } + + .text + .file "main.cpp" + .file 1 "/invalidWithin" "main.cpp" + .section .text._Z4loadv,"ax",@progbits + .globl _Z4loadv # -- Begin function _Z4loadv + .p2align 4, 0x90 + .type _Z4loadv,@function +_Z4loadv: # @_Z4loadv +.Lfunc_begin0: + .cfi_startproc +# %bb.0: # %entry + .loc 1 4 20 prologue_end # main.cpp:4:20 + movl _ZL1p.1(%rip), %eax + .loc 1 4 16 is_stmt 0 # main.cpp:4:16 + addl _ZL1p.0(%rip), %eax + .loc 1 4 5 # main.cpp:4:5 + retq +.Ltmp0: +.Lfunc_end0: + .size _Z4loadv, .Lfunc_end0-_Z4loadv + .cfi_endproc + # -- End function + .section .text._Z5storeii,"ax",@progbits + .globl _Z5storeii # -- Begin function _Z5storeii + .p2align 4, 0x90 + .type _Z5storeii,@function +_Z5storeii: # @_Z5storeii +.Lfunc_begin1: + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: store:i <- $edi + #DEBUG_VALUE: store:j <- $esi + .loc 1 7 9 prologue_end is_stmt 1 # main.cpp:7:9 + movl %edi, _ZL1p.0(%rip) + .loc 1 8 9 # main.cpp:8:9 + movl %esi, _ZL1p.1(%rip) + .loc 1 9 1 # main.cpp:9:1 + retq +.Ltmp1: +.Lfunc_end1: + .size _Z5storeii, .Lfunc_end1-_Z5storeii + .cfi_endproc + # -- End function + .section .text.main,"ax",@progbits + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin2: + .cfi_startproc +# %bb.0: # %entry + .loc 1 11 1 prologue_end # main.cpp:11:1 + xorl %eax, %eax + retq +.Ltmp2: +.Lfunc_end2: + .size main, .Lfunc_end2-main + .cfi_endproc + # -- End function + .type _ZL1p.0,@object # @_ZL1p.0 + .local _ZL1p.0 + .comm _ZL1p.0,4,4 + .type _ZL1p.1,@object # @_ZL1p.1 + .local _ZL1p.1 + .comm _ZL1p.1,4,4 + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 14 # DW_FORM_strp + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 85 # DW_AT_ranges + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 110 # DW_AT_linkage_name + .byte 14 # DW_FORM_strp + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 0 # DW_CHILDREN_no + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .ascii "\227B" # DW_AT_GNU_all_call_sites + .byte 25 # DW_FORM_flag_present + .byte 110 # DW_AT_linkage_name + .byte 14 # DW_FORM_strp + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .ascii "\227B" # DW_AT_GNU_all_call_sites + .byte 25 # DW_FORM_flag_present + .byte 110 # DW_AT_linkage_name + .byte 14 # DW_FORM_strp + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 0 # DW_CHILDREN_no + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .ascii "\227B" # DW_AT_GNU_all_call_sites + .byte 25 # DW_FORM_flag_present + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0xd9 DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 33 # DW_AT_language + .long .Linfo_string1 # DW_AT_name + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Linfo_string2 # DW_AT_comp_dir + .quad 0 # DW_AT_low_pc + .long .Ldebug_ranges0 # DW_AT_ranges + .byte 2 # Abbrev [2] 0x2a:0x26 DW_TAG_variable + .long .Linfo_string3 # DW_AT_name + .long 140 # DW_AT_type --> Modified manually s/80/140 + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 22 # DW_AT_location + .byte 3 + .quad _ZL1p.0 + .byte 147 + .byte 4 + .byte 3 + .quad _ZL1p.1 + .byte 147 + .byte 4 + .long .Linfo_string8 # DW_AT_linkage_name + .byte 3 # Abbrev [3] 0x50:0x22 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .long .Linfo_string7 # DW_AT_name + .byte 8 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 4 # Abbrev [4] 0x59:0xc DW_TAG_member + .long .Linfo_string4 # DW_AT_name + .long 114 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 4 # Abbrev [4] 0x65:0xc DW_TAG_member + .long .Linfo_string6 # DW_AT_name + .long 114 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 4 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x72:0x7 DW_TAG_base_type + .long .Linfo_string5 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 6 # Abbrev [6] 0x79:0x1d DW_TAG_subprogram + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_GNU_all_call_sites + .long .Linfo_string9 # DW_AT_linkage_name + .long .Linfo_string10 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .long 114 # DW_AT_type + # DW_AT_external + .byte 7 # Abbrev [7] 0x96:0x34 DW_TAG_subprogram + .quad .Lfunc_begin1 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_GNU_all_call_sites + .long .Linfo_string11 # DW_AT_linkage_name + .long .Linfo_string12 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + # DW_AT_external + .byte 8 # Abbrev [8] 0xaf:0xd DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 85 + .long .Linfo_string4 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 114 # DW_AT_type + .byte 8 # Abbrev [8] 0xbc:0xd DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 84 + .long .Linfo_string6 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 114 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 9 # Abbrev [9] 0xca:0x19 DW_TAG_subprogram + .quad .Lfunc_begin2 # DW_AT_low_pc + .long .Lfunc_end2-.Lfunc_begin2 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_GNU_all_call_sites + .long .Linfo_string13 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 10 # DW_AT_decl_line + .long 114 # DW_AT_type + # DW_AT_external + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_ranges,"",@progbits +.Ldebug_ranges0: + .quad .Lfunc_begin0 + .quad .Lfunc_end0 + .quad .Lfunc_begin1 + .quad .Lfunc_end1 + .quad .Lfunc_begin2 + .quad .Lfunc_end2 + .quad 0 + .quad 0 + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 37d6c1cc7d4dd3a8a47ba62254bc88521bd50d66)" # string offset=0 +.Linfo_string1: + .asciz "main.cpp" # string offset=101 +.Linfo_string2: + .asciz "/invalidWithin" # string offset=110 +.Linfo_string3: + .asciz "p" # string offset=162 +.Linfo_string4: + .asciz "i" # string offset=164 +.Linfo_string5: + .asciz "int" # string offset=166 +.Linfo_string6: + .asciz "j" # string offset=170 +.Linfo_string7: + .asciz "pair" # string offset=172 +.Linfo_string8: + .asciz "_ZL1p" # string offset=177 +.Linfo_string9: + .asciz "_Z4loadv" # string offset=183 +.Linfo_string10: + .asciz "load" # string offset=192 +.Linfo_string11: + .asciz "_Z5storeii" # string offset=197 +.Linfo_string12: + .asciz "store" # string offset=208 +.Linfo_string13: + .asciz "main" # string offset=214 + .ident "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 37d6c1cc7d4dd3a8a47ba62254bc88521bd50d66)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/dwarf4-invalid-reference-die-offset-with-internal-dwarf-error-invalid-die.s b/bolt/test/X86/dwarf4-invalid-reference-die-offset-with-internal-dwarf-error-invalid-die.s new file mode 100755 index 0000000000000..b9cbf513bb26f --- /dev/null +++ b/bolt/test/X86/dwarf4-invalid-reference-die-offset-with-internal-dwarf-error-invalid-die.s @@ -0,0 +1,408 @@ +# REQUIRES: system-linux + +# RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %s -o %t1.o +# RUN: %clang %cflags -dwarf-4 %t1.o -o %t.exe -Wl,-q +# RUN: llvm-bolt %t.exe -o %t.bolt --update-debug-sections -v 1 &> %tlog.txt +# RUN: cat %tlog.txt | FileCheck --check-prefix=CHECKBOLT %s +# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.exe | FileCheck --check-prefix=CHECK %s + +# Tests BOLT does not assert when DIE reference is invalid. + +# CHECKBOLT: BOLT-WARNING: [internal-dwarf-error]: invalid referenced DIE at offset: +# CHECKBOLT-NOT: Referenced DIE offsets not in .debug_info +# CHECK: DW_TAG_variable +# CHECK-NEXT: DW_AT_name +# CHECK-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x008f => {0x0000008f}) + +# Assembly manually modified +# struct pair {int i; int j; }; +# static pair p; +# int load() { +# return p.i + p.j; +# } +# void store(int i, int j) { +# p.i = i; +# p.j = j; +# } +# int main() { +# return 0; +# } + + .text + .file "main.cpp" + .file 1 "/invalidWithin" "main.cpp" + .section .text._Z4loadv,"ax",@progbits + .globl _Z4loadv # -- Begin function _Z4loadv + .p2align 4, 0x90 + .type _Z4loadv,@function +_Z4loadv: # @_Z4loadv +.Lfunc_begin0: + .cfi_startproc +# %bb.0: # %entry + .loc 1 4 20 prologue_end # main.cpp:4:20 + movl _ZL1p.1(%rip), %eax + .loc 1 4 16 is_stmt 0 # main.cpp:4:16 + addl _ZL1p.0(%rip), %eax + .loc 1 4 5 # main.cpp:4:5 + retq +.Ltmp0: +.Lfunc_end0: + .size _Z4loadv, .Lfunc_end0-_Z4loadv + .cfi_endproc + # -- End function + .section .text._Z5storeii,"ax",@progbits + .globl _Z5storeii # -- Begin function _Z5storeii + .p2align 4, 0x90 + .type _Z5storeii,@function +_Z5storeii: # @_Z5storeii +.Lfunc_begin1: + .cfi_startproc +# %bb.0: # %entry + #DEBUG_VALUE: store:i <- $edi + #DEBUG_VALUE: store:j <- $esi + .loc 1 7 9 prologue_end is_stmt 1 # main.cpp:7:9 + movl %edi, _ZL1p.0(%rip) + .loc 1 8 9 # main.cpp:8:9 + movl %esi, _ZL1p.1(%rip) + .loc 1 9 1 # main.cpp:9:1 + retq +.Ltmp1: +.Lfunc_end1: + .size _Z5storeii, .Lfunc_end1-_Z5storeii + .cfi_endproc + # -- End function + .section .text.main,"ax",@progbits + .globl main # -- Begin function main + .p2align 4, 0x90 + .type main,@function +main: # @main +.Lfunc_begin2: + .cfi_startproc +# %bb.0: # %entry + .loc 1 11 1 prologue_end # main.cpp:11:1 + xorl %eax, %eax + retq +.Ltmp2: +.Lfunc_end2: + .size main, .Lfunc_end2-main + .cfi_endproc + # -- End function + .type _ZL1p.0,@object # @_ZL1p.0 + .local _ZL1p.0 + .comm _ZL1p.0,4,4 + .type _ZL1p.1,@object # @_ZL1p.1 + .local _ZL1p.1 + .comm _ZL1p.1,4,4 + .section .debug_abbrev,"",@progbits + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 14 # DW_FORM_strp + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 14 # DW_FORM_strp + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 85 # DW_AT_ranges + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 52 # DW_TAG_variable + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 110 # DW_AT_linkage_name + .byte 14 # DW_FORM_strp + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 3 # Abbreviation Code + .byte 19 # DW_TAG_structure_type + .byte 1 # DW_CHILDREN_yes + .byte 54 # DW_AT_calling_convention + .byte 11 # DW_FORM_data1 + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 4 # Abbreviation Code + .byte 13 # DW_TAG_member + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 56 # DW_AT_data_member_location + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 5 # Abbreviation Code + .byte 36 # DW_TAG_base_type + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 62 # DW_AT_encoding + .byte 11 # DW_FORM_data1 + .byte 11 # DW_AT_byte_size + .byte 11 # DW_FORM_data1 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 6 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 0 # DW_CHILDREN_no + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .ascii "\227B" # DW_AT_GNU_all_call_sites + .byte 25 # DW_FORM_flag_present + .byte 110 # DW_AT_linkage_name + .byte 14 # DW_FORM_strp + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 7 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 1 # DW_CHILDREN_yes + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .ascii "\227B" # DW_AT_GNU_all_call_sites + .byte 25 # DW_FORM_flag_present + .byte 110 # DW_AT_linkage_name + .byte 14 # DW_FORM_strp + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 8 # Abbreviation Code + .byte 5 # DW_TAG_formal_parameter + .byte 0 # DW_CHILDREN_no + .byte 2 # DW_AT_location + .byte 24 # DW_FORM_exprloc + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 9 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 0 # DW_CHILDREN_no + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 18 # DW_AT_high_pc + .byte 6 # DW_FORM_data4 + .byte 64 # DW_AT_frame_base + .byte 24 # DW_FORM_exprloc + .ascii "\227B" # DW_AT_GNU_all_call_sites + .byte 25 # DW_FORM_flag_present + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 58 # DW_AT_decl_file + .byte 11 # DW_FORM_data1 + .byte 59 # DW_AT_decl_line + .byte 11 # DW_FORM_data1 + .byte 73 # DW_AT_type + .byte 19 # DW_FORM_ref4 + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"",@progbits +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .long .debug_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0xd9 DW_TAG_compile_unit + .long .Linfo_string0 # DW_AT_producer + .short 33 # DW_AT_language + .long .Linfo_string1 # DW_AT_name + .long .Lline_table_start0 # DW_AT_stmt_list + .long .Linfo_string2 # DW_AT_comp_dir + .quad 0 # DW_AT_low_pc + .long .Ldebug_ranges0 # DW_AT_ranges + .byte 2 # Abbrev [2] 0x2a:0x26 DW_TAG_variable + .long .Linfo_string3 # DW_AT_name + .long 143 # DW_AT_type --> Modified manually s/80/143 + .byte 1 # DW_AT_decl_file + .byte 2 # DW_AT_decl_line + .byte 22 # DW_AT_location + .byte 3 + .quad _ZL1p.0 + .byte 147 + .byte 4 + .byte 3 + .quad _ZL1p.1 + .byte 147 + .byte 4 + .long .Linfo_string8 # DW_AT_linkage_name + .byte 3 # Abbrev [3] 0x50:0x22 DW_TAG_structure_type + .byte 5 # DW_AT_calling_convention + .long .Linfo_string7 # DW_AT_name + .byte 8 # DW_AT_byte_size + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 4 # Abbrev [4] 0x59:0xc DW_TAG_member + .long .Linfo_string4 # DW_AT_name + .long 114 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 0 # DW_AT_data_member_location + .byte 4 # Abbrev [4] 0x65:0xc DW_TAG_member + .long .Linfo_string6 # DW_AT_name + .long 114 # DW_AT_type + .byte 1 # DW_AT_decl_file + .byte 1 # DW_AT_decl_line + .byte 4 # DW_AT_data_member_location + .byte 0 # End Of Children Mark + .byte 5 # Abbrev [5] 0x72:0x7 DW_TAG_base_type + .long .Linfo_string5 # DW_AT_name + .byte 5 # DW_AT_encoding + .byte 4 # DW_AT_byte_size + .byte 6 # Abbrev [6] 0x79:0x1d DW_TAG_subprogram + .quad .Lfunc_begin0 # DW_AT_low_pc + .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_GNU_all_call_sites + .long .Linfo_string9 # DW_AT_linkage_name + .long .Linfo_string10 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 3 # DW_AT_decl_line + .long 114 # DW_AT_type + # DW_AT_external + .byte 7 # Abbrev [7] 0x96:0x34 DW_TAG_subprogram + .quad .Lfunc_begin1 # DW_AT_low_pc + .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_GNU_all_call_sites + .long .Linfo_string11 # DW_AT_linkage_name + .long .Linfo_string12 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + # DW_AT_external + .byte 8 # Abbrev [8] 0xaf:0xd DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 85 + .long .Linfo_string4 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 114 # DW_AT_type + .byte 8 # Abbrev [8] 0xbc:0xd DW_TAG_formal_parameter + .byte 1 # DW_AT_location + .byte 84 + .long .Linfo_string6 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 6 # DW_AT_decl_line + .long 114 # DW_AT_type + .byte 0 # End Of Children Mark + .byte 9 # Abbrev [9] 0xca:0x19 DW_TAG_subprogram + .quad .Lfunc_begin2 # DW_AT_low_pc + .long .Lfunc_end2-.Lfunc_begin2 # DW_AT_high_pc + .byte 1 # DW_AT_frame_base + .byte 87 + # DW_AT_GNU_all_call_sites + .long .Linfo_string13 # DW_AT_name + .byte 1 # DW_AT_decl_file + .byte 10 # DW_AT_decl_line + .long 114 # DW_AT_type + # DW_AT_external + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_ranges,"",@progbits +.Ldebug_ranges0: + .quad .Lfunc_begin0 + .quad .Lfunc_end0 + .quad .Lfunc_begin1 + .quad .Lfunc_end1 + .quad .Lfunc_begin2 + .quad .Lfunc_end2 + .quad 0 + .quad 0 + .section .debug_str,"MS",@progbits,1 +.Linfo_string0: + .asciz "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 37d6c1cc7d4dd3a8a47ba62254bc88521bd50d66)" # string offset=0 +.Linfo_string1: + .asciz "main.cpp" # string offset=101 +.Linfo_string2: + .asciz "/invalidWithin" # string offset=110 +.Linfo_string3: + .asciz "p" # string offset=162 +.Linfo_string4: + .asciz "i" # string offset=164 +.Linfo_string5: + .asciz "int" # string offset=166 +.Linfo_string6: + .asciz "j" # string offset=170 +.Linfo_string7: + .asciz "pair" # string offset=172 +.Linfo_string8: + .asciz "_ZL1p" # string offset=177 +.Linfo_string9: + .asciz "_Z4loadv" # string offset=183 +.Linfo_string10: + .asciz "load" # string offset=192 +.Linfo_string11: + .asciz "_Z5storeii" # string offset=197 +.Linfo_string12: + .asciz "store" # string offset=208 +.Linfo_string13: + .asciz "main" # string offset=214 + .ident "clang version 18.0.0 (git@github.com:llvm/llvm-project.git 37d6c1cc7d4dd3a8a47ba62254bc88521bd50d66)" + .section ".note.GNU-stack","",@progbits + .addrsig + .section .debug_line,"",@progbits +.Lline_table_start0: diff --git a/bolt/test/X86/dwarf5-df-call-site-change-low-pc.test b/bolt/test/X86/dwarf5-df-call-site-change-low-pc.test new file mode 100644 index 0000000000000..ea717a5e0888d --- /dev/null +++ b/bolt/test/X86/dwarf5-df-call-site-change-low-pc.test @@ -0,0 +1,27 @@ +; RUN: rm -rf %t +; RUN: mkdir %t +; RUN: cd %t +; RUN: llvm-mc -dwarf-version=4 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-df-call-site-change-low-pc-main.s \ +; RUN: -split-dwarf-file=main.dwo -o main.o +; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-df-call-site-change-low-pc-helper.s \ +; RUN: -split-dwarf-file=helper.dwo -o helper.o +; RUN: %clang %cflags -gdwarf-5 -O2 -gsplit-dwarf=split main.o helper.o -o main.exe +; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.dwo &> %t/maindwo.txt +; RUN: cat %t/maindwo.txt | FileCheck -check-prefix=PRE-BOLT-DWO-MAIN %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.dwo.dwo &> %t/maindwodwo.txt +; RUN: cat %t/maindwodwo.txt | FileCheck -check-prefix=BOLT-DWO-MAIN %s + +; Tests that DW_AT_low_pc changes in DW_TAG_call_site. + +; PRE-BOLT-DWO-MAIN: version = 0x0005 +; PRE-BOLT-DWO-MAIN: DW_TAG_call_site +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_call_origin +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_call_tail_call +; PRE-BOLT-DWO-MAIN-NEXT: DW_AT_call_pc [DW_FORM_addrx] (indexed (00000003) + +; BOLT-DWO-MAIN: version = 0x0005 +; BOLT-DWO-MAIN: DW_TAG_call_site +; BOLT-DWO-MAIN-NEXT: DW_AT_call_origin +; BOLT-DWO-MAIN-NEXT: DW_AT_call_tail_call +; BOLT-DWO-MAIN-NEXT: DW_AT_call_pc [DW_FORM_addrx] (indexed (00000004) diff --git a/bolt/test/X86/dwarf5-df-change-in-dw-op-gnu-addr-index-main.test b/bolt/test/X86/dwarf5-df-change-in-dw-op-gnu-addr-index-main.test new file mode 100644 index 0000000000000..f266caec7af3b --- /dev/null +++ b/bolt/test/X86/dwarf5-df-change-in-dw-op-gnu-addr-index-main.test @@ -0,0 +1,23 @@ +; RUN: rm -rf %t +; RUN: mkdir %t +; RUN: cd %t +; RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-df-change-in-dw-op-gnu-addr-index-main.s \ +; RUN: -split-dwarf-file=main.dwo -o main.o +; RUN: %clang %cflags -gdwarf-5 -gsplit-dwarf=split main.o -o main.exe +; RUN: llvm-bolt main.exe -o main.exe.bolt --update-debug-sections +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.dwo &> %t/maindwo.txt +; RUN: cat %t/maindwo.txt | FileCheck -check-prefix=PRE-BOLT-DWO-MAIN %s +; RUN: llvm-dwarfdump --show-form --verbose --debug-info main.dwo.dwo &> %t/maindwodwo.txt +; RUN: cat %t/maindwodwo.txt | FileCheck -check-prefix=BOLT-DWO-MAIN %s + +; Tests that new indices are assigned to DW_OP_GNU_addr_index. + +; PRE-BOLT-DWO-MAIN: version = 0x0005 +; PRE-BOLT-DWO-MAIN: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x0) +; PRE-BOLT-DWO-MAIN: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x1) +; PRE-BOLT-DWO-MAIN: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x2) + +; BOLT-DWO-MAIN: version = 0x0005 +; BOLT-DWO-MAIN: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x1) +; BOLT-DWO-MAIN: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x2) +; BOLT-DWO-MAIN: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x3) diff --git a/bolt/test/runtime/X86/reg-reassign-swap-cold.s b/bolt/test/runtime/X86/reg-reassign-swap-cold.s new file mode 100644 index 0000000000000..115b5b0eeff8b --- /dev/null +++ b/bolt/test/runtime/X86/reg-reassign-swap-cold.s @@ -0,0 +1,64 @@ +# This test case reproduces a bug where, during register swapping, +# the code fragments associated with the function need to be swapped +# together (which may be generated during PGO optimization). If not +# handled properly, optimized binary execution can result in a segmentation fault. + +# REQUIRES: system-linux + +# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o +# RUN: link_fdata %s %t.o %t.fdata +# RUN: llvm-strip --strip-unneeded %t.o +# RUN: %clang -no-pie %t.o -o %t.exe -Wl,-q +# RUN: llvm-bolt %t.exe -o %t.out -data=%t.fdata --reg-reassign | FileCheck %s +# RUN: %t.out + +# CHECK: BOLT-INFO: Reg Reassignment Pass Stats +# CHECK-NEXT: 2 functions affected. + .text + .globl main + .globl main.cold + .p2align 4, 0x90 + .type main,@function + .type main.cold,@function +main.cold: +bb1: + cmp $0x3, %r12 + jne bb8 +bb2: + jmp bb4 +main: # @main + .cfi_startproc +# %bb.0: # %entry + pushq %rax + pushq %r12 + pushq %rbx + .cfi_def_cfa_offset 16 + mov $0x1, %r12 + mov $0x2, %rbx + add $0x1, %r12 + shr $0x14, %r12 + mov $0x3, %r12 +bb3: + jmp bb1 +bb4: + cmp $0x3, %r12 +bb5: + jne bb8 +bb6: + xorl %eax, %eax +bb7: + popq %rcx + popq %rbx + popq %r12 + .cfi_def_cfa_offset 8 + retq +bb8: + mov $0x1, %rax + jmp bb7 +# FDATA: 1 main.cold #bb2# 1 main #bb4# 0 100 +# FDATA: 1 main #bb5# 1 main #bb6# 0 100 +# FDATA: 1 main #bb3# 1 main.cold 0 0 100 + +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc diff --git a/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp b/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp index 45fc15619ecab..1bb5cf756b95b 100644 --- a/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp +++ b/clang-tools-extra/clang-include-fixer/IncludeFixer.cpp @@ -314,11 +314,11 @@ std::string IncludeFixerSemaSource::minimizeInclude( if (!Entry) return std::string(Include); - bool IsSystem = false; + bool IsAngled = false; std::string Suggestion = - HeaderSearch.suggestPathToFileForDiagnostics(*Entry, "", &IsSystem); + HeaderSearch.suggestPathToFileForDiagnostics(*Entry, "", &IsAngled); - return IsSystem ? '<' + Suggestion + '>' : '"' + Suggestion + '"'; + return IsAngled ? '<' + Suggestion + '>' : '"' + Suggestion + '"'; } /// Get the include fixer context for the queried symbol. diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp index 019d9b1f18a5a..41a210a83a84f 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp @@ -437,8 +437,11 @@ void ClangTidyDiagnosticConsumer::HandleDiagnostic( SmallString<100> Message; Info.FormatDiagnostic(Message); FullSourceLoc Loc; - if (Info.getLocation().isValid() && Info.hasSourceManager()) + if (Info.hasSourceManager()) Loc = FullSourceLoc(Info.getLocation(), Info.getSourceManager()); + else if (Context.DiagEngine->hasSourceManager()) + Loc = FullSourceLoc(Info.getLocation(), + Context.DiagEngine->getSourceManager()); Converter.emitDiagnostic(Loc, DiagLevel, Message, Info.getRanges(), Info.getFixItHints()); } diff --git a/clang-tools-extra/clang-tidy/add_new_check.py b/clang-tools-extra/clang-tidy/add_new_check.py index c642000eba228..520212883d997 100755 --- a/clang-tools-extra/clang-tidy/add_new_check.py +++ b/clang-tools-extra/clang-tidy/add_new_check.py @@ -483,7 +483,7 @@ def process_doc(doc_file): def format_link(doc_file): check_name, match = process_doc(doc_file) - if not match and check_name: + if not match and check_name and not check_name.startswith("clang-analyzer-"): return " `%(check_name)s <%(module)s/%(check)s.html>`_,%(autofix)s\n" % { "check_name": check_name, "module": doc_file[0], @@ -495,13 +495,13 @@ def format_link(doc_file): def format_link_alias(doc_file): check_name, match = process_doc(doc_file) - if match and check_name: + if (match or (check_name.startswith("clang-analyzer-"))) and check_name: module = doc_file[0] check_file = doc_file[1].replace(".rst", "") - if match.group(1) == "https://clang.llvm.org/docs/analyzer/checkers": + if not match or match.group(1) == "https://clang.llvm.org/docs/analyzer/checkers": title = "Clang Static Analyzer " + check_file # Preserve the anchor in checkers.html from group 2. - target = match.group(1) + ".html" + match.group(2) + target = "" if not match else match.group(1) + ".html" + match.group(2) autofix = "" else: redirect_parts = re.search("^\.\./([^/]*)/([^/]*)$", match.group(1)) @@ -509,18 +509,30 @@ def format_link_alias(doc_file): target = redirect_parts[1] + "/" + redirect_parts[2] + ".html" autofix = has_auto_fix(title) - # The checker is just a redirect. - return ( - " `%(check_name)s <%(module)s/%(check_file)s.html>`_, `%(title)s <%(target)s>`_,%(autofix)s\n" - % { - "check_name": check_name, - "module": module, - "check_file": check_file, - "target": target, - "title": title, - "autofix": autofix, - } - ) + if target: + # The checker is just a redirect. + return ( + " `%(check_name)s <%(module)s/%(check_file)s.html>`_, `%(title)s <%(target)s>`_,%(autofix)s\n" + % { + "check_name": check_name, + "module": module, + "check_file": check_file, + "target": target, + "title": title, + "autofix": autofix, + }) + else: + # The checker is just a alias without redirect. + return ( + " `%(check_name)s <%(module)s/%(check_file)s.html>`_, %(title)s,%(autofix)s\n" + % { + "check_name": check_name, + "module": module, + "check_file": check_file, + "target": target, + "title": title, + "autofix": autofix, + }) return "" checks = map(format_link, doc_files) diff --git a/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp index 2f155820a83e5..a01b7f5a4ee6e 100644 --- a/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp @@ -19,6 +19,8 @@ namespace clang::tidy::bugprone { namespace { +static constexpr bool DefaultIgnoreMacros = false; + // Keep track of macro expansions that contain both __FILE__ and __LINE__. If // such a macro also uses __func__ or __FUNCTION__, we don't want to issue a // warning because __FILE__ and __LINE__ may be useful even if __func__ or @@ -56,6 +58,16 @@ class MacroExpansionsWithFileAndLine : public PPCallbacks { } // namespace +LambdaFunctionNameCheck::LambdaFunctionNameCheck(StringRef Name, + ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + IgnoreMacros( + Options.getLocalOrGlobal("IgnoreMacros", DefaultIgnoreMacros)) {} + +void LambdaFunctionNameCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "IgnoreMacros", IgnoreMacros); +} + void LambdaFunctionNameCheck::registerMatchers(MatchFinder *Finder) { // Match on PredefinedExprs inside a lambda. Finder->addMatcher(predefinedExpr(hasAncestor(lambdaExpr())).bind("E"), @@ -76,6 +88,9 @@ void LambdaFunctionNameCheck::check(const MatchFinder::MatchResult &Result) { return; } if (E->getLocation().isMacroID()) { + if (IgnoreMacros) + return; + auto ER = Result.SourceManager->getImmediateExpansionRange(E->getLocation()); if (SuppressMacroExpansions.find(ER.getAsRange()) != @@ -84,6 +99,7 @@ void LambdaFunctionNameCheck::check(const MatchFinder::MatchResult &Result) { return; } } + diag(E->getLocation(), "inside a lambda, '%0' expands to the name of the function call " "operator; consider capturing the name of the enclosing function " diff --git a/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.h b/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.h index 03f1c4544aee1..dab64f74aa6ca 100644 --- a/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.h @@ -31,8 +31,9 @@ class LambdaFunctionNameCheck : public ClangTidyCheck { }; using SourceRangeSet = std::set; - LambdaFunctionNameCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} + LambdaFunctionNameCheck(StringRef Name, ClangTidyContext *Context); + + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; void registerMatchers(ast_matchers::MatchFinder *Finder) override; void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) override; @@ -40,6 +41,7 @@ class LambdaFunctionNameCheck : public ClangTidyCheck { private: SourceRangeSet SuppressMacroExpansions; + bool IgnoreMacros; }; } // namespace clang::tidy::bugprone diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt index c2cde34fb1336..eb35bbc6a538f 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt @@ -18,6 +18,7 @@ add_clang_library(clangTidyCppCoreGuidelinesModule MissingStdForwardCheck.cpp NarrowingConversionsCheck.cpp NoMallocCheck.cpp + NoSuspendWithLockCheck.cpp OwningMemoryCheck.cpp PreferMemberInitializerCheck.cpp ProBoundsArrayToPointerDecayCheck.cpp @@ -50,6 +51,7 @@ add_clang_library(clangTidyCppCoreGuidelinesModule clang_target_link_libraries(clangTidyCppCoreGuidelinesModule PRIVATE + clangAnalysis clangAST clangASTMatchers clangBasic diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp index fdbf0e11f3f5f..e9f0201615616 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp @@ -32,6 +32,7 @@ #include "MissingStdForwardCheck.h" #include "NarrowingConversionsCheck.h" #include "NoMallocCheck.h" +#include "NoSuspendWithLockCheck.h" #include "OwningMemoryCheck.h" #include "PreferMemberInitializerCheck.h" #include "ProBoundsArrayToPointerDecayCheck.h" @@ -89,6 +90,8 @@ class CppCoreGuidelinesModule : public ClangTidyModule { CheckFactories.registerCheck( "cppcoreguidelines-narrowing-conversions"); CheckFactories.registerCheck("cppcoreguidelines-no-malloc"); + CheckFactories.registerCheck( + "cppcoreguidelines-no-suspend-with-lock"); CheckFactories.registerCheck( "cppcoreguidelines-noexcept-destructor"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.cpp new file mode 100644 index 0000000000000..ca293178c78b4 --- /dev/null +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.cpp @@ -0,0 +1,73 @@ +//===--- NoSuspendWithLockCheck.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 "NoSuspendWithLockCheck.h" +#include "../utils/ExprSequence.h" +#include "../utils/Matchers.h" +#include "../utils/OptionsUtils.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Analysis/CFG.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::cppcoreguidelines { + +void NoSuspendWithLockCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "LockGuards", LockGuards); +} + +void NoSuspendWithLockCheck::registerMatchers(MatchFinder *Finder) { + auto LockType = elaboratedType(namesType(templateSpecializationType( + hasDeclaration(namedDecl(matchers::matchesAnyListedName( + utils::options::parseStringList(LockGuards))))))); + + StatementMatcher Lock = + declStmt(has(varDecl(hasType(LockType)).bind("lock-decl"))) + .bind("lock-decl-stmt"); + Finder->addMatcher( + expr(anyOf(coawaitExpr(), coyieldExpr(), dependentCoawaitExpr()), + forCallable(functionDecl().bind("function")), + unless(isInTemplateInstantiation()), + hasAncestor( + compoundStmt(has(Lock), forCallable(equalsBoundNode("function"))) + .bind("block"))) + .bind("suspend"), + this); +} + +void NoSuspendWithLockCheck::check(const MatchFinder::MatchResult &Result) { + const auto *Block = Result.Nodes.getNodeAs("block"); + const auto *Suspend = Result.Nodes.getNodeAs("suspend"); + const auto *LockDecl = Result.Nodes.getNodeAs("lock-decl"); + const auto *LockStmt = Result.Nodes.getNodeAs("lock-decl-stmt"); + + if (!Block || !Suspend || !LockDecl || !LockStmt) + return; + + ASTContext &Context = *Result.Context; + CFG::BuildOptions Options; + Options.AddImplicitDtors = true; + Options.AddTemporaryDtors = true; + + std::unique_ptr TheCFG = CFG::buildCFG( + nullptr, const_cast(Block), &Context, Options); + if (!TheCFG) + return; + + utils::ExprSequence Sequence(TheCFG.get(), Block, &Context); + const Stmt *LastBlockStmt = Block->body_back(); + if (Sequence.inSequence(LockStmt, Suspend) && + (Suspend == LastBlockStmt || + Sequence.inSequence(Suspend, LastBlockStmt))) { + diag(Suspend->getBeginLoc(), "coroutine suspended with lock %0 held") + << LockDecl; + } +} + +} // namespace clang::tidy::cppcoreguidelines diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.h new file mode 100644 index 0000000000000..c7b7f476003fb --- /dev/null +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/NoSuspendWithLockCheck.h @@ -0,0 +1,44 @@ +//===--- NoSuspendWithLockCheck.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_CPPCOREGUIDELINES_NOSUSPENDWITHLOCKCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_NOSUSPENDWITHLOCKCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::cppcoreguidelines { + +/// Flag coroutines that suspend while any lock guard is alive. +/// This check implements CppCoreGuideline CP.52. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines/no-suspend-with-lock.html +class NoSuspendWithLockCheck : public ClangTidyCheck { +public: + NoSuspendWithLockCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + LockGuards(Options.get("LockGuards", + "::std::unique_lock;::std::scoped_lock;::" + "std::shared_lock;::std::lock_guard")) {} + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + return LangOpts.CPlusPlus20; + } + +private: + /// Semicolon-separated list of fully qualified names of lock guard template + /// types. Defaults to + /// `::std::unique_lock;::std::scoped_lock;::std::shared_lock;::std::lock_guard`. + const StringRef LockGuards; +}; + +} // namespace clang::tidy::cppcoreguidelines + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_NOSUSPENDWITHLOCKCHECK_H diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp index c210cb67e4f6b..6f67ab955baa3 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsArrayToPointerDecayCheck.cpp @@ -10,6 +10,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ParentMapContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" using namespace clang::ast_matchers; @@ -56,6 +57,7 @@ void ProBoundsArrayToPointerDecayCheck::registerMatchers(MatchFinder *Finder) { TK_AsIs, implicitCastExpr( unless(hasParent(arraySubscriptExpr())), + unless(hasSourceExpression(predefinedExpr())), unless(hasParentIgnoringImpCasts(explicitCastExpr())), unless(isInsideOfRangeBeginEndStmt()), unless(hasSourceExpression(ignoringParens(stringLiteral()))), diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp index 07b88d5c49e80..ff5a750a8dac4 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp @@ -281,8 +281,14 @@ ProTypeMemberInitCheck::ProTypeMemberInitCheck(StringRef Name, void ProTypeMemberInitCheck::registerMatchers(MatchFinder *Finder) { auto IsUserProvidedNonDelegatingConstructor = - allOf(isUserProvided(), - unless(anyOf(isInstantiated(), isDelegatingConstructor()))); + allOf(isUserProvided(), unless(isInstantiated()), + unless(isDelegatingConstructor()), + ofClass(cxxRecordDecl().bind("parent")), + unless(hasAnyConstructorInitializer(cxxCtorInitializer( + isWritten(), unless(isMemberInitializer()), + hasTypeLoc(loc( + qualType(hasDeclaration(equalsBoundNode("parent"))))))))); + auto IsNonTrivialDefaultConstructor = allOf( isDefaultConstructor(), unless(isUserProvided()), hasParent(cxxRecordDecl(unless(isTriviallyDefaultConstructible())))); diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.cpp index ac1f40cfe18ae..3923df312791d 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeVarargCheck.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "ProTypeVarargCheck.h" +#include "../utils/Matchers.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" @@ -133,7 +134,9 @@ void ProTypeVarargCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( callExpr(callee(functionDecl(isVariadic(), - unless(hasAnyName(AllowedVariadics))))) + unless(hasAnyName(AllowedVariadics)))), + unless(hasAncestor(expr(matchers::hasUnevaluatedContext()))), + unless(hasAncestor(typeLoc()))) .bind("callvararg"), this); diff --git a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp index f47609b19badf..2658c4b38702c 100644 --- a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp @@ -87,7 +87,7 @@ void IncludeCleanerCheck::registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) { PP->addPPCallbacks(RecordedPreprocessor.record(*PP)); - HS = &PP->getHeaderSearchInfo(); + this->PP = PP; RecordedPI.record(*PP); } @@ -121,7 +121,7 @@ void IncludeCleanerCheck::check(const MatchFinder::MatchResult &Result) { // FIXME: Find a way to have less code duplication between include-cleaner // analysis implementation and the below code. walkUsed(MainFileDecls, RecordedPreprocessor.MacroReferences, &RecordedPI, - *SM, + *PP, [&](const include_cleaner::SymbolReference &Ref, llvm::ArrayRef Providers) { // Process each symbol once to reduce noise in the findings. @@ -200,8 +200,8 @@ void IncludeCleanerCheck::check(const MatchFinder::MatchResult &Result) { tooling::HeaderIncludes HeaderIncludes(getCurrentMainFile(), Code, FileStyle->IncludeStyle); for (const auto &Inc : Missing) { - std::string Spelling = - include_cleaner::spellHeader({Inc.Missing, *HS, MainFile}); + std::string Spelling = include_cleaner::spellHeader( + {Inc.Missing, PP->getHeaderSearchInfo(), MainFile}); bool Angled = llvm::StringRef{Spelling}.starts_with("<"); // We might suggest insertion of an existing include in edge cases, e.g., // include is present in a PP-disabled region, or spelling of the header diff --git a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.h b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.h index 9641c7fd9dfcf..b46e409bd6f6a 100644 --- a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.h +++ b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.h @@ -18,6 +18,7 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/Preprocessor.h" #include "llvm/Support/Regex.h" #include @@ -42,7 +43,7 @@ class IncludeCleanerCheck : public ClangTidyCheck { private: include_cleaner::RecordedPP RecordedPreprocessor; include_cleaner::PragmaIncludes RecordedPI; - HeaderSearch *HS; + const Preprocessor *PP = nullptr; std::vector IgnoreHeaders; // Whether emit only one finding per usage of a symbol. const bool DeduplicateFindings; diff --git a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp index 4850440329bc1..92a541c9e59be 100644 --- a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp @@ -441,8 +441,6 @@ AST_MATCHER(Expr, isIntegerConstantExpr) { return Node.isIntegerConstantExpr(Finder->getASTContext()); } -AST_MATCHER(Expr, isRequiresExpr) { return isa(Node); } - AST_MATCHER(BinaryOperator, operandsAreEquivalent) { return areEquivalentExpr(Node.getLHS(), Node.getRHS()); } @@ -862,7 +860,8 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { const auto BannedIntegerLiteral = integerLiteral(expandedByMacro(KnownBannedMacroNames)); - const auto BannedAncestor = expr(isRequiresExpr()); + const auto IsInUnevaluatedContext = expr(anyOf( + hasAncestor(expr(hasUnevaluatedContext())), hasAncestor(typeLoc()))); // Binary with equivalent operands, like (X != 2 && X != 2). Finder->addMatcher( @@ -879,7 +878,7 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { unless(hasEitherOperand(hasType(realFloatingPointType()))), unless(hasLHS(AnyLiteralExpr)), unless(hasDescendant(BannedIntegerLiteral)), - unless(hasAncestor(BannedAncestor))) + unless(IsInUnevaluatedContext)) .bind("binary")), this); @@ -893,7 +892,7 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { unless(binaryOperatorIsInMacro()), // TODO: if the banned macros are themselves duplicated unless(hasDescendant(BannedIntegerLiteral)), - unless(hasAncestor(BannedAncestor))) + unless(IsInUnevaluatedContext)) .bind("nested-duplicates"), this); @@ -904,7 +903,7 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { // Filter noisy false positives. unless(conditionalOperatorIsInMacro()), unless(isInTemplateInstantiation()), - unless(hasAncestor(BannedAncestor))) + unless(IsInUnevaluatedContext)) .bind("cond")), this); @@ -918,7 +917,7 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { parametersAreEquivalent(), // Filter noisy false positives. unless(isMacro()), unless(isInTemplateInstantiation()), - unless(hasAncestor(BannedAncestor))) + unless(IsInUnevaluatedContext)) .bind("call")), this); @@ -929,7 +928,7 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { nestedParametersAreEquivalent(), argumentCountIs(2), // Filter noisy false positives. unless(isMacro()), unless(isInTemplateInstantiation()), - unless(hasAncestor(BannedAncestor))) + unless(IsInUnevaluatedContext)) .bind("nested-duplicates"), this); @@ -947,7 +946,7 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { integerLiteral())), hasRHS(integerLiteral()))))) .bind("logical-bitwise-confusion")), - unless(hasAncestor(BannedAncestor)))), + unless(IsInUnevaluatedContext))), this); // Match expressions like: (X << 8) & 0xFF @@ -961,7 +960,7 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { integerLiteral().bind("shift-const"))))), ignoringParenImpCasts( integerLiteral().bind("and-const"))), - unless(hasAncestor(BannedAncestor))) + unless(IsInUnevaluatedContext)) .bind("left-right-shift-confusion")), this); @@ -980,7 +979,7 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( traverse(TK_AsIs, binaryOperator(isComparisonOperator(), hasOperands(BinOpCstLeft, CstRight), - unless(hasAncestor(BannedAncestor))) + unless(IsInUnevaluatedContext)) .bind("binop-const-compare-to-const")), this); @@ -991,7 +990,7 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { binaryOperator(isComparisonOperator(), anyOf(allOf(hasLHS(BinOpCstLeft), hasRHS(SymRight)), allOf(hasLHS(SymRight), hasRHS(BinOpCstLeft))), - unless(hasAncestor(BannedAncestor))) + unless(IsInUnevaluatedContext)) .bind("binop-const-compare-to-sym")), this); @@ -1002,7 +1001,7 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { hasRHS(BinOpCstRight), // Already reported as redundant. unless(operandsAreEquivalent()), - unless(hasAncestor(BannedAncestor))) + unless(IsInUnevaluatedContext)) .bind("binop-const-compare-to-binop-const")), this); @@ -1019,7 +1018,7 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { hasLHS(ComparisonLeft), hasRHS(ComparisonRight), // Already reported as redundant. unless(operandsAreEquivalent()), - unless(hasAncestor(BannedAncestor))) + unless(IsInUnevaluatedContext)) .bind("comparisons-of-symbol-and-const")), this); } diff --git a/clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp b/clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp index d932b5fb936cb..ca4f6ad409b08 100644 --- a/clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp @@ -26,14 +26,20 @@ std::optional makeCharacterLiteral(const StringLiteral *Literal) { Literal->outputString(OS); } // Now replace the " with '. - auto Pos = Result.find_first_of('"'); - if (Pos == Result.npos) + auto OpenPos = Result.find_first_of('"'); + if (OpenPos == Result.npos) return std::nullopt; - Result[Pos] = '\''; - Pos = Result.find_last_of('"'); - if (Pos == Result.npos) + Result[OpenPos] = '\''; + + auto ClosePos = Result.find_last_of('"'); + if (ClosePos == Result.npos) return std::nullopt; - Result[Pos] = '\''; + Result[ClosePos] = '\''; + + // "'" is OK, but ''' is not, so add a backslash + if ((ClosePos - OpenPos) == 2 && Result[OpenPos + 1] == '\'') + Result.replace(OpenPos + 1, 1, "\\'"); + return Result; } diff --git a/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp b/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp index 863ac4dbbf4c6..99b792b90a3ca 100644 --- a/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/ImplicitBoolConversionCheck.cpp @@ -228,7 +228,8 @@ bool isCastAllowedInCondition(const ImplicitCastExpr *Cast, if (!S) return false; if (isa(S) || isa(S) || isa(S) || - isa(S) || isa(S)) + isa(S) || isa(S) || + isa(S)) return true; if (isa(S) || isa(S) || isUnaryLogicalNotOperator(S) || diff --git a/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp b/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp index 619374cddbcf6..93c31d80c1138 100644 --- a/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp @@ -15,8 +15,12 @@ using namespace clang::ast_matchers; namespace clang::tidy::readability { +namespace { +AST_MATCHER(CXXMethodDecl, isStatic) { return Node.isStatic(); } +} // namespace + static unsigned getNameSpecifierNestingLevel(const QualType &QType) { - if (const ElaboratedType *ElType = QType->getAs()) { + if (const auto *ElType = QType->getAs()) { if (const NestedNameSpecifier *NestedSpecifiers = ElType->getQualifier()) { unsigned NameSpecifierNestingLevel = 1; do { @@ -38,7 +42,7 @@ void StaticAccessedThroughInstanceCheck::storeOptions( void StaticAccessedThroughInstanceCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( - memberExpr(hasDeclaration(anyOf(cxxMethodDecl(isStaticStorageClass()), + memberExpr(hasDeclaration(anyOf(cxxMethodDecl(isStatic()), varDecl(hasStaticStorageDuration()), enumConstantDecl()))) .bind("memberExpression"), diff --git a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py index e0c2d63d2024c..312d9241cfa57 100755 --- a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py +++ b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py @@ -389,6 +389,8 @@ def main(): clang_apply_replacements_binary = find_binary( args.clang_apply_replacements_binary, "clang-apply-replacements", build_path ) + + if args.fix or (yaml and args.export_fixes): tmpdir = tempfile.mkdtemp() try: diff --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp index 957a6f873e102..ef5d5db0577b0 100644 --- a/clang-tools-extra/clangd/CompileCommands.cpp +++ b/clang-tools-extra/clangd/CompileCommands.cpp @@ -237,14 +237,8 @@ void CommandMangler::operator()(tooling::CompileCommand &Command, llvm::opt::InputArgList ArgList; ArgList = OptTable.ParseArgs( llvm::ArrayRef(OriginalArgs).drop_front(), IgnoredCount, IgnoredCount, - /*FlagsToInclude=*/ - IsCLMode ? (driver::options::CLOption | driver::options::CoreOption | - driver::options::CLDXCOption) - : /*everything*/ 0, - /*FlagsToExclude=*/driver::options::NoDriverOption | - (IsCLMode - ? 0 - : (driver::options::CLOption | driver::options::CLDXCOption))); + llvm::opt::Visibility(IsCLMode ? driver::options::CLOption + : driver::options::ClangOption)); llvm::SmallVector IndicesToDrop; // Having multiple architecture options (e.g. when building fat binaries) @@ -441,23 +435,13 @@ DriverMode getDriverMode(const std::vector &Args) { // Returns the set of DriverModes where an option may be used. unsigned char getModes(const llvm::opt::Option &Opt) { - // Why is this so complicated?! - // Reference is clang::driver::Driver::getIncludeExcludeOptionFlagMasks() unsigned char Result = DM_None; - if (Opt.hasFlag(driver::options::CC1Option)) + if (Opt.hasVisibilityFlag(driver::options::ClangOption)) + Result |= DM_GCC; + if (Opt.hasVisibilityFlag(driver::options::CC1Option)) Result |= DM_CC1; - if (!Opt.hasFlag(driver::options::NoDriverOption)) { - if (Opt.hasFlag(driver::options::CLOption)) { - Result |= DM_CL; - } else if (Opt.hasFlag(driver::options::CLDXCOption)) { - Result |= DM_CL; - } else { - Result |= DM_GCC; - if (Opt.hasFlag(driver::options::CoreOption)) { - Result |= DM_CL; - } - } - } + if (Opt.hasVisibilityFlag(driver::options::CLOption)) + Result |= DM_CL; return Result; } @@ -493,8 +477,8 @@ llvm::ArrayRef ArgStripper::rulesFor(llvm::StringRef Arg) { static constexpr llvm::StringLiteral NAME##_init[] = VALUE; \ static constexpr llvm::ArrayRef NAME( \ NAME##_init, std::size(NAME##_init) - 1); -#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELP, METAVAR, VALUES) \ +#define OPTION(PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, \ + FLAGS, VISIBILITY, PARAM, HELP, METAVAR, VALUES) \ Prefixes[DriverID::OPT_##ID] = PREFIX; #include "clang/Driver/Options.inc" #undef OPTION @@ -505,8 +489,8 @@ llvm::ArrayRef ArgStripper::rulesFor(llvm::StringRef Arg) { DriverID AliasID; const void *AliasArgs; } AliasTable[] = { -#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ - HELP, METAVAR, VALUES) \ +#define OPTION(PREFIX, PREFIXED_NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, \ + FLAGS, VISIBILITY, PARAM, HELP, METAVAR, VALUES) \ {DriverID::OPT_##ID, DriverID::OPT_##ALIAS, ALIASARGS}, #include "clang/Driver/Options.inc" #undef OPTION diff --git a/clang-tools-extra/clangd/Headers.cpp b/clang-tools-extra/clangd/Headers.cpp index 83fba21b1d931..6005069be0116 100644 --- a/clang-tools-extra/clangd/Headers.cpp +++ b/clang-tools-extra/clangd/Headers.cpp @@ -286,11 +286,11 @@ IncludeInserter::calculateIncludePath(const HeaderFile &InsertedHeader, assert(InsertedHeader.valid()); if (InsertedHeader.Verbatim) return InsertedHeader.File; - bool IsSystem = false; + bool IsAngled = false; std::string Suggested; if (HeaderSearchInfo) { Suggested = HeaderSearchInfo->suggestPathToFileForDiagnostics( - InsertedHeader.File, BuildDir, IncludingFile, &IsSystem); + InsertedHeader.File, BuildDir, IncludingFile, &IsAngled); } else { // Calculate include relative to including file only. StringRef IncludingDir = llvm::sys::path::parent_path(IncludingFile); @@ -303,7 +303,7 @@ IncludeInserter::calculateIncludePath(const HeaderFile &InsertedHeader, // FIXME: should we allow (some limited number of) "../header.h"? if (llvm::sys::path::is_absolute(Suggested)) return std::nullopt; - if (IsSystem) + if (IsAngled) Suggested = "<" + Suggested + ">"; else Suggested = "\"" + Suggested + "\""; diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp index aaa160bb048ef..0ec85fc24df15 100644 --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -1245,12 +1245,11 @@ std::string getSymbolName(include_cleaner::Symbol Sym) { } void maybeAddUsedSymbols(ParsedAST &AST, HoverInfo &HI, const Inclusion &Inc) { - const SourceManager &SM = AST.getSourceManager(); auto Converted = convertIncludes(AST); llvm::DenseSet UsedSymbols; include_cleaner::walkUsed( AST.getLocalTopLevelDecls(), collectMacroReferences(AST), - AST.getPragmaIncludes().get(), SM, + AST.getPragmaIncludes().get(), AST.getPreprocessor(), [&](const include_cleaner::SymbolReference &Ref, llvm::ArrayRef Providers) { if (Ref.RT != include_cleaner::RefType::Explicit || diff --git a/clang-tools-extra/clangd/IncludeCleaner.cpp b/clang-tools-extra/clangd/IncludeCleaner.cpp index 07c6937ac10d5..1fcb5c7228fb6 100644 --- a/clang-tools-extra/clangd/IncludeCleaner.cpp +++ b/clang-tools-extra/clangd/IncludeCleaner.cpp @@ -394,7 +394,7 @@ IncludeCleanerFindings computeIncludeCleanerFindings(ParsedAST &AST) { trace::Span Tracer("include_cleaner::walkUsed"); include_cleaner::walkUsed( AST.getLocalTopLevelDecls(), /*MacroRefs=*/Macros, - AST.getPragmaIncludes().get(), SM, + AST.getPragmaIncludes().get(), AST.getPreprocessor(), [&](const include_cleaner::SymbolReference &Ref, llvm::ArrayRef Providers) { bool Satisfied = false; diff --git a/clang-tools-extra/clangd/InlayHints.cpp b/clang-tools-extra/clangd/InlayHints.cpp index 1962aa51aef41..56f85ee155cb2 100644 --- a/clang-tools-extra/clangd/InlayHints.cpp +++ b/clang-tools-extra/clangd/InlayHints.cpp @@ -273,7 +273,7 @@ std::string summarizeExpr(const Expr *E) { return getSimpleName(E->getMember()).str(); } std::string - VisitDependentScopeMemberExpr(const DependentScopeDeclRefExpr *E) { + VisitDependentScopeDeclRefExpr(const DependentScopeDeclRefExpr *E) { return getSimpleName(E->getDeclName()).str(); } std::string VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *E) { @@ -485,6 +485,56 @@ QualType maybeDesugar(ASTContext &AST, QualType QT) { return QT; } +// Given a callee expression `Fn`, if the call is through a function pointer, +// try to find the declaration of the corresponding function pointer type, +// so that we can recover argument names from it. +// FIXME: This function is mostly duplicated in SemaCodeComplete.cpp; unify. +static FunctionProtoTypeLoc getPrototypeLoc(Expr *Fn) { + TypeLoc Target; + Expr *NakedFn = Fn->IgnoreParenCasts(); + if (const auto *T = NakedFn->getType().getTypePtr()->getAs()) { + Target = T->getDecl()->getTypeSourceInfo()->getTypeLoc(); + } else if (const auto *DR = dyn_cast(NakedFn)) { + const auto *D = DR->getDecl(); + if (const auto *const VD = dyn_cast(D)) { + Target = VD->getTypeSourceInfo()->getTypeLoc(); + } + } + + if (!Target) + return {}; + + // Unwrap types that may be wrapping the function type + while (true) { + if (auto P = Target.getAs()) { + Target = P.getPointeeLoc(); + continue; + } + if (auto A = Target.getAs()) { + Target = A.getModifiedLoc(); + continue; + } + if (auto P = Target.getAs()) { + Target = P.getInnerLoc(); + continue; + } + break; + } + + if (auto F = Target.getAs()) { + return F; + } + + return {}; +} + +struct Callee { + // Only one of Decl or Loc is set. + // Loc is for calls through function pointers. + const FunctionDecl *Decl = nullptr; + FunctionProtoTypeLoc Loc; +}; + class InlayHintVisitor : public RecursiveASTVisitor { public: InlayHintVisitor(std::vector &Results, ParsedAST &AST, @@ -524,7 +574,11 @@ class InlayHintVisitor : public RecursiveASTVisitor { return true; } - processCall(E->getConstructor(), {E->getArgs(), E->getNumArgs()}); + Callee Callee; + Callee.Decl = E->getConstructor(); + if (!Callee.Decl) + return true; + processCall(Callee, {E->getArgs(), E->getNumArgs()}); return true; } @@ -534,7 +588,7 @@ class InlayHintVisitor : public RecursiveASTVisitor { // Do not show parameter hints for operator calls written using operator // syntax or user-defined literals. (Among other reasons, the resulting - // hints can look awkard, e.g. the expression can itself be a function + // hints can look awkward, e.g. the expression can itself be a function // argument and then we'd get two hints side by side). if (isa(E) || isa(E)) return true; @@ -542,12 +596,15 @@ class InlayHintVisitor : public RecursiveASTVisitor { auto CalleeDecls = Resolver->resolveCalleeOfCallExpr(E); if (CalleeDecls.size() != 1) return true; - const FunctionDecl *Callee = nullptr; + + Callee Callee; if (const auto *FD = dyn_cast(CalleeDecls[0])) - Callee = FD; + Callee.Decl = FD; else if (const auto *FTD = dyn_cast(CalleeDecls[0])) - Callee = FTD->getTemplatedDecl(); - if (!Callee) + Callee.Decl = FTD->getTemplatedDecl(); + else if (FunctionProtoTypeLoc Loc = getPrototypeLoc(E->getCallee())) + Callee.Loc = Loc; + else return true; processCall(Callee, {E->getArgs(), E->getNumArgs()}); @@ -676,7 +733,8 @@ class InlayHintVisitor : public RecursiveASTVisitor { // For structured bindings, print canonical types. This is important // because for bindings that use the tuple_element protocol, the // non-canonical types would be "tuple_element::type". - if (auto Type = Binding->getType(); !Type.isNull()) + if (auto Type = Binding->getType(); + !Type.isNull() && !Type->isDependentType()) addTypeHint(Binding->getLocation(), Type.getCanonicalType(), /*Prefix=*/": "); } @@ -762,25 +820,35 @@ class InlayHintVisitor : public RecursiveASTVisitor { private: using NameVec = SmallVector; - void processCall(const FunctionDecl *Callee, - llvm::ArrayRef Args) { - if (!Cfg.InlayHints.Parameters || Args.size() == 0 || !Callee) + void processCall(Callee Callee, llvm::ArrayRef Args) { + assert(Callee.Decl || Callee.Loc); + + if (!Cfg.InlayHints.Parameters || Args.size() == 0) return; // The parameter name of a move or copy constructor is not very interesting. - if (auto *Ctor = dyn_cast(Callee)) - if (Ctor->isCopyOrMoveConstructor()) - return; + if (Callee.Decl) + if (auto *Ctor = dyn_cast(Callee.Decl)) + if (Ctor->isCopyOrMoveConstructor()) + return; + + auto Params = + Callee.Decl ? Callee.Decl->parameters() : Callee.Loc.getParams(); // Resolve parameter packs to their forwarded parameter - auto ForwardedParams = resolveForwardingParameters(Callee); + SmallVector ForwardedParams; + if (Callee.Decl) + ForwardedParams = resolveForwardingParameters(Callee.Decl); + else + ForwardedParams = {Params.begin(), Params.end()}; NameVec ParameterNames = chooseParameterNames(ForwardedParams); // Exclude setters (i.e. functions with one argument whose name begins with // "set"), and builtins like std::move/forward/... as their parameter name // is also not likely to be interesting. - if (isSetter(Callee, ParameterNames) || isSimpleBuiltin(Callee)) + if (Callee.Decl && + (isSetter(Callee.Decl, ParameterNames) || isSimpleBuiltin(Callee.Decl))) return; for (size_t I = 0; I < ParameterNames.size() && I < Args.size(); ++I) { @@ -793,8 +861,7 @@ class InlayHintVisitor : public RecursiveASTVisitor { StringRef Name = ParameterNames[I]; bool NameHint = shouldHintName(Args[I], Name); - bool ReferenceHint = - shouldHintReference(Callee->getParamDecl(I), ForwardedParams[I]); + bool ReferenceHint = shouldHintReference(Params[I], ForwardedParams[I]); if (NameHint || ReferenceHint) { addInlayHint(Args[I]->getSourceRange(), HintSide::Left, diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp index 81cfe8bb60b3e..3cf6671be9600 100644 --- a/clang-tools-extra/clangd/ParsedAST.cpp +++ b/clang-tools-extra/clangd/ParsedAST.cpp @@ -396,6 +396,15 @@ ParsedAST::build(llvm::StringRef Filename, const ParseInputs &Inputs, VFS = Preamble->StatCache->getConsumingFS(std::move(VFS)); assert(CI); + + if (CI->getFrontendOpts().Inputs.size() > 0) { + auto Lang = CI->getFrontendOpts().Inputs[0].getKind().getLanguage(); + if (Lang == Language::Asm || Lang == Language::LLVM_IR) { + elog("Clangd does not support assembly or IR source files"); + return std::nullopt; + } + } + // Command-line parsing sets DisableFree to true by default, but we don't want // to leak memory in clangd. CI->getFrontendOpts().DisableFree = false; diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h index 23a48e0a8e5f6..e88c804692568 100644 --- a/clang-tools-extra/clangd/Protocol.h +++ b/clang-tools-extra/clangd/Protocol.h @@ -592,7 +592,7 @@ bool fromJSON(const llvm::json::Value &, ConfigurationSettings &, /// Clangd extension: parameters configurable at `initialize` time. /// LSP defines this type as `any`. struct InitializationOptions { - // What we can change throught the didChangeConfiguration request, we can + // What we can change through the didChangeConfiguration request, we can // also set through the initialize request (initializationOptions field). ConfigurationSettings ConfigSettings; diff --git a/clang-tools-extra/clangd/SystemIncludeExtractor.cpp b/clang-tools-extra/clangd/SystemIncludeExtractor.cpp index 6cce28f53b577..ac99b220f6bd3 100644 --- a/clang-tools-extra/clangd/SystemIncludeExtractor.cpp +++ b/clang-tools-extra/clangd/SystemIncludeExtractor.cpp @@ -133,6 +133,16 @@ struct DriverArgs { } } + // Downgrade objective-c++-header (used in clangd's fallback flags for .h + // files) to c++-header, as some drivers may fail to run the extraction + // command if it contains `-xobjective-c++-header` and objective-c++ support + // is not installed. + // In practice, we don't see different include paths for the two on + // clang+mac, which is the most common objectve-c compiler. + if (Lang == "objective-c++-header") { + Lang = "c++-header"; + } + // If language is not explicit in the flags, infer from the file. // This is important as we want to cache each language separately. if (Lang.empty()) { diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp index bcbd214a725ce..9beb3f1417b9a 100644 --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -1339,7 +1339,7 @@ maybeFindIncludeReferences(ParsedAST &AST, Position Pos, auto Converted = convertIncludes(AST); include_cleaner::walkUsed( AST.getLocalTopLevelDecls(), collectMacroReferences(AST), - AST.getPragmaIncludes().get(), SM, + AST.getPragmaIncludes().get(), AST.getPreprocessor(), [&](const include_cleaner::SymbolReference &Ref, llvm::ArrayRef Providers) { if (Ref.RT != include_cleaner::RefType::Explicit || diff --git a/clang-tools-extra/clangd/index/StdLib.cpp b/clang-tools-extra/clangd/index/StdLib.cpp index d9aa46d6b75b1..477a5d1ebe523 100644 --- a/clang-tools-extra/clangd/index/StdLib.cpp +++ b/clang-tools-extra/clangd/index/StdLib.cpp @@ -59,8 +59,8 @@ LangStandard::Kind standardFromOpts(const LangOptions &LO) { return LangStandard::lang_cxx11; return LangStandard::lang_cxx98; } - if (LO.C2x) - return LangStandard::lang_c2x; + if (LO.C23) + return LangStandard::lang_c23; // C17 has no new features, so treat {C11,C17} as C17. if (LO.C11) return LangStandard::lang_c17; diff --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp index c9a211b9c4fc2..e843413601f5a 100644 --- a/clang-tools-extra/clangd/index/SymbolCollector.cpp +++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp @@ -328,42 +328,33 @@ class SymbolCollector::HeaderFileURICache { // instead of // which should be used instead of directly // importing the header. - std::optional getFrameworkUmbrellaSpelling( - llvm::StringRef Framework, SrcMgr::CharacteristicKind HeadersDirKind, - const HeaderSearch &HS, FrameworkHeaderPath &HeaderPath) { + std::optional + getFrameworkUmbrellaSpelling(llvm::StringRef Framework, + const HeaderSearch &HS, + FrameworkHeaderPath &HeaderPath) { auto Res = CacheFrameworkToUmbrellaHeaderSpelling.try_emplace(Framework); auto *CachedSpelling = &Res.first->second; if (!Res.second) { return HeaderPath.IsPrivateHeader ? CachedSpelling->PrivateHeader : CachedSpelling->PublicHeader; } - bool IsSystem = isSystem(HeadersDirKind); SmallString<256> UmbrellaPath(HeaderPath.HeadersParentDir); llvm::sys::path::append(UmbrellaPath, "Headers", Framework + ".h"); llvm::vfs::Status Status; auto StatErr = HS.getFileMgr().getNoncachedStatValue(UmbrellaPath, Status); - if (!StatErr) { - if (IsSystem) - CachedSpelling->PublicHeader = llvm::formatv("<{0}/{0}.h>", Framework); - else - CachedSpelling->PublicHeader = - llvm::formatv("\"{0}/{0}.h\"", Framework); - } + if (!StatErr) + CachedSpelling->PublicHeader = llvm::formatv("<{0}/{0}.h>", Framework); UmbrellaPath = HeaderPath.HeadersParentDir; llvm::sys::path::append(UmbrellaPath, "PrivateHeaders", Framework + "_Private.h"); StatErr = HS.getFileMgr().getNoncachedStatValue(UmbrellaPath, Status); - if (!StatErr) { - if (IsSystem) - CachedSpelling->PrivateHeader = - llvm::formatv("<{0}/{0}_Private.h>", Framework); - else - CachedSpelling->PrivateHeader = - llvm::formatv("\"{0}/{0}_Private.h\"", Framework); - } + if (!StatErr) + CachedSpelling->PrivateHeader = + llvm::formatv("<{0}/{0}_Private.h>", Framework); + return HeaderPath.IsPrivateHeader ? CachedSpelling->PrivateHeader : CachedSpelling->PublicHeader; } @@ -386,21 +377,14 @@ class SymbolCollector::HeaderFileURICache { CachePathToFrameworkSpelling.erase(Res.first); return std::nullopt; } - auto DirKind = HS.getFileDirFlavor(FE); if (auto UmbrellaSpelling = - getFrameworkUmbrellaSpelling(Framework, DirKind, HS, *HeaderPath)) { + getFrameworkUmbrellaSpelling(Framework, HS, *HeaderPath)) { *CachedHeaderSpelling = *UmbrellaSpelling; return llvm::StringRef(*CachedHeaderSpelling); } - if (isSystem(DirKind)) - *CachedHeaderSpelling = - llvm::formatv("<{0}/{1}>", Framework, HeaderPath->HeaderSubpath) - .str(); - else - *CachedHeaderSpelling = - llvm::formatv("\"{0}/{1}\"", Framework, HeaderPath->HeaderSubpath) - .str(); + *CachedHeaderSpelling = + llvm::formatv("<{0}/{1}>", Framework, HeaderPath->HeaderSubpath).str(); return llvm::StringRef(*CachedHeaderSpelling); } diff --git a/clang-tools-extra/clangd/index/SymbolLocation.h b/clang-tools-extra/clangd/index/SymbolLocation.h index eadf211bb3bf6..ea7d605172e47 100644 --- a/clang-tools-extra/clangd/index/SymbolLocation.h +++ b/clang-tools-extra/clangd/index/SymbolLocation.h @@ -30,7 +30,7 @@ struct SymbolLocation { // Position is encoded into 32 bits to save space. // If Line/Column overflow, the value will be their maximum value. struct Position { - Position() : LineColumnPacked(0) {} + Position() = default; void setLine(uint32_t Line); uint32_t line() const { return LineColumnPacked >> ColumnBits; } void setColumn(uint32_t Column); @@ -46,7 +46,7 @@ struct SymbolLocation { static constexpr uint32_t MaxColumn = (1 << ColumnBits) - 1; private: - uint32_t LineColumnPacked; // Top 20 bit line, bottom 12 bits column. + uint32_t LineColumnPacked = 0; // Top 20 bit line, bottom 12 bits column. }; /// The symbol range, using half-open range [Start, End). diff --git a/clang-tools-extra/clangd/tool/CMakeLists.txt b/clang-tools-extra/clangd/tool/CMakeLists.txt index 5c3b566c97364..6c21175d7687c 100644 --- a/clang-tools-extra/clangd/tool/CMakeLists.txt +++ b/clang-tools-extra/clangd/tool/CMakeLists.txt @@ -26,11 +26,7 @@ clang_target_link_libraries(clangdMain clangBasic clangFormat clangFrontend - clangLex - clangSema clangTooling - clangToolingCore - clangToolingRefactoring clangToolingSyntax ) @@ -48,11 +44,8 @@ clang_target_link_libraries(clangd PRIVATE clangAST clangBasic - clangFormat - clangFrontend clangLex clangSema - clangTooling clangToolingCore clangToolingRefactoring clangToolingSyntax diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index dd6ee44224471..671c0b7da97c6 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -1397,20 +1397,37 @@ TEST(SignatureHelpTest, Overloads) { } TEST(SignatureHelpTest, FunctionPointers) { - auto FunctionPointerResults = signatures(R"cpp( + llvm::StringLiteral Tests[] = { + // Variable of function pointer type + R"cpp( void (*foo)(int x, int y); int main() { foo(^); } - )cpp"); - EXPECT_THAT(FunctionPointerResults.signatures, - UnorderedElementsAre(sig("([[int x]], [[int y]]) -> void"))); - - auto FunctionPointerTypedefResults = signatures(R"cpp( + )cpp", + // Wrapped in an AttributedType + R"cpp( + void (__stdcall *foo)(int x, int y); + int main() { foo(^); } + )cpp", + // Another syntax for an AttributedType + R"cpp( + void (__attribute__(stdcall) *foo)(int x, int y); + int main() { foo(^); }, + )cpp", + // Wrapped in a typedef + R"cpp( typedef void (*fn)(int x, int y); fn foo; int main() { foo(^); } - )cpp"); - EXPECT_THAT(FunctionPointerTypedefResults.signatures, - UnorderedElementsAre(sig("([[int x]], [[int y]]) -> void"))); + )cpp", + // Wrapped in both a typedef and an AttributedTyped + R"cpp( + typedef void (__stdcall *fn)(int x, int y); + fn foo; + int main() { foo(^); } + )cpp"}; + for (auto Test : Tests) + EXPECT_THAT(signatures(Test).signatures, + UnorderedElementsAre(sig("([[int x]], [[int y]]) -> void"))); } TEST(SignatureHelpTest, Constructors) { diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp index 2ad7f0ee55d72..9cab9a086958d 100644 --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -2543,6 +2543,19 @@ TEST(Hover, All) { HI.Type = "Test &&"; HI.Definition = "Test &&test = {}"; }}, + { + R"cpp(// Shouldn't crash when evaluating the initializer. + struct Bar {}; // error-ok + struct Foo { void foo(Bar x = y); } + void Foo::foo(Bar [[^x]]) {})cpp", + [](HoverInfo &HI) { + HI.Name = "x"; + HI.Kind = index::SymbolKind::Parameter; + HI.NamespaceScope = ""; + HI.LocalScope = "Foo::foo::"; + HI.Type = "Bar"; + HI.Definition = "Bar x = ()"; + }}, { R"cpp(// auto on alias typedef int int_type; diff --git a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp index d38b875994e63..1d12db3661c9e 100644 --- a/clang-tools-extra/clangd/unittests/InlayHintTests.cpp +++ b/clang-tools-extra/clangd/unittests/InlayHintTests.cpp @@ -919,6 +919,26 @@ TEST(ParameterHints, ImplicitConstructor) { )cpp"); } +TEST(ParameterHints, FunctionPointer) { + assertParameterHints( + R"cpp( + void (*f1)(int param); + void (__stdcall *f2)(int param); + using f3_t = void(*)(int param); + f3_t f3; + using f4_t = void(__stdcall *)(int param); + f4_t f4; + void bar() { + f1($f1[[42]]); + f2($f2[[42]]); + f3($f3[[42]]); + f4($f4[[42]]); + } + )cpp", + ExpectedHint{"param: ", "f1"}, ExpectedHint{"param: ", "f2"}, + ExpectedHint{"param: ", "f3"}, ExpectedHint{"param: ", "f4"}); +} + TEST(ParameterHints, ArgMatchesParam) { assertParameterHints(R"cpp( void foo(int param); @@ -1333,6 +1353,11 @@ TEST(TypeHints, DependentType) { // FIXME: It would be nice to show "T" as the hint. auto $var2[[var2]] = arg; } + + template + void bar(T arg) { + auto [a, b] = arg; + } )cpp"); } diff --git a/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp b/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp index b0d5bea1d3279..ec8132645f81f 100644 --- a/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp +++ b/clang-tools-extra/clangd/unittests/ParsedASTTests.cpp @@ -13,6 +13,7 @@ #include "../../clang-tidy/ClangTidyCheck.h" #include "AST.h" +#include "CompileCommands.h" #include "Compiler.h" #include "Config.h" #include "Diagnostics.h" @@ -731,6 +732,37 @@ TEST(ParsedASTTest, DiscoversPragmaMarks) { pragmaTrivia(" End"))); } +TEST(ParsedASTTest, GracefulFailureOnAssemblyFile) { + std::string Filename = "TestTU.S"; + std::string Code = R"S( +main: + # test comment + bx lr + )S"; + + // The rest is a simplified version of TestTU::build(). + // Don't call TestTU::build() itself because it would assert on + // failure to build an AST. + MockFS FS; + std::string FullFilename = testPath(Filename); + FS.Files[FullFilename] = Code; + ParseInputs Inputs; + auto &Argv = Inputs.CompileCommand.CommandLine; + Argv = {"clang"}; + Argv.push_back(FullFilename); + Inputs.CompileCommand.Filename = FullFilename; + Inputs.CompileCommand.Directory = testRoot(); + Inputs.Contents = Code; + Inputs.TFS = &FS; + StoreDiags Diags; + auto CI = buildCompilerInvocation(Inputs, Diags); + assert(CI && "Failed to build compilation invocation."); + auto AST = ParsedAST::build(FullFilename, Inputs, std::move(CI), {}, nullptr); + + EXPECT_FALSE(AST.has_value()) + << "Should not try to build AST for assembly source file"; +} + } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp index 338cada5c03cb..58b9c85801051 100644 --- a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp +++ b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp @@ -702,9 +702,9 @@ TEST_F(SymbolCollectorTest, ObjCFrameworkIncludeHeader) { EXPECT_THAT( Symbols, UnorderedElementsAre( - AllOf(qName("NSObject"), includeHeader("\"Foundation/NSObject.h\"")), + AllOf(qName("NSObject"), includeHeader("")), AllOf(qName("PrivateClass"), - includeHeader("\"Foundation/NSObject+Private.h\"")), + includeHeader("")), AllOf(qName("Container")))); // After adding the umbrella headers, we should use that spelling instead. @@ -722,13 +722,13 @@ TEST_F(SymbolCollectorTest, ObjCFrameworkIncludeHeader) { "Foundation_Private.h"), 0, llvm::MemoryBuffer::getMemBuffer(PrivateUmbrellaHeader)); runSymbolCollector(Header, Main, {"-F", FrameworksPath, "-xobjective-c++"}); - EXPECT_THAT(Symbols, - UnorderedElementsAre( - AllOf(qName("NSObject"), - includeHeader("\"Foundation/Foundation.h\"")), - AllOf(qName("PrivateClass"), - includeHeader("\"Foundation/Foundation_Private.h\"")), - AllOf(qName("Container")))); + EXPECT_THAT( + Symbols, + UnorderedElementsAre( + AllOf(qName("NSObject"), includeHeader("")), + AllOf(qName("PrivateClass"), + includeHeader("")), + AllOf(qName("Container")))); runSymbolCollector(Header, Main, {"-iframework", FrameworksPath, "-xobjective-c++"}); diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index dbd2fbf6de6d4..5cf09bd26fab8 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -136,6 +136,12 @@ New checks extracted from an optional-like type and then used to create a new instance of the same optional-like type. +- New :doc:`cppcoreguidelines-no-suspend-with-lock + ` check. + + Flags coroutines that suspend while a lock guard is in scope at the + suspension point. + - New :doc:`modernize-use-constraints ` check. @@ -167,6 +173,10 @@ Changes in existing checks `, so that it does not warn on macros starting with underscore and lowercase letter. +- Improved :doc:`bugprone-lambda-function-name + ` check by adding option + `IgnoreMacros` to ignore warnings in macros. + - Improved :doc:`cppcoreguidelines-avoid-non-const-global-variables ` check to ignore ``static`` variables declared within the scope of @@ -176,18 +186,38 @@ Changes in existing checks ` check to ignore delegate constructors. +- Improved :doc `cppcoreguidelines-pro-bounds-array-to-pointer-decay + ` check + to ignore predefined expression (e.g., ``__func__``, ...). + +- Improved :doc:`cppcoreguidelines-pro-type-member-init + ` check to ignore + dependent delegate constructors. + +- Improved :doc:`cppcoreguidelines-pro-type-vararg + ` check to ignore + false-positives in unevaluated context (e.g., ``decltype``, ``sizeof``, ...). + - Improved :doc:`llvm-namespace-comment ` check to provide fixes for ``inline`` namespaces in the same format as :program:`clang-format`. - Improved :doc:`misc-include-cleaner ` check by adding option - `DeduplicateFindings` to output one finding per symbol occurence. + `DeduplicateFindings` to output one finding per symbol occurrence. + +- Improved :doc:`misc-redundant-expression + ` check to ignore + false-positives in unevaluated context (e.g., ``decltype``). - Improved :doc:`modernize-loop-convert ` to support for-loops with iterators initialized by free functions like ``begin``, ``end``, or ``size``. +- Improved :doc:`performance-faster-string-find + ` check to properly escape + single quotes. + - Improved :doc:`performanc-noexcept-swap ` check to enforce a stricter match with the swap function signature, eliminating false-positives. @@ -196,6 +226,15 @@ Changes in existing checks ` check to emit proper warnings when a type forward declaration precedes its definition. +- Improved :doc:`readability-implicit-bool-conversion + ` check to take + do-while loops into account for the `AllowIntegerConditions` and + `AllowPointerConditions` options. + +- Improved :doc:`readability-static-accessed-through-instance + ` check to + identify calls to static member functions with out-of-class inline definitions. + Removed checks ^^^^^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/lambda-function-name.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/lambda-function-name.rst index 6f0ba836fdf5c..e9cbf2b46b2bc 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/lambda-function-name.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/lambda-function-name.rst @@ -25,3 +25,11 @@ Likely intended output:: Called from FancyFunction Now called from FancyFunction + +Options +------- + +.. option:: IgnoreMacros + + The value `true` specifies that attempting to get the name of a function from + within a macro should not be diagnosed. The default value is `false`. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.CallAndMessage.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.CallAndMessage.rst index 69d1e6e5a5d4a..cb8a21dc688c7 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.CallAndMessage.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.CallAndMessage.rst @@ -5,6 +5,10 @@ clang-analyzer-core.CallAndMessage ================================== +Check for logical errors for function calls and Objective-C message expressions +(e.g., uninitialized arguments, null function pointers). + The clang-analyzer-core.CallAndMessage check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.DivideZero.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.DivideZero.rst index f3c652f88b6f8..2128501702515 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.DivideZero.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.DivideZero.rst @@ -5,6 +5,9 @@ clang-analyzer-core.DivideZero ============================== +Check for division by zero. + The clang-analyzer-core.DivideZero check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.DynamicTypePropagation.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.DynamicTypePropagation.rst deleted file mode 100644 index e4f8eeaaab9d0..0000000000000 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.DynamicTypePropagation.rst +++ /dev/null @@ -1,6 +0,0 @@ -.. title:: clang-tidy - clang-analyzer-core.DynamicTypePropagation - -clang-analyzer-core.DynamicTypePropagation -========================================== - -Generate dynamic type information diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.NonNullParamChecker.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.NonNullParamChecker.rst index 3188c29e5c285..c103b99da3eba 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.NonNullParamChecker.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.NonNullParamChecker.rst @@ -5,6 +5,10 @@ clang-analyzer-core.NonNullParamChecker ======================================= +Check for null pointers passed as arguments to a function whose arguments are +references or marked with the 'nonnull' attribute. + The clang-analyzer-core.NonNullParamChecker check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.NullDereference.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.NullDereference.rst index f771c9e280369..c225fa5ee9526 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.NullDereference.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.NullDereference.rst @@ -5,6 +5,9 @@ clang-analyzer-core.NullDereference =================================== +Check for dereferences of null pointers. + The clang-analyzer-core.NullDereference check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.StackAddressEscape.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.StackAddressEscape.rst index a3fb1111556b2..1efe0a4b26b2e 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.StackAddressEscape.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.StackAddressEscape.rst @@ -5,6 +5,9 @@ clang-analyzer-core.StackAddressEscape ====================================== +Check that addresses to stack memory do not escape the function. + The clang-analyzer-core.StackAddressEscape check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.UndefinedBinaryOperatorResult.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.UndefinedBinaryOperatorResult.rst index 1e36f6bbab233..29f9d695b5f83 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.UndefinedBinaryOperatorResult.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.UndefinedBinaryOperatorResult.rst @@ -5,6 +5,9 @@ clang-analyzer-core.UndefinedBinaryOperatorResult ================================================= +Check for undefined results of binary operators. + The clang-analyzer-core.UndefinedBinaryOperatorResult check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.VLASize.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.VLASize.rst index 80e6ba5f33572..600392b564732 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.VLASize.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.VLASize.rst @@ -5,6 +5,9 @@ clang-analyzer-core.VLASize =========================== +Check for declarations of VLA of undefined or zero size. + The clang-analyzer-core.VLASize check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.ArraySubscript.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.ArraySubscript.rst index 5da6a33c3605f..ebb4c74249ca9 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.ArraySubscript.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.ArraySubscript.rst @@ -5,6 +5,9 @@ clang-analyzer-core.uninitialized.ArraySubscript ================================================ +Check for uninitialized values used as array subscripts. + The clang-analyzer-core.uninitialized.ArraySubscript check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.Assign.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.Assign.rst index 8cc982b6fee3c..eb53d0ecbd29b 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.Assign.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.Assign.rst @@ -5,6 +5,9 @@ clang-analyzer-core.uninitialized.Assign ======================================== +Check for assigning uninitialized values. + The clang-analyzer-core.uninitialized.Assign check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.Branch.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.Branch.rst index e0fcd7bcc76a9..330d8507e66a9 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.Branch.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.Branch.rst @@ -5,6 +5,9 @@ clang-analyzer-core.uninitialized.Branch ======================================== +Check for uninitialized values used as branch conditions. + The clang-analyzer-core.uninitialized.Branch check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.CapturedBlockVariable.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.CapturedBlockVariable.rst index 396ce2656cbc8..ffe7a940096a7 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.CapturedBlockVariable.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.CapturedBlockVariable.rst @@ -1,6 +1,13 @@ .. title:: clang-tidy - clang-analyzer-core.uninitialized.CapturedBlockVariable +.. meta:: + :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#core-uninitialized-capturedblockvariable clang-analyzer-core.uninitialized.CapturedBlockVariable ======================================================= -Check for blocks that capture uninitialized values +Check for blocks that capture uninitialized values. + +The clang-analyzer-core.uninitialized.CapturedBlockVariable check is an alias, please see +`Clang Static Analyzer Available Checkers +`_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.NewArraySize.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.NewArraySize.rst new file mode 100644 index 0000000000000..79a5c0abebf8f --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.NewArraySize.rst @@ -0,0 +1,13 @@ +.. title:: clang-tidy - clang-analyzer-core.uninitialized.NewArraySize +.. meta:: + :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#core-uninitialized-newarraysize + +clang-analyzer-core.uninitialized.NewArraySize +============================================== + +Check if the size of the array in a new[] expression is undefined. + +The clang-analyzer-core.uninitialized.NewArraySize check is an alias, please see +`Clang Static Analyzer Available Checkers +`_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.UndefReturn.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.UndefReturn.rst index 057567429d25a..4039cd0f9a112 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.UndefReturn.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/core.uninitialized.UndefReturn.rst @@ -5,6 +5,9 @@ clang-analyzer-core.uninitialized.UndefReturn ============================================= +Check for uninitialized values being returned to the caller. + The clang-analyzer-core.uninitialized.UndefReturn check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.InnerPointer.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.InnerPointer.rst index 660284b61de67..bc7d8a7d27660 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.InnerPointer.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.InnerPointer.rst @@ -1,6 +1,13 @@ .. title:: clang-tidy - clang-analyzer-cplusplus.InnerPointer +.. meta:: + :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#cplusplus-innerpointer clang-analyzer-cplusplus.InnerPointer ===================================== -Check for inner pointers of C++ containers used after re/deallocation +Check for inner pointers of C++ containers used after re/deallocation. + +The clang-analyzer-cplusplus.InnerPointer check is an alias, please see +`Clang Static Analyzer Available Checkers +`_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.Move.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.Move.rst index b0d663d558b3a..e723f21f6bc60 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.Move.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.Move.rst @@ -1,10 +1,9 @@ .. title:: clang-tidy - clang-analyzer-cplusplus.Move -.. meta:: - :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#cplusplus-move clang-analyzer-cplusplus.Move ============================= -The clang-analyzer-cplusplus.Move check is an alias, please see -`Clang Static Analyzer Available Checkers `_ -for more information. +Find use-after-move bugs in C++. + +The clang-analyzer-cplusplus.Move check is an alias of +Clang Static Analyzer cplusplus.Move. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.NewDelete.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.NewDelete.rst index 57964a8c93925..620f1e88da181 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.NewDelete.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.NewDelete.rst @@ -5,6 +5,10 @@ clang-analyzer-cplusplus.NewDelete ================================== +Check for double-free and use-after-free problems. Traces memory managed by +new/delete. + The clang-analyzer-cplusplus.NewDelete check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.NewDeleteLeaks.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.NewDeleteLeaks.rst index 4601a460df168..1f85373511d37 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.NewDeleteLeaks.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.NewDeleteLeaks.rst @@ -5,6 +5,9 @@ clang-analyzer-cplusplus.NewDeleteLeaks ======================================= +Check for memory leaks. Traces memory managed by new/delete. + The clang-analyzer-cplusplus.NewDeleteLeaks check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.PlacementNew.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.PlacementNew.rst new file mode 100644 index 0000000000000..c5d19a7deeb2e --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.PlacementNew.rst @@ -0,0 +1,14 @@ +.. title:: clang-tidy - clang-analyzer-cplusplus.PlacementNew +.. meta:: + :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#cplusplus-placementnew + +clang-analyzer-cplusplus.PlacementNew +===================================== + +Check if default placement new is provided with pointers to sufficient storage +capacity. + +The clang-analyzer-cplusplus.PlacementNew check is an alias, please see +`Clang Static Analyzer Available Checkers +`_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.PureVirtualCall.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.PureVirtualCall.rst new file mode 100644 index 0000000000000..9fab628b80d44 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.PureVirtualCall.rst @@ -0,0 +1,9 @@ +.. title:: clang-tidy - clang-analyzer-cplusplus.PureVirtualCall + +clang-analyzer-cplusplus.PureVirtualCall +======================================== + +Check pure virtual function calls during construction/destruction. + +The clang-analyzer-cplusplus.PureVirtualCall check is an alias of +Clang Static Analyzer cplusplus.PureVirtualCall. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.StringChecker.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.StringChecker.rst new file mode 100644 index 0000000000000..e3d4a511a61a7 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.StringChecker.rst @@ -0,0 +1,13 @@ +.. title:: clang-tidy - clang-analyzer-cplusplus.StringChecker +.. meta:: + :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#cplusplus-stringchecker + +clang-analyzer-cplusplus.StringChecker +====================================== + +Checks C++ std::string bugs. + +The clang-analyzer-cplusplus.StringChecker check is an alias, please see +`Clang Static Analyzer Available Checkers +`_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/deadcode.DeadStores.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/deadcode.DeadStores.rst index 0bb41212f4d20..b421e2cbd3c69 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/deadcode.DeadStores.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/deadcode.DeadStores.rst @@ -5,6 +5,9 @@ clang-analyzer-deadcode.DeadStores ================================== +Check for values stored to variables that are never read afterwards. + The clang-analyzer-deadcode.DeadStores check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/fuchsia.HandleChecker.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/fuchsia.HandleChecker.rst new file mode 100644 index 0000000000000..5f2a3aaae1ed1 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/fuchsia.HandleChecker.rst @@ -0,0 +1,13 @@ +.. title:: clang-tidy - clang-analyzer-fuchsia.HandleChecker +.. meta:: + :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#fuchsia-handlechecker + +clang-analyzer-fuchsia.HandleChecker +==================================== + +A Checker that detect leaks related to Fuchsia handles. + +The clang-analyzer-fuchsia.HandleChecker check is an alias, please see +`Clang Static Analyzer Available Checkers +`_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/nullability.NullPassedToNonnull.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/nullability.NullPassedToNonnull.rst index 7ebbb9b7d6588..85e0dc2f116c5 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/nullability.NullPassedToNonnull.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/nullability.NullPassedToNonnull.rst @@ -5,6 +5,9 @@ clang-analyzer-nullability.NullPassedToNonnull ============================================== +Warns when a null pointer is passed to a pointer which has a _Nonnull type. + The clang-analyzer-nullability.NullPassedToNonnull check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/nullability.NullReturnedFromNonnull.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/nullability.NullReturnedFromNonnull.rst index e585c7ba1826b..132c8311bc1d0 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/nullability.NullReturnedFromNonnull.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/nullability.NullReturnedFromNonnull.rst @@ -5,6 +5,10 @@ clang-analyzer-nullability.NullReturnedFromNonnull ================================================== +Warns when a null pointer is returned from a function that has _Nonnull return +type. + The clang-analyzer-nullability.NullReturnedFromNonnull check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/nullability.NullableDereferenced.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/nullability.NullableDereferenced.rst index 9734863366126..027487b1533ea 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/nullability.NullableDereferenced.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/nullability.NullableDereferenced.rst @@ -5,6 +5,9 @@ clang-analyzer-nullability.NullableDereferenced =============================================== +Warns when a nullable pointer is dereferenced. + The clang-analyzer-nullability.NullableDereferenced check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/nullability.NullablePassedToNonnull.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/nullability.NullablePassedToNonnull.rst index 1c9b590e67d8f..f1261e680595a 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/nullability.NullablePassedToNonnull.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/nullability.NullablePassedToNonnull.rst @@ -5,6 +5,9 @@ clang-analyzer-nullability.NullablePassedToNonnull ================================================== +Warns when a nullable pointer is passed to a pointer which has a _Nonnull type. + The clang-analyzer-nullability.NullablePassedToNonnull check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/nullability.NullableReturnedFromNonnull.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/nullability.NullableReturnedFromNonnull.rst index c30b530a0dec1..dc6f7a1525b80 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/nullability.NullableReturnedFromNonnull.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/nullability.NullableReturnedFromNonnull.rst @@ -1,6 +1,14 @@ .. title:: clang-tidy - clang-analyzer-nullability.NullableReturnedFromNonnull +.. meta:: + :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#nullability-nullablereturnedfromnonnull clang-analyzer-nullability.NullableReturnedFromNonnull ====================================================== -Warns when a nullable pointer is returned from a function that has _Nonnull return type. +Warns when a nullable pointer is returned from a function that has _Nonnull +return type. + +The clang-analyzer-nullability.NullableReturnedFromNonnull check is an alias, please see +`Clang Static Analyzer Available Checkers +`_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.cplusplus.UninitializedObject.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.cplusplus.UninitializedObject.rst index 3380dc3277735..5cf352a23cadc 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.cplusplus.UninitializedObject.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.cplusplus.UninitializedObject.rst @@ -5,6 +5,9 @@ clang-analyzer-optin.cplusplus.UninitializedObject ================================================== +Reports uninitialized fields after object construction. + The clang-analyzer-optin.cplusplus.UninitializedObject check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.cplusplus.VirtualCall.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.cplusplus.VirtualCall.rst index 52cf5ff97db81..5ec5faaec71ee 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.cplusplus.VirtualCall.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.cplusplus.VirtualCall.rst @@ -5,6 +5,9 @@ clang-analyzer-optin.cplusplus.VirtualCall ========================================== +Check virtual function calls during construction/destruction. + The clang-analyzer-optin.cplusplus.VirtualCall check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.mpi.MPI-Checker.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.mpi.MPI-Checker.rst index 211070c5a6e0e..45b1a92fc3378 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.mpi.MPI-Checker.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.mpi.MPI-Checker.rst @@ -5,6 +5,9 @@ clang-analyzer-optin.mpi.MPI-Checker ==================================== +Checks MPI code. + The clang-analyzer-optin.mpi.MPI-Checker check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.osx.OSObjectCStyleCast.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.osx.OSObjectCStyleCast.rst index 65e9efba1b2eb..c2fef59f56894 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.osx.OSObjectCStyleCast.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.osx.OSObjectCStyleCast.rst @@ -3,4 +3,7 @@ clang-analyzer-optin.osx.OSObjectCStyleCast =========================================== -Checker for C-style casts of OSObjects +Checker for C-style casts of OSObjects. + +The clang-analyzer-optin.osx.OSObjectCStyleCast check is an alias of +Clang Static Analyzer optin.osx.OSObjectCStyleCast. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.osx.cocoa.localizability.EmptyLocalizationContextChecker.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.osx.cocoa.localizability.EmptyLocalizationContextChecker.rst index 8a8395c8c8ce9..669f37c365c8e 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.osx.cocoa.localizability.EmptyLocalizationContextChecker.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.osx.cocoa.localizability.EmptyLocalizationContextChecker.rst @@ -5,6 +5,9 @@ clang-analyzer-optin.osx.cocoa.localizability.EmptyLocalizationContextChecker ============================================================================= +Check that NSLocalizedString macros include a comment for context. + The clang-analyzer-optin.osx.cocoa.localizability.EmptyLocalizationContextChecker check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.osx.cocoa.localizability.NonLocalizedStringChecker.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.osx.cocoa.localizability.NonLocalizedStringChecker.rst index dc214719ba73b..3ab5fd847d407 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.osx.cocoa.localizability.NonLocalizedStringChecker.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.osx.cocoa.localizability.NonLocalizedStringChecker.rst @@ -5,6 +5,10 @@ clang-analyzer-optin.osx.cocoa.localizability.NonLocalizedStringChecker ======================================================================= +Warns about uses of non-localized NSStrings passed to UI methods expecting +localized NSStrings. + The clang-analyzer-optin.osx.cocoa.localizability.NonLocalizedStringChecker check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.performance.GCDAntipattern.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.performance.GCDAntipattern.rst index 2684f750091a0..6b1af473c572b 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.performance.GCDAntipattern.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.performance.GCDAntipattern.rst @@ -1,6 +1,13 @@ .. title:: clang-tidy - clang-analyzer-optin.performance.GCDAntipattern +.. meta:: + :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#optin-performance-gcdantipattern clang-analyzer-optin.performance.GCDAntipattern =============================================== -Check for performance anti-patterns when using Grand Central Dispatch +Check for performance anti-patterns when using Grand Central Dispatch. + +The clang-analyzer-optin.performance.GCDAntipattern check is an alias, please see +`Clang Static Analyzer Available Checkers +`_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.performance.Padding.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.performance.Padding.rst index fc2d7300de76a..40e5e65419285 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.performance.Padding.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.performance.Padding.rst @@ -1,6 +1,13 @@ .. title:: clang-tidy - clang-analyzer-optin.performance.Padding +.. meta:: + :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#optin-performance-padding clang-analyzer-optin.performance.Padding ======================================== Check for excessively padded structs. + +The clang-analyzer-optin.performance.Padding check is an alias, please see +`Clang Static Analyzer Available Checkers +`_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.portability.UnixAPI.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.portability.UnixAPI.rst index 07545becaef8e..43dafc841777d 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.portability.UnixAPI.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.portability.UnixAPI.rst @@ -1,6 +1,13 @@ .. title:: clang-tidy - clang-analyzer-optin.portability.UnixAPI +.. meta:: + :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#optin-portability-unixapi clang-analyzer-optin.portability.UnixAPI ======================================== -Finds implementation-defined behavior in UNIX/Posix functions +Finds implementation-defined behavior in UNIX/Posix functions. + +The clang-analyzer-optin.portability.UnixAPI check is an alias, please see +`Clang Static Analyzer Available Checkers +`_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.API.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.API.rst index b3aae0c8bb504..46f0821880d50 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.API.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.API.rst @@ -5,6 +5,9 @@ clang-analyzer-osx.API ====================== +Check for proper uses of various Apple APIs. + The clang-analyzer-osx.API check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.MIG.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.MIG.rst index 50fb5a8db6b0a..a7b8a1cfb14cd 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.MIG.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.MIG.rst @@ -3,4 +3,7 @@ clang-analyzer-osx.MIG ====================== -Find violations of the Mach Interface Generator calling convention +Find violations of the Mach Interface Generator calling convention. + +The clang-analyzer-osx.MIG check is an alias of +Clang Static Analyzer osx.MIG. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.NumberObjectConversion.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.NumberObjectConversion.rst index 7471ad17d7d7d..cc45624987db8 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.NumberObjectConversion.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.NumberObjectConversion.rst @@ -1,6 +1,13 @@ .. title:: clang-tidy - clang-analyzer-osx.NumberObjectConversion +.. meta:: + :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#osx-numberobjectconversion clang-analyzer-osx.NumberObjectConversion ========================================= -Check for erroneous conversions of objects representing numbers into numbers +Check for erroneous conversions of objects representing numbers into numbers. + +The clang-analyzer-osx.NumberObjectConversion check is an alias, please see +`Clang Static Analyzer Available Checkers +`_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.OSObjectRetainCount.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.OSObjectRetainCount.rst index 8eceb3f3b4dd1..c32982d407c28 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.OSObjectRetainCount.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.OSObjectRetainCount.rst @@ -3,4 +3,7 @@ clang-analyzer-osx.OSObjectRetainCount ====================================== -Check for leaks and improper reference count management for OSObject +Check for leaks and improper reference count management for OSObject. + +The clang-analyzer-osx.OSObjectRetainCount check is an alias of +Clang Static Analyzer osx.OSObjectRetainCount. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.ObjCProperty.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.ObjCProperty.rst index 0b87cd0207825..8df48b78ca2bc 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.ObjCProperty.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.ObjCProperty.rst @@ -1,6 +1,13 @@ .. title:: clang-tidy - clang-analyzer-osx.ObjCProperty +.. meta:: + :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#osx-objcproperty clang-analyzer-osx.ObjCProperty =============================== -Check for proper uses of Objective-C properties +Check for proper uses of Objective-C properties. + +The clang-analyzer-osx.ObjCProperty check is an alias, please see +`Clang Static Analyzer Available Checkers +`_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.SecKeychainAPI.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.SecKeychainAPI.rst index 130fae59a677b..4d6f6a1684111 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.SecKeychainAPI.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.SecKeychainAPI.rst @@ -5,6 +5,9 @@ clang-analyzer-osx.SecKeychainAPI ================================= +Check for proper uses of Secure Keychain APIs. + The clang-analyzer-osx.SecKeychainAPI check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.AtSync.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.AtSync.rst index 56a98bfb9a2e1..60e4022ff9915 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.AtSync.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.AtSync.rst @@ -5,6 +5,9 @@ clang-analyzer-osx.cocoa.AtSync =============================== +Check for nil pointers used as mutexes for @synchronized. + The clang-analyzer-osx.cocoa.AtSync check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.AutoreleaseWrite.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.AutoreleaseWrite.rst index 01fbe4f84368f..1cca7bb9238e6 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.AutoreleaseWrite.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.AutoreleaseWrite.rst @@ -1,6 +1,14 @@ .. title:: clang-tidy - clang-analyzer-osx.cocoa.AutoreleaseWrite +.. meta:: + :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#osx-cocoa-autoreleasewrite clang-analyzer-osx.cocoa.AutoreleaseWrite ========================================= -Warn about potentially crashing writes to autoreleasing objects from different autoreleasing pools in Objective-C +Warn about potentially crashing writes to autoreleasing objects from different +autoreleasing pools in Objective-C. + +The clang-analyzer-osx.cocoa.AutoreleaseWrite check is an alias, please see +`Clang Static Analyzer Available Checkers +`_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.ClassRelease.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.ClassRelease.rst index d6c0bae27ead7..3cf78ab874f3b 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.ClassRelease.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.ClassRelease.rst @@ -5,6 +5,9 @@ clang-analyzer-osx.cocoa.ClassRelease ===================================== +Check for sending 'retain', 'release', or 'autorelease' directly to a Class. + The clang-analyzer-osx.cocoa.ClassRelease check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.Dealloc.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.Dealloc.rst index e02bf63b9a33b..acaf11442b0e2 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.Dealloc.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.Dealloc.rst @@ -5,6 +5,9 @@ clang-analyzer-osx.cocoa.Dealloc ================================ +Warn about Objective-C classes that lack a correct implementation of -dealloc. + The clang-analyzer-osx.cocoa.Dealloc check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.IncompatibleMethodTypes.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.IncompatibleMethodTypes.rst index 6aa64e209746e..17e13f582c0f6 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.IncompatibleMethodTypes.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.IncompatibleMethodTypes.rst @@ -5,6 +5,9 @@ clang-analyzer-osx.cocoa.IncompatibleMethodTypes ================================================ +Warn about Objective-C method signatures with type incompatibilities. + The clang-analyzer-osx.cocoa.IncompatibleMethodTypes check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.Loops.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.Loops.rst index 622f80ff87106..2ee092bbf8f00 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.Loops.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.Loops.rst @@ -1,6 +1,13 @@ .. title:: clang-tidy - clang-analyzer-osx.cocoa.Loops +.. meta:: + :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#osx-cocoa-loops clang-analyzer-osx.cocoa.Loops ============================== -Improved modeling of loops using Cocoa collection types +Improved modeling of loops using Cocoa collection types. + +The clang-analyzer-osx.cocoa.Loops check is an alias, please see +`Clang Static Analyzer Available Checkers +`_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.MissingSuperCall.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.MissingSuperCall.rst index a8e4290278a9f..ee57d1d86f100 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.MissingSuperCall.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.MissingSuperCall.rst @@ -1,6 +1,13 @@ .. title:: clang-tidy - clang-analyzer-osx.cocoa.MissingSuperCall +.. meta:: + :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#osx-cocoa-missingsupercall clang-analyzer-osx.cocoa.MissingSuperCall ========================================= -Warn about Objective-C methods that lack a necessary call to super +Warn about Objective-C methods that lack a necessary call to super. + +The clang-analyzer-osx.cocoa.MissingSuperCall check is an alias, please see +`Clang Static Analyzer Available Checkers +`_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.NSAutoreleasePool.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.NSAutoreleasePool.rst index 9446850c45881..0c10069041604 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.NSAutoreleasePool.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.NSAutoreleasePool.rst @@ -5,6 +5,9 @@ clang-analyzer-osx.cocoa.NSAutoreleasePool ========================================== +Warn for suboptimal uses of NSAutoreleasePool in Objective-C GC mode. + The clang-analyzer-osx.cocoa.NSAutoreleasePool check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.NSError.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.NSError.rst index 23416fcf8688d..35fddde39d8db 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.NSError.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.NSError.rst @@ -5,6 +5,9 @@ clang-analyzer-osx.cocoa.NSError ================================ +Check usage of NSError** parameters. + The clang-analyzer-osx.cocoa.NSError check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.NilArg.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.NilArg.rst index 4b521041976cf..0e189a1d9d1d8 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.NilArg.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.NilArg.rst @@ -5,6 +5,9 @@ clang-analyzer-osx.cocoa.NilArg =============================== +Check for prohibited nil arguments to ObjC method calls. + The clang-analyzer-osx.cocoa.NilArg check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.NonNilReturnValue.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.NonNilReturnValue.rst index a6da9b0cca491..aafdd3dc27f5c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.NonNilReturnValue.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.NonNilReturnValue.rst @@ -1,6 +1,13 @@ .. title:: clang-tidy - clang-analyzer-osx.cocoa.NonNilReturnValue +.. meta:: + :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#osx-cocoa-nonnilreturnvalue clang-analyzer-osx.cocoa.NonNilReturnValue ========================================== -Model the APIs that are guaranteed to return a non-nil value +Model the APIs that are guaranteed to return a non-nil value. + +The clang-analyzer-osx.cocoa.NonNilReturnValue check is an alias, please see +`Clang Static Analyzer Available Checkers +`_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.ObjCGenerics.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.ObjCGenerics.rst index 10e21e30a5ea3..d27a492cb224e 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.ObjCGenerics.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.ObjCGenerics.rst @@ -5,6 +5,9 @@ clang-analyzer-osx.cocoa.ObjCGenerics ===================================== +Check for type errors when using Objective-C generics. + The clang-analyzer-osx.cocoa.ObjCGenerics check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.RetainCount.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.RetainCount.rst index 92a72df785fad..d0e71e8a823bf 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.RetainCount.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.RetainCount.rst @@ -5,6 +5,9 @@ clang-analyzer-osx.cocoa.RetainCount ==================================== +Check for leaks and improper reference count management. + The clang-analyzer-osx.cocoa.RetainCount check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.RunLoopAutoreleaseLeak.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.RunLoopAutoreleaseLeak.rst index 67a0519b9b777..3b2e433964e77 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.RunLoopAutoreleaseLeak.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.RunLoopAutoreleaseLeak.rst @@ -1,6 +1,13 @@ .. title:: clang-tidy - clang-analyzer-osx.cocoa.RunLoopAutoreleaseLeak +.. meta:: + :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#osx-cocoa-runloopautoreleaseleak clang-analyzer-osx.cocoa.RunLoopAutoreleaseLeak =============================================== -Check for leaked memory in autorelease pools that will never be drained +Check for leaked memory in autorelease pools that will never be drained. + +The clang-analyzer-osx.cocoa.RunLoopAutoreleaseLeak check is an alias, please see +`Clang Static Analyzer Available Checkers +`_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.SelfInit.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.SelfInit.rst index 96e559e103a35..a5484f2ad8c7f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.SelfInit.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.SelfInit.rst @@ -5,6 +5,9 @@ clang-analyzer-osx.cocoa.SelfInit ================================= +Check that 'self' is properly initialized inside an initializer method. + The clang-analyzer-osx.cocoa.SelfInit check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.SuperDealloc.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.SuperDealloc.rst index 598f12686b42c..ab13b6ab3289b 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.SuperDealloc.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.SuperDealloc.rst @@ -5,6 +5,9 @@ clang-analyzer-osx.cocoa.SuperDealloc ===================================== +Warn about improper use of '[super dealloc]' in Objective-C. + The clang-analyzer-osx.cocoa.SuperDealloc check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.UnusedIvars.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.UnusedIvars.rst index 5a12aa4802c96..cb3ffd1d870eb 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.UnusedIvars.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.UnusedIvars.rst @@ -5,6 +5,9 @@ clang-analyzer-osx.cocoa.UnusedIvars ==================================== +Warn about private ivars that are never used. + The clang-analyzer-osx.cocoa.UnusedIvars check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.VariadicMethodTypes.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.VariadicMethodTypes.rst index 292e7e3fd1c08..fd9405451a427 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.VariadicMethodTypes.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.cocoa.VariadicMethodTypes.rst @@ -5,6 +5,10 @@ clang-analyzer-osx.cocoa.VariadicMethodTypes ============================================ +Check for passing non-Objective-C types to variadic collection initialization +methods that expect only Objective-C types. + The clang-analyzer-osx.cocoa.VariadicMethodTypes check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.coreFoundation.CFError.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.coreFoundation.CFError.rst index 7dab4bdabda31..200ec6232bcc2 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.coreFoundation.CFError.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.coreFoundation.CFError.rst @@ -5,6 +5,9 @@ clang-analyzer-osx.coreFoundation.CFError ========================================= +Check usage of CFErrorRef* parameters. + The clang-analyzer-osx.coreFoundation.CFError check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.coreFoundation.CFNumber.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.coreFoundation.CFNumber.rst index 86e117a72f8b3..83a0541e0e32c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.coreFoundation.CFNumber.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.coreFoundation.CFNumber.rst @@ -5,6 +5,9 @@ clang-analyzer-osx.coreFoundation.CFNumber ========================================== +Check for proper uses of CFNumber APIs. + The clang-analyzer-osx.coreFoundation.CFNumber check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.coreFoundation.CFRetainRelease.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.coreFoundation.CFRetainRelease.rst index 0865611b5df61..766993900d364 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.coreFoundation.CFRetainRelease.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.coreFoundation.CFRetainRelease.rst @@ -5,6 +5,9 @@ clang-analyzer-osx.coreFoundation.CFRetainRelease ================================================= +Check for null arguments to CFRetain/CFRelease/CFMakeCollectable. + The clang-analyzer-osx.coreFoundation.CFRetainRelease check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.coreFoundation.containers.OutOfBounds.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.coreFoundation.containers.OutOfBounds.rst index ca1eb756eace6..e8fb9ea806f68 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.coreFoundation.containers.OutOfBounds.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.coreFoundation.containers.OutOfBounds.rst @@ -5,6 +5,9 @@ clang-analyzer-osx.coreFoundation.containers.OutOfBounds ======================================================== +Checks for index out-of-bounds when using 'CFArray' API. + The clang-analyzer-osx.coreFoundation.containers.OutOfBounds check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.coreFoundation.containers.PointerSizedValues.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.coreFoundation.containers.PointerSizedValues.rst index fb1fa15f96267..57370934eae6f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.coreFoundation.containers.PointerSizedValues.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/osx.coreFoundation.containers.PointerSizedValues.rst @@ -5,6 +5,10 @@ clang-analyzer-osx.coreFoundation.containers.PointerSizedValues =============================================================== +Warns if 'CFArray', 'CFDictionary', 'CFSet' are created with non-pointer-size +values. + The clang-analyzer-osx.coreFoundation.containers.PointerSizedValues check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.FloatLoopCounter.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.FloatLoopCounter.rst index b378a34b9f7da..a39f4ae66f032 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.FloatLoopCounter.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.FloatLoopCounter.rst @@ -5,6 +5,10 @@ clang-analyzer-security.FloatLoopCounter ======================================== +Warn on using a floating point value as a loop counter (CERT: FLP30-C, +FLP30-CPP). + The clang-analyzer-security.FloatLoopCounter check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.DeprecatedOrUnsafeBufferHandling.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.DeprecatedOrUnsafeBufferHandling.rst index b4e611b265318..c7c035ecec6ae 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.DeprecatedOrUnsafeBufferHandling.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.DeprecatedOrUnsafeBufferHandling.rst @@ -5,6 +5,9 @@ clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling ==================================================================== +Warn on uses of unsecure or deprecated buffer manipulating functions. + The clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.UncheckedReturn.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.UncheckedReturn.rst index 9f050da3509e1..52b03170e0842 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.UncheckedReturn.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.UncheckedReturn.rst @@ -5,6 +5,9 @@ clang-analyzer-security.insecureAPI.UncheckedReturn =================================================== +Warn on uses of functions whose return values must be always checked. + The clang-analyzer-security.insecureAPI.UncheckedReturn check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.bcmp.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.bcmp.rst index a135ee7f20532..26412c0c2cdc2 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.bcmp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.bcmp.rst @@ -5,6 +5,9 @@ clang-analyzer-security.insecureAPI.bcmp ======================================== +Warn on uses of the 'bcmp' function. + The clang-analyzer-security.insecureAPI.bcmp check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.bcopy.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.bcopy.rst index fc8d2349a09e8..73894233661d8 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.bcopy.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.bcopy.rst @@ -5,6 +5,9 @@ clang-analyzer-security.insecureAPI.bcopy ========================================= +Warn on uses of the 'bcopy' function. + The clang-analyzer-security.insecureAPI.bcopy check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.bzero.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.bzero.rst index c74c2d186cb73..5626015234c5b 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.bzero.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.bzero.rst @@ -5,6 +5,9 @@ clang-analyzer-security.insecureAPI.bzero ========================================= +Warn on uses of the 'bzero' function. + The clang-analyzer-security.insecureAPI.bzero check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.decodeValueOfObjCType.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.decodeValueOfObjCType.rst new file mode 100644 index 0000000000000..4405f721a66dd --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.decodeValueOfObjCType.rst @@ -0,0 +1,9 @@ +.. title:: clang-tidy - clang-analyzer-security.insecureAPI.decodeValueOfObjCType + +clang-analyzer-security.insecureAPI.decodeValueOfObjCType +========================================================= + +Warn on uses of the '-decodeValueOfObjCType:at:' method. + +The clang-analyzer-security.insecureAPI.decodeValueOfObjCType check is an alias of +Clang Static Analyzer security.insecureAPI.decodeValueOfObjCType. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.getpw.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.getpw.rst index 4f2b79666f681..0bac901c623ad 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.getpw.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.getpw.rst @@ -5,6 +5,9 @@ clang-analyzer-security.insecureAPI.getpw ========================================= +Warn on uses of the 'getpw' function. + The clang-analyzer-security.insecureAPI.getpw check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.gets.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.gets.rst index fc62fe6245e89..7f9cf4ff32dcb 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.gets.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.gets.rst @@ -5,6 +5,9 @@ clang-analyzer-security.insecureAPI.gets ======================================== +Warn on uses of the 'gets' function. + The clang-analyzer-security.insecureAPI.gets check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.mkstemp.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.mkstemp.rst index 6c0d8110ac287..54349760ed584 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.mkstemp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.mkstemp.rst @@ -5,6 +5,9 @@ clang-analyzer-security.insecureAPI.mkstemp =========================================== +Warn when 'mkstemp' is passed fewer than 6 X's in the format string. + The clang-analyzer-security.insecureAPI.mkstemp check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.mktemp.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.mktemp.rst index 153904f08797c..5d04ffecbd1df 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.mktemp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.mktemp.rst @@ -5,6 +5,9 @@ clang-analyzer-security.insecureAPI.mktemp ========================================== +Warn on uses of the 'mktemp' function. + The clang-analyzer-security.insecureAPI.mktemp check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.rand.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.rand.rst index 67c4c87c17397..634898bf40eb0 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.rand.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.rand.rst @@ -5,6 +5,9 @@ clang-analyzer-security.insecureAPI.rand ======================================== +Warn on uses of the 'rand', 'random', and related functions. + The clang-analyzer-security.insecureAPI.rand check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.strcpy.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.strcpy.rst index 1fcbe160e6b8e..608bb5841a592 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.strcpy.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.strcpy.rst @@ -5,6 +5,9 @@ clang-analyzer-security.insecureAPI.strcpy ========================================== +Warn on uses of the 'strcpy' and 'strcat' functions. + The clang-analyzer-security.insecureAPI.strcpy check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.vfork.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.vfork.rst index c20dea356add0..d65307855824d 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.vfork.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.insecureAPI.vfork.rst @@ -5,6 +5,9 @@ clang-analyzer-security.insecureAPI.vfork ========================================= +Warn on uses of the 'vfork' function. + The clang-analyzer-security.insecureAPI.vfork check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.API.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.API.rst index a3931b2b027ee..02438ad635f62 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.API.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.API.rst @@ -5,6 +5,9 @@ clang-analyzer-unix.API ======================= +Check calls to various UNIX/Posix functions. + The clang-analyzer-unix.API check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.Malloc.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.Malloc.rst index f772674ed5481..949b9164b6bfd 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.Malloc.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.Malloc.rst @@ -5,6 +5,10 @@ clang-analyzer-unix.Malloc ========================== +Check for memory leaks, double free, and use-after-free problems. Traces memory +managed by malloc()/free(). + The clang-analyzer-unix.Malloc check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.MallocSizeof.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.MallocSizeof.rst index 3cc066b219c30..c33f6d3f6728f 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.MallocSizeof.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.MallocSizeof.rst @@ -5,6 +5,9 @@ clang-analyzer-unix.MallocSizeof ================================ +Check for dubious malloc arguments involving sizeof. + The clang-analyzer-unix.MallocSizeof check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.MismatchedDeallocator.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.MismatchedDeallocator.rst index 01fc56933b20d..c14e0e2873b2b 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.MismatchedDeallocator.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.MismatchedDeallocator.rst @@ -5,6 +5,9 @@ clang-analyzer-unix.MismatchedDeallocator ========================================= +Check for mismatched deallocators. + The clang-analyzer-unix.MismatchedDeallocator check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.Vfork.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.Vfork.rst index d3f00afe5099e..f4bc2a32cae40 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.Vfork.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.Vfork.rst @@ -5,6 +5,9 @@ clang-analyzer-unix.Vfork ========================= +Check for proper usage of vfork. + The clang-analyzer-unix.Vfork check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.cstring.BadSizeArg.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.cstring.BadSizeArg.rst index d861faa3ff085..c388c15f5f084 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.cstring.BadSizeArg.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.cstring.BadSizeArg.rst @@ -5,6 +5,10 @@ clang-analyzer-unix.cstring.BadSizeArg ====================================== +Check the size argument passed into C string functions for common erroneous +patterns. + The clang-analyzer-unix.cstring.BadSizeArg check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.cstring.NullArg.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.cstring.NullArg.rst index 17bb6af8a5fa4..98a150dfe7cff 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.cstring.NullArg.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.cstring.NullArg.rst @@ -5,6 +5,9 @@ clang-analyzer-unix.cstring.NullArg =================================== +Check for null pointers being passed as arguments to C string functions. + The clang-analyzer-unix.cstring.NullArg check is an alias, please see -`Clang Static Analyzer Available Checkers `_ +`Clang Static Analyzer Available Checkers +`_ for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/valist.CopyToSelf.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/valist.CopyToSelf.rst index d693705d0c6ef..d0c82abd81901 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/valist.CopyToSelf.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/valist.CopyToSelf.rst @@ -4,3 +4,6 @@ clang-analyzer-valist.CopyToSelf ================================ Check for va_lists which are copied onto itself. + +The clang-analyzer-valist.CopyToSelf check is an alias of +Clang Static Analyzer valist.CopyToSelf. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/valist.Uninitialized.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/valist.Uninitialized.rst index da3f5dbb1641c..98b5dd023254a 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/valist.Uninitialized.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/valist.Uninitialized.rst @@ -4,3 +4,6 @@ clang-analyzer-valist.Uninitialized =================================== Check for usages of uninitialized (or already released) va_lists. + +The clang-analyzer-valist.Uninitialized check is an alias of +Clang Static Analyzer valist.Uninitialized. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/valist.Unterminated.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/valist.Unterminated.rst index d73688b0e1c50..85e21c5721063 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/valist.Unterminated.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/valist.Unterminated.rst @@ -4,3 +4,6 @@ clang-analyzer-valist.Unterminated ================================== Check for va_lists which are not released by a va_end call. + +The clang-analyzer-valist.Unterminated check is an alias of +Clang Static Analyzer valist.Unterminated. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/webkit.NoUncountedMemberChecker.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/webkit.NoUncountedMemberChecker.rst new file mode 100644 index 0000000000000..36003280718c7 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/webkit.NoUncountedMemberChecker.rst @@ -0,0 +1,13 @@ +.. title:: clang-tidy - clang-analyzer-webkit.NoUncountedMemberChecker +.. meta:: + :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#webkit-nouncountedmemberchecker + +clang-analyzer-webkit.NoUncountedMemberChecker +============================================== + +Check for no uncounted member variables. + +The clang-analyzer-webkit.NoUncountedMemberChecker check is an alias, please see +`Clang Static Analyzer Available Checkers +`_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/webkit.RefCntblBaseVirtualDtor.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/webkit.RefCntblBaseVirtualDtor.rst new file mode 100644 index 0000000000000..b88df7d86e674 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/webkit.RefCntblBaseVirtualDtor.rst @@ -0,0 +1,13 @@ +.. title:: clang-tidy - clang-analyzer-webkit.RefCntblBaseVirtualDtor +.. meta:: + :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#webkit-refcntblbasevirtualdtor + +clang-analyzer-webkit.RefCntblBaseVirtualDtor +============================================= + +Check for any ref-countable base class having virtual destructor. + +The clang-analyzer-webkit.RefCntblBaseVirtualDtor check is an alias, please see +`Clang Static Analyzer Available Checkers +`_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/webkit.UncountedLambdaCapturesChecker.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/webkit.UncountedLambdaCapturesChecker.rst new file mode 100644 index 0000000000000..1022b434c8d4e --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/webkit.UncountedLambdaCapturesChecker.rst @@ -0,0 +1,13 @@ +.. title:: clang-tidy - clang-analyzer-webkit.UncountedLambdaCapturesChecker +.. meta:: + :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#webkit-uncountedlambdacaptureschecker + +clang-analyzer-webkit.UncountedLambdaCapturesChecker +==================================================== + +Check uncounted lambda captures. + +The clang-analyzer-webkit.UncountedLambdaCapturesChecker check is an alias, please see +`Clang Static Analyzer Available Checkers +`_ +for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/no-suspend-with-lock.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/no-suspend-with-lock.rst new file mode 100644 index 0000000000000..59981f2c8d6d3 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/no-suspend-with-lock.rst @@ -0,0 +1,40 @@ +.. title:: clang-tidy - cppcoreguidelines-no-suspend-with-lock + +cppcoreguidelines-no-suspend-with-lock +====================================== + +Flags coroutines that suspend while a lock guard is in scope at the +suspension point. + +When a coroutine suspends, any mutexes held by the coroutine will remain +locked until the coroutine resumes and eventually destructs the lock guard. +This can lead to long periods with a mutex held and runs the risk of deadlock. + +Instead, locks should be released before suspending a coroutine. + +This check only checks suspending coroutines while a lock_guard is in scope; +it does not consider manual locking or unlocking of mutexes, e.g., through +calls to ``std::mutex::lock()``. + +Examples: + +.. code-block:: c++ + + future bad_coro() { + std::lock_guard lock{mtx}; + ++some_counter; + co_await something(); // Suspending while holding a mutex + } + + future good_coro() { + { + std::lock_guard lock{mtx}; + ++some_counter; + } + // Destroy the lock_guard to release the mutex before suspending the coroutine + co_await something(); // Suspending while holding a mutex + } + +This check implements `CP.52 +`_ +from the C++ Core Guidelines. diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-vararg.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-vararg.rst index 823b0eaaad382..e74b00694630b 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-vararg.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-type-vararg.rst @@ -7,7 +7,8 @@ This check flags all calls to c-style vararg functions and all use of ``va_arg``. To allow for SFINAE use of vararg functions, a call is not flagged if a literal -0 is passed as the only vararg argument. +0 is passed as the only vararg argument or function is used in unevaluated +context. Passing to varargs assumes the correct type will be read. This is fragile because it cannot generally be enforced to be safe in the language and so relies diff --git a/clang-tools-extra/docs/clang-tidy/checks/gen-static-analyzer-docs.py b/clang-tools-extra/docs/clang-tidy/checks/gen-static-analyzer-docs.py index 1e54cd53bc455..92b89c1c17398 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/gen-static-analyzer-docs.py +++ b/clang-tools-extra/docs/clang-tidy/checks/gen-static-analyzer-docs.py @@ -3,7 +3,6 @@ References Checkers.td to determine what checks exist """ -import argparse import subprocess import json import os @@ -12,28 +11,31 @@ """Get path of script so files are always in correct directory""" __location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__))) +default_checkers_td_location = "../../../../clang/include/clang/StaticAnalyzer/Checkers/Checkers.td" +default_checkers_rst_location = "../../../../clang/docs/analyzer/checkers.rst" + """Get dict of checker related info and parse for full check names Returns: checkers: dict of checker info """ - - -def get_checkers(checkers_td_directory): +def get_checkers(checkers_td, checkers_rst): p = subprocess.Popen( [ "llvm-tblgen", "--dump-json", "-I", - checkers_td_directory, - checkers_td_directory + "Checkers.td", + os.path.dirname(checkers_td), + checkers_td, ], stdout=subprocess.PIPE, ) table_entries = json.loads(p.communicate()[0]) documentable_checkers = [] checkers = table_entries["!instanceof"]["Checker"] - packages = table_entries["!instanceof"]["Package"] + + with open(checkers_rst, "r") as f: + checker_rst_text = f.read() for checker_ in checkers: checker = table_entries[checker_] @@ -62,7 +64,9 @@ def get_checkers(checkers_td_directory): if not hidden and "alpha" not in full_package_name.lower(): checker["FullPackageName"] = full_package_name + checker["ShortName"] = checker_package_prefix + "." + checker_name checker["AnchorUrl"] = anchor_url + checker["Documentation"] = ".. _%s:" % (checker["ShortName"].replace(".","-")) in checker_rst_text documentable_checkers.append(checker) documentable_checkers.sort(key=lambda x: x["FullPackageName"]) @@ -73,17 +77,15 @@ def get_checkers(checkers_td_directory): Args: checker: Checker for which to generate documentation. - only_help_text: Generate documentation based off the checker description. - Used when there is no other documentation to link to. + has_documentation: Specify that there is other documentation to link to. """ +def generate_documentation(checker, has_documentation): - -def generate_documentation(checker, only_help_text=False): with open( - os.path.join(__location__, checker["FullPackageName"] + ".rst"), "w" + os.path.join(__location__, "clang-analyzer", checker["ShortName"] + ".rst"), "w" ) as f: f.write(".. title:: clang-tidy - %s\n" % checker["FullPackageName"]) - if not only_help_text: + if has_documentation: f.write(".. meta::\n") f.write( " :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#%s\n" @@ -92,18 +94,31 @@ def generate_documentation(checker, only_help_text=False): f.write("\n") f.write("%s\n" % checker["FullPackageName"]) f.write("=" * len(checker["FullPackageName"]) + "\n") - f.write("\n") - if only_help_text: - f.write("%s\n" % checker["HelpText"]) - else: + help_text = checker["HelpText"].strip() + if not help_text.endswith("."): + help_text += "." + characters = 80 + for word in help_text.split(" "): + if characters+len(word)+1 > 80: + characters = len(word) + f.write("\n") + f.write(word) + else: + f.write(" ") + f.write(word) + characters += len(word) + 1 + f.write("\n\n") + if has_documentation: f.write( "The %s check is an alias, please see\n" % checker["FullPackageName"] ) f.write( - "`Clang Static Analyzer Available Checkers `_\n" + "`Clang Static Analyzer Available Checkers\n`_\n" % checker["AnchorUrl"] ) f.write("for more information.\n") + else: + f.write("The %s check is an alias of\nClang Static Analyzer %s.\n" % (checker["FullPackageName"], checker["ShortName"])); f.close() @@ -112,70 +127,44 @@ def generate_documentation(checker, only_help_text=False): Args: checkers: dict acquired from get_checkers() """ - - def update_documentation_list(checkers): with open(os.path.join(__location__, "list.rst"), "r+") as f: f_text = f.read() - header, check_text = f_text.split(".. toctree::\n") - checks = check_text.split("\n") + check_text = f_text.split(".. csv-table:: Aliases..\n")[1] + checks = [x for x in check_text.split("\n") if ":header:" not in x and x] + old_check_text = "\n".join(checks) + checks = [x for x in checks if "clang-analyzer-" not in x] for checker in checkers: - if (" %s" % checker["FullPackageName"]) not in checks: - checks.append(" %s" % checker["FullPackageName"]) + if checker["Documentation"]: + checks.append(" `%s `_, `Clang Static Analyzer %s `_," % (checker["FullPackageName"], + checker["ShortName"], checker["ShortName"], checker["AnchorUrl"])) + else: + checks.append(" `%s `_, Clang Static Analyzer %s," % (checker["FullPackageName"], checker["ShortName"], checker["ShortName"])) + checks.sort() # Overwrite file with new data f.seek(0) - f.write(header) - f.write(".. toctree::") - for check in checks: - f.write("%s\n" % check) + f_text = f_text.replace(old_check_text, "\n".join(checks)) + f.write(f_text) f.close() -default_path_monorepo = "../../../../clang/include/clang/StaticAnalyzer/Checkers/" -default_path_in_tree = "../../../../../include/clang/StaticAnalyzer/Checkers/" - - -def parse_arguments(): - """Set up and parse command-line arguments - Returns: - file_path: Path to Checkers.td""" - usage = """Parse Checkers.td to generate documentation for static analyzer checks""" - parse = argparse.ArgumentParser(description=usage) - - file_path_help = """Path to Checkers directory - defaults to ../../../../clang/include/clang/StaticAnalyzer/Checkers/ if it exists - then to ../../../../../include/clang/StaticAnalyzer/Checkers/""" - - default_path = None - if os.path.exists(default_path_monorepo): - default_path = default_path_monorepo - elif os.path.exists(default_path_in_tree): - default_path = default_path_in_tree - - parse.add_argument( - "file", type=str, help=file_path_help, nargs="?", default=default_path - ) - args = parse.parse_args() - - if args.file is None: - print("Could not find Checkers directory. Please see -h") +def main(): + CheckersPath = os.path.join(__location__, default_checkers_td_location) + if not os.path.exists(CheckersPath): + print("Could not find Checkers.td under %s." % (os.path.abspath(CheckersPath))) exit(1) - return args.file - + CheckersDoc = os.path.join(__location__, default_checkers_rst_location) + if not os.path.exists(CheckersDoc): + print("Could not find checkers.rst under %s." % (os.path.abspath(CheckersDoc))) + exit(1) -def main(): - file_path = parse_arguments() - checkers = get_checkers(file_path) + checkers = get_checkers(CheckersPath, CheckersDoc) for checker in checkers: - # No documentation nor alpha documentation - if checker["Documentation"][1] == 0 and checker["Documentation"][0] == 0: - generate_documentation(checker, True) - else: - generate_documentation(checker) - print("Generated documentation for: %s" % checker["FullPackageName"]) + generate_documentation(checker, checker["Documentation"]) + print("Generated documentation for: %s" % (checker["FullPackageName"])) update_documentation_list(checkers) diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index 2e2fe0dfa51fe..bbacd7458c6c3 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -165,26 +165,6 @@ Clang-Tidy Checks `cert-msc51-cpp `_, `cert-oop57-cpp `_, `cert-oop58-cpp `_, - `clang-analyzer-core.DynamicTypePropagation `_, - `clang-analyzer-core.uninitialized.CapturedBlockVariable `_, - `clang-analyzer-cplusplus.InnerPointer `_, - `clang-analyzer-nullability.NullableReturnedFromNonnull `_, - `clang-analyzer-optin.osx.OSObjectCStyleCast `_, - `clang-analyzer-optin.performance.GCDAntipattern `_, - `clang-analyzer-optin.performance.Padding `_, - `clang-analyzer-optin.portability.UnixAPI `_, - `clang-analyzer-osx.MIG `_, - `clang-analyzer-osx.NumberObjectConversion `_, - `clang-analyzer-osx.OSObjectRetainCount `_, - `clang-analyzer-osx.ObjCProperty `_, - `clang-analyzer-osx.cocoa.AutoreleaseWrite `_, - `clang-analyzer-osx.cocoa.Loops `_, - `clang-analyzer-osx.cocoa.MissingSuperCall `_, - `clang-analyzer-osx.cocoa.NonNilReturnValue `_, - `clang-analyzer-osx.cocoa.RunLoopAutoreleaseLeak `_, - `clang-analyzer-valist.CopyToSelf `_, - `clang-analyzer-valist.Uninitialized `_, - `clang-analyzer-valist.Unterminated `_, `concurrency-mt-unsafe `_, `concurrency-thread-canceltype-asynchronous `_, `cppcoreguidelines-avoid-capturing-lambda-coroutines `_, @@ -200,6 +180,7 @@ Clang-Tidy Checks `cppcoreguidelines-missing-std-forward `_, `cppcoreguidelines-narrowing-conversions `_, `cppcoreguidelines-no-malloc `_, + `cppcoreguidelines-no-suspend-with-lock `_, `cppcoreguidelines-owning-memory `_, `cppcoreguidelines-prefer-member-initializer `_, "Yes" `cppcoreguidelines-pro-bounds-array-to-pointer-decay `_, @@ -254,7 +235,7 @@ Clang-Tidy Checks `llvm-twine-local `_, "Yes" `llvmlibc-callee-namespace `_, `llvmlibc-implementation-in-namespace `_, - `llvmlibc-inline-function-decl `_, + `llvmlibc-inline-function-decl `_, "Yes" `llvmlibc-restrict-system-libc-headers `_, "Yes" `misc-confusable-identifiers `_, `misc-const-correctness `_, "Yes" @@ -433,31 +414,52 @@ Clang-Tidy Checks `clang-analyzer-core.uninitialized.ArraySubscript `_, `Clang Static Analyzer core.uninitialized.ArraySubscript `_, `clang-analyzer-core.uninitialized.Assign `_, `Clang Static Analyzer core.uninitialized.Assign `_, `clang-analyzer-core.uninitialized.Branch `_, `Clang Static Analyzer core.uninitialized.Branch `_, + `clang-analyzer-core.uninitialized.CapturedBlockVariable `_, `Clang Static Analyzer core.uninitialized.CapturedBlockVariable `_, + `clang-analyzer-core.uninitialized.NewArraySize `_, `Clang Static Analyzer core.uninitialized.NewArraySize `_, `clang-analyzer-core.uninitialized.UndefReturn `_, `Clang Static Analyzer core.uninitialized.UndefReturn `_, - `clang-analyzer-cplusplus.Move `_, `Clang Static Analyzer cplusplus.Move `_, + `clang-analyzer-cplusplus.InnerPointer `_, `Clang Static Analyzer cplusplus.InnerPointer `_, + `clang-analyzer-cplusplus.Move `_, Clang Static Analyzer cplusplus.Move, `clang-analyzer-cplusplus.NewDelete `_, `Clang Static Analyzer cplusplus.NewDelete `_, `clang-analyzer-cplusplus.NewDeleteLeaks `_, `Clang Static Analyzer cplusplus.NewDeleteLeaks `_, + `clang-analyzer-cplusplus.PlacementNew `_, `Clang Static Analyzer cplusplus.PlacementNew `_, + `clang-analyzer-cplusplus.PureVirtualCall `_, Clang Static Analyzer cplusplus.PureVirtualCall, + `clang-analyzer-cplusplus.StringChecker `_, `Clang Static Analyzer cplusplus.StringChecker `_, `clang-analyzer-deadcode.DeadStores `_, `Clang Static Analyzer deadcode.DeadStores `_, + `clang-analyzer-fuchsia.HandleChecker `_, `Clang Static Analyzer fuchsia.HandleChecker `_, `clang-analyzer-nullability.NullPassedToNonnull `_, `Clang Static Analyzer nullability.NullPassedToNonnull `_, `clang-analyzer-nullability.NullReturnedFromNonnull `_, `Clang Static Analyzer nullability.NullReturnedFromNonnull `_, `clang-analyzer-nullability.NullableDereferenced `_, `Clang Static Analyzer nullability.NullableDereferenced `_, `clang-analyzer-nullability.NullablePassedToNonnull `_, `Clang Static Analyzer nullability.NullablePassedToNonnull `_, + `clang-analyzer-nullability.NullableReturnedFromNonnull `_, `Clang Static Analyzer nullability.NullableReturnedFromNonnull `_, `clang-analyzer-optin.cplusplus.UninitializedObject `_, `Clang Static Analyzer optin.cplusplus.UninitializedObject `_, `clang-analyzer-optin.cplusplus.VirtualCall `_, `Clang Static Analyzer optin.cplusplus.VirtualCall `_, `clang-analyzer-optin.mpi.MPI-Checker `_, `Clang Static Analyzer optin.mpi.MPI-Checker `_, + `clang-analyzer-optin.osx.OSObjectCStyleCast `_, Clang Static Analyzer optin.osx.OSObjectCStyleCast, `clang-analyzer-optin.osx.cocoa.localizability.EmptyLocalizationContextChecker `_, `Clang Static Analyzer optin.osx.cocoa.localizability.EmptyLocalizationContextChecker `_, `clang-analyzer-optin.osx.cocoa.localizability.NonLocalizedStringChecker `_, `Clang Static Analyzer optin.osx.cocoa.localizability.NonLocalizedStringChecker `_, + `clang-analyzer-optin.performance.GCDAntipattern `_, `Clang Static Analyzer optin.performance.GCDAntipattern `_, + `clang-analyzer-optin.performance.Padding `_, `Clang Static Analyzer optin.performance.Padding `_, + `clang-analyzer-optin.portability.UnixAPI `_, `Clang Static Analyzer optin.portability.UnixAPI `_, `clang-analyzer-osx.API `_, `Clang Static Analyzer osx.API `_, + `clang-analyzer-osx.MIG `_, Clang Static Analyzer osx.MIG, + `clang-analyzer-osx.NumberObjectConversion `_, `Clang Static Analyzer osx.NumberObjectConversion `_, + `clang-analyzer-osx.OSObjectRetainCount `_, Clang Static Analyzer osx.OSObjectRetainCount, + `clang-analyzer-osx.ObjCProperty `_, `Clang Static Analyzer osx.ObjCProperty `_, `clang-analyzer-osx.SecKeychainAPI `_, `Clang Static Analyzer osx.SecKeychainAPI `_, `clang-analyzer-osx.cocoa.AtSync `_, `Clang Static Analyzer osx.cocoa.AtSync `_, + `clang-analyzer-osx.cocoa.AutoreleaseWrite `_, `Clang Static Analyzer osx.cocoa.AutoreleaseWrite `_, `clang-analyzer-osx.cocoa.ClassRelease `_, `Clang Static Analyzer osx.cocoa.ClassRelease `_, `clang-analyzer-osx.cocoa.Dealloc `_, `Clang Static Analyzer osx.cocoa.Dealloc `_, `clang-analyzer-osx.cocoa.IncompatibleMethodTypes `_, `Clang Static Analyzer osx.cocoa.IncompatibleMethodTypes `_, + `clang-analyzer-osx.cocoa.Loops `_, `Clang Static Analyzer osx.cocoa.Loops `_, + `clang-analyzer-osx.cocoa.MissingSuperCall `_, `Clang Static Analyzer osx.cocoa.MissingSuperCall `_, `clang-analyzer-osx.cocoa.NSAutoreleasePool `_, `Clang Static Analyzer osx.cocoa.NSAutoreleasePool `_, `clang-analyzer-osx.cocoa.NSError `_, `Clang Static Analyzer osx.cocoa.NSError `_, `clang-analyzer-osx.cocoa.NilArg `_, `Clang Static Analyzer osx.cocoa.NilArg `_, + `clang-analyzer-osx.cocoa.NonNilReturnValue `_, `Clang Static Analyzer osx.cocoa.NonNilReturnValue `_, `clang-analyzer-osx.cocoa.ObjCGenerics `_, `Clang Static Analyzer osx.cocoa.ObjCGenerics `_, `clang-analyzer-osx.cocoa.RetainCount `_, `Clang Static Analyzer osx.cocoa.RetainCount `_, + `clang-analyzer-osx.cocoa.RunLoopAutoreleaseLeak `_, `Clang Static Analyzer osx.cocoa.RunLoopAutoreleaseLeak `_, `clang-analyzer-osx.cocoa.SelfInit `_, `Clang Static Analyzer osx.cocoa.SelfInit `_, `clang-analyzer-osx.cocoa.SuperDealloc `_, `Clang Static Analyzer osx.cocoa.SuperDealloc `_, `clang-analyzer-osx.cocoa.UnusedIvars `_, `Clang Static Analyzer osx.cocoa.UnusedIvars `_, @@ -473,6 +475,7 @@ Clang-Tidy Checks `clang-analyzer-security.insecureAPI.bcmp `_, `Clang Static Analyzer security.insecureAPI.bcmp `_, `clang-analyzer-security.insecureAPI.bcopy `_, `Clang Static Analyzer security.insecureAPI.bcopy `_, `clang-analyzer-security.insecureAPI.bzero `_, `Clang Static Analyzer security.insecureAPI.bzero `_, + `clang-analyzer-security.insecureAPI.decodeValueOfObjCType `_, Clang Static Analyzer security.insecureAPI.decodeValueOfObjCType, `clang-analyzer-security.insecureAPI.getpw `_, `Clang Static Analyzer security.insecureAPI.getpw `_, `clang-analyzer-security.insecureAPI.gets `_, `Clang Static Analyzer security.insecureAPI.gets `_, `clang-analyzer-security.insecureAPI.mkstemp `_, `Clang Static Analyzer security.insecureAPI.mkstemp `_, @@ -487,6 +490,12 @@ Clang-Tidy Checks `clang-analyzer-unix.Vfork `_, `Clang Static Analyzer unix.Vfork `_, `clang-analyzer-unix.cstring.BadSizeArg `_, `Clang Static Analyzer unix.cstring.BadSizeArg `_, `clang-analyzer-unix.cstring.NullArg `_, `Clang Static Analyzer unix.cstring.NullArg `_, + `clang-analyzer-valist.CopyToSelf `_, Clang Static Analyzer valist.CopyToSelf, + `clang-analyzer-valist.Uninitialized `_, Clang Static Analyzer valist.Uninitialized, + `clang-analyzer-valist.Unterminated `_, Clang Static Analyzer valist.Unterminated, + `clang-analyzer-webkit.NoUncountedMemberChecker `_, `Clang Static Analyzer webkit.NoUncountedMemberChecker `_, + `clang-analyzer-webkit.RefCntblBaseVirtualDtor `_, `Clang Static Analyzer webkit.RefCntblBaseVirtualDtor `_, + `clang-analyzer-webkit.UncountedLambdaCapturesChecker `_, `Clang Static Analyzer webkit.UncountedLambdaCapturesChecker `_, `cppcoreguidelines-avoid-c-arrays `_, `modernize-avoid-c-arrays `_, `cppcoreguidelines-avoid-magic-numbers `_, `readability-magic-numbers `_, `cppcoreguidelines-c-copy-assignment-signature `_, `misc-unconventional-assign-operator `_, diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst index 378caccf611bb..9bb691e9d9512 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-std-print.rst @@ -81,7 +81,7 @@ If the call is deemed suitable for conversion then: is of ``signed char`` or ``unsigned char`` type are wrapped in a ``reinterpret_cast``. - any arguments where the format string and the parameter differ in - signedness will be wrapped in an approprate ``static_cast`` if `StrictMode` + signedness will be wrapped in an appropriate ``static_cast`` if `StrictMode` is enabled. - any arguments that end in a call to ``std::string::c_str()`` or ``std::string::data()`` will have that call removed. diff --git a/clang-tools-extra/docs/clang-tidy/checks/objc/assert-equals.rst b/clang-tools-extra/docs/clang-tidy/checks/objc/assert-equals.rst index b7a3e76401c46..09f5ef01c10c3 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/objc/assert-equals.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/objc/assert-equals.rst @@ -7,5 +7,5 @@ Finds improper usages of `XCTAssertEqual` and `XCTAssertNotEqual` and replaces them with `XCTAssertEqualObjects` or `XCTAssertNotEqualObjects`. This makes tests less fragile, as many improperly rely on pointer equality for -strings that have equal values. This assumption is not guarantted by the +strings that have equal values. This assumption is not guaranteed by the language. diff --git a/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h b/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h index 77be4f1dad521..cd2111cf72abf 100644 --- a/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h +++ b/clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h @@ -15,6 +15,7 @@ #include "clang-include-cleaner/Types.h" #include "clang/Format/Format.h" #include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/Preprocessor.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLFunctionalExtras.h" #include "llvm/ADT/SmallVector.h" @@ -56,7 +57,8 @@ using UsedSymbolCB = llvm::function_ref ASTRoots, llvm::ArrayRef MacroRefs, - const PragmaIncludes *PI, const SourceManager &, UsedSymbolCB CB); + const PragmaIncludes *PI, const Preprocessor &PP, + UsedSymbolCB CB); struct AnalysisResults { std::vector Unused; @@ -72,8 +74,7 @@ struct AnalysisResults { AnalysisResults analyze(llvm::ArrayRef ASTRoots, llvm::ArrayRef MacroRefs, const Includes &I, - const PragmaIncludes *PI, const SourceManager &SM, - const HeaderSearch &HS, + const PragmaIncludes *PI, const Preprocessor &PP, llvm::function_ref HeaderFilter = nullptr); /// Removes unused includes and inserts missing ones in the main file. diff --git a/clang-tools-extra/include-cleaner/lib/Analysis.cpp b/clang-tools-extra/include-cleaner/lib/Analysis.cpp index d1c7eda026657..630be33e79169 100644 --- a/clang-tools-extra/include-cleaner/lib/Analysis.cpp +++ b/clang-tools-extra/include-cleaner/lib/Analysis.cpp @@ -17,6 +17,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Format/Format.h" #include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Tooling/Core/Replacement.h" #include "clang/Tooling/Inclusions/StandardLibrary.h" #include "llvm/ADT/ArrayRef.h" @@ -28,14 +29,30 @@ #include "llvm/ADT/StringSet.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" +#include +#include #include namespace clang::include_cleaner { +namespace { +bool shouldIgnoreMacroReference(const Preprocessor &PP, const Macro &M) { + auto *MI = PP.getMacroInfo(M.Name); + // Macros that expand to themselves are confusing from user's point of view. + // They usually aspect the usage to be attributed to the underlying decl and + // not the macro definition. So ignore such macros (e.g. std{in,out,err} are + // implementation defined macros, that just resolve to themselves in + // practice). + return MI && MI->getNumTokens() == 1 && MI->isObjectLike() && + MI->getReplacementToken(0).getIdentifierInfo() == M.Name; +} +} // namespace + void walkUsed(llvm::ArrayRef ASTRoots, llvm::ArrayRef MacroRefs, - const PragmaIncludes *PI, const SourceManager &SM, + const PragmaIncludes *PI, const Preprocessor &PP, UsedSymbolCB CB) { + const auto &SM = PP.getSourceManager(); // This is duplicated in writeHTMLReport, changes should be mirrored there. tooling::stdlib::Recognizer Recognizer; for (auto *Root : ASTRoots) { @@ -51,7 +68,8 @@ void walkUsed(llvm::ArrayRef ASTRoots, } for (const SymbolReference &MacroRef : MacroRefs) { assert(MacroRef.Target.kind() == Symbol::Macro); - if (!SM.isWrittenInMainFile(SM.getSpellingLoc(MacroRef.RefLocation))) + if (!SM.isWrittenInMainFile(SM.getSpellingLoc(MacroRef.RefLocation)) || + shouldIgnoreMacroReference(PP, MacroRef.Target.macro())) continue; CB(MacroRef, headersForSymbol(MacroRef.Target, SM, PI)); } @@ -60,15 +78,15 @@ void walkUsed(llvm::ArrayRef ASTRoots, AnalysisResults analyze(llvm::ArrayRef ASTRoots, llvm::ArrayRef MacroRefs, const Includes &Inc, - const PragmaIncludes *PI, const SourceManager &SM, - const HeaderSearch &HS, + const PragmaIncludes *PI, const Preprocessor &PP, llvm::function_ref HeaderFilter) { + auto &SM = PP.getSourceManager(); const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID()); llvm::DenseSet Used; llvm::StringSet<> Missing; if (!HeaderFilter) HeaderFilter = [](llvm::StringRef) { return false; }; - walkUsed(ASTRoots, MacroRefs, PI, SM, + walkUsed(ASTRoots, MacroRefs, PI, PP, [&](const SymbolReference &Ref, llvm::ArrayRef
Providers) { bool Satisfied = false; for (const Header &H : Providers) { @@ -82,7 +100,8 @@ analyze(llvm::ArrayRef ASTRoots, if (!Satisfied && !Providers.empty() && Ref.RT == RefType::Explicit && !HeaderFilter(Providers.front().resolvedPath())) - Missing.insert(spellHeader({Providers.front(), HS, MainFile})); + Missing.insert(spellHeader( + {Providers.front(), PP.getHeaderSearchInfo(), MainFile})); }); AnalysisResults Results; diff --git a/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp b/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp index a1d9d3b5fb215..f9438a2c8c49e 100644 --- a/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp +++ b/clang-tools-extra/include-cleaner/lib/FindHeaders.cpp @@ -25,6 +25,8 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include +#include +#include #include namespace clang::include_cleaner { @@ -188,13 +190,13 @@ llvm::SmallVector> findHeaders(const SymbolLocation &Loc, if (!PI) return {{FE, Hints::PublicHeader | Hints::OriginHeader}}; bool IsOrigin = true; + std::queue Exporters; while (FE) { Results.emplace_back(FE, isPublicHeader(FE, *PI) | (IsOrigin ? Hints::OriginHeader : Hints::None)); - // FIXME: compute transitive exporter headers. for (const auto *Export : PI->getExporters(FE, SM.getFileManager())) - Results.emplace_back(Export, isPublicHeader(Export, *PI)); + Exporters.push(Export); if (auto Verbatim = PI->getPublic(FE); !Verbatim.empty()) { Results.emplace_back(Verbatim, @@ -209,6 +211,20 @@ llvm::SmallVector> findHeaders(const SymbolLocation &Loc, FE = SM.getFileEntryForID(FID); IsOrigin = false; } + // Now traverse provider trees rooted at exporters. + // Note that we only traverse export edges, and ignore private -> public + // mappings, as those pragmas apply to exporter, and not the main provider + // being exported in this header. + std::set SeenExports; + while (!Exporters.empty()) { + auto *Export = Exporters.front(); + Exporters.pop(); + if (!SeenExports.insert(Export).second) // In case of cyclic exports + continue; + Results.emplace_back(Export, isPublicHeader(Export, *PI)); + for (const auto *Export : PI->getExporters(Export, SM.getFileManager())) + Exporters.push(Export); + } return Results; } case SymbolLocation::Standard: { diff --git a/clang-tools-extra/include-cleaner/lib/HTMLReport.cpp b/clang-tools-extra/include-cleaner/lib/HTMLReport.cpp index 431d4bb211e0d..1bb4080b7e2b8 100644 --- a/clang-tools-extra/include-cleaner/lib/HTMLReport.cpp +++ b/clang-tools-extra/include-cleaner/lib/HTMLReport.cpp @@ -170,10 +170,10 @@ class Reporter { std::string spellHeader(const Header &H) { switch (H.kind()) { case Header::Physical: { - bool IsSystem = false; + bool IsAngled = false; std::string Path = HS.suggestPathToFileForDiagnostics( - H.physical(), MainFE->tryGetRealPathName(), &IsSystem); - return IsSystem ? "<" + Path + ">" : "\"" + Path + "\""; + H.physical(), MainFE->tryGetRealPathName(), &IsAngled); + return IsAngled ? "<" + Path + ">" : "\"" + Path + "\""; } case Header::Standard: return H.standard().name().str(); diff --git a/clang-tools-extra/include-cleaner/lib/IncludeSpeller.cpp b/clang-tools-extra/include-cleaner/lib/IncludeSpeller.cpp index bb49630fe3c80..2073f0a1d3d87 100644 --- a/clang-tools-extra/include-cleaner/lib/IncludeSpeller.cpp +++ b/clang-tools-extra/include-cleaner/lib/IncludeSpeller.cpp @@ -29,10 +29,10 @@ class DefaultIncludeSpeller : public IncludeSpeller { case Header::Verbatim: return Input.H.verbatim().str(); case Header::Physical: - bool IsSystem = false; + bool IsAngled = false; std::string FinalSpelling = Input.HS.suggestPathToFileForDiagnostics( - Input.H.physical(), Input.Main->tryGetRealPathName(), &IsSystem); - return IsSystem ? "<" + FinalSpelling + ">" : "\"" + FinalSpelling + "\""; + Input.H.physical(), Input.Main->tryGetRealPathName(), &IsAngled); + return IsAngled ? "<" + FinalSpelling + ">" : "\"" + FinalSpelling + "\""; } llvm_unreachable("Unknown clang::include_cleaner::Header::Kind enum"); } diff --git a/clang-tools-extra/include-cleaner/lib/Record.cpp b/clang-tools-extra/include-cleaner/lib/Record.cpp index 62eaa16dbf337..d7237325f701b 100644 --- a/clang-tools-extra/include-cleaner/lib/Record.cpp +++ b/clang-tools-extra/include-cleaner/lib/Record.cpp @@ -12,6 +12,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclGroup.h" #include "clang/Basic/FileEntry.h" +#include "clang/Basic/FileManager.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" @@ -24,16 +25,21 @@ #include "clang/Tooling/Inclusions/HeaderAnalysis.h" #include "clang/Tooling/Inclusions/StandardLibrary.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Error.h" +#include "llvm/Support/FileSystem/UniqueID.h" #include "llvm/Support/StringSaver.h" #include #include #include #include +#include #include #include diff --git a/clang-tools-extra/include-cleaner/lib/TypesInternal.h b/clang-tools-extra/include-cleaner/lib/TypesInternal.h index e9f8689e8647e..ca9b961cbccda 100644 --- a/clang-tools-extra/include-cleaner/lib/TypesInternal.h +++ b/clang-tools-extra/include-cleaner/lib/TypesInternal.h @@ -69,15 +69,15 @@ enum class Hints : uint8_t { /// Provides a generally-usable definition for the symbol. (a function decl, /// or class definition and not a forward declaration of a template). CompleteSymbol = 1 << 1, - /// Symbol is provided by a public file. Only absent in the cases where file - /// is explicitly marked as such, non self-contained or IWYU private - /// pragmas. - PublicHeader = 1 << 2, /// Header providing the symbol is explicitly marked as preferred, with an /// IWYU private pragma that points at this provider or header and symbol has /// ~the same name. - PreferredHeader = 1 << 3, - LLVM_MARK_AS_BITMASK_ENUM(PreferredHeader), + PreferredHeader = 1 << 2, + /// Symbol is provided by a public file. Only absent in the cases where file + /// is explicitly marked as such, non self-contained or IWYU private + /// pragmas. + PublicHeader = 1 << 3, + LLVM_MARK_AS_BITMASK_ENUM(PublicHeader), }; LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); /// A wrapper to augment values with hints. diff --git a/clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp b/clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp index 193fdaeeb5e4c..30aaee29b9a39 100644 --- a/clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp +++ b/clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp @@ -153,14 +153,14 @@ class Action : public clang::ASTFrontendAction { if (!HTMLReportPath.empty()) writeHTML(); - auto &HS = getCompilerInstance().getPreprocessor().getHeaderSearchInfo(); llvm::StringRef Path = SM.getFileEntryForID(SM.getMainFileID())->tryGetRealPathName(); assert(!Path.empty() && "Main file path not known?"); llvm::StringRef Code = SM.getBufferData(SM.getMainFileID()); - auto Results = analyze(AST.Roots, PP.MacroReferences, PP.Includes, &PI, SM, - HS, HeaderFilter); + auto Results = + analyze(AST.Roots, PP.MacroReferences, PP.Includes, &PI, + getCompilerInstance().getPreprocessor(), HeaderFilter); if (!Insert) Results.Missing.clear(); if (!Remove) diff --git a/clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp b/clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp index 3ad632a18c563..daa5f91463ec2 100644 --- a/clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp +++ b/clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp @@ -66,8 +66,9 @@ class WalkUsedTest : public testing::Test { } std::multimap> - offsetToProviders(TestAST &AST, SourceManager &SM, + offsetToProviders(TestAST &AST, llvm::ArrayRef MacroRefs = {}) { + const auto &SM = AST.sourceManager(); llvm::SmallVector TopLevelDecls; for (Decl *D : AST.context().getTranslationUnitDecl()->decls()) { if (!SM.isWrittenInMainFile(SM.getExpansionLoc(D->getLocation()))) @@ -75,7 +76,7 @@ class WalkUsedTest : public testing::Test { TopLevelDecls.emplace_back(D); } std::multimap> OffsetToProviders; - walkUsed(TopLevelDecls, MacroRefs, &PI, SM, + walkUsed(TopLevelDecls, MacroRefs, &PI, AST.preprocessor(), [&](const SymbolReference &Ref, llvm::ArrayRef
Providers) { auto [FID, Offset] = SM.getDecomposedLoc(Ref.RefLocation); if (FID != SM.getMainFileID()) @@ -118,7 +119,7 @@ TEST_F(WalkUsedTest, Basic) { auto VectorSTL = Header(*tooling::stdlib::Header::named("")); auto UtilitySTL = Header(*tooling::stdlib::Header::named("")); EXPECT_THAT( - offsetToProviders(AST, SM), + offsetToProviders(AST), UnorderedElementsAre( Pair(Code.point("bar"), UnorderedElementsAre(MainFile)), Pair(Code.point("private"), @@ -155,7 +156,7 @@ TEST_F(WalkUsedTest, MultipleProviders) { auto HeaderFile2 = Header(AST.fileManager().getFile("header2.h").get()); auto MainFile = Header(SM.getFileEntryForID(SM.getMainFileID())); EXPECT_THAT( - offsetToProviders(AST, SM), + offsetToProviders(AST), Contains(Pair(Code.point("foo"), UnorderedElementsAre(HeaderFile1, HeaderFile2, MainFile)))); } @@ -171,19 +172,19 @@ TEST_F(WalkUsedTest, MacroRefs) { Inputs.ExtraFiles["hdr.h"] = Hdr.code(); TestAST AST(Inputs); auto &SM = AST.sourceManager(); + auto &PP = AST.preprocessor(); const auto *HdrFile = SM.getFileManager().getFile("hdr.h").get(); auto MainFile = Header(SM.getFileEntryForID(SM.getMainFileID())); auto HdrID = SM.translateFile(HdrFile); - IdentifierTable Idents; - Symbol Answer1 = - Macro{&Idents.get("ANSWER"), SM.getComposedLoc(HdrID, Hdr.point())}; - Symbol Answer2 = - Macro{&Idents.get("ANSWER"), SM.getComposedLoc(HdrID, Hdr.point())}; + Symbol Answer1 = Macro{PP.getIdentifierInfo("ANSWER"), + SM.getComposedLoc(HdrID, Hdr.point())}; + Symbol Answer2 = Macro{PP.getIdentifierInfo("ANSWER"), + SM.getComposedLoc(HdrID, Hdr.point())}; EXPECT_THAT( offsetToProviders( - AST, SM, + AST, {SymbolReference{ Answer1, SM.getComposedLoc(SM.getMainFileID(), Code.point("1")), RefType::Explicit}, @@ -240,8 +241,7 @@ int x = a + c; auto Decls = AST.context().getTranslationUnitDecl()->decls(); auto Results = analyze(std::vector{Decls.begin(), Decls.end()}, - PP.MacroReferences, PP.Includes, &PI, AST.sourceManager(), - AST.preprocessor().getHeaderSearchInfo()); + PP.MacroReferences, PP.Includes, &PI, AST.preprocessor()); const Include *B = PP.Includes.atLine(3); ASSERT_EQ(B->Spelled, "b.h"); @@ -257,8 +257,7 @@ TEST_F(AnalyzeTest, PrivateUsedInPublic) { Inputs.FileName = "public.h"; TestAST AST(Inputs); EXPECT_FALSE(PP.Includes.all().empty()); - auto Results = analyze({}, {}, PP.Includes, &PI, AST.sourceManager(), - AST.preprocessor().getHeaderSearchInfo()); + auto Results = analyze({}, {}, PP.Includes, &PI, AST.preprocessor()); EXPECT_THAT(Results.Unused, testing::IsEmpty()); } @@ -268,8 +267,7 @@ TEST_F(AnalyzeTest, NoCrashWhenUnresolved) { Inputs.ErrorOK = true; TestAST AST(Inputs); EXPECT_FALSE(PP.Includes.all().empty()); - auto Results = analyze({}, {}, PP.Includes, &PI, AST.sourceManager(), - AST.preprocessor().getHeaderSearchInfo()); + auto Results = analyze({}, {}, PP.Includes, &PI, AST.preprocessor()); EXPECT_THAT(Results.Unused, testing::IsEmpty()); } @@ -409,7 +407,7 @@ TEST(WalkUsed, FilterRefsNotSpelledInMainFile) { SourceLocation RefLoc; walkUsed(TopLevelDecls, Recorded.MacroReferences, - /*PragmaIncludes=*/nullptr, SM, + /*PragmaIncludes=*/nullptr, AST.preprocessor(), [&](const SymbolReference &Ref, llvm::ArrayRef
) { if (!Ref.RefLocation.isMacroID()) return; @@ -441,9 +439,9 @@ TEST(Hints, Ordering) { }; EXPECT_LT(Hinted(Hints::None), Hinted(Hints::CompleteSymbol)); EXPECT_LT(Hinted(Hints::CompleteSymbol), Hinted(Hints::PublicHeader)); - EXPECT_LT(Hinted(Hints::PublicHeader), Hinted(Hints::PreferredHeader)); - EXPECT_LT(Hinted(Hints::CompleteSymbol | Hints::PublicHeader), - Hinted(Hints::PreferredHeader)); + EXPECT_LT(Hinted(Hints::PreferredHeader), Hinted(Hints::PublicHeader)); + EXPECT_LT(Hinted(Hints::CompleteSymbol | Hints::PreferredHeader), + Hinted(Hints::PublicHeader)); } // Test ast traversal & redecl selection end-to-end for templates, as explicit @@ -472,7 +470,7 @@ TEST_F(WalkUsedTest, TemplateDecls) { const auto *Partial = SM.getFileManager().getFile("partial.h").get(); EXPECT_THAT( - offsetToProviders(AST, SM), + offsetToProviders(AST), AllOf(Contains( Pair(Code.point("exp_spec"), UnorderedElementsAre(Fwd, Def))), Contains(Pair(Code.point("exp"), UnorderedElementsAre(Fwd, Def))), @@ -483,5 +481,29 @@ TEST_F(WalkUsedTest, TemplateDecls) { Pair(Code.point("partial"), UnorderedElementsAre(Partial))))); } +TEST_F(WalkUsedTest, IgnoresIdentityMacros) { + llvm::Annotations Code(R"cpp( + #include "header.h" + void $bar^bar() { + $stdin^stdin(); + } + )cpp"); + Inputs.Code = Code.code(); + Inputs.ExtraFiles["header.h"] = guard(R"cpp( + #include "inner.h" + void stdin(); + )cpp"); + Inputs.ExtraFiles["inner.h"] = guard(R"cpp( + #define stdin stdin + )cpp"); + + TestAST AST(Inputs); + auto &SM = AST.sourceManager(); + auto MainFile = Header(SM.getFileEntryForID(SM.getMainFileID())); + EXPECT_THAT(offsetToProviders(AST), + UnorderedElementsAre( + // FIXME: we should have a reference from stdin to header.h + Pair(Code.point("bar"), UnorderedElementsAre(MainFile)))); +} } // namespace } // namespace clang::include_cleaner diff --git a/clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp b/clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp index 9f9ac11a93eb8..be97eb13a704e 100644 --- a/clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp +++ b/clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp @@ -465,6 +465,71 @@ TEST_F(HeadersForSymbolTest, PreferPublicOverNameMatchOnPrivate) { physicalHeader("foo.h"))); } +TEST_F(HeadersForSymbolTest, PublicOverPrivateWithoutUmbrella) { + Inputs.Code = R"cpp( + #include "bar.h" + #include "foo.h" + )cpp"; + Inputs.ExtraFiles["bar.h"] = + guard(R"cpp(#include "foo.h" // IWYU pragma: export)cpp"); + Inputs.ExtraFiles["foo.h"] = guard(R"cpp( + // IWYU pragma: private + struct foo {}; + )cpp"); + buildAST(); + EXPECT_THAT(headersForFoo(), + ElementsAre(physicalHeader("bar.h"), physicalHeader("foo.h"))); +} + +TEST_F(HeadersForSymbolTest, IWYUTransitiveExport) { + Inputs.Code = R"cpp( + #include "export1.h" + )cpp"; + Inputs.ExtraFiles["export1.h"] = guard(R"cpp( + #include "export2.h" // IWYU pragma: export + )cpp"); + Inputs.ExtraFiles["export2.h"] = guard(R"cpp( + #include "foo.h" // IWYU pragma: export + )cpp"); + Inputs.ExtraFiles["foo.h"] = guard(R"cpp( + struct foo {}; + )cpp"); + buildAST(); + EXPECT_THAT(headersForFoo(), + ElementsAre(physicalHeader("foo.h"), physicalHeader("export1.h"), + physicalHeader("export2.h"))); +} + +TEST_F(HeadersForSymbolTest, IWYUTransitiveExportWithPrivate) { + Inputs.Code = R"cpp( + #include "export1.h" + void bar() { foo();} + )cpp"; + Inputs.ExtraFiles["export1.h"] = guard(R"cpp( + // IWYU pragma: private, include "public1.h" + #include "export2.h" // IWYU pragma: export + void foo(); + )cpp"); + Inputs.ExtraFiles["export2.h"] = guard(R"cpp( + // IWYU pragma: private, include "public2.h" + #include "export3.h" // IWYU pragma: export + )cpp"); + Inputs.ExtraFiles["export3.h"] = guard(R"cpp( + // IWYU pragma: private, include "public3.h" + #include "foo.h" // IWYU pragma: export + )cpp"); + Inputs.ExtraFiles["foo.h"] = guard(R"cpp( + void foo(); + )cpp"); + buildAST(); + EXPECT_THAT(headersForFoo(), + ElementsAre(physicalHeader("foo.h"), + Header(StringRef("\"public1.h\"")), + physicalHeader("export1.h"), + physicalHeader("export2.h"), + physicalHeader("export3.h"))); +} + TEST_F(HeadersForSymbolTest, AmbiguousStdSymbols) { struct { llvm::StringRef Code; diff --git a/clang-tools-extra/modularize/Modularize.cpp b/clang-tools-extra/modularize/Modularize.cpp index b90ccccf30cd3..d6f1520cc40e7 100644 --- a/clang-tools-extra/modularize/Modularize.cpp +++ b/clang-tools-extra/modularize/Modularize.cpp @@ -336,13 +336,13 @@ std::string CommandLine; // Helper function for finding the input file in an arguments list. static std::string findInputFile(const CommandLineArguments &CLArgs) { - const unsigned IncludedFlagsBitmask = options::CC1Option; + llvm::opt::Visibility VisibilityMask(options::CC1Option); unsigned MissingArgIndex, MissingArgCount; SmallVector Argv; for (auto I = CLArgs.begin(), E = CLArgs.end(); I != E; ++I) Argv.push_back(I->c_str()); InputArgList Args = getDriverOptTable().ParseArgs( - Argv, MissingArgIndex, MissingArgCount, IncludedFlagsBitmask); + Argv, MissingArgIndex, MissingArgCount, VisibilityMask); std::vector Inputs = Args.getAllArgValues(OPT_INPUT); return ModularizeUtilities::getCanonicalPath(Inputs.back()); } diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/lambda-function-name.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/lambda-function-name.cpp index 145928b4e20d9..936ee87a856cd 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/lambda-function-name.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/lambda-function-name.cpp @@ -1,4 +1,6 @@ -// RUN: %check_clang_tidy %s bugprone-lambda-function-name %t +// RUN: %check_clang_tidy -check-suffixes=,NO-CONFIG %s bugprone-lambda-function-name %t +// RUN: %check_clang_tidy %s bugprone-lambda-function-name %t -- -config="{CheckOptions: [{key: bugprone-lambda-function-name.IgnoreMacros, value: true}]}" -- + void Foo(const char* a, const char* b, int c) {} @@ -12,11 +14,11 @@ void Positives() { [] { __FUNCTION__; }(); // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: inside a lambda, '__FUNCTION__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name] [] { FUNC_MACRO; }(); - // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name] + // CHECK-MESSAGES-NO-CONFIG: :[[@LINE-1]]:8: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name] [] { FUNCTION_MACRO; }(); - // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: inside a lambda, '__FUNCTION__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name] + // CHECK-MESSAGES-NO-CONFIG: :[[@LINE-1]]:8: warning: inside a lambda, '__FUNCTION__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name] [] { EMBED_IN_ANOTHER_MACRO1; }(); - // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name] + // CHECK-MESSAGES-NO-CONFIG: :[[@LINE-1]]:8: warning: inside a lambda, '__func__' expands to the name of the function call operator; consider capturing the name of the enclosing function explicitly [bugprone-lambda-function-name] } #define FUNC_MACRO_WITH_FILE_AND_LINE Foo(__func__, __FILE__, __LINE__) diff --git a/clang-tools-extra/test/clang-tidy/checkers/cert/mem57-cpp-cpp17.cpp b/clang-tools-extra/test/clang-tidy/checkers/cert/mem57-cpp-cpp17.cpp index 13ab5135953b3..38ffcbd7e805d 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cert/mem57-cpp-cpp17.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cert/mem57-cpp-cpp17.cpp @@ -1,6 +1,6 @@ // RUN: %check_clang_tidy %s -std=c++14 cert-mem57-cpp %t -// RUN: clang-tidy --extra-arg='-std=c++17' --extra-arg='-faligned-allocation' -checks='-*,cert-mem57-cpp' --extra-arg=-Wno-unused-variable --warnings-as-errors='*' %s -// RUN: clang-tidy --extra-arg='-std=c++20' --extra-arg='-faligned-allocation' -checks='-*,cert-mem57-cpp' --extra-arg=-Wno-unused-variable --warnings-as-errors='*' %s +// RUN: clang-tidy -checks='-*,cert-mem57-cpp' --extra-arg=-Wno-unused-variable --warnings-as-errors='*' %s -- -std=c++17 -faligned-allocation +// RUN: clang-tidy -checks='-*,cert-mem57-cpp' --extra-arg=-Wno-unused-variable --warnings-as-errors='*' %s -- -std=c++17 -faligned-allocation struct alignas(128) Vector { char Elems[128]; diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/no-suspend-with-lock.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/no-suspend-with-lock.cpp new file mode 100644 index 0000000000000..a6e0cd778c40c --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/no-suspend-with-lock.cpp @@ -0,0 +1,279 @@ +// RUN: %check_clang_tidy -std=c++20 %s cppcoreguidelines-no-suspend-with-lock %t -- -- -fno-delayed-template-parsing -fexceptions + +// NOLINTBEGIN +namespace std { +template +struct coroutine_traits { + using promise_type = typename T::promise_type; +}; +template +struct coroutine_handle; +template <> +struct coroutine_handle { + coroutine_handle() noexcept; + coroutine_handle(decltype(nullptr)) noexcept; + static constexpr coroutine_handle from_address(void*); +}; +template +struct coroutine_handle { + coroutine_handle() noexcept; + coroutine_handle(decltype(nullptr)) noexcept; + static constexpr coroutine_handle from_address(void*); + operator coroutine_handle<>() const noexcept; +}; + +template +class unique_lock { +public: + unique_lock() noexcept; + explicit unique_lock(Mutex &m); + unique_lock& operator=(unique_lock&&); + void unlock(); + Mutex* release() noexcept; + Mutex* mutex() const noexcept; + void swap(unique_lock& other) noexcept; +}; + +class mutex { +public: + mutex() noexcept; + ~mutex(); + mutex(const mutex &) = delete; + mutex &operator=(const mutex &) = delete; + + void lock(); + void unlock(); +}; +} // namespace std + +class my_own_mutex { +public: + void lock(); + void unlock(); +}; + +struct Awaiter { + bool await_ready() noexcept; + void await_suspend(std::coroutine_handle<>) noexcept; + void await_resume() noexcept; +}; + +struct Coro { + struct promise_type { + Awaiter initial_suspend(); + Awaiter final_suspend() noexcept; + void return_void(); + Coro get_return_object(); + void unhandled_exception(); + Awaiter yield_value(int); + }; +}; +// NOLINTEND + +std::mutex mtx; +std::mutex mtx2; + +Coro awaits_with_lock() { + std::unique_lock lock(mtx); + + co_await Awaiter{}; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock] + + co_await Awaiter{}; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock] + + if (true) { + co_await Awaiter{}; + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock] + } + + if (true) { + std::unique_lock lock2; + lock2.unlock(); + co_await Awaiter{}; + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock2' held [cppcoreguidelines-no-suspend-with-lock] + } +} + +Coro awaits_with_lock_in_try() try { + std::unique_lock lock(mtx); + co_await Awaiter{}; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock] +} catch (...) {} + +Coro lock_possibly_unlocked() { + // CppCoreGuideline CP.52's enforcement strictly requires flagging + // code that suspends while any lock guard is not destructed. + + { + std::unique_lock lock(mtx); + lock.unlock(); + co_await Awaiter{}; + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock] + } + + { + std::unique_lock lock(mtx); + lock.release(); + co_await Awaiter{}; + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock] + } + + { + std::unique_lock lock(mtx); + std::unique_lock lock2; + lock.swap(lock2); + co_await Awaiter{}; + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock] + } + + { + std::unique_lock lock(mtx); + std::unique_lock lock2{mtx2}; + lock.swap(lock2); + co_await Awaiter{}; + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock] + } + + { + std::unique_lock lock(mtx); + lock = std::unique_lock{}; + co_await Awaiter{}; + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock] + } + + { + std::unique_lock lock(mtx); + lock = std::unique_lock{mtx2}; + co_await Awaiter{}; + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock] + } +} + +Coro await_with_underlying_mutex_unlocked() { + std::unique_lock lock(mtx); + + // Even though we unlock the mutex here, 'lock' is still active unless + // there is a call to lock.unlock(). This is a bug in the program since + // it will result in locking the mutex twice. The check does not track + // unlock calls on the underlying mutex held by a lock guard object. + mtx.unlock(); + + co_await Awaiter{}; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock] +} + +Coro await_with_empty_lock() { + std::unique_lock lock; + co_await Awaiter{}; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock] +} + +Coro await_before_lock() { + co_await Awaiter{}; + std::unique_lock lock(mtx); +} + +Coro await_with_lock_different_scope() { + { + std::unique_lock lock(mtx); + } + co_await Awaiter{}; +} + +Coro await_with_goto() { +first: + co_await Awaiter{}; + std::unique_lock lock(mtx); + goto first; +} + +void await_in_lambda() { + auto f1 = []() -> Coro { + std::unique_lock lock(mtx); + co_await Awaiter{}; + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock] + }; + + auto f2 = [](auto& m) -> Coro { + std::unique_lock lock(m); + co_await Awaiter{}; + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock] + }; +} + +void await_in_lambda_without_immediate_mutex() { + std::unique_lock lock(mtx); + + auto f1 = []() -> Coro { + co_await Awaiter{}; + }; + + // The check only finds suspension points where there is a lock held in the + // immediate callable. + f1(); +} + +Coro yields_with_lock() { + std::unique_lock lock(mtx); + co_yield 0; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock] +} + +template +Coro awaits_templated_type(Mutex& m) { + std::unique_lock lock(m); + co_await Awaiter{}; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock] +} + +template +Coro awaits_in_template_function(T) { + std::unique_lock lock(mtx); + co_await Awaiter{}; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock] +} + +template +Coro awaits_in_never_instantiated_template_of_mutex(Mutex& m) { + // Nothing should instantiate this function + std::unique_lock lock(m); + co_await Awaiter{}; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock] +} + +template +Coro awaits_in_never_instantiated_templated_function(T) { + // Nothing should instantiate this function + std::unique_lock lock(mtx); + co_await Awaiter{}; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock] +} + +template +struct my_container { + + Coro push_back() { + std::unique_lock lock(mtx_); + co_await Awaiter{}; + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock] + } + + template + Coro emplace_back(Args&&...) { + std::unique_lock lock(mtx_); + co_await Awaiter{}; + // CHECK-MESSAGES: [[@LINE-1]]:5: warning: coroutine suspended with lock 'lock' held [cppcoreguidelines-no-suspend-with-lock] + } + + std::mutex mtx_; +}; + +void calls_templated_functions() { + my_own_mutex m2; + awaits_templated_type(mtx); + awaits_templated_type(m2); + + awaits_in_template_function(1); + awaits_in_template_function(1.0); +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-array-to-pointer-decay.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-array-to-pointer-decay.cpp index d41f54b4e77f2..0bd058caf74ff 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-array-to-pointer-decay.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-array-to-pointer-decay.cpp @@ -43,6 +43,9 @@ const char *g() { const char *g2() { return ("clang"); // OK, ParenExpr hides the literal-pointer decay } +const char *g3() { + return __func__; // OK, don't diagnose PredefinedExpr +} void f2(void *const *); void bug25362() { diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-member-init.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-member-init.cpp index 2e2097bae361a..8d6992afef08a 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-member-init.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-member-init.cpp @@ -372,8 +372,7 @@ template class PositiveSelfInitialization : NegativeAggregateType { PositiveSelfInitialization() : PositiveSelfInitialization() {} - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NegativeAggregateType - // CHECK-FIXES: PositiveSelfInitialization() : NegativeAggregateType(), PositiveSelfInitialization() {} + // This will be detected by -Wdelegating-ctor-cycles and there is no proper way to fix this }; class PositiveIndirectMember { @@ -579,3 +578,42 @@ struct S3 { int C = 0; }; }; + +// Ignore issues from delegate constructors +namespace PR37250 { + template + struct A { + A() : A(42) {} + explicit A(int value) : value_(value) {} + int value_; + }; + + struct B { + B() : B(42) {} + explicit B(int value) : value_(value) {} + int value_; + }; + + template + struct C { + C() : C(T()) {} + explicit C(T value) : value_(value) {} + T value_; + }; + + struct V { + unsigned size() const; + }; + + struct S { + unsigned size_; + + S(unsigned size) : size_{size} {} + + template + S(const U& u) : S(u.size()) {} + }; + + const V v; + const S s{v}; +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-vararg.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-vararg.cpp index e5bf98f02d8b3..6792c7920dd11 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-vararg.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-type-vararg.cpp @@ -66,3 +66,16 @@ void no_false_positive_desugar_va_list(char *in) { char *tmp1 = in; void *tmp2 = in; } + +namespace PR30542 { + struct X; + template + char IsNullConstant(X*); + template + char (&IsNullConstant(...))[2]; + + static_assert(sizeof(IsNullConstant(0)) == 1, ""); + static_assert(sizeof(IsNullConstant(17)) == 2, ""); + + using Type = decltype(IsNullConstant(17)); +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp index 895a1666757ff..1b271630e0d19 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression.cpp @@ -855,3 +855,11 @@ static_assert(sizeof(X) == sizeof(X)); // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: both sides of operator are equivalent } + +namespace PR35857 { + void test() { + int x = 0; + int y = 0; + decltype(x + y - (x + y)) z = 10; + } +} diff --git a/clang-tools-extra/test/clang-tidy/checkers/performance/faster-string-find.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance/faster-string-find.cpp index dc625024fd1bc..b50d175cff3b7 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/performance/faster-string-find.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/performance/faster-string-find.cpp @@ -56,13 +56,21 @@ void StringFind() { // CHECK-MESSAGES: [[@LINE-1]]:12: warning: 'find' called with a string literal // CHECK-FIXES: Str.find('a', 1); - // Doens't work with strings smaller or larger than 1 char. + // Doesn't work with strings smaller or larger than 1 char. Str.find(""); Str.find("ab"); // Doesn't do anything with the 3 argument overload. Str.find("a", 1, 1); + // Single quotes are escaped properly + Str.find("'"); + // CHECK-MESSAGES: [[@LINE-1]]:12: warning: 'find' called with a string literal + // CHECK-FIXES: Str.find('\''); + Str.find("\'"); + // CHECK-MESSAGES: [[@LINE-1]]:12: warning: 'find' called with a string literal + // CHECK-FIXES: Str.find('\''); + // Other methods that can also be replaced Str.rfind("a"); // CHECK-MESSAGES: [[@LINE-1]]:13: warning: 'rfind' called with a string literal diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/else-after-return-pp-no-crash.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/else-after-return-pp-no-crash.cpp index a10868fbc3944..82bacd5431792 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/else-after-return-pp-no-crash.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/else-after-return-pp-no-crash.cpp @@ -1,4 +1,4 @@ -// RUN: clang-tidy %s -checks=-*,readability-else-after-return +// RUN: clang-tidy %s -checks=-*,readability-else-after-return -- // We aren't concerned about the output here, just want to ensure clang-tidy doesn't crash. void foo() { diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-case-violation.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-case-violation.cpp index 09245e6541a0b..6102a2e7031af 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-case-violation.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-case-violation.cpp @@ -5,7 +5,7 @@ // RUN: readability-identifier-naming.ClassCase: UUPER_CASE, \ // RUN: readability-identifier-naming.StructCase: CAMEL, \ // RUN: readability-identifier-naming.EnumCase: AnY_cASe, \ -// RUN: }}" 2>&1 | FileCheck %s --implicit-check-not="{{warning|error}}:" +// RUN: }}" -- 2>&1 | FileCheck %s --implicit-check-not="{{warning|error}}:" // CHECK-DAG: warning: invalid configuration value 'camelback' for option 'readability-identifier-naming.FunctionCase'; did you mean 'camelBack'? [clang-tidy-config] // CHECK-DAG: warning: invalid configuration value 'UUPER_CASE' for option 'readability-identifier-naming.ClassCase'; did you mean 'UPPER_CASE'? [clang-tidy-config] diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/implicit-bool-conversion-allow-in-conditions.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/implicit-bool-conversion-allow-in-conditions.cpp index f17b4dcacdb61..e393e297140cb 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/implicit-bool-conversion-allow-in-conditions.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/implicit-bool-conversion-allow-in-conditions.cpp @@ -38,6 +38,9 @@ void implicitConversionIntegerToBoolInConditionalsIsAllowed() { while (functionReturningInt()) {} while (functionReturningPointer()) {} while (functionReturningInt() && !functionReturningPointer() || (!functionReturningInt() && functionReturningPointer())) {} + do {} while (functionReturningInt()); + do {} while (functionReturningPointer()); + do {} while (functionReturningInt() && !functionReturningPointer() || (!functionReturningInt() && functionReturningPointer())); int value1 = functionReturningInt() ? 1 : 2; int value2 = !functionReturningInt() ? 1 : 2; int value3 = (functionReturningInt() && functionReturningPointer() || !functionReturningInt()) ? 1 : 2; diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/static-accessed-through-instance.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/static-accessed-through-instance.cpp index 9e8930084a65a..81c1cecf607f6 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/static-accessed-through-instance.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/static-accessed-through-instance.cpp @@ -363,3 +363,20 @@ void testEmbeddedAnonymousStructAndClass() { } } // namespace llvm_issue_61736 + +namespace PR51861 { + class Foo { + public: + static Foo& getInstance(); + static int getBar(); + }; + + inline int Foo::getBar() { return 42; } + + void test() { + auto& params = Foo::getInstance(); + params.getBar(); + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: static member accessed through instance [readability-static-accessed-through-instance] + // CHECK-FIXES: {{^}} PR51861::Foo::getBar();{{$}} + } +} diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp index c87496292b9db..547f634a101c5 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp +++ b/clang-tools-extra/test/clang-tidy/infrastructure/diagnostic.cpp @@ -25,6 +25,7 @@ // RUN: not clang-tidy -checks='-*,modernize-use-override' %T/diagnostics/input.cpp -- -DCOMPILATION_ERROR 2>&1 | FileCheck -check-prefix=CHECK6 -implicit-check-not='{{warning:|error:}}' %s // RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined' %s -- -DMACRO_FROM_COMMAND_LINE -std=c++20 | FileCheck -check-prefix=CHECK4 -implicit-check-not='{{warning:|error:}}' %s // RUN: clang-tidy -checks='-*,modernize-use-override,clang-diagnostic-macro-redefined,clang-diagnostic-literal-conversion' %s -- -DMACRO_FROM_COMMAND_LINE -std=c++20 -Wno-macro-redefined | FileCheck --check-prefix=CHECK7 -implicit-check-not='{{warning:|error:}}' %s +// RUN: not clang-tidy -checks='-*,modernize-use-override' %s -- -std=c++20 -DPR64602 | FileCheck -check-prefix=CHECK8 -implicit-check-not='{{warning:|error:}}' %s // CHECK1: error: no input files [clang-diagnostic-error] // CHECK1: error: no such file or directory: '{{.*}}nonexistent.cpp' [clang-diagnostic-error] @@ -54,3 +55,18 @@ void f(int a) { // CHECK6: :[[@LINE-1]]:3: error: cannot take the address of an rvalue of type 'int' [clang-diagnostic-error] } #endif + +#ifdef PR64602 // Should not crash +template +struct S +{ + auto foo(auto); +}; + +template <> +auto S<>::foo(auto) +{ + return 1; +} +// CHECK8: error: template parameter list matching the non-templated nested type 'S<>' should be empty ('template<>') [clang-diagnostic-error] +#endif diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-multiple-TUs.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-multiple-TUs.cpp index 773e023cb22c9..8264e399273e5 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-multiple-TUs.cpp +++ b/clang-tools-extra/test/clang-tidy/infrastructure/nolintbeginend-multiple-TUs.cpp @@ -1,4 +1,4 @@ -// RUN: clang-tidy %S/Inputs/nolintbeginend/1st-translation-unit.cpp %S/Inputs/nolintbeginend/2nd-translation-unit.cpp --checks='-*,google-explicit-constructor' 2>&1 | FileCheck %s +// RUN: clang-tidy %S/Inputs/nolintbeginend/1st-translation-unit.cpp %S/Inputs/nolintbeginend/2nd-translation-unit.cpp --checks='-*,google-explicit-constructor' -- 2>&1 | FileCheck %s // CHECK-NOT: 1st-translation-unit.cpp:2:11: warning: single-argument constructors must be marked explicit // CHECK: 1st-translation-unit.cpp:5:11: warning: single-argument constructors must be marked explicit diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/use-color.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/use-color.cpp index ace70a4a051e8..94d3732cc5293 100644 --- a/clang-tools-extra/test/clang-tidy/infrastructure/use-color.cpp +++ b/clang-tools-extra/test/clang-tidy/infrastructure/use-color.cpp @@ -5,9 +5,9 @@ // RUN: clang-tidy -config='UseColor: false' -dump-config | FileCheck -check-prefix=CHECK-CONFIG-NO-COLOR %s // RUN: clang-tidy -help | FileCheck -check-prefix=CHECK-OPT-PRESENT %s -// RUN: clang-tidy -checks='-*, modernize-use-override' -extra-arg=-std=c++11 -use-color=false %s | FileCheck -check-prefix=CHECK-NO-COLOR %s -// RUN: clang-tidy -checks='-*, modernize-use-override' -extra-arg=-std=c++11 %s | FileCheck -check-prefix=CHECK-NO-COLOR %s -// RUN: clang-tidy -checks='-*, modernize-use-override' -extra-arg=-std=c++11 -use-color %s | FileCheck -check-prefix=CHECK-COLOR %s +// RUN: clang-tidy -checks='-*, modernize-use-override' -use-color=false %s -- -std=c++11 | FileCheck -check-prefix=CHECK-NO-COLOR %s +// RUN: clang-tidy -checks='-*, modernize-use-override' %s -- -std=c++11 | FileCheck -check-prefix=CHECK-NO-COLOR %s +// RUN: clang-tidy -checks='-*, modernize-use-override' -use-color %s -- -std=c++11 | FileCheck -check-prefix=CHECK-COLOR %s // CHECK-NOT: UseColor // CHECK-CONFIG-NO-COLOR: UseColor: false diff --git a/clang-tools-extra/test/pp-trace/pp-trace-filter.cpp b/clang-tools-extra/test/pp-trace/pp-trace-filter.cpp index 1cd2ce7ef14d7..8f090ab0bb79a 100644 --- a/clang-tools-extra/test/pp-trace/pp-trace-filter.cpp +++ b/clang-tools-extra/test/pp-trace/pp-trace-filter.cpp @@ -14,4 +14,4 @@ int i = M; // CHECK-NOT: - Callback: EndOfMainFile // CHECK: ... -// INVALID: error: invalid glob pattern: [ +// INVALID: error: invalid glob pattern, unmatched '[' diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 6f02a436b0ac8..3b3f6f2860906 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -3832,7 +3832,7 @@ the configuration (without a prefix: ``Auto``). .. _Macros: -**Macros** (``List of Strings``) :versionbadge:`clang-format 17.0` :ref:`¶ ` +**Macros** (``List of Strings``) :versionbadge:`clang-format 17` :ref:`¶ ` A list of macros of the form ``=`` . Code will be parsed with macros expanded, in order to determine how to @@ -5097,7 +5097,7 @@ the configuration (without a prefix: ``Auto``). AfterControlStatements: true AfterFunctionDefinitionName: true - * ``bool AfterControlStatements`` If ``true``, put space betwee control statement keywords + * ``bool AfterControlStatements`` If ``true``, put space between control statement keywords (for/if/while...) and opening parentheses. .. code-block:: c++ diff --git a/clang/docs/DebuggingCoroutines.rst b/clang/docs/DebuggingCoroutines.rst index 842f7645f967b..53bdd08fdbc02 100644 --- a/clang/docs/DebuggingCoroutines.rst +++ b/clang/docs/DebuggingCoroutines.rst @@ -501,7 +501,7 @@ So we can use the ``continuation`` field to construct the asynchronous stack: # In the example, the continuation is the first field member of the promise_type. # So they have the same addresses. # If we want to generalize the scripts to other coroutine types, we need to be sure - # the continuation field is the first memeber of promise_type. + # the continuation field is the first member of promise_type. self.continuation_addr = self.promise_addr def next_task_addr(self): diff --git a/clang/docs/InternalsManual.rst b/clang/docs/InternalsManual.rst index 1698e11d7b3e2..b7d88d3d67d0a 100644 --- a/clang/docs/InternalsManual.rst +++ b/clang/docs/InternalsManual.rst @@ -663,9 +663,11 @@ Then, specify additional attributes via mix-ins: * ``HelpText`` holds the text that will be printed besides the option name when the user requests help (e.g. via ``clang --help``). * ``Group`` specifies the "category" of options this option belongs to. This is - used by various tools to filter certain options of interest. -* ``Flags`` may contain a number of "tags" associated with the option. This - enables more granular filtering than the ``Group`` attribute. + used by various tools to categorize and sometimes filter options. +* ``Flags`` may contain "tags" associated with the option. These may affect how + the option is rendered, or if it's hidden in some contexts. +* ``Visibility`` should be used to specify the drivers in which a particular + option would be available. This attribute will impact tool --help * ``Alias`` denotes that the option is an alias of another option. This may be combined with ``AliasArgs`` that holds the implied value. @@ -674,12 +676,14 @@ Then, specify additional attributes via mix-ins: // Options.td def fpass_plugin_EQ : Joined<["-"], "fpass-plugin=">, - + Group, Flags<[CC1Option]>, + + Group, Visibility<[ClangOption, CC1Option]>, + HelpText<"Load pass plugin from a dynamic shared object file.">; -New options are recognized by the Clang driver unless marked with the -``NoDriverOption`` flag. On the other hand, options intended for the ``-cc1`` -frontend must be explicitly marked with the ``CC1Option`` flag. +New options are recognized by the ``clang`` driver mode if ``Visibility`` is +not specified or contains ``ClangOption``. Options intended for ``clang -cc1`` +must be explicitly marked with the ``CC1Option`` flag. Flags that specify +``CC1Option`` but not ``ClangOption`` will only be accessible via ``-cc1``. +This is similar for other driver modes, such as ``clang-cl`` or ``flang``. Next, parse (or manufacture) the command line arguments in the Clang driver and use them to construct the ``-cc1`` job: @@ -874,7 +878,8 @@ present on command line. .. code-block:: text - def fignore_exceptions : Flag<["-"], "fignore-exceptions">, Flags<[CC1Option]>, + def fignore_exceptions : Flag<["-"], "fignore-exceptions">, + Visibility<[ClangOption, CC1Option]>, MarshallingInfoFlag>; **Negative Flag** @@ -884,7 +889,8 @@ present on command line. .. code-block:: text - def fno_verbose_asm : Flag<["-"], "fno-verbose-asm">, Flags<[CC1Option]>, + def fno_verbose_asm : Flag<["-"], "fno-verbose-asm">, + Visibility<[ClangOption, CC1Option]>, MarshallingInfoNegativeFlag>; **Negative and Positive Flag** @@ -898,9 +904,9 @@ line. defm legacy_pass_manager : BoolOption<"f", "legacy-pass-manager", CodeGenOpts<"LegacyPassManager">, DefaultFalse, - PosFlag, - NegFlag, - BothFlags<[CC1Option]>>; + PosFlag, + NegFlag, + BothFlags<[], [ClangOption, CC1Option]>>; With most such pair of flags, the ``-cc1`` frontend accepts only the flag that changes the default key path value. The Clang driver is responsible for @@ -912,10 +918,11 @@ full names of both flags. The positive flag would then be named ``flegacy-pass-manager`` and the negative ``fno-legacy-pass-manager``. ``BoolOption`` also implies the ``-`` prefix for both flags. It's also possible to use ``BoolFOption`` that implies the ``"f"`` prefix and ``Group``. -The ``PosFlag`` and ``NegFlag`` classes hold the associated boolean value, an -array of elements passed to the ``Flag`` class and the help text. The optional -``BothFlags`` class holds an array of ``Flag`` elements that are common for both -the positive and negative flag and their common help text suffix. +The ``PosFlag`` and ``NegFlag`` classes hold the associated boolean value, +arrays of elements passed to the ``Flag`` and ``Visibility`` classes and the +help text. The optional ``BothFlags`` class holds arrays of ``Flag`` and +``Visibility`` elements that are common for both the positive and negative flag +and their common help text suffix. **String** @@ -924,7 +931,8 @@ the option appears on the command line, the argument value is simply copied. .. code-block:: text - def isysroot : JoinedOrSeparate<["-"], "isysroot">, Flags<[CC1Option]>, + def isysroot : JoinedOrSeparate<["-"], "isysroot">, + Visibility<[ClangOption, CC1Option]>, MarshallingInfoString, [{"/"}]>; **List of Strings** @@ -935,7 +943,8 @@ vector. .. code-block:: text - def frewrite_map_file : Separate<["-"], "frewrite-map-file">, Flags<[CC1Option]>, + def frewrite_map_file : Separate<["-"], "frewrite-map-file">, + Visibility<[ClangOption, CC1Option]>, MarshallingInfoStringVector>; **Integer** @@ -946,7 +955,8 @@ and the result is assigned to the key path on success. .. code-block:: text - def mstack_probe_size : Joined<["-"], "mstack-probe-size=">, Flags<[CC1Option]>, + def mstack_probe_size : Joined<["-"], "mstack-probe-size=">, + Visibility<[ClangOption, CC1Option]>, MarshallingInfoInt, "4096">; **Enumeration** @@ -963,7 +973,8 @@ comma-separated string values and elements of the array within .. code-block:: text - def mthread_model : Separate<["-"], "mthread-model">, Flags<[CC1Option]>, + def mthread_model : Separate<["-"], "mthread-model">, + Visibility<[ClangOption, CC1Option]>, Values<"posix,single">, NormalizedValues<["POSIX", "Single"]>, NormalizedValuesScope<"LangOptions::ThreadModelKind">, MarshallingInfoEnum, "POSIX">; @@ -983,7 +994,8 @@ Finally, the command line is parsed according to the primary annotation. .. code-block:: text - def fms_extensions : Flag<["-"], "fms-extensions">, Flags<[CC1Option]>, + def fms_extensions : Flag<["-"], "fms-extensions">, + Visibility<[ClangOption, CC1Option]>, MarshallingInfoFlag>, ImpliedByAnyOf<[fms_compatibility.KeyPath], "true">; @@ -994,7 +1006,8 @@ true. .. code-block:: text - def fopenmp_enable_irbuilder : Flag<["-"], "fopenmp-enable-irbuilder">, Flags<[CC1Option]>, + def fopenmp_enable_irbuilder : Flag<["-"], "fopenmp-enable-irbuilder">, + Visibility<[ClangOption, CC1Option]>, MarshallingInfoFlag>, ShouldParseIf; @@ -2863,7 +2876,7 @@ are created implicitly. The following spellings are accepted: syntax and placement. ``CXX11`` Spelled with a C++-style ``[[attr]]`` syntax with an optional vendor-specific namespace. - ``C2x`` Spelled with a C-style ``[[attr]]`` syntax with an + ``C23`` Spelled with a C-style ``[[attr]]`` syntax with an optional vendor-specific namespace. ``Declspec`` Spelled with a Microsoft-style ``__declspec(attr)`` syntax. @@ -2895,7 +2908,7 @@ are created implicitly. The following spellings are accepted: The C++ standard specifies that “any [non-standard attribute] that is not recognized by the implementation is ignored†(``[dcl.attr.grammar]``). -The rule for C is similar. This makes ``CXX11`` and ``C2x`` spellings +The rule for C is similar. This makes ``CXX11`` and ``C23`` spellings unsuitable for attributes that affect the type system, that change the binary interface of the code, or that have other similar semantic meaning. diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 1a3a5a14a867b..8da10412f1bf2 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -612,7 +612,7 @@ to perform additional operations on certain scalar and vector types. Let ``T`` be one of the following types: -* an integer type (as in C2x 6.2.5p19), but excluding enumerated types and _Bool +* an integer type (as in C23 6.2.5p22), but excluding enumerated types and ``bool`` * the standard floating types float or double * a half-precision floating point type, if one is supported on the target * a vector type. @@ -643,6 +643,8 @@ Unless specified otherwise operation(±0) = ±0 and operation(±infinity) = ±in T __builtin_elementwise_bitreverse(T x) return the integer represented after reversing the bits of x integer types T __builtin_elementwise_exp(T x) returns the base-e exponential, e^x, of the specified value floating point types T __builtin_elementwise_exp2(T x) returns the base-2 exponential, 2^x, of the specified value floating point types + + T __builtin_elementwise_sqrt(T x) return the square root of a floating-point number floating point types T __builtin_elementwise_roundeven(T x) round x to the nearest integer value in floating point format, floating point types rounding halfway cases to even (that is, to the nearest value that is an even integer), regardless of the current rounding @@ -812,6 +814,7 @@ to ``float``; see below for more information on this emulation. * AMDGPU (natively) * SPIR (natively) * X86 (if SSE2 is available; natively if AVX512-FP16 is also available) + * RISC-V (natively if Zfh or Zhinx is available) * ``__bf16`` is supported on the following targets (currently never natively): * 32-bit ARM @@ -1462,8 +1465,8 @@ Conditional ``explicit`` __cpp_conditional_explicit C++20 ``static operator()`` __cpp_static_call_operator C++23 C++03 -------------------------------------- -------------------------------- ------------- ------------- Designated initializers (N494) C99 C89 -Array & element qualification (N2607) C2x C89 -Attributes (N2335) C2x C89 +Array & element qualification (N2607) C23 C89 +Attributes (N2335) C23 C89 ====================================== ================================ ============= ============= Type Trait Primitives @@ -2407,7 +2410,7 @@ this always needs to be called to grow the table. It takes three arguments. The first argument is the WebAssembly table to grow. The second argument is the reference typed value to store in the new table entries (the initialization value), and the third argument -is the amound to grow the table by. It returns the previous table size +is the amount to grow the table by. It returns the previous table size or -1. It will return -1 if not enough space could be allocated. .. code-block:: c++ @@ -3690,7 +3693,7 @@ A predefined typedef for the target-specific ``va_list`` type. A builtin function for the target-specific ``va_start`` function-like macro. The ``parameter-name`` argument is the name of the parameter preceding the -ellipsis (``...``) in the function signature. Alternatively, in C2x mode or +ellipsis (``...``) in the function signature. Alternatively, in C23 mode or later, it may be the integer literal ``0`` if there is no parameter preceding the ellipsis. This function initializes the given ``__builtin_va_list`` object. It is undefined behavior to call this function on an already initialized @@ -5243,12 +5246,18 @@ The following x86-specific intrinsics can be used in constant expressions: * ``_castf64_u64`` * ``_castu32_f32`` * ``_castu64_f64`` +* ``__lzcnt16`` +* ``__lzcnt`` +* ``__lzcnt64`` * ``_mm_popcnt_u32`` * ``_mm_popcnt_u64`` * ``_popcnt32`` * ``_popcnt64`` * ``__popcntd`` * ``__popcntq`` +* ``__popcnt16`` +* ``__popcnt`` +* ``__popcnt64`` * ``__rolb`` * ``__rolw`` * ``__rold`` diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index d30e151edae05..a526751f0116f 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -2531,12 +2531,12 @@

Node Matchers

class array { T data[Size]; }; -dependentSizedArrayType +dependentSizedArrayType() matches "T data[Size]" -Matcher<Type>dependentSizedExtVectorTypeMatcher<DependentSizedExtVectorType>... +Matcher<Type>dependentSizedExtVectorTypeMatcher<DependentSizedExtVectorType>...
Matches C++ extended vector type where either the type or size is dependent.
 
 Given
@@ -2544,7 +2544,7 @@ 

Node Matchers

class vector { typedef T __attribute__((ext_vector_type(Size))) type; }; -dependentSizedExtVectorType +dependentSizedExtVectorType() matches "T __attribute__((ext_vector_type(Size)))"
@@ -2648,6 +2648,18 @@

Node Matchers

+Matcher<Type>macroQualifiedTypeMatcher<MacroQualifiedType>... +
Matches qualified types when the qualifier is applied via a macro.
+
+Given
+  #define CDECL __attribute__((cdecl))
+  typedef void (CDECL *X)();
+  typedef void (__attribute__((cdecl)) *Y)();
+macroQualifiedType()
+  matches the type of the typedef declaration of X but not Y.
+
+ + Matcher<Type>memberPointerTypeMatcher<MemberPointerType>...
Matches member pointer types.
 Given
diff --git a/clang/docs/MatrixTypes.rst b/clang/docs/MatrixTypes.rst
index 2efebbfad9381..e32e13b73aba6 100644
--- a/clang/docs/MatrixTypes.rst
+++ b/clang/docs/MatrixTypes.rst
@@ -33,7 +33,7 @@ program is ill-formed.
 Currently, the element type of a matrix is only permitted to be one of the
 following types:
 
-* an integer type (as in C2x 6.2.5p19), but excluding enumerated types and ``_Bool``
+* an integer type (as in C23 6.2.5p22), but excluding enumerated types and ``bool``
 * the standard floating types ``float`` or ``double``
 * a half-precision floating point type, if one is supported on the target
 
@@ -68,7 +68,7 @@ rows and columns are the same and the value's elements can be converted to the
 element type of the result type. The result is a matrix where each element is
 the converted corresponding element.
 
-A value of any real type (as in C2x 6.2.5p17) can be converted to a matrix type
+A value of any real type (as in C23 6.2.5p14) can be converted to a matrix type
 if it can be converted to the element type of the matrix. The result is a
 matrix where all elements are the converted original value.
 
diff --git a/clang/docs/OpenCLSupport.rst b/clang/docs/OpenCLSupport.rst
index 43c30970d113b..f9b6564a9ebaa 100644
--- a/clang/docs/OpenCLSupport.rst
+++ b/clang/docs/OpenCLSupport.rst
@@ -333,7 +333,7 @@ Missing features or with limited support
 - IR generation for non-trivial global destructors is incomplete (See:
   `PR48047 `_).
 
-- Support of `destrutors with non-default address spaces
+- Support of `destructors with non-default address spaces
   `_
   is incomplete (See: `D109609 `_).
 
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index d3757c833ef83..57f945f266821 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -46,6 +46,8 @@ C++ Specific Potentially Breaking Changes
 
 ABI Changes in This Version
 ---------------------------
+- Following the SystemV ABI for x86-64, ``__int128`` arguments will no longer
+  be split between a register and a stack slot.
 
 What's New in Clang |release|?
 ==============================
@@ -85,10 +87,17 @@ C++2c Feature Support
       int _; // Previously diagnosed under -Wunused, no longer diagnosed
     }
 
+- Attributes now expect unevaluated strings in attributes parameters that are string literals.
+  This is applied to both C++ standard attributes, and other attributes supported by Clang.
+  This completes the implementation of `P2361R6 Unevaluated Strings `_
 
 
 Resolutions to C++ Defect Reports
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+- Implemented `CWG1473 `_ which allows spaces after ``operator""``.
+  Clang used to err on the lack of space when the literal suffix identifier was invalid in
+  all the language modes, which contradicted the deprecation of the whitespaces.
+  Also turn on ``-Wdeprecated-literal-operator`` by default in all the language modes.
 
 C Language Changes
 ------------------
@@ -96,8 +105,12 @@ C Language Changes
   constant expressions.  This change is more consistent with the behavior of
   GCC.
 
-C2x Feature Support
+C23 Feature Support
 ^^^^^^^^^^^^^^^^^^^
+- Clang now accepts ``-std=c23`` and ``-std=gnu23`` as language standard modes,
+  and the ``__STDC_VERSION__`` macro now expands to ``202311L`` instead of its
+  previous placeholder value. Clang continues to accept ``-std=c2x`` and
+  ``-std=gnu2x`` as aliases for C23 and GNU C23, respectively.
 
 Non-comprehensive list of changes in this release
 -------------------------------------------------
@@ -111,6 +124,8 @@ Deprecated Compiler Flags
 Modified Compiler Flags
 -----------------------
 
+* ``-Woverriding-t-option`` is renamed to ``-Woverriding-option``.
+
 Removed Compiler Flags
 -------------------------
 
@@ -123,6 +138,12 @@ Improvements to Clang's diagnostics
   template-specialization function calls.
 - Clang contexpr evaluator now displays notes as well as an error when a constructor
   of a base class is not called in the constructor of its derived class.
+- Clang no longer emits ``-Wmissing-variable-declarations`` for variables declared
+  with the ``register`` storage class.
+- Clang's ``-Wtautological-negation-compare`` flag now diagnoses logical
+  tautologies like ``x && !x`` and ``!x || x`` in expressions. This also
+  makes ``-Winfinite-recursion`` diagnose more cases.
+  (`#56035: `_).
 
 Bug Fixes in This Version
 -------------------------
@@ -132,6 +153,12 @@ Bug Fixes in This Version
   class, which can result in miscompiles in some cases.
 - Fix crash on use of a variadic overloaded operator.
   (`#42535 _`)
+- Fix a hang on valid C code passing a function type as an argument to
+  ``typeof`` to form a function declaration.
+  (`#64713 _`)
+- Clang now reports missing-field-initializers warning for missing designated
+  initializers in C++.
+  (`#56628 `_)
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -149,17 +176,20 @@ Bug Fixes to C++ Support
 
 - Fix a crash caused by some named unicode escape sequences designating
   a Unicode character whose name contains a ``-``.
-  (`Fixes #64161 _`)
+  (Fixes `#64161 `_)
 
-- Fix cases where we ignore ambiguous name lookup when looking up memebers.
-  (`#22413 _`),
-  (`#29942 _`),
-  (`#35574 _`) and
-  (`#27224 _`).
+- Fix cases where we ignore ambiguous name lookup when looking up members.
+  (`#22413 `_),
+  (`#29942 `_),
+  (`#35574 `_) and
+  (`#27224 `_).
 
 - Clang emits an error on substitution failure within lambda body inside a
   requires-expression. This fixes:
-  (`#64138 _`).
+  (`#64138 `_).
+
+- Update ``FunctionDeclBitfields.NumFunctionDeclBits``. This fixes:
+  (`#64171 `_).
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -179,12 +209,18 @@ Miscellaneous Clang Crashes Fixed
   terminated. Clang should now also recover better when an @end is missing
   between blocks.
   `Issue 64065 `_
+- Fixed a crash when check array access on zero-length element.
+  `Issue 64564 `_
 
 Target Specific Changes
 -----------------------
 
 AMDGPU Support
 ^^^^^^^^^^^^^^
+- Use pass-by-reference (byref) in stead of pass-by-value (byval) for struct
+  arguments in C ABI. Callee is responsible for allocating stack memory and
+  copying the value of the struct if modified. Note that AMDGPU backend still
+  supports byval for struct arguments.
 
 X86 Support
 ^^^^^^^^^^^
@@ -198,16 +234,10 @@ Windows Support
 LoongArch Support
 ^^^^^^^^^^^^^^^^^
 
-- An ABI mismatch between GCC and Clang related to the handling of empty structs
-  in C++ parameter passing under ``lp64d`` ABI was fixed.
-
 RISC-V Support
 ^^^^^^^^^^^^^^
 - Unaligned memory accesses can be toggled by ``-m[no-]unaligned-access`` or the
   aliases ``-m[no-]strict-align``.
-- An ABI mismatch between GCC and Clang related to the handling of empty
-  structs in C++ parameter passing under the hard floating point calling
-  conventions was fixed.
 
 CUDA/HIP Language Changes
 ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -237,11 +267,13 @@ Floating Point Support in Clang
 - Add ``__builtin_set_flt_rounds`` builtin for X86, x86_64, Arm and AArch64 only.
 - Add ``__builtin_elementwise_pow`` builtin for floating point types only.
 - Add ``__builtin_elementwise_bitreverse`` builtin for integer types only.
+- Add ``__builtin_elementwise_sqrt`` builtin for floating point types only.
 
 AST Matchers
 ------------
 - Add ``convertVectorExpr``.
 - Add ``dependentSizedExtVectorType``.
+- Add ``macroQualifiedType``.
 
 clang-format
 ------------
@@ -249,9 +281,15 @@ clang-format
 libclang
 --------
 
+- Exposed arguments of ``clang::annotate``.
+
 Static Analyzer
 ---------------
 
+- Added a new checker ``core.BitwiseShift`` which reports situations where
+  bitwise shift operators produce undefined behavior (because some operand is
+  negative or too large).
+
 .. _release-notes-sanitizers:
 
 Sanitizers
diff --git a/clang/docs/StandardCPlusPlusModules.rst b/clang/docs/StandardCPlusPlusModules.rst
index 06609063c61c9..3aeb55d8f4dad 100644
--- a/clang/docs/StandardCPlusPlusModules.rst
+++ b/clang/docs/StandardCPlusPlusModules.rst
@@ -1072,12 +1072,6 @@ the user can choose to get the dependency information per file. For example:
 
   $ clang-scan-deps -format=p1689 -- /clang++ -std=c++20 impl_part.cppm -c -o impl_part.o
 
-.. warning::
-
-   The ``/clang++`` should point to the real
-   binary and not to a symlink. If it points to a symlink the include paths
-   will not be correctly resolved.
-
 And we'll get:
 
 .. code-block:: text
@@ -1134,6 +1128,32 @@ We will get:
 When clang-scan-deps detects ``-MF`` option, clang-scan-deps will try to write the
 dependency information for headers to the file specified by ``-MF``.
 
+Possible Issues: Failed to find system headers
+----------------------------------------------
+
+In case the users encounter errors like ``fatal error: 'stddef.h' file not found``,
+probably the specified ``/clang++`` refers to a symlink
+instead a real binary. There are 4 potential solutions to the problem:
+
+* (1) End users can resolve the issue by pointing the specified compiler executable to
+  the real binary instead of the symlink.
+* (2) End users can invoke ``/clang++ -print-resource-dir``
+  to get the corresponding resource directory for your compiler and add that directory
+  to the include search paths manually in the build scripts.
+* (3) Build systems that use a compilation database as the input for clang-scan-deps
+  scanner, the build system can add the flag ``--resource-dir-recipe invoke-compiler`` to
+  the clang-scan-deps scanner to calculate the resources directory dynamically.
+  The calculation happens only once for a unique ``/clang++``.
+* (4) For build systems that invokes the clang-scan-deps scanner per file, repeatedly
+  calculating the resource directory may be inefficient. In such cases, the build
+  system can cache the resource directory by itself and pass ``-resource-dir ``
+  explicitly in the command line options:
+
+.. code-block:: console
+
+  $ clang-scan-deps -format=p1689 -- /clang++ -std=c++20 -resource-dir  mod.cppm -c -o mod.o
+
+
 Possible Questions
 ==================
 
diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index a774fd91aa277..d7854d3920f4a 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -2759,9 +2759,6 @@ programs using the same instrumentation method as ``-fprofile-generate``.
   overhead. ``prefer-atomic`` will be transformed to ``atomic`` when supported
   by the target, or ``single`` otherwise.
 
-  This option currently works with ``-fprofile-arcs`` and ``-fprofile-instr-generate``,
-  but not with ``-fprofile-generate``.
-
 Disabling Instrumentation
 ^^^^^^^^^^^^^^^^^^^^^^^^^
 
@@ -3172,7 +3169,7 @@ Differences between various standard modes
 
 clang supports the -std option, which changes what language mode clang uses.
 The supported modes for C are c89, gnu89, c94, c99, gnu99, c11, gnu11, c17,
-gnu17, c2x, gnu2x, and various aliases for those modes. If no -std option is
+gnu17, c23, gnu23, and various aliases for those modes. If no -std option is
 specified, clang defaults to gnu17 mode. Many C99 and C11 features are
 supported in earlier modes as a conforming extension, with a warning. Use
 ``-pedantic-errors`` to request an error if a feature from a later standard
@@ -3224,6 +3221,19 @@ Differences between ``*11`` and ``*17`` modes:
 
 -  ``__STDC_VERSION__`` is defined to ``201710L`` rather than ``201112L``.
 
+Differences between ``*17`` and ``*23`` modes:
+
+- ``__STDC_VERSION__`` is defined to ``202311L`` rather than ``201710L``.
+- ``nullptr`` and ``nullptr_t`` are supported, only in ``*23`` mode.
+- ``ATOMIC_VAR_INIT`` is removed from ``*23`` mode.
+- ``bool``, ``true``, ``false``, ``alignas``, ``alignof``, ``static_assert``,
+  and ``thread_local` are now first-class keywords, only in ``*23`` mode.
+- ``typeof`` and ``typeof_unqual`` are supported, only ``*23`` mode.
+- Bit-precise integers (``_BitInt(N)``) are supported by default in ``*23``
+  mode, and as an extension in ``*17`` and earlier modes.
+- ``[[]]`` attributes are supported by default in ``*23`` mode, and as an
+  extension in ``*17`` and earlier modes.
+
 GCC extensions not implemented yet
 ----------------------------------
 
diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index 97b5369ac86c9..ac6919e4c9829 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -29,6 +29,56 @@ Models core language features and contains general-purpose checkers such as divi
 null pointer dereference, usage of uninitialized values, etc.
 *These checkers must be always switched on as other checker rely on them.*
 
+.. _core-BitwiseShift:
+
+core.BitwiseShift (C, C++)
+""""""""""""""""""""""""""
+
+Finds undefined behavior caused by the bitwise left- and right-shift operator
+operating on integer types.
+
+By default, this checker only reports situations when the right operand is
+either negative or larger than the bit width of the type of the left operand;
+these are logically unsound.
+
+Moreover, if the pedantic mode is activated by
+``-analyzer-config core.BitwiseShift:Pedantic=true``, then this checker also
+reports situations where the _left_ operand of a shift operator is negative or
+overflow occurs during the right shift of a signed value. (Most compilers
+handle these predictably, but the C standard and the C++ standards before C++20
+say that they're undefined behavior. In the C++20 standard these constructs are
+well-defined, so activating pedantic mode in C++20 has no effect.)
+
+**Examples**
+
+.. code-block:: cpp
+
+ static_assert(sizeof(int) == 4, "assuming 32-bit int")
+
+ void basic_examples(int a, int b) {
+   if (b < 0) {
+     b = a << b; // warn: right operand is negative in left shift
+   } else if (b >= 32) {
+     b = a >> b; // warn: right shift overflows the capacity of 'int'
+   }
+ }
+
+ int pedantic_examples(int a, int b) {
+   if (a < 0) {
+     return a >> b; // warn: left operand is negative in right shift
+   }
+   a = 1000u << 31; // OK, overflow of unsigned value is well-defined, a == 0
+   if (b > 10) {
+     a = b << 31; // this is undefined before C++20, but the checker doesn't
+                  // warn because it doesn't know the exact value of b
+   }
+   return 1000 << 31; // warn: this overflows the capacity of 'int'
+ }
+
+**Solution**
+
+Ensure the shift operands are in proper range before shifting.
+
 .. _core-CallAndMessage:
 
 core.CallAndMessage (C, C++, ObjC)
@@ -321,10 +371,10 @@ Check for memory leaks. Traces memory managed by new/delete.
    int *p = new int;
  } // warn
 
-.. _cplusplus-PlacementNewChecker:
+.. _cplusplus-PlacementNew:
 
-cplusplus.PlacementNewChecker (C++)
-"""""""""""""""""""""""""""""""""""
+cplusplus.PlacementNew (C++)
+""""""""""""""""""""""""""""
 Check if default placement new is provided with pointers to sufficient storage capacity.
 
 .. code-block:: cpp
@@ -2375,8 +2425,8 @@ The malicious data is injected at the taint source (e.g. ``getenv()`` call)
 which is then propagated through function calls and being used as arguments of
 sensitive operations, also called as taint sinks (e.g. ``system()`` call).
 
-One can defend agains this type of vulnerability by always checking and
-santizing the potentially malicious, untrusted user input.
+One can defend against this type of vulnerability by always checking and
+sanitizing the potentially malicious, untrusted user input.
 
 The goal of the checker is to discover and show to the user these potential
 taint source-sink pairs and the propagation call chain.
@@ -2438,7 +2488,7 @@ Unfortunately, the checker cannot discover automatically that the programmer
 have performed data sanitation, so it still emits the warning.
 
 One can get rid of this superflous warning by telling by specifying the
-sanitation functions in the taint configuation file (see
+sanitation functions in the taint configuration file (see
 :doc:`user-docs/TaintAnalysisConfiguration`).
 
 .. code-block:: YAML
@@ -2499,7 +2549,7 @@ and add the `csa_mark_sanitized` function.
 
 Then calling `csa_mark_sanitized(X)` will tell the analyzer that `X` is safe to
 be used after this point, because its contents are verified. It is the
-responisibility of the programmer to ensure that this verification was indeed
+responsibility of the programmer to ensure that this verification was indeed
 correct. Please note that `csa_mark_sanitized` function is only declared and
 used during Clang Static Analysis and skipped in (production) builds.
 
diff --git a/clang/docs/tools/clang-formatted-files.txt b/clang/docs/tools/clang-formatted-files.txt
index 27aab1e130524..e22f01e8c150e 100644
--- a/clang/docs/tools/clang-formatted-files.txt
+++ b/clang/docs/tools/clang-formatted-files.txt
@@ -2185,6 +2185,8 @@ flang/include/flang/Runtime/time-intrinsic.h
 flang/include/flang/Runtime/transformational.h
 flang/include/flang/Runtime/type-code.h
 flang/include/flang/Semantics/attr.h
+flang/include/flang/Semantics/expression.h
+flang/include/flang/Semantics/openmp-directive-sets.h
 flang/include/flang/Semantics/runtime-type-info.h
 flang/include/flang/Semantics/scope.h
 flang/include/flang/Semantics/semantics.h
diff --git a/clang/examples/Attribute/Attribute.cpp b/clang/examples/Attribute/Attribute.cpp
index 008da2e18e44f..9d6cf9ae36c6a 100644
--- a/clang/examples/Attribute/Attribute.cpp
+++ b/clang/examples/Attribute/Attribute.cpp
@@ -29,10 +29,10 @@ struct ExampleAttrInfo : public ParsedAttrInfo {
     // number of arguments. This just illustrates how many arguments a
     // `ParsedAttrInfo` can hold, we will not use that much in this example.
     OptArgs = 15;
-    // GNU-style __attribute__(("example")) and C++/C2x-style [[example]] and
+    // GNU-style __attribute__(("example")) and C++/C23-style [[example]] and
     // [[plugin::example]] supported.
     static constexpr Spelling S[] = {{ParsedAttr::AS_GNU, "example"},
-                                     {ParsedAttr::AS_C2x, "example"},
+                                     {ParsedAttr::AS_C23, "example"},
                                      {ParsedAttr::AS_CXX11, "example"},
                                      {ParsedAttr::AS_CXX11, "plugin::example"}};
     Spellings = S;
diff --git a/clang/include/clang/APINotes/APINotesWriter.h b/clang/include/clang/APINotes/APINotesWriter.h
new file mode 100644
index 0000000000000..eab03a2a83012
--- /dev/null
+++ b/clang/include/clang/APINotes/APINotesWriter.h
@@ -0,0 +1,37 @@
+//===-- APINotesWriter.h - API Notes Writer ---------------------*- 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_APINOTES_WRITER_H
+#define LLVM_CLANG_APINOTES_WRITER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include 
+
+namespace clang {
+class FileEntry;
+
+namespace api_notes {
+class APINotesWriter {
+  class Implementation;
+  std::unique_ptr Implementation;
+
+public:
+  APINotesWriter(llvm::StringRef ModuleName, const FileEntry *SF);
+  ~APINotesWriter();
+
+  APINotesWriter(const APINotesWriter &) = delete;
+  APINotesWriter &operator=(const APINotesWriter &) = delete;
+
+  void writeToStream(llvm::raw_ostream &OS);
+};
+} // namespace api_notes
+} // namespace clang
+
+#endif
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 615b477fc95db..3540f3f7d36a8 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1698,7 +1698,7 @@ class ASTContext : public RefCountedBase {
   /// Return a ObjCObjectPointerType type for the given ObjCObjectType.
   QualType getObjCObjectPointerType(QualType OIT) const;
 
-  /// C2x feature and GCC extension.
+  /// C23 feature and GCC extension.
   QualType getTypeOfExprType(Expr *E, TypeOfKind Kind) const;
   QualType getTypeOfType(QualType QT, TypeOfKind Kind) const;
 
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 1b99709ca90d9..12137387b676a 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -1702,7 +1702,7 @@ class DeclContext {
   };
 
   /// Number of non-inherited bits in FunctionDeclBitfields.
-  enum { NumFunctionDeclBits = 30 };
+  enum { NumFunctionDeclBits = 31 };
 
   /// Stores the bits used by CXXConstructorDecl. If modified
   /// NumCXXConstructorDeclBits and the accessor
@@ -1714,12 +1714,12 @@ class DeclContext {
     /// For the bits in FunctionDeclBitfields.
     uint64_t : NumFunctionDeclBits;
 
-    /// 21 bits to fit in the remaining available space.
+    /// 20 bits to fit in the remaining available space.
     /// Note that this makes CXXConstructorDeclBitfields take
     /// exactly 64 bits and thus the width of NumCtorInitializers
     /// will need to be shrunk if some bit is added to NumDeclContextBitfields,
     /// NumFunctionDeclBitfields or CXXConstructorDeclBitfields.
-    uint64_t NumCtorInitializers : 18;
+    uint64_t NumCtorInitializers : 17;
     uint64_t IsInheritingConstructor : 1;
 
     /// Whether this constructor has a trail-allocated explicit specifier.
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index 7185d91af07cf..353b6331ac7c1 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -760,7 +760,7 @@ class CXXBoolLiteralExpr : public Expr {
 /// The null pointer literal (C++11 [lex.nullptr])
 ///
 /// Introduced in C++11, the only literal of type \c nullptr_t is \c nullptr.
-/// This also implements the null pointer literal in C2x (C2x 6.4.1) which is
+/// This also implements the null pointer literal in C23 (C23 6.4.1) which is
 /// intended to have the same semantics as the feature in C++.
 class CXXNullPtrLiteralExpr : public Expr {
 public:
diff --git a/clang/include/clang/AST/JSONNodeDumper.h b/clang/include/clang/AST/JSONNodeDumper.h
index d3668e7656f78..c2cd3070e2768 100644
--- a/clang/include/clang/AST/JSONNodeDumper.h
+++ b/clang/include/clang/AST/JSONNodeDumper.h
@@ -208,6 +208,14 @@ class JSONNodeDumper
   void Visit(const concepts::Requirement *R);
   void Visit(const APValue &Value, QualType Ty);
 
+  void VisitAliasAttr(const AliasAttr *AA);
+  void VisitCleanupAttr(const CleanupAttr *CA);
+  void VisitDeprecatedAttr(const DeprecatedAttr *DA);
+  void VisitUnavailableAttr(const UnavailableAttr *UA);
+  void VisitSectionAttr(const SectionAttr *SA);
+  void VisitVisibilityAttr(const VisibilityAttr *VA);
+  void VisitTLSModelAttr(const TLSModelAttr *TA);
+
   void VisitTypedefType(const TypedefType *TT);
   void VisitUsingType(const UsingType *TT);
   void VisitFunctionType(const FunctionType *T);
diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h
index 0a20f2a9c4864..c2d5e7d9cd4e1 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -67,7 +67,7 @@ struct PrintingPolicy {
         SuppressTypedefs(false), SuppressFinalSpecifier(false),
         SuppressTemplateArgsInCXXConstructors(false),
         SuppressDefaultTemplateArgs(true), Bool(LO.Bool),
-        Nullptr(LO.CPlusPlus11 || LO.C2x), NullptrTypeInNamespace(LO.CPlusPlus),
+        Nullptr(LO.CPlusPlus11 || LO.C23), NullptrTypeInNamespace(LO.CPlusPlus),
         Restrict(LO.C99), Alignof(LO.CPlusPlus11), UnderscoreAlignof(LO.C11),
         UseVoidForZeroParams(!LO.CPlusPlus),
         SplitTemplateClosers(!LO.CPlusPlus11), TerseOutput(false),
diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h
index 354d7eae61111..eecf0e88776a7 100644
--- a/clang/include/clang/AST/TextNodeDumper.h
+++ b/clang/include/clang/AST/TextNodeDumper.h
@@ -202,6 +202,8 @@ class TextNodeDumper
   void dumpName(const NamedDecl *ND);
   void dumpAccessSpecifier(AccessSpecifier AS);
   void dumpCleanupObject(const ExprWithCleanups::CleanupObject &C);
+  void dumpTemplateSpecializationKind(TemplateSpecializationKind TSK);
+  void dumpNestedNameSpecifier(const NestedNameSpecifier *NNS);
 
   void dumpDeclRef(const Decl *D, StringRef Label = {});
 
@@ -246,6 +248,7 @@ class TextNodeDumper
   void VisitLabelStmt(const LabelStmt *Node);
   void VisitGotoStmt(const GotoStmt *Node);
   void VisitCaseStmt(const CaseStmt *Node);
+  void VisitReturnStmt(const ReturnStmt *Node);
   void VisitCompoundStmt(const CompoundStmt *Node);
   void VisitConstantExpr(const ConstantExpr *Node);
   void VisitCallExpr(const CallExpr *Node);
@@ -253,6 +256,7 @@ class TextNodeDumper
   void VisitCastExpr(const CastExpr *Node);
   void VisitImplicitCastExpr(const ImplicitCastExpr *Node);
   void VisitDeclRefExpr(const DeclRefExpr *Node);
+  void VisitDependentScopeDeclRefExpr(const DependentScopeDeclRefExpr *Node);
   void VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *Node);
   void VisitSYCLUniqueStableIdExpr(const SYCLUniqueStableIdExpr *Node);
   void VisitPredefinedExpr(const PredefinedExpr *Node);
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 796798b52fd02..8256637138a24 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -817,6 +817,26 @@ class QualType {
   /// Determine whether this type is const-qualified.
   bool isConstQualified() const;
 
+  enum class NonConstantStorageReason {
+    MutableField,
+    NonConstNonReferenceType,
+    NonTrivialCtor,
+    NonTrivialDtor,
+  };
+  /// Determine whether instances of this type can be placed in immutable
+  /// storage.
+  /// If ExcludeCtor is true, the duration when the object's constructor runs
+  /// will not be considered. The caller will need to verify that the object is
+  /// not written to during its construction. ExcludeDtor works similarly.
+  std::optional
+  isNonConstantStorage(const ASTContext &Ctx, bool ExcludeCtor,
+                       bool ExcludeDtor);
+
+  bool isConstantStorage(const ASTContext &Ctx, bool ExcludeCtor,
+                         bool ExcludeDtor) {
+    return !isNonConstantStorage(Ctx, ExcludeCtor, ExcludeDtor);
+  }
+
   /// Determine whether this particular QualType instance has the
   /// "restrict" qualifier set, without looking through typedefs that may have
   /// added "restrict" at a different level.
@@ -1011,7 +1031,7 @@ class QualType {
   /// type.  To strip qualifiers even from within a sugared array type, use
   /// ASTContext::getUnqualifiedArrayType.
   ///
-  /// Note: In C, the _Atomic qualifier is special (see C2x 6.2.5p29 for
+  /// Note: In C, the _Atomic qualifier is special (see C23 6.2.5p32 for
   /// details), and it is not stripped by this function. Use
   /// getAtomicUnqualifiedType() to strip qualifiers including _Atomic.
   inline QualType getUnqualifiedType() const;
@@ -2055,7 +2075,7 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
   /// Determines if this is a sizeless type supported by the
   /// 'arm_sve_vector_bits' type attribute, which can be applied to a single
   /// SVE vector or predicate, excluding tuple types such as svint32x4_t.
-  bool isVLSTBuiltinType() const;
+  bool isSveVLSBuiltinType() const;
 
   /// Returns the representative type for the element of an SVE builtin type.
   /// This is used to represent fixed-length SVE vectors created with the
@@ -2264,7 +2284,7 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
   bool isCARCBridgableType() const;
   bool isTemplateTypeParmType() const;          // C++ template type parameter
   bool isNullPtrType() const;                   // C++11 std::nullptr_t or
-                                                // C2x nullptr_t
+                                                // C23   nullptr_t
   bool isNothrowT() const;                      // C++   std::nothrow_t
   bool isAlignValT() const;                     // C++17 std::align_val_t
   bool isStdByteType() const;                   // C++17 std::byte
@@ -3628,7 +3648,7 @@ class MatrixType : public Type, public llvm::FoldingSetNode {
   QualType getElementType() const { return ElementType; }
 
   /// Valid elements types are the following:
-  /// * an integer type (as in C2x 6.2.5p19), but excluding enumerated types
+  /// * an integer type (as in C23 6.2.5p22), but excluding enumerated types
   ///   and _Bool
   /// * the standard floating types float or double
   /// * a half-precision floating point type, if one is supported on the target
@@ -4705,8 +4725,8 @@ class MacroQualifiedType : public Type {
   }
 };
 
-/// Represents a `typeof` (or __typeof__) expression (a C2x feature and GCC
-/// extension) or a `typeof_unqual` expression (a C2x feature).
+/// Represents a `typeof` (or __typeof__) expression (a C23 feature and GCC
+/// extension) or a `typeof_unqual` expression (a C23 feature).
 class TypeOfExprType : public Type {
   Expr *TOExpr;
 
@@ -4756,8 +4776,8 @@ class DependentTypeOfExprType
                       Expr *E, bool IsUnqual);
 };
 
-/// Represents `typeof(type)`, a C2x feature and GCC extension, or
-/// `typeof_unqual(type), a C2x feature.
+/// Represents `typeof(type)`, a C23 feature and GCC extension, or
+/// `typeof_unqual(type), a C23 feature.
 class TypeOfType : public Type {
   friend class ASTContext; // ASTContext creates these.
 
diff --git a/clang/include/clang/AST/VTableBuilder.h b/clang/include/clang/AST/VTableBuilder.h
index 1bf7d0467aa3f..fbf6c041a1ec1 100644
--- a/clang/include/clang/AST/VTableBuilder.h
+++ b/clang/include/clang/AST/VTableBuilder.h
@@ -279,7 +279,7 @@ class VTableLayout {
 
   AddressPointLocation getAddressPoint(BaseSubobject Base) const {
     assert(AddressPoints.count(Base) && "Did not find address point!");
-    return AddressPoints.find(Base)->second;
+    return AddressPoints.lookup(Base);
   }
 
   const AddressPointsMapTy &getAddressPoints() const {
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 620f0cb7872f1..bdc9a5624ce3a 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -7258,6 +7258,18 @@ AST_TYPELOC_TRAVERSE_MATCHER_DECL(
 ///   matches "typedef int X"
 extern const AstTypeMatcher typedefType;
 
+/// Matches qualified types when the qualifier is applied via a macro.
+///
+/// Given
+/// \code
+///   #define CDECL __attribute__((cdecl))
+///   typedef void (CDECL *X)();
+///   typedef void (__attribute__((cdecl)) *Y)();
+/// \endcode
+/// macroQualifiedType()
+///   matches the type of the typedef declaration of \c X but not \c Y.
+extern const AstTypeMatcher macroQualifiedType;
+
 /// Matches enum types.
 ///
 /// Given
diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
index 13f28076c6f4d..c865b2e8bdb37 100644
--- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
+++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
@@ -20,7 +20,19 @@
 
 namespace clang {
 
-using DefMapTy = llvm::DenseMap>;
+using VarGrpTy = std::vector;
+using VarGrpRef = ArrayRef;
+
+class VariableGroupsManager {
+public:
+  VariableGroupsManager() = default;
+  virtual ~VariableGroupsManager() = default;
+  /// Returns the set of variables (including `Var`) that need to be fixed
+  /// together in one step.
+  ///
+  /// `Var` must be a variable that needs fix (so it must be in a group).
+  virtual VarGrpRef getGroupOfVar(const VarDecl *Var) const =0;
+};
 
 /// The interface that lets the caller handle unsafe buffer usage analysis
 /// results by overriding this class's handle... methods.
@@ -53,7 +65,7 @@ class UnsafeBufferUsageHandler {
   /// all variables that must be fixed together (i.e their types must be changed to the
   /// same target type to prevent type mismatches) into a single fixit.
   virtual void handleUnsafeVariableGroup(const VarDecl *Variable,
-                                         const DefMapTy &VarGrpMap,
+                                         const VariableGroupsManager &VarGrpMgr,
                                          FixItList &&Fixes) = 0;
 
 #ifndef NDEBUG
diff --git a/clang/include/clang/Analysis/CFG.h b/clang/include/clang/Analysis/CFG.h
index eacebe176dda4..cf4fa2da2a358 100644
--- a/clang/include/clang/Analysis/CFG.h
+++ b/clang/include/clang/Analysis/CFG.h
@@ -1162,6 +1162,7 @@ class CFGCallback {
   CFGCallback() = default;
   virtual ~CFGCallback() = default;
 
+  virtual void logicAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {}
   virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {}
   virtual void compareBitwiseEquality(const BinaryOperator *B,
                                       bool isAlwaysTrue) {}
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 4d2e45164797c..a3b861c7292c8 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -310,8 +310,8 @@ class CXX11
     : Spelling {
   string Namespace = namespace;
 }
-class C2x
-    : Spelling {
+class C23
+    : Spelling {
   string Namespace = namespace;
 }
 
@@ -334,14 +334,14 @@ class Pragma : Spelling {
 }
 
 // The GCC spelling implies GNU, CXX11<"gnu", name>, and optionally,
-// C2x<"gnu", name>. This spelling should be used for any GCC-compatible
+// C23<"gnu", name>. This spelling should be used for any GCC-compatible
 // attributes.
 class GCC : Spelling {
   bit AllowInC = allowInC;
 }
 
 // The Clang spelling implies GNU, CXX11<"clang", name>, and optionally,
-// C2x<"clang", name>. This spelling should be used for any Clang-specific
+// C23<"clang", name>. This spelling should be used for any Clang-specific
 // attributes.
 class Clang
     : Spelling {
@@ -748,7 +748,7 @@ def Alias : Attr {
 
 def BuiltinAlias : Attr {
   let Spellings = [CXX11<"clang", "builtin_alias">,
-                   C2x<"clang", "builtin_alias">,
+                   C23<"clang", "builtin_alias">,
                    GNU<"clang_builtin_alias">];
   let Args = [IdentifierArgument<"BuiltinName">];
   let Subjects = SubjectList<[Function], ErrorDiag>;
@@ -810,9 +810,9 @@ def AlignNatural : InheritableAttr {
 
 def AlwaysInline : DeclOrStmtAttr {
   let Spellings = [GCC<"always_inline">, CXX11<"clang", "always_inline">,
-                   C2x<"clang", "always_inline">, CustomKeyword<"__forceinline">];
+                   C23<"clang", "always_inline">, CustomKeyword<"__forceinline">];
   let Accessors = [Accessor<"isClangAlwaysInline", [CXX11<"clang", "always_inline">,
-                                                    C2x<"clang", "always_inline">]>];
+                                                    C23<"clang", "always_inline">]>];
   let Subjects = SubjectList<[Function, Stmt], WarnDiag,
                              "functions and statements">;
   let Documentation = [AlwaysInlineDocs];
@@ -898,7 +898,7 @@ def Annotate : InheritableParamAttr {
 }
 
 def AnnotateType : TypeAttr {
-  let Spellings = [CXX11<"clang", "annotate_type">, C2x<"clang", "annotate_type">];
+  let Spellings = [CXX11<"clang", "annotate_type">, C23<"clang", "annotate_type">];
   let Args = [StringArgument<"Annotation">, VariadicExprArgument<"Args">];
   let HasCustomParsing = 1;
   let AcceptsExprPack = 1;
@@ -1879,7 +1879,7 @@ def C11NoReturn : InheritableAttr {
 
 def CXX11NoReturn : InheritableAttr {
   let Spellings = [CXX11<"", "noreturn", 200809>,
-                   C2x<"", "noreturn", 202202>, C2x<"", "_Noreturn", 202202>];
+                   C23<"", "noreturn", 202202>, C23<"", "_Noreturn", 202202>];
   let Subjects = SubjectList<[Function], ErrorDiag>;
   let Documentation = [CXX11NoReturnDocs];
 }
@@ -2024,7 +2024,7 @@ def RenderScriptKernel : Attr {
 def Deprecated : InheritableAttr {
   let Spellings = [GCC<"deprecated">, Declspec<"deprecated">,
                    CXX11<"","deprecated", 201309>,
-                   C2x<"", "deprecated", 201904>];
+                   C23<"", "deprecated", 201904>];
   let Args = [StringArgument<"Message", 1>,
               // An optional string argument that enables us to provide a
               // Fix-It.
@@ -2082,7 +2082,7 @@ def ExtVectorType : Attr {
 
 def FallThrough : StmtAttr {
   let Spellings = [CXX11<"", "fallthrough", 201603>,
-                   C2x<"", "fallthrough", 201910>,
+                   C23<"", "fallthrough", 201910>,
                    CXX11<"clang", "fallthrough">, GCC<"fallthrough">];
   // The attribute only applies to a NullStmt, but we have special fix-it
   // behavior if applied to a case label.
@@ -2092,12 +2092,12 @@ def FallThrough : StmtAttr {
 }
 
 def Likely : StmtAttr {
-  let Spellings = [CXX11<"", "likely", 201803>, C2x<"clang", "likely">];
+  let Spellings = [CXX11<"", "likely", 201803>, C23<"clang", "likely">];
   let Documentation = [LikelihoodDocs];
 }
 
 def Unlikely : StmtAttr {
-  let Spellings = [CXX11<"", "unlikely", 201803>, C2x<"clang", "unlikely">];
+  let Spellings = [CXX11<"", "unlikely", 201803>, C23<"clang", "unlikely">];
   let Documentation = [LikelihoodDocs];
 }
 def : MutualExclusions<[Likely, Unlikely]>;
@@ -2821,10 +2821,10 @@ def Convergent : InheritableAttr {
 
 def NoInline : DeclOrStmtAttr {
   let Spellings = [CustomKeyword<"__noinline__">, GCC<"noinline">,
-                   CXX11<"clang", "noinline">, C2x<"clang", "noinline">,
+                   CXX11<"clang", "noinline">, C23<"clang", "noinline">,
                    Declspec<"noinline">];
   let Accessors = [Accessor<"isClangNoInline", [CXX11<"clang", "noinline">,
-                                                C2x<"clang", "noinline">]>];
+                                                C23<"clang", "noinline">]>];
   let Documentation = [NoInlineDocs];
   let Subjects = SubjectList<[Function, Stmt], WarnDiag,
                              "functions and statements">;
@@ -4021,7 +4021,7 @@ def ObjCRequiresPropertyDefs : InheritableAttr {
 
 def Unused : InheritableAttr {
   let Spellings = [CXX11<"", "maybe_unused", 201603>, GCC<"unused">,
-                   C2x<"", "maybe_unused", 202106>];
+                   C23<"", "maybe_unused", 202106>];
   let Subjects = SubjectList<[Var, ObjCIvar, Type, Enum, EnumConstant, Label,
                               Field, ObjCMethod, FunctionLike]>;
   let Documentation = [WarnMaybeUnusedDocs];
@@ -4115,7 +4115,7 @@ def WarnUnused : InheritableAttr {
 
 def WarnUnusedResult : InheritableAttr {
   let Spellings = [CXX11<"", "nodiscard", 201907>,
-                   C2x<"", "nodiscard", 202003>,
+                   C23<"", "nodiscard", 202003>,
                    CXX11<"clang", "warn_unused_result">,
                    GCC<"warn_unused_result">];
   let Subjects = SubjectList<[ObjCMethod, Enum, Record, FunctionLike, TypedefName]>;
diff --git a/clang/include/clang/Basic/AttributeCommonInfo.h b/clang/include/clang/Basic/AttributeCommonInfo.h
index 6396c0dc6ef02..e57adc4bf5b99 100644
--- a/clang/include/clang/Basic/AttributeCommonInfo.h
+++ b/clang/include/clang/Basic/AttributeCommonInfo.h
@@ -31,7 +31,7 @@ class AttributeCommonInfo {
     AS_CXX11,
 
     /// [[...]]
-    AS_C2x,
+    AS_C23,
 
     /// __declspec(...)
     AS_Declspec,
@@ -104,7 +104,7 @@ class AttributeCommonInfo {
 
     static Form GNU() { return AS_GNU; }
     static Form CXX11() { return AS_CXX11; }
-    static Form C2x() { return AS_C2x; }
+    static Form C23() { return AS_C23; }
     static Form Declspec() { return AS_Declspec; }
     static Form Microsoft() { return AS_Microsoft; }
     static Form Keyword(bool IsAlignas, bool IsRegularKeywordAttribute) {
@@ -188,12 +188,12 @@ class AttributeCommonInfo {
 
   bool isCXX11Attribute() const { return SyntaxUsed == AS_CXX11 || IsAlignas; }
 
-  bool isC2xAttribute() const { return SyntaxUsed == AS_C2x; }
+  bool isC23Attribute() const { return SyntaxUsed == AS_C23; }
 
   /// The attribute is spelled [[]] in either C or C++ mode, including standard
   /// attributes spelled with a keyword, like alignas.
   bool isStandardAttributeSyntax() const {
-    return isCXX11Attribute() || isC2xAttribute();
+    return isCXX11Attribute() || isC23Attribute();
   }
 
   bool isGNUAttribute() const { return SyntaxUsed == AS_GNU; }
diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def
index 1189a66a8fdd8..3af46529860bb 100644
--- a/clang/include/clang/Basic/Builtins.def
+++ b/clang/include/clang/Basic/Builtins.def
@@ -694,6 +694,7 @@ BUILTIN(__builtin_elementwise_round, "v.", "nct")
 BUILTIN(__builtin_elementwise_rint, "v.", "nct")
 BUILTIN(__builtin_elementwise_nearbyint, "v.", "nct")
 BUILTIN(__builtin_elementwise_sin, "v.", "nct")
+BUILTIN(__builtin_elementwise_sqrt, "v.", "nct")
 BUILTIN(__builtin_elementwise_trunc, "v.", "nct")
 BUILTIN(__builtin_elementwise_canonicalize, "v.", "nct")
 BUILTIN(__builtin_elementwise_copysign, "v.", "nct")
@@ -1016,12 +1017,12 @@ LANGBUILTIN(__iso_volatile_store16, "vsD*s",     "n", ALL_MS_LANGUAGES)
 LANGBUILTIN(__iso_volatile_store32, "viD*i",     "n", ALL_MS_LANGUAGES)
 LANGBUILTIN(__iso_volatile_store64, "vLLiD*LLi", "n", ALL_MS_LANGUAGES)
 LANGBUILTIN(__noop,           "i.",  "n", ALL_MS_LANGUAGES)
-LANGBUILTIN(__lzcnt16, "UsUs",    "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__lzcnt,   "UiUi",    "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__lzcnt64, "UWiUWi",  "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__popcnt16, "UsUs",   "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__popcnt,   "UiUi",   "nc", ALL_MS_LANGUAGES)
-LANGBUILTIN(__popcnt64, "UWiUWi", "nc", ALL_MS_LANGUAGES)
+LANGBUILTIN(__lzcnt16, "UsUs",    "ncE", ALL_MS_LANGUAGES)
+LANGBUILTIN(__lzcnt,   "UiUi",    "ncE", ALL_MS_LANGUAGES)
+LANGBUILTIN(__lzcnt64, "UWiUWi",  "ncE", ALL_MS_LANGUAGES)
+LANGBUILTIN(__popcnt16, "UsUs",   "ncE", ALL_MS_LANGUAGES)
+LANGBUILTIN(__popcnt,   "UiUi",   "ncE", ALL_MS_LANGUAGES)
+LANGBUILTIN(__popcnt64, "UWiUWi", "ncE", ALL_MS_LANGUAGES)
 LANGBUILTIN(_ReturnAddress, "v*", "n", ALL_MS_LANGUAGES)
 LANGBUILTIN(_rotl8,  "UcUcUc",    "nE", ALL_MS_LANGUAGES)
 LANGBUILTIN(_rotl16, "UsUsUc",    "nE", ALL_MS_LANGUAGES)
diff --git a/clang/include/clang/Basic/BuiltinsLoongArch.def b/clang/include/clang/Basic/BuiltinsLoongArch.def
index 7f2c8403410dd..20510e18fe58c 100644
--- a/clang/include/clang/Basic/BuiltinsLoongArch.def
+++ b/clang/include/clang/Basic/BuiltinsLoongArch.def
@@ -16,8 +16,7 @@
 #endif
 
 // TODO: Support more builtins.
-// TODO: Added feature constraints.
-TARGET_BUILTIN(__builtin_loongarch_cacop_d, "vLiULiLi", "nc", "64bit")
+TARGET_BUILTIN(__builtin_loongarch_cacop_d, "vWiUWiWi", "nc", "64bit")
 TARGET_BUILTIN(__builtin_loongarch_cacop_w, "viUii", "nc", "32bit")
 TARGET_BUILTIN(__builtin_loongarch_dbar, "vIUi", "nc", "")
 TARGET_BUILTIN(__builtin_loongarch_ibar, "vIUi", "nc", "")
@@ -26,36 +25,36 @@ TARGET_BUILTIN(__builtin_loongarch_movgr2fcsr, "vIUiUi", "nc", "f")
 TARGET_BUILTIN(__builtin_loongarch_break, "vIUi", "nc", "")
 TARGET_BUILTIN(__builtin_loongarch_syscall, "vIUi", "nc", "")
 TARGET_BUILTIN(__builtin_loongarch_cpucfg, "UiUi", "nc", "")
-TARGET_BUILTIN(__builtin_loongarch_asrtle_d, "vLiLi", "nc", "64bit")
-TARGET_BUILTIN(__builtin_loongarch_asrtgt_d, "vLiLi", "nc", "64bit")
+TARGET_BUILTIN(__builtin_loongarch_asrtle_d, "vWiWi", "nc", "64bit")
+TARGET_BUILTIN(__builtin_loongarch_asrtgt_d, "vWiWi", "nc", "64bit")
 
 TARGET_BUILTIN(__builtin_loongarch_crc_w_b_w, "iii", "nc", "64bit")
 TARGET_BUILTIN(__builtin_loongarch_crc_w_h_w, "iii", "nc", "64bit")
 TARGET_BUILTIN(__builtin_loongarch_crc_w_w_w, "iii", "nc", "64bit")
-TARGET_BUILTIN(__builtin_loongarch_crc_w_d_w, "iLii", "nc", "64bit")
+TARGET_BUILTIN(__builtin_loongarch_crc_w_d_w, "iWii", "nc", "64bit")
 TARGET_BUILTIN(__builtin_loongarch_crcc_w_b_w, "iii", "nc", "64bit")
 TARGET_BUILTIN(__builtin_loongarch_crcc_w_h_w, "iii", "nc", "64bit")
 TARGET_BUILTIN(__builtin_loongarch_crcc_w_w_w, "iii", "nc", "64bit")
-TARGET_BUILTIN(__builtin_loongarch_crcc_w_d_w, "iLii", "nc", "64bit")
+TARGET_BUILTIN(__builtin_loongarch_crcc_w_d_w, "iWii", "nc", "64bit")
 
 TARGET_BUILTIN(__builtin_loongarch_csrrd_w, "UiIUi", "nc", "")
-TARGET_BUILTIN(__builtin_loongarch_csrrd_d, "ULiIUi", "nc", "64bit")
+TARGET_BUILTIN(__builtin_loongarch_csrrd_d, "UWiIUi", "nc", "64bit")
 TARGET_BUILTIN(__builtin_loongarch_csrwr_w, "UiUiIUi", "nc", "")
-TARGET_BUILTIN(__builtin_loongarch_csrwr_d, "ULiULiIUi", "nc", "64bit")
+TARGET_BUILTIN(__builtin_loongarch_csrwr_d, "UWiUWiIUi", "nc", "64bit")
 TARGET_BUILTIN(__builtin_loongarch_csrxchg_w, "UiUiUiIUi", "nc", "")
-TARGET_BUILTIN(__builtin_loongarch_csrxchg_d, "ULiULiULiIUi", "nc", "64bit")
+TARGET_BUILTIN(__builtin_loongarch_csrxchg_d, "UWiUWiUWiIUi", "nc", "64bit")
 
 TARGET_BUILTIN(__builtin_loongarch_iocsrrd_b, "UiUi", "nc", "")
 TARGET_BUILTIN(__builtin_loongarch_iocsrrd_h, "UiUi", "nc", "")
 TARGET_BUILTIN(__builtin_loongarch_iocsrrd_w, "UiUi", "nc", "")
-TARGET_BUILTIN(__builtin_loongarch_iocsrrd_d, "ULiUi", "nc", "64bit")
+TARGET_BUILTIN(__builtin_loongarch_iocsrrd_d, "UWiUi", "nc", "64bit")
 TARGET_BUILTIN(__builtin_loongarch_iocsrwr_b, "vUiUi", "nc", "")
 TARGET_BUILTIN(__builtin_loongarch_iocsrwr_h, "vUiUi", "nc", "")
 TARGET_BUILTIN(__builtin_loongarch_iocsrwr_w, "vUiUi", "nc", "")
-TARGET_BUILTIN(__builtin_loongarch_iocsrwr_d, "vULiUi", "nc", "64bit")
+TARGET_BUILTIN(__builtin_loongarch_iocsrwr_d, "vUWiUi", "nc", "64bit")
 
-TARGET_BUILTIN(__builtin_loongarch_lddir_d, "LiLiIULi", "nc", "64bit")
-TARGET_BUILTIN(__builtin_loongarch_ldpte_d, "vLiIULi", "nc", "64bit")
+TARGET_BUILTIN(__builtin_loongarch_lddir_d, "WiWiIUWi", "nc", "64bit")
+TARGET_BUILTIN(__builtin_loongarch_ldpte_d, "vWiIUWi", "nc", "64bit")
 
 #undef BUILTIN
 #undef TARGET_BUILTIN
diff --git a/clang/include/clang/Basic/BuiltinsRISCV.def b/clang/include/clang/Basic/BuiltinsRISCV.def
index 50e912c2c1c74..1528b18c82ead 100644
--- a/clang/include/clang/Basic/BuiltinsRISCV.def
+++ b/clang/include/clang/Basic/BuiltinsRISCV.def
@@ -86,8 +86,8 @@ TARGET_BUILTIN(__builtin_riscv_sm3p0, "UiUi", "nc", "zksh")
 TARGET_BUILTIN(__builtin_riscv_sm3p1, "UiUi", "nc", "zksh")
 
 // Zihintntl extension
-TARGET_BUILTIN(__builtin_riscv_ntl_load, "v.", "t", "experimental-zihintntl")
-TARGET_BUILTIN(__builtin_riscv_ntl_store, "v.", "t", "experimental-zihintntl")
+TARGET_BUILTIN(__builtin_riscv_ntl_load, "v.", "t", "zihintntl")
+TARGET_BUILTIN(__builtin_riscv_ntl_store, "v.", "t", "zihintntl")
 
 #undef BUILTIN
 #undef TARGET_BUILTIN
diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td
index 6f547ef06de86..38ab10a984165 100644
--- a/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -56,7 +56,9 @@ def err_expected_string_literal : Error<"expected string literal "
   "%select{in %1|for diagnostic message in static_assert|"
           "for optional message in 'availability' attribute|"
           "for %select{language name|source container name|USR}1 in "
-          "'external_source_symbol' attribute}0">;
+          "'external_source_symbol' attribute|"
+          "as argument of '%1' attribute}0">;
+
 def err_invalid_string_udl : Error<
   "string literal with user-defined suffix cannot be used here">;
 def err_invalid_character_udl : Error<
@@ -132,10 +134,10 @@ def warn_missing_type_specifier : Warning<
   InGroup, DefaultIgnore;
 
 def ext_c_empty_initializer : Extension<
-  "use of an empty initializer is a C2x extension">, InGroup;
-def warn_c2x_compat_empty_initializer : Warning<
-  "use of an empty initializer is incompatible with C standards before C2x">,
-  InGroup, DefaultIgnore;
+  "use of an empty initializer is a C23 extension">, InGroup;
+def warn_c23_compat_empty_initializer : Warning<
+  "use of an empty initializer is incompatible with C standards before C23">,
+  InGroup, DefaultIgnore;
 }
 
 let CategoryName = "Nullability Issue" in {
@@ -223,12 +225,12 @@ def err_cxx23_size_t_suffix: Error<
 def err_size_t_literal_too_large: Error<
   "%select{signed |}0'size_t' literal is out of range of possible "
   "%select{signed |}0'size_t' values">;
-def ext_c2x_bitint_suffix : ExtWarn<
-  "'_BitInt' suffix for literals is a C2x extension">,
-  InGroup;
-def warn_c2x_compat_bitint_suffix : Warning<
-  "'_BitInt' suffix for literals is incompatible with C standards before C2x">,
-  InGroup, DefaultIgnore;
+def ext_c23_bitint_suffix : ExtWarn<
+  "'_BitInt' suffix for literals is a C23 extension">,
+  InGroup;
+def warn_c23_compat_bitint_suffix : Warning<
+  "'_BitInt' suffix for literals is incompatible with C standards before C23">,
+  InGroup, DefaultIgnore;
 def err_integer_literal_too_large : Error<
   "integer literal is too large to be represented in any %select{signed |}0"
   "integer type">;
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index fe9b372c68987..2b1cddf51ffa5 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -478,9 +478,9 @@ def warn_drv_no_floating_point_registers: Warning<
   InGroup;
 def warn_ignoring_ftabstop_value : Warning<
   "ignoring invalid -ftabstop value '%0', using default value %1">;
-def warn_drv_overriding_flag_option : Warning<
+def warn_drv_overriding_option : Warning<
   "overriding '%0' option with '%1'">,
-  InGroup>;
+  InGroup>;
 def warn_drv_treating_input_as_cxx : Warning<
   "treating '%0' input as '%1' when in C++ mode, this behavior is deprecated">,
   InGroup;
@@ -756,6 +756,10 @@ def warn_drv_fjmc_for_elf_only : Warning<
   "-fjmc works only for ELF; option ignored">,
   InGroup;
 
+def warn_drv_for_elf_only : Warning<
+  "'%0' works only for ELF; option ignored">,
+  InGroup;
+
 def warn_target_override_arm64ec : Warning<
   "/arm64EC has been overridden by specified target: %0; option ignored">,
   InGroup;
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index e46164495998a..ee1ef1f25c660 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -20,6 +20,7 @@ def DeprecatedStaticAnalyzerFlag : DiagGroup<"deprecated-static-analyzer-flag">;
 // Empty DiagGroups are recognized by clang but ignored.
 def ODR : DiagGroup<"odr">;
 def : DiagGroup<"abi">;
+def : DiagGroup<"gnu-empty-initializer">; // Now a C extension, not GNU.
 def AbsoluteValue : DiagGroup<"absolute-value">;
 def MisspelledAssumption : DiagGroup<"misspelled-assumption">;
 def UnknownAssumption : DiagGroup<"unknown-assumption">;
@@ -145,7 +146,9 @@ def MacroRedefined : DiagGroup<"macro-redefined">;
 def BuiltinMacroRedefined : DiagGroup<"builtin-macro-redefined">;
 def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">;
 def C99Compat : DiagGroup<"c99-compat">;
-def C2xCompat : DiagGroup<"c2x-compat">;
+def C23Compat : DiagGroup<"c23-compat">;
+def : DiagGroup<"c2x-compat", [C23Compat]>;
+
 def CXXCompat: DiagGroup<"c++-compat">;
 def ExternCCompat : DiagGroup<"extern-c-compat">;
 def KeywordCompat : DiagGroup<"keyword-compat">;
@@ -288,9 +291,11 @@ def : DiagGroup<"c++1z-compat-mangling", [CXX17CompatMangling]>;
 def NoexceptType : DiagGroup<"noexcept-type", [CXX17CompatMangling]>;
 
 // Warnings for C code which is not compatible with previous C standards.
-def CPre2xCompat : DiagGroup<"pre-c2x-compat">;
-def CPre2xCompatPedantic : DiagGroup<"pre-c2x-compat-pedantic",
-                                     [CPre2xCompat]>;
+def CPre23Compat : DiagGroup<"pre-c23-compat">;
+def CPre23CompatPedantic : DiagGroup<"pre-c23-compat-pedantic",
+                                     [CPre23Compat]>;
+def : DiagGroup<"pre-c2x-compat", [CPre23Compat]>;
+def : DiagGroup<"pre-c2x-compat-pedantic", [CPre23CompatPedantic]>;
 
 // Warning for treating C input as C++ input.
 def ExpectedFileType : DiagGroup<"expected-file-type">;
@@ -446,6 +451,7 @@ def IgnoredQualifiers : DiagGroup<"ignored-qualifiers", [IgnoredReferenceQualifi
 def : DiagGroup<"import">;
 def GNUIncludeNext : DiagGroup<"gnu-include-next">;
 def IncompatibleMSStruct : DiagGroup<"incompatible-ms-struct">;
+def IncompatibleMSPragmaSection : DiagGroup<"incompatible-ms-pragma-section">;
 def IncompatiblePointerTypesDiscardsQualifiers
   : DiagGroup<"incompatible-pointer-types-discards-qualifiers">;
 def IncompatibleFunctionPointerTypes
@@ -677,13 +683,15 @@ def TautologicalOverlapCompare : DiagGroup<"tautological-overlap-compare">;
 def TautologicalBitwiseCompare : DiagGroup<"tautological-bitwise-compare">;
 def TautologicalUndefinedCompare : DiagGroup<"tautological-undefined-compare">;
 def TautologicalObjCBoolCompare : DiagGroup<"tautological-objc-bool-compare">;
+def TautologicalNegationCompare : DiagGroup<"tautological-negation-compare">;
 def TautologicalCompare : DiagGroup<"tautological-compare",
                                     [TautologicalConstantCompare,
                                      TautologicalPointerCompare,
                                      TautologicalOverlapCompare,
                                      TautologicalBitwiseCompare,
                                      TautologicalUndefinedCompare,
-                                     TautologicalObjCBoolCompare]>;
+                                     TautologicalObjCBoolCompare,
+                                     TautologicalNegationCompare]>;
 def HeaderHygiene : DiagGroup<"header-hygiene">;
 def DuplicateDeclSpecifier : DiagGroup<"duplicate-decl-specifier">;
 def CompareDistinctPointerType : DiagGroup<"compare-distinct-pointer-types">;
@@ -1150,8 +1158,10 @@ def C11 : DiagGroup<"c11-extensions">;
 // A warning group for warnings about using C99 features as extensions.
 def C99 : DiagGroup<"c99-extensions", [C99Designator]>;
 
-// A warning group for warnings about using C2x features as extensions.
-def C2x : DiagGroup<"c2x-extensions">;
+// A warning group for warnings about using C23 features as extensions.
+def C23 : DiagGroup<"c23-extensions">;
+
+def : DiagGroup<"c2x-extensions", [C23]>;
 
 // A warning group for warnings about GCC extensions.
 def GNU : DiagGroup<"gnu", [GNUAlignofExpression, GNUAnonymousStruct,
@@ -1215,6 +1225,8 @@ def MicrosoftEndOfFile : DiagGroup<"microsoft-end-of-file">;
 def MicrosoftInaccessibleBase : DiagGroup<"microsoft-inaccessible-base">;
 def MicrosoftStaticAssert : DiagGroup<"microsoft-static-assert">;
 def MicrosoftInitFromPredefined : DiagGroup<"microsoft-init-from-predefined">;
+def MicrosoftStringLiteralFromPredefined : DiagGroup<
+    "microsoft-string-literal-from-predefined">;
 
 // Aliases.
 def : DiagGroup<"msvc-include", [MicrosoftInclude]>;
@@ -1232,7 +1244,8 @@ def Microsoft : DiagGroup<"microsoft",
      MicrosoftFlexibleArray, MicrosoftExtraQualification, MicrosoftCast,
      MicrosoftConstInit, MicrosoftVoidPseudoDtor, MicrosoftAnonTag,
      MicrosoftCommentPaste, MicrosoftEndOfFile, MicrosoftStaticAssert,
-     MicrosoftInitFromPredefined, MicrosoftInconsistentDllImport]>;
+     MicrosoftInitFromPredefined, MicrosoftStringLiteralFromPredefined,
+     MicrosoftInconsistentDllImport]>;
 
 def ClangClPch : DiagGroup<"clang-cl-pch">;
 
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 0eb270aeea0e5..c5da98c4f0001 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -82,8 +82,8 @@ def warn_cxx20_keyword : Warning<"'%0' is a keyword in C++20">,
   InGroup, DefaultIgnore;
 def warn_c99_keyword : Warning<"'%0' is a keyword in C99">,
   InGroup, DefaultIgnore;
-def warn_c2x_keyword : Warning<"'%0' is a keyword in C2x">,
-  InGroup, DefaultIgnore;
+def warn_c23_keyword : Warning<"'%0' is a keyword in C23">,
+  InGroup, DefaultIgnore;
 
 def ext_unterminated_char_or_string : ExtWarn<
   "missing terminating %select{'|'\"'}0 character">, InGroup;
@@ -197,14 +197,14 @@ def warn_cxx98_compat_literal_ucn_escape_basic_scs : Warning<
 def warn_cxx98_compat_literal_ucn_control_character : Warning<
   "universal character name referring to a control character "
   "is incompatible with C++98">, InGroup, DefaultIgnore;
-def warn_c2x_compat_literal_ucn_escape_basic_scs : Warning<
+def warn_c23_compat_literal_ucn_escape_basic_scs : Warning<
   "specifying character '%0' with a universal character name is "
-  "incompatible with C standards before C2x">,
-  InGroup, DefaultIgnore;
-def warn_c2x_compat_literal_ucn_control_character : Warning<
+  "incompatible with C standards before C23">,
+  InGroup, DefaultIgnore;
+def warn_c23_compat_literal_ucn_control_character : Warning<
   "universal character name referring to a control character "
-  "is incompatible with C standards before C2x">,
-  InGroup, DefaultIgnore;
+  "is incompatible with C standards before C23">,
+  InGroup, DefaultIgnore;
 def warn_ucn_not_valid_in_c89 : Warning<
   "universal character names are only valid in C99 or C++; "
   "treating as '\\' followed by identifier">, InGroup;
@@ -224,9 +224,9 @@ def err_invalid_suffix_constant : Error<
 def warn_cxx11_compat_digit_separator : Warning<
   "digit separators are incompatible with C++ standards before C++14">,
   InGroup, DefaultIgnore;
-def warn_c2x_compat_digit_separator : Warning<
-  "digit separators are incompatible with C standards before C2x">,
-  InGroup, DefaultIgnore;
+def warn_c23_compat_digit_separator : Warning<
+  "digit separators are incompatible with C standards before C23">,
+  InGroup, DefaultIgnore;
 def err_digit_separator_not_between_digits : Error<
   "digit separator cannot appear at %select{start|end}0 of digit sequence">;
 def warn_char_constant_too_large : Warning<
@@ -276,15 +276,13 @@ def warn_cxx11_compat_reserved_user_defined_literal : Warning<
   "identifier after literal will be treated as a reserved user-defined literal "
   "suffix in C++11">,
   InGroup, DefaultIgnore;
-def ext_reserved_user_defined_literal : ExtWarn<
-  "invalid suffix on literal; C++11 requires a space between literal and "
-  "identifier">, InGroup, DefaultError;
-def ext_ms_reserved_user_defined_literal : ExtWarn<
-  "invalid suffix on literal; C++11 requires a space between literal and "
-  "identifier">, InGroup;
 def err_unsupported_string_concat : Error<
   "unsupported non-standard concatenation of string literals">;
 
+def warn_unevaluated_string_prefix : Warning<
+  "encoding prefix '%0' on an unevaluated string literal has no effect"
+  "%select{| and is incompatible with c++2c}1">,
+  InGroup>;
 def err_unevaluated_string_prefix : Error<
   "an unevaluated string literal cannot have an encoding prefix">;
 def err_unevaluated_string_udl : Error<
@@ -411,13 +409,13 @@ def ext_pp_include_next_directive : Extension<
   "#include_next is a language extension">, InGroup;
 
 def ext_pp_warning_directive : Extension<
-  "#warning is a %select{C2x|C++23}0 extension">;
+  "#warning is a %select{C23|C++23}0 extension">;
 def warn_cxx23_compat_warning_directive : Warning<
   "#warning is incompatible with C++ standards before C++23">,
   InGroup, DefaultIgnore;
-def warn_c2x_compat_warning_directive : Warning<
-  "#warning is incompatible with C standards before C2x">,
-  InGroup, DefaultIgnore;
+def warn_c23_compat_warning_directive : Warning<
+  "#warning is incompatible with C standards before C23">,
+  InGroup, DefaultIgnore;
 
 def ext_pp_extra_tokens_at_eol : ExtWarn<
   "extra tokens at end of #%0 directive">, InGroup;
@@ -746,14 +744,14 @@ def warn_cxx98_compat_pp_line_too_big : Warning<
   "#line number greater than 32767 is incompatible with C++98">,
   InGroup, DefaultIgnore;
 
-def warn_c2x_compat_pp_directive : Warning<
+def warn_c23_compat_pp_directive : Warning<
   "use of a '#%select{|elifdef|elifndef}0' directive "
-  "is incompatible with C standards before C2x">,
-  InGroup, DefaultIgnore;
-def ext_c2x_pp_directive : ExtWarn<
+  "is incompatible with C standards before C23">,
+  InGroup, DefaultIgnore;
+def ext_c23_pp_directive : ExtWarn<
   "use of a '#%select{|elifdef|elifndef}0' directive "
-  "is a C2x extension">,
-  InGroup;
+  "is a C23 extension">,
+  InGroup;
 def warn_cxx23_compat_pp_directive : Warning<
   "use of a '#%select{|elifdef|elifndef}0' directive "
   "is incompatible with C++ standards before C++23">,
diff --git a/clang/include/clang/Basic/DiagnosticOptions.h b/clang/include/clang/Basic/DiagnosticOptions.h
index 7e218b9c71e69..0f3120859ecef 100644
--- a/clang/include/clang/Basic/DiagnosticOptions.h
+++ b/clang/include/clang/Basic/DiagnosticOptions.h
@@ -123,6 +123,10 @@ class DiagnosticOptions : public RefCountedBase{
   /// default).
   std::vector VerifyPrefixes;
 
+  /// The list of -Wsystem-header-in-module=... options used to override
+  /// whether -Wsystem-headers is enabled on a per-module basis.
+  std::vector SystemHeaderWarningsModules;
+
 public:
   // Define accessors/mutators for diagnostic options of enumeration type.
 #define DIAGOPT(Name, Bits, Default)
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index a804442ab34ec..178761bdcf4d5 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -165,9 +165,9 @@ def ext_c99_feature : Extension<
   "'%0' is a C99 extension">, InGroup;
 def ext_c11_feature : Extension<
   "'%0' is a C11 extension">, InGroup;
-def warn_c2x_compat_keyword : Warning<
- "'%0' is incompatible with C standards before C2x">,
- InGroup, DefaultIgnore;
+def warn_c23_compat_keyword : Warning<
+ "'%0' is incompatible with C standards before C23">,
+ InGroup, DefaultIgnore;
 
 def err_c11_noreturn_misplaced : Error<
   "'_Noreturn' keyword must precede function declarator">;
@@ -300,14 +300,14 @@ def note_force_empty_selector_name : Note<
   "or insert whitespace before ':' to use %0 as parameter name "
   "and have an empty entry in the selector">;
 def ext_c_label_end_of_compound_statement : ExtWarn<
-  "label at end of compound statement is a C2x extension">,
-   InGroup;
+  "label at end of compound statement is a C23 extension">,
+   InGroup;
 def ext_cxx_label_end_of_compound_statement : ExtWarn<
   "label at end of compound statement is a C++23 extension">,
    InGroup;
-def warn_c2x_compat_label_end_of_compound_statement : Warning<
-  "label at end of compound statement is incompatible with C standards before C2x">,
-  InGroup, DefaultIgnore;
+def warn_c23_compat_label_end_of_compound_statement : Warning<
+  "label at end of compound statement is incompatible with C standards before C23">,
+  InGroup, DefaultIgnore;
 def warn_cxx20_compat_label_end_of_compound_statement : Warning<
   "label at end of compound statement is incompatible with C++ standards before C++23">,
   InGroup, DefaultIgnore;
@@ -447,15 +447,15 @@ def ext_ms_static_assert : ExtWarn<
 def ext_cxx_static_assert_no_message : ExtWarn<
   "'static_assert' with no message is a C++17 extension">, InGroup;
 def ext_c_static_assert_no_message : ExtWarn<
-  "'_Static_assert' with no message is a C2x extension">, InGroup;
+  "'_Static_assert' with no message is a C23 extension">, InGroup;
 def warn_cxx14_compat_static_assert_no_message : Warning<
   "'static_assert' with no message is incompatible with C++ standards before "
   "C++17">,
   DefaultIgnore, InGroup;
 def warn_c17_compat_static_assert_no_message : Warning<
   "'_Static_assert' with no message is incompatible with C standards before "
-  "C2x">,
-  DefaultIgnore, InGroup;
+  "C23">,
+  DefaultIgnore, InGroup;
 def err_function_definition_not_allowed : Error<
   "function definition is not allowed here">;
 def err_expected_end_of_enumerator : Error<
@@ -704,7 +704,7 @@ def warn_cxx98_compat_noexcept_expr : Warning<
 def warn_cxx98_compat_nullptr : Warning<
   "'nullptr' is incompatible with C++98">, InGroup, DefaultIgnore;
 def ext_c_nullptr : Extension<
-  "'nullptr' is a C2x extension">, InGroup;
+  "'nullptr' is a C23 extension">, InGroup;
 
 def warn_wrong_clang_attr_namespace : Warning<
   "'__clang__' is a predefined macro name, not an attribute scope specifier; "
@@ -724,12 +724,12 @@ def warn_cxx98_compat_attribute : Warning<
 def warn_ext_cxx11_attributes : Extension<
   "[[]] attributes are a C++11 extension">,
   InGroup;
-def warn_pre_c2x_compat_attributes : Warning<
-  "[[]] attributes are incompatible with C standards before C2x">,
-  DefaultIgnore, InGroup;
-def warn_ext_c2x_attributes : Extension<
-  "[[]] attributes are a C2x extension">,
-  InGroup;
+def warn_pre_c23_compat_attributes : Warning<
+  "[[]] attributes are incompatible with C standards before C23">,
+  DefaultIgnore, InGroup;
+def warn_ext_c23_attributes : Extension<
+  "[[]] attributes are a C23 extension">,
+  InGroup;
 def err_cxx11_attribute_forbids_arguments : Error<
   "attribute %0 cannot have an argument list">;
 def err_attribute_requires_arguments : Error<
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 3d50aa847e577..d710bf6d7ce1a 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -115,6 +115,9 @@ def ext_predef_outside_function : Warning<
 def ext_init_from_predefined : ExtWarn<
   "initializing an array from a '%0' predefined identifier is a Microsoft extension">,
   InGroup;
+def ext_string_literal_from_predefined : ExtWarn<
+  "expansion of predefined identifier '%0' to a string literal is a Microsoft extension">,
+  InGroup;
 def warn_float_overflow : Warning<
   "magnitude of floating-point constant too large for type %0; maximum is %1">,
    InGroup;
@@ -340,9 +343,9 @@ def err_bad_parameter_name : Error<
   "%0 cannot be the name of a parameter">;
 def err_bad_parameter_name_template_id : Error<
   "parameter name cannot have template arguments">;
-def ext_parameter_name_omitted_c2x : ExtWarn<
-  "omitting the parameter name in a function definition is a C2x extension">,
-  InGroup;
+def ext_parameter_name_omitted_c23 : ExtWarn<
+  "omitting the parameter name in a function definition is a C23 extension">,
+  InGroup;
 def err_anyx86_interrupt_attribute : Error<
   "%select{x86|x86-64}0 'interrupt' attribute only applies to functions that "
   "have %select{a 'void' return type|"
@@ -451,7 +454,7 @@ def warn_reserved_extern_symbol: Warning<
   InGroup, DefaultIgnore;
 def warn_deprecated_literal_operator_id: Warning<
   "identifier %0 preceded by whitespace in a literal operator declaration "
-  "is deprecated">, InGroup, DefaultIgnore;
+  "is deprecated">, InGroup;
 def warn_reserved_module_name : Warning<
   "%0 is a reserved name for a module">, InGroup;
 
@@ -1036,6 +1039,9 @@ def warn_cxx_ms_struct :
 def err_pragma_pack_identifer_not_supported : Error<
   "specifying an identifier within `#pragma pack` is not supported on this target">;
 def err_section_conflict : Error<"%0 causes a section type conflict with %1">;
+def warn_section_msvc_compat : Warning<"`#pragma const_seg` for section %1 will"
+  " not apply to %0 due to the presence of a %select{mutable field||non-trivial constructor|non-trivial destructor}2">,
+  InGroup;
 def err_no_base_classes : Error<"invalid use of '__super', %0 has no base classes">;
 def err_invalid_super_scope : Error<"invalid use of '__super', "
   "this keyword can only be used inside class or member function scope">;
@@ -3685,6 +3691,14 @@ def err_attribute_vecreturn_only_pod_record : Error<
   "the vecreturn attribute can only be used on a POD (plain old data) class or structure (i.e. no virtual functions)">;
 def err_sme_attr_mismatch : Error<
   "function declared %0 was previously declared %1, which has different SME function attributes">;
+def err_sme_call_in_non_sme_target : Error<
+  "call to a streaming function requires 'sme'">;
+def err_sme_za_call_no_za_state : Error<
+  "call to a shared ZA function requires the caller to have ZA state">;
+def err_sme_definition_using_sm_in_non_sme_target : Error<
+  "function executed in streaming-SVE mode requires 'sme'">;
+def err_sme_definition_using_za_in_non_sme_target : Error<
+  "function using ZA state requires 'sme'">;
 def err_cconv_change : Error<
   "function declared '%0' here was previously declared "
   "%select{'%2'|without calling convention}1">;
@@ -4231,7 +4245,7 @@ def warn_vector_mode_deprecated : Warning<
   "use the 'vector_size' attribute instead">,
   InGroup;
 def warn_deprecated_noreturn_spelling : Warning<
-  "the '[[_Noreturn]]' attribute spelling is deprecated in C2x; use "
+  "the '[[_Noreturn]]' attribute spelling is deprecated in C23; use "
   "'[[noreturn]]' instead">, InGroup;
 def err_complex_mode_vector_type : Error<
   "type of machine mode does not support base vector types">;
@@ -5764,7 +5778,7 @@ def note_sentinel_here : Note<
   "%select{function|method|block}0 has been explicitly marked sentinel here">;
 def warn_strict_uses_without_prototype : Warning<
   "passing arguments to %select{a function|%1}0 without a prototype is "
-  "deprecated in all versions of C and is not supported in C2x">,
+  "deprecated in all versions of C and is not supported in C23">,
   InGroup;
 def warn_missing_prototype : Warning<
   "no previous prototype for function %0">,
@@ -5779,8 +5793,8 @@ def warn_strict_prototypes : Extension<
   "%select{in all versions of C|}0">, InGroup;
 def warn_non_prototype_changes_behavior : Warning<
   "a function %select{declaration|definition}0 without a prototype is "
-  "deprecated in all versions of C %select{and is not supported in C2x|and is "
-  "treated as a zero-parameter prototype in C2x, conflicting with a "
+  "deprecated in all versions of C %select{and is not supported in C23|and is "
+  "treated as a zero-parameter prototype in C23, conflicting with a "
   "%select{previous|subsequent}2 %select{declaration|definition}3}1">,
   InGroup;
 def note_conflicting_prototype : Note<"conflicting prototype is here">;
@@ -9857,6 +9871,12 @@ def warn_comparison_bitwise_always : Warning<
 def warn_comparison_bitwise_or : Warning<
   "bitwise or with non-zero value always evaluates to true">,
   InGroup, DefaultIgnore;
+def warn_tautological_negation_and_compare: Warning<
+  "'&&' of a value and its negation always evaluates to false">,
+  InGroup, DefaultIgnore;
+def warn_tautological_negation_or_compare: Warning<
+  "'||' of a value and its negation always evaluates to true">,
+  InGroup, DefaultIgnore;
 def warn_tautological_overlap_comparison : Warning<
   "overlapping comparisons always evaluate to %select{false|true}0">,
   InGroup, DefaultIgnore;
@@ -10056,7 +10076,7 @@ def warn_second_arg_of_va_start_not_last_named_param : Warning<
   InGroup;
 def warn_c17_compat_ellipsis_only_parameter : Warning<
   "'...' as the only parameter of a function is incompatible with C standards "
-  "before C2x">, DefaultIgnore, InGroup;
+  "before C23">, DefaultIgnore, InGroup;
 def warn_va_start_type_is_undefined : Warning<
   "passing %select{an object that undergoes default argument promotion|"
   "an object of reference type|a parameter declared with the 'register' "
@@ -11386,6 +11406,8 @@ def err_module_import_in_implementation : Error<
   "@import of module '%0' in implementation of '%1'; use #import">;
 
 // C++ Modules
+def err_module_import_non_interface_nor_parition : Error<
+  "import of module '%0' imported non C++20 importable modules">;
 def err_module_decl_not_at_start : Error<
   "module declaration must occur at the start of the translation unit">;
 def note_global_module_introducer_missing : Note<
@@ -12126,10 +12148,6 @@ def err_non_designated_init_used : Error<
 def err_cast_from_randomized_struct : Error<
   "casting from randomized structure pointer type %0 to %1">;
 
-// LoongArch-specific Diagnostics
-def err_loongarch_builtin_requires_la64 : Error<
-  "this builtin requires target: loongarch64">;
-
 // Unsafe buffer usage diagnostics.
 def warn_unsafe_buffer_variable : Warning<
   "%0 is an %select{unsafe pointer used for buffer access|unsafe buffer that "
@@ -12151,9 +12169,6 @@ def note_safe_buffer_usage_suggestions_disabled : Note<
 def note_safe_buffer_debug_mode : Note<"safe buffers debug: %0">;
 #endif
 
-def err_loongarch_builtin_requires_la32 : Error<
-  "this builtin requires target: loongarch32">;
-
 def err_builtin_pass_in_regs_non_class : Error<
   "argument %0 is not an unqualified class type">;
 
diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def
index e05ac46258272..cbeb92fbe4fdd 100644
--- a/clang/include/clang/Basic/Features.def
+++ b/clang/include/clang/Basic/Features.def
@@ -245,7 +245,7 @@ EXTENSION(c_generic_selections, true)
 EXTENSION(c_generic_selection_with_controlling_type, true)
 EXTENSION(c_static_assert, true)
 EXTENSION(c_thread_local, PP.getTargetInfo().isTLSSupported())
-// C2x features supported by other languages as extensions
+// C23 features supported by other languages as extensions
 EXTENSION(c_attributes, true)
 // C++11 features supported by other languages as extensions.
 EXTENSION(cxx_atomic, LangOpts.CPlusPlus)
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index ff827354716b8..dc13391639835 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -86,7 +86,7 @@
 LANGOPT(C99               , 1, 0, "C99")
 LANGOPT(C11               , 1, 0, "C11")
 LANGOPT(C17               , 1, 0, "C17")
-LANGOPT(C2x               , 1, 0, "C2x")
+LANGOPT(C23               , 1, 0, "C23")
 LANGOPT(MSVCCompat        , 1, 0, "Microsoft Visual C++ full compatibility mode")
 LANGOPT(Kernel            , 1, 0, "Kernel mode")
 LANGOPT(MicrosoftExt      , 1, 0, "Microsoft C++ extensions")
diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index 32e364399cb8b..1a9e779d50b44 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -612,7 +612,7 @@ class LangOptions : public LangOptionsBase {
   /// Returns true if functions without prototypes or functions with an
   /// identifier list (aka K&R C functions) are not allowed.
   bool requiresStrictPrototypes() const {
-    return CPlusPlus || C2x || DisableKNRFunctions;
+    return CPlusPlus || C23 || DisableKNRFunctions;
   }
 
   /// Returns true if implicit function declarations are allowed in the current
@@ -625,7 +625,7 @@ class LangOptions : public LangOptionsBase {
   bool isImplicitIntRequired() const { return !CPlusPlus && !C99; }
 
   /// Returns true if implicit int is supported at all.
-  bool isImplicitIntAllowed() const { return !CPlusPlus && !C2x; }
+  bool isImplicitIntAllowed() const { return !CPlusPlus && !C23; }
 
   /// Check if return address signing is enabled.
   bool hasSignReturnAddress() const {
@@ -781,7 +781,7 @@ class FPOptions {
   RoundingMode getRoundingMode() const {
     RoundingMode RM = getConstRoundingMode();
     if (RM == RoundingMode::Dynamic) {
-      // C2x: 7.6.2p3  If the FE_DYNAMIC mode is specified and FENV_ACCESS is
+      // C23: 7.6.2p3  If the FE_DYNAMIC mode is specified and FENV_ACCESS is
       // "off", the translator may assume that the default rounding mode is in
       // effect.
       if (!getAllowFEnvAccess() && !getRoundingMath())
diff --git a/clang/include/clang/Basic/LangStandard.h b/clang/include/clang/Basic/LangStandard.h
index fd949bcd68555..6356f16acc811 100644
--- a/clang/include/clang/Basic/LangStandard.h
+++ b/clang/include/clang/Basic/LangStandard.h
@@ -49,7 +49,7 @@ enum LangFeatures {
   C99 = (1 << 1),
   C11 = (1 << 2),
   C17 = (1 << 3),
-  C2x = (1 << 4),
+  C23 = (1 << 4),
   CPlusPlus = (1 << 5),
   CPlusPlus11 = (1 << 6),
   CPlusPlus14 = (1 << 7),
@@ -101,8 +101,8 @@ struct LangStandard {
   /// isC17 - Language is a superset of C17.
   bool isC17() const { return Flags & C17; }
 
-  /// isC2x - Language is a superset of C2x.
-  bool isC2x() const { return Flags & C2x; }
+  /// isC23 - Language is a superset of C23.
+  bool isC23() const { return Flags & C23; }
 
   /// isCPlusPlus - Language is a C++ variant.
   bool isCPlusPlus() const { return Flags & CPlusPlus; }
diff --git a/clang/include/clang/Basic/LangStandards.def b/clang/include/clang/Basic/LangStandards.def
index 5c28bdd28ef25..b6192e48efc11 100644
--- a/clang/include/clang/Basic/LangStandards.def
+++ b/clang/include/clang/Basic/LangStandards.def
@@ -87,13 +87,17 @@ LANGSTANDARD(gnu17, "gnu17",
              LineComment | C99 | C11 | C17 | Digraphs | GNUMode | HexFloat)
 LANGSTANDARD_ALIAS(gnu17, "gnu18")
 
-// C2x modes
-LANGSTANDARD(c2x, "c2x",
-             C, "Working Draft for ISO C2x",
-             LineComment | C99 | C11 | C17 | C2x | Digraphs | HexFloat)
-LANGSTANDARD(gnu2x, "gnu2x",
-             C, "Working Draft for ISO C2x with GNU extensions",
-             LineComment | C99 | C11 | C17 | C2x | Digraphs | GNUMode | HexFloat)
+// C23 modes
+LANGSTANDARD(c23, "c23",
+             C, "Working Draft for ISO C23",
+             LineComment | C99 | C11 | C17 | C23 | Digraphs | HexFloat)
+LANGSTANDARD_ALIAS_DEPR(c23, "c2x")
+LANGSTANDARD(gnu23, "gnu23",
+             C, "Working Draft for ISO C23 with GNU extensions",
+             LineComment | C99 | C11 | C17 | C23 | Digraphs | GNUMode | HexFloat)
+LANGSTANDARD_ALIAS_DEPR(gnu23, "gnu2x")
+// FIXME: Add the alias for iso9899:202* once we know the year ISO publishes
+// the document (expected to be 2024).
 
 // C++ modes
 LANGSTANDARD(cxx98, "c++98",
diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h
index 06279a016a507..6ae56703eca41 100644
--- a/clang/include/clang/Basic/Specifiers.h
+++ b/clang/include/clang/Basic/Specifiers.h
@@ -82,10 +82,10 @@ namespace clang {
     TST_class,     // C++ class type
     TST_interface, // C++ (Microsoft-specific) __interface type
     TST_typename,  // Typedef, C++ class-name or enum name, etc.
-    TST_typeofType,        // C2x (and GNU extension) typeof(type-name)
-    TST_typeofExpr,        // C2x (and GNU extension) typeof(expression)
-    TST_typeof_unqualType, // C2x typeof_unqual(type-name)
-    TST_typeof_unqualExpr, // C2x typeof_unqual(expression)
+    TST_typeofType,        // C23 (and GNU extension) typeof(type-name)
+    TST_typeofExpr,        // C23 (and GNU extension) typeof(expression)
+    TST_typeof_unqualType, // C23 typeof_unqual(type-name)
+    TST_typeof_unqualExpr, // C23 typeof_unqual(expression)
     TST_decltype, // C++11 decltype
 #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) TST_##Trait,
 #include "clang/Basic/TransformTypeTraits.def"
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 41ef47eb565b1..61be52149341f 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -1414,7 +1414,9 @@ class TargetInfo : public TransferrableTargetInfo,
 
   /// Identify whether this target supports IFuncs.
   bool supportsIFunc() const {
-    return getTriple().isOSBinFormatELF() && !getTriple().isOSFuchsia();
+    return getTriple().isOSBinFormatELF() &&
+           ((getTriple().isOSLinux() && !getTriple().isMusl()) ||
+            getTriple().isOSFreeBSD());
   }
 
   // Validate the contents of the __builtin_cpu_supports(const char*)
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index c9f51148aae3e..6a5eb03218ad1 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -31,8 +31,8 @@
 #ifndef C99_KEYWORD
 #define C99_KEYWORD(X,Y) KEYWORD(X,KEYC99|(Y))
 #endif
-#ifndef C2X_KEYWORD
-#define C2X_KEYWORD(X,Y) KEYWORD(X,KEYC2X|(Y))
+#ifndef C23_KEYWORD
+#define C23_KEYWORD(X,Y) KEYWORD(X,KEYC23|(Y))
 #endif
 #ifndef COROUTINES_KEYWORD
 #define COROUTINES_KEYWORD(X) CXX20_KEYWORD(X,KEYCOROUTINES)
@@ -259,7 +259,7 @@ PUNCTUATOR(caretcaret,            "^^")
 //              always be treated as a keyword
 //   KEYC99   - This is a keyword introduced to C in C99
 //   KEYC11   - This is a keyword introduced to C in C11
-//   KEYC2X   - This is a keyword introduced to C in C2x
+//   KEYC23   - This is a keyword introduced to C in C23
 //   KEYCXX   - This is a C++ keyword, or a C++-specific keyword in the
 //              implementation namespace
 //   KEYNOCXX - This is a keyword in every non-C++ dialect.
@@ -337,7 +337,7 @@ KEYWORD(__objc_no                   , KEYALL)
 
 // C++ 2.11p1: Keywords.
 KEYWORD(asm                         , KEYCXX|KEYGNU)
-KEYWORD(bool                        , BOOLSUPPORT|KEYC2X)
+KEYWORD(bool                        , BOOLSUPPORT|KEYC23)
 KEYWORD(catch                       , KEYCXX)
 KEYWORD(class                       , KEYCXX)
 KEYWORD(const_cast                  , KEYCXX)
@@ -345,7 +345,7 @@ KEYWORD(delete                      , KEYCXX)
 KEYWORD(dynamic_cast                , KEYCXX)
 KEYWORD(explicit                    , KEYCXX)
 KEYWORD(export                      , KEYCXX)
-KEYWORD(false                       , BOOLSUPPORT|KEYC2X)
+KEYWORD(false                       , BOOLSUPPORT|KEYC23)
 KEYWORD(friend                      , KEYCXX)
 KEYWORD(mutable                     , KEYCXX)
 KEYWORD(namespace                   , KEYCXX)
@@ -359,7 +359,7 @@ KEYWORD(static_cast                 , KEYCXX)
 KEYWORD(template                    , KEYCXX)
 KEYWORD(this                        , KEYCXX)
 KEYWORD(throw                       , KEYCXX)
-KEYWORD(true                        , BOOLSUPPORT|KEYC2X)
+KEYWORD(true                        , BOOLSUPPORT|KEYC23)
 KEYWORD(try                         , KEYCXX)
 KEYWORD(typename                    , KEYCXX)
 KEYWORD(typeid                      , KEYCXX)
@@ -386,17 +386,17 @@ C99_KEYWORD(inline                      , KEYCXX|KEYGNU)
 
 
 // C++11 keywords
-CXX11_KEYWORD(alignas               , KEYC2X)
+CXX11_KEYWORD(alignas               , KEYC23)
 // alignof and _Alignof return the required ABI alignment
-CXX11_UNARY_EXPR_OR_TYPE_TRAIT(alignof, AlignOf, KEYC2X)
+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(decltype              , 0)
 CXX11_KEYWORD(noexcept              , 0)
-CXX11_KEYWORD(nullptr               , KEYC2X)
-CXX11_KEYWORD(static_assert         , KEYMSCOMPAT|KEYC2X)
-CXX11_KEYWORD(thread_local          , KEYC2X)
+CXX11_KEYWORD(nullptr               , KEYC23)
+CXX11_KEYWORD(static_assert         , KEYMSCOMPAT|KEYC23)
+CXX11_KEYWORD(thread_local          , KEYC23)
 
 // C++20 / coroutines keywords
 COROUTINES_KEYWORD(co_await)
@@ -419,9 +419,9 @@ KEYWORD(char8_t                     , CHAR8SUPPORT)
 // C11 Extension
 KEYWORD(_Float16                    , KEYALL)
 
-// C2x keywords
-C2X_KEYWORD(typeof                  , KEYGNU)
-C2X_KEYWORD(typeof_unqual           , 0)
+// C23 keywords
+C23_KEYWORD(typeof                  , KEYGNU)
+C23_KEYWORD(typeof_unqual           , 0)
 
 // ISO/IEC JTC1 SC22 WG14 N1169 Extension
 KEYWORD(_Accum                      , KEYNOCXX)
@@ -995,5 +995,5 @@ ANNOTATION(repl_input_end)
 #undef PUNCTUATOR
 #undef TOK
 #undef C99_KEYWORD
-#undef C2X_KEYWORD
+#undef C23_KEYWORD
 #undef INTERESTING_IDENTIFIER
diff --git a/clang/include/clang/Basic/riscv_sifive_vector.td b/clang/include/clang/Basic/riscv_sifive_vector.td
index 0d390be711c83..6583a7eb7b2e5 100644
--- a/clang/include/clang/Basic/riscv_sifive_vector.td
+++ b/clang/include/clang/Basic/riscv_sifive_vector.td
@@ -72,34 +72,34 @@ multiclass RVVVCIXBuiltinSetWVType range, string prototype,
 }
 
 let SupportOverloading = false in {
-  defm sf_vc_x_se  : RVVVCIXBuiltinSetWVType<["c", "s", "i", "l"], "0KzKzKzUe", [0, 3], /*UseGPR*/1>;
-  defm sf_vc_i_se  : RVVVCIXBuiltinSetWVType<["c", "s", "i", "l"], "0KzKzKzKz", [2, 3], /*UseGPR*/0>;
-  defm sf_vc_xv    : RVVVCIXBuiltinSet<["csi", "l"], "0KzKzUvUe",  [0, 2, 3],  /*UseGPR*/1>;
-  defm sf_vc_iv    : RVVVCIXBuiltinSet<["csi", "l"], "0KzKzUvKz",  [0, 2, 3],  /*UseGPR*/0>;
-  defm sf_vc_vv    : RVVVCIXBuiltinSet<["csi", "l"], "0KzKzUvUv",  [0, 2, 3],  /*UseGPR*/0>;
-  defm sf_vc_fv    : RVVVCIXBuiltinSet<["si",  "l"], "0KzKzUvFe",  [0, 2, 3],  /*UseGPR*/0>;
-  defm sf_vc_xvv   : RVVVCIXBuiltinSet<["csi", "l"], "0KzUvUvUe",  [0, 1, 3],  /*UseGPR*/1>;
-  defm sf_vc_ivv   : RVVVCIXBuiltinSet<["csi", "l"], "0KzUvUvKz",  [0, 1, 3],  /*UseGPR*/0>;
-  defm sf_vc_vvv   : RVVVCIXBuiltinSet<["csi", "l"], "0KzUvUvUv",  [0, 1, 3],  /*UseGPR*/0>;
-  defm sf_vc_fvv   : RVVVCIXBuiltinSet<["si",  "l"], "0KzUvUvFe",  [0, 1, 3],  /*UseGPR*/0>;
-  defm sf_vc_v_x   : RVVVCIXBuiltinSet<["csi", "l"], "UvKzKzUe",   [-1, 1, 2], /*UseGPR*/1>;
-  defm sf_vc_v_i   : RVVVCIXBuiltinSet<["csi", "l"], "UvKzKzKz",   [-1, 1, 2], /*UseGPR*/0>;
-  defm sf_vc_v_xv  : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUe",   [-1, 0, 2], /*UseGPR*/1>;
-  defm sf_vc_v_iv  : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvKz",   [-1, 0, 2], /*UseGPR*/0>;
-  defm sf_vc_v_vv  : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUv",   [-1, 0, 2], /*UseGPR*/0>;
-  defm sf_vc_v_fv  : RVVVCIXBuiltinSet<["si",  "l"], "UvKzUvFe",   [-1, 0, 2], /*UseGPR*/0>;
-  defm sf_vc_v_xvv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUvUe", [-1, 0, 3], /*UseGPR*/1>;
-  defm sf_vc_v_ivv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUvKz", [-1, 0, 3], /*UseGPR*/0>;
-  defm sf_vc_v_vvv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUvUv", [-1, 0, 3], /*UseGPR*/0>;
-  defm sf_vc_v_fvv : RVVVCIXBuiltinSet<["si",  "l"], "UvKzUvUvFe", [-1, 0, 3], /*UseGPR*/0>;
+  defm sf_vc_x_se  : RVVVCIXBuiltinSetWVType<["c", "s", "i", "l"], "0KzKzKzUe", [0, 3], UseGPR=1>;
+  defm sf_vc_i_se  : RVVVCIXBuiltinSetWVType<["c", "s", "i", "l"], "0KzKzKzKz", [2, 3], UseGPR=0>;
+  defm sf_vc_xv    : RVVVCIXBuiltinSet<["csi", "l"], "0KzKzUvUe",  [0, 2, 3],  UseGPR=1>;
+  defm sf_vc_iv    : RVVVCIXBuiltinSet<["csi", "l"], "0KzKzUvKz",  [0, 2, 3],  UseGPR=0>;
+  defm sf_vc_vv    : RVVVCIXBuiltinSet<["csi", "l"], "0KzKzUvUv",  [0, 2, 3],  UseGPR=0>;
+  defm sf_vc_fv    : RVVVCIXBuiltinSet<["si",  "l"], "0KzKzUvFe",  [0, 2, 3],  UseGPR=0>;
+  defm sf_vc_xvv   : RVVVCIXBuiltinSet<["csi", "l"], "0KzUvUvUe",  [0, 1, 3],  UseGPR=1>;
+  defm sf_vc_ivv   : RVVVCIXBuiltinSet<["csi", "l"], "0KzUvUvKz",  [0, 1, 3],  UseGPR=0>;
+  defm sf_vc_vvv   : RVVVCIXBuiltinSet<["csi", "l"], "0KzUvUvUv",  [0, 1, 3],  UseGPR=0>;
+  defm sf_vc_fvv   : RVVVCIXBuiltinSet<["si",  "l"], "0KzUvUvFe",  [0, 1, 3],  UseGPR=0>;
+  defm sf_vc_v_x   : RVVVCIXBuiltinSet<["csi", "l"], "UvKzKzUe",   [-1, 1, 2], UseGPR=1>;
+  defm sf_vc_v_i   : RVVVCIXBuiltinSet<["csi", "l"], "UvKzKzKz",   [-1, 1, 2], UseGPR=0>;
+  defm sf_vc_v_xv  : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUe",   [-1, 0, 2], UseGPR=1>;
+  defm sf_vc_v_iv  : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvKz",   [-1, 0, 2], UseGPR=0>;
+  defm sf_vc_v_vv  : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUv",   [-1, 0, 2], UseGPR=0>;
+  defm sf_vc_v_fv  : RVVVCIXBuiltinSet<["si",  "l"], "UvKzUvFe",   [-1, 0, 2], UseGPR=0>;
+  defm sf_vc_v_xvv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUvUe", [-1, 0, 3], UseGPR=1>;
+  defm sf_vc_v_ivv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUvKz", [-1, 0, 3], UseGPR=0>;
+  defm sf_vc_v_vvv : RVVVCIXBuiltinSet<["csi", "l"], "UvKzUvUvUv", [-1, 0, 3], UseGPR=0>;
+  defm sf_vc_v_fvv : RVVVCIXBuiltinSet<["si",  "l"], "UvKzUvUvFe", [-1, 0, 3], UseGPR=0>;
   let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
-    defm sf_vc_xvw   : RVVVCIXBuiltinSet<["csi"], "0KzUwUvUe",  [0, 1, 2, 3],  /*UseGPR*/1>;
-    defm sf_vc_ivw   : RVVVCIXBuiltinSet<["csi"], "0KzUwUvKz",  [0, 1, 2, 3],  /*UseGPR*/0>;
-    defm sf_vc_vvw   : RVVVCIXBuiltinSet<["csi"], "0KzUwUvUv",  [0, 1, 2, 3],  /*UseGPR*/0>;
-    defm sf_vc_fvw   : RVVVCIXBuiltinSet<["si"],  "0KzUwUvFe",  [0, 1, 2, 3],  /*UseGPR*/0>;
-    defm sf_vc_v_xvw : RVVVCIXBuiltinSet<["csi"], "UwKzUwUvUe", [-1, 0, 2, 3], /*UseGPR*/1>;
-    defm sf_vc_v_ivw : RVVVCIXBuiltinSet<["csi"], "UwKzUwUvKz", [-1, 0, 2, 3], /*UseGPR*/0>;
-    defm sf_vc_v_vvw : RVVVCIXBuiltinSet<["csi"], "UwKzUwUvUv", [-1, 0, 2, 3], /*UseGPR*/0>;
-    defm sf_vc_v_fvw : RVVVCIXBuiltinSet<["si"],  "UwKzUwUvFe", [-1, 0, 2, 3], /*UseGPR*/0>;
+    defm sf_vc_xvw   : RVVVCIXBuiltinSet<["csi"], "0KzUwUvUe",  [0, 1, 2, 3],  UseGPR=1>;
+    defm sf_vc_ivw   : RVVVCIXBuiltinSet<["csi"], "0KzUwUvKz",  [0, 1, 2, 3],  UseGPR=0>;
+    defm sf_vc_vvw   : RVVVCIXBuiltinSet<["csi"], "0KzUwUvUv",  [0, 1, 2, 3],  UseGPR=0>;
+    defm sf_vc_fvw   : RVVVCIXBuiltinSet<["si"],  "0KzUwUvFe",  [0, 1, 2, 3],  UseGPR=0>;
+    defm sf_vc_v_xvw : RVVVCIXBuiltinSet<["csi"], "UwKzUwUvUe", [-1, 0, 2, 3], UseGPR=1>;
+    defm sf_vc_v_ivw : RVVVCIXBuiltinSet<["csi"], "UwKzUwUvKz", [-1, 0, 2, 3], UseGPR=0>;
+    defm sf_vc_v_vvw : RVVVCIXBuiltinSet<["csi"], "UwKzUwUvUv", [-1, 0, 2, 3], UseGPR=0>;
+    defm sf_vc_v_fvw : RVVVCIXBuiltinSet<["si"],  "UwKzUwUvFe", [-1, 0, 2, 3], UseGPR=0>;
   }
 }
diff --git a/clang/include/clang/Basic/riscv_vector.td b/clang/include/clang/Basic/riscv_vector.td
index 5bf1916df117b..239bacb629ea4 100644
--- a/clang/include/clang/Basic/riscv_vector.td
+++ b/clang/include/clang/Basic/riscv_vector.td
@@ -85,6 +85,11 @@ multiclass RVVOutOp1Op2BuiltinSet> suffixes_prototypes>
     : RVVBuiltinSet;
 
+// IntrinsicTypes is output, op2 [-1, 2]
+multiclass RVVOutOp2BuiltinSet> suffixes_prototypes>
+    : RVVBuiltinSet;
+
 multiclass RVVSignedBinBuiltinSet
     : RVVOutOp1BuiltinSet,
+      RVVOutOp1BuiltinSet;
+
 multiclass RVVSlideOneBuiltinSet
     : RVVOutOp1BuiltinSet;
+                           ["vx", "Uv", "UvUvUe"]]>;
 
 multiclass RVVSignedShiftBuiltinSet
     : RVVOutOp1BuiltinSet;
+}
+
+multiclass RVVOutBuiltinSetZvk {
+  // vaesz only has 'vs' and vgmul only has 'vv' and they do not have ambiguous
+  // prototypes like other zvkned instructions (e.g. vaesdf), so we don't
+  // need to encode the operand mnemonics into its intrinsic function name.
+  if HasVV then {
+    defvar name = NAME # !if(!eq(NAME, "vgmul"), "", "_vv");
+    let OverloadedName = name in
+      defm "" : RVVOutBuiltinSet;
+  }
+
+  if HasVS then {
+    foreach vs2_lmul = ["(SEFixedLog2LMUL:-1)", "(SEFixedLog2LMUL:0)",
+                        "(SEFixedLog2LMUL:1)", "(SEFixedLog2LMUL:2)",
+                        "(SEFixedLog2LMUL:3)"] in {
+    defvar name = NAME # !if(!eq(NAME, "vaesz"), "", "_vs");
+    let OverloadedName = name, IRName = NAME # "_vs", Name = NAME # "_vs",
+        IntrinsicTypes = [-1, 1] in
+      def NAME # vs2_lmul
+          : RVVBuiltin;
+    }
+  }
+}
+
+multiclass RVVOutOp2BuiltinSetVVZvk
+    : RVVOutOp2BuiltinSet;
+
+multiclass RVVOutOp2BuiltinSetVIZvk
+    : RVVOutOp2BuiltinSet;
+
+multiclass RVVSignedWidenBinBuiltinSetVwsll
+    : RVVWidenBuiltinSet;
+
+let UnMaskedPolicyScheme = HasPassthruOperand in {
+  // zvkb
+  defm vandn   : RVVUnsignedBinBuiltinSet;
+  defm vbrev8  : RVVOutBuiltinSetZvbb;
+  defm vrev8   : RVVOutBuiltinSetZvbb;
+  defm vrol    : RVVUnsignedShiftBuiltinSet;
+  defm vror    : RVVUnsignedShiftBuiltinSet;
+
+  // zvbb
+  defm vbrev   : RVVOutBuiltinSetZvbb;
+  defm vclz    : RVVOutBuiltinSetZvbb;
+  defm vctz    : RVVOutBuiltinSetZvbb;
+  defm vcpopv  : RVVOutBuiltinSetZvbb;
+  let OverloadedName = "vwsll" in
+  defm vwsll   : RVVSignedWidenBinBuiltinSetVwsll;
+
+  // zvbc
+  defm vclmul  : RVVInt64BinBuiltinSet;
+  defm vclmulh : RVVInt64BinBuiltinSet;
+}
+
+let UnMaskedPolicyScheme = HasPolicyOperand, HasMasked = false in {
+  // zvkg
+  defm vghsh   : RVVOutOp2BuiltinSetVVZvk;
+  defm vgmul   : RVVOutBuiltinSetZvk;
+
+  // zvkned
+  defm vaesdf  : RVVOutBuiltinSetZvk;
+  defm vaesdm  : RVVOutBuiltinSetZvk;
+  defm vaesef  : RVVOutBuiltinSetZvk;
+  defm vaesem  : RVVOutBuiltinSetZvk;
+  let UnMaskedPolicyScheme = HasPassthruOperand in
+  defm vaeskf1 : RVVOutOp1BuiltinSet<"vaeskf1", "i", [["vi", "Uv", "UvUvKz"]]>;
+  defm vaeskf2 : RVVOutOp2BuiltinSetVIZvk;
+  defm vaesz   : RVVOutBuiltinSetZvk;
+
+  // zvknha or zvknhb
+  defm vsha2ch : RVVOutOp2BuiltinSetVVZvk<"il">;
+  defm vsha2cl : RVVOutOp2BuiltinSetVVZvk<"il">;
+  defm vsha2ms : RVVOutOp2BuiltinSetVVZvk<"il">;
+
+  // zvksed
+  let UnMaskedPolicyScheme = HasPassthruOperand in
+  defm vsm4k   : RVVOutOp1BuiltinSet<"vsm4k", "i", [["vi", "Uv", "UvUvKz"]]>;
+  defm vsm4r   : RVVOutBuiltinSetZvk;
+
+  // zvksh
+  defm vsm3c   : RVVOutOp2BuiltinSetVIZvk;
+  let UnMaskedPolicyScheme = HasPassthruOperand in
+  defm vsm3me  : RVVOutOp1BuiltinSet<"vsm3me", "i", [["vv", "Uv", "UvUvUv"]]>;
+}
diff --git a/clang/include/clang/Basic/riscv_vector_common.td b/clang/include/clang/Basic/riscv_vector_common.td
index e276e4c3c409b..74d9ace212e15 100644
--- a/clang/include/clang/Basic/riscv_vector_common.td
+++ b/clang/include/clang/Basic/riscv_vector_common.td
@@ -97,6 +97,11 @@
 //      and LMUL), and computes another vector type which only changed LMUL as
 //      given value. The new LMUL should be smaller than the old one. Ignore to
 //      define a new builtin if its equivalent type has illegal lmul.
+//   (SEFixedLog2LMUL:Value): Smaller or Equal Fixed Log2LMUL. Given a vector
+//      type (SEW and LMUL), and computes another vector type which only
+//      changed LMUL as given value. The new LMUL should be smaller than or
+//      equal to the old one. Ignore to define a new builtin if its equivalent
+//      type has illegal lmul.
 //   (LFixedLog2LMUL:Value): Larger Fixed Log2LMUL. Given a vector type (SEW
 //      and LMUL), and computes another vector type which only changed LMUL as
 //      given value. The new LMUL should be larger than the old one. Ignore to
diff --git a/clang/include/clang/Driver/ClangOptionDocs.td b/clang/include/clang/Driver/ClangOptionDocs.td
index 3f914afea735a..a5ee577c5f45d 100644
--- a/clang/include/clang/Driver/ClangOptionDocs.td
+++ b/clang/include/clang/Driver/ClangOptionDocs.td
@@ -28,8 +28,10 @@ GCC-compatible ``clang`` and ``clang++`` drivers.
 }];
 
   string Program = "clang";
-  list ExcludedFlags = ["HelpHidden", "NoDriverOption",
-                                "CLOption", "Unsupported", "Ignored", "FlangOnlyOption"];
+  // Note: We *must* use DefaultVis and not ClangOption, since that's
+  // the name of the actual TableGen record. The alias will not work.
+  list VisibilityMask = ["DefaultVis"];
+  list IgnoreFlags = ["HelpHidden", "Unsupported", "Ignored"];
 }
 
 include "Options.td"
diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index 66795d364f1fc..5b0f74351cdd8 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -455,7 +455,7 @@ class Driver {
   /// ParseArgStrings - Parse the given list of strings into an
   /// ArgList.
   llvm::opt::InputArgList ParseArgStrings(ArrayRef Args,
-                                          bool IsClCompatMode,
+                                          bool UseDriverMode,
                                           bool &ContainsError);
 
   /// BuildInputs - Construct the list of inputs and their types from
@@ -791,7 +791,8 @@ class Driver {
 
   /// Get bitmasks for which option flags to include and exclude based on
   /// the driver mode.
-  std::pair getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const;
+  llvm::opt::Visibility
+  getOptionVisibilityMask(bool UseDriverMode = true) const;
 
   /// Helper used in BuildJobsForAction.  Doesn't use the cache when building
   /// jobs specifically for the given action, but will use the cache when
diff --git a/clang/include/clang/Driver/Options.h b/clang/include/clang/Driver/Options.h
index aa9649fbb037f..9222b4b0666e0 100644
--- a/clang/include/clang/Driver/Options.h
+++ b/clang/include/clang/Driver/Options.h
@@ -10,6 +10,7 @@
 #define LLVM_CLANG_DRIVER_OPTIONS_H
 
 #include "llvm/Option/OptTable.h"
+#include "llvm/Option/Option.h"
 
 namespace clang {
 namespace driver {
@@ -22,20 +23,23 @@ enum ClangFlags {
   LinkerInput = (1 << 5),
   NoArgumentUnused = (1 << 6),
   Unsupported = (1 << 7),
-  CoreOption = (1 << 8),
-  CLOption = (1 << 9),
-  CC1Option = (1 << 10),
-  CC1AsOption = (1 << 11),
-  NoDriverOption = (1 << 12),
-  LinkOption = (1 << 13),
-  FlangOption = (1 << 14),
-  FC1Option = (1 << 15),
-  FlangOnlyOption = (1 << 16),
-  DXCOption = (1 << 17),
-  CLDXCOption = (1 << 18),
-  Ignored = (1 << 19),
-  TargetSpecific = (1 << 20),
-  Deprecated = (1 << 21),
+  LinkOption = (1 << 8),
+  Ignored = (1 << 9),
+  TargetSpecific = (1 << 10),
+  Deprecated = (1 << 11),
+};
+
+// Flags specifically for clang option visibility. We alias DefaultVis to
+// ClangOption, because "DefaultVis" is confusing in Options.td, which is used
+// for multiple drivers (clang, cl, flang, etc).
+enum ClangVisibility {
+  ClangOption = llvm::opt::DefaultVis,
+  CLOption = (1 << 1),
+  CC1Option = (1 << 2),
+  CC1AsOption = (1 << 3),
+  FlangOption = (1 << 4),
+  FC1Option = (1 << 5),
+  DXCOption = (1 << 6),
 };
 
 enum ID {
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index f1fe71eec2c19..e583f88cc7e37 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -35,54 +35,56 @@ def Unsupported : OptionFlag;
 // Ignored - The option is unsupported, and the driver will silently ignore it.
 def Ignored : OptionFlag;
 
-// CoreOption - This is considered a "core" Clang option, available in both
-// clang and clang-cl modes.
-def CoreOption : OptionFlag;
+// If an option affects linking, but has a primary group (so Link_Group cannot
+// be used), add this flag.
+def LinkOption : OptionFlag;
 
-// CLOption - This is a cl.exe compatibility option. Options with this flag
-// are made available when the driver is running in CL compatibility mode.
-def CLOption : OptionFlag;
+// Deprecated - The option is deprecated, but still supported.  A
+// diagnostic is emitted about the potential for the option to be removed
+// in an upcoming release.
+def Deprecated : OptionFlag;
 
-// CC1Option - This option should be accepted by clang -cc1.
-def CC1Option : OptionFlag;
+// This is a target-specific option for compilation. Using it on an unsupported
+// target will lead to an err_drv_unsupported_opt_for_target error.
+def TargetSpecific : OptionFlag;
 
-// CC1AsOption - This option should be accepted by clang -cc1as.
-def CC1AsOption : OptionFlag;
+// Indicates that this warning is ignored, but accepted with a warning for
+// GCC compatibility.
+class IgnoredGCCCompat : Flags<[HelpHidden]> {}
 
-// DXCOption - This is a dxc.exe compatibility option. Options with this flag
-// are made available when the driver is running in DXC compatibility mode.
-def DXCOption : OptionFlag;
+class TargetSpecific : Flags<[TargetSpecific]> {}
 
-// CLDXCOption - This is a cl.exe/dxc.exe compatibility option. Options with this flag
-// are made available when the driver is running in CL/DXC compatibility mode.
-def CLDXCOption : OptionFlag;
+/////////
+// Visibility
 
-// NoDriverOption - This option should not be accepted by the driver.
-def NoDriverOption : OptionFlag;
+// We prefer the name "ClangOption" here rather than "Default" to make
+// it clear that these options will be visible in the clang driver (as
+// opposed to clang -cc1, the CL driver, or the flang driver).
+defvar ClangOption = DefaultVis;
 
-// If an option affects linking, but has a primary group (so Link_Group cannot
-// be used), add this flag.
-def LinkOption : OptionFlag;
+// CLOption - This is a cl.exe compatibility option. Options with this flag
+// are made available when the driver is running in CL compatibility mode.
+def CLOption : OptionVisibility;
+
+// CC1Option - This option should be accepted by clang -cc1.
+def CC1Option : OptionVisibility;
+
+// CC1AsOption - This option should be accepted by clang -cc1as.
+def CC1AsOption : OptionVisibility;
 
 // FlangOption - This is considered a "core" Flang option, available in
 // flang mode.
-def FlangOption : OptionFlag;
-
-// FlangOnlyOption - This option should only be used by Flang (i.e. it is not
-// available for Clang)
-def FlangOnlyOption : OptionFlag;
+def FlangOption : OptionVisibility;
 
 // FC1Option - This option should be accepted by flang -fc1.
-def FC1Option : OptionFlag;
+def FC1Option : OptionVisibility;
 
-// Deprecated - The option is deprecated, but still supported.  A
-// diagnostic is emitted about the potential for the option to be removed
-// in an upcoming release.
-def Deprecated : OptionFlag;
+// DXCOption - This is a dxc.exe compatibility option. Options with this flag
+// are made available when the driver is running in DXC compatibility mode.
+def DXCOption : OptionVisibility;
 
-// This is a target-specific option for compilation. Using it on an unsupported
-// target will lead to an err_drv_unsupported_opt_for_target error.
-def TargetSpecific : OptionFlag;
+/////////
+// Docs
 
 // A short name to show in documentation. The name will be interpreted as rST.
 class DocName { string DocName = name; }
@@ -94,12 +96,6 @@ class DocBrief { code DocBrief = descr; }
 // documentation.
 class DocFlatten { bit DocFlatten = 1; }
 
-// Indicates that this warning is ignored, but accepted with a warning for
-// GCC compatibility.
-class IgnoredGCCCompat : Flags<[HelpHidden]> {}
-
-class TargetSpecific : Flags<[TargetSpecific]> {}
-
 /////////
 // Groups
 
@@ -204,7 +200,8 @@ def m_wasm_Features_Group : OptionGroup<"">,
 def m_wasm_Features_Driver_Group : OptionGroup<"">,
                                    Group, DocName<"WebAssembly Driver">;
 def m_x86_Features_Group : OptionGroup<"">,
-                           Group, Flags<[CoreOption]>, DocName<"X86">;
+                           Group, Visibility<[ClangOption, CLOption]>,
+                           DocName<"X86">;
 def m_riscv_Features_Group : OptionGroup<"">,
                              Group, DocName<"RISC-V">;
 
@@ -260,7 +257,7 @@ def clang_ignored_m_Group : OptionGroup<"">,
 
 // Unsupported flang groups
 def flang_ignored_w_Group : OptionGroup<"">,
-  Group, Flags<[FlangOnlyOption, Ignored]>;
+  Group, Flags<[Ignored]>, Visibility<[FlangOption]>;
 
 // Group for clang options in the process of deprecation.
 // Please include the version that deprecated the flag as comment to allow
@@ -283,7 +280,7 @@ def mno_mpx : Flag<["-"], "mno-mpx">, Group;
 // Retired with clang-16.0, to provide a deprecation period; it should
 // be removed in Clang 18 or later.
 def enable_trivial_var_init_zero : Flag<["-"], "enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang">,
-  Flags<[CC1Option, CoreOption, NoArgumentUnused]>,
+  Flags<[NoArgumentUnused]>, Visibility<[ClangOption, CC1Option, CLOption]>,
   Group;
 
 // Group that ignores all gcc optimizations that won't be implemented
@@ -320,10 +317,11 @@ class MigratorOpts
 // This is useful if the option is usually disabled.
 // Use this only when the option cannot be declared via BoolFOption.
 multiclass OptInCC1FFlag flags=[]> {
-  def f#NAME : Flag<["-"], "f"#name>, Flags<[CC1Option] # flags>,
+                         string help="",
+                         list vis=[ClangOption]> {
+  def f#NAME : Flag<["-"], "f"#name>, Visibility<[CC1Option] # vis>,
                Group, HelpText;
-  def fno_#NAME : Flag<["-"], "fno-"#name>, Flags,
+  def fno_#NAME : Flag<["-"], "fno-"#name>, Visibility,
                   Group, HelpText;
 }
 
@@ -331,10 +329,11 @@ multiclass OptInCC1FFlag flags=[]> {
-  def f#NAME : Flag<["-"], "f"#name>, Flags,
+                          string help="",
+                          list vis=[ClangOption]> {
+  def f#NAME : Flag<["-"], "f"#name>, Visibility,
                Group, HelpText;
-  def fno_#NAME : Flag<["-"], "fno-"#name>, Flags<[CC1Option] # flags>,
+  def fno_#NAME : Flag<["-"], "fno-"#name>, Visibility<[CC1Option] # vis>,
                   Group, HelpText;
 }
 
@@ -342,20 +341,22 @@ multiclass OptOutCC1FFlag flags=[]> {
-  def f#NAME : Flag<["-"], "f"#name>, Flags<[FC1Option] # flags>,
+                         string help="",
+                         list vis=[ClangOption]> {
+  def f#NAME : Flag<["-"], "f"#name>, Visibility<[FC1Option] # vis>,
                Group, HelpText;
-  def fno_#NAME : Flag<["-"], "fno-"#name>, Flags,
+  def fno_#NAME : Flag<["-"], "fno-"#name>, Visibility,
                   Group, HelpText;
 }
 
 // A boolean option which is opt-out in FC1. The negative option exists in FC1 and
 // Args.hasArg(OPT_fno_foo) can be used to check that the flag is disabled.
 multiclass OptOutFC1FFlag flags=[]> {
-  def f#NAME : Flag<["-"], "f"#name>, Flags,
+                          string help="",
+                          list vis=[ClangOption]> {
+  def f#NAME : Flag<["-"], "f"#name>, Visibility,
                Group, HelpText;
-  def fno_#NAME : Flag<["-"], "fno-"#name>, Flags<[FC1Option] # flags>,
+  def fno_#NAME : Flag<["-"], "fno-"#name>, Visibility<[FC1Option] # vis>,
                   Group, HelpText;
 }
 
@@ -388,7 +389,8 @@ def SetFalse : Set {}
 
 // Definition of single command line flag. This is an implementation detail, use
 // SetTrueBy or SetFalseBy instead.
-class FlagDef option_flags,
+class FlagDef option_flags, list option_vis,
               string help, list implied_by_expressions = []> {
   // The polarity. Besides spelling, this also decides whether the TableGen
   // record will be prefixed with "no_".
@@ -397,9 +399,12 @@ class FlagDef option_flags,
   // The value assigned to key path when the flag is present on command line.
   bit Value = value;
 
-  // OptionFlags that control visibility of the flag in different tools.
+  // OptionFlags in different tools.
   list OptionFlags = option_flags;
 
+  // OptionVisibility flags for different tools.
+  list OptionVisibility = option_vis;
+
   // The help text associated with the flag.
   string Help = help;
 
@@ -408,8 +413,11 @@ class FlagDef option_flags,
 }
 
 // Additional information to be appended to both positive and negative flag.
-class BothFlags option_flags, string help = ""> {
+class BothFlags option_flags,
+                list option_vis = [ClangOption],
+                string help = ""> {
   list OptionFlags = option_flags;
+  list OptionVisibility = option_vis;
   string Help = help;
 }
 
@@ -418,23 +426,26 @@ class ApplySuffix {
   FlagDef Result
     = FlagDef;
 }
 
 // Definition of the command line flag with positive spelling, e.g. "-ffoo".
-class PosFlag flags = [], string help = "",
-              list implied_by_expressions = []>
-  : FlagDef {}
+class PosFlag flags = [], list vis = [],
+              string help = "", list implied_by_expressions = []>
+  : FlagDef {}
 
 // Definition of the command line flag with negative spelling, e.g. "-fno-foo".
-class NegFlag flags = [], string help = "",
-              list implied_by_expressions = []>
-  : FlagDef {}
+class NegFlag flags = [], list vis = [],
+              string help = "", list implied_by_expressions = []>
+  : FlagDef {}
 
 // Expanded FlagDef that's convenient for creation of TableGen records.
 class FlagDefExpanded
-  : FlagDef {
+  : FlagDef {
   // Name of the TableGen record.
   string RecordName = prefix # !if(flag.Polarity, "", "no_") # name;
 
@@ -452,7 +463,8 @@ class FlagDefExpanded
 class MarshalledFlagRec
-  : Flag<["-"], flag.Spelling>, Flags, HelpText,
+  : Flag<["-"], flag.Spelling>, Flags,
+    Visibility, HelpText,
     MarshallingInfoBooleanFlag,
     ImpliedByAnyOf {}
@@ -466,7 +478,7 @@ class MarshalledFlagRec> {
+                      BothFlags suffix = BothFlags<[]>> {
   defvar flag1 = FlagDefExpanded.Result, prefix,
                                  NAME, spelling_base>;
 
@@ -497,7 +509,7 @@ multiclass BoolOption> {
+                       BothFlags both = BothFlags<[]>> {
   defm NAME : BoolOption<"f", flag_base, kpm, default, flag1, flag2, both>,
               Group;
 }
@@ -508,7 +520,7 @@ multiclass BoolFOption> {
+                       BothFlags both = BothFlags<[]>> {
   defm NAME : BoolOption<"g", flag_base, kpm, default, flag1, flag2, both>,
               Group;
 }
@@ -516,7 +528,7 @@ multiclass BoolGOption> {
+                                        BothFlags suffix = BothFlags<[]>> {
   defvar flag1 = FlagDefExpanded.Result, prefix,
                                  NAME, spelling_base>;
 
@@ -538,10 +550,12 @@ multiclass BoolOptionWithoutMarshalling, Flags,
+                         Visibility,
                          HelpText,
                          ImpliedByAnyOf
                          {}
   def flag2.RecordName : Flag<["-"], flag2.Spelling>, Flags,
+                         Visibility,
                          HelpText,
                          ImpliedByAnyOf
                          {}
@@ -560,7 +574,7 @@ defvar cpp11 = LangOpts<"CPlusPlus11">;
 defvar cpp17 = LangOpts<"CPlusPlus17">;
 defvar cpp20 = LangOpts<"CPlusPlus20">;
 defvar c99 = LangOpts<"C99">;
-defvar c2x = LangOpts<"C2x">;
+defvar c23 = LangOpts<"C23">;
 defvar lang_std = LangOpts<"LangStd">;
 defvar open_cl = LangOpts<"OpenCL">;
 defvar cuda = LangOpts<"CUDA">;
@@ -597,7 +611,8 @@ defvar std = !strconcat("LangStandard::getLangStandardForKind(", lang_std.KeyPat
 
 // Developer Driver Options
 
-def internal_Group : OptionGroup<"">, Flags<[HelpHidden]>;
+def internal_Group : OptionGroup<"">,
+  Flags<[HelpHidden]>;
 def internal_driver_Group : OptionGroup<"">,
   Group, HelpText<"DRIVER OPTIONS">;
 def internal_debug_Group :
@@ -607,20 +622,25 @@ def internal_debug_Group :
 class InternalDriverOpt : Group,
   Flags<[NoXarchOption, HelpHidden]>;
 def driver_mode : Joined<["--"], "driver-mode=">, Group,
-  Flags<[CoreOption, NoXarchOption, HelpHidden]>,
-  HelpText<"Set the driver mode to either 'gcc', 'g++', 'cpp', or 'cl'">;
+  Flags<[NoXarchOption, HelpHidden]>,
+  Visibility<[ClangOption, FlangOption, CLOption, DXCOption]>,
+  HelpText<"Set the driver mode to either 'gcc', 'g++', 'cpp', 'cl' or 'flang'">;
 def rsp_quoting : Joined<["--"], "rsp-quoting=">, Group,
-  Flags<[CoreOption, NoXarchOption, HelpHidden]>,
+  Flags<[NoXarchOption, HelpHidden]>,
+  Visibility<[ClangOption, CLOption, DXCOption]>,
   HelpText<"Set the rsp quoting to either 'posix', or 'windows'">;
 def ccc_gcc_name : Separate<["-"], "ccc-gcc-name">, InternalDriverOpt,
   HelpText<"Name for native GCC compiler">,
   MetaVarName<"">;
 
 class InternalDebugOpt : Group,
-  Flags<[NoXarchOption, HelpHidden, CoreOption]>;
+  Flags<[NoXarchOption, HelpHidden]>,
+  Visibility<[ClangOption, CLOption, DXCOption]>;
 def ccc_install_dir : Separate<["-"], "ccc-install-dir">, InternalDebugOpt,
   HelpText<"Simulate installation in the given directory">;
-def ccc_print_phases : Flag<["-"], "ccc-print-phases">, InternalDebugOpt,
+def ccc_print_phases : Flag<["-"], "ccc-print-phases">,
+  Flags<[NoXarchOption, HelpHidden]>, Visibility<[ClangOption, CLOption, DXCOption,
+  FlangOption]>,
   HelpText<"Dump list of actions to perform">;
 def ccc_print_bindings : Flag<["-"], "ccc-print-bindings">, InternalDebugOpt,
   HelpText<"Show bindings of tools to actions">;
@@ -632,12 +652,15 @@ def ccc_arcmt_modify : Flag<["-"], "ccc-arcmt-modify">, InternalDriverOpt,
 def ccc_arcmt_migrate : Separate<["-"], "ccc-arcmt-migrate">, InternalDriverOpt,
   HelpText<"Apply modifications and produces temporary files that conform to ARC">;
 def arcmt_migrate_report_output : Separate<["-"], "arcmt-migrate-report-output">,
-  HelpText<"Output path for the plist report">,  Flags<[CC1Option]>,
+  HelpText<"Output path for the plist report">,
+  Visibility<[ClangOption, CC1Option]>,
   MarshallingInfoString>;
 def arcmt_migrate_emit_arc_errors : Flag<["-"], "arcmt-migrate-emit-errors">,
-  HelpText<"Emit ARC errors even if the migrator can fix them">, Flags<[CC1Option]>,
+  HelpText<"Emit ARC errors even if the migrator can fix them">,
+  Visibility<[ClangOption, CC1Option]>,
   MarshallingInfoFlag>;
-def gen_reproducer_eq: Joined<["-"], "gen-reproducer=">, Flags<[NoArgumentUnused, CoreOption]>,
+def gen_reproducer_eq: Joined<["-"], "gen-reproducer=">,
+  Flags<[NoArgumentUnused]>, Visibility<[ClangOption, CLOption, DXCOption]>,
   HelpText<"Emit reproducer on (option: off, crash (default), error, always)">;
 def gen_reproducer: Flag<["-"], "gen-reproducer">, InternalDebugOpt,
   Alias, AliasArgs<["always"]>,
@@ -645,9 +668,10 @@ def gen_reproducer: Flag<["-"], "gen-reproducer">, InternalDebugOpt,
 def gen_cdb_fragment_path: Separate<["-"], "gen-cdb-fragment-path">, InternalDebugOpt,
   HelpText<"Emit a compilation database fragment to the specified directory">;
 
-def round_trip_args : Flag<["-"], "round-trip-args">, Flags<[CC1Option, NoDriverOption]>,
+def round_trip_args : Flag<["-"], "round-trip-args">, Visibility<[CC1Option]>,
   HelpText<"Enable command line arguments round-trip.">;
-def no_round_trip_args : Flag<["-"], "no-round-trip-args">, Flags<[CC1Option, NoDriverOption]>,
+def no_round_trip_args : Flag<["-"], "no-round-trip-args">,
+  Visibility<[CC1Option]>,
   HelpText<"Disable command line arguments round-trip.">;
 
 def _migrate : Flag<["--"], "migrate">, Flags<[NoXarchOption]>,
@@ -657,60 +681,78 @@ def ccc_objcmt_migrate : Separate<["-"], "ccc-objcmt-migrate">,
   HelpText<"Apply modifications and produces temporary files to migrate to "
    "modern ObjC syntax">;
 
-def objcmt_migrate_literals : Flag<["-"], "objcmt-migrate-literals">, Flags<[CC1Option]>,
+def objcmt_migrate_literals : Flag<["-"], "objcmt-migrate-literals">,
+  Visibility<[ClangOption, CC1Option]>,
   HelpText<"Enable migration to modern ObjC literals">,
   MarshallingInfoBitfieldFlag, "FrontendOptions::ObjCMT_Literals">;
-def objcmt_migrate_subscripting : Flag<["-"], "objcmt-migrate-subscripting">, Flags<[CC1Option]>,
+def objcmt_migrate_subscripting : Flag<["-"], "objcmt-migrate-subscripting">,
+  Visibility<[ClangOption, CC1Option]>,
   HelpText<"Enable migration to modern ObjC subscripting">,
   MarshallingInfoBitfieldFlag, "FrontendOptions::ObjCMT_Subscripting">;
-def objcmt_migrate_property : Flag<["-"], "objcmt-migrate-property">, Flags<[CC1Option]>,
+def objcmt_migrate_property : Flag<["-"], "objcmt-migrate-property">,
+  Visibility<[ClangOption, CC1Option]>,
   HelpText<"Enable migration to modern ObjC property">,
   MarshallingInfoBitfieldFlag, "FrontendOptions::ObjCMT_Property">;
-def objcmt_migrate_all : Flag<["-"], "objcmt-migrate-all">, Flags<[CC1Option]>,
+def objcmt_migrate_all : Flag<["-"], "objcmt-migrate-all">,
+  Visibility<[ClangOption, CC1Option]>,
   HelpText<"Enable migration to modern ObjC">,
   MarshallingInfoBitfieldFlag, "FrontendOptions::ObjCMT_MigrateDecls">;
-def objcmt_migrate_readonly_property : Flag<["-"], "objcmt-migrate-readonly-property">, Flags<[CC1Option]>,
+def objcmt_migrate_readonly_property : Flag<["-"], "objcmt-migrate-readonly-property">,
+  Visibility<[ClangOption, CC1Option]>,
   HelpText<"Enable migration to modern ObjC readonly property">,
   MarshallingInfoBitfieldFlag, "FrontendOptions::ObjCMT_ReadonlyProperty">;
-def objcmt_migrate_readwrite_property : Flag<["-"], "objcmt-migrate-readwrite-property">, Flags<[CC1Option]>,
+def objcmt_migrate_readwrite_property : Flag<["-"], "objcmt-migrate-readwrite-property">,
+  Visibility<[ClangOption, CC1Option]>,
   HelpText<"Enable migration to modern ObjC readwrite property">,
   MarshallingInfoBitfieldFlag, "FrontendOptions::ObjCMT_ReadwriteProperty">;
-def objcmt_migrate_property_dot_syntax : Flag<["-"], "objcmt-migrate-property-dot-syntax">, Flags<[CC1Option]>,
+def objcmt_migrate_property_dot_syntax : Flag<["-"], "objcmt-migrate-property-dot-syntax">,
+  Visibility<[ClangOption, CC1Option]>,
   HelpText<"Enable migration of setter/getter messages to property-dot syntax">,
   MarshallingInfoBitfieldFlag, "FrontendOptions::ObjCMT_PropertyDotSyntax">;
-def objcmt_migrate_annotation : Flag<["-"], "objcmt-migrate-annotation">, Flags<[CC1Option]>,
+def objcmt_migrate_annotation : Flag<["-"], "objcmt-migrate-annotation">,
+  Visibility<[ClangOption, CC1Option]>,
   HelpText<"Enable migration to property and method annotations">,
   MarshallingInfoBitfieldFlag, "FrontendOptions::ObjCMT_Annotation">;
-def objcmt_migrate_instancetype : Flag<["-"], "objcmt-migrate-instancetype">, Flags<[CC1Option]>,
+def objcmt_migrate_instancetype : Flag<["-"], "objcmt-migrate-instancetype">,
+  Visibility<[ClangOption, CC1Option]>,
   HelpText<"Enable migration to infer instancetype for method result type">,
   MarshallingInfoBitfieldFlag, "FrontendOptions::ObjCMT_Instancetype">;
-def objcmt_migrate_nsmacros : Flag<["-"], "objcmt-migrate-ns-macros">, Flags<[CC1Option]>,
+def objcmt_migrate_nsmacros : Flag<["-"], "objcmt-migrate-ns-macros">,
+  Visibility<[ClangOption, CC1Option]>,
   HelpText<"Enable migration to NS_ENUM/NS_OPTIONS macros">,
   MarshallingInfoBitfieldFlag, "FrontendOptions::ObjCMT_NsMacros">;
-def objcmt_migrate_protocol_conformance : Flag<["-"], "objcmt-migrate-protocol-conformance">, Flags<[CC1Option]>,
+def objcmt_migrate_protocol_conformance : Flag<["-"], "objcmt-migrate-protocol-conformance">,
+  Visibility<[ClangOption, CC1Option]>,
   HelpText<"Enable migration to add protocol conformance on classes">,
   MarshallingInfoBitfieldFlag, "FrontendOptions::ObjCMT_ProtocolConformance">;
-def objcmt_atomic_property : Flag<["-"], "objcmt-atomic-property">, Flags<[CC1Option]>,
+def objcmt_atomic_property : Flag<["-"], "objcmt-atomic-property">,
+  Visibility<[ClangOption, CC1Option]>,
   HelpText<"Make migration to 'atomic' properties">,
   MarshallingInfoBitfieldFlag, "FrontendOptions::ObjCMT_AtomicProperty">;
-def objcmt_returns_innerpointer_property : Flag<["-"], "objcmt-returns-innerpointer-property">, Flags<[CC1Option]>,
+def objcmt_returns_innerpointer_property : Flag<["-"], "objcmt-returns-innerpointer-property">,
+  Visibility<[ClangOption, CC1Option]>,
   HelpText<"Enable migration to annotate property with NS_RETURNS_INNER_POINTER">,
   MarshallingInfoBitfieldFlag, "FrontendOptions::ObjCMT_ReturnsInnerPointerProperty">;
-def objcmt_ns_nonatomic_iosonly: Flag<["-"], "objcmt-ns-nonatomic-iosonly">, Flags<[CC1Option]>,
+def objcmt_ns_nonatomic_iosonly: Flag<["-"], "objcmt-ns-nonatomic-iosonly">,
+  Visibility<[ClangOption, CC1Option]>,
   HelpText<"Enable migration to use NS_NONATOMIC_IOSONLY macro for setting property's 'atomic' attribute">,
   MarshallingInfoBitfieldFlag, "FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty">;
-def objcmt_migrate_designated_init : Flag<["-"], "objcmt-migrate-designated-init">, Flags<[CC1Option]>,
+def objcmt_migrate_designated_init : Flag<["-"], "objcmt-migrate-designated-init">,
+  Visibility<[ClangOption, CC1Option]>,
   HelpText<"Enable migration to infer NS_DESIGNATED_INITIALIZER for initializer methods">,
   MarshallingInfoBitfieldFlag, "FrontendOptions::ObjCMT_DesignatedInitializer">;
 
-def objcmt_allowlist_dir_path: Joined<["-"], "objcmt-allowlist-dir-path=">, Flags<[CC1Option]>,
+def objcmt_allowlist_dir_path: Joined<["-"], "objcmt-allowlist-dir-path=">,
+  Visibility<[ClangOption, CC1Option]>,
   HelpText<"Only modify files with a filename contained in the provided directory path">,
   MarshallingInfoString>;
-def : Joined<["-"], "objcmt-whitelist-dir-path=">, Flags<[CC1Option]>,
+def : Joined<["-"], "objcmt-whitelist-dir-path=">,
+  Visibility<[ClangOption, CC1Option]>,
   HelpText<"Alias for -objcmt-allowlist-dir-path">,
   Alias;
 // The misspelt "white-list" [sic] alias is due for removal.
-def : Joined<["-"], "objcmt-white-list-dir-path=">, Flags<[CC1Option]>,
+def : Joined<["-"], "objcmt-white-list-dir-path=">,
+  Visibility<[ClangOption, CC1Option]>,
   Alias;
 
 // Make sure all other -ccc- options are rejected.
@@ -718,11 +760,13 @@ def ccc_ : Joined<["-"], "ccc-">, Group, Flags<[Unsupported]>;
 
 // Standard Options
 
-def _HASH_HASH_HASH : Flag<["-"], "###">, Flags<[NoXarchOption, CoreOption, FlangOption]>,
+def _HASH_HASH_HASH : Flag<["-"], "###">, Flags<[NoXarchOption]>,
+  Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>,
     HelpText<"Print (but do not run) the commands to run for this compilation">;
 def _DASH_DASH : Option<["--"], "", KIND_REMAINING_ARGS>,
-    Flags<[NoXarchOption, CoreOption]>;
-def A : JoinedOrSeparate<["-"], "A">, Flags<[RenderJoined]>, Group;
+    Flags<[NoXarchOption]>, Visibility<[ClangOption, CLOption, DXCOption]>;
+def A : JoinedOrSeparate<["-"], "A">, Flags<[RenderJoined]>,
+  Group;
 def B : JoinedOrSeparate<["-"], "B">, MetaVarName<"">,
     HelpText<"Search $prefix$file for executables, libraries, and data files. "
     "If $prefix is a directory, search $prefix/$file">;
@@ -732,28 +776,38 @@ def gcc_install_dir_EQ : Joined<["--"], "gcc-install-dir=">,
 def gcc_toolchain : Joined<["--"], "gcc-toolchain=">, Flags<[NoXarchOption]>,
   HelpText<"Specify a directory where Clang can find 'include' and 'lib{,32,64}/gcc{,-cross}/$triple/$version'. "
   "Clang will use the GCC installation with the largest version">;
-def CC : Flag<["-"], "CC">, Flags<[CC1Option]>, Group,
+def CC : Flag<["-"], "CC">, Visibility<[ClangOption, CC1Option]>,
+  Group,
     HelpText<"Include comments from within macros in preprocessed output">,
     MarshallingInfoFlag>;
-def C : Flag<["-"], "C">, Flags<[CC1Option]>, Group,
+def C : Flag<["-"], "C">, Visibility<[ClangOption, CC1Option]>,
+  Group,
     HelpText<"Include comments in preprocessed output">,
     MarshallingInfoFlag>;
 def D : JoinedOrSeparate<["-"], "D">, Group,
-    Flags<[CC1Option, FlangOption, FC1Option]>, MetaVarName<"=">,
+    Visibility<[ClangOption, CC1Option, FlangOption, FC1Option, DXCOption]>,
+    MetaVarName<"=">,
     HelpText<"Define  to  (or 1 if  omitted)">;
-def E : Flag<["-"], "E">, Flags<[NoXarchOption,CC1Option, FlangOption, FC1Option]>, Group,
+def E : Flag<["-"], "E">, Flags<[NoXarchOption]>,
+  Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
+  Group,
     HelpText<"Only run the preprocessor">;
-def F : JoinedOrSeparate<["-"], "F">, Flags<[RenderJoined,CC1Option]>,
+def F : JoinedOrSeparate<["-"], "F">, Flags<[RenderJoined]>,
+  Visibility<[ClangOption, CC1Option]>,
     HelpText<"Add directory to framework include search path">;
-def G : JoinedOrSeparate<["-"], "G">, Flags<[NoXarchOption,TargetSpecific]>, Group,
+def G : JoinedOrSeparate<["-"], "G">, Flags<[NoXarchOption, TargetSpecific]>,
+  Group,
     MetaVarName<"">, HelpText<"Put objects of at most  bytes "
     "into small data section (MIPS / Hexagon)">;
-def G_EQ : Joined<["-"], "G=">, Flags<[NoXarchOption]>, Group, Alias;
-def H : Flag<["-"], "H">, Flags<[CC1Option]>, Group,
+def G_EQ : Joined<["-"], "G=">, Flags<[NoXarchOption]>,
+  Group, Alias;
+def H : Flag<["-"], "H">, Visibility<[ClangOption, CC1Option]>,
+  Group,
     HelpText<"Show header includes and nesting depth">,
     MarshallingInfoFlag>;
 def fshow_skipped_includes : Flag<["-"], "fshow-skipped-includes">,
-  Flags<[CC1Option]>, HelpText<"Show skipped includes in -H output.">,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Show skipped includes in -H output.">,
   DocBrief<[{#include files may be "skipped" due to include guard optimization
              or #pragma once. This flag makes -H show also such includes.}]>,
   MarshallingInfoFlag>;
@@ -762,7 +816,8 @@ def I_ : Flag<["-"], "I-">, Group,
     HelpText<"Restrict all prior -I flags to double-quoted inclusion and "
              "remove current directory from include path">;
 def I : JoinedOrSeparate<["-"], "I">, Group,
-    Flags<[CC1Option,CC1AsOption,FlangOption,FC1Option]>, MetaVarName<"">,
+    Visibility<[ClangOption, CC1Option, CC1AsOption, FlangOption, FC1Option]>,
+    MetaVarName<"">,
     HelpText<"Add directory to the end of the list of include search paths">,
     DocBrief<[{Add directory to include search path. For C++ inputs, if
 there are multiple -I options, these directories are searched
@@ -783,96 +838,113 @@ def MM : Flag<["-"], "MM">, Group,
 def MF : JoinedOrSeparate<["-"], "MF">, Group,
     HelpText<"Write depfile output from -MMD, -MD, -MM, or -M to ">,
     MetaVarName<"">;
-def MG : Flag<["-"], "MG">, Group, Flags<[CC1Option]>,
+def MG : Flag<["-"], "MG">, Group, Visibility<[ClangOption, CC1Option]>,
     HelpText<"Add missing headers to depfile">,
     MarshallingInfoFlag>;
 def MJ : JoinedOrSeparate<["-"], "MJ">, Group,
     HelpText<"Write a compilation database entry per input">;
-def MP : Flag<["-"], "MP">, Group, Flags<[CC1Option]>,
+def MP : Flag<["-"], "MP">, Group, Visibility<[ClangOption, CC1Option]>,
     HelpText<"Create phony target for each dependency (other than main file)">,
     MarshallingInfoFlag>;
-def MQ : JoinedOrSeparate<["-"], "MQ">, Group, Flags<[CC1Option]>,
+def MQ : JoinedOrSeparate<["-"], "MQ">, Group,
+  Visibility<[ClangOption, CC1Option]>,
     HelpText<"Specify name of main file output to quote in depfile">;
-def MT : JoinedOrSeparate<["-"], "MT">, Group, Flags<[CC1Option]>,
+def MT : JoinedOrSeparate<["-"], "MT">, Group,
+  Visibility<[ClangOption, CC1Option]>,
     HelpText<"Specify name of main file output in depfile">,
     MarshallingInfoStringVector>;
-def MV : Flag<["-"], "MV">, Group, Flags<[CC1Option]>,
+def MV : Flag<["-"], "MV">, Group, Visibility<[ClangOption, CC1Option]>,
     HelpText<"Use NMake/Jom format for the depfile">,
     MarshallingInfoFlag, "DependencyOutputFormat::Make">,
     Normalizer<"makeFlagToValueNormalizer(DependencyOutputFormat::NMake)">;
 def Mach : Flag<["-"], "Mach">, Group;
-def O0 : Flag<["-"], "O0">, Group, Flags<[CC1Option, FC1Option, HelpHidden]>;
-def O4 : Flag<["-"], "O4">, Group, Flags<[CC1Option, FC1Option, HelpHidden]>;
+def O0 : Flag<["-"], "O0">, Group, Flags<[HelpHidden]>,
+  Visibility<[ClangOption, CC1Option, FC1Option, FlangOption]>;
+def O4 : Flag<["-"], "O4">, Group, Flags<[HelpHidden]>,
+  Visibility<[ClangOption, CC1Option, FC1Option, FlangOption]>;
 def ObjCXX : Flag<["-"], "ObjC++">, Flags<[NoXarchOption]>,
   HelpText<"Treat source input files as Objective-C++ inputs">;
 def ObjC : Flag<["-"], "ObjC">, Flags<[NoXarchOption]>,
   HelpText<"Treat source input files as Objective-C inputs">;
-def O : Joined<["-"], "O">, Group, Flags<[CC1Option,FC1Option]>;
-def O_flag : Flag<["-"], "O">, Flags<[CC1Option,FC1Option]>, Alias, AliasArgs<["1"]>;
-def Ofast : Joined<["-"], "Ofast">, Group, Flags<[CC1Option, FlangOption]>;
-def P : Flag<["-"], "P">, Flags<[CC1Option,FlangOption,FC1Option]>, Group,
+def O : Joined<["-"], "O">, Group,
+  Visibility<[ClangOption, CC1Option, FC1Option, FlangOption]>;
+def O_flag : Flag<["-"], "O">, Visibility<[ClangOption, CC1Option, FC1Option]>,
+  Alias, AliasArgs<["1"]>;
+def Ofast : Joined<["-"], "Ofast">, Group,
+  Visibility<[ClangOption, CC1Option, FlangOption]>;
+def P : Flag<["-"], "P">,
+  Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
+  Group,
   HelpText<"Disable linemarker output in -E mode">,
   MarshallingInfoNegativeFlag>;
-def Qy : Flag<["-"], "Qy">, Flags<[CC1Option]>,
+def Qy : Flag<["-"], "Qy">, Visibility<[ClangOption, CC1Option]>,
   HelpText<"Emit metadata containing compiler name and version">;
-def Qn : Flag<["-"], "Qn">, Flags<[CC1Option]>,
+def Qn : Flag<["-"], "Qn">, Visibility<[ClangOption, CC1Option]>,
   HelpText<"Do not emit metadata containing compiler name and version">;
 def : Flag<["-"], "fident">, Group, Alias,
-  Flags<[CoreOption, CC1Option]>;
+  Visibility<[ClangOption, CLOption, DXCOption, CC1Option]>;
 def : Flag<["-"], "fno-ident">, Group, Alias,
-  Flags<[CoreOption, CC1Option]>;
-def Qunused_arguments : Flag<["-"], "Qunused-arguments">, Flags<[NoXarchOption, CoreOption]>,
+  Visibility<[ClangOption, CLOption, DXCOption, CC1Option]>;
+def Qunused_arguments : Flag<["-"], "Qunused-arguments">,
+  Flags<[NoXarchOption]>, Visibility<[ClangOption, CLOption, DXCOption]>,
   HelpText<"Don't emit warning for unused driver arguments">;
 def Q : Flag<["-"], "Q">, IgnoredGCCCompat;
-def Rpass_EQ : Joined<["-"], "Rpass=">, Group, Flags<[CC1Option]>,
-  HelpText<"Report transformations performed by optimization passes whose "
-           "name matches the given POSIX regular expression">;
-def Rpass_missed_EQ : Joined<["-"], "Rpass-missed=">, Group,
-  Flags<[CC1Option]>,
-  HelpText<"Report missed transformations by optimization passes whose "
-           "name matches the given POSIX regular expression">;
-def Rpass_analysis_EQ : Joined<["-"], "Rpass-analysis=">, Group,
-  Flags<[CC1Option]>,
-  HelpText<"Report transformation analysis from optimization passes whose "
-           "name matches the given POSIX regular expression">;
-def R_Joined : Joined<["-"], "R">, Group, Flags<[CC1Option, CoreOption]>,
-  MetaVarName<"">, HelpText<"Enable the specified remark">;
-def S : Flag<["-"], "S">, Flags<[NoXarchOption,CC1Option,FlangOption,FC1Option]>, Group,
+def S : Flag<["-"], "S">, Flags<[NoXarchOption]>,
+  Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
+  Group,
   HelpText<"Only run preprocess and compilation steps">;
 def T : JoinedOrSeparate<["-"], "T">, Group,
   MetaVarName<"