227 changes: 96 additions & 131 deletions bolt/lib/Profile/DataAggregator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -604,8 +604,6 @@ Error DataAggregator::readProfile(BinaryContext &BC) {
// BAT YAML is handled by DataAggregator since normal YAML output requires
// CFG which is not available in BAT mode.
if (usesBAT()) {
// Postprocess split function profile for BAT
fixupBATProfile(BC);
if (opts::ProfileFormat == opts::ProfileFormatKind::PF_YAML)
if (std::error_code EC = writeBATYAML(BC, opts::OutputFilename))
report_error("cannot create output data file", EC);
Expand Down Expand Up @@ -664,18 +662,19 @@ DataAggregator::getBinaryFunctionContainingAddress(uint64_t Address) const {
/*UseMaxSize=*/true);
}

StringRef DataAggregator::getLocationName(BinaryFunction &Func,
uint64_t Count) {
BinaryFunction *
DataAggregator::getBATParentFunction(const BinaryFunction &Func) const {
if (BAT)
if (const uint64_t HotAddr = BAT->fetchParentAddress(Func.getAddress()))
return getBinaryFunctionContainingAddress(HotAddr);
return nullptr;
}

StringRef DataAggregator::getLocationName(const BinaryFunction &Func) const {
if (!BAT)
return Func.getOneName();

const BinaryFunction *OrigFunc = &Func;
if (const uint64_t HotAddr = BAT->fetchParentAddress(Func.getAddress())) {
NumColdSamples += Count;
BinaryFunction *HotFunc = getBinaryFunctionContainingAddress(HotAddr);
if (HotFunc)
OrigFunc = HotFunc;
}
// If it is a local function, prefer the name containing the file name where
// the local function was declared
for (StringRef AlternativeName : OrigFunc->getNames()) {
Expand All @@ -690,12 +689,17 @@ StringRef DataAggregator::getLocationName(BinaryFunction &Func,
return OrigFunc->getOneName();
}

bool DataAggregator::doSample(BinaryFunction &Func, uint64_t Address,
bool DataAggregator::doSample(BinaryFunction &OrigFunc, uint64_t Address,
uint64_t Count) {
BinaryFunction *ParentFunc = getBATParentFunction(OrigFunc);
BinaryFunction &Func = ParentFunc ? *ParentFunc : OrigFunc;
if (ParentFunc)
NumColdSamples += Count;

auto I = NamesToSamples.find(Func.getOneName());
if (I == NamesToSamples.end()) {
bool Success;
StringRef LocName = getLocationName(Func, Count);
StringRef LocName = getLocationName(Func);
std::tie(I, Success) = NamesToSamples.insert(
std::make_pair(Func.getOneName(),
FuncSampleData(LocName, FuncSampleData::ContainerTy())));
Expand All @@ -715,22 +719,12 @@ bool DataAggregator::doIntraBranch(BinaryFunction &Func, uint64_t From,
FuncBranchData *AggrData = getBranchData(Func);
if (!AggrData) {
AggrData = &NamesToBranches[Func.getOneName()];
AggrData->Name = getLocationName(Func, Count);
AggrData->Name = getLocationName(Func);
setBranchData(Func, AggrData);
}

From -= Func.getAddress();
To -= Func.getAddress();
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: bumpBranchCount: "
<< formatv("{0} @ {1:x} -> {0} @ {2:x}\n", Func, From, To));
if (BAT) {
From = BAT->translate(Func.getAddress(), From, /*IsBranchSrc=*/true);
To = BAT->translate(Func.getAddress(), To, /*IsBranchSrc=*/false);
LLVM_DEBUG(
dbgs() << "BOLT-DEBUG: BAT translation on bumpBranchCount: "
<< formatv("{0} @ {1:x} -> {0} @ {2:x}\n", Func, From, To));
}

AggrData->bumpBranchCount(From, To, Count, Mispreds);
return true;
}
Expand All @@ -744,30 +738,24 @@ bool DataAggregator::doInterBranch(BinaryFunction *FromFunc,
StringRef SrcFunc;
StringRef DstFunc;
if (FromFunc) {
SrcFunc = getLocationName(*FromFunc, Count);
SrcFunc = getLocationName(*FromFunc);
FromAggrData = getBranchData(*FromFunc);
if (!FromAggrData) {
FromAggrData = &NamesToBranches[FromFunc->getOneName()];
FromAggrData->Name = SrcFunc;
setBranchData(*FromFunc, FromAggrData);
}
From -= FromFunc->getAddress();
if (BAT)
From = BAT->translate(FromFunc->getAddress(), From, /*IsBranchSrc=*/true);

recordExit(*FromFunc, From, Mispreds, Count);
}
if (ToFunc) {
DstFunc = getLocationName(*ToFunc, 0);
DstFunc = getLocationName(*ToFunc);
ToAggrData = getBranchData(*ToFunc);
if (!ToAggrData) {
ToAggrData = &NamesToBranches[ToFunc->getOneName()];
ToAggrData->Name = DstFunc;
setBranchData(*ToFunc, ToAggrData);
}
To -= ToFunc->getAddress();
if (BAT)
To = BAT->translate(ToFunc->getAddress(), To, /*IsBranchSrc=*/false);

recordEntry(*ToFunc, To, Mispreds, Count);
}
Expand All @@ -783,15 +771,32 @@ bool DataAggregator::doInterBranch(BinaryFunction *FromFunc,

bool DataAggregator::doBranch(uint64_t From, uint64_t To, uint64_t Count,
uint64_t Mispreds) {
BinaryFunction *FromFunc = getBinaryFunctionContainingAddress(From);
BinaryFunction *ToFunc = getBinaryFunctionContainingAddress(To);
auto handleAddress = [&](uint64_t &Addr, bool IsFrom) -> BinaryFunction * {
if (BinaryFunction *Func = getBinaryFunctionContainingAddress(Addr)) {
Addr -= Func->getAddress();

if (BAT)
Addr = BAT->translate(Func->getAddress(), Addr, IsFrom);

if (BinaryFunction *ParentFunc = getBATParentFunction(*Func)) {
Func = ParentFunc;
if (IsFrom)
NumColdSamples += Count;
}

return Func;
}
return nullptr;
};

BinaryFunction *FromFunc = handleAddress(From, /*IsFrom=*/true);
BinaryFunction *ToFunc = handleAddress(To, /*IsFrom=*/false);
if (!FromFunc && !ToFunc)
return false;

// Treat recursive control transfers as inter-branches.
if (FromFunc == ToFunc && (To != ToFunc->getAddress())) {
recordBranch(*FromFunc, From - FromFunc->getAddress(),
To - FromFunc->getAddress(), Count, Mispreds);
if (FromFunc == ToFunc && To != 0) {
recordBranch(*FromFunc, From, To, Count, Mispreds);
return doIntraBranch(*FromFunc, From, To, Count, Mispreds);
}

Expand Down Expand Up @@ -842,9 +847,14 @@ bool DataAggregator::doTrace(const LBREntry &First, const LBREntry &Second,
<< FromFunc->getPrintName() << ":"
<< Twine::utohexstr(First.To) << " to "
<< Twine::utohexstr(Second.From) << ".\n");
for (const std::pair<uint64_t, uint64_t> &Pair : *FTs)
doIntraBranch(*FromFunc, Pair.first + FromFunc->getAddress(),
Pair.second + FromFunc->getAddress(), Count, false);
BinaryFunction *ParentFunc = getBATParentFunction(*FromFunc);
for (auto [From, To] : *FTs) {
if (BAT) {
From = BAT->translate(FromFunc->getAddress(), From, /*IsBranchSrc=*/true);
To = BAT->translate(FromFunc->getAddress(), To, /*IsBranchSrc=*/false);
}
doIntraBranch(ParentFunc ? *ParentFunc : *FromFunc, From, To, Count, false);
}

return true;
}
Expand Down Expand Up @@ -2273,29 +2283,6 @@ DataAggregator::writeAggregatedFile(StringRef OutputFilename) const {
return std::error_code();
}

void DataAggregator::fixupBATProfile(BinaryContext &BC) {
for (auto &[FuncName, Branches] : NamesToBranches) {
BinaryData *BD = BC.getBinaryDataByName(FuncName);
assert(BD);
uint64_t FuncAddress = BD->getAddress();
if (!BAT->isBATFunction(FuncAddress))
continue;
// Filter out cold fragments
if (!BD->getSectionName().equals(BC.getMainCodeSectionName()))
continue;
// Convert inter-branches between hot and cold fragments into
// intra-branches.
for (auto &[OffsetFrom, CallToMap] : Branches.InterIndex) {
for (auto &[CallToLoc, CallToIdx] : CallToMap) {
if (CallToLoc.Name != FuncName)
continue;
Branches.IntraIndex[OffsetFrom][CallToLoc.Offset] = CallToIdx;
Branches.InterIndex[OffsetFrom].erase(CallToLoc);
}
}
}
}

std::error_code DataAggregator::writeBATYAML(BinaryContext &BC,
StringRef OutputFilename) const {
std::error_code EC;
Expand Down Expand Up @@ -2345,9 +2332,6 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC,
uint64_t FuncAddress = BD->getAddress();
if (!BAT->isBATFunction(FuncAddress))
continue;
// Filter out cold fragments
if (!BD->getSectionName().equals(BC.getMainCodeSectionName()))
continue;
BinaryFunction *BF = BC.getBinaryFunctionAtAddress(FuncAddress);
assert(BF);
YamlBF.Name = FuncName.str();
Expand All @@ -2357,87 +2341,68 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC,
YamlBF.NumBasicBlocks = BAT->getNumBasicBlocks(FuncAddress);
const BoltAddressTranslation::BBHashMapTy &BlockMap =
BAT->getBBHashMap(FuncAddress);
YamlBF.Blocks.resize(YamlBF.NumBasicBlocks);

auto addSuccProfile = [&](yaml::bolt::BinaryBasicBlockProfile &YamlBB,
uint64_t SuccOffset, unsigned SuccDataIdx) {
for (auto &&[Idx, YamlBB] : llvm::enumerate(YamlBF.Blocks))
YamlBB.Index = Idx;

for (auto BI = BlockMap.begin(), BE = BlockMap.end(); BI != BE; ++BI)
YamlBF.Blocks[BI->second.getBBIndex()].Hash = BI->second.getBBHash();

auto getSuccessorInfo = [&](uint32_t SuccOffset, unsigned SuccDataIdx) {
const llvm::bolt::BranchInfo &BI = Branches.Data.at(SuccDataIdx);
yaml::bolt::SuccessorInfo SI;
SI.Index = BlockMap.getBBIndex(SuccOffset);
SI.Count = BI.Branches;
SI.Mispreds = BI.Mispreds;
YamlBB.Successors.emplace_back(SI);
return SI;
};

std::unordered_map<uint32_t, std::vector<uint32_t>> BFBranches =
BAT->getBFBranches(FuncAddress);

auto addCallsProfile = [&](yaml::bolt::BinaryBasicBlockProfile &YamlBB,
uint64_t Offset) {
// Iterate over BRANCHENTRY records in the current block
for (uint32_t BranchOffset : BFBranches[Offset]) {
if (!Branches.InterIndex.contains(BranchOffset))
continue;
for (const auto &[CallToLoc, CallToIdx] :
Branches.InterIndex.at(BranchOffset)) {
const llvm::bolt::BranchInfo &BI = Branches.Data.at(CallToIdx);
yaml::bolt::CallSiteInfo YamlCSI;
YamlCSI.DestId = 0; // designated for unknown functions
YamlCSI.EntryDiscriminator = 0;
YamlCSI.Count = BI.Branches;
YamlCSI.Mispreds = BI.Mispreds;
YamlCSI.Offset = BranchOffset - Offset;
BinaryData *CallTargetBD = BC.getBinaryDataByName(CallToLoc.Name);
if (!CallTargetBD) {
YamlBB.CallSites.emplace_back(YamlCSI);
continue;
}
uint64_t CallTargetAddress = CallTargetBD->getAddress();
BinaryFunction *CallTargetBF =
BC.getBinaryFunctionAtAddress(CallTargetAddress);
if (!CallTargetBF) {
YamlBB.CallSites.emplace_back(YamlCSI);
continue;
}
// Calls between hot and cold fragments must be handled in
// fixupBATProfile.
assert(CallTargetBF != BF && "invalid CallTargetBF");
YamlCSI.DestId = CallTargetBF->getFunctionNumber();
if (CallToLoc.Offset) {
if (BAT->isBATFunction(CallTargetAddress)) {
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: Unsupported secondary "
"entry point in BAT function "
<< CallToLoc.Name << '\n');
} else if (const BinaryBasicBlock *CallTargetBB =
CallTargetBF->getBasicBlockAtOffset(
CallToLoc.Offset)) {
// Only record true call information, ignoring returns (normally
// won't have a target basic block) and jumps to the landing
// pads (not an entry point).
if (CallTargetBB->isEntryPoint()) {
YamlCSI.EntryDiscriminator =
CallTargetBF->getEntryIDForSymbol(
CallTargetBB->getLabel());
}
}
}
YamlBB.CallSites.emplace_back(YamlCSI);
}
}
auto getCallSiteInfo = [&](Location CallToLoc, unsigned CallToIdx,
uint32_t Offset) {
const llvm::bolt::BranchInfo &BI = Branches.Data.at(CallToIdx);
yaml::bolt::CallSiteInfo CSI;
CSI.DestId = 0; // designated for unknown functions
CSI.EntryDiscriminator = 0;
CSI.Count = BI.Branches;
CSI.Mispreds = BI.Mispreds;
CSI.Offset = Offset;
if (BinaryData *BD = BC.getBinaryDataByName(CallToLoc.Name))
YAMLProfileWriter::setCSIDestination(BC, CSI, BD->getSymbol(), BAT,
CallToLoc.Offset);
return CSI;
};

for (const auto &[FromOffset, SuccKV] : Branches.IntraIndex) {
yaml::bolt::BinaryBasicBlockProfile YamlBB;
if (!BlockMap.isInputBlock(FromOffset))
continue;
YamlBB.Index = BlockMap.getBBIndex(FromOffset);
YamlBB.Hash = BlockMap.getBBHash(FromOffset);
const unsigned Index = BlockMap.getBBIndex(FromOffset);
yaml::bolt::BinaryBasicBlockProfile &YamlBB = YamlBF.Blocks[Index];
for (const auto &[SuccOffset, SuccDataIdx] : SuccKV)
addSuccProfile(YamlBB, SuccOffset, SuccDataIdx);
addCallsProfile(YamlBB, FromOffset);
if (YamlBB.ExecCount || !YamlBB.Successors.empty() ||
!YamlBB.CallSites.empty())
YamlBF.Blocks.emplace_back(YamlBB);
if (BlockMap.isInputBlock(SuccOffset))
YamlBB.Successors.emplace_back(
getSuccessorInfo(SuccOffset, SuccDataIdx));
}
for (const auto &[FromOffset, CallTo] : Branches.InterIndex) {
auto BlockIt = BlockMap.upper_bound(FromOffset);
--BlockIt;
const unsigned BlockOffset = BlockIt->first;
const unsigned BlockIndex = BlockIt->second.getBBIndex();
yaml::bolt::BinaryBasicBlockProfile &YamlBB = YamlBF.Blocks[BlockIndex];
const uint32_t Offset = FromOffset - BlockOffset;
for (const auto &[CallToLoc, CallToIdx] : CallTo)
YamlBB.CallSites.emplace_back(
getCallSiteInfo(CallToLoc, CallToIdx, Offset));
llvm::sort(YamlBB.CallSites, [](yaml::bolt::CallSiteInfo &A,
yaml::bolt::CallSiteInfo &B) {
return A.Offset < B.Offset;
});
}
// Drop blocks without a hash, won't be useful for stale matching.
llvm::erase_if(YamlBF.Blocks,
[](const yaml::bolt::BinaryBasicBlockProfile &YamlBB) {
return YamlBB.Hash == (yaml::Hex64)0;
});
BP.Functions.emplace_back(YamlBF);
}
}
Expand Down
5 changes: 3 additions & 2 deletions bolt/lib/Rewrite/BinaryPassManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,9 @@ Error BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) {

Manager.registerPass(std::make_unique<NormalizeCFG>(PrintNormalized));

Manager.registerPass(std::make_unique<StripRepRet>(NeverPrint),
opts::StripRepRet);
if (BC.isX86())
Manager.registerPass(std::make_unique<StripRepRet>(NeverPrint),
opts::StripRepRet);

Manager.registerPass(std::make_unique<IdenticalCodeFolding>(PrintICF),
opts::ICF);
Expand Down
30 changes: 17 additions & 13 deletions bolt/lib/Rewrite/RewriteInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ Error RewriteInstance::discoverStorage() {
if (Error E = SectionNameOrErr.takeError())
return E;
StringRef SectionName = SectionNameOrErr.get();
if (SectionName == ".text") {
if (SectionName == BC->getMainCodeSectionName()) {
BC->OldTextSectionAddress = Section.getAddress();
BC->OldTextSectionSize = Section.getSize();

Expand Down Expand Up @@ -1864,7 +1864,8 @@ Error RewriteInstance::readSpecialSections() {
"Use -update-debug-sections to keep it.\n";
}

HasTextRelocations = (bool)BC->getUniqueSectionByName(".rela.text");
HasTextRelocations = (bool)BC->getUniqueSectionByName(
".rela" + std::string(BC->getMainCodeSectionName()));
HasSymbolTable = (bool)BC->getUniqueSectionByName(".symtab");
EHFrameSection = BC->getUniqueSectionByName(".eh_frame");
BuildIDSection = BC->getUniqueSectionByName(".note.gnu.build-id");
Expand Down Expand Up @@ -2305,9 +2306,13 @@ void RewriteInstance::processRelocations() {
return;

for (const SectionRef &Section : InputFile->sections()) {
if (cantFail(Section.getRelocatedSection()) != InputFile->section_end() &&
!BinarySection(*BC, Section).isAllocatable())
readRelocations(Section);
section_iterator SecIter = cantFail(Section.getRelocatedSection());
if (SecIter == InputFile->section_end())
continue;
if (BinarySection(*BC, Section).isAllocatable())
continue;

readRelocations(Section);
}

if (NumFailedRelocations)
Expand Down Expand Up @@ -3441,7 +3446,8 @@ void RewriteInstance::emitAndLink() {
ErrorOr<BinarySection &> TextSection =
BC->getUniqueSectionByName(BC->getMainCodeSectionName());
if (BC->HasRelocations && TextSection)
BC->renameSection(*TextSection, getOrgSecPrefix() + ".text");
BC->renameSection(*TextSection,
getOrgSecPrefix() + BC->getMainCodeSectionName());

//////////////////////////////////////////////////////////////////////////////
// Assign addresses to new sections.
Expand Down Expand Up @@ -4298,18 +4304,17 @@ RewriteInstance::getOutputSections(ELFObjectFile<ELFT> *File,
for (auto &SectionKV : OutputSections) {
ELFShdrTy &Section = SectionKV.second;

// Ignore TLS sections as they don't take any space in the file.
// Ignore NOBITS sections as they don't take any space in the file.
if (Section.sh_type == ELF::SHT_NOBITS)
continue;

// Note that address continuity is not guaranteed as sections could be
// placed in different loadable segments.
if (PrevSection &&
PrevSection->sh_offset + PrevSection->sh_size > Section.sh_offset) {
if (opts::Verbosity > 1) {
if (opts::Verbosity > 1)
BC->outs() << "BOLT-INFO: adjusting size for section "
<< PrevBinSec->getOutputName() << '\n';
}
PrevSection->sh_size = Section.sh_offset - PrevSection->sh_offset;
}

Expand Down Expand Up @@ -4417,6 +4422,7 @@ void RewriteInstance::patchELFSectionHeaderTable(ELFObjectFile<ELFT> *File) {
raw_fd_ostream &OS = Out->os();
const ELFFile<ELFT> &Obj = File->getELFFile();

// Mapping from old section indices to new ones
std::vector<uint32_t> NewSectionIndex;
std::vector<ELFShdrTy> OutputSections =
getOutputSections(File, NewSectionIndex);
Expand All @@ -4434,10 +4440,8 @@ void RewriteInstance::patchELFSectionHeaderTable(ELFObjectFile<ELFT> *File) {
// Write all section header entries while patching section references.
for (ELFShdrTy &Section : OutputSections) {
Section.sh_link = NewSectionIndex[Section.sh_link];
if (Section.sh_type == ELF::SHT_REL || Section.sh_type == ELF::SHT_RELA) {
if (Section.sh_info)
Section.sh_info = NewSectionIndex[Section.sh_info];
}
if (Section.sh_type == ELF::SHT_REL || Section.sh_type == ELF::SHT_RELA)
Section.sh_info = NewSectionIndex[Section.sh_info];
OS.write(reinterpret_cast<const char *>(&Section), sizeof(Section));
}

Expand Down
23 changes: 22 additions & 1 deletion bolt/test/X86/patch-entries.test
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,25 @@ REQUIRES: system-linux

RUN: %clang %cflags -no-pie -g %p/Inputs/patch-entries.c -fuse-ld=lld -o %t.exe \
RUN: -Wl,-q -I%p/../Inputs
RUN: llvm-bolt -relocs %t.exe -o %t.out --update-debug-sections --force-patch
RUN: llvm-bolt -relocs %t.exe -o %t.out --update-debug-sections --force-patch \
RUN: --enable-bat

# Check that patched functions can be disassembled (override FDE from the
# original function)
# PREAGG: B X:0 #foo.org.0# 1 0
RUN: link_fdata %s %t.out %t.preagg PREAGG
RUN: perf2bolt %t.out -p %t.preagg --pa -o %t.yaml --profile-format=yaml \
RUN: -print-disasm -print-only=foo.org.0/1 2>&1 | FileCheck %s
CHECK-NOT: BOLT-WARNING: sizes differ for function foo.org.0/1
CHECK: Binary Function "foo.org.0/1(*2)" after disassembly {

# Check the expected eh_frame contents
RUN: llvm-nm --print-size %t.out > %t.foo
RUN: llvm-objdump %t.out --dwarf=frames >> %t.foo
RUN: FileCheck %s --input-file %t.foo --check-prefix=CHECK-FOO
CHECK-FOO: 0000000000[[#%x,FOO:]] [[#%x,OPTSIZE:]] t foo
CHECK-FOO: 0000000000[[#%x,ORG:]] [[#%x,ORGSIZE:]] t foo.org.0
# patched FDE comes first
CHECK-FOO: FDE {{.*}} pc=00[[#%x,ORG]]...00[[#%x,ORG+ORGSIZE]]
# original FDE comes second
CHECK-FOO: FDE {{.*}} pc=00[[#%x,ORG]]...00[[#%x,ORG+OPTSIZE]]
74 changes: 66 additions & 8 deletions bolt/test/X86/yaml-secondary-entry-discriminator.s
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# This reproduces a bug with BOLT setting incorrect discriminator for
# secondary entry points in YAML profile.
## This reproduces a bug with BOLT setting incorrect discriminator for
## secondary entry points in YAML profile.

# REQUIRES: system-linux
# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o
Expand All @@ -24,7 +24,7 @@
# CHECK-NEXT: hash: {{.*}}
# CHECK-NEXT: calls: [ { off: 0x0, fid: 1, disc: 1, cnt: 1, mis: 1 } ]

# Make sure that the profile is attached correctly
## Make sure that the profile is attached correctly
# RUN: llvm-bolt %t.exe -o %t.out --data %t.yaml --print-profile \
# RUN: --print-only=main | FileCheck %s --check-prefix=CHECK-CFG

Expand All @@ -33,25 +33,77 @@
# CHECK-CFG: callq *%rax # Offset: [[#]] # CallProfile: 1 (1 misses) :
# CHECK-CFG-NEXT: { secondary_entry: 1 (1 misses) }

# YAML BAT test of calling BAT secondary entry from non-BAT function
# Now force-split func and skip main (making it call secondary entries)
## YAML BAT test of calling BAT secondary entry from non-BAT function
## Now force-split func and skip main (making it call secondary entries)
# RUN: llvm-bolt %t.exe -o %t.bat --data %t.fdata --funcs=func \
# RUN: --split-functions --split-strategy=all --split-all-cold --enable-bat

## Prepare pre-aggregated profile using %t.bat
# RUN: link_fdata %s %t.bat %t.preagg PREAGG
## Strip labels used for pre-aggregated profile
# RUN: llvm-strip -NLcall -NLindcall %t.bat

## Convert pre-aggregated profile using BAT
# RUN: perf2bolt %t.bat -p %t.preagg --pa -o %t.bat.fdata -w %t.bat.yaml

## Convert BAT fdata into YAML
# RUN: llvm-bolt %t.exe -data %t.bat.fdata -w %t.bat.fdata-yaml -o /dev/null

## Check fdata YAML - make sure that a direct call has discriminator field
# RUN: FileCheck %s --input-file %t.bat.fdata-yaml -check-prefix CHECK-BAT-YAML

## Check BAT YAML - make sure that a direct call has discriminator field
# RUN: FileCheck %s --input-file %t.bat.yaml --check-prefix CHECK-BAT-YAML

## YAML BAT test of calling BAT secondary entry from BAT function
# RUN: llvm-bolt %t.exe -o %t.bat2 --data %t.fdata --funcs=main,func \
# RUN: --split-functions --split-strategy=all --split-all-cold --enable-bat

## Prepare pre-aggregated profile using %t.bat
# RUN: link_fdata %s %t.bat2 %t.preagg2 PREAGG2

## Strip labels used for pre-aggregated profile
# RUN: llvm-strip -NLcall -NLindcall %t.bat2

## Convert pre-aggregated profile using BAT
# RUN: perf2bolt %t.bat2 -p %t.preagg2 --pa -o %t.bat2.fdata -w %t.bat2.yaml

## Convert BAT fdata into YAML
# RUN: llvm-bolt %t.exe -data %t.bat2.fdata -w %t.bat2.fdata-yaml -o /dev/null

## Check fdata YAML - make sure that a direct call has discriminator field
# RUN: FileCheck %s --input-file %t.bat2.fdata-yaml -check-prefix CHECK-BAT-YAML

## Check BAT YAML - make sure that a direct call has discriminator field
# RUN: FileCheck %s --input-file %t.bat2.yaml --check-prefix CHECK-BAT-YAML

# CHECK-BAT-YAML: - name: main
# CHECK-BAT-YAML-NEXT: fid: [[#]]
# CHECK-BAT-YAML-NEXT: hash: 0xADF270D550151185
# CHECK-BAT-YAML-NEXT: exec: 0
# CHECK-BAT-YAML-NEXT: nblocks: 4
# CHECK-BAT-YAML-NEXT: blocks:
# CHECK-BAT-YAML: - bid: 1
# CHECK-BAT-YAML-NEXT: insns: [[#]]
# CHECK-BAT-YAML-NEXT: hash: 0x36A303CBA4360018
# CHECK-BAT-YAML-NEXT: calls: [ { off: 0x0, fid: [[#]], disc: 1, cnt: 1

.globl func
.type func, @function
func:
# FDATA: 0 [unknown] 0 1 func 0 1 0
# PREAGG: B X:0 #func# 1 1
# PREAGG2: B X:0 #func# 1 1
.cfi_startproc
pushq %rbp
movq %rsp, %rbp
# Placeholder code to make splitting profitable
## Placeholder code to make splitting profitable
.rept 5
testq %rax, %rax
.endr
.globl secondary_entry
secondary_entry:
# Placeholder code to make splitting profitable
## Placeholder code to make splitting profitable
.rept 5
testq %rax, %rax
.endr
Expand All @@ -71,17 +123,23 @@ main:
movl $0, -4(%rbp)
testq %rax, %rax
jne Lindcall
.globl Lcall
Lcall:
call secondary_entry
# FDATA: 1 main #Lcall# 1 secondary_entry 0 1 1
# PREAGG: B #Lcall# #secondary_entry# 1 1
# PREAGG2: B #main.cold.0# #func.cold.0# 1 1
.globl Lindcall
Lindcall:
callq *%rax
# FDATA: 1 main #Lindcall# 1 secondary_entry 0 1 1
# PREAGG: B #Lindcall# #secondary_entry# 1 1
# PREAGG2: B #main.cold.1# #func.cold.0# 1 1
xorl %eax, %eax
addq $16, %rsp
popq %rbp
retq
# For relocations against .text
## For relocations against .text
call exit
.cfi_endproc
.size main, .-main
164 changes: 164 additions & 0 deletions bolt/test/runtime/X86/jt-confusion.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# REQUIRES: system-linux

# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o
# RUN: llvm-strip --strip-unneeded %t.o
# RUN: %clang %cflags -no-pie -nostartfiles -nostdlib -lc %t.o -o %t.exe -Wl,-q

# RUN: llvm-bolt %t.exe -o %t.exe.bolt --relocs=1 --lite=0

# RUN: %t.exe.bolt

## Check that BOLT's jump table detection diffrentiates between
## __builtin_unreachable() targets and function pointers.

## The test case was built from the following two source files and
## modiffied for standalone build. main became _start, etc.
## $ $(CC) a.c -O1 -S -o a.s
## $ $(CC) b.c -O0 -S -o b.s

## a.c:

## typedef int (*fptr)(int);
## void check_fptr(fptr, int);
##
## int foo(int a) {
## check_fptr(foo, 0);
## switch (a) {
## default:
## __builtin_unreachable();
## case 0:
## return 3;
## case 1:
## return 5;
## case 2:
## return 7;
## case 3:
## return 11;
## case 4:
## return 13;
## case 5:
## return 17;
## }
## return 0;
## }
##
## int main(int argc) {
## check_fptr(main, 1);
## return foo(argc);
## }
##
## const fptr funcs[2] = {foo, main};

## b.c.:

## typedef int (*fptr)(int);
## extern const fptr funcs[2];
##
## #define assert(C) { if (!(C)) (*(unsigned long long *)0) = 0; }
## void check_fptr(fptr f, int i) {
## assert(f == funcs[i]);
## }


.text
.globl foo
.type foo, @function
foo:
.LFB0:
.cfi_startproc
pushq %rbx
.cfi_def_cfa_offset 16
.cfi_offset 3, -16
movl %edi, %ebx
movl $0, %esi
movl $foo, %edi
call check_fptr
movl %ebx, %ebx
jmp *.L4(,%rbx,8)
.L8:
movl $5, %eax
jmp .L1
.L7:
movl $7, %eax
jmp .L1
.L6:
movl $11, %eax
jmp .L1
.L5:
movl $13, %eax
jmp .L1
.L3:
movl $17, %eax
jmp .L1
.L10:
movl $3, %eax
.L1:
popq %rbx
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE0:
.size foo, .-foo
.globl _start
.type _start, @function
_start:
.LFB1:
.cfi_startproc
pushq %rbx
.cfi_def_cfa_offset 16
.cfi_offset 3, -16
movl %edi, %ebx
movl $1, %esi
movl $_start, %edi
call check_fptr
movl $1, %edi
call foo
popq %rbx
.cfi_def_cfa_offset 8
callq exit@PLT
.cfi_endproc
.LFE1:
.size _start, .-_start
.globl check_fptr
.type check_fptr, @function
check_fptr:
.LFB2:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movq %rdi, -8(%rbp)
movl %esi, -12(%rbp)
movl -12(%rbp), %eax
cltq
movq funcs(,%rax,8), %rax
cmpq %rax, -8(%rbp)
je .L33
movl $0, %eax
movq $0, (%rax)
.L33:
nop
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc

.section .rodata
.align 8
.align 4
.L4:
.quad .L10
.quad .L8
.quad .L7
.quad .L6
.quad .L5
.quad .L3

.globl funcs
.type funcs, @object
.size funcs, 16
funcs:
.quad foo
.quad _start
46 changes: 26 additions & 20 deletions clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,14 +169,14 @@ class RenamerClangTidyCheckPPCallbacks : public PPCallbacks {
return;
if (SM.isWrittenInCommandLineFile(MacroNameTok.getLocation()))
return;
Check->checkMacro(SM, MacroNameTok, Info);
Check->checkMacro(MacroNameTok, Info, SM);
}

/// MacroExpands calls expandMacro for macros in the main file
void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
SourceRange /*Range*/,
const MacroArgs * /*Args*/) override {
Check->expandMacro(MacroNameTok, MD.getMacroInfo());
Check->expandMacro(MacroNameTok, MD.getMacroInfo(), SM);
}

private:
Expand All @@ -187,7 +187,7 @@ class RenamerClangTidyCheckPPCallbacks : public PPCallbacks {
class RenamerClangTidyVisitor
: public RecursiveASTVisitor<RenamerClangTidyVisitor> {
public:
RenamerClangTidyVisitor(RenamerClangTidyCheck *Check, const SourceManager *SM,
RenamerClangTidyVisitor(RenamerClangTidyCheck *Check, const SourceManager &SM,
bool AggressiveDependentMemberLookup)
: Check(Check), SM(SM),
AggressiveDependentMemberLookup(AggressiveDependentMemberLookup) {}
Expand Down Expand Up @@ -258,7 +258,7 @@ class RenamerClangTidyVisitor
// Fix overridden methods
if (const auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
if (const CXXMethodDecl *Overridden = getOverrideMethod(Method)) {
Check->addUsage(Overridden, Method->getLocation());
Check->addUsage(Overridden, Method->getLocation(), SM);
return true; // Don't try to add the actual decl as a Failure.
}
}
Expand All @@ -268,7 +268,7 @@ class RenamerClangTidyVisitor
if (isa<ClassTemplateSpecializationDecl>(Decl))
return true;

Check->checkNamedDecl(Decl, *SM);
Check->checkNamedDecl(Decl, SM);
return true;
}

Expand Down Expand Up @@ -385,7 +385,7 @@ class RenamerClangTidyVisitor

private:
RenamerClangTidyCheck *Check;
const SourceManager *SM;
const SourceManager &SM;
const bool AggressiveDependentMemberLookup;
};

Expand Down Expand Up @@ -415,7 +415,7 @@ void RenamerClangTidyCheck::registerPPCallbacks(

void RenamerClangTidyCheck::addUsage(
const RenamerClangTidyCheck::NamingCheckId &Decl, SourceRange Range,
const SourceManager *SourceMgr) {
const SourceManager &SourceMgr) {
// Do nothing if the provided range is invalid.
if (Range.isInvalid())
return;
Expand All @@ -425,8 +425,7 @@ void RenamerClangTidyCheck::addUsage(
// spelling location to different source locations, and we only want to fix
// the token once, before it is expanded by the macro.
SourceLocation FixLocation = Range.getBegin();
if (SourceMgr)
FixLocation = SourceMgr->getSpellingLoc(FixLocation);
FixLocation = SourceMgr.getSpellingLoc(FixLocation);
if (FixLocation.isInvalid())
return;

Expand All @@ -440,15 +439,15 @@ void RenamerClangTidyCheck::addUsage(
if (!Failure.shouldFix())
return;

if (SourceMgr && SourceMgr->isWrittenInScratchSpace(FixLocation))
if (SourceMgr.isWrittenInScratchSpace(FixLocation))
Failure.FixStatus = RenamerClangTidyCheck::ShouldFixStatus::InsideMacro;

if (!utils::rangeCanBeFixed(Range, SourceMgr))
if (!utils::rangeCanBeFixed(Range, &SourceMgr))
Failure.FixStatus = RenamerClangTidyCheck::ShouldFixStatus::InsideMacro;
}

void RenamerClangTidyCheck::addUsage(const NamedDecl *Decl, SourceRange Range,
const SourceManager *SourceMgr) {
const SourceManager &SourceMgr) {
// Don't keep track for non-identifier names.
auto *II = Decl->getIdentifier();
if (!II)
Expand Down Expand Up @@ -489,18 +488,24 @@ void RenamerClangTidyCheck::checkNamedDecl(const NamedDecl *Decl,
}

Failure.Info = std::move(Info);
addUsage(Decl, Range, &SourceMgr);
addUsage(Decl, Range, SourceMgr);
}

void RenamerClangTidyCheck::check(const MatchFinder::MatchResult &Result) {
RenamerClangTidyVisitor Visitor(this, Result.SourceManager,
if (!Result.SourceManager) {
// In principle SourceManager is not null but going only by the definition
// of MatchResult it must be handled. Cannot rename anything without a
// SourceManager.
return;
}
RenamerClangTidyVisitor Visitor(this, *Result.SourceManager,
AggressiveDependentMemberLookup);
Visitor.TraverseAST(*Result.Context);
}

void RenamerClangTidyCheck::checkMacro(const SourceManager &SourceMgr,
const Token &MacroNameTok,
const MacroInfo *MI) {
void RenamerClangTidyCheck::checkMacro(const Token &MacroNameTok,
const MacroInfo *MI,
const SourceManager &SourceMgr) {
std::optional<FailureInfo> MaybeFailure =
getMacroFailureInfo(MacroNameTok, SourceMgr);
if (!MaybeFailure)
Expand All @@ -515,11 +520,12 @@ void RenamerClangTidyCheck::checkMacro(const SourceManager &SourceMgr,
Failure.FixStatus = ShouldFixStatus::FixInvalidIdentifier;

Failure.Info = std::move(Info);
addUsage(ID, Range);
addUsage(ID, Range, SourceMgr);
}

void RenamerClangTidyCheck::expandMacro(const Token &MacroNameTok,
const MacroInfo *MI) {
const MacroInfo *MI,
const SourceManager &SourceMgr) {
StringRef Name = MacroNameTok.getIdentifierInfo()->getName();
NamingCheckId ID(MI->getDefinitionLoc(), Name);

Expand All @@ -528,7 +534,7 @@ void RenamerClangTidyCheck::expandMacro(const Token &MacroNameTok,
return;

SourceRange Range(MacroNameTok.getLocation(), MacroNameTok.getEndLoc());
addUsage(ID, Range);
addUsage(ID, Range, SourceMgr);
}

static std::string
Expand Down
11 changes: 6 additions & 5 deletions clang-tools-extra/clang-tidy/utils/RenamerClangTidyCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,18 +108,19 @@ class RenamerClangTidyCheck : public ClangTidyCheck {
llvm::DenseMap<NamingCheckId, NamingCheckFailure>;

/// Check Macros for style violations.
void checkMacro(const SourceManager &SourceMgr, const Token &MacroNameTok,
const MacroInfo *MI);
void checkMacro(const Token &MacroNameTok, const MacroInfo *MI,
const SourceManager &SourceMgr);

/// Add a usage of a macro if it already has a violation.
void expandMacro(const Token &MacroNameTok, const MacroInfo *MI);
void expandMacro(const Token &MacroNameTok, const MacroInfo *MI,
const SourceManager &SourceMgr);

void addUsage(const RenamerClangTidyCheck::NamingCheckId &Decl,
SourceRange Range, const SourceManager *SourceMgr = nullptr);
SourceRange Range, const SourceManager &SourceMgr);

/// Convenience method when the usage to be added is a NamedDecl.
void addUsage(const NamedDecl *Decl, SourceRange Range,
const SourceManager *SourceMgr = nullptr);
const SourceManager &SourceMgr);

void checkNamedDecl(const NamedDecl *Decl, const SourceManager &SourceMgr);

Expand Down
16 changes: 13 additions & 3 deletions clang-tools-extra/clangd/CodeComplete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,11 @@ const CodeCompleteOptions::CodeCompletionRankingModel

namespace {

CompletionItemKind toCompletionItemKind(index::SymbolKind Kind) {
// Note: changes to this function should also be reflected in the
// CodeCompletionResult overload where appropriate.
CompletionItemKind
toCompletionItemKind(index::SymbolKind Kind,
const llvm::StringRef *Signature = nullptr) {
using SK = index::SymbolKind;
switch (Kind) {
case SK::Unknown:
Expand All @@ -99,7 +103,10 @@ CompletionItemKind toCompletionItemKind(index::SymbolKind Kind) {
case SK::NamespaceAlias:
return CompletionItemKind::Module;
case SK::Macro:
return CompletionItemKind::Text;
// Use macro signature (if provided) to tell apart function-like and
// object-like macros.
return Signature && Signature->contains('(') ? CompletionItemKind::Function
: CompletionItemKind::Constant;
case SK::Enum:
return CompletionItemKind::Enum;
case SK::Struct:
Expand Down Expand Up @@ -150,6 +157,8 @@ CompletionItemKind toCompletionItemKind(index::SymbolKind Kind) {
llvm_unreachable("Unhandled clang::index::SymbolKind.");
}

// Note: changes to this function should also be reflected in the
// index::SymbolKind overload where appropriate.
CompletionItemKind toCompletionItemKind(const CodeCompletionResult &Res,
CodeCompletionContext::Kind CtxKind) {
if (Res.Declaration)
Expand Down Expand Up @@ -379,7 +388,8 @@ struct CodeCompletionBuilder {
if (Completion.Scope.empty())
Completion.Scope = std::string(C.IndexResult->Scope);
if (Completion.Kind == CompletionItemKind::Missing)
Completion.Kind = toCompletionItemKind(C.IndexResult->SymInfo.Kind);
Completion.Kind = toCompletionItemKind(C.IndexResult->SymInfo.Kind,
&C.IndexResult->Signature);
if (Completion.Name.empty())
Completion.Name = std::string(C.IndexResult->Name);
if (Completion.FilterText.empty())
Expand Down
2 changes: 1 addition & 1 deletion clang-tools-extra/clangd/index/SymbolCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ class SymbolCollector::HeaderFileURICache {
// Framework headers are spelled as <FrameworkName/Foo.h>, not
// "path/FrameworkName.framework/Headers/Foo.h".
auto &HS = PP->getHeaderSearchInfo();
if (const auto *HFI = HS.getExistingFileInfo(*FE, /*WantExternal*/ false))
if (const auto *HFI = HS.getExistingFileInfo(*FE))
if (!HFI->Framework.empty())
if (auto Spelling =
getFrameworkHeaderIncludeSpelling(*FE, HFI->Framework, HS))
Expand Down
7 changes: 5 additions & 2 deletions clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,8 @@ TEST(CompletionTest, Kinds) {
#define MACRO 10
int X = ^
)cpp",
{func("indexFunction"), var("indexVariable"), cls("indexClass")});
{func("indexFunction"), var("indexVariable"), cls("indexClass"),
macro("indexObjMacro"), macro("indexFuncMacro", "(x, y)")});
EXPECT_THAT(Results.Completions,
AllOf(has("function", CompletionItemKind::Function),
has("variable", CompletionItemKind::Variable),
Expand All @@ -680,7 +681,9 @@ TEST(CompletionTest, Kinds) {
has("MACRO", CompletionItemKind::Constant),
has("indexFunction", CompletionItemKind::Function),
has("indexVariable", CompletionItemKind::Variable),
has("indexClass", CompletionItemKind::Class)));
has("indexClass", CompletionItemKind::Class),
has("indexObjMacro", CompletionItemKind::Constant),
has("indexFuncMacro", CompletionItemKind::Function)));

Results = completions("nam^");
EXPECT_THAT(Results.Completions,
Expand Down
8 changes: 6 additions & 2 deletions clang-tools-extra/clangd/unittests/HoverTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1983,10 +1983,14 @@ TEST(Hover, All) {
HI.Kind = index::SymbolKind::Macro;
HI.Definition =
R"cpp(#define MACRO \
{ return 0; }
{ \
return 0; \
}
// Expands to
{ return 0; })cpp";
{
return 0;
})cpp";
}},
{
R"cpp(// Forward class declaration
Expand Down
7 changes: 6 additions & 1 deletion clang-tools-extra/clangd/unittests/TestIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ static std::string replace(llvm::StringRef Haystack, llvm::StringRef Needle,
// Helpers to produce fake index symbols for memIndex() or completions().
// USRFormat is a regex replacement string for the unqualified part of the USR.
Symbol sym(llvm::StringRef QName, index::SymbolKind Kind,
llvm::StringRef USRFormat) {
llvm::StringRef USRFormat, llvm::StringRef Signature) {
Symbol Sym;
std::string USR = "c:"; // We synthesize a few simple cases of USRs by hand!
size_t Pos = QName.rfind("::");
Expand All @@ -55,6 +55,7 @@ Symbol sym(llvm::StringRef QName, index::SymbolKind Kind,
Sym.SymInfo.Kind = Kind;
Sym.Flags |= Symbol::IndexedForCodeCompletion;
Sym.Origin = SymbolOrigin::Static;
Sym.Signature = Signature;
return Sym;
}

Expand Down Expand Up @@ -86,6 +87,10 @@ Symbol conceptSym(llvm::StringRef Name) {
return sym(Name, index::SymbolKind::Concept, "@CT@\\0");
}

Symbol macro(llvm::StringRef Name, llvm::StringRef ArgList) {
return sym(Name, index::SymbolKind::Macro, "@macro@\\0", ArgList);
}

Symbol objcSym(llvm::StringRef Name, index::SymbolKind Kind,
llvm::StringRef USRPrefix) {
Symbol Sym;
Expand Down
4 changes: 3 additions & 1 deletion clang-tools-extra/clangd/unittests/TestIndex.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Symbol symbol(llvm::StringRef QName);
// Helpers to produce fake index symbols with proper SymbolID.
// USRFormat is a regex replacement string for the unqualified part of the USR.
Symbol sym(llvm::StringRef QName, index::SymbolKind Kind,
llvm::StringRef USRFormat);
llvm::StringRef USRFormat, llvm::StringRef Signature = {});
// Creats a function symbol assuming no function arg.
Symbol func(llvm::StringRef Name);
// Creates a class symbol.
Expand All @@ -35,6 +35,8 @@ Symbol var(llvm::StringRef Name);
Symbol ns(llvm::StringRef Name);
// Create a C++20 concept symbol.
Symbol conceptSym(llvm::StringRef Name);
// Create a macro symbol.
Symbol macro(llvm::StringRef Name, llvm::StringRef ArgList = {});

// Create an Objective-C symbol.
Symbol objcSym(llvm::StringRef Name, index::SymbolKind Kind,
Expand Down
6 changes: 6 additions & 0 deletions clang-tools-extra/include-cleaner/lib/FindHeaders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,12 @@ llvm::SmallVector<Header> headersForSymbol(const Symbol &S,
// are already ranked in the stdlib mapping.
if (H.kind() == Header::Standard)
continue;
// Don't apply name match hints to exporting headers. As they usually have
// names similar to the original header, e.g. foo_wrapper/foo.h vs
// foo/foo.h, but shouldn't be preferred (unless marked as the public
// interface).
if ((H.Hint & Hints::OriginHeader) == Hints::None)
continue;
if (nameMatch(SymbolName, H))
H.Hint |= Hints::PreferredHeader;
}
Expand Down
19 changes: 19 additions & 0 deletions clang-tools-extra/include-cleaner/unittests/FindHeadersTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -628,5 +628,24 @@ TEST_F(HeadersForSymbolTest, StandardHeaders) {
tooling::stdlib::Header::named("<assert.h>")));
}

TEST_F(HeadersForSymbolTest, ExporterNoNameMatch) {
Inputs.Code = R"cpp(
#include "exporter/foo.h"
#include "foo_public.h"
)cpp";
Inputs.ExtraArgs.emplace_back("-I.");
// Deliberately named as foo_public to make sure it doesn't get name-match
// boost and also gets lexicographically bigger order than "exporter/foo.h".
Inputs.ExtraFiles["foo_public.h"] = guard(R"cpp(
struct foo {};
)cpp");
Inputs.ExtraFiles["exporter/foo.h"] = guard(R"cpp(
#include "foo_public.h" // IWYU pragma: export
)cpp");
buildAST();
EXPECT_THAT(headersForFoo(), ElementsAre(physicalHeader("foo_public.h"),
physicalHeader("exporter/foo.h")));
}

} // namespace
} // namespace clang::include_cleaner
7 changes: 7 additions & 0 deletions clang/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,13 @@ if(CLANG_ENABLE_LIBXML2)
endif()
endif()

if(CLANG_ENABLE_CIR)
if (NOT "${LLVM_ENABLE_PROJECTS}" MATCHES "MLIR|mlir")
message(FATAL_ERROR
"Cannot build ClangIR without MLIR in LLVM_ENABLE_PROJECTS")
endif()
endif()

include(CheckIncludeFile)
check_include_file(sys/resource.h CLANG_HAVE_RLIMITS)

Expand Down
2 changes: 1 addition & 1 deletion clang/docs/ClangFormat.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# code.
Objective-C: .m .mm
Proto: .proto .protodevel
TableGen: .td
TextProto: .textpb .pb.txt .textproto .asciipb
TextProto: .txtpb .textpb .pb.txt .textproto .asciipb
Verilog: .sv .svh .v .vh
--cursor=<uint> - The position of the cursor when invoking
clang-format from an editor integration
Expand Down
9 changes: 9 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ Resolutions to C++ Defect Reports
compatibility of two types.
(`CWG2759: [[no_unique_address] and common initial sequence <https://cplusplus.github.io/CWG/issues/2759.html>`_).

- Clang now diagnoses declarative nested-name-specifiers with pack-index-specifiers.
(`CWG2858: Declarative nested-name-specifiers and pack-index-specifiers <https://cplusplus.github.io/CWG/issues/2858.html>`_).

C Language Changes
------------------

Expand Down Expand Up @@ -357,6 +360,9 @@ Improvements to Clang's diagnostics
Added the ``-Wtentative-definition-array`` warning group to cover this.
Fixes #GH87766

- Clang now uses the correct type-parameter-key (``class`` or ``typename``) when printing
template template parameter declarations.

Improvements to Clang's time-trace
----------------------------------

Expand Down Expand Up @@ -520,6 +526,8 @@ Bug Fixes to C++ Support
- Fix an issue caused by not handling invalid cases when substituting into the parameter mapping of a constraint. Fixes (#GH86757).
- Fixed a bug that prevented member function templates of class templates declared with a deduced return type
from being explicitly specialized for a given implicit instantiation of the class template.
- Fixed a crash when ``this`` is used in a dependent class scope function template specialization
that instantiates to a static member function.

- Fix crash when inheriting from a cv-qualified type. Fixes:
(`#35603 <https://github.com/llvm/llvm-project/issues/35603>`_)
Expand All @@ -532,6 +540,7 @@ Bug Fixes to C++ Support
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
- Clang now properly preserves ``FoundDecls`` within a ``ConceptReference``. (#GH82628)
- The presence of the ``typename`` keyword is now stored in ``TemplateTemplateParmDecl``.

Miscellaneous Bug Fixes
^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
1 change: 0 additions & 1 deletion clang/docs/tools/clang-formatted-files.txt
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ clang/include/clang/Analysis/Analyses/CalledOnceCheck.h
clang/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
clang/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h
clang/include/clang/Analysis/FlowSensitive/AdornedCFG.h
clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysis.h
clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h
clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -3411,13 +3411,13 @@ const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,

/// Utility function for constructing a nullary selector.
inline Selector GetNullarySelector(StringRef name, ASTContext &Ctx) {
IdentifierInfo* II = &Ctx.Idents.get(name);
const IdentifierInfo *II = &Ctx.Idents.get(name);
return Ctx.Selectors.getSelector(0, &II);
}

/// Utility function for constructing an unary selector.
inline Selector GetUnarySelector(StringRef name, ASTContext &Ctx) {
IdentifierInfo* II = &Ctx.Idents.get(name);
const IdentifierInfo *II = &Ctx.Idents.get(name);
return Ctx.Selectors.getSelector(1, &II);
}

Expand Down
11 changes: 10 additions & 1 deletion clang/include/clang/AST/ASTNodeTraverser.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,8 @@ class ASTNodeTraverser
void Visit(const OpenACCClause *C) {
getNodeDelegate().AddChild([=] {
getNodeDelegate().Visit(C);
// TODO OpenACC: Switch on clauses that have children, and add them.
for (const auto *S : C->children())
Visit(S);
});
}

Expand Down Expand Up @@ -932,6 +933,14 @@ class ASTNodeTraverser
Visit(TArg);
}

void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node) {
Visit(Node->getExpr());
}

void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node) {
Visit(Node->getExpr());
}

// Implements Visit methods for Attrs.
#include "clang/AST/AttrNodeTraverse.inc"
};
Expand Down
37 changes: 20 additions & 17 deletions clang/include/clang/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1731,7 +1731,7 @@ class ImplicitParamDecl : public VarDecl {
static ImplicitParamDecl *CreateDeserialized(ASTContext &C, unsigned ID);

ImplicitParamDecl(ASTContext &C, DeclContext *DC, SourceLocation IdLoc,
IdentifierInfo *Id, QualType Type,
const IdentifierInfo *Id, QualType Type,
ImplicitParamKind ParamKind)
: VarDecl(ImplicitParam, C, DC, IdLoc, IdLoc, Id, Type,
/*TInfo=*/nullptr, SC_None) {
Expand Down Expand Up @@ -1765,7 +1765,7 @@ class ParmVarDecl : public VarDecl {

protected:
ParmVarDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id, QualType T,
SourceLocation IdLoc, const IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
: VarDecl(DK, C, DC, StartLoc, IdLoc, Id, T, TInfo, S) {
assert(ParmVarDeclBits.HasInheritedDefaultArg == false);
Expand All @@ -1777,10 +1777,10 @@ class ParmVarDecl : public VarDecl {

public:
static ParmVarDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo,
StorageClass S, Expr *DefArg);
SourceLocation StartLoc, SourceLocation IdLoc,
const IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, StorageClass S,
Expr *DefArg);

static ParmVarDecl *CreateDeserialized(ASTContext &C, unsigned ID);

Expand Down Expand Up @@ -3095,7 +3095,7 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {

protected:
FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id, QualType T,
SourceLocation IdLoc, const IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
InClassInitStyle InitStyle)
: DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), BitField(false),
Expand All @@ -3111,7 +3111,7 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {

static FieldDecl *Create(const ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, QualType T,
const IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
InClassInitStyle InitStyle);

Expand Down Expand Up @@ -3332,8 +3332,9 @@ class IndirectFieldDecl : public ValueDecl,
friend class ASTDeclReader;

static IndirectFieldDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
QualType T, llvm::MutableArrayRef<NamedDecl *> CH);
SourceLocation L, const IdentifierInfo *Id,
QualType T,
llvm::MutableArrayRef<NamedDecl *> CH);

static IndirectFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID);

Expand Down Expand Up @@ -3381,9 +3382,9 @@ class TypeDecl : public NamedDecl {
void anchor() override;

protected:
TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, const IdentifierInfo *Id,
SourceLocation StartL = SourceLocation())
: NamedDecl(DK, DC, L, Id), LocStart(StartL) {}
: NamedDecl(DK, DC, L, Id), LocStart(StartL) {}

public:
// Low-level accessor. If you just want the type defined by this node,
Expand Down Expand Up @@ -3425,7 +3426,7 @@ class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> {
protected:
TypedefNameDecl(Kind DK, ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, TypeSourceInfo *TInfo)
const IdentifierInfo *Id, TypeSourceInfo *TInfo)
: TypeDecl(DK, DC, IdLoc, Id, StartLoc), redeclarable_base(C),
MaybeModedTInfo(TInfo, 0) {}

Expand Down Expand Up @@ -3512,13 +3513,14 @@ class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> {
/// type specifier.
class TypedefDecl : public TypedefNameDecl {
TypedefDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo)
SourceLocation IdLoc, const IdentifierInfo *Id,
TypeSourceInfo *TInfo)
: TypedefNameDecl(Typedef, C, DC, StartLoc, IdLoc, Id, TInfo) {}

public:
static TypedefDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, TypeSourceInfo *TInfo);
const IdentifierInfo *Id, TypeSourceInfo *TInfo);
static TypedefDecl *CreateDeserialized(ASTContext &C, unsigned ID);

SourceRange getSourceRange() const override LLVM_READONLY;
Expand All @@ -3535,14 +3537,15 @@ class TypeAliasDecl : public TypedefNameDecl {
TypeAliasTemplateDecl *Template;

TypeAliasDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo)
SourceLocation IdLoc, const IdentifierInfo *Id,
TypeSourceInfo *TInfo)
: TypedefNameDecl(TypeAlias, C, DC, StartLoc, IdLoc, Id, TInfo),
Template(nullptr) {}

public:
static TypeAliasDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, TypeSourceInfo *TInfo);
const IdentifierInfo *Id, TypeSourceInfo *TInfo);
static TypeAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID);

SourceRange getSourceRange() const override LLVM_READONLY;
Expand Down
89 changes: 42 additions & 47 deletions clang/include/clang/AST/DeclObjC.h
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,7 @@ class ObjCPropertyDecl : public NamedDecl {
// Synthesize ivar for this property
ObjCIvarDecl *PropertyIvarDecl = nullptr;

ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
ObjCPropertyDecl(DeclContext *DC, SourceLocation L, const IdentifierInfo *Id,
SourceLocation AtLocation, SourceLocation LParenLocation,
QualType T, TypeSourceInfo *TSI, PropertyControl propControl)
: NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation),
Expand All @@ -782,10 +782,12 @@ class ObjCPropertyDecl : public NamedDecl {
PropertyImplementation(propControl) {}

public:
static ObjCPropertyDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
SourceLocation AtLocation, SourceLocation LParenLocation, QualType T,
TypeSourceInfo *TSI, PropertyControl propControl = None);
static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, const IdentifierInfo *Id,
SourceLocation AtLocation,
SourceLocation LParenLocation, QualType T,
TypeSourceInfo *TSI,
PropertyControl propControl = None);

static ObjCPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID);

Expand Down Expand Up @@ -952,7 +954,7 @@ class ObjCContainerDecl : public NamedDecl, public DeclContext {
void anchor() override;

public:
ObjCContainerDecl(Kind DK, DeclContext *DC, IdentifierInfo *Id,
ObjCContainerDecl(Kind DK, DeclContext *DC, const IdentifierInfo *Id,
SourceLocation nameLoc, SourceLocation atStartLoc);

// Iterator access to instance/class properties.
Expand Down Expand Up @@ -1240,7 +1242,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
llvm::PointerIntPair<DefinitionData *, 1, bool> Data;

ObjCInterfaceDecl(const ASTContext &C, DeclContext *DC, SourceLocation AtLoc,
IdentifierInfo *Id, ObjCTypeParamList *typeParamList,
const IdentifierInfo *Id, ObjCTypeParamList *typeParamList,
SourceLocation CLoc, ObjCInterfaceDecl *PrevDecl,
bool IsInternal);

Expand Down Expand Up @@ -1271,13 +1273,11 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
}

public:
static ObjCInterfaceDecl *Create(const ASTContext &C, DeclContext *DC,
SourceLocation atLoc,
IdentifierInfo *Id,
ObjCTypeParamList *typeParamList,
ObjCInterfaceDecl *PrevDecl,
SourceLocation ClassLoc = SourceLocation(),
bool isInternal = false);
static ObjCInterfaceDecl *
Create(const ASTContext &C, DeclContext *DC, SourceLocation atLoc,
const IdentifierInfo *Id, ObjCTypeParamList *typeParamList,
ObjCInterfaceDecl *PrevDecl,
SourceLocation ClassLoc = SourceLocation(), bool isInternal = false);

static ObjCInterfaceDecl *CreateDeserialized(const ASTContext &C, unsigned ID);

Expand Down Expand Up @@ -1338,7 +1338,8 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
ObjCImplementationDecl *getImplementation() const;
void setImplementation(ObjCImplementationDecl *ImplD);

ObjCCategoryDecl *FindCategoryDeclaration(IdentifierInfo *CategoryId) const;
ObjCCategoryDecl *
FindCategoryDeclaration(const IdentifierInfo *CategoryId) const;

// Get the local instance/class method declared in a category.
ObjCMethodDecl *getCategoryInstanceMethod(Selector Sel) const;
Expand Down Expand Up @@ -1794,9 +1795,9 @@ class ObjCInterfaceDecl : public ObjCContainerDecl
data().CategoryList = category;
}

ObjCPropertyDecl
*FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId,
ObjCPropertyQueryKind QueryKind) const;
ObjCPropertyDecl *
FindPropertyVisibleInPrimaryClass(const IdentifierInfo *PropertyId,
ObjCPropertyQueryKind QueryKind) const;

void collectPropertiesToImplement(PropertyMap &PM) const override;

Expand Down Expand Up @@ -1954,8 +1955,8 @@ class ObjCIvarDecl : public FieldDecl {

private:
ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
SourceLocation IdLoc, const IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, AccessControl ac, Expr *BW,
bool synthesized)
: FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW,
/*Mutable=*/false, /*HasInit=*/ICIS_NoInit),
Expand All @@ -1964,10 +1965,9 @@ class ObjCIvarDecl : public FieldDecl {
public:
static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo,
AccessControl ac, Expr *BW = nullptr,
bool synthesized=false);
const IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, AccessControl ac,
Expr *BW = nullptr, bool synthesized = false);

static ObjCIvarDecl *CreateDeserialized(ASTContext &C, unsigned ID);

Expand Down Expand Up @@ -2343,7 +2343,7 @@ class ObjCCategoryDecl : public ObjCContainerDecl {

ObjCCategoryDecl(DeclContext *DC, SourceLocation AtLoc,
SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
const IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
ObjCTypeParamList *typeParamList,
SourceLocation IvarLBraceLoc = SourceLocation(),
SourceLocation IvarRBraceLoc = SourceLocation());
Expand All @@ -2354,15 +2354,13 @@ class ObjCCategoryDecl : public ObjCContainerDecl {
friend class ASTDeclReader;
friend class ASTDeclWriter;

static ObjCCategoryDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation AtLoc,
SourceLocation ClassNameLoc,
SourceLocation CategoryNameLoc,
IdentifierInfo *Id,
ObjCInterfaceDecl *IDecl,
ObjCTypeParamList *typeParamList,
SourceLocation IvarLBraceLoc=SourceLocation(),
SourceLocation IvarRBraceLoc=SourceLocation());
static ObjCCategoryDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation AtLoc,
SourceLocation ClassNameLoc, SourceLocation CategoryNameLoc,
const IdentifierInfo *Id, ObjCInterfaceDecl *IDecl,
ObjCTypeParamList *typeParamList,
SourceLocation IvarLBraceLoc = SourceLocation(),
SourceLocation IvarRBraceLoc = SourceLocation());
static ObjCCategoryDecl *CreateDeserialized(ASTContext &C, unsigned ID);

ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
Expand Down Expand Up @@ -2472,10 +2470,9 @@ class ObjCImplDecl : public ObjCContainerDecl {
void anchor() override;

protected:
ObjCImplDecl(Kind DK, DeclContext *DC,
ObjCInterfaceDecl *classInterface,
IdentifierInfo *Id,
SourceLocation nameLoc, SourceLocation atStartLoc)
ObjCImplDecl(Kind DK, DeclContext *DC, ObjCInterfaceDecl *classInterface,
const IdentifierInfo *Id, SourceLocation nameLoc,
SourceLocation atStartLoc)
: ObjCContainerDecl(DK, DC, Id, nameLoc, atStartLoc),
ClassInterface(classInterface) {}

Expand Down Expand Up @@ -2543,12 +2540,12 @@ class ObjCCategoryImplDecl : public ObjCImplDecl {
// Category name location
SourceLocation CategoryNameLoc;

ObjCCategoryImplDecl(DeclContext *DC, IdentifierInfo *Id,
ObjCCategoryImplDecl(DeclContext *DC, const IdentifierInfo *Id,
ObjCInterfaceDecl *classInterface,
SourceLocation nameLoc, SourceLocation atStartLoc,
SourceLocation CategoryNameLoc)
: ObjCImplDecl(ObjCCategoryImpl, DC, classInterface, Id,
nameLoc, atStartLoc),
: ObjCImplDecl(ObjCCategoryImpl, DC, classInterface, Id, nameLoc,
atStartLoc),
CategoryNameLoc(CategoryNameLoc) {}

void anchor() override;
Expand All @@ -2557,12 +2554,10 @@ class ObjCCategoryImplDecl : public ObjCImplDecl {
friend class ASTDeclReader;
friend class ASTDeclWriter;

static ObjCCategoryImplDecl *Create(ASTContext &C, DeclContext *DC,
IdentifierInfo *Id,
ObjCInterfaceDecl *classInterface,
SourceLocation nameLoc,
SourceLocation atStartLoc,
SourceLocation CategoryNameLoc);
static ObjCCategoryImplDecl *
Create(ASTContext &C, DeclContext *DC, const IdentifierInfo *Id,
ObjCInterfaceDecl *classInterface, SourceLocation nameLoc,
SourceLocation atStartLoc, SourceLocation CategoryNameLoc);
static ObjCCategoryImplDecl *CreateDeserialized(ASTContext &C, unsigned ID);

ObjCCategoryDecl *getCategoryDecl() const;
Expand Down
57 changes: 37 additions & 20 deletions clang/include/clang/AST/DeclTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -1389,27 +1389,27 @@ class NonTypeTemplateParmDecl final

NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, unsigned D, unsigned P,
IdentifierInfo *Id, QualType T,
const IdentifierInfo *Id, QualType T,
bool ParameterPack, TypeSourceInfo *TInfo)
: DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc),
TemplateParmPosition(D, P), ParameterPack(ParameterPack) {}

NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, unsigned D, unsigned P,
IdentifierInfo *Id, QualType T,
const IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo,
ArrayRef<QualType> ExpandedTypes,
ArrayRef<TypeSourceInfo *> ExpandedTInfos);

public:
static NonTypeTemplateParmDecl *
Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id,
SourceLocation IdLoc, unsigned D, unsigned P, const IdentifierInfo *Id,
QualType T, bool ParameterPack, TypeSourceInfo *TInfo);

static NonTypeTemplateParmDecl *
Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id,
SourceLocation IdLoc, unsigned D, unsigned P, const IdentifierInfo *Id,
QualType T, TypeSourceInfo *TInfo, ArrayRef<QualType> ExpandedTypes,
ArrayRef<TypeSourceInfo *> ExpandedTInfos);

Expand Down Expand Up @@ -1581,26 +1581,36 @@ class TemplateTemplateParmDecl final
DefaultArgStorage<TemplateTemplateParmDecl, TemplateArgumentLoc *>;
DefArgStorage DefaultArgument;

/// Whether this template template parameter was declaration with
/// the 'typename' keyword.
///
/// If false, it was declared with the 'class' keyword.
LLVM_PREFERRED_TYPE(bool)
unsigned Typename : 1;

/// Whether this parameter is a parameter pack.
bool ParameterPack;
LLVM_PREFERRED_TYPE(bool)
unsigned ParameterPack : 1;

/// Whether this template template parameter is an "expanded"
/// parameter pack, meaning that it is a pack expansion and we
/// already know the set of template parameters that expansion expands to.
bool ExpandedParameterPack = false;
LLVM_PREFERRED_TYPE(bool)
unsigned ExpandedParameterPack : 1;

/// The number of parameters in an expanded parameter pack.
unsigned NumExpandedParams = 0;

TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
unsigned D, unsigned P, bool ParameterPack,
IdentifierInfo *Id, TemplateParameterList *Params)
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
unsigned P, bool ParameterPack, IdentifierInfo *Id,
bool Typename, TemplateParameterList *Params)
: TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
TemplateParmPosition(D, P), ParameterPack(ParameterPack) {}
TemplateParmPosition(D, P), Typename(Typename),
ParameterPack(ParameterPack), ExpandedParameterPack(false) {}

TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
unsigned D, unsigned P,
IdentifierInfo *Id, TemplateParameterList *Params,
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
unsigned P, IdentifierInfo *Id, bool Typename,
TemplateParameterList *Params,
ArrayRef<TemplateParameterList *> Expansions);

void anchor() override;
Expand All @@ -1613,14 +1623,13 @@ class TemplateTemplateParmDecl final
static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D,
unsigned P, bool ParameterPack,
IdentifierInfo *Id,
IdentifierInfo *Id, bool Typename,
TemplateParameterList *Params);
static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D,
unsigned P,
IdentifierInfo *Id,
TemplateParameterList *Params,
ArrayRef<TemplateParameterList *> Expansions);
static TemplateTemplateParmDecl *
Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
unsigned P, IdentifierInfo *Id, bool Typename,
TemplateParameterList *Params,
ArrayRef<TemplateParameterList *> Expansions);

static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C,
unsigned ID);
Expand All @@ -1634,6 +1643,14 @@ class TemplateTemplateParmDecl final
using TemplateParmPosition::setPosition;
using TemplateParmPosition::getIndex;

/// Whether this template template parameter was declared with
/// the 'typename' keyword.
bool wasDeclaredWithTypename() const { return Typename; }

/// Set whether this template template parameter was declared with
/// the 'typename' or 'class' keyword.
void setDeclaredWithTypename(bool withTypename) { Typename = withTypename; }

/// Whether this template template parameter is a template
/// parameter pack.
///
Expand Down
10 changes: 5 additions & 5 deletions clang/include/clang/AST/ExprCXX.h
Original file line number Diff line number Diff line change
Expand Up @@ -2559,15 +2559,15 @@ class CXXDeleteExpr : public Expr {
class PseudoDestructorTypeStorage {
/// Either the type source information or the name of the type, if
/// it couldn't be resolved due to type-dependence.
llvm::PointerUnion<TypeSourceInfo *, IdentifierInfo *> Type;
llvm::PointerUnion<TypeSourceInfo *, const IdentifierInfo *> Type;

/// The starting source location of the pseudo-destructor type.
SourceLocation Location;

public:
PseudoDestructorTypeStorage() = default;

PseudoDestructorTypeStorage(IdentifierInfo *II, SourceLocation Loc)
PseudoDestructorTypeStorage(const IdentifierInfo *II, SourceLocation Loc)
: Type(II), Location(Loc) {}

PseudoDestructorTypeStorage(TypeSourceInfo *Info);
Expand All @@ -2576,8 +2576,8 @@ class PseudoDestructorTypeStorage {
return Type.dyn_cast<TypeSourceInfo *>();
}

IdentifierInfo *getIdentifier() const {
return Type.dyn_cast<IdentifierInfo *>();
const IdentifierInfo *getIdentifier() const {
return Type.dyn_cast<const IdentifierInfo *>();
}

SourceLocation getLocation() const { return Location; }
Expand Down Expand Up @@ -2708,7 +2708,7 @@ class CXXPseudoDestructorExpr : public Expr {
/// In a dependent pseudo-destructor expression for which we do not
/// have full type information on the destroyed type, provides the name
/// of the destroyed type.
IdentifierInfo *getDestroyedTypeIdentifier() const {
const IdentifierInfo *getDestroyedTypeIdentifier() const {
return DestroyedType.getIdentifier();
}

Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/AST/ExternalASTSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ class ExternalASTSource : public RefCountedBase<ExternalASTSource> {
virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset);

/// Update an out-of-date identifier.
virtual void updateOutOfDateIdentifier(IdentifierInfo &II) {}
virtual void updateOutOfDateIdentifier(const IdentifierInfo &II) {}

/// Find all declarations with the given name in the given context,
/// and add them to the context by calling SetExternalVisibleDeclsForName
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/AST/JSONNodeDumper.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,8 @@ class JSONNodeDumper
void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *MTE);
void VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *ME);
void VisitRequiresExpr(const RequiresExpr *RE);
void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *Node);
void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *Node);

void VisitObjCEncodeExpr(const ObjCEncodeExpr *OEE);
void VisitObjCMessageExpr(const ObjCMessageExpr *OME);
Expand Down
6 changes: 3 additions & 3 deletions clang/include/clang/AST/NestedNameSpecifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class NestedNameSpecifier : public llvm::FoldingSetNode {
/// cannot be resolved.
static NestedNameSpecifier *Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
IdentifierInfo *II);
const IdentifierInfo *II);

/// Builds a nested name specifier that names a namespace.
static NestedNameSpecifier *Create(const ASTContext &Context,
Expand All @@ -134,7 +134,7 @@ class NestedNameSpecifier : public llvm::FoldingSetNode {
/// Builds a nested name specifier that names a namespace alias.
static NestedNameSpecifier *Create(const ASTContext &Context,
NestedNameSpecifier *Prefix,
NamespaceAliasDecl *Alias);
const NamespaceAliasDecl *Alias);

/// Builds a nested name specifier that names a type.
static NestedNameSpecifier *Create(const ASTContext &Context,
Expand All @@ -148,7 +148,7 @@ class NestedNameSpecifier : public llvm::FoldingSetNode {
/// nested name specifier, e.g., in "x->Base::f", the "x" has a dependent
/// type.
static NestedNameSpecifier *Create(const ASTContext &Context,
IdentifierInfo *II);
const IdentifierInfo *II);

/// Returns the nested name specifier representing the global
/// scope.
Expand Down
81 changes: 77 additions & 4 deletions clang/include/clang/AST/OpenACCClause.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_AST_OPENACCCLAUSE_H
#define LLVM_CLANG_AST_OPENACCCLAUSE_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/StmtIterator.h"
#include "clang/Basic/OpenACCKinds.h"

namespace clang {
Expand All @@ -34,6 +35,17 @@ class OpenACCClause {

static bool classof(const OpenACCClause *) { return true; }

using child_iterator = StmtIterator;
using const_child_iterator = ConstStmtIterator;
using child_range = llvm::iterator_range<child_iterator>;
using const_child_range = llvm::iterator_range<const_child_iterator>;

child_range children();
const_child_range children() const {
auto Children = const_cast<OpenACCClause *>(this)->children();
return const_child_range(Children.begin(), Children.end());
}

virtual ~OpenACCClause() = default;
};

Expand All @@ -49,6 +61,13 @@ class OpenACCClauseWithParams : public OpenACCClause {

public:
SourceLocation getLParenLoc() const { return LParenLoc; }

child_range children() {
return child_range(child_iterator(), child_iterator());
}
const_child_range children() const {
return const_child_range(const_child_iterator(), const_child_iterator());
}
};

/// A 'default' clause, has the optional 'none' or 'present' argument.
Expand Down Expand Up @@ -81,6 +100,51 @@ class OpenACCDefaultClause : public OpenACCClauseWithParams {
SourceLocation EndLoc);
};

/// Represents one of the handful of classes that has an optional/required
/// 'condition' expression as an argument.
class OpenACCClauseWithCondition : public OpenACCClauseWithParams {
Expr *ConditionExpr = nullptr;

protected:
OpenACCClauseWithCondition(OpenACCClauseKind K, SourceLocation BeginLoc,
SourceLocation LParenLoc, Expr *ConditionExpr,
SourceLocation EndLoc)
: OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc),
ConditionExpr(ConditionExpr) {}

public:
bool hasConditionExpr() const { return ConditionExpr; }
const Expr *getConditionExpr() const { return ConditionExpr; }
Expr *getConditionExpr() { return ConditionExpr; }

child_range children() {
if (ConditionExpr)
return child_range(reinterpret_cast<Stmt **>(&ConditionExpr),
reinterpret_cast<Stmt **>(&ConditionExpr + 1));
return child_range(child_iterator(), child_iterator());
}

const_child_range children() const {
if (ConditionExpr)
return const_child_range(
reinterpret_cast<Stmt *const *>(&ConditionExpr),
reinterpret_cast<Stmt *const *>(&ConditionExpr + 1));
return const_child_range(const_child_iterator(), const_child_iterator());
}
};

/// An 'if' clause, which has a required condition expression.
class OpenACCIfClause : public OpenACCClauseWithCondition {
protected:
OpenACCIfClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
Expr *ConditionExpr, SourceLocation EndLoc);

public:
static OpenACCIfClause *Create(const ASTContext &C, SourceLocation BeginLoc,
SourceLocation LParenLoc, Expr *ConditionExpr,
SourceLocation EndLoc);
};

template <class Impl> class OpenACCClauseVisitor {
Impl &getDerived() { return static_cast<Impl &>(*this); }

Expand All @@ -98,6 +162,9 @@ template <class Impl> class OpenACCClauseVisitor {
case OpenACCClauseKind::Default:
VisitOpenACCDefaultClause(*cast<OpenACCDefaultClause>(C));
return;
case OpenACCClauseKind::If:
VisitOpenACCIfClause(*cast<OpenACCIfClause>(C));
return;
case OpenACCClauseKind::Finalize:
case OpenACCClauseKind::IfPresent:
case OpenACCClauseKind::Seq:
Expand All @@ -106,7 +173,6 @@ template <class Impl> class OpenACCClauseVisitor {
case OpenACCClauseKind::Worker:
case OpenACCClauseKind::Vector:
case OpenACCClauseKind::NoHost:
case OpenACCClauseKind::If:
case OpenACCClauseKind::Self:
case OpenACCClauseKind::Copy:
case OpenACCClauseKind::UseDevice:
Expand Down Expand Up @@ -145,9 +211,13 @@ template <class Impl> class OpenACCClauseVisitor {
llvm_unreachable("Invalid Clause kind");
}

void VisitOpenACCDefaultClause(const OpenACCDefaultClause &Clause) {
return getDerived().VisitOpenACCDefaultClause(Clause);
#define VISIT_CLAUSE(CLAUSE_NAME) \
void VisitOpenACC##CLAUSE_NAME##Clause( \
const OpenACC##CLAUSE_NAME##Clause &Clause) { \
return getDerived().VisitOpenACC##CLAUSE_NAME##Clause(Clause); \
}

#include "clang/Basic/OpenACCClauses.def"
};

class OpenACCClausePrinter final
Expand All @@ -165,7 +235,10 @@ class OpenACCClausePrinter final
}
OpenACCClausePrinter(raw_ostream &OS) : OS(OS) {}

void VisitOpenACCDefaultClause(const OpenACCDefaultClause &Clause);
#define VISIT_CLAUSE(CLAUSE_NAME) \
void VisitOpenACC##CLAUSE_NAME##Clause( \
const OpenACC##CLAUSE_NAME##Clause &Clause);
#include "clang/Basic/OpenACCClauses.def"
};

} // namespace clang
Expand Down
27 changes: 0 additions & 27 deletions clang/include/clang/Analysis/FlowSensitive/ControlFlowContext.h

This file was deleted.

64 changes: 44 additions & 20 deletions clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "llvm/ADT/MapVector.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include <memory>
#include <type_traits>
#include <utility>

Expand Down Expand Up @@ -344,17 +345,6 @@ class Environment {
/// location of the result object to pass in `this`, even though prvalues are
/// otherwise not associated with storage locations.
///
/// FIXME: Currently, this simply returns a stable storage location for `E`,
/// but this doesn't do the right thing in scenarios like the following:
/// ```
/// MyClass c = some_condition()? MyClass(foo) : MyClass(bar);
/// ```
/// Here, `MyClass(foo)` and `MyClass(bar)` will have two different storage
/// locations, when in fact their storage locations should be the same.
/// Eventually, we want to propagate storage locations from result objects
/// down to the prvalues that initialize them, similar to the way that this is
/// done in Clang's CodeGen.
///
/// Requirements:
/// `E` must be a prvalue of record type.
RecordStorageLocation &
Expand Down Expand Up @@ -462,7 +452,13 @@ class Environment {
/// Initializes the fields (including synthetic fields) of `Loc` with values,
/// unless values of the field type are not supported or we hit one of the
/// limits at which we stop producing values.
void initializeFieldsWithValues(RecordStorageLocation &Loc);
/// If `Type` is provided, initializes only those fields that are modeled for
/// `Type`; this is intended for use in cases where `Loc` is a derived type
/// and we only want to initialize the fields of a base type.
void initializeFieldsWithValues(RecordStorageLocation &Loc, QualType Type);
void initializeFieldsWithValues(RecordStorageLocation &Loc) {
initializeFieldsWithValues(Loc, Loc.getType());
}

/// Assigns `Val` as the value of `Loc` in the environment.
void setValue(const StorageLocation &Loc, Value &Val);
Expand Down Expand Up @@ -653,6 +649,9 @@ class Environment {
LLVM_DUMP_METHOD void dump(raw_ostream &OS) const;

private:
using PrValueToResultObject =
llvm::DenseMap<const Expr *, RecordStorageLocation *>;

// The copy-constructor is for use in fork() only.
Environment(const Environment &) = default;

Expand Down Expand Up @@ -682,8 +681,10 @@ class Environment {
/// Initializes the fields (including synthetic fields) of `Loc` with values,
/// unless values of the field type are not supported or we hit one of the
/// limits at which we stop producing values (controlled by `Visited`,
/// `Depth`, and `CreatedValuesCount`).
void initializeFieldsWithValues(RecordStorageLocation &Loc,
/// `Depth`, and `CreatedValuesCount`). If `Type` is different from
/// `Loc.getType()`, initializes only those fields that are modeled for
/// `Type`.
void initializeFieldsWithValues(RecordStorageLocation &Loc, QualType Type,
llvm::DenseSet<QualType> &Visited, int Depth,
int &CreatedValuesCount);

Expand All @@ -702,22 +703,45 @@ class Environment {
/// and functions referenced in `FuncDecl`. `FuncDecl` must have a body.
void initFieldsGlobalsAndFuncs(const FunctionDecl *FuncDecl);

static PrValueToResultObject
buildResultObjectMap(DataflowAnalysisContext *DACtx,
const FunctionDecl *FuncDecl,
RecordStorageLocation *ThisPointeeLoc,
RecordStorageLocation *LocForRecordReturnVal);

// `DACtx` is not null and not owned by this object.
DataflowAnalysisContext *DACtx;

// FIXME: move the fields `CallStack`, `ReturnVal`, `ReturnLoc` and
// `ThisPointeeLoc` into a separate call-context object, shared between
// environments in the same call.
// FIXME: move the fields `CallStack`, `ResultObjectMap`, `ReturnVal`,
// `ReturnLoc` and `ThisPointeeLoc` into a separate call-context object,
// shared between environments in the same call.
// https://github.com/llvm/llvm-project/issues/59005

// `DeclContext` of the block being analysed if provided.
std::vector<const DeclContext *> CallStack;

// Value returned by the function (if it has non-reference return type).
// Maps from prvalues of record type to their result objects. Shared between
// all environments for the same function.
// FIXME: It's somewhat unsatisfactory that we have to use a `shared_ptr`
// here, though the cost is acceptable: The overhead of a `shared_ptr` is
// incurred when it is copied, and this happens only relatively rarely (when
// we fork the environment). The need for a `shared_ptr` will go away once we
// introduce a shared call-context object (see above).
std::shared_ptr<PrValueToResultObject> ResultObjectMap;

// The following three member variables handle various different types of
// return values.
// - If the return type is not a reference and not a record: Value returned
// by the function.
Value *ReturnVal = nullptr;
// Storage location of the reference returned by the function (if it has
// reference return type).
// - If the return type is a reference: Storage location of the reference
// returned by the function.
StorageLocation *ReturnLoc = nullptr;
// - If the return type is a record or the function being analyzed is a
// constructor: Storage location into which the return value should be
// constructed.
RecordStorageLocation *LocForRecordReturnVal = nullptr;

// The storage location of the `this` pointee. Should only be null if the
// function being analyzed is only a function and not a method.
RecordStorageLocation *ThisPointeeLoc = nullptr;
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Analysis/SelectorExtras.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ namespace clang {

template <typename... IdentifierInfos>
static inline Selector getKeywordSelector(ASTContext &Ctx,
IdentifierInfos *... IIs) {
const IdentifierInfos *...IIs) {
static_assert(sizeof...(IdentifierInfos) > 0,
"keyword selectors must have at least one argument");
SmallVector<IdentifierInfo *, 10> II({&Ctx.Idents.get(IIs)...});
SmallVector<const IdentifierInfo *, 10> II({&Ctx.Idents.get(IIs)...});

return Ctx.Selectors.getSelector(II.size(), &II[0]);
}
Expand Down
37 changes: 25 additions & 12 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -1604,27 +1604,40 @@ specifies availability for the current target platform, the availability
attributes are ignored. Supported platforms are:

``ios``
Apple's iOS operating system. The minimum deployment target is specified by
the ``-mios-version-min=*version*`` or ``-miphoneos-version-min=*version*``
command-line arguments.
Apple's iOS operating system. The minimum deployment target is specified
as part of the ``-target *arch*-apple-ios*version*`` command line argument.
Alternatively, it can be specified by the ``-mtargetos=ios*version*``
command-line argument.

``macos``
Apple's macOS operating system. The minimum deployment target is
specified by the ``-mmacosx-version-min=*version*`` command-line argument.
``macosx`` is supported for backward-compatibility reasons, but it is
deprecated.
Apple's macOS operating system. The minimum deployment target is specified
as part of the ``-target *arch*-apple-macos*version*`` command line argument.
Alternatively, it can be specified by the ``-mtargetos=macos*version*``
command-line argument. ``macosx`` is supported for
backward-compatibility reasons, but it is deprecated.

``tvos``
Apple's tvOS operating system. The minimum deployment target is specified by
the ``-mtvos-version-min=*version*`` command-line argument.
Apple's tvOS operating system. The minimum deployment target is specified
as part of the ``-target *arch*-apple-tvos*version*`` command line argument.
Alternatively, it can be specified by the ``-mtargetos=tvos*version*``
command-line argument.

``watchos``
Apple's watchOS operating system. The minimum deployment target is specified by
the ``-mwatchos-version-min=*version*`` command-line argument.
Apple's watchOS operating system. The minimum deployment target is specified
as part of the ``-target *arch*-apple-watchos*version*`` command line argument.
Alternatively, it can be specified by the ``-mtargetos=watchos*version*``
command-line argument.

``visionos``
Apple's visionOS operating system. The minimum deployment target is specified
as part of the ``-target *arch*-apple-visionos*version*`` command line argument.
Alternatively, it can be specified by the ``-mtargetos=visionos*version*``
command-line argument.

``driverkit``
Apple's DriverKit userspace kernel extensions. The minimum deployment target
is specified as part of the triple.
is specified as part of the ``-target *arch*-apple-driverkit*version*``
command line argument.

A declaration can typically be used even when deploying back to a platform
version prior to when the declaration was introduced. When this happens, the
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/BuiltinsAMDGPU.def
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ BUILTIN(__builtin_amdgcn_s_waitcnt, "vIi", "n")
BUILTIN(__builtin_amdgcn_s_sendmsg, "vIiUi", "n")
BUILTIN(__builtin_amdgcn_s_sendmsghalt, "vIiUi", "n")
BUILTIN(__builtin_amdgcn_s_barrier, "v", "n")
BUILTIN(__builtin_amdgcn_s_ttracedata, "vi", "n")
BUILTIN(__builtin_amdgcn_wave_barrier, "v", "n")
BUILTIN(__builtin_amdgcn_sched_barrier, "vIi", "n")
BUILTIN(__builtin_amdgcn_sched_group_barrier, "vIiIiIi", "n")
Expand Down Expand Up @@ -267,6 +268,7 @@ TARGET_BUILTIN(__builtin_amdgcn_dot4_f32_bf8_bf8, "fUiUif", "nc", "dot11-insts")
TARGET_BUILTIN(__builtin_amdgcn_permlane16, "UiUiUiUiUiIbIb", "nc", "gfx10-insts")
TARGET_BUILTIN(__builtin_amdgcn_permlanex16, "UiUiUiUiUiIbIb", "nc", "gfx10-insts")
TARGET_BUILTIN(__builtin_amdgcn_mov_dpp8, "UiUiIUi", "nc", "gfx10-insts")
TARGET_BUILTIN(__builtin_amdgcn_s_ttracedata_imm, "vIs", "n", "gfx10-insts")

//===----------------------------------------------------------------------===//
// Raytracing builtins.
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/DiagnosticInstallAPIKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ def warn_no_such_excluded_header_file : Warning<"no such excluded %select{public
def warn_glob_did_not_match: Warning<"glob '%0' did not match any header file">, InGroup<InstallAPIViolation>;
def err_no_such_umbrella_header_file : Error<"%select{public|private|project}1 umbrella header file not found in input: '%0'">;
def err_cannot_find_reexport : Error<"cannot find re-exported %select{framework|library}0: '%1'">;
def err_no_matching_target : Error<"no matching target found for target variant '%0'">;
def err_unsupported_vendor : Error<"vendor '%0' is not supported: '%1'">;
def err_unsupported_environment : Error<"environment '%0' is not supported: '%1'">;
def err_unsupported_os : Error<"os '%0' is not supported: '%1'">;
} // end of command line category.

let CategoryName = "Verification" in {
Expand Down
11 changes: 5 additions & 6 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -2402,10 +2402,6 @@ def err_selected_explicit_constructor : Error<
def note_explicit_ctor_deduction_guide_here : Note<
"explicit %select{constructor|deduction guide}0 declared here">;

// C++11 decltype
def err_decltype_in_declarator : Error<
"'decltype' cannot be used to name a declaration">;

// C++11 auto
def warn_cxx98_compat_auto_type_specifier : Warning<
"'auto' type specifier is incompatible with C++98">,
Expand Down Expand Up @@ -7592,8 +7588,8 @@ def ext_gnu_ptr_func_arith : Extension<
InGroup<GNUPointerArith>;
def err_readonly_message_assignment : Error<
"assigning to 'readonly' return result of an Objective-C message not allowed">;
def ext_integer_increment_complex : Extension<
"ISO C does not support '++'/'--' on complex integer type %0">;
def ext_increment_complex : Extension<
"'%select{--|++}0' on an object of complex type is a Clang extension">;
def ext_integer_complement_complex : Extension<
"ISO C does not support '~' for complex conjugation of %0">;
def err_nosetter_property_assignment : Error<
Expand Down Expand Up @@ -8313,6 +8309,9 @@ def ext_template_after_declarative_nns : ExtWarn<
def ext_alias_template_in_declarative_nns : ExtWarn<
"a declarative nested name specifier cannot name an alias template">,
InGroup<DiagGroup<"alias-template-in-declaration-name">>;
def err_computed_type_in_declarative_nns : Error<
"a %select{pack indexing|'decltype'}0 specifier cannot be used in "
"a declarative nested name specifier">;

def err_no_typeid_with_fno_rtti : Error<
"use of typeid requires -frtti">;
Expand Down
25 changes: 13 additions & 12 deletions clang/include/clang/Basic/IdentifierTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -913,12 +913,13 @@ class alignas(IdentifierInfoAlignment) MultiKeywordSelector

public:
// Constructor for keyword selectors.
MultiKeywordSelector(unsigned nKeys, IdentifierInfo **IIV)
MultiKeywordSelector(unsigned nKeys, const IdentifierInfo **IIV)
: DeclarationNameExtra(nKeys) {
assert((nKeys > 1) && "not a multi-keyword selector");

// Fill in the trailing keyword array.
IdentifierInfo **KeyInfo = reinterpret_cast<IdentifierInfo **>(this + 1);
const IdentifierInfo **KeyInfo =
reinterpret_cast<const IdentifierInfo **>(this + 1);
for (unsigned i = 0; i != nKeys; ++i)
KeyInfo[i] = IIV[i];
}
Expand All @@ -928,7 +929,7 @@ class alignas(IdentifierInfoAlignment) MultiKeywordSelector

using DeclarationNameExtra::getNumArgs;

using keyword_iterator = IdentifierInfo *const *;
using keyword_iterator = const IdentifierInfo *const *;

keyword_iterator keyword_begin() const {
return reinterpret_cast<keyword_iterator>(this + 1);
Expand All @@ -938,7 +939,7 @@ class alignas(IdentifierInfoAlignment) MultiKeywordSelector
return keyword_begin() + getNumArgs();
}

IdentifierInfo *getIdentifierInfoForSlot(unsigned i) const {
const IdentifierInfo *getIdentifierInfoForSlot(unsigned i) const {
assert(i < getNumArgs() && "getIdentifierInfoForSlot(): illegal index");
return keyword_begin()[i];
}
Expand Down Expand Up @@ -991,10 +992,10 @@ class Selector {
/// Do not reorder or add any arguments to this template
/// without thoroughly understanding how tightly coupled these classes are.
llvm::PointerIntPair<
llvm::PointerUnion<IdentifierInfo *, MultiKeywordSelector *>, 2>
llvm::PointerUnion<const IdentifierInfo *, MultiKeywordSelector *>, 2>
InfoPtr;

Selector(IdentifierInfo *II, unsigned nArgs) {
Selector(const IdentifierInfo *II, unsigned nArgs) {
assert(nArgs < 2 && "nArgs not equal to 0/1");
InfoPtr.setPointerAndInt(II, nArgs + 1);
}
Expand All @@ -1006,8 +1007,8 @@ class Selector {
InfoPtr.setPointerAndInt(SI, MultiArg & 0b11);
}

IdentifierInfo *getAsIdentifierInfo() const {
return InfoPtr.getPointer().dyn_cast<IdentifierInfo *>();
const IdentifierInfo *getAsIdentifierInfo() const {
return InfoPtr.getPointer().dyn_cast<const IdentifierInfo *>();
}

MultiKeywordSelector *getMultiKeywordSelector() const {
Expand Down Expand Up @@ -1075,7 +1076,7 @@ class Selector {
///
/// \returns the uniqued identifier for this slot, or NULL if this slot has
/// no corresponding identifier.
IdentifierInfo *getIdentifierInfoForSlot(unsigned argIndex) const;
const IdentifierInfo *getIdentifierInfoForSlot(unsigned argIndex) const;

/// Retrieve the name at a given position in the selector.
///
Expand Down Expand Up @@ -1132,13 +1133,13 @@ class SelectorTable {
///
/// \p NumArgs indicates whether this is a no argument selector "foo", a
/// single argument selector "foo:" or multi-argument "foo:bar:".
Selector getSelector(unsigned NumArgs, IdentifierInfo **IIV);
Selector getSelector(unsigned NumArgs, const IdentifierInfo **IIV);

Selector getUnarySelector(IdentifierInfo *ID) {
Selector getUnarySelector(const IdentifierInfo *ID) {
return Selector(ID, 1);
}

Selector getNullarySelector(IdentifierInfo *ID) {
Selector getNullarySelector(const IdentifierInfo *ID) {
return Selector(ID, 0);
}

Expand Down
21 changes: 21 additions & 0 deletions clang/include/clang/Basic/OpenACCClauses.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- OpenACCClauses.def - List of implemented OpenACC Clauses -- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines a list of currently implemented OpenACC Clauses (and
// eventually, the entire list) in a way that makes generating 'visitor' and
// other lists easier.
//
// The primary macro is a single-argument version taking the name of the Clause
// as used in Clang source (so `Default` instead of `default`).
//
// VISIT_CLAUSE(CLAUSE_NAME)

VISIT_CLAUSE(Default)
VISIT_CLAUSE(If)

#undef VISIT_CLAUSE
Empty file.
3 changes: 3 additions & 0 deletions clang/include/clang/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
add_subdirectory(AST)
add_subdirectory(Basic)
if(CLANG_ENABLE_CIR)
add_subdirectory(CIR)
endif()
add_subdirectory(Driver)
add_subdirectory(Parse)
add_subdirectory(Sema)
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Config/config.h.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,7 @@
/* Spawn a new process clang.exe for the CC1 tool invocation, when necessary */
#cmakedefine01 CLANG_SPAWN_CC1

/* Whether CIR is built into Clang */
#cmakedefine01 CLANG_ENABLE_CIR

#endif
9 changes: 6 additions & 3 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1341,7 +1341,8 @@ def hip_link : Flag<["--"], "hip-link">, Group<opencl_Group>,
HelpText<"Link clang-offload-bundler bundles for HIP">;
def no_hip_rt: Flag<["-"], "no-hip-rt">, Group<hip_Group>,
HelpText<"Do not link against HIP runtime libraries">;
def rocm_path_EQ : Joined<["--"], "rocm-path=">, Group<hip_Group>,
def rocm_path_EQ : Joined<["--"], "rocm-path=">,
Visibility<[FlangOption]>, Group<hip_Group>,
HelpText<"ROCm installation path, used for finding and automatically linking required bitcode libraries.">;
def hip_path_EQ : Joined<["--"], "hip-path=">, Group<hip_Group>,
HelpText<"HIP runtime installation path, used for finding HIP version and adding HIP include path.">;
Expand Down Expand Up @@ -5464,21 +5465,23 @@ def rdynamic : Flag<["-"], "rdynamic">, Group<Link_Group>,
Visibility<[ClangOption, FlangOption]>;
def resource_dir : Separate<["-"], "resource-dir">,
Flags<[NoXarchOption, HelpHidden]>,
Visibility<[ClangOption, CC1Option, CLOption, DXCOption]>,
Visibility<[ClangOption, CC1Option, CLOption, DXCOption, FlangOption, FC1Option]>,
HelpText<"The directory which holds the compiler resource files">,
MarshallingInfoString<HeaderSearchOpts<"ResourceDir">>;
def resource_dir_EQ : Joined<["-"], "resource-dir=">, Flags<[NoXarchOption]>,
Visibility<[ClangOption, CLOption, DXCOption]>,
Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>,
Alias<resource_dir>;
def rpath : Separate<["-"], "rpath">, Flags<[LinkerInput]>, Group<Link_Group>,
Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>;
def rtlib_EQ : Joined<["-", "--"], "rtlib=">, Visibility<[ClangOption, CLOption]>,
HelpText<"Compiler runtime library to use">;
def frtlib_add_rpath: Flag<["-"], "frtlib-add-rpath">, Flags<[NoArgumentUnused]>,
Visibility<[ClangOption, FlangOption]>,
HelpText<"Add -rpath with architecture-specific resource directory to the linker flags. "
"When --hip-link is specified, also add -rpath with HIP runtime library directory to the linker flags">;
def fno_rtlib_add_rpath: Flag<["-"], "fno-rtlib-add-rpath">,
Flags<[NoArgumentUnused]>,
Visibility<[ClangOption, FlangOption]>,
HelpText<"Do not add -rpath with architecture-specific resource directory to the linker flags. "
"When --hip-link is specified, do not add -rpath with HIP runtime library directory to the linker flags">;
def offload_add_rpath: Flag<["--"], "offload-add-rpath">,
Expand Down
32 changes: 29 additions & 3 deletions clang/include/clang/InstallAPI/DylibVerifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ enum class VerificationMode {
using LibAttrs = llvm::StringMap<ArchitectureSet>;
using ReexportedInterfaces = llvm::SmallVector<llvm::MachO::InterfaceFile, 8>;

// Pointers to information about a zippered declaration used for
// querying and reporting violations against different
// declarations that all map to the same symbol.
struct ZipperedDeclSource {
const FrontendAttrs *FA;
clang::SourceManager *SrcMgr;
Target T;
};
using ZipperedDeclSources = std::vector<ZipperedDeclSource>;

/// Service responsible to tracking state of verification across the
/// lifetime of InstallAPI.
/// As declarations are collected during AST traversal, they are
Expand Down Expand Up @@ -68,10 +78,10 @@ class DylibVerifier : llvm::MachO::RecordVisitor {
DylibVerifier() = default;

DylibVerifier(llvm::MachO::Records &&Dylib, ReexportedInterfaces &&Reexports,
DiagnosticsEngine *Diag, VerificationMode Mode, bool Demangle,
StringRef DSYMPath)
DiagnosticsEngine *Diag, VerificationMode Mode, bool Zippered,
bool Demangle, StringRef DSYMPath)
: Dylib(std::move(Dylib)), Reexports(std::move(Reexports)), Mode(Mode),
Demangle(Demangle), DSYMPath(DSYMPath),
Zippered(Zippered), Demangle(Demangle), DSYMPath(DSYMPath),
Exports(std::make_unique<SymbolSet>()), Ctx(VerifierContext{Diag}) {}

Result verify(GlobalRecord *R, const FrontendAttrs *FA);
Expand Down Expand Up @@ -118,6 +128,15 @@ class DylibVerifier : llvm::MachO::RecordVisitor {
/// symbols should be omitted from the text-api file.
bool shouldIgnoreReexport(const Record *R, SymbolContext &SymCtx) const;

// Ignore and omit unavailable symbols in zippered libraries.
bool shouldIgnoreZipperedAvailability(const Record *R, SymbolContext &SymCtx);

// Check if an internal declaration in zippered library has an
// external declaration for a different platform. This results
// in the symbol being in a "seperate" platform slice.
bool shouldIgnoreInternalZipperedSymbol(const Record *R,
const SymbolContext &SymCtx) const;

/// Compare the visibility declarations to the linkage of symbol found in
/// dylib.
Result compareVisibility(const Record *R, SymbolContext &SymCtx,
Expand Down Expand Up @@ -173,6 +192,9 @@ class DylibVerifier : llvm::MachO::RecordVisitor {
// Controls what class of violations to report.
VerificationMode Mode = VerificationMode::Invalid;

// Library is zippered.
bool Zippered = false;

// Attempt to demangle when reporting violations.
bool Demangle = false;

Expand All @@ -182,6 +204,10 @@ class DylibVerifier : llvm::MachO::RecordVisitor {
// Valid symbols in final text file.
std::unique_ptr<SymbolSet> Exports = std::make_unique<SymbolSet>();

// Unavailable or obsoleted declarations for a zippered library.
// These are cross referenced against symbols in the dylib.
llvm::StringMap<ZipperedDeclSources> DeferredZipperedSymbols;

// Track current state of verification while traversing AST.
VerifierContext Ctx;

Expand Down
Loading