.ci/generate-buildkite-pipeline-premerge
@@ -91,7 +91,7 @@ function add-dependencies() {
echo "${project}" echo "${project}"
case ${project} in case ${project} in
bolt) bolt)
- for p in lld llvm; do+ for p in clang lld llvm; do
echo $p echo $p
done done
;; ;;
.ci/monolithic-linux.sh
@@ -48,7 +48,6 @@ cmake -S "${MONOREPO_ROOT}"/llvm -B "${BUILD_DIR}" \
-D LLVM_LIT_ARGS="-v --xunit-xml-output ${BUILD_DIR}/test-results.xml --timeout=1200 --time-tests" \ -D LLVM_LIT_ARGS="-v --xunit-xml-output ${BUILD_DIR}/test-results.xml --timeout=1200 --time-tests" \
-D LLVM_ENABLE_LLD=ON \ -D LLVM_ENABLE_LLD=ON \
-D CMAKE_CXX_FLAGS=-gmlt \ -D CMAKE_CXX_FLAGS=-gmlt \
- -D BOLT_CLANG_EXE=/usr/bin/clang \
-D LLVM_CCACHE_BUILD=ON \ -D LLVM_CCACHE_BUILD=ON \
-D MLIR_ENABLE_BINDINGS_PYTHON=ON -D MLIR_ENABLE_BINDINGS_PYTHON=ON
.github/CODEOWNERS
@@ -35,6 +35,10 @@
clang/lib/AST/Interp/ @tbaederr clang/lib/AST/Interp/ @tbaederr
clang/test/AST/Interp/ @tbaederr clang/test/AST/Interp/ @tbaederr
+/clang/include/clang/CIR @lanza @bcardosolopes
+/clang/lib/CIR @lanza @bcardosolopes
+/clang/tools/cir-* @lanza @bcardosolopes
+
/lldb/ @JDevlieghere /lldb/ @JDevlieghere
# MLIR Interfaces. # MLIR Interfaces.
.github/new-prs-labeler.yml
@@ -1,3 +1,6 @@
+BOLT:
+ - bolt/**/*
+
ClangIR: ClangIR:
- clang/include/clang/CIR/**/* - clang/include/clang/CIR/**/*
- clang/lib/CIR/**/* - clang/lib/CIR/**/*
@@ -467,6 +470,7 @@ backend:m68k:
libc++: libc++:
- libcxx/** - libcxx/**
+ - .github/workflows/libcxx-*
libc++abi: libc++abi:
- libcxxabi/** - libcxxabi/**
bolt/include/bolt/Passes/BinaryPasses.h
@@ -400,8 +400,7 @@ public:
/// dyno stats categories. /// dyno stats categories.
class PrintProgramStats : public BinaryFunctionPass { class PrintProgramStats : public BinaryFunctionPass {
public: public:
- explicit PrintProgramStats(const cl::opt<bool> &PrintPass)+ explicit PrintProgramStats() : BinaryFunctionPass(false) {}
- : BinaryFunctionPass(PrintPass) {}
const char *getName() const override { return "print-stats"; } const char *getName() const override { return "print-stats"; }
bool shouldPrint(const BinaryFunction &) const override { return false; } bool shouldPrint(const BinaryFunction &) const override { return false; }
bolt/include/bolt/Profile/DataAggregator.h
@@ -198,14 +198,8 @@ private:
/// A trace is region of code executed between two LBR entries supplied in /// A trace is region of code executed between two LBR entries supplied in
/// execution order. /// execution order.
/// ///
- /// Return true if the trace is valid, false otherwise.
- bool
- recordTrace(BinaryFunction &BF, const LBREntry &First, const LBREntry &Second,
- uint64_t Count,
- SmallVector<std::pair<uint64_t, uint64_t>, 16> &Branches) const;
-
/// Return a vector of offsets corresponding to a trace in a function /// Return a vector of offsets corresponding to a trace in a function
- /// (see recordTrace() above).+ /// if the trace is valid, std::nullopt otherwise.
std::optional<SmallVector<std::pair<uint64_t, uint64_t>, 16>> std::optional<SmallVector<std::pair<uint64_t, uint64_t>, 16>>
getFallthroughsInTrace(BinaryFunction &BF, const LBREntry &First, getFallthroughsInTrace(BinaryFunction &BF, const LBREntry &First,
const LBREntry &Second, uint64_t Count = 1) const; const LBREntry &Second, uint64_t Count = 1) const;
bolt/include/bolt/Rewrite/RewriteInstance.h
@@ -422,10 +422,18 @@ private:
/// Section name used for extra BOLT code in addition to .text. /// Section name used for extra BOLT code in addition to .text.
static StringRef getBOLTTextSectionName() { return ".bolt.text"; } static StringRef getBOLTTextSectionName() { return ".bolt.text"; }
+ /// Symbol markers for BOLT reserved area.
+ static StringRef getBOLTReservedStart() { return "__bolt_reserved_start"; }
+ static StringRef getBOLTReservedEnd() { return "__bolt_reserved_end"; }
+
/// Common section names. /// Common section names.
static StringRef getEHFrameSectionName() { return ".eh_frame"; } static StringRef getEHFrameSectionName() { return ".eh_frame"; }
+ static StringRef getEHFrameHdrSectionName() { return ".eh_frame_hdr"; }
static StringRef getRelaDynSectionName() { return ".rela.dyn"; } static StringRef getRelaDynSectionName() { return ".rela.dyn"; }
+ /// FILE symbol name used for local fragments of global functions.
+ static StringRef getBOLTFileSymbolName() { return "bolt-pseudo.o"; }
+
/// An instance of the input binary we are processing, externally owned. /// An instance of the input binary we are processing, externally owned.
llvm::object::ELFObjectFileBase *InputFile; llvm::object::ELFObjectFileBase *InputFile;
@@ -490,6 +498,9 @@ private:
/// Store all non-zero symbols in this map for a quick address lookup. /// Store all non-zero symbols in this map for a quick address lookup.
std::map<uint64_t, llvm::object::SymbolRef> FileSymRefs; std::map<uint64_t, llvm::object::SymbolRef> FileSymRefs;
+ /// FILE symbols used for disambiguating split function parents.
+ std::vector<ELFSymbolRef> FileSymbols;
+
std::unique_ptr<DWARFRewriter> DebugInfoRewriter; std::unique_ptr<DWARFRewriter> DebugInfoRewriter;
std::unique_ptr<BoltAddressTranslation> BAT; std::unique_ptr<BoltAddressTranslation> BAT;
bolt/include/bolt/Utils/NameResolver.h
@@ -28,10 +28,23 @@ class NameResolver {
static constexpr char Sep = '/'; static constexpr char Sep = '/';
public: public:
- /// Return unique version of the \p Name in the form "Name<Sep><Number>".+ /// Return the number of uniquified versions of a given \p Name.
+ uint64_t getUniquifiedNameCount(StringRef Name) const {
+ if (Counters.contains(Name))
+ return Counters.at(Name);
+ return 0;
+ }
+
+ /// Return unique version of the \p Name in the form "Name<Sep><ID>".
+ std::string getUniqueName(StringRef Name, const uint64_t ID) const {
+ return (Name + Twine(Sep) + Twine(ID)).str();
+ }
+
+ /// Register new version of \p Name and return unique version in the form
+ /// "Name<Sep><Number>".
std::string uniquify(StringRef Name) { std::string uniquify(StringRef Name) {
const uint64_t ID = ++Counters[Name]; const uint64_t ID = ++Counters[Name];
- return (Name + Twine(Sep) + Twine(ID)).str();+ return getUniqueName(Name, ID);
} }
/// For uniquified \p Name, return the original form (that may no longer be /// For uniquified \p Name, return the original form (that may no longer be
bolt/lib/Profile/DataAggregator.cpp
@@ -14,6 +14,7 @@
#include "bolt/Profile/DataAggregator.h" #include "bolt/Profile/DataAggregator.h"
#include "bolt/Core/BinaryContext.h" #include "bolt/Core/BinaryContext.h"
#include "bolt/Core/BinaryFunction.h" #include "bolt/Core/BinaryFunction.h"
+#include "bolt/Passes/BinaryPasses.h"
#include "bolt/Profile/BoltAddressTranslation.h" #include "bolt/Profile/BoltAddressTranslation.h"
#include "bolt/Profile/Heatmap.h" #include "bolt/Profile/Heatmap.h"
#include "bolt/Profile/YAMLProfileWriter.h" #include "bolt/Profile/YAMLProfileWriter.h"
@@ -611,6 +612,7 @@ Error DataAggregator::readProfile(BinaryContext &BC) {
if (std::error_code EC = writeBATYAML(BC, opts::SaveProfile)) if (std::error_code EC = writeBATYAML(BC, opts::SaveProfile))
report_error("cannot create output data file", EC); report_error("cannot create output data file", EC);
} }
+ BC.logBOLTErrorsAndQuitOnFatal(PrintProgramStats().runOnFunctions(BC));
} }
return Error::success(); return Error::success();
@@ -859,14 +861,17 @@ bool DataAggregator::doTrace(const LBREntry &First, const LBREntry &Second,
return true; return true;
} }
-bool DataAggregator::recordTrace(+std::optional<SmallVector<std::pair<uint64_t, uint64_t>, 16>>
- BinaryFunction &BF, const LBREntry &FirstLBR, const LBREntry &SecondLBR,+DataAggregator::getFallthroughsInTrace(BinaryFunction &BF,
- uint64_t Count,+ const LBREntry &FirstLBR,
- SmallVector<std::pair<uint64_t, uint64_t>, 16> &Branches) const {+ const LBREntry &SecondLBR,
+ uint64_t Count) const {
+ SmallVector<std::pair<uint64_t, uint64_t>, 16> Branches;
+
BinaryContext &BC = BF.getBinaryContext(); BinaryContext &BC = BF.getBinaryContext();
if (!BF.isSimple()) if (!BF.isSimple())
- return false;+ return std::nullopt;
assert(BF.hasCFG() && "can only record traces in CFG state"); assert(BF.hasCFG() && "can only record traces in CFG state");
@@ -875,13 +880,13 @@ bool DataAggregator::recordTrace(
const uint64_t To = SecondLBR.From - BF.getAddress(); const uint64_t To = SecondLBR.From - BF.getAddress();
if (From > To) if (From > To)
- return false;+ return std::nullopt;
const BinaryBasicBlock *FromBB = BF.getBasicBlockContainingOffset(From); const BinaryBasicBlock *FromBB = BF.getBasicBlockContainingOffset(From);
const BinaryBasicBlock *ToBB = BF.getBasicBlockContainingOffset(To); const BinaryBasicBlock *ToBB = BF.getBasicBlockContainingOffset(To);
if (!FromBB || !ToBB) if (!FromBB || !ToBB)
- return false;+ return std::nullopt;
// Adjust FromBB if the first LBR is a return from the last instruction in // Adjust FromBB if the first LBR is a return from the last instruction in
// the previous block (that instruction should be a call). // the previous block (that instruction should be a call).
@@ -905,7 +910,7 @@ bool DataAggregator::recordTrace(
// within the same basic block, e.g. when two call instructions are in the // within the same basic block, e.g. when two call instructions are in the
// same block. In this case we skip the processing. // same block. In this case we skip the processing.
if (FromBB == ToBB) if (FromBB == ToBB)
- return true;+ return Branches;
// Process blocks in the original layout order. // Process blocks in the original layout order.
BinaryBasicBlock *BB = BF.getLayout().getBlock(FromBB->getIndex()); BinaryBasicBlock *BB = BF.getLayout().getBlock(FromBB->getIndex());
@@ -919,7 +924,7 @@ bool DataAggregator::recordTrace(
LLVM_DEBUG(dbgs() << "no fall-through for the trace:\n" LLVM_DEBUG(dbgs() << "no fall-through for the trace:\n"
<< " " << FirstLBR << '\n' << " " << FirstLBR << '\n'
<< " " << SecondLBR << '\n'); << " " << SecondLBR << '\n');
- return false;+ return std::nullopt;
} }
const MCInst *Instr = BB->getLastNonPseudoInstr(); const MCInst *Instr = BB->getLastNonPseudoInstr();
@@ -943,20 +948,7 @@ bool DataAggregator::recordTrace(
BI.Count += Count; BI.Count += Count;
} }
- return true;+ return Branches;
-}
-
-std::optional<SmallVector<std::pair<uint64_t, uint64_t>, 16>>
-DataAggregator::getFallthroughsInTrace(BinaryFunction &BF,
- const LBREntry &FirstLBR,
- const LBREntry &SecondLBR,
- uint64_t Count) const {
- SmallVector<std::pair<uint64_t, uint64_t>, 16> Res;
-
- if (!recordTrace(BF, FirstLBR, SecondLBR, Count, Res))
- return std::nullopt;
-
- return Res;
} }
bool DataAggregator::recordEntry(BinaryFunction &BF, uint64_t To, bool Mispred, bool DataAggregator::recordEntry(BinaryFunction &BF, uint64_t To, bool Mispred,
bolt/lib/Rewrite/BinaryPassManager.cpp
@@ -356,7 +356,7 @@ Error BinaryFunctionPassManager::runAllPasses(BinaryContext &BC) {
// order they're registered. // order they're registered.
// Run this pass first to use stats for the original functions. // Run this pass first to use stats for the original functions.
- Manager.registerPass(std::make_unique<PrintProgramStats>(NeverPrint));+ Manager.registerPass(std::make_unique<PrintProgramStats>());
if (opts::PrintProfileStats) if (opts::PrintProfileStats)
Manager.registerPass(std::make_unique<PrintProfileStats>(NeverPrint)); Manager.registerPass(std::make_unique<PrintProfileStats>(NeverPrint));
bolt/lib/Rewrite/BoltDiff.cpp
@@ -292,7 +292,7 @@ class RewriteInstanceDiff {
} }
} }
} }
- PrintProgramStats PPS(opts::NeverPrint);+ PrintProgramStats PPS;
outs() << "* BOLT-DIFF: Starting print program stats pass for binary 1\n"; outs() << "* BOLT-DIFF: Starting print program stats pass for binary 1\n";
RI1.BC->logBOLTErrorsAndQuitOnFatal(PPS.runOnFunctions(*RI1.BC)); RI1.BC->logBOLTErrorsAndQuitOnFatal(PPS.runOnFunctions(*RI1.BC));
outs() << "* BOLT-DIFF: Starting print program stats pass for binary 2\n"; outs() << "* BOLT-DIFF: Starting print program stats pass for binary 2\n";
bolt/lib/Rewrite/LinuxKernelRewriter.cpp
@@ -248,6 +248,9 @@ class LinuxKernelRewriter final : public MetadataRewriter {
/// Update ORC data in the binary. /// Update ORC data in the binary.
Error rewriteORCTables(); Error rewriteORCTables();
+ /// Validate written ORC tables after binary emission.
+ Error validateORCTables();
+
/// Static call table handling. /// Static call table handling.
Error readStaticCalls(); Error readStaticCalls();
Error rewriteStaticCalls(); Error rewriteStaticCalls();
@@ -358,6 +361,9 @@ public:
if (Error E = updateStaticKeysJumpTablePostEmit()) if (Error E = updateStaticKeysJumpTablePostEmit())
return E; return E;
+ if (Error E = validateORCTables())
+ return E;
+
return Error::success(); return Error::success();
} }
}; };
@@ -837,6 +843,32 @@ Error LinuxKernelRewriter::rewriteORCTables() {
return Error::success(); return Error::success();
} }
+Error LinuxKernelRewriter::validateORCTables() {
+ if (!ORCUnwindIPSection)
+ return Error::success();
+
+ const uint64_t IPSectionAddress = ORCUnwindIPSection->getAddress();
+ DataExtractor IPDE = DataExtractor(ORCUnwindIPSection->getOutputContents(),
+ BC.AsmInfo->isLittleEndian(),
+ BC.AsmInfo->getCodePointerSize());
+ DataExtractor::Cursor IPCursor(0);
+ uint64_t PrevIP = 0;
+ for (uint32_t Index = 0; Index < NumORCEntries; ++Index) {
+ const uint64_t IP =
+ IPSectionAddress + IPCursor.tell() + (int32_t)IPDE.getU32(IPCursor);
+ if (!IPCursor)
+ return createStringError(errc::executable_format_error,
+ "out of bounds while reading ORC IP table: %s",
+ toString(IPCursor.takeError()).c_str());
+
+ assert(IP >= PrevIP && "Unsorted ORC table detected");
+ (void)PrevIP;
+ PrevIP = IP;
+ }
+
+ return Error::success();
+}
+
/// The static call site table is created by objtool and contains entries in the /// The static call site table is created by objtool and contains entries in the
/// following format: /// following format:
/// ///
bolt/lib/Rewrite/RewriteInstance.cpp
@@ -840,6 +840,7 @@ void RewriteInstance::discoverFileObjects() {
continue; continue;
if (cantFail(Symbol.getType()) == SymbolRef::ST_File) { if (cantFail(Symbol.getType()) == SymbolRef::ST_File) {
+ FileSymbols.emplace_back(Symbol);
StringRef Name = StringRef Name =
cantFail(std::move(NameOrError), "cannot get symbol name for file"); cantFail(std::move(NameOrError), "cannot get symbol name for file");
// Ignore Clang LTO artificial FILE symbol as it is not always generated, // Ignore Clang LTO artificial FILE symbol as it is not always generated,
@@ -1062,6 +1063,11 @@ void RewriteInstance::discoverFileObjects() {
continue; continue;
} }
+ if (SymName == getBOLTReservedStart() || SymName == getBOLTReservedEnd()) {
+ registerName(SymbolSize);
+ continue;
+ }
+
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: considering symbol " << UniqueName LLVM_DEBUG(dbgs() << "BOLT-DEBUG: considering symbol " << UniqueName
<< " for function\n"); << " for function\n");
@@ -1340,6 +1346,7 @@ void RewriteInstance::discoverFileObjects() {
} }
registerFragments(); registerFragments();
+ FileSymbols.clear();
} }
Error RewriteInstance::discoverRtFiniAddress() { Error RewriteInstance::discoverRtFiniAddress() {
@@ -1417,50 +1424,134 @@ void RewriteInstance::registerFragments() {
if (!BC->HasSplitFunctions) if (!BC->HasSplitFunctions)
return; return;
+ // Process fragments with ambiguous parents separately as they are typically a
+ // vanishing minority of cases and require expensive symbol table lookups.
+ std::vector<std::pair<StringRef, BinaryFunction *>> AmbiguousFragments;
for (auto &BFI : BC->getBinaryFunctions()) { for (auto &BFI : BC->getBinaryFunctions()) {
BinaryFunction &Function = BFI.second; BinaryFunction &Function = BFI.second;
if (!Function.isFragment()) if (!Function.isFragment())
continue; continue;
- unsigned ParentsFound = 0;
for (StringRef Name : Function.getNames()) { for (StringRef Name : Function.getNames()) {
- StringRef BaseName, Suffix;+ StringRef BaseName = NR.restore(Name);
- std::tie(BaseName, Suffix) = Name.split('/');+ const bool IsGlobal = BaseName == Name;
const size_t ColdSuffixPos = BaseName.find(".cold"); const size_t ColdSuffixPos = BaseName.find(".cold");
if (ColdSuffixPos == StringRef::npos) if (ColdSuffixPos == StringRef::npos)
continue; continue;
- // For cold function with local (foo.cold/1) symbol, prefer a parent with+ StringRef ParentName = BaseName.substr(0, ColdSuffixPos);
- // local symbol as well (foo/1) over global symbol (foo).
- std::string ParentName = BaseName.substr(0, ColdSuffixPos).str();
const BinaryData *BD = BC->getBinaryDataByName(ParentName); const BinaryData *BD = BC->getBinaryDataByName(ParentName);
- if (Suffix != "") {+ const uint64_t NumPossibleLocalParents =
- ParentName.append(Twine("/", Suffix).str());+ NR.getUniquifiedNameCount(ParentName);
- const BinaryData *BDLocal = BC->getBinaryDataByName(ParentName);+ // The most common case: single local parent fragment.
- if (BDLocal || !BD)+ if (!BD && NumPossibleLocalParents == 1) {
- BD = BDLocal;+ BD = BC->getBinaryDataByName(NR.getUniqueName(ParentName, 1));
- }+ } else if (BD && (!NumPossibleLocalParents || IsGlobal)) {
- if (!BD) {+ // Global parent and either no local candidates (second most common), or
- if (opts::Verbosity >= 1)+ // the fragment is global as well (uncommon).
- BC->outs() << "BOLT-INFO: parent function not found for " << Name+ } else {
- << "\n";+ // Any other case: need to disambiguate using FILE symbols.
+ AmbiguousFragments.emplace_back(ParentName, &Function);
continue; continue;
} }
- const uint64_t Address = BD->getAddress();+ if (BD) {
- BinaryFunction *BF = BC->getBinaryFunctionAtAddress(Address);+ BinaryFunction *BF = BC->getFunctionForSymbol(BD->getSymbol());
- if (!BF) {+ if (BF) {
- if (opts::Verbosity >= 1)+ BC->registerFragment(Function, *BF);
- BC->outs() << formatv(+ continue;
- "BOLT-INFO: parent function not found at {0:x}\n", Address);+ }
- continue;
} }
- BC->registerFragment(Function, *BF);
- ++ParentsFound;
- }
- if (!ParentsFound) {
BC->errs() << "BOLT-ERROR: parent function not found for " << Function BC->errs() << "BOLT-ERROR: parent function not found for " << Function
<< '\n'; << '\n';
exit(1); exit(1);
} }
} }
+
+ if (AmbiguousFragments.empty())
+ return;
+
+ if (!BC->hasSymbolsWithFileName()) {
+ BC->errs() << "BOLT-ERROR: input file has split functions but does not "
+ "have FILE symbols. If the binary was stripped, preserve "
+ "FILE symbols with --keep-file-symbols strip option";
+ exit(1);
+ }
+
+ // The first global symbol is identified by the symbol table sh_info value.
+ // Used as local symbol search stopping point.
+ auto *ELF64LEFile = cast<ELF64LEObjectFile>(InputFile);
+ const ELFFile<ELF64LE> &Obj = ELF64LEFile->getELFFile();
+ auto *SymTab = llvm::find_if(cantFail(Obj.sections()), [](const auto &Sec) {
+ return Sec.sh_type == ELF::SHT_SYMTAB;
+ });
+ assert(SymTab);
+ // Symtab sh_info contains the value one greater than the symbol table index
+ // of the last local symbol.
+ ELFSymbolRef LocalSymEnd = ELF64LEFile->toSymbolRef(SymTab, SymTab->sh_info);
+
+ for (auto &[ParentName, BF] : AmbiguousFragments) {
+ const uint64_t Address = BF->getAddress();
+
+ // Get fragment's own symbol
+ const auto SymIt = FileSymRefs.find(Address);
+ if (SymIt == FileSymRefs.end()) {
+ BC->errs()
+ << "BOLT-ERROR: symbol lookup failed for function at address 0x"
+ << Twine::utohexstr(Address) << '\n';
+ exit(1);
+ }
+
+ // Find containing FILE symbol
+ ELFSymbolRef Symbol = SymIt->second;
+ auto FSI = llvm::upper_bound(FileSymbols, Symbol);
+ if (FSI == FileSymbols.begin()) {
+ BC->errs() << "BOLT-ERROR: owning FILE symbol not found for symbol "
+ << cantFail(Symbol.getName()) << '\n';
+ exit(1);
+ }
+
+ ELFSymbolRef StopSymbol = LocalSymEnd;
+ if (FSI != FileSymbols.end())
+ StopSymbol = *FSI;
+
+ uint64_t ParentAddress{0};
+
+ // BOLT split fragment symbols are emitted just before the main function
+ // symbol.
+ for (ELFSymbolRef NextSymbol = Symbol; NextSymbol < StopSymbol;
+ NextSymbol.moveNext()) {
+ StringRef Name = cantFail(NextSymbol.getName());
+ if (Name == ParentName) {
+ ParentAddress = cantFail(NextSymbol.getValue());
+ goto registerParent;
+ }
+ if (Name.starts_with(ParentName))
+ // With multi-way splitting, there are multiple fragments with different
+ // suffixes. Parent follows the last fragment.
+ continue;
+ break;
+ }
+
+ // Iterate over local file symbols and check symbol names to match parent.
+ for (ELFSymbolRef Symbol(FSI[-1]); Symbol < StopSymbol; Symbol.moveNext()) {
+ if (cantFail(Symbol.getName()) == ParentName) {
+ ParentAddress = cantFail(Symbol.getAddress());
+ break;
+ }
+ }
+
+registerParent:
+ // No local parent is found, use global parent function.
+ if (!ParentAddress)
+ if (BinaryData *ParentBD = BC->getBinaryDataByName(ParentName))
+ ParentAddress = ParentBD->getAddress();
+
+ if (BinaryFunction *ParentBF =
+ BC->getBinaryFunctionAtAddress(ParentAddress)) {
+ BC->registerFragment(*BF, *ParentBF);
+ continue;
+ }
+ BC->errs() << "BOLT-ERROR: parent function not found for " << *BF << '\n';
+ exit(1);
+ }
} }
void RewriteInstance::createPLTBinaryFunction(uint64_t TargetAddress, void RewriteInstance::createPLTBinaryFunction(uint64_t TargetAddress,
@@ -1725,12 +1816,6 @@ void RewriteInstance::adjustFunctionBoundaries() {
if (!Function.isSymbolValidInScope(Symbol, SymbolSize)) if (!Function.isSymbolValidInScope(Symbol, SymbolSize))
break; break;
- // Ignore unnamed symbols. Used, for example, by debugging info on RISC-V.
- if (BC->isRISCV() && cantFail(Symbol.getName()).empty()) {
- ++NextSymRefI;
- continue;
- }
-
// Skip basic block labels. This happens on RISC-V with linker relaxation // Skip basic block labels. This happens on RISC-V with linker relaxation
// enabled because every branch needs a relocation and corresponding // enabled because every branch needs a relocation and corresponding
// symbol. We don't want to add such symbols as entry points. // symbol. We don't want to add such symbols as entry points.
@@ -3532,6 +3617,26 @@ void RewriteInstance::updateMetadata() {
void RewriteInstance::mapFileSections(BOLTLinker::SectionMapper MapSection) { void RewriteInstance::mapFileSections(BOLTLinker::SectionMapper MapSection) {
BC->deregisterUnusedSections(); BC->deregisterUnusedSections();
+ // Check if the input has a space reserved for BOLT.
+ BinaryData *StartBD = BC->getBinaryDataByName(getBOLTReservedStart());
+ BinaryData *EndBD = BC->getBinaryDataByName(getBOLTReservedEnd());
+ if (!StartBD != !EndBD) {
+ BC->errs() << "BOLT-ERROR: one of the symbols is missing from the binary: "
+ << getBOLTReservedStart() << ", " << getBOLTReservedEnd()
+ << '\n';
+ exit(1);
+ }
+
+ if (StartBD) {
+ PHDRTableOffset = 0;
+ PHDRTableAddress = 0;
+ NewTextSegmentAddress = 0;
+ NewTextSegmentOffset = 0;
+ NextAvailableAddress = StartBD->getAddress();
+ BC->outs()
+ << "BOLT-INFO: using reserved space for allocating new sections\n";
+ }
+
// If no new .eh_frame was written, remove relocated original .eh_frame. // If no new .eh_frame was written, remove relocated original .eh_frame.
BinarySection *RelocatedEHFrameSection = BinarySection *RelocatedEHFrameSection =
getSection(".relocated" + getEHFrameSectionName()); getSection(".relocated" + getEHFrameSectionName());
@@ -3551,6 +3656,18 @@ void RewriteInstance::mapFileSections(BOLTLinker::SectionMapper MapSection) {
// Map the rest of the sections. // Map the rest of the sections.
mapAllocatableSections(MapSection); mapAllocatableSections(MapSection);
+
+ if (StartBD) {
+ const uint64_t ReservedSpace = EndBD->getAddress() - StartBD->getAddress();
+ const uint64_t AllocatedSize = NextAvailableAddress - StartBD->getAddress();
+ if (ReservedSpace < AllocatedSize) {
+ BC->errs() << "BOLT-ERROR: reserved space (" << ReservedSpace << " byte"
+ << (ReservedSpace == 1 ? "" : "s")
+ << ") is smaller than required for new allocations ("
+ << AllocatedSize << " bytes)\n";
+ exit(1);
+ }
+ }
} }
std::vector<BinarySection *> RewriteInstance::getCodeSections() { std::vector<BinarySection *> RewriteInstance::getCodeSections() {
@@ -3792,7 +3909,7 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) {
// Add the new text section aggregating all existing code sections. // Add the new text section aggregating all existing code sections.
// This is pseudo-section that serves a purpose of creating a corresponding // This is pseudo-section that serves a purpose of creating a corresponding
// entry in section header table. // entry in section header table.
- int64_t NewTextSectionSize =+ const uint64_t NewTextSectionSize =
NextAvailableAddress - NewTextSectionStartAddress; NextAvailableAddress - NewTextSectionStartAddress;
if (NewTextSectionSize) { if (NewTextSectionSize) {
const unsigned Flags = BinarySection::getFlags(/*IsReadOnly=*/true, const unsigned Flags = BinarySection::getFlags(/*IsReadOnly=*/true,
@@ -3875,7 +3992,7 @@ void RewriteInstance::mapAllocatableSections(
if (PHDRTableAddress) { if (PHDRTableAddress) {
// Segment size includes the size of the PHDR area. // Segment size includes the size of the PHDR area.
NewTextSegmentSize = NextAvailableAddress - PHDRTableAddress; NewTextSegmentSize = NextAvailableAddress - PHDRTableAddress;
- } else {+ } else if (NewTextSegmentAddress) {
// Existing PHDR table would be updated. // Existing PHDR table would be updated.
NewTextSegmentSize = NextAvailableAddress - NewTextSegmentAddress; NewTextSegmentSize = NextAvailableAddress - NewTextSegmentAddress;
} }
@@ -3914,7 +4031,7 @@ void RewriteInstance::patchELFPHDRTable() {
assert(!PHDRTableAddress && "unexpected address for program header table"); assert(!PHDRTableAddress && "unexpected address for program header table");
PHDRTableOffset = Obj.getHeader().e_phoff; PHDRTableOffset = Obj.getHeader().e_phoff;
if (NewWritableSegmentSize) { if (NewWritableSegmentSize) {
- BC->errs() << "Unable to add writable segment with UseGnuStack option\n";+ BC->errs() << "BOLT-ERROR: unable to add writable segment\n";
exit(1); exit(1);
} }
} }
@@ -3924,19 +4041,15 @@ void RewriteInstance::patchELFPHDRTable() {
if (!NewWritableSegmentSize) { if (!NewWritableSegmentSize) {
if (PHDRTableAddress) if (PHDRTableAddress)
NewTextSegmentSize = NextAvailableAddress - PHDRTableAddress; NewTextSegmentSize = NextAvailableAddress - PHDRTableAddress;
- else+ else if (NewTextSegmentAddress)
NewTextSegmentSize = NextAvailableAddress - NewTextSegmentAddress; NewTextSegmentSize = NextAvailableAddress - NewTextSegmentAddress;
} else { } else {
NewWritableSegmentSize = NextAvailableAddress - NewWritableSegmentAddress; NewWritableSegmentSize = NextAvailableAddress - NewWritableSegmentAddress;
} }
+ const uint64_t SavedPos = OS.tell();
OS.seek(PHDRTableOffset); OS.seek(PHDRTableOffset);
- bool ModdedGnuStack = false;
- (void)ModdedGnuStack;
- bool AddedSegment = false;
- (void)AddedSegment;
-
auto createNewTextPhdr = [&]() { auto createNewTextPhdr = [&]() {
ELF64LEPhdrTy NewPhdr; ELF64LEPhdrTy NewPhdr;
NewPhdr.p_type = ELF::PT_LOAD; NewPhdr.p_type = ELF::PT_LOAD;
@@ -3952,40 +4065,55 @@ void RewriteInstance::patchELFPHDRTable() {
NewPhdr.p_filesz = NewTextSegmentSize; NewPhdr.p_filesz = NewTextSegmentSize;
NewPhdr.p_memsz = NewTextSegmentSize; NewPhdr.p_memsz = NewTextSegmentSize;
NewPhdr.p_flags = ELF::PF_X | ELF::PF_R; NewPhdr.p_flags = ELF::PF_X | ELF::PF_R;
- // FIXME: Currently instrumentation is experimental and the runtime data+ if (opts::Instrument) {
- // is emitted with code, thus everything needs to be writable+ // FIXME: Currently instrumentation is experimental and the runtime data
- if (opts::Instrument)+ // is emitted with code, thus everything needs to be writable.
NewPhdr.p_flags |= ELF::PF_W; NewPhdr.p_flags |= ELF::PF_W;
+ }
NewPhdr.p_align = BC->PageAlign; NewPhdr.p_align = BC->PageAlign;
return NewPhdr; return NewPhdr;
}; };
- auto createNewWritableSectionsPhdr = [&]() {+ auto writeNewSegmentPhdrs = [&]() {
- ELF64LEPhdrTy NewPhdr;+ if (PHDRTableAddress || NewTextSegmentSize) {
- NewPhdr.p_type = ELF::PT_LOAD;+ ELF64LE::Phdr NewPhdr = createNewTextPhdr();
- NewPhdr.p_offset = getFileOffsetForAddress(NewWritableSegmentAddress);+ OS.write(reinterpret_cast<const char *>(&NewPhdr), sizeof(NewPhdr));
- NewPhdr.p_vaddr = NewWritableSegmentAddress;+ }
- NewPhdr.p_paddr = NewWritableSegmentAddress;+
- NewPhdr.p_filesz = NewWritableSegmentSize;+ if (NewWritableSegmentSize) {
- NewPhdr.p_memsz = NewWritableSegmentSize;+ ELF64LEPhdrTy NewPhdr;
- NewPhdr.p_align = BC->RegularPageSize;+ NewPhdr.p_type = ELF::PT_LOAD;
- NewPhdr.p_flags = ELF::PF_R | ELF::PF_W;+ NewPhdr.p_offset = getFileOffsetForAddress(NewWritableSegmentAddress);
- return NewPhdr;+ NewPhdr.p_vaddr = NewWritableSegmentAddress;
+ NewPhdr.p_paddr = NewWritableSegmentAddress;
+ NewPhdr.p_filesz = NewWritableSegmentSize;
+ NewPhdr.p_memsz = NewWritableSegmentSize;
+ NewPhdr.p_align = BC->RegularPageSize;
+ NewPhdr.p_flags = ELF::PF_R | ELF::PF_W;
+ OS.write(reinterpret_cast<const char *>(&NewPhdr), sizeof(NewPhdr));
+ }
}; };
+ bool ModdedGnuStack = false;
+ bool AddedSegment = false;
+
// Copy existing program headers with modifications. // Copy existing program headers with modifications.
for (const ELF64LE::Phdr &Phdr : cantFail(Obj.program_headers())) { for (const ELF64LE::Phdr &Phdr : cantFail(Obj.program_headers())) {
ELF64LE::Phdr NewPhdr = Phdr; ELF64LE::Phdr NewPhdr = Phdr;
- if (PHDRTableAddress && Phdr.p_type == ELF::PT_PHDR) {+ switch (Phdr.p_type) {
- NewPhdr.p_offset = PHDRTableOffset;+ case ELF::PT_PHDR:
- NewPhdr.p_vaddr = PHDRTableAddress;+ if (PHDRTableAddress) {
- NewPhdr.p_paddr = PHDRTableAddress;+ NewPhdr.p_offset = PHDRTableOffset;
- NewPhdr.p_filesz = sizeof(NewPhdr) * Phnum;+ NewPhdr.p_vaddr = PHDRTableAddress;
- NewPhdr.p_memsz = sizeof(NewPhdr) * Phnum;+ NewPhdr.p_paddr = PHDRTableAddress;
- } else if (Phdr.p_type == ELF::PT_GNU_EH_FRAME) {+ NewPhdr.p_filesz = sizeof(NewPhdr) * Phnum;
- ErrorOr<BinarySection &> EHFrameHdrSec =+ NewPhdr.p_memsz = sizeof(NewPhdr) * Phnum;
- BC->getUniqueSectionByName(getNewSecPrefix() + ".eh_frame_hdr");+ }
+ break;
+ case ELF::PT_GNU_EH_FRAME: {
+ ErrorOr<BinarySection &> EHFrameHdrSec = BC->getUniqueSectionByName(
+ getNewSecPrefix() + getEHFrameHdrSectionName());
if (EHFrameHdrSec && EHFrameHdrSec->isAllocatable() && if (EHFrameHdrSec && EHFrameHdrSec->isAllocatable() &&
EHFrameHdrSec->isFinalized()) { EHFrameHdrSec->isFinalized()) {
NewPhdr.p_offset = EHFrameHdrSec->getOutputFileOffset(); NewPhdr.p_offset = EHFrameHdrSec->getOutputFileOffset();
@@ -3994,37 +4122,38 @@ void RewriteInstance::patchELFPHDRTable() {
NewPhdr.p_filesz = EHFrameHdrSec->getOutputSize(); NewPhdr.p_filesz = EHFrameHdrSec->getOutputSize();
NewPhdr.p_memsz = EHFrameHdrSec->getOutputSize(); NewPhdr.p_memsz = EHFrameHdrSec->getOutputSize();
} }
- } else if (opts::UseGnuStack && Phdr.p_type == ELF::PT_GNU_STACK) {+ break;
- NewPhdr = createNewTextPhdr();+ }
- ModdedGnuStack = true;+ case ELF::PT_GNU_STACK:
- } else if (!opts::UseGnuStack && Phdr.p_type == ELF::PT_DYNAMIC) {+ if (opts::UseGnuStack) {
- // Insert the new header before DYNAMIC.+ // Overwrite the header with the new text segment header.
- ELF64LE::Phdr NewTextPhdr = createNewTextPhdr();+ NewPhdr = createNewTextPhdr();
- OS.write(reinterpret_cast<const char *>(&NewTextPhdr),+ ModdedGnuStack = true;
- sizeof(NewTextPhdr));
- if (NewWritableSegmentSize) {
- ELF64LEPhdrTy NewWritablePhdr = createNewWritableSectionsPhdr();
- OS.write(reinterpret_cast<const char *>(&NewWritablePhdr),
- sizeof(NewWritablePhdr));
} }
- AddedSegment = true;+ break;
+ case ELF::PT_DYNAMIC:
+ if (!opts::UseGnuStack) {
+ // Insert new headers before DYNAMIC.
+ writeNewSegmentPhdrs();
+ AddedSegment = true;
+ }
+ break;
} }
OS.write(reinterpret_cast<const char *>(&NewPhdr), sizeof(NewPhdr)); OS.write(reinterpret_cast<const char *>(&NewPhdr), sizeof(NewPhdr));
} }
if (!opts::UseGnuStack && !AddedSegment) { if (!opts::UseGnuStack && !AddedSegment) {
- // Append the new header to the end of the table.+ // Append new headers to the end of the table.
- ELF64LE::Phdr NewTextPhdr = createNewTextPhdr();+ writeNewSegmentPhdrs();
- OS.write(reinterpret_cast<const char *>(&NewTextPhdr), sizeof(NewTextPhdr));+ }
- if (NewWritableSegmentSize) {+
- ELF64LEPhdrTy NewWritablePhdr = createNewWritableSectionsPhdr();+ if (opts::UseGnuStack && !ModdedGnuStack) {
- OS.write(reinterpret_cast<const char *>(&NewWritablePhdr),+ BC->errs()
- sizeof(NewWritablePhdr));+ << "BOLT-ERROR: could not find PT_GNU_STACK program header to modify\n";
- }+ exit(1);
} }
- assert((!opts::UseGnuStack || ModdedGnuStack) &&+ OS.seek(SavedPos);
- "could not find GNU_STACK program header to modify");
} }
namespace { namespace {
@@ -4050,9 +4179,8 @@ void RewriteInstance::rewriteNoteSections() {
const ELFFile<ELF64LE> &Obj = ELF64LEFile->getELFFile(); const ELFFile<ELF64LE> &Obj = ELF64LEFile->getELFFile();
raw_fd_ostream &OS = Out->os(); raw_fd_ostream &OS = Out->os();
- uint64_t NextAvailableOffset = getFileOffsetForAddress(NextAvailableAddress);+ uint64_t NextAvailableOffset = std::max(
- assert(NextAvailableOffset >= FirstNonAllocatableOffset &&+ getFileOffsetForAddress(NextAvailableAddress), FirstNonAllocatableOffset);
- "next available offset calculation failure");
OS.seek(NextAvailableOffset); OS.seek(NextAvailableOffset);
// Copy over non-allocatable section contents and update file offsets. // Copy over non-allocatable section contents and update file offsets.
@@ -4493,6 +4621,8 @@ void RewriteInstance::updateELFSymbolTable(
// Symbols for the new symbol table. // Symbols for the new symbol table.
std::vector<ELFSymTy> Symbols; std::vector<ELFSymTy> Symbols;
+ bool EmittedColdFileSymbol = false;
+
auto getNewSectionIndex = [&](uint32_t OldIndex) { auto getNewSectionIndex = [&](uint32_t OldIndex) {
// For dynamic symbol table, the section index could be wrong on the input, // For dynamic symbol table, the section index could be wrong on the input,
// and its value is ignored by the runtime if it's different from // and its value is ignored by the runtime if it's different from
@@ -4551,6 +4681,20 @@ void RewriteInstance::updateELFSymbolTable(
Symbols.emplace_back(ICFSymbol); Symbols.emplace_back(ICFSymbol);
} }
if (Function.isSplit()) { if (Function.isSplit()) {
+ // Prepend synthetic FILE symbol to prevent local cold fragments from
+ // colliding with existing symbols with the same name.
+ if (!EmittedColdFileSymbol &&
+ FunctionSymbol.getBinding() == ELF::STB_GLOBAL) {
+ ELFSymTy FileSymbol;
+ FileSymbol.st_shndx = ELF::SHN_ABS;
+ FileSymbol.st_name = AddToStrTab(getBOLTFileSymbolName());
+ FileSymbol.st_value = 0;
+ FileSymbol.st_size = 0;
+ FileSymbol.st_other = 0;
+ FileSymbol.setBindingAndType(ELF::STB_LOCAL, ELF::STT_FILE);
+ Symbols.emplace_back(FileSymbol);
+ EmittedColdFileSymbol = true;
+ }
for (const FunctionFragment &FF : for (const FunctionFragment &FF :
Function.getLayout().getSplitFragments()) { Function.getLayout().getSplitFragments()) {
if (FF.getAddress()) { if (FF.getAddress()) {
@@ -4775,7 +4919,7 @@ void RewriteInstance::updateELFSymbolTable(
++NumHotDataSymsUpdated; ++NumHotDataSymsUpdated;
} }
- if (*SymbolName == "_end")+ if (*SymbolName == "_end" && NextAvailableAddress > Symbol.st_value)
updateSymbolValue(*SymbolName, NextAvailableAddress); updateSymbolValue(*SymbolName, NextAvailableAddress);
if (IsDynSym) if (IsDynSym)
@@ -4889,13 +5033,6 @@ void RewriteInstance::patchELFSymTabs(ELFObjectFile<ELFT> *File) {
std::vector<uint32_t> NewSectionIndex; std::vector<uint32_t> NewSectionIndex;
getOutputSections(File, NewSectionIndex); getOutputSections(File, NewSectionIndex);
- // Set pointer at the end of the output file, so we can pwrite old symbol
- // tables if we need to.
- uint64_t NextAvailableOffset = getFileOffsetForAddress(NextAvailableAddress);
- assert(NextAvailableOffset >= FirstNonAllocatableOffset &&
- "next available offset calculation failure");
- Out->os().seek(NextAvailableOffset);
-
// Update dynamic symbol table. // Update dynamic symbol table.
const ELFShdrTy *DynSymSection = nullptr; const ELFShdrTy *DynSymSection = nullptr;
for (const ELFShdrTy &Section : cantFail(Obj.sections())) { for (const ELFShdrTy &Section : cantFail(Obj.sections())) {
@@ -5432,6 +5569,17 @@ uint64_t RewriteInstance::getNewFunctionOrDataAddress(uint64_t OldAddress) {
if (BD && BD->isMoved()) if (BD && BD->isMoved())
return BD->getOutputAddress(); return BD->getOutputAddress();
+ if (const BinaryFunction *BF =
+ BC->getBinaryFunctionContainingAddress(OldAddress)) {
+ if (BF->isEmitted()) {
+ BC->errs() << "BOLT-ERROR: unable to get new address corresponding to "
+ "input address 0x"
+ << Twine::utohexstr(OldAddress) << " in function " << *BF
+ << ". Consider adding this function to --skip-funcs=...\n";
+ exit(1);
+ }
+ }
+
return 0; return 0;
} }
@@ -5449,10 +5597,10 @@ void RewriteInstance::rewriteFile() {
auto Streamer = BC->createStreamer(OS); auto Streamer = BC->createStreamer(OS);
// Make sure output stream has enough reserved space, otherwise // Make sure output stream has enough reserved space, otherwise
// pwrite() will fail. // pwrite() will fail.
- uint64_t Offset = OS.seek(getFileOffsetForAddress(NextAvailableAddress));+ uint64_t Offset = std::max(getFileOffsetForAddress(NextAvailableAddress),
- (void)Offset;+ FirstNonAllocatableOffset);
- assert(Offset == getFileOffsetForAddress(NextAvailableAddress) &&+ Offset = OS.seek(Offset);
- "error resizing output file");+ assert((Offset != (uint64_t)-1) && "Error resizing output file");
// Overwrite functions with fixed output address. This is mostly used by // Overwrite functions with fixed output address. This is mostly used by
// non-relocation mode, with one exception: injected functions are covered // non-relocation mode, with one exception: injected functions are covered
@@ -5671,7 +5819,8 @@ void RewriteInstance::writeEHFrameHeader() {
BC->AsmInfo->getCodePointerSize())); BC->AsmInfo->getCodePointerSize()));
check_error(std::move(Er), "failed to parse EH frame"); check_error(std::move(Er), "failed to parse EH frame");
- LLVM_DEBUG(dbgs() << "BOLT: writing a new .eh_frame_hdr\n");+ LLVM_DEBUG(dbgs() << "BOLT: writing a new " << getEHFrameHdrSectionName()
+ << '\n');
NextAvailableAddress = NextAvailableAddress =
appendPadding(Out->os(), NextAvailableAddress, EHFrameHdrAlign); appendPadding(Out->os(), NextAvailableAddress, EHFrameHdrAlign);
@@ -5683,25 +5832,35 @@ void RewriteInstance::writeEHFrameHeader() {
std::vector<char> NewEHFrameHdr = CFIRdWrt->generateEHFrameHeader( std::vector<char> NewEHFrameHdr = CFIRdWrt->generateEHFrameHeader(
RelocatedEHFrame, NewEHFrame, EHFrameHdrOutputAddress, FailedAddresses); RelocatedEHFrame, NewEHFrame, EHFrameHdrOutputAddress, FailedAddresses);
- assert(Out->os().tell() == EHFrameHdrFileOffset && "offset mismatch");+ Out->os().seek(EHFrameHdrFileOffset);
Out->os().write(NewEHFrameHdr.data(), NewEHFrameHdr.size()); Out->os().write(NewEHFrameHdr.data(), NewEHFrameHdr.size());
const unsigned Flags = BinarySection::getFlags(/*IsReadOnly=*/true, const unsigned Flags = BinarySection::getFlags(/*IsReadOnly=*/true,
/*IsText=*/false, /*IsText=*/false,
/*IsAllocatable=*/true); /*IsAllocatable=*/true);
- BinarySection *OldEHFrameHdrSection = getSection(".eh_frame_hdr");+ BinarySection *OldEHFrameHdrSection = getSection(getEHFrameHdrSectionName());
if (OldEHFrameHdrSection) if (OldEHFrameHdrSection)
- OldEHFrameHdrSection->setOutputName(getOrgSecPrefix() + ".eh_frame_hdr");+ OldEHFrameHdrSection->setOutputName(getOrgSecPrefix() +
+ getEHFrameHdrSectionName());
BinarySection &EHFrameHdrSec = BC->registerOrUpdateSection( BinarySection &EHFrameHdrSec = BC->registerOrUpdateSection(
- getNewSecPrefix() + ".eh_frame_hdr", ELF::SHT_PROGBITS, Flags, nullptr,+ getNewSecPrefix() + getEHFrameHdrSectionName(), ELF::SHT_PROGBITS, Flags,
- NewEHFrameHdr.size(), /*Alignment=*/1);+ nullptr, NewEHFrameHdr.size(), /*Alignment=*/1);
EHFrameHdrSec.setOutputFileOffset(EHFrameHdrFileOffset); EHFrameHdrSec.setOutputFileOffset(EHFrameHdrFileOffset);
EHFrameHdrSec.setOutputAddress(EHFrameHdrOutputAddress); EHFrameHdrSec.setOutputAddress(EHFrameHdrOutputAddress);
- EHFrameHdrSec.setOutputName(".eh_frame_hdr");+ EHFrameHdrSec.setOutputName(getEHFrameHdrSectionName());
NextAvailableAddress += EHFrameHdrSec.getOutputSize(); NextAvailableAddress += EHFrameHdrSec.getOutputSize();
+ if (const BinaryData *ReservedEnd =
+ BC->getBinaryDataByName(getBOLTReservedEnd())) {
+ if (NextAvailableAddress > ReservedEnd->getAddress()) {
+ BC->errs() << "BOLT-ERROR: unable to fit " << getEHFrameHdrSectionName()
+ << " into reserved space\n";
+ exit(1);
+ }
+ }
+
// Merge new .eh_frame with the relocated original so that gdb can locate all // Merge new .eh_frame with the relocated original so that gdb can locate all
// FDEs. // FDEs.
if (RelocatedEHFrameSection) { if (RelocatedEHFrameSection) {
bolt/test/RISCV/unnamed-sym-no-entry.cbolt/test/RISCV/fake-label-no-entry.c
@@ -5,12 +5,12 @@
// RUN: %clang %cflags -g -Wl,-q -o %t %s // RUN: %clang %cflags -g -Wl,-q -o %t %s
-/// Verify that the binary indeed contains an unnamed symbol at _start+/// Verify that the binary indeed contains a fake label ".L0 " at _start.
// RUN: llvm-readelf -s %t | FileCheck %s --check-prefix=CHECK-ELF // RUN: llvm-readelf -s %t | FileCheck %s --check-prefix=CHECK-ELF
// CHECK-ELF-DAG: [[#%x,START:]] {{.*}} FUNC GLOBAL DEFAULT [[#%d,SECTION:]] _start{{$}} // CHECK-ELF-DAG: [[#%x,START:]] {{.*}} FUNC GLOBAL DEFAULT [[#%d,SECTION:]] _start{{$}}
-// CHECK-ELF-DAG: [[#%x,START]] {{.*}} NOTYPE LOCAL DEFAULT [[#SECTION]] {{$}}+// CHECK-ELF-DAG: [[#%x,START]] {{.*}} NOTYPE LOCAL DEFAULT [[#SECTION]] .L0 {{$}}
-/// Verify that BOLT did not create an extra entry point for the unnamed symbol+/// Verify that BOLT did not create an extra entry point for the fake label.
// RUN: llvm-bolt -o %t.bolt %t --print-cfg | FileCheck %s // RUN: llvm-bolt -o %t.bolt %t --print-cfg | FileCheck %s
// CHECK: Binary Function "_start" after building cfg { // CHECK: Binary Function "_start" after building cfg {
// CHECK: IsMultiEntry: 0 // CHECK: IsMultiEntry: 0
bolt/test/X86/cdsplit-symbol-names.s
@@ -10,6 +10,7 @@
# RUN: --call-scale=2 --data=%t.fdata --reorder-blocks=ext-tsp # RUN: --call-scale=2 --data=%t.fdata --reorder-blocks=ext-tsp
# RUN: llvm-objdump --syms %t.bolt | FileCheck %s --check-prefix=CHECK-SYMS-WARM # RUN: llvm-objdump --syms %t.bolt | FileCheck %s --check-prefix=CHECK-SYMS-WARM
+# CHECK-SYMS-WARM: 0000000000000000 l df *ABS* 0000000000000000 bolt-pseudo.o
# CHECK-SYMS-WARM: .text.warm # CHECK-SYMS-WARM: .text.warm
# CHECK-SYMS-WARM-SAME: chain.warm # CHECK-SYMS-WARM-SAME: chain.warm
# CHECK-SYMS-WARM: .text.cold # CHECK-SYMS-WARM: .text.cold
bolt/test/X86/fragment-lite.s
@@ -3,35 +3,42 @@
# RUN: split-file %s %t # RUN: split-file %s %t
# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %t/main.s -o %t.o # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %t/main.s -o %t.o
# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %t/baz.s -o %t.baz.o # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %t/baz.s -o %t.baz.o
+# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %t/baz2.s -o %t.baz2.o
# RUN: link_fdata %s %t.o %t.main.fdata # RUN: link_fdata %s %t.o %t.main.fdata
# RUN: link_fdata %s %t.baz.o %t.baz.fdata # RUN: link_fdata %s %t.baz.o %t.baz.fdata
-# RUN: merge-fdata %t.main.fdata %t.baz.fdata > %t.fdata+# RUN: link_fdata %s %t.baz2.o %t.baz2.fdata
-# RUN: %clang %cflags %t.o %t.baz.o -o %t.exe -Wl,-q+# RUN: merge-fdata %t.main.fdata %t.baz.fdata %t.baz2.fdata > %t.fdata
+# RUN: %clang %cflags %t.o %t.baz.o %t.baz2.o -o %t.exe -Wl,-q
# RUN: llvm-bolt %t.exe -o %t.out --lite=1 --data %t.fdata -v=1 -print-cfg \ # RUN: llvm-bolt %t.exe -o %t.out --lite=1 --data %t.fdata -v=1 -print-cfg \
# RUN: 2>&1 | FileCheck %s # RUN: 2>&1 | FileCheck %s
# CHECK: BOLT-INFO: processing main.cold.1 as a sibling of non-ignored function # CHECK: BOLT-INFO: processing main.cold.1 as a sibling of non-ignored function
-# CHECK: BOLT-INFO: processing foo.cold.1/1 as a sibling of non-ignored function+# CHECK: BOLT-INFO: processing foo.cold.1/1(*2) as a sibling of non-ignored function
-# CHECK: BOLT-INFO: processing bar.cold.1/1 as a sibling of non-ignored function+# CHECK: BOLT-INFO: processing bar.cold.1/1(*2) as a sibling of non-ignored function
# CHECK: BOLT-INFO: processing baz.cold.1 as a sibling of non-ignored function # CHECK: BOLT-INFO: processing baz.cold.1 as a sibling of non-ignored function
-# CHECK: BOLT-INFO: processing baz.cold.1/1 as a sibling of non-ignored function+# CHECK: BOLT-INFO: processing baz.cold.1/1(*2) as a sibling of non-ignored function
+# CHECK: BOLT-INFO: processing baz.cold.1/2(*2) as a sibling of non-ignored function
# CHECK: Binary Function "main.cold.1" after building cfg # CHECK: Binary Function "main.cold.1" after building cfg
# CHECK: Parent : main # CHECK: Parent : main
-# CHECK: Binary Function "foo.cold.1/1" after building cfg+# CHECK: Binary Function "foo.cold.1/1(*2)" after building cfg
# CHECK: Parent : foo # CHECK: Parent : foo
-# CHECK: Binary Function "bar.cold.1/1" after building cfg+# CHECK: Binary Function "bar.cold.1/1(*2)" after building cfg
-# CHECK: Parent : bar/1+# CHECK: Parent : bar/1(*2)
# CHECK: Binary Function "baz.cold.1" after building cfg # CHECK: Binary Function "baz.cold.1" after building cfg
# CHECK: Parent : baz{{$}} # CHECK: Parent : baz{{$}}
-# CHECK: Binary Function "baz.cold.1/1" after building cfg+# CHECK: Binary Function "baz.cold.1/1(*2)" after building cfg
-# CHECK: Parent : baz/1+# CHECK: Parent : baz/1(*2)
+
+# CHECK: Binary Function "baz.cold.1/2(*2)" after building cfg
+# CHECK: Parent : baz/2(*2)
#--- main.s #--- main.s
+.file "main.s"
.globl main .globl main
.type main, %function .type main, %function
main: main:
@@ -126,6 +133,7 @@ baz.cold.1:
.size baz.cold.1, .-baz.cold.1 .size baz.cold.1, .-baz.cold.1
#--- baz.s #--- baz.s
+.file "baz.s"
.local baz .local baz
.type baz, %function .type baz, %function
baz: baz:
@@ -149,3 +157,29 @@ baz.cold.1:
retq retq
.cfi_endproc .cfi_endproc
.size baz.cold.1, .-baz.cold.1 .size baz.cold.1, .-baz.cold.1
+
+#--- baz2.s
+.file "baz2.s"
+ .local baz
+ .type baz, %function
+baz:
+ .cfi_startproc
+# FDATA: 0 [unknown] 0 1 baz/2 0 1 0
+ cmpl $0x0, %eax
+ je baz.cold.1
+ retq
+ .cfi_endproc
+.size baz, .-baz
+
+ .section .text.cold
+ .local baz.cold.1
+ .type baz.cold.1, %function
+baz.cold.1:
+ .cfi_startproc
+ pushq %rbp
+ movq %rsp, %rbp
+ movl $0x0, %eax
+ popq %rbp
+ retq
+ .cfi_endproc
+.size baz.cold.1, .-baz.cold.1
bolt/test/X86/indirect-goto-pie.test
@@ -0,0 +1,16 @@
+# Check that llvm-bolt fails to process PIC binaries with computed goto, as the
+# support is not there yet for correctly updating dynamic relocations
+# referencing code inside functions.
+
+REQUIRES: x86_64-linux
+
+RUN: %clang %S/Inputs/indirect_goto.c -o %t -fpic -pie -Wl,-q
+RUN: not llvm-bolt %t -o %t.bolt --relocs=1 --print-cfg --print-only=main \
+RUN: |& FileCheck %s
+
+# Check that processing works if main() is skipped.
+RUN: llvm-bolt %t -o %t.bolt --relocs=1 --skip-funcs=main
+
+CHECK: jmpq *%rax # UNKNOWN CONTROL FLOW
+
+CHECK: BOLT-ERROR: unable to get new address
bolt/test/X86/pre-aggregated-perf.test
@@ -11,7 +11,14 @@ REQUIRES: system-linux
RUN: yaml2obj %p/Inputs/blarge.yaml &> %t.exe RUN: yaml2obj %p/Inputs/blarge.yaml &> %t.exe
RUN: perf2bolt %t.exe -o %t --pa -p %p/Inputs/pre-aggregated.txt -w %t.new \ RUN: perf2bolt %t.exe -o %t --pa -p %p/Inputs/pre-aggregated.txt -w %t.new \
-RUN: --profile-use-dfs+RUN: --profile-use-dfs | FileCheck %s
+
+RUN: llvm-bolt %t.exe -data %t -o %t.null | FileCheck %s
+RUN: llvm-bolt %t.exe -data %t.new -o %t.null | FileCheck %s
+RUN: llvm-bolt %t.exe -p %p/Inputs/pre-aggregated.txt --pa -o %t.null | FileCheck %s
+
+CHECK: BOLT-INFO: 4 out of 7 functions in the binary (57.1%) have non-empty execution profile
+
RUN: cat %t | sort | FileCheck %s -check-prefix=PERF2BOLT RUN: cat %t | sort | FileCheck %s -check-prefix=PERF2BOLT
RUN: cat %t.new | FileCheck %s -check-prefix=NEWFORMAT RUN: cat %t.new | FileCheck %s -check-prefix=NEWFORMAT
bolt/test/X86/register-fragments-bolt-symbols.s
@@ -0,0 +1,32 @@
+# Test the heuristics for matching BOLT-added split functions.
+
+# RUN: llvm-mc --filetype=obj --triple x86_64-unknown-unknown %S/cdsplit-symbol-names.s -o %t.main.o
+# RUN: llvm-mc --filetype=obj --triple x86_64-unknown-unknown %s -o %t.chain.o
+# RUN: link_fdata %S/cdsplit-symbol-names.s %t.main.o %t.fdata
+# RUN: sed -i 's|chain|chain/2|g' %t.fdata
+# RUN: llvm-strip --strip-unneeded %t.main.o
+# RUN: llvm-objcopy --localize-symbol=chain %t.main.o
+# RUN: %clang %cflags %t.chain.o %t.main.o -o %t.exe -Wl,-q
+# RUN: llvm-bolt %t.exe -o %t.bolt --split-functions --split-strategy=randomN \
+# RUN: --reorder-blocks=ext-tsp --enable-bat --bolt-seed=7 --data=%t.fdata
+# RUN: llvm-objdump --syms %t.bolt | FileCheck %s --check-prefix=CHECK-SYMS
+
+# RUN: link_fdata %s %t.bolt %t.preagg PREAGG
+# PREAGG: B X:0 #chain.cold.0# 1 0
+# RUN: perf2bolt %t.bolt -p %t.preagg --pa -o %t.bat.fdata -w %t.bat.yaml -v=1 \
+# RUN: | FileCheck %s --check-prefix=CHECK-REGISTER
+
+# CHECK-SYMS: l df *ABS* [[#]] chain.s
+# CHECK-SYMS: l F .bolt.org.text [[#]] chain
+# CHECK-SYMS: l F .text.cold [[#]] chain.cold.0
+# CHECK-SYMS: l F .text [[#]] chain
+# CHECK-SYMS: l df *ABS* [[#]] bolt-pseudo.o
+
+# CHECK-REGISTER: BOLT-INFO: marking chain.cold.0/1(*2) as a fragment of chain/2(*2)
+
+.file "chain.s"
+ .text
+ .type chain, @function
+chain:
+ ret
+ .size chain, .-chain
bolt/test/X86/shrinkwrapping-do-not-pessimize.s
@@ -53,6 +53,6 @@ end_if_1:
.size _start, .-_start .size _start, .-_start
.data .data
-rel: .quad end_if_1+rel: .quad _start
# CHECK: BOLT-INFO: Shrink wrapping moved 0 spills inserting load/stores and 0 spills inserting push/pops # CHECK: BOLT-INFO: Shrink wrapping moved 0 spills inserting load/stores and 0 spills inserting push/pops
bolt/test/runtime/X86/Inputs/indirect_goto.c→/dev/null
@@ -1,18 +0,0 @@
-int main(int argc, char *argv[]) {
- static const void *T1[] = { &&L1, &&L2 };
- static const void *T2[] = { &&L2, &&L3 };
-
- const void **T = (argc > 1) ? T1 : T2;
-
- int i = 0;
-
-L0:
- goto *T[argc];
-L1:
- ++i;
-L2:
- i++;
-L3:
- i++;
- return i;
-}
bolt/test/runtime/X86/indirect-goto-pie.test→/dev/null
@@ -1,10 +0,0 @@
-# Check llvm-bolt processes binaries compiled from sources that use indirect goto.
-REQUIRES: x86_64-linux
-
-RUN: %clang %S/Inputs/indirect_goto.c -o %t -fpic -pie -Wl,-q
-RUN: llvm-bolt %t -o %t.bolt --relocs=1 --print-cfg --print-only=main \
-RUN: |& FileCheck %s
-# The test fails as we don't update corresponding dynamic relocations.
-RUN: not %t.bolt
-
-CHECK: jmpq *%rax # UNKNOWN CONTROL FLOW
clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp
@@ -967,7 +967,8 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From,
// Get out the qualifiers of the original type. This will always be // Get out the qualifiers of the original type. This will always be
// re-applied to the WorkType to ensure it is the same qualification as the // re-applied to the WorkType to ensure it is the same qualification as the
// original From was. // original From was.
- auto QualifiersToApply = From.split().Quals.getAsOpaqueValue();+ auto FastQualifiersToApply = static_cast<unsigned>(
+ From.split().Quals.getAsOpaqueValue() & Qualifiers::FastMask);
// LValue->RValue is irrelevant for the check, because it is a thing to be // LValue->RValue is irrelevant for the check, because it is a thing to be
// done at a call site, and will be performed if need be performed. // done at a call site, and will be performed if need be performed.
@@ -993,7 +994,7 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From,
// "const double -> double". // "const double -> double".
LLVM_DEBUG(llvm::dbgs() LLVM_DEBUG(llvm::dbgs()
<< "--- approximateStdConv. Conversion between numerics.\n"); << "--- approximateStdConv. Conversion between numerics.\n");
- WorkType = QualType{ToBuiltin, QualifiersToApply};+ WorkType = QualType{ToBuiltin, FastQualifiersToApply};
} }
const auto *FromEnum = WorkType->getAs<EnumType>(); const auto *FromEnum = WorkType->getAs<EnumType>();
@@ -1002,7 +1003,7 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From,
// Unscoped enumerations (or enumerations in C) convert to numerics. // Unscoped enumerations (or enumerations in C) convert to numerics.
LLVM_DEBUG(llvm::dbgs() LLVM_DEBUG(llvm::dbgs()
<< "--- approximateStdConv. Unscoped enum to numeric.\n"); << "--- approximateStdConv. Unscoped enum to numeric.\n");
- WorkType = QualType{ToBuiltin, QualifiersToApply};+ WorkType = QualType{ToBuiltin, FastQualifiersToApply};
} else if (FromNumeric && ToEnum && ToEnum->isUnscopedEnumerationType()) { } else if (FromNumeric && ToEnum && ToEnum->isUnscopedEnumerationType()) {
// Numeric types convert to enumerations only in C. // Numeric types convert to enumerations only in C.
if (Ctx.getLangOpts().CPlusPlus) { if (Ctx.getLangOpts().CPlusPlus) {
@@ -1013,7 +1014,7 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From,
LLVM_DEBUG(llvm::dbgs() LLVM_DEBUG(llvm::dbgs()
<< "--- approximateStdConv. Numeric to unscoped enum.\n"); << "--- approximateStdConv. Numeric to unscoped enum.\n");
- WorkType = QualType{ToEnum, QualifiersToApply};+ WorkType = QualType{ToEnum, FastQualifiersToApply};
} }
// Check for pointer conversions. // Check for pointer conversions.
@@ -1022,14 +1023,14 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From,
if (FromPtr && ToPtr) { if (FromPtr && ToPtr) {
if (ToPtr->isVoidPointerType()) { if (ToPtr->isVoidPointerType()) {
LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. To void pointer.\n"); LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. To void pointer.\n");
- WorkType = QualType{ToPtr, QualifiersToApply};+ WorkType = QualType{ToPtr, FastQualifiersToApply};
} }
const auto *FromRecordPtr = FromPtr->getPointeeCXXRecordDecl(); const auto *FromRecordPtr = FromPtr->getPointeeCXXRecordDecl();
const auto *ToRecordPtr = ToPtr->getPointeeCXXRecordDecl(); const auto *ToRecordPtr = ToPtr->getPointeeCXXRecordDecl();
if (isDerivedToBase(FromRecordPtr, ToRecordPtr)) { if (isDerivedToBase(FromRecordPtr, ToRecordPtr)) {
LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. Derived* to Base*\n"); LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. Derived* to Base*\n");
- WorkType = QualType{ToPtr, QualifiersToApply};+ WorkType = QualType{ToPtr, FastQualifiersToApply};
} }
} }
@@ -1039,7 +1040,7 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From,
const auto *ToRecord = To->getAsCXXRecordDecl(); const auto *ToRecord = To->getAsCXXRecordDecl();
if (isDerivedToBase(FromRecord, ToRecord)) { if (isDerivedToBase(FromRecord, ToRecord)) {
LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. Derived To Base.\n"); LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. Derived To Base.\n");
- WorkType = QualType{ToRecord->getTypeForDecl(), QualifiersToApply};+ WorkType = QualType{ToRecord->getTypeForDecl(), FastQualifiersToApply};
} }
if (Ctx.getLangOpts().CPlusPlus17 && FromPtr && ToPtr) { if (Ctx.getLangOpts().CPlusPlus17 && FromPtr && ToPtr) {
@@ -1054,7 +1055,7 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From,
!ToFunctionPtr->hasNoexceptExceptionSpec()) { !ToFunctionPtr->hasNoexceptExceptionSpec()) {
LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. noexcept function " LLVM_DEBUG(llvm::dbgs() << "--- approximateStdConv. noexcept function "
"pointer to non-noexcept.\n"); "pointer to non-noexcept.\n");
- WorkType = QualType{ToPtr, QualifiersToApply};+ WorkType = QualType{ToPtr, FastQualifiersToApply};
} }
} }
clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -16,6 +16,7 @@ add_clang_library(clangTidyModernizeModule
MakeSharedCheck.cpp MakeSharedCheck.cpp
MakeSmartPtrCheck.cpp MakeSmartPtrCheck.cpp
MakeUniqueCheck.cpp MakeUniqueCheck.cpp
+ MinMaxUseInitializerListCheck.cpp
ModernizeTidyModule.cpp ModernizeTidyModule.cpp
PassByValueCheck.cpp PassByValueCheck.cpp
RawStringLiteralCheck.cpp RawStringLiteralCheck.cpp
clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.cpp
@@ -0,0 +1,271 @@
+//===--- MinMaxUseInitializerListCheck.cpp - clang-tidy -------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MinMaxUseInitializerListCheck.h"
+#include "../utils/ASTUtils.h"
+#include "../utils/LexerUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang;
+
+namespace {
+
+struct FindArgsResult {
+ const Expr *First;
+ const Expr *Last;
+ const Expr *Compare;
+ SmallVector<const clang::Expr *, 2> Args;
+};
+
+} // anonymous namespace
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+static FindArgsResult findArgs(const CallExpr *Call) {
+ FindArgsResult Result;
+ Result.First = nullptr;
+ Result.Last = nullptr;
+ Result.Compare = nullptr;
+
+ // check if the function has initializer list argument
+ if (Call->getNumArgs() < 3) {
+ auto ArgIterator = Call->arguments().begin();
+
+ const auto *InitListExpr =
+ dyn_cast<CXXStdInitializerListExpr>(*ArgIterator);
+ const auto *InitList =
+ InitListExpr != nullptr
+ ? dyn_cast<clang::InitListExpr>(
+ InitListExpr->getSubExpr()->IgnoreImplicit())
+ : nullptr;
+
+ if (InitList) {
+ Result.Args.append(InitList->inits().begin(), InitList->inits().end());
+ Result.First = *ArgIterator;
+ Result.Last = *ArgIterator;
+
+ // check if there is a comparison argument
+ std::advance(ArgIterator, 1);
+ if (ArgIterator != Call->arguments().end())
+ Result.Compare = *ArgIterator;
+
+ return Result;
+ }
+ Result.Args = SmallVector<const Expr *>(Call->arguments());
+ } else {
+ // if it has 3 arguments then the last will be the comparison
+ Result.Compare = *(std::next(Call->arguments().begin(), 2));
+ Result.Args = SmallVector<const Expr *>(llvm::drop_end(Call->arguments()));
+ }
+ Result.First = Result.Args.front();
+ Result.Last = Result.Args.back();
+
+ return Result;
+}
+
+static SmallVector<FixItHint>
+generateReplacements(const MatchFinder::MatchResult &Match,
+ const CallExpr *TopCall, const FindArgsResult &Result,
+ const bool IgnoreNonTrivialTypes,
+ const std::uint64_t IgnoreTrivialTypesOfSizeAbove) {
+ SmallVector<FixItHint> FixItHints;
+ const SourceManager &SourceMngr = *Match.SourceManager;
+ const LangOptions &LanguageOpts = Match.Context->getLangOpts();
+
+ const QualType ResultType = TopCall->getDirectCallee()
+ ->getReturnType()
+ .getCanonicalType()
+ .getNonReferenceType()
+ .getUnqualifiedType();
+
+ // check if the type is trivial
+ const bool IsResultTypeTrivial = ResultType.isTrivialType(*Match.Context);
+
+ if ((!IsResultTypeTrivial && IgnoreNonTrivialTypes))
+ return FixItHints;
+
+ if (IsResultTypeTrivial &&
+ static_cast<std::uint64_t>(
+ Match.Context->getTypeSizeInChars(ResultType).getQuantity()) >
+ IgnoreTrivialTypesOfSizeAbove)
+ return FixItHints;
+
+ for (const Expr *Arg : Result.Args) {
+ const auto *InnerCall = dyn_cast<CallExpr>(Arg->IgnoreParenImpCasts());
+
+ // If the argument is not a nested call
+ if (!InnerCall) {
+ // check if typecast is required
+ const QualType ArgType = Arg->IgnoreParenImpCasts()
+ ->getType()
+ .getCanonicalType()
+ .getUnqualifiedType();
+
+ if (ArgType == ResultType)
+ continue;
+
+ const StringRef ArgText = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(Arg->getSourceRange()), SourceMngr,
+ LanguageOpts);
+
+ const auto Replacement = Twine("static_cast<")
+ .concat(ResultType.getAsString(LanguageOpts))
+ .concat(">(")
+ .concat(ArgText)
+ .concat(")")
+ .str();
+
+ FixItHints.push_back(
+ FixItHint::CreateReplacement(Arg->getSourceRange(), Replacement));
+ continue;
+ }
+
+ const FindArgsResult InnerResult = findArgs(InnerCall);
+
+ // if the nested call doesn't have arguments skip it
+ if (!InnerResult.First || !InnerResult.Last)
+ continue;
+
+ // if the nested call is not the same as the top call
+ if (InnerCall->getDirectCallee()->getQualifiedNameAsString() !=
+ TopCall->getDirectCallee()->getQualifiedNameAsString())
+ continue;
+
+ // if the nested call doesn't have the same compare function
+ if ((Result.Compare || InnerResult.Compare) &&
+ !utils::areStatementsIdentical(Result.Compare, InnerResult.Compare,
+ *Match.Context))
+ continue;
+
+ // remove the function call
+ FixItHints.push_back(
+ FixItHint::CreateRemoval(InnerCall->getCallee()->getSourceRange()));
+
+ // remove the parentheses
+ const auto LParen = utils::lexer::findNextTokenSkippingComments(
+ InnerCall->getCallee()->getEndLoc(), SourceMngr, LanguageOpts);
+ if (LParen.has_value() && LParen->is(tok::l_paren))
+ FixItHints.push_back(
+ FixItHint::CreateRemoval(SourceRange(LParen->getLocation())));
+ FixItHints.push_back(
+ FixItHint::CreateRemoval(SourceRange(InnerCall->getRParenLoc())));
+
+ // if the inner call has an initializer list arg
+ if (InnerResult.First == InnerResult.Last) {
+ // remove the initializer list braces
+ FixItHints.push_back(FixItHint::CreateRemoval(
+ CharSourceRange::getTokenRange(InnerResult.First->getBeginLoc())));
+ FixItHints.push_back(FixItHint::CreateRemoval(
+ CharSourceRange::getTokenRange(InnerResult.First->getEndLoc())));
+ }
+
+ const SmallVector<FixItHint> InnerReplacements = generateReplacements(
+ Match, InnerCall, InnerResult, IgnoreNonTrivialTypes,
+ IgnoreTrivialTypesOfSizeAbove);
+
+ FixItHints.append(InnerReplacements);
+
+ if (InnerResult.Compare) {
+ // find the comma after the value arguments
+ const auto Comma = utils::lexer::findNextTokenSkippingComments(
+ InnerResult.Last->getEndLoc(), SourceMngr, LanguageOpts);
+
+ // remove the comma and the comparison
+ if (Comma.has_value() && Comma->is(tok::comma))
+ FixItHints.push_back(
+ FixItHint::CreateRemoval(SourceRange(Comma->getLocation())));
+
+ FixItHints.push_back(
+ FixItHint::CreateRemoval(InnerResult.Compare->getSourceRange()));
+ }
+ }
+
+ return FixItHints;
+}
+
+MinMaxUseInitializerListCheck::MinMaxUseInitializerListCheck(
+ StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ IgnoreNonTrivialTypes(Options.get("IgnoreNonTrivialTypes", true)),
+ IgnoreTrivialTypesOfSizeAbove(
+ Options.get("IgnoreTrivialTypesOfSizeAbove", 32L)),
+ Inserter(Options.getLocalOrGlobal("IncludeStyle",
+ utils::IncludeSorter::IS_LLVM),
+ areDiagsSelfContained()) {}
+
+void MinMaxUseInitializerListCheck::storeOptions(
+ ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "IgnoreNonTrivialTypes", IgnoreNonTrivialTypes);
+ Options.store(Opts, "IgnoreTrivialTypesOfSizeAbove",
+ IgnoreTrivialTypesOfSizeAbove);
+ Options.store(Opts, "IncludeStyle", Inserter.getStyle());
+}
+
+void MinMaxUseInitializerListCheck::registerMatchers(MatchFinder *Finder) {
+ auto CreateMatcher = [](const StringRef FunctionName) {
+ auto FuncDecl = functionDecl(hasName(FunctionName));
+ auto Expression = callExpr(callee(FuncDecl));
+
+ return callExpr(callee(FuncDecl),
+ anyOf(hasArgument(0, Expression),
+ hasArgument(1, Expression),
+ hasArgument(0, cxxStdInitializerListExpr())),
+ unless(hasParent(Expression)))
+ .bind("topCall");
+ };
+
+ Finder->addMatcher(CreateMatcher("::std::max"), this);
+ Finder->addMatcher(CreateMatcher("::std::min"), this);
+}
+
+void MinMaxUseInitializerListCheck::registerPPCallbacks(
+ const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
+ Inserter.registerPreprocessor(PP);
+}
+
+void MinMaxUseInitializerListCheck::check(
+ const MatchFinder::MatchResult &Match) {
+
+ const auto *TopCall = Match.Nodes.getNodeAs<CallExpr>("topCall");
+
+ const FindArgsResult Result = findArgs(TopCall);
+ const SmallVector<FixItHint> Replacements =
+ generateReplacements(Match, TopCall, Result, IgnoreNonTrivialTypes,
+ IgnoreTrivialTypesOfSizeAbove);
+
+ if (Replacements.empty())
+ return;
+
+ const DiagnosticBuilder Diagnostic =
+ diag(TopCall->getBeginLoc(),
+ "do not use nested 'std::%0' calls, use an initializer list instead")
+ << TopCall->getDirectCallee()->getName()
+ << Inserter.createIncludeInsertion(
+ Match.SourceManager->getFileID(TopCall->getBeginLoc()),
+ "<algorithm>");
+
+ // if the top call doesn't have an initializer list argument
+ if (Result.First != Result.Last) {
+ // add { and } insertions
+ Diagnostic << FixItHint::CreateInsertion(Result.First->getBeginLoc(), "{");
+
+ Diagnostic << FixItHint::CreateInsertion(
+ Lexer::getLocForEndOfToken(Result.Last->getEndLoc(), 0,
+ *Match.SourceManager,
+ Match.Context->getLangOpts()),
+ "}");
+ }
+
+ Diagnostic << Replacements;
+}
+
+} // namespace clang::tidy::modernize
clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.h
@@ -0,0 +1,56 @@
+//===--- MinMaxUseInitializerListCheck.h - clang-tidy -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MINMAXUSEINITIALIZERLISTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MINMAXUSEINITIALIZERLISTCHECK_H
+
+#include "../ClangTidyCheck.h"
+#include "../utils/IncludeInserter.h"
+
+namespace clang::tidy::modernize {
+
+/// Replaces nested ``std::min`` and ``std::max`` calls with an initializer list
+/// where applicable.
+///
+/// For example:
+///
+/// \code
+/// int a = std::max(std::max(i, j), k);
+/// \endcode
+///
+/// This code is transformed to:
+///
+/// \code
+/// int a = std::max({i, j, k});
+/// \endcode
+class MinMaxUseInitializerListCheck : public ClangTidyCheck {
+public:
+ MinMaxUseInitializerListCheck(StringRef Name, ClangTidyContext *Context);
+
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Match) override;
+
+ bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+ return LangOpts.CPlusPlus11;
+ }
+ std::optional<TraversalKind> getCheckTraversalKind() const override {
+ return TK_IgnoreUnlessSpelledInSource;
+ }
+
+private:
+ bool IgnoreNonTrivialTypes;
+ std::uint64_t IgnoreTrivialTypesOfSizeAbove;
+ utils::IncludeInserter Inserter;
+};
+
+} // namespace clang::tidy::modernize
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MINMAXUSEINITIALIZERLISTCHECK_H
clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -18,6 +18,7 @@
#include "MacroToEnumCheck.h" #include "MacroToEnumCheck.h"
#include "MakeSharedCheck.h" #include "MakeSharedCheck.h"
#include "MakeUniqueCheck.h" #include "MakeUniqueCheck.h"
+#include "MinMaxUseInitializerListCheck.h"
#include "PassByValueCheck.h" #include "PassByValueCheck.h"
#include "RawStringLiteralCheck.h" #include "RawStringLiteralCheck.h"
#include "RedundantVoidArgCheck.h" #include "RedundantVoidArgCheck.h"
@@ -68,6 +69,8 @@ public:
CheckFactories.registerCheck<MacroToEnumCheck>("modernize-macro-to-enum"); CheckFactories.registerCheck<MacroToEnumCheck>("modernize-macro-to-enum");
CheckFactories.registerCheck<MakeSharedCheck>("modernize-make-shared"); CheckFactories.registerCheck<MakeSharedCheck>("modernize-make-shared");
CheckFactories.registerCheck<MakeUniqueCheck>("modernize-make-unique"); CheckFactories.registerCheck<MakeUniqueCheck>("modernize-make-unique");
+ CheckFactories.registerCheck<MinMaxUseInitializerListCheck>(
+ "modernize-min-max-use-initializer-list");
CheckFactories.registerCheck<PassByValueCheck>("modernize-pass-by-value"); CheckFactories.registerCheck<PassByValueCheck>("modernize-pass-by-value");
CheckFactories.registerCheck<UseDesignatedInitializersCheck>( CheckFactories.registerCheck<UseDesignatedInitializersCheck>(
"modernize-use-designated-initializers"); "modernize-use-designated-initializers");
clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h
@@ -19,7 +19,7 @@ public:
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
// FIXME this should be CPlusPlus11 but that causes test cases to // FIXME this should be CPlusPlus11 but that causes test cases to
// erroneously fail. // erroneously fail.
- return LangOpts.CPlusPlus;+ return LangOpts.CPlusPlus || LangOpts.C23;
} }
void storeOptions(ClangTidyOptions::OptionMap &Opts) override; void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override; void registerMatchers(ast_matchers::MatchFinder *Finder) override;
clang-tools-extra/clang-tidy/readability/AvoidReturnWithVoidValueCheck.cpp
@@ -64,8 +64,11 @@ void AvoidReturnWithVoidValueCheck::check(
<< BraceInsertionHints.closingBraceFixIt(); << BraceInsertionHints.closingBraceFixIt();
} }
Diag << FixItHint::CreateRemoval(VoidReturn->getReturnLoc()); Diag << FixItHint::CreateRemoval(VoidReturn->getReturnLoc());
- if (!Result.Nodes.getNodeAs<FunctionDecl>("function_parent") ||+ const auto *FunctionParent =
- SurroundingBlock->body_back() != VoidReturn)+ Result.Nodes.getNodeAs<FunctionDecl>("function_parent");
+ if (!FunctionParent ||
+ (SurroundingBlock && SurroundingBlock->body_back() != VoidReturn))
+ // If this is not the last statement in a function body, we add a `return`.
Diag << FixItHint::CreateInsertion(SemicolonPos.getLocWithOffset(1), Diag << FixItHint::CreateInsertion(SemicolonPos.getLocWithOffset(1),
" return;", true); " return;", true);
} }
clang-tools-extra/clang-tidy/readability/CMakeLists.txt
@@ -28,6 +28,7 @@ add_clang_library(clangTidyReadabilityModule
IsolateDeclarationCheck.cpp IsolateDeclarationCheck.cpp
MagicNumbersCheck.cpp MagicNumbersCheck.cpp
MakeMemberFunctionConstCheck.cpp MakeMemberFunctionConstCheck.cpp
+ MathMissingParenthesesCheck.cpp
MisleadingIndentationCheck.cpp MisleadingIndentationCheck.cpp
MisplacedArrayIndexCheck.cpp MisplacedArrayIndexCheck.cpp
NamedParameterCheck.cpp NamedParameterCheck.cpp
clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
@@ -0,0 +1,99 @@
+//===--- MathMissingParenthesesCheck.cpp - clang-tidy ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MathMissingParenthesesCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+void MathMissingParenthesesCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(binaryOperator(unless(hasParent(binaryOperator())),
+ unless(isAssignmentOperator()),
+ unless(isComparisonOperator()),
+ unless(hasAnyOperatorName("&&", "||")),
+ hasDescendant(binaryOperator()))
+ .bind("binOp"),
+ this);
+}
+
+static int getPrecedence(const BinaryOperator *BinOp) {
+ if (!BinOp)
+ return 0;
+ switch (BinOp->getOpcode()) {
+ case BO_Mul:
+ case BO_Div:
+ case BO_Rem:
+ return 5;
+ case BO_Add:
+ case BO_Sub:
+ return 4;
+ case BO_And:
+ return 3;
+ case BO_Xor:
+ return 2;
+ case BO_Or:
+ return 1;
+ default:
+ return 0;
+ }
+}
+static void addParantheses(const BinaryOperator *BinOp,
+ const BinaryOperator *ParentBinOp,
+ ClangTidyCheck *Check,
+ const clang::SourceManager &SM,
+ const clang::LangOptions &LangOpts) {
+ if (!BinOp)
+ return;
+
+ int Precedence1 = getPrecedence(BinOp);
+ int Precedence2 = getPrecedence(ParentBinOp);
+
+ if (ParentBinOp != nullptr && Precedence1 != Precedence2) {
+ const clang::SourceLocation StartLoc = BinOp->getBeginLoc();
+ const clang::SourceLocation EndLoc =
+ clang::Lexer::getLocForEndOfToken(BinOp->getEndLoc(), 0, SM, LangOpts);
+
+ auto Diag =
+ Check->diag(StartLoc,
+ "'%0' has higher precedence than '%1'; add parentheses to "
+ "explicitly specify the order of operations")
+ << (Precedence1 > Precedence2 ? BinOp->getOpcodeStr()
+ : ParentBinOp->getOpcodeStr())
+ << (Precedence1 > Precedence2 ? ParentBinOp->getOpcodeStr()
+ : BinOp->getOpcodeStr())
+ << SourceRange(StartLoc, EndLoc);
+
+ if (EndLoc.isValid()) {
+ Diag << FixItHint::CreateInsertion(StartLoc, "(")
+ << FixItHint::CreateInsertion(EndLoc, ")");
+ }
+ }
+
+ addParantheses(dyn_cast<BinaryOperator>(BinOp->getLHS()->IgnoreImpCasts()),
+ BinOp, Check, SM, LangOpts);
+ addParantheses(dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreImpCasts()),
+ BinOp, Check, SM, LangOpts);
+}
+
+void MathMissingParenthesesCheck::check(
+ const MatchFinder::MatchResult &Result) {
+ const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>("binOp");
+ std::vector<
+ std::pair<clang::SourceRange, std::pair<const clang::BinaryOperator *,
+ const clang::BinaryOperator *>>>
+ Insertions;
+ const SourceManager &SM = *Result.SourceManager;
+ const clang::LangOptions &LO = Result.Context->getLangOpts();
+ addParantheses(BinOp, nullptr, this, SM, LO);
+}
+
+} // namespace clang::tidy::readability
clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.h
@@ -0,0 +1,34 @@
+//===--- MathMissingParenthesesCheck.h - clang-tidy -------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MATHMISSINGPARENTHESESCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MATHMISSINGPARENTHESESCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::readability {
+
+/// Check for mising parantheses in mathematical expressions that involve
+/// operators of different priorities.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability/math-missing-parentheses.html
+class MathMissingParenthesesCheck : public ClangTidyCheck {
+public:
+ MathMissingParenthesesCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+ std::optional<TraversalKind> getCheckTraversalKind() const override {
+ return TK_IgnoreUnlessSpelledInSource;
+ }
+};
+
+} // namespace clang::tidy::readability
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MATHMISSINGPARENTHESESCHECK_H
clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -32,6 +32,7 @@
#include "IsolateDeclarationCheck.h" #include "IsolateDeclarationCheck.h"
#include "MagicNumbersCheck.h" #include "MagicNumbersCheck.h"
#include "MakeMemberFunctionConstCheck.h" #include "MakeMemberFunctionConstCheck.h"
+#include "MathMissingParenthesesCheck.h"
#include "MisleadingIndentationCheck.h" #include "MisleadingIndentationCheck.h"
#include "MisplacedArrayIndexCheck.h" #include "MisplacedArrayIndexCheck.h"
#include "NamedParameterCheck.h" #include "NamedParameterCheck.h"
@@ -105,6 +106,8 @@ public:
"readability-identifier-naming"); "readability-identifier-naming");
CheckFactories.registerCheck<ImplicitBoolConversionCheck>( CheckFactories.registerCheck<ImplicitBoolConversionCheck>(
"readability-implicit-bool-conversion"); "readability-implicit-bool-conversion");
+ CheckFactories.registerCheck<MathMissingParenthesesCheck>(
+ "readability-math-missing-parentheses");
CheckFactories.registerCheck<RedundantInlineSpecifierCheck>( CheckFactories.registerCheck<RedundantInlineSpecifierCheck>(
"readability-redundant-inline-specifier"); "readability-redundant-inline-specifier");
CheckFactories.registerCheck<InconsistentDeclarationParameterNameCheck>( CheckFactories.registerCheck<InconsistentDeclarationParameterNameCheck>(
clang-tools-extra/clangd/CodeCompletionStrings.cpp
@@ -253,7 +253,7 @@ void getSignature(const CodeCompletionString &CCS, std::string *Signature,
if (!IncludeFunctionArguments && if (!IncludeFunctionArguments &&
ResultKind == CodeCompletionResult::RK_Declaration) ResultKind == CodeCompletionResult::RK_Declaration)
TruncateSnippetAt.emplace(Snippet->size()); TruncateSnippetAt.emplace(Snippet->size());
- LLVM_FALLTHROUGH;+ [[fallthrough]];
case CodeCompletionString::CK_RightParen: case CodeCompletionString::CK_RightParen:
case CodeCompletionString::CK_LeftBracket: case CodeCompletionString::CK_LeftBracket:
case CodeCompletionString::CK_RightBracket: case CodeCompletionString::CK_RightBracket:
clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -854,7 +854,7 @@ TEST_F(TargetDeclTest, DependentExprs) {
} }
}; };
)cpp"; )cpp";
- EXPECT_DECLS("CXXDependentScopeMemberExpr", "void foo()");+ EXPECT_DECLS("MemberExpr", "void foo()");
// Similar to above but base expression involves a function call. // Similar to above but base expression involves a function call.
Code = R"cpp( Code = R"cpp(
@@ -872,7 +872,7 @@ TEST_F(TargetDeclTest, DependentExprs) {
} }
}; };
)cpp"; )cpp";
- EXPECT_DECLS("CXXDependentScopeMemberExpr", "void foo()");+ EXPECT_DECLS("MemberExpr", "void foo()");
// Similar to above but uses a function pointer. // Similar to above but uses a function pointer.
Code = R"cpp( Code = R"cpp(
@@ -891,7 +891,7 @@ TEST_F(TargetDeclTest, DependentExprs) {
} }
}; };
)cpp"; )cpp";
- EXPECT_DECLS("CXXDependentScopeMemberExpr", "void foo()");+ EXPECT_DECLS("MemberExpr", "void foo()");
// Base expression involves a member access into this. // Base expression involves a member access into this.
Code = R"cpp( Code = R"cpp(
@@ -962,7 +962,7 @@ TEST_F(TargetDeclTest, DependentExprs) {
void Foo() { this->[[find]](); } void Foo() { this->[[find]](); }
}; };
)cpp"; )cpp";
- EXPECT_DECLS("CXXDependentScopeMemberExpr", "void find()");+ EXPECT_DECLS("MemberExpr", "void find()");
} }
TEST_F(TargetDeclTest, DependentTypes) { TEST_F(TargetDeclTest, DependentTypes) {
clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -621,7 +621,7 @@ sizeof...($TemplateParameter[[Elements]]);
struct $Class_def[[Foo]] { struct $Class_def[[Foo]] {
int $Field_decl[[Waldo]]; int $Field_decl[[Waldo]];
void $Method_def[[bar]]() { void $Method_def[[bar]]() {
- $Class[[Foo]]().$Field_dependentName[[Waldo]];+ $Class[[Foo]]().$Field[[Waldo]];
} }
template $Bracket[[<]]typename $TemplateParameter_def[[U]]$Bracket[[>]] template $Bracket[[<]]typename $TemplateParameter_def[[U]]$Bracket[[>]]
void $Method_def[[bar1]]() { void $Method_def[[bar1]]() {
clang-tools-extra/docs/ReleaseNotes.rst
@@ -100,13 +100,15 @@ Improvements to clang-tidy
- Improved :program:`run-clang-tidy.py` script. Added argument `-source-filter` - Improved :program:`run-clang-tidy.py` script. Added argument `-source-filter`
to filter source files from the compilation database, via a RegEx. In a to filter source files from the compilation database, via a RegEx. In a
similar fashion to what `-header-filter` does for header files. similar fashion to what `-header-filter` does for header files.
+
- Improved :program:`check_clang_tidy.py` script. Added argument `-export-fixes` - Improved :program:`check_clang_tidy.py` script. Added argument `-export-fixes`
to aid in clang-tidy and test development. to aid in clang-tidy and test development.
+
- Fixed bug where big values for unsigned check options overflowed into negative values - Fixed bug where big values for unsigned check options overflowed into negative values
- when being printed with ``--dump-config``.+ when being printed with `--dump-config`.
-- Fixed ``--verify-config`` option not properly parsing checks when using the +- Fixed `--verify-config` option not properly parsing checks when using the
- literal operator in the ``.clang-tidy`` config.+ literal operator in the `.clang-tidy` config.
New checks New checks
^^^^^^^^^^ ^^^^^^^^^^
@@ -131,6 +133,12 @@ New checks
to reading out-of-bounds data due to inadequate or incorrect string null to reading out-of-bounds data due to inadequate or incorrect string null
termination. termination.
+- New :doc:`modernize-min-max-use-initializer-list
+ <clang-tidy/checks/modernize/min-max-use-initializer-list>` check.
+
+ Replaces nested ``std::min`` and ``std::max`` calls with an initializer list
+ where applicable.
+
- New :doc:`modernize-use-designated-initializers - New :doc:`modernize-use-designated-initializers
<clang-tidy/checks/modernize/use-designated-initializers>` check. <clang-tidy/checks/modernize/use-designated-initializers>` check.
@@ -143,6 +151,12 @@ New checks
Enforces consistent style for enumerators' initialization, covering three Enforces consistent style for enumerators' initialization, covering three
styles: none, first only, or all initialized explicitly. styles: none, first only, or all initialized explicitly.
+- New :doc:`readability-math-missing-parentheses
+ <clang-tidy/checks/readability/math-missing-parentheses>` check.
+
+ Check for missing parentheses in mathematical expressions that involve
+ operators of different priorities.
+
- New :doc:`readability-use-std-min-max - New :doc:`readability-use-std-min-max
<clang-tidy/checks/readability/use-std-min-max>` check. <clang-tidy/checks/readability/use-std-min-max>` check.
@@ -224,7 +238,7 @@ Changes in existing checks
- Improved :doc:`google-explicit-constructor - Improved :doc:`google-explicit-constructor
<clang-tidy/checks/google/explicit-constructor>` check to better handle <clang-tidy/checks/google/explicit-constructor>` check to better handle
- ``C++-20`` `explicit(bool)`.+ C++20 `explicit(bool)`.
- Improved :doc:`google-global-names-in-headers - Improved :doc:`google-global-names-in-headers
<clang-tidy/checks/google/global-names-in-headers>` check by replacing the local <clang-tidy/checks/google/global-names-in-headers>` check by replacing the local
@@ -237,13 +251,18 @@ Changes in existing checks
check by ignoring other functions with same prefixes as the target specific check by ignoring other functions with same prefixes as the target specific
functions. functions.
+- Improved :doc:`linuxkernel-must-check-errs
+ <clang-tidy/checks/linuxkernel/must-check-errs>` check documentation to
+ consistently use the check's proper name.
+
- Improved :doc:`llvm-header-guard - Improved :doc:`llvm-header-guard
<clang-tidy/checks/llvm/header-guard>` check by replacing the local <clang-tidy/checks/llvm/header-guard>` check by replacing the local
option `HeaderFileExtensions` by the global option of the same name. option `HeaderFileExtensions` by the global option of the same name.
- Improved :doc:`misc-const-correctness - Improved :doc:`misc-const-correctness
<clang-tidy/checks/misc/const-correctness>` check by avoiding infinite recursion <clang-tidy/checks/misc/const-correctness>` check by avoiding infinite recursion
- for recursive forwarding reference.+ for recursive functions with forwarding reference parameters and reference
+ variables which refer to themselves.
- Improved :doc:`misc-definitions-in-headers - Improved :doc:`misc-definitions-in-headers
<clang-tidy/checks/misc/definitions-in-headers>` check by replacing the local <clang-tidy/checks/misc/definitions-in-headers>` check by replacing the local
@@ -269,6 +288,10 @@ Changes in existing checks
don't remove parentheses used in ``sizeof`` calls when they have array index don't remove parentheses used in ``sizeof`` calls when they have array index
accesses as arguments. accesses as arguments.
+- Improved :doc:`modernize-use-nullptr
+ <clang-tidy/checks/modernize/use-nullptr>` check to include support for C23,
+ which also has introduced the ``nullptr`` keyword.
+
- Improved :doc:`modernize-use-override - Improved :doc:`modernize-use-override
<clang-tidy/checks/modernize/use-override>` check to also remove any trailing <clang-tidy/checks/modernize/use-override>` check to also remove any trailing
whitespace when deleting the ``virtual`` keyword. whitespace when deleting the ``virtual`` keyword.
@@ -324,13 +347,9 @@ Miscellaneous
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
- Fixed incorrect formatting in :program:`clang-apply-replacements` when no - Fixed incorrect formatting in :program:`clang-apply-replacements` when no
- ``--format`` option is specified. Now :program:`clang-apply-replacements`+ `--format` option is specified. Now :program:`clang-apply-replacements`
applies formatting only with the option. applies formatting only with the option.
-- Fixed the :doc:`linuxkernel-must-check-errs
- <clang-tidy/checks/linuxkernel/must-check-errs>` documentation to consistently
- use the check's proper name.
-
Improvements to include-fixer Improvements to include-fixer
----------------------------- -----------------------------
clang-tools-extra/docs/clang-tidy/checks/cert/env33-c.rst
@@ -10,4 +10,4 @@ but does not actually attempt to execute a command.
This check corresponds to the CERT C Coding Standard rule This check corresponds to the CERT C Coding Standard rule
`ENV33-C. Do not call system() `ENV33-C. Do not call system()
-<https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=2130132>`_.+<https://www.securecoding.cert.org/confluence/display/c/ENV33-C.+Do+not+call+system()>`_.
clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -276,6 +276,7 @@ Clang-Tidy Checks
:doc:`modernize-macro-to-enum <modernize/macro-to-enum>`, "Yes" :doc:`modernize-macro-to-enum <modernize/macro-to-enum>`, "Yes"
:doc:`modernize-make-shared <modernize/make-shared>`, "Yes" :doc:`modernize-make-shared <modernize/make-shared>`, "Yes"
:doc:`modernize-make-unique <modernize/make-unique>`, "Yes" :doc:`modernize-make-unique <modernize/make-unique>`, "Yes"
+ :doc:`modernize-min-max-use-initializer-list <modernize/min-max-use-initializer-list>`, "Yes"
:doc:`modernize-pass-by-value <modernize/pass-by-value>`, "Yes" :doc:`modernize-pass-by-value <modernize/pass-by-value>`, "Yes"
:doc:`modernize-raw-string-literal <modernize/raw-string-literal>`, "Yes" :doc:`modernize-raw-string-literal <modernize/raw-string-literal>`, "Yes"
:doc:`modernize-redundant-void-arg <modernize/redundant-void-arg>`, "Yes" :doc:`modernize-redundant-void-arg <modernize/redundant-void-arg>`, "Yes"
@@ -363,6 +364,7 @@ Clang-Tidy Checks
:doc:`readability-isolate-declaration <readability/isolate-declaration>`, "Yes" :doc:`readability-isolate-declaration <readability/isolate-declaration>`, "Yes"
:doc:`readability-magic-numbers <readability/magic-numbers>`, :doc:`readability-magic-numbers <readability/magic-numbers>`,
:doc:`readability-make-member-function-const <readability/make-member-function-const>`, "Yes" :doc:`readability-make-member-function-const <readability/make-member-function-const>`, "Yes"
+ :doc:`readability-math-missing-parentheses <readability/math-missing-parentheses>`, "Yes"
:doc:`readability-misleading-indentation <readability/misleading-indentation>`, :doc:`readability-misleading-indentation <readability/misleading-indentation>`,
:doc:`readability-misplaced-array-index <readability/misplaced-array-index>`, "Yes" :doc:`readability-misplaced-array-index <readability/misplaced-array-index>`, "Yes"
:doc:`readability-named-parameter <readability/named-parameter>`, "Yes" :doc:`readability-named-parameter <readability/named-parameter>`, "Yes"
clang-tools-extra/docs/clang-tidy/checks/modernize/min-max-use-initializer-list.rst
@@ -0,0 +1,50 @@
+.. title:: clang-tidy - modernize-min-max-use-initializer-list
+
+modernize-min-max-use-initializer-list
+======================================
+
+Replaces nested ``std::min`` and ``std::max`` calls with an initializer list
+where applicable.
+
+For instance, consider the following code:
+
+.. code-block:: cpp
+
+ int a = std::max(std::max(i, j), k);
+
+The check will transform the above code to:
+
+.. code-block:: cpp
+
+ int a = std::max({i, j, k});
+
+Performance Considerations
+==========================
+
+While this check simplifies the code and makes it more readable, it may cause
+performance degradation for non-trivial types due to the need to copy objects
+into the initializer list.
+
+To avoid this, it is recommended to use `std::ref` or `std::cref` for
+non-trivial types:
+
+.. code-block:: cpp
+
+ std::string b = std::max({std::ref(i), std::ref(j), std::ref(k)});
+
+Options
+=======
+
+.. option:: IncludeStyle
+
+ A string specifying which include-style is used, `llvm` or `google`. Default
+ is `llvm`.
+
+.. option:: IgnoreNonTrivialTypes
+
+ A boolean specifying whether to ignore non-trivial types. Default is `true`.
+
+.. option:: IgnoreTrivialTypesOfSizeAbove
+
+ An integer specifying the size (in bytes) above which trivial types are
+ ignored. Default is `32`.
clang-tools-extra/docs/clang-tidy/checks/modernize/use-nullptr.rst
@@ -4,7 +4,7 @@ modernize-use-nullptr
===================== =====================
The check converts the usage of null pointer constants (e.g. ``NULL``, ``0``) The check converts the usage of null pointer constants (e.g. ``NULL``, ``0``)
-to use the new C++11 ``nullptr`` keyword.+to use the new C++11 and C23 ``nullptr`` keyword.
Example Example
------- -------
clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst
@@ -0,0 +1,27 @@
+.. title:: clang-tidy - readability-math-missing-parentheses
+
+readability-math-missing-parentheses
+====================================
+
+Check for missing parentheses in mathematical expressions that involve operators
+of different priorities.
+
+Parentheses in mathematical expressions clarify the order
+of operations, especially with different-priority operators. Lengthy or multiline
+expressions can obscure this order, leading to coding errors. IDEs can aid clarity
+by highlighting parentheses. Explicitly using parentheses also clarifies what the
+developer had in mind when writing the expression. Ensuring their presence reduces
+ambiguity and errors, promoting clearer and more maintainable code.
+
+Before:
+
+.. code-block:: c++
+
+ int x = 1 + 2 * 3 - 4 / 5;
+
+
+After:
+
+.. code-block:: c++
+
+ int x = 1 + (2 * 3) - (4 / 5);
clang-tools-extra/test/CMakeLists.txt
@@ -67,33 +67,30 @@ foreach(dep ${LLVM_UTILS_DEPS})
endif() endif()
endforeach() endforeach()
-if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)+if (NOT WIN32 OR NOT LLVM_LINK_LLVM_DYLIB)
- if (NOT WIN32 OR NOT LLVM_LINK_LLVM_DYLIB)+ llvm_add_library(
- llvm_add_library(+ CTTestTidyModule
- CTTestTidyModule+ MODULE clang-tidy/CTTestTidyModule.cpp
- MODULE clang-tidy/CTTestTidyModule.cpp+ PLUGIN_TOOL clang-tidy)
- PLUGIN_TOOL clang-tidy+endif()
- DEPENDS clang-tidy-headers)
- endif()
- if(CLANG_BUILT_STANDALONE)+if(CLANG_BUILT_STANDALONE)
- # LLVMHello library is needed below+ # LLVMHello library is needed below
- if (EXISTS ${LLVM_MAIN_SRC_DIR}/lib/Transforms/Hello+ if (EXISTS ${LLVM_MAIN_SRC_DIR}/lib/Transforms/Hello
- AND NOT TARGET LLVMHello)+ AND NOT TARGET LLVMHello)
- add_subdirectory(${LLVM_MAIN_SRC_DIR}/lib/Transforms/Hello+ add_subdirectory(${LLVM_MAIN_SRC_DIR}/lib/Transforms/Hello
- lib/Transforms/Hello)+ lib/Transforms/Hello)
- endif()
endif() endif()
+endif()
- if(TARGET CTTestTidyModule)+if(TARGET CTTestTidyModule)
- list(APPEND CLANG_TOOLS_TEST_DEPS CTTestTidyModule LLVMHello)+ list(APPEND CLANG_TOOLS_TEST_DEPS CTTestTidyModule LLVMHello)
- target_include_directories(CTTestTidyModule PUBLIC BEFORE "${CLANG_TOOLS_SOURCE_DIR}")+ target_include_directories(CTTestTidyModule PUBLIC BEFORE "${CLANG_TOOLS_SOURCE_DIR}")
- if(CLANG_PLUGIN_SUPPORT AND (WIN32 OR CYGWIN))+ if(CLANG_PLUGIN_SUPPORT AND (WIN32 OR CYGWIN))
- set(LLVM_LINK_COMPONENTS+ set(LLVM_LINK_COMPONENTS
- Support+ Support
- )+ )
- endif()+ endif()
- endif()
endif() endif()
add_lit_testsuite(check-clang-extra "Running clang-tools-extra/test" add_lit_testsuite(check-clang-extra "Running clang-tools-extra/test"
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/owning-memory.cpp
@@ -309,6 +309,8 @@ struct HeapArray { // Ok, since destruc
HeapArray(HeapArray &&other) : _data(other._data), size(other.size) { // Ok HeapArray(HeapArray &&other) : _data(other._data), size(other.size) { // Ok
other._data = nullptr; // Ok other._data = nullptr; // Ok
+ // CHECK-NOTES: [[@LINE-1]]:5: warning: expected assignment source to be of type 'gsl::owner<>'; got 'std::nullptr_t'
+ // FIXME: This warning is emitted because an ImplicitCastExpr for the NullToPointer conversion isn't created for dependent types.
other.size = 0; other.size = 0;
} }
clang-tools-extra/test/clang-tidy/checkers/modernize/min-max-use-initializer-list.cpp
@@ -0,0 +1,305 @@
+// RUN: %check_clang_tidy %s modernize-min-max-use-initializer-list %t
+
+// CHECK-FIXES: #include <algorithm>
+namespace utils {
+template <typename T>
+T max(T a, T b) {
+ return (a < b) ? b : a;
+}
+} // namespace utils
+
+namespace std {
+template< class T >
+struct initializer_list {
+ initializer_list()=default;
+ initializer_list(T*,int){}
+ const T* begin() const {return nullptr;}
+ const T* end() const {return nullptr;}
+};
+
+template<class ForwardIt>
+ForwardIt min_element(ForwardIt first, ForwardIt last)
+{
+ if (first == last)
+ return last;
+
+ ForwardIt smallest = first;
+
+ while (++first != last)
+ if (*first < *smallest)
+ smallest = first;
+
+ return smallest;
+}
+
+template<class ForwardIt, class Compare>
+ForwardIt min_element(ForwardIt first, ForwardIt last, Compare comp)
+{
+ if (first == last)
+ return last;
+
+ ForwardIt smallest = first;
+
+ while (++first != last)
+ if (comp(*first, *smallest))
+ smallest = first;
+
+ return smallest;
+}
+
+template<class ForwardIt>
+ForwardIt max_element(ForwardIt first, ForwardIt last)
+{
+ if (first == last)
+ return last;
+
+ ForwardIt largest = first;
+
+ while (++first != last)
+ if (*largest < *first)
+ largest = first;
+
+ return largest;
+}
+
+template<class ForwardIt, class Compare>
+ForwardIt max_element(ForwardIt first, ForwardIt last, Compare comp)
+{
+ if (first == last)
+ return last;
+
+ ForwardIt largest = first;
+
+ while(++first != last)
+ if (comp(*largest, *first))
+ largest = first;
+
+ return largest;
+}
+
+template< class T >
+const T& max( const T& a, const T& b ) {
+ return (a < b) ? b : a;
+};
+
+template< class T >
+T max(std::initializer_list<T> ilist)
+{
+ return *std::max_element(ilist.begin(), ilist.end());
+}
+
+template< class T, class Compare >
+const T& max( const T& a, const T& b, Compare comp ) {
+ return (comp(a, b)) ? b : a;
+};
+
+template< class T, class Compare >
+T max(std::initializer_list<T> ilist, Compare comp) {
+ return *std::max_element(ilist.begin(), ilist.end(), comp);
+};
+
+template< class T >
+const T& min( const T& a, const T& b ) {
+ return (b < a) ? b : a;
+};
+
+template< class T >
+T min(std::initializer_list<T> ilist)
+{
+ return *std::min_element(ilist.begin(), ilist.end());
+}
+
+
+template< class T, class Compare >
+const T& min( const T& a, const T& b, Compare comp ) {
+ return (comp(b, a)) ? b : a;
+};
+
+template< class T, class Compare >
+T min(std::initializer_list<T> ilist, Compare comp) {
+ return *std::min_element(ilist.begin(), ilist.end(), comp);
+};
+
+} // namespace std
+
+using namespace std;
+
+namespace {
+bool fless_than(int a, int b) {
+return a < b;
+}
+
+bool fgreater_than(int a, int b) {
+return a > b;
+}
+auto less_than = [](int a, int b) { return a < b; };
+auto greater_than = [](int a, int b) { return a > b; };
+
+int max1 = std::max(1, std::max(2, 3));
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int max1 = std::max({1, 2, 3});
+
+int min1 = std::min(1, std::min(2, 3));
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use nested 'std::min' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int min1 = std::min({1, 2, 3});
+
+int max2 = std::max(1, std::max(2, std::max(3, 4)));
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int max2 = std::max({1, 2, 3, 4});
+
+int max2b = std::max(std::max(std::max(1, 2), std::max(3, 4)), std::max(std::max(5, 6), std::max(7, 8)));
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int max2b = std::max({1, 2, 3, 4, 5, 6, 7, 8});
+
+int max2c = std::max(std::max(1, std::max(2, 3)), 4);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int max2c = std::max({1, 2, 3, 4});
+
+int max2d = std::max(std::max({1, 2, 3}), 4);
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int max2d = std::max({1, 2, 3, 4});
+
+
+int max2e = std::max(1, max(2, max(3, 4)));
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int max2e = std::max({1, 2, 3, 4});
+
+int min2 = std::min(1, std::min(2, std::min(3, 4)));
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use nested 'std::min' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int min2 = std::min({1, 2, 3, 4});
+
+int max3 = std::max(std::max(4, 5), std::min(2, std::min(3, 1)));
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-MESSAGES: :[[@LINE-2]]:37: warning: do not use nested 'std::min' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int max3 = std::max({4, 5, std::min({2, 3, 1})});
+
+int min3 = std::min(std::min(4, 5), std::max(2, std::max(3, 1)));
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use nested 'std::min' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-MESSAGES: :[[@LINE-2]]:37: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int min3 = std::min({4, 5, std::max({2, 3, 1})});
+
+int max4 = std::max(1, std::max(2, 3, greater_than), less_than);
+// CHECK-FIXES: int max4 = std::max(1, std::max(2, 3, greater_than), less_than);
+
+int min4 = std::min(1, std::min(2, 3, greater_than), less_than);
+// CHECK-FIXES: int min4 = std::min(1, std::min(2, 3, greater_than), less_than);
+
+int max5 = std::max(1, std::max(2, 3), less_than);
+// CHECK-FIXES: int max5 = std::max(1, std::max(2, 3), less_than);
+
+int min5 = std::min(1, std::min(2, 3), less_than);
+// CHECK-FIXES: int min5 = std::min(1, std::min(2, 3), less_than);
+
+int max6 = std::max(1, std::max(2, 3, greater_than), greater_than);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int max6 = std::max({1, 2, 3 }, greater_than);
+
+int min6 = std::min(1, std::min(2, 3, greater_than), greater_than);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use nested 'std::min' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int min6 = std::min({1, 2, 3 }, greater_than);
+
+int max7 = std::max(1, std::max(2, 3, fless_than), fgreater_than);
+// CHECK-FIXES: int max7 = std::max(1, std::max(2, 3, fless_than), fgreater_than);
+
+int min7 = std::min(1, std::min(2, 3, fless_than), fgreater_than);
+// CHECK-FIXES: int min7 = std::min(1, std::min(2, 3, fless_than), fgreater_than);
+
+int max8 = std::max(1, std::max(2, 3, fless_than), less_than);
+// CHECK-FIXES: int max8 = std::max(1, std::max(2, 3, fless_than), less_than)
+
+int min8 = std::min(1, std::min(2, 3, fless_than), less_than);
+// CHECK-FIXES: int min8 = std::min(1, std::min(2, 3, fless_than), less_than);
+
+int max9 = std::max(1, std::max(2, 3, fless_than), fless_than);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int max9 = std::max({1, 2, 3 }, fless_than);
+
+int min9 = std::min(1, std::min(2, 3, fless_than), fless_than);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use nested 'std::min' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int min9 = std::min({1, 2, 3 }, fless_than);
+
+int min10 = std::min(std::min(4, 5), std::max(2, utils::max(3, 1)));
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use nested 'std::min' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int min10 = std::min({4, 5, std::max(2, utils::max(3, 1))});
+
+int max10 = std::max({std::max(1, 2), std::max({5, 6, 1}), 2, std::min({1, 2, 4})});
+// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int max10 = std::max({1, 2, 5, 6, 1, 2, std::min({1, 2, 4})});
+
+int typecastTest = std::max(std::max<int>(0U, 0.0f), 0);
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int typecastTest = std::max({static_cast<int>(0U), static_cast<int>(0.0f), 0});
+
+int typecastTest1 = std::max(std::max<long>(0U, 0.0f), 0L);
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int typecastTest1 = std::max({static_cast<long>(0U), static_cast<long>(0.0f), 0L});
+
+int typecastTest2 = std::max(std::max<int>(10U, 20.0f), 30);
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int typecastTest2 = std::max({static_cast<int>(10U), static_cast<int>(20.0f), 30});
+
+int typecastTest3 = std::max(std::max<int>(0U, std::max<int>(0.0f, 1.0f)), 0);
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int typecastTest3 = std::max({static_cast<int>(0U), static_cast<int>(0.0f), static_cast<int>(1.0f), 0});
+
+#define max3f(a, b, c) std::max(a, std::max(b, c))
+// CHECK-FIXES: #define max3f(a, b, c) std::max(a, std::max(b, c))
+
+#define value 4545
+int macroVarMax = std::max(value, std::max(1, 2));
+// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int macroVarMax = std::max({value, 1, 2});
+
+#define value2 45U
+int macroVarMax2 = std::max(1, std::max<int>(value2, 2.0f));
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: do not use nested 'std::max' calls, use an initializer list instead [modernize-min-max-use-initializer-list]
+// CHECK-FIXES: int macroVarMax2 = std::max({1, static_cast<int>(value2), static_cast<int>(2.0f)});
+
+// True-negative tests
+int maxTN1 = std::max(1, 2);
+// CHECK-FIXES: int maxTN1 = std::max(1, 2);
+
+int maxTN2 = std::max({1, 2, 3});
+// CHECK-FIXES: int maxTN2 = std::max({1, 2, 3});
+
+int maxTN3 = std::max({1, 2, 3}, less_than);
+// CHECK-FIXES: int maxTN3 = std::max({1, 2, 3}, less_than);
+
+// non-trivial types
+struct A {
+ int a;
+ A(int a) : a(a) {}
+ bool operator<(const A &rhs) const { return a < rhs.a; }
+};
+
+A maxNT1 = std::max(A(1), A(2));
+// CHECK-FIXES: A maxNT1 = std::max(A(1), A(2));
+
+A maxNT2 = std::max(A(1), std::max(A(2), A(3)));
+// CHECK-FIXES: A maxNT2 = std::max(A(1), std::max(A(2), A(3)));
+
+A maxNT3 = std::max(A(1), std::max(A(2), A(3)), [](const A &lhs, const A &rhs) { return lhs.a < rhs.a; });
+// CHECK-FIXES: A maxNT3 = std::max(A(1), std::max(A(2), A(3)), [](const A &lhs, const A &rhs) { return lhs.a < rhs.a; });
+
+// Trivial type with size greater than 32
+struct B {
+ // 9*4 = 36 bytes > 32 bytes
+ int a[9];
+
+ bool operator<(const B& rhs) const {
+ return a[0] < rhs.a[0];
+ }
+};
+
+B maxTT1 = std::max(B(), B());
+// CHECK-FIXES: B maxTT1 = std::max(B(), B());
+
+B maxTT2 = std::max(B(), std::max(B(), B()));
+// CHECK-FIXES: B maxTT2 = std::max(B(), std::max(B(), B()));
+
+B maxTT3 = std::max(B(), std::max(B(), B()), [](const B &lhs, const B &rhs) { return lhs.a[0] < rhs.a[0]; });
+// CHECK-FIXES: B maxTT3 = std::max(B(), std::max(B(), B()), [](const B &lhs, const B &rhs) { return lhs.a[0] < rhs.a[0]; });
+
+
+} // namespace
+
clang-tools-extra/test/clang-tidy/checkers/modernize/use-equals-default-copy.cpp
@@ -260,6 +260,8 @@ template <class T>
struct Template { struct Template {
Template() = default; Template() = default;
Template(const Template &Other) : Field(Other.Field) {} Template(const Template &Other) : Field(Other.Field) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+ // CHECK-FIXES: Template(const Template &Other) = default;
Template &operator=(const Template &Other); Template &operator=(const Template &Other);
void foo(const T &t); void foo(const T &t);
int Field; int Field;
@@ -269,8 +271,12 @@ Template<T> &Template<T>::operator=(const Template<T> &Other) {
Field = Other.Field; Field = Other.Field;
return *this; return *this;
} }
+// CHECK-MESSAGES: :[[@LINE-4]]:27: warning: use '= default'
+// CHECK-FIXES: Template<T> &Template<T>::operator=(const Template<T> &Other) = default;
+
Template<int> T1; Template<int> T1;
+
// Dependent types. // Dependent types.
template <class T> template <class T>
struct DT1 { struct DT1 {
@@ -284,6 +290,9 @@ DT1<T> &DT1<T>::operator=(const DT1<T> &Other) {
Field = Other.Field; Field = Other.Field;
return *this; return *this;
} }
+// CHECK-MESSAGES: :[[@LINE-4]]:17: warning: use '= default'
+// CHECK-FIXES: DT1<T> &DT1<T>::operator=(const DT1<T> &Other) = default;
+
DT1<int> Dt1; DT1<int> Dt1;
template <class T> template <class T>
@@ -303,6 +312,9 @@ DT2<T> &DT2<T>::operator=(const DT2<T> &Other) {
struct T { struct T {
typedef int TT; typedef int TT;
}; };
+// CHECK-MESSAGES: :[[@LINE-8]]:17: warning: use '= default'
+// CHECK-FIXES: DT2<T> &DT2<T>::operator=(const DT2<T> &Other) = default;
+
DT2<T> Dt2; DT2<T> Dt2;
// Default arguments. // Default arguments.
clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-c23.c
@@ -0,0 +1,139 @@
+// RUN: %check_clang_tidy %s modernize-use-nullptr %t -- -- -std=c23
+
+#define NULL 0
+
+void test_assignment() {
+ int *p1 = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr [modernize-use-nullptr]
+ // CHECK-FIXES: int *p1 = nullptr;
+ p1 = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use nullptr
+ // CHECK-FIXES: p1 = nullptr;
+
+ int *p2 = NULL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr
+ // CHECK-FIXES: int *p2 = nullptr;
+
+ p2 = p1;
+ // CHECK-FIXES: p2 = p1;
+
+ const int null = 0;
+ int *p3 = &null;
+
+ p3 = NULL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use nullptr
+ // CHECK-FIXES: p3 = nullptr;
+
+ int *p4 = p3;
+
+ int i1 = 0;
+
+ int i2 = NULL;
+
+ int i3 = null;
+
+ int *p5, *p6, *p7;
+ p5 = p6 = p7 = NULL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr
+ // CHECK-FIXES: p5 = p6 = p7 = nullptr;
+}
+
+void test_function(int *p) {}
+
+void test_function_no_ptr_param(int i) {}
+
+void test_function_call() {
+ test_function(0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr
+ // CHECK-FIXES: test_function(nullptr);
+
+ test_function(NULL);
+ // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr
+ // CHECK-FIXES: test_function(nullptr);
+
+ test_function_no_ptr_param(0);
+}
+
+char *test_function_return1() {
+ return 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr
+ // CHECK-FIXES: return nullptr;
+}
+
+void *test_function_return2() {
+ return NULL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr
+ // CHECK-FIXES: return nullptr;
+}
+
+int test_function_return4() {
+ return 0;
+}
+
+int test_function_return5() {
+ return NULL;
+}
+
+int *test_function_return_cast1() {
+ return(int)0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr
+ // CHECK-FIXES: return nullptr;
+}
+
+int *test_function_return_cast2() {
+#define RET return
+ RET(int)0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use nullptr
+ // CHECK-FIXES: RET nullptr;
+#undef RET
+}
+
+// Test parentheses expressions resulting in a nullptr.
+int *test_parentheses_expression1() {
+ return(0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr
+ // CHECK-FIXES: return(nullptr);
+}
+
+int *test_parentheses_expression2() {
+ return((int)(0.0f));
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr
+ // CHECK-FIXES: return(nullptr);
+}
+
+int *test_nested_parentheses_expression() {
+ return((((0))));
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr
+ // CHECK-FIXES: return((((nullptr))));
+}
+
+void test_const_pointers() {
+ const int *const_p1 = 0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr
+ // CHECK-FIXES: const int *const_p1 = nullptr;
+ const int *const_p2 = NULL;
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr
+ // CHECK-FIXES: const int *const_p2 = nullptr;
+ const int *const_p3 = (int)0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr
+ // CHECK-FIXES: const int *const_p3 = nullptr;
+ const int *const_p4 = (int)0.0f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr
+ // CHECK-FIXES: const int *const_p4 = nullptr;
+}
+
+void test_nested_implicit_cast_expr() {
+ int func0(void*, void*);
+ int func1(int, void*, void*);
+
+ (double)func1(0, 0, 0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use nullptr
+ // CHECK-MESSAGES: :[[@LINE-2]]:23: warning: use nullptr
+ // CHECK-FIXES: (double)func1(0, nullptr, nullptr);
+ (double)func1(func0(0, 0), 0, 0);
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: use nullptr
+ // CHECK-MESSAGES: :[[@LINE-2]]:26: warning: use nullptr
+ // CHECK-MESSAGES: :[[@LINE-3]]:30: warning: use nullptr
+ // CHECK-MESSAGES: :[[@LINE-4]]:33: warning: use nullptr
+ // CHECK-FIXES: (double)func1(func0(nullptr, nullptr), nullptr, nullptr);
+}
clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr.c
@@ -1,4 +1,4 @@
-// RUN: clang-tidy %s -checks=-*,modernize-use-nullptr -- | count 0+// RUN: clang-tidy %s -checks=-*,modernize-use-nullptr -- -std=c17 | count 0
// Note: this test expects no diagnostics, but FileCheck cannot handle that, // Note: this test expects no diagnostics, but FileCheck cannot handle that,
// hence the use of | count 0. // hence the use of | count 0.
clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp
@@ -0,0 +1,142 @@
+// RUN: %check_clang_tidy %s readability-math-missing-parentheses %t
+
+#define MACRO_AND &
+#define MACRO_ADD +
+#define MACRO_OR |
+#define MACRO_MULTIPLY *
+#define MACRO_XOR ^
+#define MACRO_SUBTRACT -
+#define MACRO_DIVIDE /
+
+int foo(){
+ return 5;
+}
+
+int bar(){
+ return 4;
+}
+
+int sink(int);
+#define FUN(ARG) (sink(ARG))
+#define FUN2(ARG) sink((ARG))
+#define FUN3(ARG) sink(ARG)
+#define FUN4(ARG) sink(1 + ARG)
+#define FUN5(ARG) sink(4 * ARG)
+
+class fun{
+public:
+ int A;
+ double B;
+ fun(){
+ A = 5;
+ B = 5.4;
+ }
+};
+
+void f(){
+ //CHECK-MESSAGES: :[[@LINE+2]]:17: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-FIXES: int a = 1 + (2 * 3);
+ int a = 1 + 2 * 3;
+
+ int a_negative = 1 + (2 * 3); // No warning
+
+ int b = 1 + 2 + 3; // No warning
+
+ int c = 1 * 2 * 3; // No warning
+
+ //CHECK-MESSAGES: :[[@LINE+3]]:17: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-MESSAGES: :[[@LINE+2]]:25: warning: '/' has higher precedence than '-'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-FIXES: int d = 1 + (2 * 3) - (4 / 5);
+ int d = 1 + 2 * 3 - 4 / 5;
+
+ int d_negative = 1 + (2 * 3) - (4 / 5); // No warning
+
+ //CHECK-MESSAGES: :[[@LINE+4]]:13: warning: '&' has higher precedence than '|'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-MESSAGES: :[[@LINE+3]]:17: warning: '+' has higher precedence than '&'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-MESSAGES: :[[@LINE+2]]:25: warning: '*' has higher precedence than '|'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-FIXES: int e = (1 & (2 + 3)) | (4 * 5);
+ int e = 1 & 2 + 3 | 4 * 5;
+
+ int e_negative = (1 & (2 + 3)) | (4 * 5); // No warning
+
+ //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-FIXES: int f = (1 * -2) + 4;
+ int f = 1 * -2 + 4;
+
+ int f_negative = (1 * -2) + 4; // No warning
+
+ //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-FIXES: int g = (1 * 2 * 3) + 4 + 5;
+ int g = 1 * 2 * 3 + 4 + 5;
+
+ int g_negative = (1 * 2 * 3) + 4 + 5; // No warning
+
+ //CHECK-MESSAGES: :[[@LINE+4]]:13: warning: '&' has higher precedence than '|'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-MESSAGES: :[[@LINE+3]]:19: warning: '+' has higher precedence than '&'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-MESSAGES: :[[@LINE+2]]:27: warning: '*' has higher precedence than '|'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-FIXES: int h = (120 & (2 + 3)) | (22 * 5);
+ int h = 120 & 2 + 3 | 22 * 5;
+
+ int h_negative = (120 & (2 + 3)) | (22 * 5); // No warning
+
+ int i = 1 & 2 & 3; // No warning
+
+ int j = 1 | 2 | 3; // No warning
+
+ int k = 1 ^ 2 ^ 3; // No warning
+
+ //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '+' has higher precedence than '^'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-FIXES: int l = (1 + 2) ^ 3;
+ int l = 1 + 2 ^ 3;
+
+ int l_negative = (1 + 2) ^ 3; // No warning
+
+ //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-FIXES: int m = (2 * foo()) + bar();
+ int m = 2 * foo() + bar();
+
+ int m_negative = (2 * foo()) + bar(); // No warning
+
+ //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-FIXES: int n = (1.05 * foo()) + double(bar());
+ int n = 1.05 * foo() + double(bar());
+
+ int n_negative = (1.05 * foo()) + double(bar()); // No warning
+
+ //CHECK-MESSAGES: :[[@LINE+3]]:17: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-FIXES: int o = 1 + (obj.A * 3) + obj.B;
+ fun obj;
+ int o = 1 + obj.A * 3 + obj.B;
+
+ int o_negative = 1 + (obj.A * 3) + obj.B; // No warning
+
+ //CHECK-MESSAGES: :[[@LINE+2]]:18: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-FIXES: int p = 1U + (2 * 3);
+ int p = 1U + 2 * 3;
+
+ int p_negative = 1U + (2 * 3); // No warning
+
+ //CHECK-MESSAGES: :[[@LINE+7]]:13: warning: '+' has higher precedence than '|'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-MESSAGES: :[[@LINE+6]]:25: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-MESSAGES: :[[@LINE+5]]:53: warning: '&' has higher precedence than '^'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-MESSAGES: :[[@LINE+4]]:53: warning: '^' has higher precedence than '|'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-MESSAGES: :[[@LINE+3]]:77: warning: '-' has higher precedence than '^'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-MESSAGES: :[[@LINE+2]]:94: warning: '/' has higher precedence than '-'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ //CHECK-FIXES: int q = (1 MACRO_ADD (2 MACRO_MULTIPLY 3)) MACRO_OR ((4 MACRO_AND 5) MACRO_XOR (6 MACRO_SUBTRACT (7 MACRO_DIVIDE 8)));
+ int q = 1 MACRO_ADD 2 MACRO_MULTIPLY 3 MACRO_OR 4 MACRO_AND 5 MACRO_XOR 6 MACRO_SUBTRACT 7 MACRO_DIVIDE 8; // No warning
+
+ //CHECK-MESSAGES: :[[@LINE+1]]:21: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ int r = FUN(0 + 1 * 2);
+
+ //CHECK-MESSAGES: :[[@LINE+1]]:22: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ int s = FUN2(0 + 1 * 2);
+
+ //CHECK-MESSAGES: :[[@LINE+1]]:22: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ int t = FUN3(0 + 1 * 2);
+
+ //CHECK-MESSAGES: :[[@LINE+1]]:18: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ int u = FUN4(1 * 2);
+
+ //CHECK-MESSAGES: :[[@LINE+1]]:13: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+ int v = FUN5(0 + 1);
+}
clang-tools-extra/test/lit.site.cfg.py.in
@@ -10,7 +10,7 @@ config.python_executable = "@Python3_EXECUTABLE@"
config.target_triple = "@LLVM_TARGET_TRIPLE@" config.target_triple = "@LLVM_TARGET_TRIPLE@"
config.host_triple = "@LLVM_HOST_TRIPLE@" config.host_triple = "@LLVM_HOST_TRIPLE@"
config.clang_tidy_staticanalyzer = @CLANG_TIDY_ENABLE_STATIC_ANALYZER@ config.clang_tidy_staticanalyzer = @CLANG_TIDY_ENABLE_STATIC_ANALYZER@
-config.has_plugins = @CLANG_PLUGIN_SUPPORT@ & ~@LLVM_INSTALL_TOOLCHAIN_ONLY@+config.has_plugins = @CLANG_PLUGIN_SUPPORT@
# Support substitution of the tools and libs dirs with user parameters. This is # Support substitution of the tools and libs dirs with user parameters. This is
# used when we can't determine the tool dir at configuration time. # used when we can't determine the tool dir at configuration time.
config.llvm_tools_dir = lit_config.substitute("@LLVM_TOOLS_DIR@") config.llvm_tools_dir = lit_config.substitute("@LLVM_TOOLS_DIR@")
clang-tools-extra/test/pp-trace/pp-trace-pragma-general.cpp
@@ -21,6 +21,12 @@ void foo() {
// CHECK: --- // CHECK: ---
// CHECK-NEXT: - Callback: PragmaDirective // CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT: Loc: "<built-in>:{{.+}}:1"
+// CHECK-NEXT: Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT: Loc: "<built-in>:{{.+}}:1"
+// CHECK-NEXT: Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaDirective
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:3:1" // CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-general.cpp:3:1"
// CHECK-NEXT: Introducer: PIK_HashPragma // CHECK-NEXT: Introducer: PIK_HashPragma
// CHECK-NEXT: - Callback: PragmaDiagnosticPush // CHECK-NEXT: - Callback: PragmaDiagnosticPush
clang-tools-extra/test/pp-trace/pp-trace-pragma-ms.cpp
@@ -18,6 +18,12 @@
// CHECK: --- // CHECK: ---
// CHECK-NEXT: - Callback: PragmaDirective // CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT: Loc: "<built-in>:{{.+}}:1"
+// CHECK-NEXT: Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT: Loc: "<built-in>:{{.+}}:1"
+// CHECK-NEXT: Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaDirective
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:3:1" // CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:3:1"
// CHECK-NEXT: Introducer: PIK_HashPragma // CHECK-NEXT: Introducer: PIK_HashPragma
// CHECK-NEXT: - Callback: PragmaComment // CHECK-NEXT: - Callback: PragmaComment
@@ -67,7 +73,7 @@
// CHECK-NEXT: Introducer: PIK_HashPragma // CHECK-NEXT: Introducer: PIK_HashPragma
// CHECK-NEXT: - Callback: PragmaMessage // CHECK-NEXT: - Callback: PragmaMessage
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:13:9" // CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-ms.cpp:13:9"
-// CHECK-NEXT: Namespace: +// CHECK-NEXT: Namespace:
// CHECK-NEXT: Kind: PMK_Message // CHECK-NEXT: Kind: PMK_Message
// CHECK-NEXT: Str: message argument // CHECK-NEXT: Str: message argument
// CHECK-NEXT: - Callback: PragmaDirective // CHECK-NEXT: - Callback: PragmaDirective
clang-tools-extra/test/pp-trace/pp-trace-pragma-opencl.cpp
@@ -6,6 +6,12 @@
// CHECK: --- // CHECK: ---
// CHECK-NEXT: - Callback: PragmaDirective // CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT: Loc: "<built-in>:{{.+}}:1"
+// CHECK-NEXT: Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaDirective
+// CHECK-NEXT: Loc: "<built-in>:{{.+}}:1"
+// CHECK-NEXT: Introducer: PIK_HashPragma
+// CHECK-NEXT: - Callback: PragmaDirective
// CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-opencl.cpp:3:1" // CHECK-NEXT: Loc: "{{.*}}{{[/\\]}}pp-trace-pragma-opencl.cpp:3:1"
// CHECK-NEXT: Introducer: PIK_HashPragma // CHECK-NEXT: Introducer: PIK_HashPragma
// CHECK-NEXT: - Callback: PragmaOpenCLExtension // CHECK-NEXT: - Callback: PragmaOpenCLExtension
clang/CMakeLists.txt
@@ -166,6 +166,10 @@ if(CLANG_ENABLE_LIBXML2)
endif() endif()
if(CLANG_ENABLE_CIR) if(CLANG_ENABLE_CIR)
+ if (CLANG_BUILT_STANDALONE)
+ message(FATAL_ERROR
+ "ClangIR is not yet supported in the standalone build.")
+ endif()
if (NOT "${LLVM_ENABLE_PROJECTS}" MATCHES "MLIR|mlir") if (NOT "${LLVM_ENABLE_PROJECTS}" MATCHES "MLIR|mlir")
message(FATAL_ERROR message(FATAL_ERROR
"Cannot build ClangIR without MLIR in LLVM_ENABLE_PROJECTS") "Cannot build ClangIR without MLIR in LLVM_ENABLE_PROJECTS")
clang/cmake/caches/Release.cmake
@@ -1,95 +1,94 @@
# Plain options configure the first build. # Plain options configure the first build.
# BOOTSTRAP_* options configure the second build. # BOOTSTRAP_* options configure the second build.
# BOOTSTRAP_BOOTSTRAP_* options configure the third build. # BOOTSTRAP_BOOTSTRAP_* options configure the third build.
+# PGO Builds have 3 stages (stage1, stage2-instrumented, stage2)
+# non-PGO Builds have 2 stages (stage1, stage2)
-# General Options+
+function (set_final_stage_var name value type)
+ if (LLVM_RELEASE_ENABLE_PGO)
+ set(BOOTSTRAP_BOOTSTRAP_${name} ${value} CACHE ${type} "")
+ else()
+ set(BOOTSTRAP_${name} ${value} CACHE ${type} "")
+ endif()
+endfunction()
+
+function (set_instrument_and_final_stage_var name value type)
+ # This sets the varaible for the final stage in non-PGO builds and in
+ # the stage2-instrumented stage for PGO builds.
+ set(BOOTSTRAP_${name} ${value} CACHE ${type} "")
+ if (LLVM_RELEASE_ENABLE_PGO)
+ # Set the variable in the final stage for PGO builds.
+ set(BOOTSTRAP_BOOTSTRAP_${name} ${value} CACHE ${type} "")
+ endif()
+endfunction()
+
+# General Options:
+# If you want to override any of the LLVM_RELEASE_* variables you can set them
+# on the command line via -D, but you need to do this before you pass this
+# cache file to CMake via -C. e.g.
+#
+# cmake -D LLVM_RELEASE_ENABLE_PGO=ON -C Release.cmake
set(LLVM_RELEASE_ENABLE_LTO THIN CACHE STRING "") set(LLVM_RELEASE_ENABLE_LTO THIN CACHE STRING "")
set(LLVM_RELEASE_ENABLE_PGO OFF CACHE BOOL "") set(LLVM_RELEASE_ENABLE_PGO OFF CACHE BOOL "")
-+set(LLVM_RELEASE_ENABLE_RUNTIMES "compiler-rt;libcxx;libcxxabi;libunwind" CACHE STRING "")
+set(LLVM_RELEASE_ENABLE_PROJECTS "clang;lld;lldb;clang-tools-extra;bolt;polly;mlir;flang" CACHE STRING "")
+# Note we don't need to add install here, since it is one of the pre-defined
+# steps.
+set(LLVM_RELEASE_FINAL_STAGE_TARGETS "clang;package;check-all;check-llvm;check-clang" CACHE STRING "")
set(CMAKE_BUILD_TYPE RELEASE CACHE STRING "") set(CMAKE_BUILD_TYPE RELEASE CACHE STRING "")
-# Stage 1 Bootstrap Setup+# Stage 1 Options
+set(LLVM_TARGETS_TO_BUILD Native CACHE STRING "")
set(CLANG_ENABLE_BOOTSTRAP ON CACHE BOOL "") set(CLANG_ENABLE_BOOTSTRAP ON CACHE BOOL "")
+
+set(STAGE1_PROJECTS "clang")
+set(STAGE1_RUNTIMES "")
+
if (LLVM_RELEASE_ENABLE_PGO) if (LLVM_RELEASE_ENABLE_PGO)
+ list(APPEND STAGE1_PROJECTS "lld")
+ list(APPEND STAGE1_RUNTIMES "compiler-rt")
set(CLANG_BOOTSTRAP_TARGETS set(CLANG_BOOTSTRAP_TARGETS
generate-profdata generate-profdata
- stage2
stage2-package stage2-package
stage2-clang stage2-clang
- stage2-distribution
stage2-install stage2-install
- stage2-install-distribution
- stage2-install-distribution-toolchain
stage2-check-all stage2-check-all
stage2-check-llvm stage2-check-llvm
- stage2-check-clang+ stage2-check-clang CACHE STRING "")
- stage2-test-suite CACHE STRING "")
-else()
- set(CLANG_BOOTSTRAP_TARGETS
- clang
- check-all
- check-llvm
- check-clang
- test-suite
- stage3
- stage3-clang
- stage3-check-all
- stage3-check-llvm
- stage3-check-clang
- stage3-install
- stage3-test-suite CACHE STRING "")
-endif()
-# Stage 1 Options+ # Configuration for stage2-instrumented
-set(STAGE1_PROJECTS "clang")+ set(BOOTSTRAP_CLANG_ENABLE_BOOTSTRAP ON CACHE STRING "")
-set(STAGE1_RUNTIMES "")+ # This enables the build targets for the final stage which is called stage2.
+ set(BOOTSTRAP_CLANG_BOOTSTRAP_TARGETS ${LLVM_RELEASE_FINAL_STAGE_TARGETS} CACHE STRING "")
+ set(BOOTSTRAP_LLVM_BUILD_INSTRUMENTED IR CACHE STRING "")
+ set(BOOTSTRAP_LLVM_ENABLE_RUNTIMES "compiler-rt" CACHE STRING "")
+ set(BOOTSTRAP_LLVM_ENABLE_PROJECTS "clang;lld" CACHE STRING "")
-if (LLVM_RELEASE_ENABLE_PGO)+else()
- list(APPEND STAGE1_PROJECTS "lld")+ if (LLVM_RELEASE_ENABLE_LTO)
- list(APPEND STAGE1_RUNTIMES "compiler-rt")+ list(APPEND STAGE1_PROJECTS "lld")
+ endif()
+ # Any targets added here will be given the target name stage2-${target}, so
+ # if you want to run them you can just use:
+ # ninja -C $BUILDDIR stage2-${target}
+ set(CLANG_BOOTSTRAP_TARGETS ${LLVM_RELEASE_FINAL_STAGE_TARGETS} CACHE STRING "")
endif() endif()
+# Stage 1 Common Config
set(LLVM_ENABLE_RUNTIMES ${STAGE1_RUNTIMES} CACHE STRING "") set(LLVM_ENABLE_RUNTIMES ${STAGE1_RUNTIMES} CACHE STRING "")
set(LLVM_ENABLE_PROJECTS ${STAGE1_PROJECTS} CACHE STRING "") set(LLVM_ENABLE_PROJECTS ${STAGE1_PROJECTS} CACHE STRING "")
-set(LLVM_TARGETS_TO_BUILD Native CACHE STRING "")+# stage2-instrumented and Final Stage Config:
-+# Options that need to be set in both the instrumented stage (if we are doing
-# Stage 2 Bootstrap Setup+# a pgo build) and the final stage.
-set(BOOTSTRAP_CLANG_ENABLE_BOOTSTRAP ON CACHE STRING "")+set_instrument_and_final_stage_var(CMAKE_POSITION_INDEPENDENT_CODE "ON" STRING)
-set(BOOTSTRAP_CLANG_BOOTSTRAP_TARGETS+set_instrument_and_final_stage_var(LLVM_ENABLE_LTO "${LLVM_RELEASE_ENABLE_LTO}" STRING)
- clang+if (LLVM_RELEASE_ENABLE_LTO)
- package+ set_instrument_and_final_stage_var(LLVM_ENABLE_LLD "ON" BOOL)
- check-all
- check-llvm
- check-clang CACHE STRING "")
-
-# Stage 2 Options
-set(STAGE2_PROJECTS "clang")
-set(STAGE2_RUNTIMES "")
-
-if (LLVM_RELEASE_ENABLE_LTO OR LLVM_RELEASE_ENABLE_PGO)
- list(APPEND STAGE2_PROJECTS "lld")
-endif()
-
-if (LLVM_RELEASE_ENABLE_PGO)
- set(BOOTSTRAP_LLVM_BUILD_INSTRUMENTED IR CACHE STRING "")
- list(APPEND STAGE2_RUNTIMES "compiler-rt")
- set(BOOTSTRAP_LLVM_ENABLE_LTO ${LLVM_RELEASE_ENABLE_LTO})
- if (LLVM_RELEASE_ENABLE_LTO)
- set(BOOTSTRAP_LLVM_ENABLE_LLD ON CACHE BOOL "")
- endif()
endif() endif()
-set(BOOTSTRAP_LLVM_ENABLE_PROJECTS ${STAGE2_PROJECTS} CACHE STRING "")+# Final Stage Config (stage2)
-set(BOOTSTRAP_LLVM_ENABLE_RUNTIMES ${STAGE2_RUNTIMES} CACHE STRING "")+set_final_stage_var(LLVM_ENABLE_RUNTIMES "${LLVM_RELEASE_ENABLE_RUNTIMES}" STRING)
-if (NOT LLVM_RELEASE_ENABLE_PGO)+set_final_stage_var(LLVM_ENABLE_PROJECTS "${LLVM_RELEASE_ENABLE_PROJECTS}" STRING)
- set(BOOTSTRAP_LLVM_TARGETS_TO_BUILD Native CACHE STRING "")
-endif()
-# Stage 3 Options
-set(BOOTSTRAP_BOOTSTRAP_LLVM_ENABLE_RUNTIMES "compiler-rt;libcxx;libcxxabi;libunwind" CACHE STRING "")
-set(BOOTSTRAP_BOOTSTRAP_LLVM_ENABLE_PROJECTS "clang;lld;lldb;clang-tools-extra;bolt;polly;mlir;flang" CACHE STRING "")
-set(BOOTSTRAP_BOOTSTRAP_LLVM_ENABLE_LTO ${LLVM_RELEASE_ENABLE_LTO} CACHE STRING "")
-if (LLVM_RELEASE_ENABLE_LTO)
- set(BOOTSTRAP_BOOTSTRAP_LLVM_ENABLE_LLD ON CACHE BOOL "")
-endif()
clang/cmake/caches/VectorEngine.cmake
@@ -40,6 +40,7 @@ set(RUNTIMES_x86_64-unknown-linux-gnu_COMPILER_RT_BUILD_CRT OFF CACHE BOOL "")
set(RUNTIMES_x86_64-unknown-linux-gnu_COMPILER_RT_BUILD_SANITIZERS OFF CACHE BOOL "") set(RUNTIMES_x86_64-unknown-linux-gnu_COMPILER_RT_BUILD_SANITIZERS OFF CACHE BOOL "")
set(RUNTIMES_x86_64-unknown-linux-gnu_COMPILER_RT_BUILD_XRAY OFF CACHE BOOL "") set(RUNTIMES_x86_64-unknown-linux-gnu_COMPILER_RT_BUILD_XRAY OFF CACHE BOOL "")
set(RUNTIMES_x86_64-unknown-linux-gnu_COMPILER_RT_BUILD_LIBFUZZER OFF CACHE BOOL "") set(RUNTIMES_x86_64-unknown-linux-gnu_COMPILER_RT_BUILD_LIBFUZZER OFF CACHE BOOL "")
+set(RUNTIMES_x86_64-unknown-linux-gnu_COMPILER_RT_BUILD_CTX_PROFILE OFF CACHE BOOL "")
set(RUNTIMES_x86_64-unknown-linux-gnu_COMPILER_RT_BUILD_PROFILE OFF CACHE BOOL "") set(RUNTIMES_x86_64-unknown-linux-gnu_COMPILER_RT_BUILD_PROFILE OFF CACHE BOOL "")
set(RUNTIMES_x86_64-unknown-linux-gnu_COMPILER_RT_BUILD_MEMPROF OFF CACHE BOOL "") set(RUNTIMES_x86_64-unknown-linux-gnu_COMPILER_RT_BUILD_MEMPROF OFF CACHE BOOL "")
set(RUNTIMES_x86_64-unknown-linux-gnu_COMPILER_RT_BUILD_ORC OFF CACHE BOOL "") set(RUNTIMES_x86_64-unknown-linux-gnu_COMPILER_RT_BUILD_ORC OFF CACHE BOOL "")
@@ -52,6 +53,7 @@ set(RUNTIMES_ve-unknown-linux-gnu_COMPILER_RT_BUILD_SANITIZERS OFF CACHE BOOL ""
set(RUNTIMES_ve-unknown-linux-gnu_COMPILER_RT_BUILD_XRAY OFF CACHE BOOL "") set(RUNTIMES_ve-unknown-linux-gnu_COMPILER_RT_BUILD_XRAY OFF CACHE BOOL "")
set(RUNTIMES_ve-unknown-linux-gnu_COMPILER_RT_BUILD_LIBFUZZER OFF CACHE BOOL "") set(RUNTIMES_ve-unknown-linux-gnu_COMPILER_RT_BUILD_LIBFUZZER OFF CACHE BOOL "")
set(RUNTIMES_ve-unknown-linux-gnu_COMPILER_RT_BUILD_PROFILE ON CACHE BOOL "") set(RUNTIMES_ve-unknown-linux-gnu_COMPILER_RT_BUILD_PROFILE ON CACHE BOOL "")
+set(RUNTIMES_ve-unknown-linux-gnu_COMPILER_RT_BUILD_CTX_PROFILE OFF CACHE BOOL "")
set(RUNTIMES_ve-unknown-linux-gnu_COMPILER_RT_BUILD_MEMPROF OFF CACHE BOOL "") set(RUNTIMES_ve-unknown-linux-gnu_COMPILER_RT_BUILD_MEMPROF OFF CACHE BOOL "")
set(RUNTIMES_ve-unknown-linux-gnu_COMPILER_RT_BUILD_ORC OFF CACHE BOOL "") set(RUNTIMES_ve-unknown-linux-gnu_COMPILER_RT_BUILD_ORC OFF CACHE BOOL "")
set(RUNTIMES_ve-unknown-linux-gnu_COMPILER_RT_BUILD_GWP_ASAN OFF CACHE BOOL "") set(RUNTIMES_ve-unknown-linux-gnu_COMPILER_RT_BUILD_GWP_ASAN OFF CACHE BOOL "")
clang/docs/LanguageExtensions.rst
@@ -711,6 +711,8 @@ even-odd element pair with indices ``i * 2`` and ``i * 2 + 1`` with
power of 2, the vector is widened with neutral elements for the reduction power of 2, the vector is widened with neutral elements for the reduction
at the end to the next power of 2. at the end to the next power of 2.
+These reductions support both fixed-sized and scalable vector types.
+
Example: Example:
.. code-block:: c++ .. code-block:: c++
@@ -1493,6 +1495,7 @@ Conditional ``explicit`` __cpp_conditional_explicit C+
``if consteval`` __cpp_if_consteval C++23 C++20 ``if consteval`` __cpp_if_consteval C++23 C++20
``static operator()`` __cpp_static_call_operator C++23 C++03 ``static operator()`` __cpp_static_call_operator C++23 C++03
Attributes on Lambda-Expressions C++23 C++11 Attributes on Lambda-Expressions C++23 C++11
+Attributes on Structured Bindings __cpp_structured_bindings C++26 C++03
``= delete ("should have a reason");`` __cpp_deleted_function C++26 C++03 ``= delete ("should have a reason");`` __cpp_deleted_function C++26 C++03
-------------------------------------------- -------------------------------- ------------- ------------- -------------------------------------------- -------------------------------- ------------- -------------
Designated initializers (N494) C99 C89 Designated initializers (N494) C99 C89
@@ -2928,7 +2931,7 @@ Query for this feature with ``__has_builtin(__builtin_dump_struct)``
``__builtin_shufflevector`` is used to express generic vector ``__builtin_shufflevector`` is used to express generic vector
permutation/shuffle/swizzle operations. This builtin is also very important permutation/shuffle/swizzle operations. This builtin is also very important
for the implementation of various target-specific header files like for the implementation of various target-specific header files like
-``<xmmintrin.h>``.+``<xmmintrin.h>``. This builtin can be used within constant expressions.
**Syntax**: **Syntax**:
@@ -2955,7 +2958,7 @@ for the implementation of various target-specific header files like
// Concatenate every other element of 8-element vectors V1 and V2. // Concatenate every other element of 8-element vectors V1 and V2.
__builtin_shufflevector(V1, V2, 0, 2, 4, 6, 8, 10, 12, 14) __builtin_shufflevector(V1, V2, 0, 2, 4, 6, 8, 10, 12, 14)
- // Shuffle v1 with some elements being undefined+ // Shuffle v1 with some elements being undefined. Not allowed in constexpr.
__builtin_shufflevector(v1, v1, 3, -1, 1, -1) __builtin_shufflevector(v1, v1, 3, -1, 1, -1)
**Description**: **Description**:
@@ -2968,6 +2971,7 @@ starting with the first vector, continuing into the second vector. Thus, if
``vec1`` is a 4-element vector, index 5 would refer to the second element of ``vec1`` is a 4-element vector, index 5 would refer to the second element of
``vec2``. An index of -1 can be used to indicate that the corresponding element ``vec2``. An index of -1 can be used to indicate that the corresponding element
in the returned vector is a don't care and can be optimized by the backend. in the returned vector is a don't care and can be optimized by the backend.
+Values of -1 are not supported in constant expressions.
The result of ``__builtin_shufflevector`` is a vector with the same element The result of ``__builtin_shufflevector`` is a vector with the same element
type as ``vec1``/``vec2`` but that has an element count equal to the number of type as ``vec1``/``vec2`` but that has an element count equal to the number of
@@ -2982,7 +2986,8 @@ Query for this feature with ``__has_builtin(__builtin_shufflevector)``.
``__builtin_convertvector`` is used to express generic vector ``__builtin_convertvector`` is used to express generic vector
type-conversion operations. The input vector and the output vector type-conversion operations. The input vector and the output vector
-type must have the same number of elements.+type must have the same number of elements. This builtin can be used within
+constant expressions.
**Syntax**: **Syntax**:
@@ -5572,3 +5577,25 @@ but the expression has no runtime effects.
Type- and value-dependent expressions are not supported yet. Type- and value-dependent expressions are not supported yet.
This facility is designed to aid with testing name lookup machinery. This facility is designed to aid with testing name lookup machinery.
+
+Predefined Macros
+=================
+
+`__GCC_DESTRUCTIVE_SIZE` and `__GCC_CONSTRUCTIVE_SIZE`
+------------------------------------------------------
+Specify the mimum offset between two objects to avoid false sharing and the
+maximum size of contiguous memory to promote true sharing, respectively. These
+macros are predefined in all C and C++ language modes, but can be redefined on
+the command line with ``-D`` to specify different values as needed or can be
+undefined on the command line with ``-U`` to disable support for the feature.
+
+**Note: the values the macros expand to are not guaranteed to be stable. They
+are are affected by architectures and CPU tuning flags, can change between
+releases of Clang and will not match the values defined by other compilers such
+as GCC.**
+
+Compiling different TUs depending on these flags (including use of
+``std::hardware_constructive_interference`` or
+``std::hardware_destructive_interference``) with different compilers, macro
+definitions, or architecture flags will lead to ODR violations and should be
+avoided.
clang/docs/LibTooling.rst
@@ -63,15 +63,22 @@ and automatic location of the compilation database using source files paths.
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
using namespace clang::tooling; using namespace clang::tooling;
+ using namespace llvm;
// Apply a custom category to all command-line options so that they are the // Apply a custom category to all command-line options so that they are the
// only ones displayed. // only ones displayed.
- static llvm::cl::OptionCategory MyToolCategory("my-tool options");+ static cl::OptionCategory MyToolCategory("my-tool options");
int main(int argc, const char **argv) { int main(int argc, const char **argv) {
- // CommonOptionsParser constructor will parse arguments and create a+ // CommonOptionsParser::create will parse arguments and create a
- // CompilationDatabase. In case of error it will terminate the program.+ // CompilationDatabase.
- CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);+ auto ExpectedParser = CommonOptionsParser::create(argc, argv, MyToolCategory);
+ if (!ExpectedParser) {
+ // Fail gracefully for unsupported options.
+ llvm::errs() << ExpectedParser.takeError();
+ return 1;
+ }
+ CommonOptionsParser& OptionsParser = ExpectedParser.get();
// Use OptionsParser.getCompilations() and OptionsParser.getSourcePathList() // Use OptionsParser.getCompilations() and OptionsParser.getSourcePathList()
// to retrieve CompilationDatabase and the list of input file paths. // to retrieve CompilationDatabase and the list of input file paths.
@@ -133,7 +140,12 @@ version of this example tool is also checked into the clang tree at
static cl::extrahelp MoreHelp("\nMore help text...\n"); static cl::extrahelp MoreHelp("\nMore help text...\n");
int main(int argc, const char **argv) { int main(int argc, const char **argv) {
- CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);+ auto ExpectedParser = CommonOptionsParser::create(argc, argv, MyToolCategory);
+ if (!ExpectedParser) {
+ llvm::errs() << ExpectedParser.takeError();
+ return 1;
+ }
+ CommonOptionsParser& OptionsParser = ExpectedParser.get();
ClangTool Tool(OptionsParser.getCompilations(), ClangTool Tool(OptionsParser.getCompilations(),
OptionsParser.getSourcePathList()); OptionsParser.getSourcePathList());
return Tool.run(newFrontendActionFactory<clang::SyntaxOnlyAction>().get()); return Tool.run(newFrontendActionFactory<clang::SyntaxOnlyAction>().get());
clang/docs/OpenMPSupport.rst
@@ -310,7 +310,9 @@ implementation.
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| misc | dispatch construct and function variant argument adjustment | :part:`worked on` | D99537, D99679 | | misc | dispatch construct and function variant argument adjustment | :part:`worked on` | D99537, D99679 |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
-| misc | assume and assumes directives | :part:`worked on` | |+| misc | assumes directives | :part:`worked on` | |
++------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
+| misc | assume directive | :part:`worked on` | |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| misc | nothing directive | :good:`done` | D123286 | | misc | nothing directive | :good:`done` | D123286 |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
clang/docs/ReleaseNotes.rst
@@ -63,6 +63,12 @@ ABI Changes in This Version
MSVC uses a different mangling for these objects, compatibility is not affected. MSVC uses a different mangling for these objects, compatibility is not affected.
(#GH85423). (#GH85423).
+- Fixed Microsoft calling convention for returning certain classes with a
+ templated constructor. If a class has a templated constructor, it should
+ be returned indirectly even if it meets all the other requirements for
+ returning a class in a register. This affects some uses of std::pair.
+ (#GH86384).
+
AST Dumping Potentially Breaking Changes AST Dumping Potentially Breaking Changes
---------------------------------------- ----------------------------------------
@@ -90,6 +96,18 @@ C++ Language Changes
-------------------- --------------------
- Implemented ``_BitInt`` literal suffixes ``__wb`` or ``__WB`` as a Clang extension with ``unsigned`` modifiers also allowed. (#GH85223). - Implemented ``_BitInt`` literal suffixes ``__wb`` or ``__WB`` as a Clang extension with ``unsigned`` modifiers also allowed. (#GH85223).
+C++17 Feature Support
+^^^^^^^^^^^^^^^^^^^^^
+- Clang now exposes ``__GCC_DESTRUCTIVE_SIZE`` and ``__GCC_CONSTRUCTIVE_SIZE``
+ predefined macros to support standard library implementations of
+ ``std::hardware_destructive_interference_size`` and
+ ``std::hardware_constructive_interference_size``, respectively. These macros
+ are predefined in all C and C++ language modes. The values the macros
+ expand to are not stable between releases of Clang and do not need to match
+ the values produced by GCC, so these macros should not be used from header
+ files because they may not be stable across multiple TUs (the values may vary
+ based on compiler version as well as CPU tuning). #GH60174
+
C++20 Feature Support C++20 Feature Support
^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
@@ -131,6 +149,9 @@ C++2c Feature Support
- Implemented `P2573R2: = delete("should have a reason"); <https://wg21.link/P2573R2>`_ - Implemented `P2573R2: = delete("should have a reason"); <https://wg21.link/P2573R2>`_
+- Implemented `P0609R3: Attributes for Structured Bindings <https://wg21.link/P0609R3>`_
+
+- Implemented `P2748R5 Disallow Binding a Returned Glvalue to a Temporary <https://wg21.link/P2748R5>`_.
Resolutions to C++ Defect Reports Resolutions to C++ Defect Reports
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -207,6 +228,20 @@ Non-comprehensive list of changes in this release
- ``__typeof_unqual__`` is available in all C modes as an extension, which behaves - ``__typeof_unqual__`` is available in all C modes as an extension, which behaves
like ``typeof_unqual`` from C23, similar to ``__typeof__`` and ``typeof``. like ``typeof_unqual`` from C23, similar to ``__typeof__`` and ``typeof``.
+- ``__builtin_reduce_{add|mul|xor|or|and|min|max}`` builtins now support scalable vectors.
+
+* Shared libraries linked with either the ``-ffast-math``, ``-Ofast``, or
+ ``-funsafe-math-optimizations`` flags will no longer enable flush-to-zero
+ floating-point mode by default. This decision can be overridden with use of
+ ``-mdaz-ftz``. This behavior now matches GCC's behavior.
+ (`#57589 <https://github.com/llvm/llvm-project/issues/57589>`_)
+
+* ``-fdenormal-fp-math=preserve-sign`` is no longer implied by ``-ffast-math``
+ on x86 systems.
+
+- Builtins ``__builtin_shufflevector()`` and ``__builtin_convertvector()`` may
+ now be used within constant expressions.
+
New Compiler Flags New Compiler Flags
------------------ ------------------
- ``-fsanitize=implicit-bitfield-conversion`` checks implicit truncation and - ``-fsanitize=implicit-bitfield-conversion`` checks implicit truncation and
@@ -221,6 +256,10 @@ New Compiler Flags
- ``-fexperimental-modules-reduced-bmi`` enables the Reduced BMI for C++20 named modules. - ``-fexperimental-modules-reduced-bmi`` enables the Reduced BMI for C++20 named modules.
See the document of standard C++ modules for details. See the document of standard C++ modules for details.
+- ``-fexperimental-late-parse-attributes`` enables an experimental feature to
+ allow late parsing certain attributes in specific contexts where they would
+ not normally be late parsed.
+
Deprecated Compiler Flags Deprecated Compiler Flags
------------------------- -------------------------
@@ -375,6 +414,18 @@ Improvements to Clang's diagnostics
- Clang now diagnoses requires expressions with explicit object parameters. - Clang now diagnoses requires expressions with explicit object parameters.
+- Clang now looks up members of the current instantiation in the template definition context
+ if the current instantiation has no dependent base classes.
+
+ .. code-block:: c++
+
+ template<typename T>
+ struct A {
+ int f() {
+ return this->x; // error: no member named 'x' in 'A<T>'
+ }
+ };
+
Improvements to Clang's time-trace Improvements to Clang's time-trace
---------------------------------- ----------------------------------
@@ -421,6 +472,9 @@ Bug Fixes in This Version
- Clang now correctly generates overloads for bit-precise integer types for - Clang now correctly generates overloads for bit-precise integer types for
builtin operators in C++. Fixes #GH82998. builtin operators in C++. Fixes #GH82998.
+- Fix crash when destructor definition is preceded with an equals sign.
+ Fixes (#GH89544).
+
- When performing mixed arithmetic between ``_Complex`` floating-point types and integers, - When performing mixed arithmetic between ``_Complex`` floating-point types and integers,
Clang now correctly promotes the integer to its corresponding real floating-point Clang now correctly promotes the integer to its corresponding real floating-point
type only rather than to the complex type (e.g. ``_Complex float / int`` is now evaluated type only rather than to the complex type (e.g. ``_Complex float / int`` is now evaluated
@@ -436,6 +490,10 @@ Bug Fixes in This Version
- Fixed an assertion failure on invalid InitListExpr in C89 mode (#GH88008). - Fixed an assertion failure on invalid InitListExpr in C89 mode (#GH88008).
+- Fixed missing destructor calls when we branch from middle of an expression.
+ This could happen through a branch in stmt-expr or in an expression containing a coroutine
+ suspension. Fixes (#GH63818) (#GH88478).
+
- Clang will no longer diagnose an erroneous non-dependent ``switch`` condition - Clang will no longer diagnose an erroneous non-dependent ``switch`` condition
during instantiation, and instead will only diagnose it once, during checking during instantiation, and instead will only diagnose it once, during checking
of the function template. of the function template.
@@ -564,6 +622,14 @@ Bug Fixes to C++ Support
- Fixed a crash when trying to evaluate a user-defined ``static_assert`` message whose ``size()`` - Fixed a crash when trying to evaluate a user-defined ``static_assert`` message whose ``size()``
function returns a large or negative value. Fixes (#GH89407). function returns a large or negative value. Fixes (#GH89407).
- Fixed a use-after-free bug in parsing of type constraints with default arguments that involve lambdas. (#GH67235) - Fixed a use-after-free bug in parsing of type constraints with default arguments that involve lambdas. (#GH67235)
+- Fixed bug in which the body of a consteval lambda within a template was not parsed as within an
+ immediate function context.
+- Fix CTAD for ``std::initializer_list``. This allows ``std::initializer_list{1, 2, 3}`` to be deduced as
+ ``std::initializer_list<int>`` as intended.
+- Fix a bug on template partial specialization whose template parameter is `decltype(auto)`.
+- Fix a bug on template partial specialization with issue on deduction of nontype template parameter
+ whose type is `decltype(auto)`. Fixes (#GH68885).
+- Clang now correctly treats the noexcept-specifier of a friend function to be a complete-class context.
Bug Fixes to AST Handling Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -616,6 +682,10 @@ Arm and AArch64 Support
* Arm Cortex-A78AE (cortex-a78ae). * Arm Cortex-A78AE (cortex-a78ae).
* Arm Cortex-A520AE (cortex-a520ae). * Arm Cortex-A520AE (cortex-a520ae).
* Arm Cortex-A720AE (cortex-a720ae). * Arm Cortex-A720AE (cortex-a720ae).
+ * Arm Cortex-R82AE (cortex-r82ae).
+ * Arm Neoverse-N3 (neoverse-n3).
+ * Arm Neoverse-V3 (neoverse-v3).
+ * Arm Neoverse-V3AE (neoverse-v3ae).
Android Support Android Support
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
@@ -672,6 +742,11 @@ AIX Support
WebAssembly Support WebAssembly Support
^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
+The -mcpu=generic configuration now enables multivalue and reference-types.These
+proposals are standardized and available in all major engines. Enabling
+multivalue here only enables the language feature but does not turn on the
+multivalue ABI (this enables non-ABI uses of multivalue, like exnref).
+
AVR Support AVR Support
^^^^^^^^^^^ ^^^^^^^^^^^
clang/docs/UsersManual.rst
@@ -1452,8 +1452,6 @@ floating point semantic models: precise (the default), strict, and fast.
"fenv_access", "off", "on", "off" "fenv_access", "off", "on", "off"
"rounding_mode", "tonearest", "dynamic", "tonearest" "rounding_mode", "tonearest", "dynamic", "tonearest"
"contract", "on", "off", "fast" "contract", "on", "off", "fast"
- "denormal_fp_math", "IEEE", "IEEE", "IEEE"
- "denormal_fp32_math", "IEEE","IEEE", "IEEE"
"support_math_errno", "on", "on", "off" "support_math_errno", "on", "on", "off"
"no_honor_nans", "off", "off", "on" "no_honor_nans", "off", "off", "on"
"no_honor_infinities", "off", "off", "on" "no_honor_infinities", "off", "off", "on"
@@ -1462,6 +1460,14 @@ floating point semantic models: precise (the default), strict, and fast.
"allow_approximate_fns", "off", "off", "on" "allow_approximate_fns", "off", "off", "on"
"allow_reassociation", "off", "off", "on" "allow_reassociation", "off", "off", "on"
+The ``-ffp-model`` option does not modify the ``fdenormal-fp-math``
+setting, but it does have an impact on whether ``crtfastmath.o`` is
+linked. Because linking ``crtfastmath.o`` has a global effect on the
+program, and because the global denormal handling can be changed in
+other ways, the state of ``fdenormal-fp-math`` handling cannot
+be assumed in any function based on fp-model. See :ref:`crtfastmath.o`
+for more details.
+
.. option:: -ffast-math .. option:: -ffast-math
Enable fast-math mode. This option lets the Enable fast-math mode. This option lets the
@@ -1506,7 +1512,8 @@ floating point semantic models: precise (the default), strict, and fast.
* ``-ffp-contract=fast`` * ``-ffp-contract=fast``
- Note: ``-ffast-math`` causes ``crtfastmath.o`` to be linked with code. See+ Note: ``-ffast-math`` causes ``crtfastmath.o`` to be linked with code unless
+ ``-shared`` or ``-mno-daz-ftz`` is present. See
:ref:`crtfastmath.o` for more details. :ref:`crtfastmath.o` for more details.
.. option:: -fno-fast-math .. option:: -fno-fast-math
@@ -1536,7 +1543,6 @@ floating point semantic models: precise (the default), strict, and fast.
Also, this option resets following options to their target-dependent defaults. Also, this option resets following options to their target-dependent defaults.
* ``-f[no-]math-errno`` * ``-f[no-]math-errno``
- * ``-fdenormal-fp-math=<value>``
There is ambiguity about how ``-ffp-contract``, ``-ffast-math``, There is ambiguity about how ``-ffp-contract``, ``-ffast-math``,
and ``-fno-fast-math`` behave when combined. To keep the value of and ``-fno-fast-math`` behave when combined. To keep the value of
@@ -1559,8 +1565,8 @@ floating point semantic models: precise (the default), strict, and fast.
``-ffp-contract`` setting is determined by the default value of ``-ffp-contract`` setting is determined by the default value of
``-ffp-contract``. ``-ffp-contract``.
- Note: ``-fno-fast-math`` implies ``-fdenormal-fp-math=ieee``.+ Note: ``-fno-fast-math`` causes ``crtfastmath.o`` to not be linked with code
- ``-fno-fast-math`` causes ``crtfastmath.o`` to not be linked with code.+ unless ``-mdaz-ftz`` is present.
.. option:: -fdenormal-fp-math=<value> .. option:: -fdenormal-fp-math=<value>
@@ -1690,9 +1696,7 @@ floating point semantic models: precise (the default), strict, and fast.
* ``-fno-associative-math`` * ``-fno-associative-math``
* ``-fno-reciprocal-math`` * ``-fno-reciprocal-math``
* ``-fsigned-zeros`` * ``-fsigned-zeros``
- * ``-ftrapping-math``
* ``-ffp-contract=on`` * ``-ffp-contract=on``
- * ``-fdenormal-fp-math=ieee``
There is ambiguity about how ``-ffp-contract``, There is ambiguity about how ``-ffp-contract``,
``-funsafe-math-optimizations``, and ``-fno-unsafe-math-optimizations`` ``-funsafe-math-optimizations``, and ``-fno-unsafe-math-optimizations``
@@ -1938,10 +1942,13 @@ by using ``#pragma STDC FENV_ROUND`` with a value other than ``FE_DYNAMIC``.
A note about ``crtfastmath.o`` A note about ``crtfastmath.o``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-``-ffast-math`` and ``-funsafe-math-optimizations`` cause ``crtfastmath.o`` to be+``-ffast-math`` and ``-funsafe-math-optimizations`` without the ``-shared``
-automatically linked, which adds a static constructor that sets the FTZ/DAZ+option cause ``crtfastmath.o`` to be
+automatically linked, which adds a static constructor that sets the FTZ/DAZ
bits in MXCSR, affecting not only the current compilation unit but all static bits in MXCSR, affecting not only the current compilation unit but all static
-and shared libraries included in the program.+and shared libraries included in the program. This decision can be overridden
+by using either the flag ``-mdaz-ftz`` or ``-mno-daz-ftz`` to respectively
+link or not link ``crtfastmath.o``.
.. _FLT_EVAL_METHOD: .. _FLT_EVAL_METHOD:
@@ -2314,6 +2321,8 @@ are listed below.
on ELF targets when using the integrated assembler. This flag currently on ELF targets when using the integrated assembler. This flag currently
only has an effect on ELF targets. only has an effect on ELF targets.
+.. _funique_internal_linkage_names:
+
.. option:: -f[no]-unique-internal-linkage-names .. option:: -f[no]-unique-internal-linkage-names
Controls whether Clang emits a unique (best-effort) symbol name for internal Controls whether Clang emits a unique (best-effort) symbol name for internal
@@ -2443,27 +2452,41 @@ usual build cycle when using sample profilers for optimization:
usual build flags that you always build your application with. The only usual build flags that you always build your application with. The only
requirement is that DWARF debug info including source line information is requirement is that DWARF debug info including source line information is
generated. This DWARF information is important for the profiler to be able generated. This DWARF information is important for the profiler to be able
- to map instructions back to source line locations.+ to map instructions back to source line locations. The usefulness of this
+ DWARF information can be improved with the ``-fdebug-info-for-profiling``
+ and ``-funique-internal-linkage-names`` options.
- On Linux, ``-g`` or just ``-gline-tables-only`` is sufficient:+ On Linux:
.. code-block:: console .. code-block:: console
- $ clang++ -O2 -gline-tables-only code.cc -o code+ $ clang++ -O2 -gline-tables-only \
+ -fdebug-info-for-profiling -funique-internal-linkage-names \
+ code.cc -o code
While MSVC-style targets default to CodeView debug information, DWARF debug While MSVC-style targets default to CodeView debug information, DWARF debug
information is required to generate source-level LLVM profiles. Use information is required to generate source-level LLVM profiles. Use
``-gdwarf`` to include DWARF debug information: ``-gdwarf`` to include DWARF debug information:
- .. code-block:: console+ .. code-block:: winbatch
+
+ > clang-cl /O2 -gdwarf -gline-tables-only ^
+ /clang:-fdebug-info-for-profiling /clang:-funique-internal-linkage-names ^
+ code.cc /Fe:code /fuse-ld=lld /link /debug:dwarf
- $ clang-cl -O2 -gdwarf -gline-tables-only coff-profile.cpp -fuse-ld=lld -link -debug:dwarf+.. note::
+
+ :ref:`-funique-internal-linkage-names <funique_internal_linkage_names>`
+ generates unique names based on given command-line source file paths. If
+ your build system uses absolute source paths and these paths may change
+ between steps 1 and 4, then the uniqued function names may change and result
+ in unused profile data. Consider omitting this option in such cases.
2. Run the executable under a sampling profiler. The specific profiler 2. Run the executable under a sampling profiler. The specific profiler
you use does not really matter, as long as its output can be converted you use does not really matter, as long as its output can be converted
into the format that the LLVM optimizer understands. into the format that the LLVM optimizer understands.
- Two such profilers are the the Linux Perf profiler+ Two such profilers are the Linux Perf profiler
(https://perf.wiki.kernel.org/) and Intel's Sampling Enabling Product (SEP), (https://perf.wiki.kernel.org/) and Intel's Sampling Enabling Product (SEP),
available as part of `Intel VTune available as part of `Intel VTune
<https://software.intel.com/content/www/us/en/develop/tools/oneapi/components/vtune-profiler.html>`_. <https://software.intel.com/content/www/us/en/develop/tools/oneapi/components/vtune-profiler.html>`_.
@@ -2477,7 +2500,9 @@ usual build cycle when using sample profilers for optimization:
.. code-block:: console .. code-block:: console
- $ perf record -b ./code+ $ perf record -b -e BR_INST_RETIRED.NEAR_TAKEN:uppp ./code
+
+ If the event above is unavailable, ``branches:u`` is probably next-best.
Note the use of the ``-b`` flag. This tells Perf to use the Last Branch Note the use of the ``-b`` flag. This tells Perf to use the Last Branch
Record (LBR) to record call chains. While this is not strictly required, Record (LBR) to record call chains. While this is not strictly required,
@@ -2527,21 +2552,42 @@ usual build cycle when using sample profilers for optimization:
that executes faster than the original one. Note that you are not that executes faster than the original one. Note that you are not
required to build the code with the exact same arguments that you required to build the code with the exact same arguments that you
used in the first step. The only requirement is that you build the code used in the first step. The only requirement is that you build the code
- with ``-gline-tables-only`` and ``-fprofile-sample-use``.+ with the same debug info options and ``-fprofile-sample-use``.
+
+ On Linux:
.. code-block:: console .. code-block:: console
- $ clang++ -O2 -gline-tables-only -fprofile-sample-use=code.prof code.cc -o code+ $ clang++ -O2 -gline-tables-only \
+ -fdebug-info-for-profiling -funique-internal-linkage-names \
+ -fprofile-sample-use=code.prof code.cc -o code
- [OPTIONAL] Sampling-based profiles can have inaccuracies or missing block/+ On Windows:
- edge counters. The profile inference algorithm (profi) can be used to infer
- missing blocks and edge counts, and improve the quality of profile data.
- Enable it with ``-fsample-profile-use-profi``.
- .. code-block:: console+ .. code-block:: winbatch
+
+ > clang-cl /O2 -gdwarf -gline-tables-only ^
+ /clang:-fdebug-info-for-profiling /clang:-funique-internal-linkage-names ^
+ /fprofile-sample-use=code.prof code.cc /Fe:code /fuse-ld=lld /link /debug:dwarf
+
+ [OPTIONAL] Sampling-based profiles can have inaccuracies or missing block/
+ edge counters. The profile inference algorithm (profi) can be used to infer
+ missing blocks and edge counts, and improve the quality of profile data.
+ Enable it with ``-fsample-profile-use-profi``. For example, on Linux:
+
+ .. code-block:: console
+
+ $ clang++ -fsample-profile-use-profi -O2 -gline-tables-only \
+ -fdebug-info-for-profiling -funique-internal-linkage-names \
+ -fprofile-sample-use=code.prof code.cc -o code
+
+ On Windows:
+
+ .. code-block:: winbatch
- $ clang++ -O2 -gline-tables-only -fprofile-sample-use=code.prof \+ > clang-cl /clang:-fsample-profile-use-profi /O2 -gdwarf -gline-tables-only ^
- -fsample-profile-use-profi code.cc -o code+ /clang:-fdebug-info-for-profiling /clang:-funique-internal-linkage-names ^
+ /fprofile-sample-use=code.prof code.cc /Fe:code /fuse-ld=lld /link /debug:dwarf
Sample Profile Formats Sample Profile Formats
"""""""""""""""""""""" """"""""""""""""""""""
clang/docs/analyzer/checkers.rst
@@ -1462,6 +1462,99 @@ checker).
Default value of the option is ``true``. Default value of the option is ``true``.
+.. _unix-Stream:
+
+unix.Stream (C)
+"""""""""""""""
+Check C stream handling functions:
+``fopen, fdopen, freopen, tmpfile, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, fprintf, fscanf, ungetc, getdelim, getline, fseek, fseeko, ftell, ftello, fflush, rewind, fgetpos, fsetpos, clearerr, feof, ferror, fileno``.
+
+The checker maintains information about the C stream objects (``FILE *``) and
+can detect error conditions related to use of streams. The following conditions
+are detected:
+
+* The ``FILE *`` pointer passed to the function is NULL (the single exception is
+ ``fflush`` where NULL is allowed).
+* Use of stream after close.
+* Opened stream is not closed.
+* Read from a stream after end-of-file. (This is not a fatal error but reported
+ by the checker. Stream remains in EOF state and the read operation fails.)
+* Use of stream when the file position is indeterminate after a previous failed
+ operation. Some functions (like ``ferror``, ``clearerr``, ``fseek``) are
+ allowed in this state.
+* Invalid 3rd ("``whence``") argument to ``fseek``.
+
+The stream operations are by this checker usually split into two cases, a success
+and a failure case. However, in the case of write operations (like ``fwrite``,
+``fprintf`` and even ``fsetpos``) this behavior could produce a large amount of
+unwanted reports on projects that don't have error checks around the write
+operations, so by default the checker assumes that write operations always succeed.
+This behavior can be controlled by the ``Pedantic`` flag: With
+``-analyzer-config unix.Stream:Pedantic=true`` the checker will model the
+cases where a write operation fails and report situations where this leads to
+erroneous behavior. (The default is ``Pedantic=false``, where write operations
+are assumed to succeed.)
+
+.. code-block:: c
+
+ void test1() {
+ FILE *p = fopen("foo", "r");
+ } // warn: opened file is never closed
+
+ void test2() {
+ FILE *p = fopen("foo", "r");
+ fseek(p, 1, SEEK_SET); // warn: stream pointer might be NULL
+ fclose(p);
+ }
+
+ void test3() {
+ FILE *p = fopen("foo", "r");
+ if (p) {
+ fseek(p, 1, 3); // warn: third arg should be SEEK_SET, SEEK_END, or SEEK_CUR
+ fclose(p);
+ }
+ }
+
+ void test4() {
+ FILE *p = fopen("foo", "r");
+ if (!p)
+ return;
+
+ fclose(p);
+ fclose(p); // warn: stream already closed
+ }
+
+ void test5() {
+ FILE *p = fopen("foo", "r");
+ if (!p)
+ return;
+
+ fgetc(p);
+ if (!ferror(p))
+ fgetc(p); // warn: possible read after end-of-file
+
+ fclose(p);
+ }
+
+ void test6() {
+ FILE *p = fopen("foo", "r");
+ if (!p)
+ return;
+
+ fgetc(p);
+ if (!feof(p))
+ fgetc(p); // warn: file position may be indeterminate after I/O error
+
+ fclose(p);
+ }
+
+**Limitations**
+
+The checker does not track the correspondence between integer file descriptors
+and ``FILE *`` pointers. Operations on standard streams like ``stdin`` are not
+treated specially and are therefore often not recognized (because these streams
+are usually not opened explicitly by the program, and are global variables).
+
.. _osx-checkers: .. _osx-checkers:
osx osx
@@ -3116,99 +3209,6 @@ Check for misuses of stream APIs. Check for misuses of stream APIs: ``fopen, fcl
fclose(F); // warn: closing a previously closed file stream fclose(F); // warn: closing a previously closed file stream
} }
-.. _alpha-unix-Stream:
-
-alpha.unix.Stream (C)
-"""""""""""""""""""""
-Check C stream handling functions:
-``fopen, fdopen, freopen, tmpfile, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, fprintf, fscanf, ungetc, getdelim, getline, fseek, fseeko, ftell, ftello, fflush, rewind, fgetpos, fsetpos, clearerr, feof, ferror, fileno``.
-
-The checker maintains information about the C stream objects (``FILE *``) and
-can detect error conditions related to use of streams. The following conditions
-are detected:
-
-* The ``FILE *`` pointer passed to the function is NULL (the single exception is
- ``fflush`` where NULL is allowed).
-* Use of stream after close.
-* Opened stream is not closed.
-* Read from a stream after end-of-file. (This is not a fatal error but reported
- by the checker. Stream remains in EOF state and the read operation fails.)
-* Use of stream when the file position is indeterminate after a previous failed
- operation. Some functions (like ``ferror``, ``clearerr``, ``fseek``) are
- allowed in this state.
-* Invalid 3rd ("``whence``") argument to ``fseek``.
-
-The stream operations are by this checker usually split into two cases, a success
-and a failure case. However, in the case of write operations (like ``fwrite``,
-``fprintf`` and even ``fsetpos``) this behavior could produce a large amount of
-unwanted reports on projects that don't have error checks around the write
-operations, so by default the checker assumes that write operations always succeed.
-This behavior can be controlled by the ``Pedantic`` flag: With
-``-analyzer-config alpha.unix.Stream:Pedantic=true`` the checker will model the
-cases where a write operation fails and report situations where this leads to
-erroneous behavior. (The default is ``Pedantic=false``, where write operations
-are assumed to succeed.)
-
-.. code-block:: c
-
- void test1() {
- FILE *p = fopen("foo", "r");
- } // warn: opened file is never closed
-
- void test2() {
- FILE *p = fopen("foo", "r");
- fseek(p, 1, SEEK_SET); // warn: stream pointer might be NULL
- fclose(p);
- }
-
- void test3() {
- FILE *p = fopen("foo", "r");
- if (p) {
- fseek(p, 1, 3); // warn: third arg should be SEEK_SET, SEEK_END, or SEEK_CUR
- fclose(p);
- }
- }
-
- void test4() {
- FILE *p = fopen("foo", "r");
- if (!p)
- return;
-
- fclose(p);
- fclose(p); // warn: stream already closed
- }
-
- void test5() {
- FILE *p = fopen("foo", "r");
- if (!p)
- return;
-
- fgetc(p);
- if (!ferror(p))
- fgetc(p); // warn: possible read after end-of-file
-
- fclose(p);
- }
-
- void test6() {
- FILE *p = fopen("foo", "r");
- if (!p)
- return;
-
- fgetc(p);
- if (!feof(p))
- fgetc(p); // warn: file position may be indeterminate after I/O error
-
- fclose(p);
- }
-
-**Limitations**
-
-The checker does not track the correspondence between integer file descriptors
-and ``FILE *`` pointers. Operations on standard streams like ``stdin`` are not
-treated specially and are therefore often not recognized (because these streams
-are usually not opened explicitly by the program, and are global variables).
-
.. _alpha-unix-cstring-BufferOverlap: .. _alpha-unix-cstring-BufferOverlap:
alpha.unix.cstring.BufferOverlap (C) alpha.unix.cstring.BufferOverlap (C)
clang/include/clang-c/Index.h
@@ -1644,8 +1644,9 @@ enum CXCursorKind {
CXCursor_ObjCSelfExpr = 146, CXCursor_ObjCSelfExpr = 146,
/** OpenMP 5.0 [2.1.5, Array Section]. /** OpenMP 5.0 [2.1.5, Array Section].
+ * OpenACC 3.3 [2.7.1, Data Specification for Data Clauses (Sub Arrays)]
*/ */
- CXCursor_OMPArraySectionExpr = 147,+ CXCursor_ArraySectionExpr = 147,
/** Represents an @available(...) check. /** Represents an @available(...) check.
*/ */
clang/include/clang/APINotes/Types.h
@@ -675,6 +675,11 @@ class TagInfo : public CommonTypeInfo {
LLVM_PREFERRED_TYPE(bool) LLVM_PREFERRED_TYPE(bool)
unsigned IsFlagEnum : 1; unsigned IsFlagEnum : 1;
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned SwiftCopyableSpecified : 1;
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned SwiftCopyable : 1;
+
public: public:
std::optional<std::string> SwiftImportAs; std::optional<std::string> SwiftImportAs;
std::optional<std::string> SwiftRetainOp; std::optional<std::string> SwiftRetainOp;
@@ -682,7 +687,9 @@ public:
std::optional<EnumExtensibilityKind> EnumExtensibility; std::optional<EnumExtensibilityKind> EnumExtensibility;
- TagInfo() : HasFlagEnum(0), IsFlagEnum(0) {}+ TagInfo()
+ : HasFlagEnum(0), IsFlagEnum(0), SwiftCopyableSpecified(false),
+ SwiftCopyable(false) {}
std::optional<bool> isFlagEnum() const { std::optional<bool> isFlagEnum() const {
if (HasFlagEnum) if (HasFlagEnum)
@@ -694,6 +701,15 @@ public:
IsFlagEnum = Value.value_or(false); IsFlagEnum = Value.value_or(false);
} }
+ std::optional<bool> isSwiftCopyable() const {
+ return SwiftCopyableSpecified ? std::optional<bool>(SwiftCopyable)
+ : std::nullopt;
+ }
+ void setSwiftCopyable(std::optional<bool> Value) {
+ SwiftCopyableSpecified = Value.has_value();
+ SwiftCopyable = Value.value_or(false);
+ }
+
TagInfo &operator|=(const TagInfo &RHS) { TagInfo &operator|=(const TagInfo &RHS) {
static_cast<CommonTypeInfo &>(*this) |= RHS; static_cast<CommonTypeInfo &>(*this) |= RHS;
@@ -710,6 +726,9 @@ public:
if (!EnumExtensibility) if (!EnumExtensibility)
EnumExtensibility = RHS.EnumExtensibility; EnumExtensibility = RHS.EnumExtensibility;
+ if (!SwiftCopyableSpecified)
+ setSwiftCopyable(RHS.isSwiftCopyable());
+
return *this; return *this;
} }
@@ -724,6 +743,7 @@ inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) {
LHS.SwiftRetainOp == RHS.SwiftRetainOp && LHS.SwiftRetainOp == RHS.SwiftRetainOp &&
LHS.SwiftReleaseOp == RHS.SwiftReleaseOp && LHS.SwiftReleaseOp == RHS.SwiftReleaseOp &&
LHS.isFlagEnum() == RHS.isFlagEnum() && LHS.isFlagEnum() == RHS.isFlagEnum() &&
+ LHS.isSwiftCopyable() == RHS.isSwiftCopyable() &&
LHS.EnumExtensibility == RHS.EnumExtensibility; LHS.EnumExtensibility == RHS.EnumExtensibility;
} }
clang/include/clang/AST/ASTContext.h
@@ -455,7 +455,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// initialization of another module). /// initialization of another module).
struct PerModuleInitializers { struct PerModuleInitializers {
llvm::SmallVector<Decl*, 4> Initializers; llvm::SmallVector<Decl*, 4> Initializers;
- llvm::SmallVector<Decl::DeclID, 4> LazyInitializers;+ llvm::SmallVector<GlobalDeclID, 4> LazyInitializers;
void resolve(ASTContext &Ctx); void resolve(ASTContext &Ctx);
}; };
@@ -1059,7 +1059,7 @@ public:
/// or an ImportDecl nominating another module that has initializers. /// or an ImportDecl nominating another module that has initializers.
void addModuleInitializer(Module *M, Decl *Init); void addModuleInitializer(Module *M, Decl *Init);
- void addLazyModuleInitializers(Module *M, ArrayRef<Decl::DeclID> IDs);+ void addLazyModuleInitializers(Module *M, ArrayRef<GlobalDeclID> IDs);
/// Get the initializations to perform when importing a module, if any. /// Get the initializations to perform when importing a module, if any.
ArrayRef<Decl*> getModuleInitializers(Module *M); ArrayRef<Decl*> getModuleInitializers(Module *M);
@@ -1127,7 +1127,8 @@ public:
CanQualType OCLSamplerTy, OCLEventTy, OCLClkEventTy; CanQualType OCLSamplerTy, OCLEventTy, OCLClkEventTy;
CanQualType OCLQueueTy, OCLReserveIDTy; CanQualType OCLQueueTy, OCLReserveIDTy;
CanQualType IncompleteMatrixIdxTy; CanQualType IncompleteMatrixIdxTy;
- CanQualType OMPArraySectionTy, OMPArrayShapingTy, OMPIteratorTy;+ CanQualType ArraySectionTy;
+ CanQualType OMPArrayShapingTy, OMPIteratorTy;
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
CanQualType Id##Ty; CanQualType Id##Ty;
#include "clang/Basic/OpenCLExtensionTypes.def" #include "clang/Basic/OpenCLExtensionTypes.def"
@@ -2196,6 +2197,16 @@ public:
return getQualifiedType(type.getUnqualifiedType(), Qs); return getQualifiedType(type.getUnqualifiedType(), Qs);
} }
+ /// \brief Return a type with the given __ptrauth qualifier.
+ QualType getPointerAuthType(QualType Ty, PointerAuthQualifier PointerAuth) {
+ assert(!Ty.getPointerAuth());
+ assert(PointerAuth);
+
+ Qualifiers Qs;
+ Qs.setPointerAuth(PointerAuth);
+ return getQualifiedType(Ty, Qs);
+ }
+
unsigned char getFixedPointScale(QualType Ty) const; unsigned char getFixedPointScale(QualType Ty) const;
unsigned char getFixedPointIBits(QualType Ty) const; unsigned char getFixedPointIBits(QualType Ty) const;
llvm::FixedPointSemantics getFixedPointSemantics(QualType Ty) const; llvm::FixedPointSemantics getFixedPointSemantics(QualType Ty) const;
clang/include/clang/AST/ASTNodeTraverser.h
@@ -844,6 +844,12 @@ public:
} }
} }
+ void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *E) {
+ if (E->hasExplicitTemplateArgs())
+ for (auto Arg : E->template_arguments())
+ Visit(Arg.getArgument());
+ }
+
void VisitRequiresExpr(const RequiresExpr *E) { void VisitRequiresExpr(const RequiresExpr *E) {
for (auto *D : E->getLocalParameters()) for (auto *D : E->getLocalParameters())
Visit(D); Visit(D);
clang/include/clang/AST/AbstractBasicReader.h
@@ -213,9 +213,9 @@ public:
} }
Qualifiers readQualifiers() { Qualifiers readQualifiers() {
- static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint32_t),+ static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint64_t),
"update this if the value size changes"); "update this if the value size changes");
- uint32_t value = asImpl().readUInt32();+ uint64_t value = asImpl().readUInt64();
return Qualifiers::fromOpaqueValue(value); return Qualifiers::fromOpaqueValue(value);
} }
clang/include/clang/AST/AbstractBasicWriter.h
@@ -196,9 +196,9 @@ public:
} }
void writeQualifiers(Qualifiers value) { void writeQualifiers(Qualifiers value) {
- static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint32_t),+ static_assert(sizeof(value.getAsOpaqueValue()) <= sizeof(uint64_t),
"update this if the value size changes"); "update this if the value size changes");
- asImpl().writeUInt32(value.getAsOpaqueValue());+ asImpl().writeUInt64(value.getAsOpaqueValue());
} }
void writeExceptionSpecInfo( void writeExceptionSpecInfo(
clang/include/clang/AST/BuiltinTypes.def
@@ -320,7 +320,7 @@ PLACEHOLDER_TYPE(ARCUnbridgedCast, ARCUnbridgedCastTy)
PLACEHOLDER_TYPE(IncompleteMatrixIdx, IncompleteMatrixIdxTy) PLACEHOLDER_TYPE(IncompleteMatrixIdx, IncompleteMatrixIdxTy)
// A placeholder type for OpenMP array sections. // A placeholder type for OpenMP array sections.
-PLACEHOLDER_TYPE(OMPArraySection, OMPArraySectionTy)+PLACEHOLDER_TYPE(ArraySection, ArraySectionTy)
// A placeholder type for OpenMP array shaping operation. // A placeholder type for OpenMP array shaping operation.
PLACEHOLDER_TYPE(OMPArrayShaping, OMPArrayShapingTy) PLACEHOLDER_TYPE(OMPArrayShaping, OMPArrayShapingTy)
clang/include/clang/AST/ComputeDependence.h
@@ -94,7 +94,7 @@ class DesignatedInitExpr;
class ParenListExpr; class ParenListExpr;
class PseudoObjectExpr; class PseudoObjectExpr;
class AtomicExpr; class AtomicExpr;
-class OMPArraySectionExpr;+class ArraySectionExpr;
class OMPArrayShapingExpr; class OMPArrayShapingExpr;
class OMPIteratorExpr; class OMPIteratorExpr;
class ObjCArrayLiteral; class ObjCArrayLiteral;
@@ -189,7 +189,7 @@ ExprDependence computeDependence(ParenListExpr *E);
ExprDependence computeDependence(PseudoObjectExpr *E); ExprDependence computeDependence(PseudoObjectExpr *E);
ExprDependence computeDependence(AtomicExpr *E); ExprDependence computeDependence(AtomicExpr *E);
-ExprDependence computeDependence(OMPArraySectionExpr *E);+ExprDependence computeDependence(ArraySectionExpr *E);
ExprDependence computeDependence(OMPArrayShapingExpr *E); ExprDependence computeDependence(OMPArrayShapingExpr *E);
ExprDependence computeDependence(OMPIteratorExpr *E); ExprDependence computeDependence(OMPIteratorExpr *E);
clang/include/clang/AST/Decl.h
@@ -157,7 +157,7 @@ public:
SourceLocation CommentLoc, SourceLocation CommentLoc,
PragmaMSCommentKind CommentKind, PragmaMSCommentKind CommentKind,
StringRef Arg); StringRef Arg);
- static PragmaCommentDecl *CreateDeserialized(ASTContext &C, DeclID ID,+ static PragmaCommentDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
unsigned ArgSize); unsigned ArgSize);
PragmaMSCommentKind getCommentKind() const { return CommentKind; } PragmaMSCommentKind getCommentKind() const { return CommentKind; }
@@ -192,7 +192,7 @@ public:
SourceLocation Loc, StringRef Name, SourceLocation Loc, StringRef Name,
StringRef Value); StringRef Value);
static PragmaDetectMismatchDecl * static PragmaDetectMismatchDecl *
- CreateDeserialized(ASTContext &C, DeclID ID, unsigned NameValueSize);+ CreateDeserialized(ASTContext &C, GlobalDeclID ID, unsigned NameValueSize);
StringRef getName() const { return getTrailingObjects<char>(); } StringRef getName() const { return getTrailingObjects<char>(); }
StringRef getValue() const { return getTrailingObjects<char>() + ValueStart; } StringRef getValue() const { return getTrailingObjects<char>() + ValueStart; }
@@ -518,7 +518,7 @@ public:
static LabelDecl *Create(ASTContext &C, DeclContext *DC, static LabelDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation IdentL, IdentifierInfo *II, SourceLocation IdentL, IdentifierInfo *II,
SourceLocation GnuLabelL); SourceLocation GnuLabelL);
- static LabelDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static LabelDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
LabelStmt *getStmt() const { return TheStmt; } LabelStmt *getStmt() const { return TheStmt; }
void setStmt(LabelStmt *T) { TheStmt = T; } void setStmt(LabelStmt *T) { TheStmt = T; }
@@ -581,7 +581,7 @@ public:
IdentifierInfo *Id, NamespaceDecl *PrevDecl, IdentifierInfo *Id, NamespaceDecl *PrevDecl,
bool Nested); bool Nested);
- static NamespaceDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static NamespaceDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
using redecl_range = redeclarable_base::redecl_range; using redecl_range = redeclarable_base::redecl_range;
using redecl_iterator = redeclarable_base::redecl_iterator; using redecl_iterator = redeclarable_base::redecl_iterator;
@@ -1146,7 +1146,7 @@ public:
const IdentifierInfo *Id, QualType T, const IdentifierInfo *Id, QualType T,
TypeSourceInfo *TInfo, StorageClass S); TypeSourceInfo *TInfo, StorageClass S);
- static VarDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static VarDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
SourceRange getSourceRange() const override LLVM_READONLY; SourceRange getSourceRange() const override LLVM_READONLY;
@@ -1728,7 +1728,7 @@ public:
static ImplicitParamDecl *Create(ASTContext &C, QualType T, static ImplicitParamDecl *Create(ASTContext &C, QualType T,
ImplicitParamKind ParamKind); ImplicitParamKind ParamKind);
- static ImplicitParamDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static ImplicitParamDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
ImplicitParamDecl(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, ImplicitParamDecl(ASTContext &C, DeclContext *DC, SourceLocation IdLoc,
const IdentifierInfo *Id, QualType Type, const IdentifierInfo *Id, QualType Type,
@@ -1782,7 +1782,7 @@ public:
TypeSourceInfo *TInfo, StorageClass S, TypeSourceInfo *TInfo, StorageClass S,
Expr *DefArg); Expr *DefArg);
- static ParmVarDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static ParmVarDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
SourceRange getSourceRange() const override LLVM_READONLY; SourceRange getSourceRange() const override LLVM_READONLY;
@@ -2178,7 +2178,7 @@ public:
bool hasWrittenPrototype, ConstexprSpecKind ConstexprKind, bool hasWrittenPrototype, ConstexprSpecKind ConstexprKind,
Expr *TrailingRequiresClause); Expr *TrailingRequiresClause);
- static FunctionDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static FunctionDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
DeclarationNameInfo getNameInfo() const { DeclarationNameInfo getNameInfo() const {
return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
@@ -3136,7 +3136,7 @@ public:
TypeSourceInfo *TInfo, Expr *BW, bool Mutable, TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
InClassInitStyle InitStyle); InClassInitStyle InitStyle);
- static FieldDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static FieldDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
/// Returns the index of this field within its record, /// Returns the index of this field within its record,
/// as appropriate for passing to ASTRecordLayout::getFieldOffset. /// as appropriate for passing to ASTRecordLayout::getFieldOffset.
@@ -3311,7 +3311,7 @@ public:
SourceLocation L, IdentifierInfo *Id, SourceLocation L, IdentifierInfo *Id,
QualType T, Expr *E, QualType T, Expr *E,
const llvm::APSInt &V); const llvm::APSInt &V);
- static EnumConstantDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static EnumConstantDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
const Expr *getInitExpr() const { return (const Expr*) Init; } const Expr *getInitExpr() const { return (const Expr*) Init; }
Expr *getInitExpr() { return (Expr*) Init; } Expr *getInitExpr() { return (Expr*) Init; }
@@ -3357,7 +3357,7 @@ public:
QualType T, QualType T,
llvm::MutableArrayRef<NamedDecl *> CH); llvm::MutableArrayRef<NamedDecl *> CH);
- static IndirectFieldDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static IndirectFieldDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
using chain_iterator = ArrayRef<NamedDecl *>::const_iterator; using chain_iterator = ArrayRef<NamedDecl *>::const_iterator;
@@ -3542,7 +3542,7 @@ public:
static TypedefDecl *Create(ASTContext &C, DeclContext *DC, static TypedefDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc, SourceLocation StartLoc, SourceLocation IdLoc,
const IdentifierInfo *Id, TypeSourceInfo *TInfo); const IdentifierInfo *Id, TypeSourceInfo *TInfo);
- static TypedefDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static TypedefDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
SourceRange getSourceRange() const override LLVM_READONLY; SourceRange getSourceRange() const override LLVM_READONLY;
@@ -3567,7 +3567,7 @@ public:
static TypeAliasDecl *Create(ASTContext &C, DeclContext *DC, static TypeAliasDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc, SourceLocation StartLoc, SourceLocation IdLoc,
const IdentifierInfo *Id, TypeSourceInfo *TInfo); const IdentifierInfo *Id, TypeSourceInfo *TInfo);
- static TypeAliasDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static TypeAliasDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
SourceRange getSourceRange() const override LLVM_READONLY; SourceRange getSourceRange() const override LLVM_READONLY;
@@ -3977,7 +3977,7 @@ public:
IdentifierInfo *Id, EnumDecl *PrevDecl, IdentifierInfo *Id, EnumDecl *PrevDecl,
bool IsScoped, bool IsScopedUsingClassTag, bool IsScoped, bool IsScopedUsingClassTag,
bool IsFixed); bool IsFixed);
- static EnumDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static EnumDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
/// Overrides to provide correct range when there's an enum-base specifier /// Overrides to provide correct range when there's an enum-base specifier
/// with forward declarations. /// with forward declarations.
@@ -4182,7 +4182,7 @@ public:
static RecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, static RecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc, SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, RecordDecl* PrevDecl = nullptr); IdentifierInfo *Id, RecordDecl* PrevDecl = nullptr);
- static RecordDecl *CreateDeserialized(const ASTContext &C, DeclID ID);+ static RecordDecl *CreateDeserialized(const ASTContext &C, GlobalDeclID ID);
RecordDecl *getPreviousDecl() { RecordDecl *getPreviousDecl() {
return cast_or_null<RecordDecl>( return cast_or_null<RecordDecl>(
@@ -4433,7 +4433,7 @@ public:
StringLiteral *Str, SourceLocation AsmLoc, StringLiteral *Str, SourceLocation AsmLoc,
SourceLocation RParenLoc); SourceLocation RParenLoc);
- static FileScopeAsmDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static FileScopeAsmDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
SourceLocation getAsmLoc() const { return getLocation(); } SourceLocation getAsmLoc() const { return getLocation(); }
SourceLocation getRParenLoc() const { return RParenLoc; } SourceLocation getRParenLoc() const { return RParenLoc; }
@@ -4469,7 +4469,7 @@ class TopLevelStmtDecl : public Decl, public DeclContext {
public: public:
static TopLevelStmtDecl *Create(ASTContext &C, Stmt *Statement); static TopLevelStmtDecl *Create(ASTContext &C, Stmt *Statement);
- static TopLevelStmtDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static TopLevelStmtDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
SourceRange getSourceRange() const override LLVM_READONLY; SourceRange getSourceRange() const override LLVM_READONLY;
Stmt *getStmt() { return Statement; } Stmt *getStmt() { return Statement; }
@@ -4563,7 +4563,7 @@ protected:
public: public:
static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L);
- static BlockDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static BlockDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
SourceLocation getCaretLocation() const { return getLocation(); } SourceLocation getCaretLocation() const { return getLocation(); }
@@ -4717,7 +4717,7 @@ public:
static CapturedDecl *Create(ASTContext &C, DeclContext *DC, static CapturedDecl *Create(ASTContext &C, DeclContext *DC,
unsigned NumParams); unsigned NumParams);
- static CapturedDecl *CreateDeserialized(ASTContext &C, DeclID ID,+ static CapturedDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
unsigned NumParams); unsigned NumParams);
Stmt *getBody() const override; Stmt *getBody() const override;
@@ -4851,7 +4851,7 @@ public:
SourceLocation EndLoc); SourceLocation EndLoc);
/// Create a new, deserialized module import declaration. /// Create a new, deserialized module import declaration.
- static ImportDecl *CreateDeserialized(ASTContext &C, DeclID ID,+ static ImportDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
unsigned NumLocations); unsigned NumLocations);
/// Retrieve the module that was imported by the import declaration. /// Retrieve the module that was imported by the import declaration.
@@ -4892,7 +4892,7 @@ private:
public: public:
static ExportDecl *Create(ASTContext &C, DeclContext *DC, static ExportDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation ExportLoc); SourceLocation ExportLoc);
- static ExportDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static ExportDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
SourceLocation getExportLoc() const { return getLocation(); } SourceLocation getExportLoc() const { return getLocation(); }
SourceLocation getRBraceLoc() const { return RBraceLoc; } SourceLocation getRBraceLoc() const { return RBraceLoc; }
@@ -4931,7 +4931,7 @@ class EmptyDecl : public Decl {
public: public:
static EmptyDecl *Create(ASTContext &C, DeclContext *DC, static EmptyDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L); SourceLocation L);
- static EmptyDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static EmptyDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Empty; } static bool classofKind(Kind K) { return K == Empty; }
@@ -4957,7 +4957,7 @@ public:
bool CBuffer, SourceLocation KwLoc, bool CBuffer, SourceLocation KwLoc,
IdentifierInfo *ID, SourceLocation IDLoc, IdentifierInfo *ID, SourceLocation IDLoc,
SourceLocation LBrace); SourceLocation LBrace);
- static HLSLBufferDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static HLSLBufferDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
SourceRange getSourceRange() const override LLVM_READONLY { SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(getLocStart(), RBraceLoc); return SourceRange(getLocStart(), RBraceLoc);
clang/include/clang/AST/DeclBase.h
@@ -15,6 +15,7 @@
#include "clang/AST/ASTDumperUtils.h" #include "clang/AST/ASTDumperUtils.h"
#include "clang/AST/AttrIterator.h" #include "clang/AST/AttrIterator.h"
+#include "clang/AST/DeclID.h"
#include "clang/AST/DeclarationName.h" #include "clang/AST/DeclarationName.h"
#include "clang/AST/SelectorLocationsKind.h" #include "clang/AST/SelectorLocationsKind.h"
#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/IdentifierTable.h"
@@ -239,9 +240,6 @@ public:
ModulePrivate ModulePrivate
}; };
- /// An ID number that refers to a declaration in an AST file.
- using DeclID = uint32_t;
-
protected: protected:
/// The next declaration within the same lexical /// The next declaration within the same lexical
/// DeclContext. These pointers form the linked list that is /// DeclContext. These pointers form the linked list that is
@@ -361,7 +359,7 @@ protected:
/// \param Ctx The context in which we will allocate memory. /// \param Ctx The context in which we will allocate memory.
/// \param ID The global ID of the deserialized declaration. /// \param ID The global ID of the deserialized declaration.
/// \param Extra The amount of extra space to allocate after the object. /// \param Extra The amount of extra space to allocate after the object.
- void *operator new(std::size_t Size, const ASTContext &Ctx, DeclID ID,+ void *operator new(std::size_t Size, const ASTContext &Ctx, GlobalDeclID ID,
std::size_t Extra = 0); std::size_t Extra = 0);
/// Allocate memory for a non-deserialized declaration. /// Allocate memory for a non-deserialized declaration.
@@ -779,10 +777,10 @@ public:
/// Retrieve the global declaration ID associated with this /// Retrieve the global declaration ID associated with this
/// declaration, which specifies where this Decl was loaded from. /// declaration, which specifies where this Decl was loaded from.
- DeclID getGlobalID() const {+ GlobalDeclID getGlobalID() const {
if (isFromASTFile()) if (isFromASTFile())
- return *((const DeclID *)this - 1);+ return (*((const GlobalDeclID *)this - 1));
- return 0;+ return GlobalDeclID();
} }
/// Retrieve the global ID of the module that owns this particular /// Retrieve the global ID of the module that owns this particular
clang/include/clang/AST/DeclCXX.h
@@ -120,7 +120,7 @@ public:
return new (C, DC) AccessSpecDecl(AS, DC, ASLoc, ColonLoc); return new (C, DC) AccessSpecDecl(AS, DC, ASLoc, ColonLoc);
} }
- static AccessSpecDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static AccessSpecDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
// Implement isa/cast/dyncast/etc. // Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -579,7 +579,8 @@ public:
TypeSourceInfo *Info, SourceLocation Loc, TypeSourceInfo *Info, SourceLocation Loc,
unsigned DependencyKind, bool IsGeneric, unsigned DependencyKind, bool IsGeneric,
LambdaCaptureDefault CaptureDefault); LambdaCaptureDefault CaptureDefault);
- static CXXRecordDecl *CreateDeserialized(const ASTContext &C, DeclID ID);+ static CXXRecordDecl *CreateDeserialized(const ASTContext &C,
+ GlobalDeclID ID);
bool isDynamicClass() const { bool isDynamicClass() const {
return data().Polymorphic || data().NumVBases != 0; return data().Polymorphic || data().NumVBases != 0;
@@ -1980,7 +1981,8 @@ public:
CXXConstructorDecl *Ctor = nullptr, CXXConstructorDecl *Ctor = nullptr,
DeductionCandidate Kind = DeductionCandidate::Normal); DeductionCandidate Kind = DeductionCandidate::Normal);
- static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static CXXDeductionGuideDecl *CreateDeserialized(ASTContext &C,
+ GlobalDeclID ID);
ExplicitSpecifier getExplicitSpecifier() { return ExplicitSpec; } ExplicitSpecifier getExplicitSpecifier() { return ExplicitSpec; }
const ExplicitSpecifier getExplicitSpecifier() const { return ExplicitSpec; } const ExplicitSpecifier getExplicitSpecifier() const { return ExplicitSpec; }
@@ -2035,7 +2037,8 @@ public:
static RequiresExprBodyDecl *Create(ASTContext &C, DeclContext *DC, static RequiresExprBodyDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc); SourceLocation StartLoc);
- static RequiresExprBodyDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static RequiresExprBodyDecl *CreateDeserialized(ASTContext &C,
+ GlobalDeclID ID);
// Implement isa/cast/dyncast/etc. // Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -2078,7 +2081,7 @@ public:
ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, ConstexprSpecKind ConstexprKind, SourceLocation EndLocation,
Expr *TrailingRequiresClause = nullptr); Expr *TrailingRequiresClause = nullptr);
- static CXXMethodDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static CXXMethodDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
bool isStatic() const; bool isStatic() const;
bool isInstance() const { return !isStatic(); } bool isInstance() const { return !isStatic(); }
@@ -2579,7 +2582,7 @@ public:
friend class ASTDeclWriter; friend class ASTDeclWriter;
friend TrailingObjects; friend TrailingObjects;
- static CXXConstructorDecl *CreateDeserialized(ASTContext &C, DeclID ID,+ static CXXConstructorDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
uint64_t AllocKind); uint64_t AllocKind);
static CXXConstructorDecl * static CXXConstructorDecl *
Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
@@ -2822,7 +2825,7 @@ public:
bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared,
ConstexprSpecKind ConstexprKind, ConstexprSpecKind ConstexprKind,
Expr *TrailingRequiresClause = nullptr); Expr *TrailingRequiresClause = nullptr);
- static CXXDestructorDecl *CreateDeserialized(ASTContext & C, DeclID ID);+ static CXXDestructorDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg); void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg);
@@ -2881,7 +2884,7 @@ public:
bool UsesFPIntrin, bool isInline, ExplicitSpecifier ES, bool UsesFPIntrin, bool isInline, ExplicitSpecifier ES,
ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, ConstexprSpecKind ConstexprKind, SourceLocation EndLocation,
Expr *TrailingRequiresClause = nullptr); Expr *TrailingRequiresClause = nullptr);
- static CXXConversionDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static CXXConversionDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
ExplicitSpecifier getExplicitSpecifier() { ExplicitSpecifier getExplicitSpecifier() {
return getCanonicalDecl()->ExplicitSpec; return getCanonicalDecl()->ExplicitSpec;
@@ -2948,7 +2951,7 @@ public:
SourceLocation ExternLoc, SourceLocation ExternLoc,
SourceLocation LangLoc, SourceLocation LangLoc,
LinkageSpecLanguageIDs Lang, bool HasBraces); LinkageSpecLanguageIDs Lang, bool HasBraces);
- static LinkageSpecDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static LinkageSpecDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
/// Return the language specified by this linkage specification. /// Return the language specified by this linkage specification.
LinkageSpecLanguageIDs getLanguage() const { LinkageSpecLanguageIDs getLanguage() const {
@@ -3096,7 +3099,7 @@ public:
SourceLocation IdentLoc, SourceLocation IdentLoc,
NamedDecl *Nominated, NamedDecl *Nominated,
DeclContext *CommonAncestor); DeclContext *CommonAncestor);
- static UsingDirectiveDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static UsingDirectiveDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
SourceRange getSourceRange() const override LLVM_READONLY { SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(UsingLoc, getLocation()); return SourceRange(UsingLoc, getLocation());
@@ -3157,7 +3160,7 @@ public:
SourceLocation IdentLoc, SourceLocation IdentLoc,
NamedDecl *Namespace); NamedDecl *Namespace);
- static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
using redecl_range = redeclarable_base::redecl_range; using redecl_range = redeclarable_base::redecl_range;
using redecl_iterator = redeclarable_base::redecl_iterator; using redecl_iterator = redeclarable_base::redecl_iterator;
@@ -3254,7 +3257,7 @@ public:
LifetimeExtendedTemporaryDecl(Temp, EDec, Mangling); LifetimeExtendedTemporaryDecl(Temp, EDec, Mangling);
} }
static LifetimeExtendedTemporaryDecl *CreateDeserialized(ASTContext &C, static LifetimeExtendedTemporaryDecl *CreateDeserialized(ASTContext &C,
- DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) LifetimeExtendedTemporaryDecl(EmptyShell{}); return new (C, ID) LifetimeExtendedTemporaryDecl(EmptyShell{});
} }
@@ -3357,7 +3360,7 @@ public:
UsingShadowDecl(UsingShadow, C, DC, Loc, Name, Introducer, Target); UsingShadowDecl(UsingShadow, C, DC, Loc, Name, Introducer, Target);
} }
- static UsingShadowDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static UsingShadowDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
using redecl_range = redeclarable_base::redecl_range; using redecl_range = redeclarable_base::redecl_range;
using redecl_iterator = redeclarable_base::redecl_iterator; using redecl_iterator = redeclarable_base::redecl_iterator;
@@ -3566,7 +3569,7 @@ public:
const DeclarationNameInfo &NameInfo, const DeclarationNameInfo &NameInfo,
bool HasTypenameKeyword); bool HasTypenameKeyword);
- static UsingDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static UsingDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
SourceRange getSourceRange() const override LLVM_READONLY; SourceRange getSourceRange() const override LLVM_READONLY;
@@ -3645,7 +3648,7 @@ public:
UsingDecl *Using, NamedDecl *Target, UsingDecl *Using, NamedDecl *Target,
bool IsVirtual); bool IsVirtual);
static ConstructorUsingShadowDecl *CreateDeserialized(ASTContext &C, static ConstructorUsingShadowDecl *CreateDeserialized(ASTContext &C,
- DeclID ID);+ GlobalDeclID ID);
/// Override the UsingShadowDecl's getIntroducer, returning the UsingDecl that /// Override the UsingShadowDecl's getIntroducer, returning the UsingDecl that
/// introduced this. /// introduced this.
@@ -3757,7 +3760,7 @@ public:
SourceLocation UsingL, SourceLocation EnumL, SourceLocation UsingL, SourceLocation EnumL,
SourceLocation NameL, TypeSourceInfo *EnumType); SourceLocation NameL, TypeSourceInfo *EnumType);
- static UsingEnumDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static UsingEnumDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
SourceRange getSourceRange() const override LLVM_READONLY; SourceRange getSourceRange() const override LLVM_READONLY;
@@ -3830,7 +3833,7 @@ public:
NamedDecl *InstantiatedFrom, NamedDecl *InstantiatedFrom,
ArrayRef<NamedDecl *> UsingDecls); ArrayRef<NamedDecl *> UsingDecls);
- static UsingPackDecl *CreateDeserialized(ASTContext &C, DeclID ID,+ static UsingPackDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
unsigned NumExpansions); unsigned NumExpansions);
SourceRange getSourceRange() const override LLVM_READONLY { SourceRange getSourceRange() const override LLVM_READONLY {
@@ -3923,8 +3926,8 @@ public:
NestedNameSpecifierLoc QualifierLoc, NestedNameSpecifierLoc QualifierLoc,
const DeclarationNameInfo &NameInfo, SourceLocation EllipsisLoc); const DeclarationNameInfo &NameInfo, SourceLocation EllipsisLoc);
- static UnresolvedUsingValueDecl *+ static UnresolvedUsingValueDecl *CreateDeserialized(ASTContext &C,
- CreateDeserialized(ASTContext &C, DeclID ID);+ GlobalDeclID ID);
SourceRange getSourceRange() const override LLVM_READONLY; SourceRange getSourceRange() const override LLVM_READONLY;
@@ -4014,8 +4017,8 @@ public:
SourceLocation TargetNameLoc, DeclarationName TargetName, SourceLocation TargetNameLoc, DeclarationName TargetName,
SourceLocation EllipsisLoc); SourceLocation EllipsisLoc);
- static UnresolvedUsingTypenameDecl *+ static UnresolvedUsingTypenameDecl *CreateDeserialized(ASTContext &C,
- CreateDeserialized(ASTContext &C, DeclID ID);+ GlobalDeclID ID);
/// Retrieves the canonical declaration of this declaration. /// Retrieves the canonical declaration of this declaration.
UnresolvedUsingTypenameDecl *getCanonicalDecl() override { UnresolvedUsingTypenameDecl *getCanonicalDecl() override {
@@ -4045,7 +4048,7 @@ public:
SourceLocation Loc, SourceLocation Loc,
DeclarationName Name); DeclarationName Name);
static UnresolvedUsingIfExistsDecl *CreateDeserialized(ASTContext &Ctx, static UnresolvedUsingIfExistsDecl *CreateDeserialized(ASTContext &Ctx,
- DeclID ID);+ GlobalDeclID ID);
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Decl::UnresolvedUsingIfExists; } static bool classofKind(Kind K) { return K == Decl::UnresolvedUsingIfExists; }
@@ -4073,7 +4076,7 @@ public:
SourceLocation StaticAssertLoc, SourceLocation StaticAssertLoc,
Expr *AssertExpr, Expr *Message, Expr *AssertExpr, Expr *Message,
SourceLocation RParenLoc, bool Failed); SourceLocation RParenLoc, bool Failed);
- static StaticAssertDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static StaticAssertDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
Expr *getAssertExpr() { return AssertExprAndFailed.getPointer(); } Expr *getAssertExpr() { return AssertExprAndFailed.getPointer(); }
const Expr *getAssertExpr() const { return AssertExprAndFailed.getPointer(); } const Expr *getAssertExpr() const { return AssertExprAndFailed.getPointer(); }
@@ -4120,7 +4123,7 @@ public:
static BindingDecl *Create(ASTContext &C, DeclContext *DC, static BindingDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation IdLoc, IdentifierInfo *Id); SourceLocation IdLoc, IdentifierInfo *Id);
- static BindingDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static BindingDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
/// Get the expression to which this declaration is bound. This may be null /// Get the expression to which this declaration is bound. This may be null
/// in two different cases: while parsing the initializer for the /// in two different cases: while parsing the initializer for the
@@ -4189,7 +4192,7 @@ public:
QualType T, TypeSourceInfo *TInfo, QualType T, TypeSourceInfo *TInfo,
StorageClass S, StorageClass S,
ArrayRef<BindingDecl *> Bindings); ArrayRef<BindingDecl *> Bindings);
- static DecompositionDecl *CreateDeserialized(ASTContext &C, DeclID ID,+ static DecompositionDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
unsigned NumBindings); unsigned NumBindings);
ArrayRef<BindingDecl *> bindings() const { ArrayRef<BindingDecl *> bindings() const {
@@ -4246,7 +4249,7 @@ public:
SourceLocation L, DeclarationName N, QualType T, SourceLocation L, DeclarationName N, QualType T,
TypeSourceInfo *TInfo, SourceLocation StartL, TypeSourceInfo *TInfo, SourceLocation StartL,
IdentifierInfo *Getter, IdentifierInfo *Setter); IdentifierInfo *Getter, IdentifierInfo *Setter);
- static MSPropertyDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static MSPropertyDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
static bool classof(const Decl *D) { return D->getKind() == MSProperty; } static bool classof(const Decl *D) { return D->getKind() == MSProperty; }
@@ -4300,7 +4303,7 @@ private:
MSGuidDecl(DeclContext *DC, QualType T, Parts P); MSGuidDecl(DeclContext *DC, QualType T, Parts P);
static MSGuidDecl *Create(const ASTContext &C, QualType T, Parts P); static MSGuidDecl *Create(const ASTContext &C, QualType T, Parts P);
- static MSGuidDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static MSGuidDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
// Only ASTContext::getMSGuidDecl and deserialization create these. // Only ASTContext::getMSGuidDecl and deserialization create these.
friend class ASTContext; friend class ASTContext;
@@ -4353,7 +4356,7 @@ class UnnamedGlobalConstantDecl : public ValueDecl,
static UnnamedGlobalConstantDecl *Create(const ASTContext &C, QualType T, static UnnamedGlobalConstantDecl *Create(const ASTContext &C, QualType T,
const APValue &APVal); const APValue &APVal);
static UnnamedGlobalConstantDecl *CreateDeserialized(ASTContext &C, static UnnamedGlobalConstantDecl *CreateDeserialized(ASTContext &C,
- DeclID ID);+ GlobalDeclID ID);
// Only ASTContext::getUnnamedGlobalConstantDecl and deserialization create // Only ASTContext::getUnnamedGlobalConstantDecl and deserialization create
// these. // these.
clang/include/clang/AST/DeclContextInternals.h
@@ -42,11 +42,12 @@ class StoredDeclsList {
/// external declarations. /// external declarations.
DeclsAndHasExternalTy Data; DeclsAndHasExternalTy Data;
- template<typename Fn>+ template <typename Fn> DeclListNode::Decls *erase_if(Fn ShouldErase) {
- void erase_if(Fn ShouldErase) {
Decls List = Data.getPointer(); Decls List = Data.getPointer();
+
if (!List) if (!List)
- return;+ return nullptr;
+
ASTContext &C = getASTContext(); ASTContext &C = getASTContext();
DeclListNode::Decls NewHead = nullptr; DeclListNode::Decls NewHead = nullptr;
DeclListNode::Decls *NewLast = nullptr; DeclListNode::Decls *NewLast = nullptr;
@@ -79,6 +80,17 @@ class StoredDeclsList {
Data.setPointer(NewHead); Data.setPointer(NewHead);
assert(llvm::none_of(getLookupResult(), ShouldErase) && "Still exists!"); assert(llvm::none_of(getLookupResult(), ShouldErase) && "Still exists!");
+
+ if (!Data.getPointer())
+ // All declarations are erased.
+ return nullptr;
+ else if (NewHead.is<NamedDecl *>())
+ // The list only contains a declaration, the header itself.
+ return (DeclListNode::Decls *)&Data;
+ else {
+ assert(NewLast && NewLast->is<NamedDecl *>() && "Not the tail?");
+ return NewLast;
+ }
} }
void erase(NamedDecl *ND) { void erase(NamedDecl *ND) {
@@ -160,12 +172,16 @@ public:
void replaceExternalDecls(ArrayRef<NamedDecl*> Decls) { void replaceExternalDecls(ArrayRef<NamedDecl*> Decls) {
// Remove all declarations that are either external or are replaced with // Remove all declarations that are either external or are replaced with
- // external declarations.+ // external declarations with higher visibilities.
- erase_if([Decls](NamedDecl *ND) {+ DeclListNode::Decls *Tail = erase_if([Decls](NamedDecl *ND) {
if (ND->isFromASTFile()) if (ND->isFromASTFile())
return true; return true;
+ // FIXME: Can we get rid of this loop completely?
for (NamedDecl *D : Decls) for (NamedDecl *D : Decls)
- if (D->declarationReplaces(ND, /*IsKnownNewer=*/false))+ // Only replace the local declaration if the external declaration has
+ // higher visibilities.
+ if (D->getModuleOwnershipKind() <= ND->getModuleOwnershipKind() &&
+ D->declarationReplaces(ND, /*IsKnownNewer=*/false))
return true; return true;
return false; return false;
}); });
@@ -185,24 +201,15 @@ public:
DeclsAsList = Node; DeclsAsList = Node;
} }
- DeclListNode::Decls Head = Data.getPointer();+ if (!Data.getPointer()) {
- if (Head.isNull()) {
Data.setPointer(DeclsAsList); Data.setPointer(DeclsAsList);
return; return;
} }
- // Find the end of the existing list.
- // FIXME: It would be possible to preserve information from erase_if to
- // avoid this rescan looking for the end of the list.
- DeclListNode::Decls *Tail = &Head;
- while (DeclListNode *Node = Tail->dyn_cast<DeclListNode *>())
- Tail = &Node->Rest;
-
// Append the Decls. // Append the Decls.
DeclListNode *Node = C.AllocateDeclListNode(Tail->get<NamedDecl *>()); DeclListNode *Node = C.AllocateDeclListNode(Tail->get<NamedDecl *>());
Node->Rest = DeclsAsList; Node->Rest = DeclsAsList;
*Tail = Node; *Tail = Node;
- Data.setPointer(Head);
} }
/// Return the list of all the decls. /// Return the list of all the decls.
clang/include/clang/AST/DeclFriend.h
@@ -112,7 +112,7 @@ public:
Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend_, Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend_,
SourceLocation FriendL, SourceLocation FriendL,
ArrayRef<TemplateParameterList *> FriendTypeTPLists = std::nullopt); ArrayRef<TemplateParameterList *> FriendTypeTPLists = std::nullopt);
- static FriendDecl *CreateDeserialized(ASTContext &C, DeclID ID,+ static FriendDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
unsigned FriendTypeNumTPLists); unsigned FriendTypeNumTPLists);
/// If this friend declaration names an (untemplated but possibly /// If this friend declaration names an (untemplated but possibly
clang/include/clang/AST/DeclID.h
@@ -0,0 +1,227 @@
+//===--- DeclID.h - ID number for deserialized declarations ----*- 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 DeclID class family to describe the deserialized
+// declarations. The DeclID is widely used in AST via LazyDeclPtr, or calls to
+// `ExternalASTSource::getExternalDecl`. It will be helpful for type safety to
+// require the use of `DeclID` to explicit.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_DECLID_H
+#define LLVM_CLANG_AST_DECLID_H
+
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/iterator.h"
+
+namespace clang {
+
+/// Predefined declaration IDs.
+///
+/// These declaration IDs correspond to predefined declarations in the AST
+/// context, such as the NULL declaration ID. Such declarations are never
+/// actually serialized, since they will be built by the AST context when
+/// it is created.
+enum PredefinedDeclIDs {
+ /// The NULL declaration.
+ PREDEF_DECL_NULL_ID = 0,
+
+ /// The translation unit.
+ PREDEF_DECL_TRANSLATION_UNIT_ID = 1,
+
+ /// The Objective-C 'id' type.
+ PREDEF_DECL_OBJC_ID_ID = 2,
+
+ /// The Objective-C 'SEL' type.
+ PREDEF_DECL_OBJC_SEL_ID = 3,
+
+ /// The Objective-C 'Class' type.
+ PREDEF_DECL_OBJC_CLASS_ID = 4,
+
+ /// The Objective-C 'Protocol' type.
+ PREDEF_DECL_OBJC_PROTOCOL_ID = 5,
+
+ /// The signed 128-bit integer type.
+ PREDEF_DECL_INT_128_ID = 6,
+
+ /// The unsigned 128-bit integer type.
+ PREDEF_DECL_UNSIGNED_INT_128_ID = 7,
+
+ /// The internal 'instancetype' typedef.
+ PREDEF_DECL_OBJC_INSTANCETYPE_ID = 8,
+
+ /// The internal '__builtin_va_list' typedef.
+ PREDEF_DECL_BUILTIN_VA_LIST_ID = 9,
+
+ /// The internal '__va_list_tag' struct, if any.
+ PREDEF_DECL_VA_LIST_TAG = 10,
+
+ /// The internal '__builtin_ms_va_list' typedef.
+ PREDEF_DECL_BUILTIN_MS_VA_LIST_ID = 11,
+
+ /// The predeclared '_GUID' struct.
+ PREDEF_DECL_BUILTIN_MS_GUID_ID = 12,
+
+ /// The extern "C" context.
+ PREDEF_DECL_EXTERN_C_CONTEXT_ID = 13,
+
+ /// The internal '__make_integer_seq' template.
+ PREDEF_DECL_MAKE_INTEGER_SEQ_ID = 14,
+
+ /// The internal '__NSConstantString' typedef.
+ PREDEF_DECL_CF_CONSTANT_STRING_ID = 15,
+
+ /// The internal '__NSConstantString' tag type.
+ PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID = 16,
+
+ /// The internal '__type_pack_element' template.
+ PREDEF_DECL_TYPE_PACK_ELEMENT_ID = 17,
+};
+
+/// The number of declaration IDs that are predefined.
+///
+/// For more information about predefined declarations, see the
+/// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants.
+const unsigned int NUM_PREDEF_DECL_IDS = 18;
+
+/// GlobalDeclID means DeclID in the current ASTContext and LocalDeclID means
+/// DeclID specific to a certain ModuleFile. Specially, in ASTWriter, the
+/// LocalDeclID to the ModuleFile been writting is equal to the GlobalDeclID.
+/// Outside the serializer, all the DeclID been used should be GlobalDeclID.
+/// We can translate a LocalDeclID to the GlobalDeclID by
+/// `ASTReader::getGlobalDeclID()`.
+
+class DeclIDBase {
+public:
+ /// An ID number that refers to a declaration in an AST file.
+ ///
+ /// The ID numbers of declarations are consecutive (in order of
+ /// discovery), with values below NUM_PREDEF_DECL_IDS being reserved.
+ /// At the start of a chain of precompiled headers, declaration ID 1 is
+ /// used for the translation unit declaration.
+ ///
+ /// DeclID should only be used directly in serialization. All other users
+ /// should use LocalDeclID or GlobalDeclID.
+ using DeclID = uint32_t;
+
+protected:
+ DeclIDBase() : ID(PREDEF_DECL_NULL_ID) {}
+ explicit DeclIDBase(DeclID ID) : ID(ID) {}
+
+public:
+ DeclID get() const { return ID; }
+
+ explicit operator DeclID() const { return ID; }
+
+ explicit operator PredefinedDeclIDs() const { return (PredefinedDeclIDs)ID; }
+
+ bool isValid() const { return ID != PREDEF_DECL_NULL_ID; }
+
+ bool isInvalid() const { return ID == PREDEF_DECL_NULL_ID; }
+
+ friend bool operator==(const DeclIDBase &LHS, const DeclIDBase &RHS) {
+ return LHS.ID == RHS.ID;
+ }
+ friend bool operator!=(const DeclIDBase &LHS, const DeclIDBase &RHS) {
+ return LHS.ID != RHS.ID;
+ }
+ // We may sort the decl ID.
+ friend bool operator<(const DeclIDBase &LHS, const DeclIDBase &RHS) {
+ return LHS.ID < RHS.ID;
+ }
+ friend bool operator>(const DeclIDBase &LHS, const DeclIDBase &RHS) {
+ return LHS.ID > RHS.ID;
+ }
+ friend bool operator<=(const DeclIDBase &LHS, const DeclIDBase &RHS) {
+ return LHS.ID <= RHS.ID;
+ }
+ friend bool operator>=(const DeclIDBase &LHS, const DeclIDBase &RHS) {
+ return LHS.ID >= RHS.ID;
+ }
+
+protected:
+ DeclID ID;
+};
+
+class LocalDeclID : public DeclIDBase {
+ using Base = DeclIDBase;
+
+public:
+ LocalDeclID() : Base() {}
+ LocalDeclID(PredefinedDeclIDs ID) : Base(ID) {}
+ explicit LocalDeclID(DeclID ID) : Base(ID) {}
+
+ LocalDeclID &operator++() {
+ ++ID;
+ return *this;
+ }
+
+ LocalDeclID operator++(int) {
+ LocalDeclID Ret = *this;
+ ++(*this);
+ return Ret;
+ }
+};
+
+class GlobalDeclID : public DeclIDBase {
+ using Base = DeclIDBase;
+
+public:
+ GlobalDeclID() : Base() {}
+ explicit GlobalDeclID(DeclID ID) : Base(ID) {}
+
+ // For DeclIDIterator<GlobalDeclID> to be able to convert a GlobalDeclID
+ // to a LocalDeclID.
+ explicit operator LocalDeclID() const { return LocalDeclID(this->ID); }
+};
+
+/// A helper iterator adaptor to convert the iterators to
+/// `SmallVector<SomeDeclID>` to the iterators to `SmallVector<OtherDeclID>`.
+template <class FromTy, class ToTy>
+class DeclIDIterator
+ : public llvm::iterator_adaptor_base<DeclIDIterator<FromTy, ToTy>,
+ const FromTy *,
+ std::forward_iterator_tag, ToTy> {
+public:
+ DeclIDIterator() : DeclIDIterator::iterator_adaptor_base(nullptr) {}
+
+ DeclIDIterator(const FromTy *ID)
+ : DeclIDIterator::iterator_adaptor_base(ID) {}
+
+ ToTy operator*() const { return ToTy(*this->I); }
+
+ bool operator==(const DeclIDIterator &RHS) const { return this->I == RHS.I; }
+};
+
+} // namespace clang
+
+namespace llvm {
+template <> struct DenseMapInfo<clang::GlobalDeclID> {
+ using GlobalDeclID = clang::GlobalDeclID;
+ using DeclID = GlobalDeclID::DeclID;
+
+ static GlobalDeclID getEmptyKey() {
+ return GlobalDeclID(DenseMapInfo<DeclID>::getEmptyKey());
+ }
+
+ static GlobalDeclID getTombstoneKey() {
+ return GlobalDeclID(DenseMapInfo<DeclID>::getTombstoneKey());
+ }
+
+ static unsigned getHashValue(const GlobalDeclID &Key) {
+ return DenseMapInfo<DeclID>::getHashValue(Key.get());
+ }
+
+ static bool isEqual(const GlobalDeclID &L, const GlobalDeclID &R) {
+ return L == R;
+ }
+};
+
+} // namespace llvm
+
+#endif
clang/include/clang/AST/DeclObjC.h
@@ -236,7 +236,7 @@ public:
ObjCImplementationControl impControl = ObjCImplementationControl::None, ObjCImplementationControl impControl = ObjCImplementationControl::None,
bool HasRelatedResultType = false); bool HasRelatedResultType = false);
- static ObjCMethodDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static ObjCMethodDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
ObjCMethodDecl *getCanonicalDecl() override; ObjCMethodDecl *getCanonicalDecl() override;
const ObjCMethodDecl *getCanonicalDecl() const { const ObjCMethodDecl *getCanonicalDecl() const {
@@ -614,7 +614,8 @@ public:
IdentifierInfo *name, IdentifierInfo *name,
SourceLocation colonLoc, SourceLocation colonLoc,
TypeSourceInfo *boundInfo); TypeSourceInfo *boundInfo);
- static ObjCTypeParamDecl *CreateDeserialized(ASTContext &ctx, DeclID ID);+ static ObjCTypeParamDecl *CreateDeserialized(ASTContext &ctx,
+ GlobalDeclID ID);
SourceRange getSourceRange() const override LLVM_READONLY; SourceRange getSourceRange() const override LLVM_READONLY;
@@ -789,7 +790,7 @@ public:
TypeSourceInfo *TSI, TypeSourceInfo *TSI,
PropertyControl propControl = None); PropertyControl propControl = None);
- static ObjCPropertyDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static ObjCPropertyDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
SourceLocation getAtLoc() const { return AtLoc; } SourceLocation getAtLoc() const { return AtLoc; }
void setAtLoc(SourceLocation L) { AtLoc = L; } void setAtLoc(SourceLocation L) { AtLoc = L; }
@@ -1279,7 +1280,8 @@ public:
ObjCInterfaceDecl *PrevDecl, ObjCInterfaceDecl *PrevDecl,
SourceLocation ClassLoc = SourceLocation(), bool isInternal = false); SourceLocation ClassLoc = SourceLocation(), bool isInternal = false);
- static ObjCInterfaceDecl *CreateDeserialized(const ASTContext &C, DeclID ID);+ static ObjCInterfaceDecl *CreateDeserialized(const ASTContext &C,
+ GlobalDeclID ID);
/// Retrieve the type parameters of this class. /// Retrieve the type parameters of this class.
/// ///
@@ -1969,7 +1971,7 @@ public:
TypeSourceInfo *TInfo, AccessControl ac, TypeSourceInfo *TInfo, AccessControl ac,
Expr *BW = nullptr, bool synthesized = false); Expr *BW = nullptr, bool synthesized = false);
- static ObjCIvarDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static ObjCIvarDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
/// Return the class interface that this ivar is logically contained /// Return the class interface that this ivar is logically contained
/// in; this is either the interface where the ivar was declared, or the /// in; this is either the interface where the ivar was declared, or the
@@ -2039,7 +2041,8 @@ public:
SourceLocation IdLoc, IdentifierInfo *Id, SourceLocation IdLoc, IdentifierInfo *Id,
QualType T, Expr *BW); QualType T, Expr *BW);
- static ObjCAtDefsFieldDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static ObjCAtDefsFieldDecl *CreateDeserialized(ASTContext &C,
+ GlobalDeclID ID);
// Implement isa/cast/dyncast/etc. // Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -2142,7 +2145,7 @@ public:
SourceLocation atStartLoc, SourceLocation atStartLoc,
ObjCProtocolDecl *PrevDecl); ObjCProtocolDecl *PrevDecl);
- static ObjCProtocolDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static ObjCProtocolDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
const ObjCProtocolList &getReferencedProtocols() const { const ObjCProtocolList &getReferencedProtocols() const {
assert(hasDefinition() && "No definition available!"); assert(hasDefinition() && "No definition available!");
@@ -2361,7 +2364,7 @@ public:
ObjCTypeParamList *typeParamList, ObjCTypeParamList *typeParamList,
SourceLocation IvarLBraceLoc = SourceLocation(), SourceLocation IvarLBraceLoc = SourceLocation(),
SourceLocation IvarRBraceLoc = SourceLocation()); SourceLocation IvarRBraceLoc = SourceLocation());
- static ObjCCategoryDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static ObjCCategoryDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
ObjCInterfaceDecl *getClassInterface() { return ClassInterface; } ObjCInterfaceDecl *getClassInterface() { return ClassInterface; }
const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; } const ObjCInterfaceDecl *getClassInterface() const { return ClassInterface; }
@@ -2558,7 +2561,8 @@ public:
Create(ASTContext &C, DeclContext *DC, const IdentifierInfo *Id, Create(ASTContext &C, DeclContext *DC, const IdentifierInfo *Id,
ObjCInterfaceDecl *classInterface, SourceLocation nameLoc, ObjCInterfaceDecl *classInterface, SourceLocation nameLoc,
SourceLocation atStartLoc, SourceLocation CategoryNameLoc); SourceLocation atStartLoc, SourceLocation CategoryNameLoc);
- static ObjCCategoryImplDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static ObjCCategoryImplDecl *CreateDeserialized(ASTContext &C,
+ GlobalDeclID ID);
ObjCCategoryDecl *getCategoryDecl() const; ObjCCategoryDecl *getCategoryDecl() const;
@@ -2640,7 +2644,8 @@ public:
SourceLocation IvarLBraceLoc=SourceLocation(), SourceLocation IvarLBraceLoc=SourceLocation(),
SourceLocation IvarRBraceLoc=SourceLocation()); SourceLocation IvarRBraceLoc=SourceLocation());
- static ObjCImplementationDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static ObjCImplementationDecl *CreateDeserialized(ASTContext &C,
+ GlobalDeclID ID);
/// init_iterator - Iterates through the ivar initializer list. /// init_iterator - Iterates through the ivar initializer list.
using init_iterator = CXXCtorInitializer **; using init_iterator = CXXCtorInitializer **;
@@ -2780,7 +2785,7 @@ public:
ObjCInterfaceDecl* aliasedClass); ObjCInterfaceDecl* aliasedClass);
static ObjCCompatibleAliasDecl *CreateDeserialized(ASTContext &C, static ObjCCompatibleAliasDecl *CreateDeserialized(ASTContext &C,
- DeclID ID);+ GlobalDeclID ID);
const ObjCInterfaceDecl *getClassInterface() const { return AliasedClass; } const ObjCInterfaceDecl *getClassInterface() const { return AliasedClass; }
ObjCInterfaceDecl *getClassInterface() { return AliasedClass; } ObjCInterfaceDecl *getClassInterface() { return AliasedClass; }
@@ -2851,7 +2856,8 @@ public:
ObjCIvarDecl *ivarDecl, ObjCIvarDecl *ivarDecl,
SourceLocation ivarLoc); SourceLocation ivarLoc);
- static ObjCPropertyImplDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static ObjCPropertyImplDecl *CreateDeserialized(ASTContext &C,
+ GlobalDeclID ID);
SourceRange getSourceRange() const override LLVM_READONLY; SourceRange getSourceRange() const override LLVM_READONLY;
clang/include/clang/AST/DeclOpenMP.h
@@ -59,7 +59,7 @@ protected:
} }
template <typename T, typename... Params> template <typename T, typename... Params>
- static T *createEmptyDirective(const ASTContext &C, unsigned ID,+ static T *createEmptyDirective(const ASTContext &C, GlobalDeclID ID,
unsigned NumClauses, unsigned NumChildren, unsigned NumClauses, unsigned NumChildren,
Params &&... P) { Params &&... P) {
auto *Inst = new (C, ID, size(NumClauses, NumChildren)) auto *Inst = new (C, ID, size(NumClauses, NumChildren))
@@ -133,7 +133,7 @@ public:
SourceLocation L, SourceLocation L,
ArrayRef<Expr *> VL); ArrayRef<Expr *> VL);
static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C, static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C,
- DeclID ID, unsigned N);+ GlobalDeclID ID, unsigned N);
typedef MutableArrayRef<Expr *>::iterator varlist_iterator; typedef MutableArrayRef<Expr *>::iterator varlist_iterator;
typedef ArrayRef<const Expr *>::iterator varlist_const_iterator; typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
@@ -214,7 +214,7 @@ public:
QualType T, OMPDeclareReductionDecl *PrevDeclInScope); QualType T, OMPDeclareReductionDecl *PrevDeclInScope);
/// Create deserialized declare reduction node. /// Create deserialized declare reduction node.
static OMPDeclareReductionDecl *CreateDeserialized(ASTContext &C, static OMPDeclareReductionDecl *CreateDeserialized(ASTContext &C,
- DeclID ID);+ GlobalDeclID ID);
/// Get combiner expression of the declare reduction construct. /// Get combiner expression of the declare reduction construct.
Expr *getCombiner() { return Combiner; } Expr *getCombiner() { return Combiner; }
@@ -318,8 +318,8 @@ public:
ArrayRef<OMPClause *> Clauses, ArrayRef<OMPClause *> Clauses,
OMPDeclareMapperDecl *PrevDeclInScope); OMPDeclareMapperDecl *PrevDeclInScope);
/// Creates deserialized declare mapper node. /// Creates deserialized declare mapper node.
- static OMPDeclareMapperDecl *CreateDeserialized(ASTContext &C, DeclID ID,+ static OMPDeclareMapperDecl *CreateDeserialized(ASTContext &C,
- unsigned N);+ GlobalDeclID ID, unsigned N);
using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator; using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator;
using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator; using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator;
@@ -397,7 +397,8 @@ public:
IdentifierInfo *Id, QualType T, IdentifierInfo *Id, QualType T,
SourceLocation StartLoc); SourceLocation StartLoc);
- static OMPCapturedExprDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static OMPCapturedExprDecl *CreateDeserialized(ASTContext &C,
+ GlobalDeclID ID);
SourceRange getSourceRange() const override LLVM_READONLY; SourceRange getSourceRange() const override LLVM_READONLY;
@@ -427,7 +428,7 @@ public:
static OMPRequiresDecl *Create(ASTContext &C, DeclContext *DC, static OMPRequiresDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, ArrayRef<OMPClause *> CL); SourceLocation L, ArrayRef<OMPClause *> CL);
/// Create deserialized requires node. /// Create deserialized requires node.
- static OMPRequiresDecl *CreateDeserialized(ASTContext &C, DeclID ID,+ static OMPRequiresDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
unsigned N); unsigned N);
using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator; using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator;
@@ -495,7 +496,7 @@ public:
static OMPAllocateDecl *Create(ASTContext &C, DeclContext *DC, static OMPAllocateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, ArrayRef<Expr *> VL, SourceLocation L, ArrayRef<Expr *> VL,
ArrayRef<OMPClause *> CL); ArrayRef<OMPClause *> CL);
- static OMPAllocateDecl *CreateDeserialized(ASTContext &C, DeclID ID,+ static OMPAllocateDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
unsigned NVars, unsigned NClauses); unsigned NVars, unsigned NClauses);
typedef MutableArrayRef<Expr *>::iterator varlist_iterator; typedef MutableArrayRef<Expr *>::iterator varlist_iterator;
clang/include/clang/AST/DeclTemplate.h
@@ -797,7 +797,7 @@ protected:
/// ///
/// The first value in the array is the number of specializations/partial /// The first value in the array is the number of specializations/partial
/// specializations that follow. /// specializations that follow.
- Decl::DeclID *LazySpecializations = nullptr;+ GlobalDeclID *LazySpecializations = nullptr;
/// The set of "injected" template arguments used within this /// The set of "injected" template arguments used within this
/// template. /// template.
@@ -1087,7 +1087,8 @@ public:
NamedDecl *Decl); NamedDecl *Decl);
/// Create an empty function template node. /// Create an empty function template node.
- static FunctionTemplateDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static FunctionTemplateDecl *CreateDeserialized(ASTContext &C,
+ GlobalDeclID ID);
// Implement isa/cast/dyncast support // Implement isa/cast/dyncast support
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -1204,9 +1205,9 @@ public:
bool Typename, bool ParameterPack, bool HasTypeConstraint = false, bool Typename, bool ParameterPack, bool HasTypeConstraint = false,
std::optional<unsigned> NumExpanded = std::nullopt); std::optional<unsigned> NumExpanded = std::nullopt);
static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C, static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C,
- DeclID ID);+ GlobalDeclID ID);
static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C, static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C,
- DeclID ID,+ GlobalDeclID ID,
bool HasTypeConstraint); bool HasTypeConstraint);
/// Whether this template type parameter was declared with /// Whether this template type parameter was declared with
@@ -1413,11 +1414,10 @@ public:
QualType T, TypeSourceInfo *TInfo, ArrayRef<QualType> ExpandedTypes, QualType T, TypeSourceInfo *TInfo, ArrayRef<QualType> ExpandedTypes,
ArrayRef<TypeSourceInfo *> ExpandedTInfos); ArrayRef<TypeSourceInfo *> ExpandedTInfos);
+ static NonTypeTemplateParmDecl *
+ CreateDeserialized(ASTContext &C, GlobalDeclID ID, bool HasTypeConstraint);
static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C, static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C,
- DeclID ID,+ GlobalDeclID ID,
- bool HasTypeConstraint);
- static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C,
- DeclID ID,
unsigned NumExpandedTypes, unsigned NumExpandedTypes,
bool HasTypeConstraint); bool HasTypeConstraint);
@@ -1632,10 +1632,9 @@ public:
ArrayRef<TemplateParameterList *> Expansions); ArrayRef<TemplateParameterList *> Expansions);
static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C, static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C,
- DeclID ID);+ GlobalDeclID ID);
- static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C,+ static TemplateTemplateParmDecl *
- DeclID ID,+ CreateDeserialized(ASTContext &C, GlobalDeclID ID, unsigned NumExpansions);
- unsigned NumExpansions);
using TemplateParmPosition::getDepth; using TemplateParmPosition::getDepth;
using TemplateParmPosition::setDepth; using TemplateParmPosition::setDepth;
@@ -1857,8 +1856,8 @@ public:
ClassTemplateDecl *SpecializedTemplate, ClassTemplateDecl *SpecializedTemplate,
ArrayRef<TemplateArgument> Args, ArrayRef<TemplateArgument> Args,
ClassTemplateSpecializationDecl *PrevDecl); ClassTemplateSpecializationDecl *PrevDecl);
- static ClassTemplateSpecializationDecl *+ static ClassTemplateSpecializationDecl *CreateDeserialized(ASTContext &C,
- CreateDeserialized(ASTContext &C, DeclID ID);+ GlobalDeclID ID);
void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy,
bool Qualified) const override; bool Qualified) const override;
@@ -2110,7 +2109,7 @@ public:
ClassTemplatePartialSpecializationDecl *PrevDecl); ClassTemplatePartialSpecializationDecl *PrevDecl);
static ClassTemplatePartialSpecializationDecl * static ClassTemplatePartialSpecializationDecl *
- CreateDeserialized(ASTContext &C, DeclID ID);+ CreateDeserialized(ASTContext &C, GlobalDeclID ID);
ClassTemplatePartialSpecializationDecl *getMostRecentDecl() { ClassTemplatePartialSpecializationDecl *getMostRecentDecl() {
return cast<ClassTemplatePartialSpecializationDecl>( return cast<ClassTemplatePartialSpecializationDecl>(
@@ -2306,7 +2305,7 @@ public:
NamedDecl *Decl); NamedDecl *Decl);
/// Create an empty class template node. /// Create an empty class template node.
- static ClassTemplateDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static ClassTemplateDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
/// Return the specialization with the provided arguments if it exists, /// Return the specialization with the provided arguments if it exists,
/// otherwise return the insertion point. /// otherwise return the insertion point.
@@ -2472,7 +2471,7 @@ public:
MutableArrayRef<TemplateParameterList *> Params, FriendUnion Friend, MutableArrayRef<TemplateParameterList *> Params, FriendUnion Friend,
SourceLocation FriendLoc); SourceLocation FriendLoc);
- static FriendTemplateDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static FriendTemplateDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
/// If this friend declaration names a templated type (or /// If this friend declaration names a templated type (or
/// a dependent member type of a templated type), return that /// a dependent member type of a templated type), return that
@@ -2573,7 +2572,8 @@ public:
NamedDecl *Decl); NamedDecl *Decl);
/// Create an empty alias template node. /// Create an empty alias template node.
- static TypeAliasTemplateDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static TypeAliasTemplateDecl *CreateDeserialized(ASTContext &C,
+ GlobalDeclID ID);
// Implement isa/cast/dyncast support // Implement isa/cast/dyncast support
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -2670,7 +2670,7 @@ public:
TypeSourceInfo *TInfo, StorageClass S, TypeSourceInfo *TInfo, StorageClass S,
ArrayRef<TemplateArgument> Args); ArrayRef<TemplateArgument> Args);
static VarTemplateSpecializationDecl *CreateDeserialized(ASTContext &C, static VarTemplateSpecializationDecl *CreateDeserialized(ASTContext &C,
- DeclID ID);+ GlobalDeclID ID);
void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy,
bool Qualified) const override; bool Qualified) const override;
@@ -2900,8 +2900,8 @@ public:
TypeSourceInfo *TInfo, StorageClass S, ArrayRef<TemplateArgument> Args, TypeSourceInfo *TInfo, StorageClass S, ArrayRef<TemplateArgument> Args,
const TemplateArgumentListInfo &ArgInfos); const TemplateArgumentListInfo &ArgInfos);
- static VarTemplatePartialSpecializationDecl *CreateDeserialized(ASTContext &C,+ static VarTemplatePartialSpecializationDecl *
- DeclID ID);+ CreateDeserialized(ASTContext &C, GlobalDeclID ID);
VarTemplatePartialSpecializationDecl *getMostRecentDecl() { VarTemplatePartialSpecializationDecl *getMostRecentDecl() {
return cast<VarTemplatePartialSpecializationDecl>( return cast<VarTemplatePartialSpecializationDecl>(
@@ -3078,7 +3078,7 @@ public:
VarDecl *Decl); VarDecl *Decl);
/// Create an empty variable template node. /// Create an empty variable template node.
- static VarTemplateDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static VarTemplateDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
/// Return the specialization with the provided arguments if it exists, /// Return the specialization with the provided arguments if it exists,
/// otherwise return the insertion point. /// otherwise return the insertion point.
@@ -3183,7 +3183,7 @@ public:
SourceLocation L, DeclarationName Name, SourceLocation L, DeclarationName Name,
TemplateParameterList *Params, TemplateParameterList *Params,
Expr *ConstraintExpr); Expr *ConstraintExpr);
- static ConceptDecl *CreateDeserialized(ASTContext &C, DeclID ID);+ static ConceptDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
Expr *getConstraintExpr() const { Expr *getConstraintExpr() const {
return ConstraintExpr; return ConstraintExpr;
@@ -3232,7 +3232,7 @@ public:
Create(const ASTContext &C, DeclContext *DC, SourceLocation SL, Create(const ASTContext &C, DeclContext *DC, SourceLocation SL,
ArrayRef<TemplateArgument> ConvertedArgs); ArrayRef<TemplateArgument> ConvertedArgs);
static ImplicitConceptSpecializationDecl * static ImplicitConceptSpecializationDecl *
- CreateDeserialized(const ASTContext &C, DeclID ID,+ CreateDeserialized(const ASTContext &C, GlobalDeclID ID,
unsigned NumTemplateArgs); unsigned NumTemplateArgs);
ArrayRef<TemplateArgument> getTemplateArguments() const { ArrayRef<TemplateArgument> getTemplateArguments() const {
@@ -3275,7 +3275,7 @@ private:
static TemplateParamObjectDecl *Create(const ASTContext &C, QualType T, static TemplateParamObjectDecl *Create(const ASTContext &C, QualType T,
const APValue &V); const APValue &V);
static TemplateParamObjectDecl *CreateDeserialized(ASTContext &C, static TemplateParamObjectDecl *CreateDeserialized(ASTContext &C,
- DeclID ID);+ GlobalDeclID ID);
/// Only ASTContext::getTemplateParamObjectDecl and deserialization /// Only ASTContext::getTemplateParamObjectDecl and deserialization
/// create these. /// create these.
clang/include/clang/AST/Expr.h
@@ -6610,6 +6610,275 @@ public:
}; };
+/// This class represents BOTH the OpenMP Array Section and OpenACC 'subarray',
+/// with a boolean differentiator.
+/// OpenMP 5.0 [2.1.5, Array Sections].
+/// To specify an array section in an OpenMP construct, array subscript
+/// expressions are extended with the following syntax:
+/// \code
+/// [ lower-bound : length : stride ]
+/// [ lower-bound : length : ]
+/// [ lower-bound : length ]
+/// [ lower-bound : : stride ]
+/// [ lower-bound : : ]
+/// [ lower-bound : ]
+/// [ : length : stride ]
+/// [ : length : ]
+/// [ : length ]
+/// [ : : stride ]
+/// [ : : ]
+/// [ : ]
+/// \endcode
+/// The array section must be a subset of the original array.
+/// Array sections are allowed on multidimensional arrays. Base language array
+/// subscript expressions can be used to specify length-one dimensions of
+/// multidimensional array sections.
+/// Each of the lower-bound, length, and stride expressions if specified must be
+/// an integral type expressions of the base language. When evaluated
+/// they represent a set of integer values as follows:
+/// \code
+/// { lower-bound, lower-bound + stride, lower-bound + 2 * stride,... ,
+/// lower-bound + ((length - 1) * stride) }
+/// \endcode
+/// The lower-bound and length must evaluate to non-negative integers.
+/// The stride must evaluate to a positive integer.
+/// When the size of the array dimension is not known, the length must be
+/// specified explicitly.
+/// When the stride is absent it defaults to 1.
+/// When the length is absent it defaults to ⌈(size − lower-bound)/stride⌉,
+/// where size is the size of the array dimension. When the lower-bound is
+/// absent it defaults to 0.
+///
+///
+/// OpenACC 3.3 [2.7.1 Data Specification in Data Clauses]
+/// In C and C++, a subarray is an array name followed by an extended array
+/// range specification in brackets, with start and length, such as
+///
+/// AA[2:n]
+///
+/// If the lower bound is missing, zero is used. If the length is missing and
+/// the array has known size, the size of the array is used; otherwise the
+/// length is required. The subarray AA[2:n] means elements AA[2], AA[3], . . .
+/// , AA[2+n-1]. In C and C++, a two dimensional array may be declared in at
+/// least four ways:
+///
+/// -Statically-sized array: float AA[100][200];
+/// -Pointer to statically sized rows: typedef float row[200]; row* BB;
+/// -Statically-sized array of pointers: float* CC[200];
+/// -Pointer to pointers: float** DD;
+///
+/// Each dimension may be statically sized, or a pointer to dynamically
+/// allocated memory. Each of these may be included in a data clause using
+/// subarray notation to specify a rectangular array:
+///
+/// -AA[2:n][0:200]
+/// -BB[2:n][0:m]
+/// -CC[2:n][0:m]
+/// -DD[2:n][0:m]
+///
+/// Multidimensional rectangular subarrays in C and C++ may be specified for any
+/// array with any combination of statically-sized or dynamically-allocated
+/// dimensions. For statically sized dimensions, all dimensions except the first
+/// must specify the whole extent to preserve the contiguous data restriction,
+/// discussed below. For dynamically allocated dimensions, the implementation
+/// will allocate pointers in device memory corresponding to the pointers in
+/// local memory and will fill in those pointers as appropriate.
+///
+/// In Fortran, a subarray is an array name followed by a comma-separated list
+/// of range specifications in parentheses, with lower and upper bound
+/// subscripts, such as
+///
+/// arr(1:high,low:100)
+///
+/// If either the lower or upper bounds are missing, the declared or allocated
+/// bounds of the array, if known, are used. All dimensions except the last must
+/// specify the whole extent, to preserve the contiguous data restriction,
+/// discussed below.
+///
+/// Restrictions
+///
+/// -In Fortran, the upper bound for the last dimension of an assumed-size dummy
+/// array must be specified.
+///
+/// -In C and C++, the length for dynamically allocated dimensions of an array
+/// must be explicitly specified.
+///
+/// -In C and C++, modifying pointers in pointer arrays during the data
+/// lifetime, either on the host or on the device, may result in undefined
+/// behavior.
+///
+/// -If a subarray appears in a data clause, the implementation may choose to
+/// allocate memory for only that subarray on the accelerator.
+///
+/// -In Fortran, array pointers may appear, but pointer association is not
+/// preserved in device memory.
+///
+/// -Any array or subarray in a data clause, including Fortran array pointers,
+/// must be a contiguous section of memory, except for dynamic multidimensional
+/// C arrays.
+///
+/// -In C and C++, if a variable or array of composite type appears, all the
+/// data members of the struct or class are allocated and copied, as
+/// appropriate. If a composite member is a pointer type, the data addressed by
+/// that pointer are not implicitly copied.
+///
+/// -In Fortran, if a variable or array of composite type appears, all the
+/// members of that derived type are allocated and copied, as appropriate. If
+/// any member has the allocatable or pointer attribute, the data accessed
+/// through that member are not copied.
+///
+/// -If an expression is used in a subscript or subarray expression in a clause
+/// on a data construct, the same value is used when copying data at the end of
+/// the data region, even if the values of variables in the expression change
+/// during the data region.
+class ArraySectionExpr : public Expr {
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
+public:
+ enum ArraySectionType { OMPArraySection, OpenACCArraySection };
+
+private:
+ enum {
+ BASE,
+ LOWER_BOUND,
+ LENGTH,
+ STRIDE,
+ END_EXPR,
+ OPENACC_END_EXPR = STRIDE
+ };
+
+ ArraySectionType ASType = OMPArraySection;
+ Stmt *SubExprs[END_EXPR] = {nullptr};
+ SourceLocation ColonLocFirst;
+ SourceLocation ColonLocSecond;
+ SourceLocation RBracketLoc;
+
+public:
+ // Constructor for OMP array sections, which include a 'stride'.
+ ArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, Expr *Stride,
+ QualType Type, ExprValueKind VK, ExprObjectKind OK,
+ SourceLocation ColonLocFirst, SourceLocation ColonLocSecond,
+ SourceLocation RBracketLoc)
+ : Expr(ArraySectionExprClass, Type, VK, OK), ASType(OMPArraySection),
+ ColonLocFirst(ColonLocFirst), ColonLocSecond(ColonLocSecond),
+ RBracketLoc(RBracketLoc) {
+ setBase(Base);
+ setLowerBound(LowerBound);
+ setLength(Length);
+ setStride(Stride);
+ setDependence(computeDependence(this));
+ }
+
+ // Constructor for OpenACC sub-arrays, which do not permit a 'stride'.
+ ArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, QualType Type,
+ ExprValueKind VK, ExprObjectKind OK, SourceLocation ColonLoc,
+ SourceLocation RBracketLoc)
+ : Expr(ArraySectionExprClass, Type, VK, OK), ASType(OpenACCArraySection),
+ ColonLocFirst(ColonLoc), RBracketLoc(RBracketLoc) {
+ setBase(Base);
+ setLowerBound(LowerBound);
+ setLength(Length);
+ setDependence(computeDependence(this));
+ }
+
+ /// Create an empty array section expression.
+ explicit ArraySectionExpr(EmptyShell Shell)
+ : Expr(ArraySectionExprClass, Shell) {}
+
+ /// Return original type of the base expression for array section.
+ static QualType getBaseOriginalType(const Expr *Base);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ArraySectionExprClass;
+ }
+
+ bool isOMPArraySection() const { return ASType == OMPArraySection; }
+ bool isOpenACCArraySection() const { return ASType == OpenACCArraySection; }
+
+ /// Get base of the array section.
+ Expr *getBase() { return cast<Expr>(SubExprs[BASE]); }
+ const Expr *getBase() const { return cast<Expr>(SubExprs[BASE]); }
+
+ /// Get lower bound of array section.
+ Expr *getLowerBound() { return cast_or_null<Expr>(SubExprs[LOWER_BOUND]); }
+ const Expr *getLowerBound() const {
+ return cast_or_null<Expr>(SubExprs[LOWER_BOUND]);
+ }
+
+ /// Get length of array section.
+ Expr *getLength() { return cast_or_null<Expr>(SubExprs[LENGTH]); }
+ const Expr *getLength() const { return cast_or_null<Expr>(SubExprs[LENGTH]); }
+
+ /// Get stride of array section.
+ Expr *getStride() {
+ assert(ASType != OpenACCArraySection &&
+ "Stride not valid in OpenACC subarrays");
+ return cast_or_null<Expr>(SubExprs[STRIDE]);
+ }
+
+ const Expr *getStride() const {
+ assert(ASType != OpenACCArraySection &&
+ "Stride not valid in OpenACC subarrays");
+ return cast_or_null<Expr>(SubExprs[STRIDE]);
+ }
+
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ return getBase()->getBeginLoc();
+ }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RBracketLoc; }
+
+ SourceLocation getColonLocFirst() const { return ColonLocFirst; }
+ SourceLocation getColonLocSecond() const {
+ assert(ASType != OpenACCArraySection &&
+ "second colon for stride not valid in OpenACC subarrays");
+ return ColonLocSecond;
+ }
+ SourceLocation getRBracketLoc() const { return RBracketLoc; }
+
+ SourceLocation getExprLoc() const LLVM_READONLY {
+ return getBase()->getExprLoc();
+ }
+
+ child_range children() {
+ return child_range(
+ &SubExprs[BASE],
+ &SubExprs[ASType == OMPArraySection ? END_EXPR : OPENACC_END_EXPR]);
+ }
+
+ const_child_range children() const {
+ return const_child_range(
+ &SubExprs[BASE],
+ &SubExprs[ASType == OMPArraySection ? END_EXPR : OPENACC_END_EXPR]);
+ }
+
+private:
+ /// Set base of the array section.
+ void setBase(Expr *E) { SubExprs[BASE] = E; }
+
+ /// Set lower bound of the array section.
+ void setLowerBound(Expr *E) { SubExprs[LOWER_BOUND] = E; }
+
+ /// Set length of the array section.
+ void setLength(Expr *E) { SubExprs[LENGTH] = E; }
+
+ /// Set length of the array section.
+ void setStride(Expr *E) {
+ assert(ASType != OpenACCArraySection &&
+ "Stride not valid in OpenACC subarrays");
+ SubExprs[STRIDE] = E;
+ }
+
+ void setColonLocFirst(SourceLocation L) { ColonLocFirst = L; }
+
+ void setColonLocSecond(SourceLocation L) {
+ assert(ASType != OpenACCArraySection &&
+ "second colon for stride not valid in OpenACC subarrays");
+ ColonLocSecond = L;
+ }
+ void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
+};
+
/// Frontend produces RecoveryExprs on semantic errors that prevent creating /// Frontend produces RecoveryExprs on semantic errors that prevent creating
/// other well-formed expressions. E.g. when type-checking of a binary operator /// other well-formed expressions. E.g. when type-checking of a binary operator
/// fails, we cannot produce a BinaryOperator expression. Instead, we can choose /// fails, we cannot produce a BinaryOperator expression. Instead, we can choose
clang/include/clang/AST/ExprCXX.h
@@ -1482,6 +1482,8 @@ public:
/// const S &s_ref = S(); // Requires a CXXBindTemporaryExpr. /// const S &s_ref = S(); // Requires a CXXBindTemporaryExpr.
/// } /// }
/// \endcode /// \endcode
+///
+/// Destructor might be null if destructor declaration is not valid.
class CXXBindTemporaryExpr : public Expr { class CXXBindTemporaryExpr : public Expr {
CXXTemporary *Temp = nullptr; CXXTemporary *Temp = nullptr;
Stmt *SubExpr = nullptr; Stmt *SubExpr = nullptr;
clang/include/clang/AST/ExprOpenMP.h
@@ -17,130 +17,6 @@
#include "clang/AST/Expr.h" #include "clang/AST/Expr.h"
namespace clang { namespace clang {
-/// OpenMP 5.0 [2.1.5, Array Sections].
-/// To specify an array section in an OpenMP construct, array subscript
-/// expressions are extended with the following syntax:
-/// \code
-/// [ lower-bound : length : stride ]
-/// [ lower-bound : length : ]
-/// [ lower-bound : length ]
-/// [ lower-bound : : stride ]
-/// [ lower-bound : : ]
-/// [ lower-bound : ]
-/// [ : length : stride ]
-/// [ : length : ]
-/// [ : length ]
-/// [ : : stride ]
-/// [ : : ]
-/// [ : ]
-/// \endcode
-/// The array section must be a subset of the original array.
-/// Array sections are allowed on multidimensional arrays. Base language array
-/// subscript expressions can be used to specify length-one dimensions of
-/// multidimensional array sections.
-/// Each of the lower-bound, length, and stride expressions if specified must be
-/// an integral type expressions of the base language. When evaluated
-/// they represent a set of integer values as follows:
-/// \code
-/// { lower-bound, lower-bound + stride, lower-bound + 2 * stride,... ,
-/// lower-bound + ((length - 1) * stride) }
-/// \endcode
-/// The lower-bound and length must evaluate to non-negative integers.
-/// The stride must evaluate to a positive integer.
-/// When the size of the array dimension is not known, the length must be
-/// specified explicitly.
-/// When the stride is absent it defaults to 1.
-/// When the length is absent it defaults to ⌈(size − lower-bound)/stride⌉,
-/// where size is the size of the array dimension. When the lower-bound is
-/// absent it defaults to 0.
-class OMPArraySectionExpr : public Expr {
- enum { BASE, LOWER_BOUND, LENGTH, STRIDE, END_EXPR };
- Stmt *SubExprs[END_EXPR];
- SourceLocation ColonLocFirst;
- SourceLocation ColonLocSecond;
- SourceLocation RBracketLoc;
-
-public:
- OMPArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, Expr *Stride,
- QualType Type, ExprValueKind VK, ExprObjectKind OK,
- SourceLocation ColonLocFirst,
- SourceLocation ColonLocSecond, SourceLocation RBracketLoc)
- : Expr(OMPArraySectionExprClass, Type, VK, OK),
- ColonLocFirst(ColonLocFirst), ColonLocSecond(ColonLocSecond),
- RBracketLoc(RBracketLoc) {
- SubExprs[BASE] = Base;
- SubExprs[LOWER_BOUND] = LowerBound;
- SubExprs[LENGTH] = Length;
- SubExprs[STRIDE] = Stride;
- setDependence(computeDependence(this));
- }
-
- /// Create an empty array section expression.
- explicit OMPArraySectionExpr(EmptyShell Shell)
- : Expr(OMPArraySectionExprClass, Shell) {}
-
- /// An array section can be written only as Base[LowerBound:Length].
-
- /// Get base of the array section.
- Expr *getBase() { return cast<Expr>(SubExprs[BASE]); }
- const Expr *getBase() const { return cast<Expr>(SubExprs[BASE]); }
- /// Set base of the array section.
- void setBase(Expr *E) { SubExprs[BASE] = E; }
-
- /// Return original type of the base expression for array section.
- static QualType getBaseOriginalType(const Expr *Base);
-
- /// Get lower bound of array section.
- Expr *getLowerBound() { return cast_or_null<Expr>(SubExprs[LOWER_BOUND]); }
- const Expr *getLowerBound() const {
- return cast_or_null<Expr>(SubExprs[LOWER_BOUND]);
- }
- /// Set lower bound of the array section.
- void setLowerBound(Expr *E) { SubExprs[LOWER_BOUND] = E; }
-
- /// Get length of array section.
- Expr *getLength() { return cast_or_null<Expr>(SubExprs[LENGTH]); }
- const Expr *getLength() const { return cast_or_null<Expr>(SubExprs[LENGTH]); }
- /// Set length of the array section.
- void setLength(Expr *E) { SubExprs[LENGTH] = E; }
-
- /// Get stride of array section.
- Expr *getStride() { return cast_or_null<Expr>(SubExprs[STRIDE]); }
- const Expr *getStride() const { return cast_or_null<Expr>(SubExprs[STRIDE]); }
- /// Set length of the array section.
- void setStride(Expr *E) { SubExprs[STRIDE] = E; }
-
- SourceLocation getBeginLoc() const LLVM_READONLY {
- return getBase()->getBeginLoc();
- }
- SourceLocation getEndLoc() const LLVM_READONLY { return RBracketLoc; }
-
- SourceLocation getColonLocFirst() const { return ColonLocFirst; }
- void setColonLocFirst(SourceLocation L) { ColonLocFirst = L; }
-
- SourceLocation getColonLocSecond() const { return ColonLocSecond; }
- void setColonLocSecond(SourceLocation L) { ColonLocSecond = L; }
-
- SourceLocation getRBracketLoc() const { return RBracketLoc; }
- void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
-
- SourceLocation getExprLoc() const LLVM_READONLY {
- return getBase()->getExprLoc();
- }
-
- static bool classof(const Stmt *T) {
- return T->getStmtClass() == OMPArraySectionExprClass;
- }
-
- child_range children() {
- return child_range(&SubExprs[BASE], &SubExprs[END_EXPR]);
- }
-
- const_child_range children() const {
- return const_child_range(&SubExprs[BASE], &SubExprs[END_EXPR]);
- }
-};
-
/// An explicit cast in C or a C-style cast in C++, which uses the syntax /// An explicit cast in C or a C-style cast in C++, which uses the syntax
/// ([s1][s2]...[sn])expr. For example: @c ([3][3])f. /// ([s1][s2]...[sn])expr. For example: @c ([3][3])f.
class OMPArrayShapingExpr final class OMPArrayShapingExpr final
clang/include/clang/AST/ExternalASTSource.h
@@ -99,7 +99,7 @@ public:
/// passes back decl sets as VisibleDeclaration objects. /// passes back decl sets as VisibleDeclaration objects.
/// ///
/// The default implementation of this method is a no-op. /// The default implementation of this method is a no-op.
- virtual Decl *GetExternalDecl(Decl::DeclID ID);+ virtual Decl *GetExternalDecl(GlobalDeclID ID);
/// Resolve a selector ID into a selector. /// Resolve a selector ID into a selector.
/// ///
@@ -375,7 +375,7 @@ public:
if (isOffset()) { if (isOffset()) {
assert(Source && assert(Source &&
"Cannot deserialize a lazy pointer without an AST source"); "Cannot deserialize a lazy pointer without an AST source");
- Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1));+ Ptr = reinterpret_cast<uint64_t>((Source->*Get)(OffsT(Ptr >> 1)));
} }
return reinterpret_cast<T*>(Ptr); return reinterpret_cast<T*>(Ptr);
} }
@@ -579,7 +579,7 @@ using LazyDeclStmtPtr =
/// A lazy pointer to a declaration. /// A lazy pointer to a declaration.
using LazyDeclPtr = using LazyDeclPtr =
- LazyOffsetPtr<Decl, Decl::DeclID, &ExternalASTSource::GetExternalDecl>;+ LazyOffsetPtr<Decl, GlobalDeclID, &ExternalASTSource::GetExternalDecl>;
/// A lazy pointer to a set of CXXCtorInitializers. /// A lazy pointer to a set of CXXCtorInitializers.
using LazyCXXCtorInitializersPtr = using LazyCXXCtorInitializersPtr =
clang/include/clang/AST/NestedNameSpecifier.h
@@ -266,7 +266,7 @@ public:
explicit operator bool() const { return Qualifier; } explicit operator bool() const { return Qualifier; }
/// Evaluates true when this nested-name-specifier location is /// Evaluates true when this nested-name-specifier location is
- /// empty.+ /// non-empty.
bool hasQualifier() const { return Qualifier; } bool hasQualifier() const { return Qualifier; }
/// Retrieve the nested-name-specifier to which this instance /// Retrieve the nested-name-specifier to which this instance
clang/include/clang/AST/OpenACCClause.h
@@ -156,51 +156,50 @@ public:
Expr *ConditionExpr, SourceLocation EndLoc); Expr *ConditionExpr, SourceLocation EndLoc);
}; };
-/// Represents a clause that has one or more IntExprs. It does not own the+/// Represents a clause that has one or more expressions associated with it.
-/// IntExprs, but provides 'children' and other accessors.+class OpenACCClauseWithExprs : public OpenACCClauseWithParams {
-class OpenACCClauseWithIntExprs : public OpenACCClauseWithParams {+ MutableArrayRef<Expr *> Exprs;
- MutableArrayRef<Expr *> IntExprs;
protected: protected:
- OpenACCClauseWithIntExprs(OpenACCClauseKind K, SourceLocation BeginLoc,+ OpenACCClauseWithExprs(OpenACCClauseKind K, SourceLocation BeginLoc,
- SourceLocation LParenLoc, SourceLocation EndLoc)+ SourceLocation LParenLoc, SourceLocation EndLoc)
: OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc) {} : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc) {}
/// Used only for initialization, the leaf class can initialize this to /// Used only for initialization, the leaf class can initialize this to
/// trailing storage. /// trailing storage.
- void setIntExprs(MutableArrayRef<Expr *> NewIntExprs) {+ void setExprs(MutableArrayRef<Expr *> NewExprs) {
- assert(IntExprs.empty() && "Cannot change IntExprs list");+ assert(Exprs.empty() && "Cannot change Exprs list");
- IntExprs = NewIntExprs;+ Exprs = NewExprs;
} }
- /// Gets the entire list of integer expressions, but leave it to the+ /// Gets the entire list of expressions, but leave it to the
/// individual clauses to expose this how they'd like. /// individual clauses to expose this how they'd like.
- llvm::ArrayRef<Expr *> getIntExprs() const { return IntExprs; }+ llvm::ArrayRef<Expr *> getExprs() const { return Exprs; }
public: public:
child_range children() { child_range children() {
- return child_range(reinterpret_cast<Stmt **>(IntExprs.begin()),+ return child_range(reinterpret_cast<Stmt **>(Exprs.begin()),
- reinterpret_cast<Stmt **>(IntExprs.end()));+ reinterpret_cast<Stmt **>(Exprs.end()));
} }
const_child_range children() const { const_child_range children() const {
child_range Children = child_range Children =
- const_cast<OpenACCClauseWithIntExprs *>(this)->children();+ const_cast<OpenACCClauseWithExprs *>(this)->children();
return const_child_range(Children.begin(), Children.end()); return const_child_range(Children.begin(), Children.end());
} }
}; };
class OpenACCNumGangsClause final class OpenACCNumGangsClause final
- : public OpenACCClauseWithIntExprs,+ : public OpenACCClauseWithExprs,
public llvm::TrailingObjects<OpenACCNumGangsClause, Expr *> { public llvm::TrailingObjects<OpenACCNumGangsClause, Expr *> {
OpenACCNumGangsClause(SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCNumGangsClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<Expr *> IntExprs, SourceLocation EndLoc) ArrayRef<Expr *> IntExprs, SourceLocation EndLoc)
- : OpenACCClauseWithIntExprs(OpenACCClauseKind::NumGangs, BeginLoc,+ : OpenACCClauseWithExprs(OpenACCClauseKind::NumGangs, BeginLoc, LParenLoc,
- LParenLoc, EndLoc) {+ EndLoc) {
std::uninitialized_copy(IntExprs.begin(), IntExprs.end(), std::uninitialized_copy(IntExprs.begin(), IntExprs.end(),
getTrailingObjects<Expr *>()); getTrailingObjects<Expr *>());
- setIntExprs(MutableArrayRef(getTrailingObjects<Expr *>(), IntExprs.size()));+ setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), IntExprs.size()));
} }
public: public:
@@ -209,35 +208,35 @@ public:
ArrayRef<Expr *> IntExprs, SourceLocation EndLoc); ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);
llvm::ArrayRef<Expr *> getIntExprs() { llvm::ArrayRef<Expr *> getIntExprs() {
- return OpenACCClauseWithIntExprs::getIntExprs();+ return OpenACCClauseWithExprs::getExprs();
} }
llvm::ArrayRef<Expr *> getIntExprs() const { llvm::ArrayRef<Expr *> getIntExprs() const {
- return OpenACCClauseWithIntExprs::getIntExprs();+ return OpenACCClauseWithExprs::getExprs();
} }
}; };
/// Represents one of a handful of clauses that have a single integer /// Represents one of a handful of clauses that have a single integer
/// expression. /// expression.
-class OpenACCClauseWithSingleIntExpr : public OpenACCClauseWithIntExprs {+class OpenACCClauseWithSingleIntExpr : public OpenACCClauseWithExprs {
Expr *IntExpr; Expr *IntExpr;
protected: protected:
OpenACCClauseWithSingleIntExpr(OpenACCClauseKind K, SourceLocation BeginLoc, OpenACCClauseWithSingleIntExpr(OpenACCClauseKind K, SourceLocation BeginLoc,
SourceLocation LParenLoc, Expr *IntExpr, SourceLocation LParenLoc, Expr *IntExpr,
SourceLocation EndLoc) SourceLocation EndLoc)
- : OpenACCClauseWithIntExprs(K, BeginLoc, LParenLoc, EndLoc),+ : OpenACCClauseWithExprs(K, BeginLoc, LParenLoc, EndLoc),
IntExpr(IntExpr) { IntExpr(IntExpr) {
- setIntExprs(MutableArrayRef<Expr *>{&this->IntExpr, 1});+ setExprs(MutableArrayRef<Expr *>{&this->IntExpr, 1});
} }
public: public:
- bool hasIntExpr() const { return !getIntExprs().empty(); }+ bool hasIntExpr() const { return !getExprs().empty(); }
const Expr *getIntExpr() const { const Expr *getIntExpr() const {
- return hasIntExpr() ? getIntExprs()[0] : nullptr;+ return hasIntExpr() ? getExprs()[0] : nullptr;
} }
- Expr *getIntExpr() { return hasIntExpr() ? getIntExprs()[0] : nullptr; };+ Expr *getIntExpr() { return hasIntExpr() ? getExprs()[0] : nullptr; };
}; };
class OpenACCNumWorkersClause : public OpenACCClauseWithSingleIntExpr { class OpenACCNumWorkersClause : public OpenACCClauseWithSingleIntExpr {
@@ -261,6 +260,40 @@ public:
Expr *IntExpr, SourceLocation EndLoc); Expr *IntExpr, SourceLocation EndLoc);
}; };
+/// Represents a clause with one or more 'var' objects, represented as an expr,
+/// as its arguments. Var-list is expected to be stored in trailing storage.
+/// For now, we're just storing the original expression in its entirety, unlike
+/// OMP which has to do a bunch of work to create a private.
+class OpenACCClauseWithVarList : public OpenACCClauseWithExprs {
+protected:
+ OpenACCClauseWithVarList(OpenACCClauseKind K, SourceLocation BeginLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc)
+ : OpenACCClauseWithExprs(K, BeginLoc, LParenLoc, EndLoc) {}
+
+public:
+ ArrayRef<Expr *> getVarList() { return getExprs(); }
+ ArrayRef<Expr *> getVarList() const { return getExprs(); }
+};
+
+class OpenACCPrivateClause final
+ : public OpenACCClauseWithVarList,
+ public llvm::TrailingObjects<OpenACCPrivateClause, Expr *> {
+
+ OpenACCPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
+ ArrayRef<Expr *> VarList, SourceLocation EndLoc)
+ : OpenACCClauseWithVarList(OpenACCClauseKind::Private, BeginLoc,
+ LParenLoc, EndLoc) {
+ std::uninitialized_copy(VarList.begin(), VarList.end(),
+ getTrailingObjects<Expr *>());
+ setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
+ }
+
+public:
+ static OpenACCPrivateClause *
+ Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
+ ArrayRef<Expr *> VarList, SourceLocation EndLoc);
+};
+
template <class Impl> class OpenACCClauseVisitor { template <class Impl> class OpenACCClauseVisitor {
Impl &getDerived() { return static_cast<Impl &>(*this); } Impl &getDerived() { return static_cast<Impl &>(*this); }
@@ -299,6 +332,9 @@ public:
class OpenACCClausePrinter final class OpenACCClausePrinter final
: public OpenACCClauseVisitor<OpenACCClausePrinter> { : public OpenACCClauseVisitor<OpenACCClausePrinter> {
raw_ostream &OS; raw_ostream &OS;
+ const PrintingPolicy &Policy;
+
+ void printExpr(const Expr *E);
public: public:
void VisitClauseList(ArrayRef<const OpenACCClause *> List) { void VisitClauseList(ArrayRef<const OpenACCClause *> List) {
@@ -309,7 +345,8 @@ public:
OS << ' '; OS << ' ';
} }
} }
- OpenACCClausePrinter(raw_ostream &OS) : OS(OS) {}+ OpenACCClausePrinter(raw_ostream &OS, const PrintingPolicy &Policy)
+ : OS(OS), Policy(Policy) {}
#define VISIT_CLAUSE(CLAUSE_NAME) \ #define VISIT_CLAUSE(CLAUSE_NAME) \
void Visit##CLAUSE_NAME##Clause(const OpenACC##CLAUSE_NAME##Clause &Clause); void Visit##CLAUSE_NAME##Clause(const OpenACC##CLAUSE_NAME##Clause &Clause);
clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2740,7 +2740,7 @@ DEF_TRAVERSE_STMT(CXXMemberCallExpr, {})
DEF_TRAVERSE_STMT(AddrLabelExpr, {}) DEF_TRAVERSE_STMT(AddrLabelExpr, {})
DEF_TRAVERSE_STMT(ArraySubscriptExpr, {}) DEF_TRAVERSE_STMT(ArraySubscriptExpr, {})
DEF_TRAVERSE_STMT(MatrixSubscriptExpr, {}) DEF_TRAVERSE_STMT(MatrixSubscriptExpr, {})
-DEF_TRAVERSE_STMT(OMPArraySectionExpr, {})+DEF_TRAVERSE_STMT(ArraySectionExpr, {})
DEF_TRAVERSE_STMT(OMPArrayShapingExpr, {}) DEF_TRAVERSE_STMT(OMPArrayShapingExpr, {})
DEF_TRAVERSE_STMT(OMPIteratorExpr, {}) DEF_TRAVERSE_STMT(OMPIteratorExpr, {})
clang/include/clang/AST/Type.h
@@ -25,8 +25,10 @@
#include "clang/Basic/Diagnostic.h" #include "clang/Basic/Diagnostic.h"
#include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/LLVM.h" #include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Linkage.h" #include "clang/Basic/Linkage.h"
#include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/PointerAuthOptions.h"
#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h" #include "clang/Basic/Specifiers.h"
#include "clang/Basic/Visibility.h" #include "clang/Basic/Visibility.h"
@@ -139,6 +141,174 @@ using CanQualType = CanQual<Type>;
#define TYPE(Class, Base) class Class##Type; #define TYPE(Class, Base) class Class##Type;
#include "clang/AST/TypeNodes.inc" #include "clang/AST/TypeNodes.inc"
+/// Pointer-authentication qualifiers.
+class PointerAuthQualifier {
+ enum : uint32_t {
+ EnabledShift = 0,
+ EnabledBits = 1,
+ EnabledMask = 1 << EnabledShift,
+ AddressDiscriminatedShift = EnabledShift + EnabledBits,
+ AddressDiscriminatedBits = 1,
+ AddressDiscriminatedMask = 1 << AddressDiscriminatedShift,
+ AuthenticationModeShift =
+ AddressDiscriminatedShift + AddressDiscriminatedBits,
+ AuthenticationModeBits = 2,
+ AuthenticationModeMask = ((1 << AuthenticationModeBits) - 1)
+ << AuthenticationModeShift,
+ IsaPointerShift = AuthenticationModeShift + AuthenticationModeBits,
+ IsaPointerBits = 1,
+ IsaPointerMask = ((1 << IsaPointerBits) - 1) << IsaPointerShift,
+ AuthenticatesNullValuesShift = IsaPointerShift + IsaPointerBits,
+ AuthenticatesNullValuesBits = 1,
+ AuthenticatesNullValuesMask = ((1 << AuthenticatesNullValuesBits) - 1)
+ << AuthenticatesNullValuesShift,
+ KeyShift = AuthenticatesNullValuesShift + AuthenticatesNullValuesBits,
+ KeyBits = 10,
+ KeyMask = ((1 << KeyBits) - 1) << KeyShift,
+ DiscriminatorShift = KeyShift + KeyBits,
+ DiscriminatorBits = 16,
+ DiscriminatorMask = ((1u << DiscriminatorBits) - 1) << DiscriminatorShift,
+ };
+
+ // bits: |0 |1 |2..3 |4 |
+ // |Enabled|Address|AuthenticationMode|ISA pointer|
+ // bits: |5 |6..15| 16...31 |
+ // |AuthenticatesNull|Key |Discriminator|
+ uint32_t Data = 0;
+
+ // The following static assertions check that each of the 32 bits is present
+ // exactly in one of the constants.
+ static_assert((EnabledBits + AddressDiscriminatedBits +
+ AuthenticationModeBits + IsaPointerBits +
+ AuthenticatesNullValuesBits + KeyBits + DiscriminatorBits) ==
+ 32,
+ "PointerAuthQualifier should be exactly 32 bits");
+ static_assert((EnabledMask + AddressDiscriminatedMask +
+ AuthenticationModeMask + IsaPointerMask +
+ AuthenticatesNullValuesMask + KeyMask + DiscriminatorMask) ==
+ 0xFFFFFFFF,
+ "All masks should cover the entire bits");
+ static_assert((EnabledMask ^ AddressDiscriminatedMask ^
+ AuthenticationModeMask ^ IsaPointerMask ^
+ AuthenticatesNullValuesMask ^ KeyMask ^ DiscriminatorMask) ==
+ 0xFFFFFFFF,
+ "All masks should cover the entire bits");
+
+ PointerAuthQualifier(unsigned Key, bool IsAddressDiscriminated,
+ unsigned ExtraDiscriminator,
+ PointerAuthenticationMode AuthenticationMode,
+ bool IsIsaPointer, bool AuthenticatesNullValues)
+ : Data(EnabledMask |
+ (IsAddressDiscriminated
+ ? llvm::to_underlying(AddressDiscriminatedMask)
+ : 0) |
+ (Key << KeyShift) |
+ (llvm::to_underlying(AuthenticationMode)
+ << AuthenticationModeShift) |
+ (ExtraDiscriminator << DiscriminatorShift) |
+ (IsIsaPointer << IsaPointerShift) |
+ (AuthenticatesNullValues << AuthenticatesNullValuesShift)) {
+ assert(Key <= KeyNoneInternal);
+ assert(ExtraDiscriminator <= MaxDiscriminator);
+ assert((Data == 0) ==
+ (getAuthenticationMode() == PointerAuthenticationMode::None));
+ }
+
+public:
+ enum {
+ KeyNoneInternal = (1u << KeyBits) - 1,
+
+ /// The maximum supported pointer-authentication key.
+ MaxKey = KeyNoneInternal - 1,
+
+ /// The maximum supported pointer-authentication discriminator.
+ MaxDiscriminator = (1u << DiscriminatorBits) - 1
+ };
+
+public:
+ PointerAuthQualifier() = default;
+
+ static PointerAuthQualifier
+ Create(unsigned Key, bool IsAddressDiscriminated, unsigned ExtraDiscriminator,
+ PointerAuthenticationMode AuthenticationMode, bool IsIsaPointer,
+ bool AuthenticatesNullValues) {
+ if (Key == PointerAuthKeyNone)
+ Key = KeyNoneInternal;
+ assert(Key <= KeyNoneInternal && "out-of-range key value");
+ return PointerAuthQualifier(Key, IsAddressDiscriminated, ExtraDiscriminator,
+ AuthenticationMode, IsIsaPointer,
+ AuthenticatesNullValues);
+ }
+
+ bool isPresent() const {
+ assert((Data == 0) ==
+ (getAuthenticationMode() == PointerAuthenticationMode::None));
+ return Data != 0;
+ }
+
+ explicit operator bool() const { return isPresent(); }
+
+ unsigned getKey() const {
+ assert(isPresent());
+ return (Data & KeyMask) >> KeyShift;
+ }
+
+ bool hasKeyNone() const { return isPresent() && getKey() == KeyNoneInternal; }
+
+ bool isAddressDiscriminated() const {
+ assert(isPresent());
+ return (Data & AddressDiscriminatedMask) >> AddressDiscriminatedShift;
+ }
+
+ unsigned getExtraDiscriminator() const {
+ assert(isPresent());
+ return (Data >> DiscriminatorShift);
+ }
+
+ PointerAuthenticationMode getAuthenticationMode() const {
+ return PointerAuthenticationMode((Data & AuthenticationModeMask) >>
+ AuthenticationModeShift);
+ }
+
+ bool isIsaPointer() const {
+ assert(isPresent());
+ return (Data & IsaPointerMask) >> IsaPointerShift;
+ }
+
+ bool authenticatesNullValues() const {
+ assert(isPresent());
+ return (Data & AuthenticatesNullValuesMask) >> AuthenticatesNullValuesShift;
+ }
+
+ PointerAuthQualifier withoutKeyNone() const {
+ return hasKeyNone() ? PointerAuthQualifier() : *this;
+ }
+
+ friend bool operator==(PointerAuthQualifier Lhs, PointerAuthQualifier Rhs) {
+ return Lhs.Data == Rhs.Data;
+ }
+ friend bool operator!=(PointerAuthQualifier Lhs, PointerAuthQualifier Rhs) {
+ return Lhs.Data != Rhs.Data;
+ }
+
+ bool isEquivalent(PointerAuthQualifier Other) const {
+ return withoutKeyNone() == Other.withoutKeyNone();
+ }
+
+ uint32_t getAsOpaqueValue() const { return Data; }
+
+ // Deserialize pointer-auth qualifiers from an opaque representation.
+ static PointerAuthQualifier fromOpaqueValue(uint32_t Opaque) {
+ PointerAuthQualifier Result;
+ Result.Data = Opaque;
+ assert((Result.Data == 0) ==
+ (Result.getAuthenticationMode() == PointerAuthenticationMode::None));
+ return Result;
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Data); }
+};
+
/// The collection of all-type qualifiers we support. /// The collection of all-type qualifiers we support.
/// Clang supports five independent qualifiers: /// Clang supports five independent qualifiers:
/// * C99: const, volatile, and restrict /// * C99: const, volatile, and restrict
@@ -147,8 +317,9 @@ using CanQualType = CanQual<Type>;
/// * Objective C: the GC attributes (none, weak, or strong) /// * Objective C: the GC attributes (none, weak, or strong)
class Qualifiers { class Qualifiers {
public: public:
- enum TQ { // NOTE: These flags must be kept in sync with DeclSpec::TQ.+ enum TQ : uint64_t {
- Const = 0x1,+ // NOTE: These flags must be kept in sync with DeclSpec::TQ.
+ Const = 0x1,
Restrict = 0x2, Restrict = 0x2,
Volatile = 0x4, Volatile = 0x4,
CVRMask = Const | Volatile | Restrict CVRMask = Const | Volatile | Restrict
@@ -182,7 +353,7 @@ public:
OCL_Autoreleasing OCL_Autoreleasing
}; };
- enum {+ enum : uint64_t {
/// The maximum supported address space number. /// The maximum supported address space number.
/// 23 bits should be enough for anyone. /// 23 bits should be enough for anyone.
MaxAddressSpace = 0x7fffffu, MaxAddressSpace = 0x7fffffu,
@@ -197,16 +368,25 @@ public:
/// Returns the common set of qualifiers while removing them from /// Returns the common set of qualifiers while removing them from
/// the given sets. /// the given sets.
static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) { static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R) {
+ Qualifiers Q;
+ PointerAuthQualifier LPtrAuth = L.getPointerAuth();
+ if (LPtrAuth.isPresent() &&
+ LPtrAuth.getKey() != PointerAuthQualifier::KeyNoneInternal &&
+ LPtrAuth == R.getPointerAuth()) {
+ Q.setPointerAuth(LPtrAuth);
+ PointerAuthQualifier Empty;
+ L.setPointerAuth(Empty);
+ R.setPointerAuth(Empty);
+ }
+
// If both are only CVR-qualified, bit operations are sufficient. // If both are only CVR-qualified, bit operations are sufficient.
if (!(L.Mask & ~CVRMask) && !(R.Mask & ~CVRMask)) { if (!(L.Mask & ~CVRMask) && !(R.Mask & ~CVRMask)) {
- Qualifiers Q;
Q.Mask = L.Mask & R.Mask; Q.Mask = L.Mask & R.Mask;
L.Mask &= ~Q.Mask; L.Mask &= ~Q.Mask;
R.Mask &= ~Q.Mask; R.Mask &= ~Q.Mask;
return Q; return Q;
} }
- Qualifiers Q;
unsigned CommonCRV = L.getCVRQualifiers() & R.getCVRQualifiers(); unsigned CommonCRV = L.getCVRQualifiers() & R.getCVRQualifiers();
Q.addCVRQualifiers(CommonCRV); Q.addCVRQualifiers(CommonCRV);
L.removeCVRQualifiers(CommonCRV); L.removeCVRQualifiers(CommonCRV);
@@ -251,16 +431,14 @@ public:
} }
// Deserialize qualifiers from an opaque representation. // Deserialize qualifiers from an opaque representation.
- static Qualifiers fromOpaqueValue(unsigned opaque) {+ static Qualifiers fromOpaqueValue(uint64_t opaque) {
Qualifiers Qs; Qualifiers Qs;
Qs.Mask = opaque; Qs.Mask = opaque;
return Qs; return Qs;
} }
// Serialize these qualifiers into an opaque representation. // Serialize these qualifiers into an opaque representation.
- unsigned getAsOpaqueValue() const {+ uint64_t getAsOpaqueValue() const { return Mask; }
- return Mask;
- }
bool hasConst() const { return Mask & Const; } bool hasConst() const { return Mask & Const; }
bool hasOnlyConst() const { return Mask == Const; } bool hasOnlyConst() const { return Mask == Const; }
@@ -302,7 +480,7 @@ public:
} }
void removeCVRQualifiers(unsigned mask) { void removeCVRQualifiers(unsigned mask) {
assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits"); assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits");
- Mask &= ~mask;+ Mask &= ~static_cast<uint64_t>(mask);
} }
void removeCVRQualifiers() { void removeCVRQualifiers() {
removeCVRQualifiers(CVRMask); removeCVRQualifiers(CVRMask);
@@ -407,6 +585,20 @@ public:
setAddressSpace(space); setAddressSpace(space);
} }
+ bool hasPointerAuth() const { return Mask & PtrAuthMask; }
+ PointerAuthQualifier getPointerAuth() const {
+ return PointerAuthQualifier::fromOpaqueValue(Mask >> PtrAuthShift);
+ }
+ void setPointerAuth(PointerAuthQualifier Q) {
+ Mask = (Mask & ~PtrAuthMask) |
+ (uint64_t(Q.getAsOpaqueValue()) << PtrAuthShift);
+ }
+ void removePointerAuth() { Mask &= ~PtrAuthMask; }
+ void addPointerAuth(PointerAuthQualifier Q) {
+ assert(Q.isPresent());
+ setPointerAuth(Q);
+ }
+
// Fast qualifiers are those that can be allocated directly // Fast qualifiers are those that can be allocated directly
// on a QualType object. // on a QualType object.
bool hasFastQualifiers() const { return getFastQualifiers(); } bool hasFastQualifiers() const { return getFastQualifiers(); }
@@ -417,7 +609,7 @@ public:
} }
void removeFastQualifiers(unsigned mask) { void removeFastQualifiers(unsigned mask) {
assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits"); assert(!(mask & ~FastMask) && "bitmask contains non-fast qualifier bits");
- Mask &= ~mask;+ Mask &= ~static_cast<uint64_t>(mask);
} }
void removeFastQualifiers() { void removeFastQualifiers() {
removeFastQualifiers(FastMask); removeFastQualifiers(FastMask);
@@ -454,6 +646,8 @@ public:
addObjCGCAttr(Q.getObjCGCAttr()); addObjCGCAttr(Q.getObjCGCAttr());
if (Q.hasObjCLifetime()) if (Q.hasObjCLifetime())
addObjCLifetime(Q.getObjCLifetime()); addObjCLifetime(Q.getObjCLifetime());
+ if (Q.hasPointerAuth())
+ addPointerAuth(Q.getPointerAuth());
} }
} }
@@ -471,6 +665,8 @@ public:
removeObjCLifetime(); removeObjCLifetime();
if (getAddressSpace() == Q.getAddressSpace()) if (getAddressSpace() == Q.getAddressSpace())
removeAddressSpace(); removeAddressSpace();
+ if (getPointerAuth() == Q.getPointerAuth())
+ removePointerAuth();
} }
} }
@@ -483,6 +679,8 @@ public:
!hasObjCGCAttr() || !qs.hasObjCGCAttr()); !hasObjCGCAttr() || !qs.hasObjCGCAttr());
assert(getObjCLifetime() == qs.getObjCLifetime() || assert(getObjCLifetime() == qs.getObjCLifetime() ||
!hasObjCLifetime() || !qs.hasObjCLifetime()); !hasObjCLifetime() || !qs.hasObjCLifetime());
+ assert(!hasPointerAuth() || !qs.hasPointerAuth() ||
+ getPointerAuth() == qs.getPointerAuth());
Mask |= qs.Mask; Mask |= qs.Mask;
} }
@@ -536,6 +734,8 @@ public:
// be changed. // be changed.
(getObjCGCAttr() == other.getObjCGCAttr() || !hasObjCGCAttr() || (getObjCGCAttr() == other.getObjCGCAttr() || !hasObjCGCAttr() ||
!other.hasObjCGCAttr()) && !other.hasObjCGCAttr()) &&
+ // Pointer-auth qualifiers must match exactly.
+ getPointerAuth() == other.getPointerAuth() &&
// ObjC lifetime qualifiers must match exactly. // ObjC lifetime qualifiers must match exactly.
getObjCLifetime() == other.getObjCLifetime() && getObjCLifetime() == other.getObjCLifetime() &&
// CVR qualifiers may subset. // CVR qualifiers may subset.
@@ -605,24 +805,26 @@ public:
void print(raw_ostream &OS, const PrintingPolicy &Policy, void print(raw_ostream &OS, const PrintingPolicy &Policy,
bool appendSpaceIfNonEmpty = false) const; bool appendSpaceIfNonEmpty = false) const;
- void Profile(llvm::FoldingSetNodeID &ID) const {+ void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(Mask); }
- ID.AddInteger(Mask);
- }
private: private:
- // bits: |0 1 2|3|4 .. 5|6 .. 8|9 ... 31|+ // bits: |0 1 2|3|4 .. 5|6 .. 8|9 ... 31|32 ... 63|
- // |C R V|U|GCAttr|Lifetime|AddressSpace|+ // |C R V|U|GCAttr|Lifetime|AddressSpace| PtrAuth |
- uint32_t Mask = 0;+ uint64_t Mask = 0;
-+ static_assert(sizeof(PointerAuthQualifier) == sizeof(uint32_t),
- static const uint32_t UMask = 0x8;+ "PointerAuthQualifier must be 32 bits");
- static const uint32_t UShift = 3;+
- static const uint32_t GCAttrMask = 0x30;+ static constexpr uint64_t UMask = 0x8;
- static const uint32_t GCAttrShift = 4;+ static constexpr uint64_t UShift = 3;
- static const uint32_t LifetimeMask = 0x1C0;+ static constexpr uint64_t GCAttrMask = 0x30;
- static const uint32_t LifetimeShift = 6;+ static constexpr uint64_t GCAttrShift = 4;
- static const uint32_t AddressSpaceMask =+ static constexpr uint64_t LifetimeMask = 0x1C0;
+ static constexpr uint64_t LifetimeShift = 6;
+ static constexpr uint64_t AddressSpaceMask =
~(CVRMask | UMask | GCAttrMask | LifetimeMask); ~(CVRMask | UMask | GCAttrMask | LifetimeMask);
- static const uint32_t AddressSpaceShift = 9;+ static constexpr uint64_t AddressSpaceShift = 9;
+ static constexpr uint64_t PtrAuthShift = 32;
+ static constexpr uint64_t PtrAuthMask = uint64_t(0xffffffff) << PtrAuthShift;
}; };
class QualifiersAndAtomic { class QualifiersAndAtomic {
@@ -1242,6 +1444,10 @@ public:
// true when Type is objc's weak and weak is enabled but ARC isn't. // true when Type is objc's weak and weak is enabled but ARC isn't.
bool isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const; bool isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const;
+ PointerAuthQualifier getPointerAuth() const {
+ return getQualifiers().getPointerAuth();
+ }
+
enum PrimitiveDefaultInitializeKind { enum PrimitiveDefaultInitializeKind {
/// The type does not fall into any of the following categories. Note that /// The type does not fall into any of the following categories. Note that
/// this case is zero-valued so that values of this enum can be used as a /// this case is zero-valued so that values of this enum can be used as a
@@ -2172,6 +2378,10 @@ public:
/// 'riscv_rvv_vector_bits' type attribute as VectorType. /// 'riscv_rvv_vector_bits' type attribute as VectorType.
QualType getRVVEltType(const ASTContext &Ctx) const; QualType getRVVEltType(const ASTContext &Ctx) const;
+ /// Returns the representative type for the element of a sizeless vector
+ /// builtin type.
+ QualType getSizelessVectorEltType(const ASTContext &Ctx) const;
+
/// Types are partitioned into 3 broad categories (C99 6.2.5p1): /// Types are partitioned into 3 broad categories (C99 6.2.5p1):
/// object types, function types, and incomplete types. /// object types, function types, and incomplete types.
clang/include/clang/Basic/Attr.td
@@ -592,6 +592,49 @@ class AttrSubjectMatcherAggregateRule<AttrSubject subject> {
def SubjectMatcherForNamed : AttrSubjectMatcherAggregateRule<Named>; def SubjectMatcherForNamed : AttrSubjectMatcherAggregateRule<Named>;
+// Enumeration specifying what kind of behavior should be used for late
+// parsing of attributes.
+class LateAttrParseKind <int val> {
+ int Kind = val;
+}
+
+// Never late parsed
+def LateAttrParseNever : LateAttrParseKind<0>;
+
+// Standard late attribute parsing
+//
+// This is language dependent. For example:
+//
+// * For C++ enables late parsing of a declaration attributes
+// * For C does not enable late parsing of attributes
+//
+def LateAttrParseStandard : LateAttrParseKind<1>;
+
+// Experimental extension to standard late attribute parsing
+//
+// This extension behaves like `LateAttrParseStandard` but allows
+// late parsing attributes in more contexts.
+//
+// In contexts where `LateAttrParseStandard` attributes are late
+// parsed, `LateAttrParseExperimentalExt` attributes will also
+// be late parsed.
+//
+// In contexts that only late parse `LateAttrParseExperimentalExt` attributes
+// (see `LateParsedAttrList::lateAttrParseExperimentalExtOnly()`)
+//
+// * If `-fexperimental-late-parse-attributes`
+// (`LangOpts.ExperimentalLateParseAttributes`) is enabled the attribute
+// will be late parsed.
+// * If `-fexperimental-late-parse-attributes`
+// (`LangOpts.ExperimentalLateParseAttributes`) is disabled the attribute
+// will **not** be late parsed (i.e parsed immediately).
+//
+// The following contexts are supported:
+//
+// * TODO: Add contexts here when they are implemented.
+//
+def LateAttrParseExperimentalExt : LateAttrParseKind<2>;
+
class Attr { class Attr {
// The various ways in which an attribute can be spelled in source // The various ways in which an attribute can be spelled in source
list<Spelling> Spellings; list<Spelling> Spellings;
@@ -603,8 +646,8 @@ class Attr {
list<Accessor> Accessors = []; list<Accessor> Accessors = [];
// Specify targets for spellings. // Specify targets for spellings.
list<TargetSpecificSpelling> TargetSpecificSpellings = []; list<TargetSpecificSpelling> TargetSpecificSpellings = [];
- // Set to true for attributes with arguments which require delayed parsing.+ // Specifies the late parsing kind.
- bit LateParsed = 0;+ LateAttrParseKind LateParsed = LateAttrParseNever;
// Set to false to prevent an attribute from being propagated from a template // Set to false to prevent an attribute from being propagated from a template
// to the instantiation. // to the instantiation.
bit Clone = 1; bit Clone = 1;
@@ -3173,7 +3216,7 @@ def DiagnoseIf : InheritableAttr {
BoolArgument<"ArgDependent", 0, /*fake*/ 1>, BoolArgument<"ArgDependent", 0, /*fake*/ 1>,
DeclArgument<Named, "Parent", 0, /*fake*/ 1>]; DeclArgument<Named, "Parent", 0, /*fake*/ 1>];
let InheritEvenIfAlreadyPresent = 1; let InheritEvenIfAlreadyPresent = 1;
- let LateParsed = 1;+ let LateParsed = LateAttrParseStandard;
let AdditionalMembers = [{ let AdditionalMembers = [{
bool isError() const { return diagnosticType == DT_Error; } bool isError() const { return diagnosticType == DT_Error; }
bool isWarning() const { return diagnosticType == DT_Warning; } bool isWarning() const { return diagnosticType == DT_Warning; }
@@ -3211,7 +3254,7 @@ def ObjCRequiresPropertyDefs : InheritableAttr {
def Unused : InheritableAttr { def Unused : InheritableAttr {
let Spellings = [CXX11<"", "maybe_unused", 201603>, GCC<"unused">, let Spellings = [CXX11<"", "maybe_unused", 201603>, GCC<"unused">,
C23<"", "maybe_unused", 202106>]; C23<"", "maybe_unused", 202106>];
- let Subjects = SubjectList<[Var, ObjCIvar, Type, Enum, EnumConstant, Label,+ let Subjects = SubjectList<[Var, Binding, ObjCIvar, Type, Enum, EnumConstant, Label,
Field, ObjCMethod, FunctionLike]>; Field, ObjCMethod, FunctionLike]>;
let Documentation = [WarnMaybeUnusedDocs]; let Documentation = [WarnMaybeUnusedDocs];
} }
@@ -3472,7 +3515,7 @@ def AssertCapability : InheritableAttr {
let Spellings = [Clang<"assert_capability", 0>, let Spellings = [Clang<"assert_capability", 0>,
Clang<"assert_shared_capability", 0>]; Clang<"assert_shared_capability", 0>];
let Subjects = SubjectList<[Function]>; let Subjects = SubjectList<[Function]>;
- let LateParsed = 1;+ let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1; let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1; let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1; let InheritEvenIfAlreadyPresent = 1;
@@ -3488,7 +3531,7 @@ def AcquireCapability : InheritableAttr {
GNU<"exclusive_lock_function">, GNU<"exclusive_lock_function">,
GNU<"shared_lock_function">]; GNU<"shared_lock_function">];
let Subjects = SubjectList<[Function]>; let Subjects = SubjectList<[Function]>;
- let LateParsed = 1;+ let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1; let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1; let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1; let InheritEvenIfAlreadyPresent = 1;
@@ -3504,7 +3547,7 @@ def TryAcquireCapability : InheritableAttr {
Clang<"try_acquire_shared_capability", 0>]; Clang<"try_acquire_shared_capability", 0>];
let Subjects = SubjectList<[Function], let Subjects = SubjectList<[Function],
ErrorDiag>; ErrorDiag>;
- let LateParsed = 1;+ let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1; let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1; let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1; let InheritEvenIfAlreadyPresent = 1;
@@ -3520,7 +3563,7 @@ def ReleaseCapability : InheritableAttr {
Clang<"release_generic_capability", 0>, Clang<"release_generic_capability", 0>,
Clang<"unlock_function", 0>]; Clang<"unlock_function", 0>];
let Subjects = SubjectList<[Function]>; let Subjects = SubjectList<[Function]>;
- let LateParsed = 1;+ let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1; let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1; let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1; let InheritEvenIfAlreadyPresent = 1;
@@ -3539,7 +3582,7 @@ def RequiresCapability : InheritableAttr {
Clang<"requires_shared_capability", 0>, Clang<"requires_shared_capability", 0>,
Clang<"shared_locks_required", 0>]; Clang<"shared_locks_required", 0>];
let Args = [VariadicExprArgument<"Args">]; let Args = [VariadicExprArgument<"Args">];
- let LateParsed = 1;+ let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1; let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1; let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1; let InheritEvenIfAlreadyPresent = 1;
@@ -3559,7 +3602,7 @@ def NoThreadSafetyAnalysis : InheritableAttr {
def GuardedBy : InheritableAttr { def GuardedBy : InheritableAttr {
let Spellings = [GNU<"guarded_by">]; let Spellings = [GNU<"guarded_by">];
let Args = [ExprArgument<"Arg">]; let Args = [ExprArgument<"Arg">];
- let LateParsed = 1;+ let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1; let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1; let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1; let InheritEvenIfAlreadyPresent = 1;
@@ -3570,7 +3613,7 @@ def GuardedBy : InheritableAttr {
def PtGuardedBy : InheritableAttr { def PtGuardedBy : InheritableAttr {
let Spellings = [GNU<"pt_guarded_by">]; let Spellings = [GNU<"pt_guarded_by">];
let Args = [ExprArgument<"Arg">]; let Args = [ExprArgument<"Arg">];
- let LateParsed = 1;+ let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1; let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1; let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1; let InheritEvenIfAlreadyPresent = 1;
@@ -3581,7 +3624,7 @@ def PtGuardedBy : InheritableAttr {
def AcquiredAfter : InheritableAttr { def AcquiredAfter : InheritableAttr {
let Spellings = [GNU<"acquired_after">]; let Spellings = [GNU<"acquired_after">];
let Args = [VariadicExprArgument<"Args">]; let Args = [VariadicExprArgument<"Args">];
- let LateParsed = 1;+ let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1; let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1; let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1; let InheritEvenIfAlreadyPresent = 1;
@@ -3592,7 +3635,7 @@ def AcquiredAfter : InheritableAttr {
def AcquiredBefore : InheritableAttr { def AcquiredBefore : InheritableAttr {
let Spellings = [GNU<"acquired_before">]; let Spellings = [GNU<"acquired_before">];
let Args = [VariadicExprArgument<"Args">]; let Args = [VariadicExprArgument<"Args">];
- let LateParsed = 1;+ let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1; let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1; let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1; let InheritEvenIfAlreadyPresent = 1;
@@ -3603,7 +3646,7 @@ def AcquiredBefore : InheritableAttr {
def AssertExclusiveLock : InheritableAttr { def AssertExclusiveLock : InheritableAttr {
let Spellings = [GNU<"assert_exclusive_lock">]; let Spellings = [GNU<"assert_exclusive_lock">];
let Args = [VariadicExprArgument<"Args">]; let Args = [VariadicExprArgument<"Args">];
- let LateParsed = 1;+ let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1; let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1; let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1; let InheritEvenIfAlreadyPresent = 1;
@@ -3614,7 +3657,7 @@ def AssertExclusiveLock : InheritableAttr {
def AssertSharedLock : InheritableAttr { def AssertSharedLock : InheritableAttr {
let Spellings = [GNU<"assert_shared_lock">]; let Spellings = [GNU<"assert_shared_lock">];
let Args = [VariadicExprArgument<"Args">]; let Args = [VariadicExprArgument<"Args">];
- let LateParsed = 1;+ let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1; let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1; let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1; let InheritEvenIfAlreadyPresent = 1;
@@ -3627,7 +3670,7 @@ def AssertSharedLock : InheritableAttr {
def ExclusiveTrylockFunction : InheritableAttr { def ExclusiveTrylockFunction : InheritableAttr {
let Spellings = [GNU<"exclusive_trylock_function">]; let Spellings = [GNU<"exclusive_trylock_function">];
let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">]; let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">];
- let LateParsed = 1;+ let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1; let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1; let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1; let InheritEvenIfAlreadyPresent = 1;
@@ -3640,7 +3683,7 @@ def ExclusiveTrylockFunction : InheritableAttr {
def SharedTrylockFunction : InheritableAttr { def SharedTrylockFunction : InheritableAttr {
let Spellings = [GNU<"shared_trylock_function">]; let Spellings = [GNU<"shared_trylock_function">];
let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">]; let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">];
- let LateParsed = 1;+ let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1; let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1; let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1; let InheritEvenIfAlreadyPresent = 1;
@@ -3651,7 +3694,7 @@ def SharedTrylockFunction : InheritableAttr {
def LockReturned : InheritableAttr { def LockReturned : InheritableAttr {
let Spellings = [GNU<"lock_returned">]; let Spellings = [GNU<"lock_returned">];
let Args = [ExprArgument<"Arg">]; let Args = [ExprArgument<"Arg">];
- let LateParsed = 1;+ let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1; let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1; let ParseArgumentsAsUnevaluated = 1;
let Subjects = SubjectList<[Function]>; let Subjects = SubjectList<[Function]>;
@@ -3661,7 +3704,7 @@ def LockReturned : InheritableAttr {
def LocksExcluded : InheritableAttr { def LocksExcluded : InheritableAttr {
let Spellings = [GNU<"locks_excluded">]; let Spellings = [GNU<"locks_excluded">];
let Args = [VariadicExprArgument<"Args">]; let Args = [VariadicExprArgument<"Args">];
- let LateParsed = 1;+ let LateParsed = LateAttrParseStandard;
let TemplateDependent = 1; let TemplateDependent = 1;
let ParseArgumentsAsUnevaluated = 1; let ParseArgumentsAsUnevaluated = 1;
let InheritEvenIfAlreadyPresent = 1; let InheritEvenIfAlreadyPresent = 1;
clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -370,4 +370,7 @@ def warn_missing_symbol_graph_dir : Warning<
"Missing symbol graph output directory, defaulting to working directory">, "Missing symbol graph output directory, defaulting to working directory">,
InGroup<ExtractAPIMisuse>; InGroup<ExtractAPIMisuse>;
+def err_ast_action_on_llvm_ir : Error<
+ "cannot apply AST actions to LLVM IR file '%0'">,
+ DefaultFatal;
} }
clang/include/clang/Basic/DiagnosticInstallAPIKinds.td
@@ -24,7 +24,7 @@ def err_no_matching_target : Error<"no matching target found for target variant
def err_unsupported_vendor : Error<"vendor '%0' is not supported: '%1'">; 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_environment : Error<"environment '%0' is not supported: '%1'">;
def err_unsupported_os : Error<"os '%0' is not supported: '%1'">; def err_unsupported_os : Error<"os '%0' is not supported: '%1'">;
-def err_cannot_read_alias_list : Error<"could not read alias list '%0': %1">;+def err_cannot_read_input_list : Error<"could not read %select{alias list|filelist}0 '%1': %2">;
} // end of command line category. } // end of command line category.
let CategoryName = "Verification" in { let CategoryName = "Verification" in {
clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -478,6 +478,15 @@ def ext_decomp_decl_empty : ExtWarn<
"ISO C++17 does not allow a decomposition group to be empty">, "ISO C++17 does not allow a decomposition group to be empty">,
InGroup<DiagGroup<"empty-decomposition">>; InGroup<DiagGroup<"empty-decomposition">>;
+// C++26 structured bindings
+def ext_decl_attrs_on_binding : ExtWarn<
+ "an attribute specifier sequence attached to a structured binding declaration "
+ "is a C++2c extension">, InGroup<CXX26>;
+def warn_cxx23_compat_decl_attrs_on_binding : Warning<
+ "an attribute specifier sequence attached to a structured binding declaration "
+ "is incompatible with C++ standards before C++2c">,
+ InGroup<CXXPre26Compat>, DefaultIgnore;
+
/// Objective-C parser diagnostics /// Objective-C parser diagnostics
def err_expected_minus_or_plus : Error< def err_expected_minus_or_plus : Error<
"method type specifier must start with '-' or '+'">; "method type specifier must start with '-' or '+'">;
@@ -1429,6 +1438,9 @@ def err_omp_decl_in_declare_simd_variant : Error<
def err_omp_sink_and_source_iteration_not_allowd: Error<" '%0 %select{sink:|source:}1' must be with '%select{omp_cur_iteration - 1|omp_cur_iteration}1'">; def err_omp_sink_and_source_iteration_not_allowd: Error<" '%0 %select{sink:|source:}1' must be with '%select{omp_cur_iteration - 1|omp_cur_iteration}1'">;
def err_omp_unknown_map_type : Error< def err_omp_unknown_map_type : Error<
"incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'">; "incorrect map type, expected one of 'to', 'from', 'tofrom', 'alloc', 'release', or 'delete'">;
+def err_omp_more_one_map_type : Error<"map type is already specified">;
+def note_previous_map_type_specified_here
+ : Note<"map type '%0' is previous specified here">;
def err_omp_unknown_map_type_modifier : Error< def err_omp_unknown_map_type_modifier : Error<
"incorrect map type modifier, expected one of: 'always', 'close', 'mapper'" "incorrect map type modifier, expected one of: 'always', 'close', 'mapper'"
"%select{|, 'present'|, 'present', 'iterator'}0%select{|, 'ompx_hold'}1">; "%select{|, 'present'|, 'present', 'iterator'}0%select{|, 'ompx_hold'}1">;
@@ -1436,6 +1448,8 @@ def err_omp_map_type_missing : Error<
"missing map type">; "missing map type">;
def err_omp_map_type_modifier_missing : Error< def err_omp_map_type_modifier_missing : Error<
"missing map type modifier">; "missing map type modifier">;
+def err_omp_map_modifier_specification_list : Error<
+ "empty modifier-specification-list is not allowed">;
def err_omp_declare_simd_inbranch_notinbranch : Error< def err_omp_declare_simd_inbranch_notinbranch : Error<
"unexpected '%0' clause, '%1' is specified already">; "unexpected '%0' clause, '%1' is specified already">;
def err_omp_expected_clause_argument def err_omp_expected_clause_argument
clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -307,6 +307,8 @@ def err_invalid_vector_long_long_decl_spec : Error <
"POWER7 or later) to be enabled">; "POWER7 or later) to be enabled">;
def err_invalid_vector_long_double_decl_spec : Error< def err_invalid_vector_long_double_decl_spec : Error<
"cannot use 'long double' with '__vector'">; "cannot use 'long double' with '__vector'">;
+def err_invalid_vector_complex_decl_spec : Error<
+ "cannot use '_Complex' with '__vector'">;
def warn_vector_long_decl_spec_combination : Warning< def warn_vector_long_decl_spec_combination : Warning<
"Use of 'long' with '__vector' is deprecated">, InGroup<Deprecated>; "Use of 'long' with '__vector' is deprecated">, InGroup<Deprecated>;
@@ -9901,6 +9903,9 @@ def warn_format_invalid_annotation : Warning<
def warn_format_P_no_precision : Warning< def warn_format_P_no_precision : Warning<
"using '%%P' format specifier without precision">, "using '%%P' format specifier without precision">,
InGroup<Format>; InGroup<Format>;
+def warn_format_P_with_objc_pointer : Warning<
+ "using '%%P' format specifier with an Objective-C pointer results in dumping runtime object structure, not object value">,
+ InGroup<Format>;
def warn_printf_ignored_flag: Warning< def warn_printf_ignored_flag: Warning<
"flag '%0' is ignored when flag '%1' is present">, "flag '%0' is ignored when flag '%1' is present">,
InGroup<Format>; InGroup<Format>;
@@ -9950,6 +9955,8 @@ def warn_ret_stack_addr_ref : Warning<
def warn_ret_local_temp_addr_ref : Warning< def warn_ret_local_temp_addr_ref : Warning<
"returning %select{address of|reference to}0 local temporary object">, "returning %select{address of|reference to}0 local temporary object">,
InGroup<ReturnStackAddress>; InGroup<ReturnStackAddress>;
+def err_ret_local_temp_ref : Error<
+ "returning reference to local temporary object">;
def warn_ret_addr_label : Warning< def warn_ret_addr_label : Warning<
"returning address of label, which is local">, "returning address of label, which is local">,
InGroup<ReturnStackAddress>; InGroup<ReturnStackAddress>;
@@ -10328,9 +10335,13 @@ def err_shufflevector_nonconstant_argument : Error<
def err_shufflevector_argument_too_large : Error< def err_shufflevector_argument_too_large : Error<
"index for __builtin_shufflevector must be less than the total number " "index for __builtin_shufflevector must be less than the total number "
"of vector elements">; "of vector elements">;
+def err_shufflevector_minus_one_is_undefined_behavior_constexpr : Error<
+ "index for __builtin_shufflevector not within the bounds of the input vectors; index of -1 found at position %0 not permitted in a constexpr context.">;
def err_convertvector_non_vector : Error< def err_convertvector_non_vector : Error<
"first argument to __builtin_convertvector must be a vector">; "first argument to __builtin_convertvector must be a vector">;
+def err_convertvector_constexpr_unsupported_vector_cast : Error<
+ "unsupported vector cast from %0 to %1 in a constant expression.">;
def err_builtin_non_vector_type : Error< def err_builtin_non_vector_type : Error<
"%0 argument to %1 must be of vector type">; "%0 argument to %1 must be of vector type">;
def err_convertvector_incompatible_vector : Error< def err_convertvector_incompatible_vector : Error<
@@ -11161,7 +11172,7 @@ def err_omp_declare_mapper_redefinition : Error<
"redefinition of user-defined mapper for type %0 with name %1">; "redefinition of user-defined mapper for type %0 with name %1">;
def err_omp_invalid_mapper: Error< def err_omp_invalid_mapper: Error<
"cannot find a valid user-defined mapper for type %0 with name %1">; "cannot find a valid user-defined mapper for type %0 with name %1">;
-def err_omp_array_section_use : Error<"OpenMP array section is not allowed here">;+def err_array_section_use : Error<"%select{OpenACC sub-array|OpenMP array section}0 is not allowed here">;
def err_omp_array_shaping_use : Error<"OpenMP array shaping operation is not allowed here">; def err_omp_array_shaping_use : Error<"OpenMP array shaping operation is not allowed here">;
def err_omp_iterator_use : Error<"OpenMP iterator is not allowed here">; def err_omp_iterator_use : Error<"OpenMP iterator is not allowed here">;
def err_omp_typecheck_section_value : Error< def err_omp_typecheck_section_value : Error<
@@ -12296,4 +12307,7 @@ def err_acc_num_gangs_num_args
"OpenACC 'num_gangs' " "OpenACC 'num_gangs' "
"%select{|clause: '%1' directive expects maximum of %2, %3 were " "%select{|clause: '%1' directive expects maximum of %2, %3 were "
"provided}0">; "provided}0">;
+def err_acc_not_a_var_ref
+ : Error<"OpenACC variable is not a valid variable name, sub-array, array "
+ "element, or composite variable member">;
} // end of sema component. } // end of sema component.
clang/include/clang/Basic/FileManager.h
@@ -114,6 +114,12 @@ class FileManager : public RefCountedBase<FileManager> {
/// ///
unsigned NextFileUID; unsigned NextFileUID;
+ /// Statistics gathered during the lifetime of the FileManager.
+ unsigned NumDirLookups = 0;
+ unsigned NumFileLookups = 0;
+ unsigned NumDirCacheMisses = 0;
+ unsigned NumFileCacheMisses = 0;
+
// Caching. // Caching.
std::unique_ptr<FileSystemStatCache> StatCache; std::unique_ptr<FileSystemStatCache> StatCache;
@@ -341,6 +347,10 @@ private:
public: public:
void PrintStats() const; void PrintStats() const;
+
+ /// Import statistics from a child FileManager and add them to this current
+ /// FileManager.
+ void AddStats(const FileManager &Other);
}; };
} // end namespace clang } // end namespace clang
clang/include/clang/Basic/LangOptions.def
@@ -164,6 +164,7 @@ LANGOPT(ExperimentalLibrary, 1, 0, "enable unstable and experimental library fea
LANGOPT(PointerAuthIntrinsics, 1, 0, "pointer authentication intrinsics") LANGOPT(PointerAuthIntrinsics, 1, 0, "pointer authentication intrinsics")
LANGOPT(DoubleSquareBracketAttributes, 1, 0, "'[[]]' attributes extension for all language standard modes") LANGOPT(DoubleSquareBracketAttributes, 1, 0, "'[[]]' attributes extension for all language standard modes")
+LANGOPT(ExperimentalLateParseAttributes, 1, 0, "experimental late parsing of attributes")
COMPATIBLE_LANGOPT(RecoveryAST, 1, 1, "Preserve expressions in AST when encountering errors") COMPATIBLE_LANGOPT(RecoveryAST, 1, 1, "Preserve expressions in AST when encountering errors")
COMPATIBLE_LANGOPT(RecoveryASTType, 1, 1, "Preserve the type in recovery expressions") COMPATIBLE_LANGOPT(RecoveryASTType, 1, 1, "Preserve the type in recovery expressions")
clang/include/clang/Basic/LangOptions.h
@@ -57,6 +57,13 @@ enum class ShaderStage {
Invalid, Invalid,
}; };
+enum class PointerAuthenticationMode : unsigned {
+ None,
+ Strip,
+ SignAndStrip,
+ SignAndAuth
+};
+
/// Bitfields of LangOptions, split out from LangOptions in order to ensure that /// Bitfields of LangOptions, split out from LangOptions in order to ensure that
/// this large collection of bitfields is a trivial class type. /// this large collection of bitfields is a trivial class type.
class LangOptionsBase { class LangOptionsBase {
clang/include/clang/Basic/OpenACCClauses.def
@@ -20,6 +20,7 @@ VISIT_CLAUSE(If)
VISIT_CLAUSE(Self) VISIT_CLAUSE(Self)
VISIT_CLAUSE(NumGangs) VISIT_CLAUSE(NumGangs)
VISIT_CLAUSE(NumWorkers) VISIT_CLAUSE(NumWorkers)
+VISIT_CLAUSE(Private)
VISIT_CLAUSE(VectorLength) VISIT_CLAUSE(VectorLength)
#undef VISIT_CLAUSE #undef VISIT_CLAUSE
clang/include/clang/Basic/PointerAuthOptions.h
@@ -0,0 +1,23 @@
+//===--- PointerAuthOptions.h -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines options for configuring pointer-auth technologies
+// like ARMv8.3.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H
+#define LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H
+
+namespace clang {
+
+constexpr unsigned PointerAuthKeyNone = -1;
+
+} // end namespace clang
+
+#endif
clang/include/clang/Basic/StmtNodes.td
@@ -71,7 +71,7 @@ def OffsetOfExpr : StmtNode<Expr>;
def UnaryExprOrTypeTraitExpr : StmtNode<Expr>; def UnaryExprOrTypeTraitExpr : StmtNode<Expr>;
def ArraySubscriptExpr : StmtNode<Expr>; def ArraySubscriptExpr : StmtNode<Expr>;
def MatrixSubscriptExpr : StmtNode<Expr>; def MatrixSubscriptExpr : StmtNode<Expr>;
-def OMPArraySectionExpr : StmtNode<Expr>;+def ArraySectionExpr : StmtNode<Expr>;
def OMPIteratorExpr : StmtNode<Expr>; def OMPIteratorExpr : StmtNode<Expr>;
def CallExpr : StmtNode<Expr>; def CallExpr : StmtNode<Expr>;
def MemberExpr : StmtNode<Expr>; def MemberExpr : StmtNode<Expr>;
clang/include/clang/Basic/TargetInfo.h
@@ -40,6 +40,7 @@
#include <cassert> #include <cassert>
#include <optional> #include <optional>
#include <string> #include <string>
+#include <utility>
#include <vector> #include <vector>
namespace llvm { namespace llvm {
@@ -1792,6 +1793,15 @@ public:
/// Whether to support HIP image/texture API's. /// Whether to support HIP image/texture API's.
virtual bool hasHIPImageSupport() const { return true; } virtual bool hasHIPImageSupport() const { return true; }
+ /// The first value in the pair is the minimum offset between two objects to
+ /// avoid false sharing (destructive interference). The second value in the
+ /// pair is maximum size of contiguous memory to promote true sharing
+ /// (constructive interference). Neither of these values are considered part
+ /// of the ABI and can be changed by targets at any time.
+ virtual std::pair<unsigned, unsigned> hardwareInterferenceSizes() const {
+ return std::make_pair(64, 64);
+ }
+
protected: protected:
/// Copy type and layout related info. /// Copy type and layout related info.
void copyAuxTarget(const TargetInfo *Aux); void copyAuxTarget(const TargetInfo *Aux);
clang/include/clang/Basic/arm_neon.td
@@ -275,7 +275,7 @@ def OP_VCVT_BF16_F32_HI_A32
(call "vget_low", $p0))>; (call "vget_low", $p0))>;
def OP_CVT_F32_BF16 def OP_CVT_F32_BF16
- : Op<(bitcast "R", (op "<<", (bitcast "int32_t", $p0),+ : Op<(bitcast "R", (op "<<", (cast "int32_t", (bitcast "int16_t", $p0)),
(literal "int32_t", "16")))>; (literal "int32_t", "16")))>;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
clang/include/clang/Basic/arm_sve.td
@@ -1961,19 +1961,20 @@ def SVPSEL_D : SInst<"svpsel_lane_b64", "PPPm", "Pl", MergeNone, "", [IsStreamin
// Standalone sve2.1 builtins // Standalone sve2.1 builtins
let TargetGuard = "sve2p1" in { let TargetGuard = "sve2p1" in {
-def SVORQV : SInst<"svorqv[_{d}]", "{Pd", "csilUcUsUiUl", MergeNone, "aarch64_sve_orqv", [IsReductionQV]>;+def SVORQV : SInst<"svorqv[_{d}]", "{Pd", "csilUcUsUiUl", MergeNone, "aarch64_sve_orqv", [IsReductionQV]>;
-def SVEORQV : SInst<"sveorqv[_{d}]", "{Pd", "csilUcUsUiUl", MergeNone, "aarch64_sve_eorqv", [IsReductionQV]>;+def SVEORQV : SInst<"sveorqv[_{d}]", "{Pd", "csilUcUsUiUl", MergeNone, "aarch64_sve_eorqv", [IsReductionQV]>;
-def SVADDQV : SInst<"svaddqv[_{d}]", "{Pd", "hfdcsilUcUsUiUl", MergeNone, "aarch64_sve_addqv", [IsReductionQV]>;+def SVADDQV : SInst<"svaddqv[_{d}]", "{Pd", "csilUcUsUiUl", MergeNone, "aarch64_sve_addqv", [IsReductionQV]>;
-def SVANDQV : SInst<"svandqv[_{d}]", "{Pd", "csilUcUsUiUl", MergeNone, "aarch64_sve_andqv", [IsReductionQV]>;+def SVANDQV : SInst<"svandqv[_{d}]", "{Pd", "csilUcUsUiUl", MergeNone, "aarch64_sve_andqv", [IsReductionQV]>;
-def SVSMAXQV : SInst<"svmaxqv[_{d}]", "{Pd", "csil", MergeNone, "aarch64_sve_smaxqv", [IsReductionQV]>;+def SVSMAXQV : SInst<"svmaxqv[_{d}]", "{Pd", "csil", MergeNone, "aarch64_sve_smaxqv", [IsReductionQV]>;
-def SVUMAXQV : SInst<"svmaxqv[_{d}]", "{Pd", "UcUsUiUl", MergeNone, "aarch64_sve_umaxqv", [IsReductionQV]>;+def SVUMAXQV : SInst<"svmaxqv[_{d}]", "{Pd", "UcUsUiUl", MergeNone, "aarch64_sve_umaxqv", [IsReductionQV]>;
-def SVSMINQV : SInst<"svminqv[_{d}]", "{Pd", "csil", MergeNone, "aarch64_sve_sminqv", [IsReductionQV]>;+def SVSMINQV : SInst<"svminqv[_{d}]", "{Pd", "csil", MergeNone, "aarch64_sve_sminqv", [IsReductionQV]>;
-def SVUMINQV : SInst<"svminqv[_{d}]", "{Pd", "UcUsUiUl", MergeNone, "aarch64_sve_uminqv", [IsReductionQV]>;+def SVUMINQV : SInst<"svminqv[_{d}]", "{Pd", "UcUsUiUl", MergeNone, "aarch64_sve_uminqv", [IsReductionQV]>;
-+
-def SVFMAXNMQV: SInst<"svmaxnmqv[_{d}]", "{Pd", "hfd", MergeNone, "aarch64_sve_fmaxnmqv", [IsReductionQV]>;+def SVFADDQV : SInst<"svaddqv[_{d}]", "{Pd", "hfd", MergeNone, "aarch64_sve_faddqv", [IsReductionQV]>;
-def SVFMINNMQV: SInst<"svminnmqv[_{d}]", "{Pd", "hfd", MergeNone, "aarch64_sve_fminnmqv", [IsReductionQV]>;+def SVFMAXNMQV : SInst<"svmaxnmqv[_{d}]", "{Pd", "hfd", MergeNone, "aarch64_sve_fmaxnmqv", [IsReductionQV]>;
-def SVFMAXQV: SInst<"svmaxqv[_{d}]", "{Pd", "hfd", MergeNone, "aarch64_sve_fmaxqv", [IsReductionQV]>;+def SVFMINNMQV : SInst<"svminnmqv[_{d}]", "{Pd", "hfd", MergeNone, "aarch64_sve_fminnmqv", [IsReductionQV]>;
-def SVFMINQV: SInst<"svminqv[_{d}]", "{Pd", "hfd", MergeNone, "aarch64_sve_fminqv", [IsReductionQV]>;+def SVFMAXQV : SInst<"svmaxqv[_{d}]", "{Pd", "hfd", MergeNone, "aarch64_sve_fmaxqv", [IsReductionQV]>;
+def SVFMINQV : SInst<"svminqv[_{d}]", "{Pd", "hfd", MergeNone, "aarch64_sve_fminqv", [IsReductionQV]>;
} }
let TargetGuard = "sve2p1|sme2" in { let TargetGuard = "sve2p1|sme2" in {
clang/include/clang/CIR/CMakeLists.txt
@@ -0,0 +1,6 @@
+set(MLIR_INCLUDE_DIR ${LLVM_MAIN_SRC_DIR}/../mlir/include ) # --includedir
+set(MLIR_TABLEGEN_OUTPUT_DIR ${CMAKE_BINARY_DIR}/tools/mlir/include)
+include_directories(${MLIR_INCLUDE_DIR})
+include_directories(${MLIR_TABLEGEN_OUTPUT_DIR})
+
+add_subdirectory(Dialect)
clang/include/clang/CIR/Dialect/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(IR)
clang/include/clang/CIR/Dialect/IR/CIRDialect.h
@@ -0,0 +1,16 @@
+//===- CIRDialect.h - CIR dialect -------------------------------*- 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 declares the CIR dialect.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CIR_DIALECT_IR_CIRDIALECT_H
+#define LLVM_CLANG_CIR_DIALECT_IR_CIRDIALECT_H
+
+#endif // LLVM_CLANG_CIR_DIALECT_IR_CIRDIALECT_H
clang/include/clang/CIR/Dialect/IR/CIRDialect.td
@@ -0,0 +1,44 @@
+//===- CIRDialect.td - CIR dialect -------------------------*- tablegen -*-===//
+//
+// 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 declares the CIR dialect.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CIR_DIALECT_IR_CIRDIALECT
+#define LLVM_CLANG_CIR_DIALECT_IR_CIRDIALECT
+
+include "mlir/IR/OpBase.td"
+
+def CIR_Dialect : Dialect {
+ let name = "cir";
+
+ // A short one-line summary of our dialect.
+ let summary = "A high-level dialect for analyzing and optimizing Clang "
+ "supported languages";
+
+ let cppNamespace = "::mlir::cir";
+
+ let useDefaultAttributePrinterParser = 0;
+ let useDefaultTypePrinterParser = 0;
+
+ let extraClassDeclaration = [{
+ void registerAttributes();
+ void registerTypes();
+
+ Type parseType(DialectAsmParser &parser) const override;
+ void printType(Type type, DialectAsmPrinter &printer) const override;
+
+ Attribute parseAttribute(DialectAsmParser &parser,
+ Type type) const override;
+
+ void printAttribute(Attribute attr, DialectAsmPrinter &os) const override;
+ }];
+}
+
+#endif // LLVM_CLANG_CIR_DIALECT_IR_CIRDIALECT
clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -0,0 +1,19 @@
+//===-- CIROps.td - CIR dialect definition -----------------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Definition of the CIR dialect
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CIR_DIALECT_IR_CIROPS
+#define LLVM_CLANG_CIR_DIALECT_IR_CIROPS
+
+include "clang/CIR/Dialect/IR/CIRDialect.td"
+
+#endif // LLVM_CLANG_CIR_DIALECT_IR_CIROPS
clang/include/clang/CIR/Dialect/IR/CMakeLists.txt
@@ -0,0 +1,16 @@
+# This replicates part of the add_mlir_dialect cmake function from MLIR that
+# cannot be used here. This happens because it expects to be run inside MLIR
+# directory which is not the case for CIR (and also FIR, both have similar
+# workarounds).
+
+# Equivalent to add_mlir_dialect(CIROps cir)
+set(LLVM_TARGET_DEFINITIONS CIROps.td)
+mlir_tablegen(CIROps.h.inc -gen-op-decls)
+mlir_tablegen(CIROps.cpp.inc -gen-op-defs)
+mlir_tablegen(CIROpsTypes.h.inc -gen-typedef-decls)
+mlir_tablegen(CIROpsTypes.cpp.inc -gen-typedef-defs)
+mlir_tablegen(CIROpsDialect.h.inc -gen-dialect-decls)
+mlir_tablegen(CIROpsDialect.cpp.inc -gen-dialect-defs)
+add_public_tablegen_target(MLIRCIROpsIncGen)
+add_dependencies(mlir-headers MLIRCIROpsIncGen)
+
clang/include/clang/Driver/Options.td
@@ -1608,6 +1608,13 @@ defm double_square_bracket_attributes : BoolFOption<"double-square-bracket-attri
LangOpts<"DoubleSquareBracketAttributes">, DefaultTrue, PosFlag<SetTrue>, LangOpts<"DoubleSquareBracketAttributes">, DefaultTrue, PosFlag<SetTrue>,
NegFlag<SetFalse>>; NegFlag<SetFalse>>;
+defm experimental_late_parse_attributes : BoolFOption<"experimental-late-parse-attributes",
+ LangOpts<"ExperimentalLateParseAttributes">, DefaultFalse,
+ PosFlag<SetTrue, [], [ClangOption], "Enable">,
+ NegFlag<SetFalse, [], [ClangOption], "Disable">,
+ BothFlags<[], [ClangOption, CC1Option],
+ " experimental late parsing of attributes">>;
+
defm autolink : BoolFOption<"autolink", defm autolink : BoolFOption<"autolink",
CodeGenOpts<"Autolink">, DefaultTrue, CodeGenOpts<"Autolink">, DefaultTrue,
NegFlag<SetFalse, [], [ClangOption, CC1Option], NegFlag<SetFalse, [], [ClangOption, CC1Option],
@@ -2615,6 +2622,11 @@ defm protect_parens : BoolFOption<"protect-parens",
"floating-point expressions are evaluated">, "floating-point expressions are evaluated">,
NegFlag<SetFalse>>; NegFlag<SetFalse>>;
+defm daz_ftz : SimpleMFlag<"daz-ftz",
+ "Globally set", "Do not globally set",
+ " the denormals-are-zero (DAZ) and flush-to-zero (FTZ) bits in the "
+ "floating-point control register on program startup">;
+
def ffor_scope : Flag<["-"], "ffor-scope">, Group<f_Group>; def ffor_scope : Flag<["-"], "ffor-scope">, Group<f_Group>;
def fno_for_scope : Flag<["-"], "fno-for-scope">, Group<f_Group>; def fno_for_scope : Flag<["-"], "fno-for-scope">, Group<f_Group>;
@@ -2881,6 +2893,17 @@ def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Gr
def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>; def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>;
def fapple_link_rtlib : Flag<["-"], "fapple-link-rtlib">, Group<f_Group>, def fapple_link_rtlib : Flag<["-"], "fapple-link-rtlib">, Group<f_Group>,
HelpText<"Force linking the clang builtins runtime library">; HelpText<"Force linking the clang builtins runtime library">;
+
+/// ClangIR-specific options - BEGIN
+defm clangir : BoolFOption<"clangir",
+ FrontendOpts<"UseClangIRPipeline">, DefaultFalse,
+ PosFlag<SetTrue, [], [ClangOption, CC1Option], "Use the ClangIR pipeline to compile">,
+ NegFlag<SetFalse, [], [ClangOption, CC1Option], "Use the AST -> LLVM pipeline to compile">,
+ BothFlags<[], [ClangOption, CC1Option], "">>;
+def emit_cir : Flag<["-"], "emit-cir">, Visibility<[CC1Option]>,
+ Group<Action_Group>, HelpText<"Build ASTs and then lower to ClangIR">;
+/// ClangIR-specific options - END
+
def flto_EQ : Joined<["-"], "flto=">, def flto_EQ : Joined<["-"], "flto=">,
Visibility<[ClangOption, CLOption, CC1Option, FC1Option, FlangOption]>, Visibility<[ClangOption, CLOption, CC1Option, FC1Option, FlangOption]>,
Group<f_Group>, Group<f_Group>,
@@ -4880,6 +4903,8 @@ def msimd128 : Flag<["-"], "msimd128">, Group<m_wasm_Features_Group>;
def mno_simd128 : Flag<["-"], "mno-simd128">, Group<m_wasm_Features_Group>; def mno_simd128 : Flag<["-"], "mno-simd128">, Group<m_wasm_Features_Group>;
def mrelaxed_simd : Flag<["-"], "mrelaxed-simd">, Group<m_wasm_Features_Group>; def mrelaxed_simd : Flag<["-"], "mrelaxed-simd">, Group<m_wasm_Features_Group>;
def mno_relaxed_simd : Flag<["-"], "mno-relaxed-simd">, Group<m_wasm_Features_Group>; def mno_relaxed_simd : Flag<["-"], "mno-relaxed-simd">, Group<m_wasm_Features_Group>;
+def mhalf_precision : Flag<["-"], "mhalf-precision">, Group<m_wasm_Features_Group>;
+def mno_half_precision : Flag<["-"], "mno-half-precision">, Group<m_wasm_Features_Group>;
def mnontrapping_fptoint : Flag<["-"], "mnontrapping-fptoint">, Group<m_wasm_Features_Group>; def mnontrapping_fptoint : Flag<["-"], "mnontrapping-fptoint">, Group<m_wasm_Features_Group>;
def mno_nontrapping_fptoint : Flag<["-"], "mno-nontrapping-fptoint">, Group<m_wasm_Features_Group>; def mno_nontrapping_fptoint : Flag<["-"], "mno-nontrapping-fptoint">, Group<m_wasm_Features_Group>;
def msign_ext : Flag<["-"], "msign-ext">, Group<m_wasm_Features_Group>; def msign_ext : Flag<["-"], "msign-ext">, Group<m_wasm_Features_Group>;
@@ -6586,12 +6611,6 @@ def J : JoinedOrSeparate<["-"], "J">,
Group<gfortran_Group>, Group<gfortran_Group>,
Alias<module_dir>; Alias<module_dir>;
-let Visibility = [FlangOption] in {
-def no_fortran_main : Flag<["-"], "fno-fortran-main">,
- Visibility<[FlangOption]>, Group<f_Group>,
- HelpText<"Do not include Fortran_main.a (provided by Flang) when linking">;
-} // let Visibility = [ FlangOption ]
-
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// FC1 Options // FC1 Options
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
clang/include/clang/Frontend/ASTUnit.h
@@ -241,7 +241,7 @@ private:
/// A list of the serialization ID numbers for each of the top-level /// A list of the serialization ID numbers for each of the top-level
/// declarations parsed within the precompiled preamble. /// declarations parsed within the precompiled preamble.
- std::vector<serialization::DeclID> TopLevelDeclsInPreamble;+ std::vector<LocalDeclID> TopLevelDeclsInPreamble;
/// Whether we should be caching code-completion results. /// Whether we should be caching code-completion results.
bool ShouldCacheCodeCompletionResults : 1; bool ShouldCacheCodeCompletionResults : 1;
clang/include/clang/Frontend/FrontendOptions.h
@@ -65,6 +65,9 @@ enum ActionKind {
/// Translate input source into HTML. /// Translate input source into HTML.
EmitHTML, EmitHTML,
+ /// Emit a .cir file
+ EmitCIR,
+
/// Emit a .ll file. /// Emit a .ll file.
EmitLLVM, EmitLLVM,
@@ -408,6 +411,10 @@ public:
LLVM_PREFERRED_TYPE(bool) LLVM_PREFERRED_TYPE(bool)
unsigned GenReducedBMI : 1; unsigned GenReducedBMI : 1;
+ /// Use Clang IR pipeline to emit code
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned UseClangIRPipeline : 1;
+
CodeCompleteOptions CodeCompleteOpts; CodeCompleteOptions CodeCompleteOpts;
/// Specifies the output format of the AST. /// Specifies the output format of the AST.
@@ -590,7 +597,7 @@ public:
EmitSymbolGraph(false), EmitExtensionSymbolGraphs(false), EmitSymbolGraph(false), EmitExtensionSymbolGraphs(false),
EmitSymbolGraphSymbolLabelsForTesting(false), EmitSymbolGraphSymbolLabelsForTesting(false),
EmitPrettySymbolGraphs(false), GenReducedBMI(false), EmitPrettySymbolGraphs(false), GenReducedBMI(false),
- TimeTraceGranularity(500) {}+ UseClangIRPipeline(false), TimeTraceGranularity(500) {}
/// getInputKindForExtension - Return the appropriate input kind for a file /// getInputKindForExtension - Return the appropriate input kind for a file
/// extension. For example, "c" would return Language::C. /// extension. For example, "c" would return Language::C.
clang/include/clang/Frontend/MultiplexConsumer.h
@@ -35,7 +35,7 @@ public:
void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II) override; void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II) override;
void MacroRead(serialization::MacroID ID, MacroInfo *MI) override; void MacroRead(serialization::MacroID ID, MacroInfo *MI) override;
void TypeRead(serialization::TypeIdx Idx, QualType T) override; void TypeRead(serialization::TypeIdx Idx, QualType T) override;
- void DeclRead(serialization::DeclID ID, const Decl *D) override;+ void DeclRead(GlobalDeclID ID, const Decl *D) override;
void SelectorRead(serialization::SelectorID iD, Selector Sel) override; void SelectorRead(serialization::SelectorID iD, Selector Sel) override;
void MacroDefinitionRead(serialization::PreprocessedEntityID, void MacroDefinitionRead(serialization::PreprocessedEntityID,
MacroDefinitionRecord *MD) override; MacroDefinitionRecord *MD) override;
clang/include/clang/InstallAPI/FileList.h
@@ -29,9 +29,10 @@ public:
/// ///
/// \param InputBuffer JSON input data. /// \param InputBuffer JSON input data.
/// \param Destination Container to load headers into. /// \param Destination Container to load headers into.
+ /// \param FM Optional File Manager to validate input files exist.
static llvm::Error static llvm::Error
loadHeaders(std::unique_ptr<llvm::MemoryBuffer> InputBuffer, loadHeaders(std::unique_ptr<llvm::MemoryBuffer> InputBuffer,
- HeaderSeq &Destination);+ HeaderSeq &Destination, clang::FileManager *FM = nullptr);
FileListReader() = delete; FileListReader() = delete;
}; };
clang/include/clang/Parse/Parser.h
@@ -1398,12 +1398,21 @@ private:
// A list of late-parsed attributes. Used by ParseGNUAttributes. // A list of late-parsed attributes. Used by ParseGNUAttributes.
class LateParsedAttrList: public SmallVector<LateParsedAttribute *, 2> { class LateParsedAttrList: public SmallVector<LateParsedAttribute *, 2> {
public: public:
- LateParsedAttrList(bool PSoon = false) : ParseSoon(PSoon) { }+ LateParsedAttrList(bool PSoon = false,
+ bool LateAttrParseExperimentalExtOnly = false)
+ : ParseSoon(PSoon),
+ LateAttrParseExperimentalExtOnly(LateAttrParseExperimentalExtOnly) {}
bool parseSoon() { return ParseSoon; } bool parseSoon() { return ParseSoon; }
+ /// returns true iff the attribute to be parsed should only be late parsed
+ /// if it is annotated with `LateAttrParseExperimentalExt`
+ bool lateAttrParseExperimentalExtOnly() {
+ return LateAttrParseExperimentalExtOnly;
+ }
private: private:
- bool ParseSoon; // Are we planning to parse these shortly after creation?+ bool ParseSoon; // Are we planning to parse these shortly after creation?
+ bool LateAttrParseExperimentalExtOnly;
}; };
/// Contains the lexed tokens of a member function definition /// Contains the lexed tokens of a member function definition
@@ -3645,11 +3654,12 @@ private:
ExprResult ParseOpenACCIDExpression(); ExprResult ParseOpenACCIDExpression();
/// Parses the variable list for the `cache` construct. /// Parses the variable list for the `cache` construct.
void ParseOpenACCCacheVarList(); void ParseOpenACCCacheVarList();
+
+ using OpenACCVarParseResult = std::pair<ExprResult, OpenACCParseCanContinue>;
/// Parses a single variable in a variable list for OpenACC. /// Parses a single variable in a variable list for OpenACC.
- bool ParseOpenACCVar();+ OpenACCVarParseResult ParseOpenACCVar();
- /// Parses the variable list for the variety of clauses that take a var-list,+ /// Parses the variable list for the variety of places that take a var-list.
- /// including the optional Special Token listed for some,based on clause type.+ llvm::SmallVector<Expr *> ParseOpenACCVarList();
- bool ParseOpenACCClauseVarList(OpenACCClauseKind Kind);
/// Parses any parameters for an OpenACC Clause, including required/optional /// Parses any parameters for an OpenACC Clause, including required/optional
/// parens. /// parens.
OpenACCClauseParseResult OpenACCClauseParseResult
clang/include/clang/Sema/DeclSpec.h
@@ -36,6 +36,7 @@
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Compiler.h" #include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
+#include <optional>
namespace clang { namespace clang {
class ASTContext; class ASTContext;
@@ -1790,6 +1791,7 @@ public:
struct Binding { struct Binding {
IdentifierInfo *Name; IdentifierInfo *Name;
SourceLocation NameLoc; SourceLocation NameLoc;
+ std::optional<ParsedAttributes> Attrs;
}; };
private: private:
@@ -1809,15 +1811,15 @@ public:
: Bindings(nullptr), NumBindings(0), DeleteBindings(false) {} : Bindings(nullptr), NumBindings(0), DeleteBindings(false) {}
DecompositionDeclarator(const DecompositionDeclarator &G) = delete; DecompositionDeclarator(const DecompositionDeclarator &G) = delete;
DecompositionDeclarator &operator=(const DecompositionDeclarator &G) = delete; DecompositionDeclarator &operator=(const DecompositionDeclarator &G) = delete;
- ~DecompositionDeclarator() {+ ~DecompositionDeclarator() { clear(); }
- if (DeleteBindings)
- delete[] Bindings;
- }
void clear() { void clear() {
LSquareLoc = RSquareLoc = SourceLocation(); LSquareLoc = RSquareLoc = SourceLocation();
if (DeleteBindings) if (DeleteBindings)
delete[] Bindings; delete[] Bindings;
+ else
+ llvm::for_each(llvm::MutableArrayRef(Bindings, NumBindings),
+ [](Binding &B) { B.Attrs.reset(); });
Bindings = nullptr; Bindings = nullptr;
NumBindings = 0; NumBindings = 0;
DeleteBindings = false; DeleteBindings = false;
@@ -2339,10 +2341,10 @@ public:
} }
/// Set the decomposition bindings for this declarator. /// Set the decomposition bindings for this declarator.
- void+ void setDecompositionBindings(
- setDecompositionBindings(SourceLocation LSquareLoc,+ SourceLocation LSquareLoc,
- ArrayRef<DecompositionDeclarator::Binding> Bindings,+ MutableArrayRef<DecompositionDeclarator::Binding> Bindings,
- SourceLocation RSquareLoc);+ SourceLocation RSquareLoc);
/// AddTypeInfo - Add a chunk to this declarator. Also extend the range to /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to
/// EndLoc, which should be the last token of the chunk. /// EndLoc, which should be the last token of the chunk.
clang/include/clang/Sema/Lookup.h
@@ -499,7 +499,9 @@ public:
/// Note that while no result was found in the current instantiation, /// Note that while no result was found in the current instantiation,
/// there were dependent base classes that could not be searched. /// there were dependent base classes that could not be searched.
void setNotFoundInCurrentInstantiation() { void setNotFoundInCurrentInstantiation() {
- assert(ResultKind == NotFound && Decls.empty());+ assert((ResultKind == NotFound ||
+ ResultKind == NotFoundInCurrentInstantiation) &&
+ Decls.empty());
ResultKind = NotFoundInCurrentInstantiation; ResultKind = NotFoundInCurrentInstantiation;
} }
clang/include/clang/Sema/MultiplexExternalSemaSource.h
@@ -65,7 +65,7 @@ public:
/// Resolve a declaration ID into a declaration, potentially /// Resolve a declaration ID into a declaration, potentially
/// building a new declaration. /// building a new declaration.
- Decl *GetExternalDecl(Decl::DeclID ID) override;+ Decl *GetExternalDecl(GlobalDeclID ID) override;
/// Complete the redeclaration chain if it's been extended since the /// Complete the redeclaration chain if it's been extended since the
/// previous generation of the AST source. /// previous generation of the AST source.
clang/include/clang/Sema/ParsedAttr.h
@@ -948,6 +948,7 @@ public:
ParsedAttributes(AttributeFactory &factory) : pool(factory) {} ParsedAttributes(AttributeFactory &factory) : pool(factory) {}
ParsedAttributes(const ParsedAttributes &) = delete; ParsedAttributes(const ParsedAttributes &) = delete;
ParsedAttributes &operator=(const ParsedAttributes &) = delete; ParsedAttributes &operator=(const ParsedAttributes &) = delete;
+ ParsedAttributes(ParsedAttributes &&G) = default;
AttributePool &getPool() const { return pool; } AttributePool &getPool() const { return pool; }
clang/include/clang/Sema/Sema.h
@@ -4097,12 +4097,12 @@ public:
SmallVectorImpl<QualType> &Exceptions, SmallVectorImpl<QualType> &Exceptions,
FunctionProtoType::ExceptionSpecInfo &ESI); FunctionProtoType::ExceptionSpecInfo &ESI);
- /// Add an exception-specification to the given member function+ /// Add an exception-specification to the given member or friend function
- /// (or member function template). The exception-specification was parsed+ /// (or function template). The exception-specification was parsed
- /// after the method itself was declared.+ /// after the function itself was declared.
void actOnDelayedExceptionSpecification( void actOnDelayedExceptionSpecification(
- Decl *Method, ExceptionSpecificationType EST,+ Decl *D, ExceptionSpecificationType EST, SourceRange SpecificationRange,
- SourceRange SpecificationRange, ArrayRef<ParsedType> DynamicExceptions,+ ArrayRef<ParsedType> DynamicExceptions,
ArrayRef<SourceRange> DynamicExceptionRanges, Expr *NoexceptExpr); ArrayRef<SourceRange> DynamicExceptionRanges, Expr *NoexceptExpr);
class InheritedConstructorInfo; class InheritedConstructorInfo;
@@ -6978,12 +6978,6 @@ public:
SourceLocation TemplateKWLoc, SourceLocation TemplateKWLoc,
UnqualifiedId &Member, Decl *ObjCImpDecl); UnqualifiedId &Member, Decl *ObjCImpDecl);
- MemberExpr *BuildMemberExpr(
- Expr *Base, bool IsArrow, SourceLocation OpLoc, const CXXScopeSpec *SS,
- SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl,
- bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo,
- QualType Ty, ExprValueKind VK, ExprObjectKind OK,
- const TemplateArgumentListInfo *TemplateArgs = nullptr);
MemberExpr * MemberExpr *
BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc, BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc,
NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
@@ -7472,7 +7466,7 @@ public:
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
CXXScopeSpec &SS); CXXScopeSpec &SS);
bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS,
- bool AllowBuiltinCreation = false,+ QualType ObjectType, bool AllowBuiltinCreation = false,
bool EnteringContext = false); bool EnteringContext = false);
ObjCProtocolDecl *LookupProtocol( ObjCProtocolDecl *LookupProtocol(
IdentifierInfo *II, SourceLocation IdLoc, IdentifierInfo *II, SourceLocation IdLoc,
@@ -8881,11 +8875,13 @@ public:
/// functions (but no function templates). /// functions (but no function templates).
FoundFunctions, FoundFunctions,
}; };
- bool LookupTemplateName(+
- LookupResult &R, Scope *S, CXXScopeSpec &SS, QualType ObjectType,+ bool
- bool EnteringContext, bool &MemberOfUnknownSpecialization,+ LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS,
- RequiredTemplateKind RequiredTemplate = SourceLocation(),+ QualType ObjectType, bool EnteringContext,
- AssumedTemplateKind *ATK = nullptr, bool AllowTypoCorrection = true);+ RequiredTemplateKind RequiredTemplate = SourceLocation(),
+ AssumedTemplateKind *ATK = nullptr,
+ bool AllowTypoCorrection = true);
TemplateNameKind isTemplateName(Scope *S, CXXScopeSpec &SS, TemplateNameKind isTemplateName(Scope *S, CXXScopeSpec &SS,
bool hasTemplateKeyword, bool hasTemplateKeyword,
@@ -9249,7 +9245,8 @@ public:
void NoteTemplateParameterLocation(const NamedDecl &Decl); void NoteTemplateParameterLocation(const NamedDecl &Decl);
ExprResult BuildExpressionFromDeclTemplateArgument( ExprResult BuildExpressionFromDeclTemplateArgument(
- const TemplateArgument &Arg, QualType ParamType, SourceLocation Loc);+ const TemplateArgument &Arg, QualType ParamType, SourceLocation Loc,
+ NamedDecl *TemplateParam = nullptr);
ExprResult ExprResult
BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg, BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
SourceLocation Loc); SourceLocation Loc);
@@ -9572,9 +9569,10 @@ public:
bool isSameOrCompatibleFunctionType(QualType Param, QualType Arg); bool isSameOrCompatibleFunctionType(QualType Param, QualType Arg);
- TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg,+ TemplateArgumentLoc
- QualType NTTPType,+ getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType,
- SourceLocation Loc);+ SourceLocation Loc,
+ NamedDecl *TemplateParam = nullptr);
/// Get a template argument mapping the given template parameter to itself, /// Get a template argument mapping the given template parameter to itself,
/// e.g. for X in \c template<int X>, this would return an expression template /// e.g. for X in \c template<int X>, this would return an expression template
clang/include/clang/Sema/SemaOpenACC.h
@@ -48,8 +48,12 @@ public:
SmallVector<Expr *> IntExprs; SmallVector<Expr *> IntExprs;
}; };
+ struct VarListDetails {
+ SmallVector<Expr *> VarList;
+ };
+
std::variant<std::monostate, DefaultDetails, ConditionDetails, std::variant<std::monostate, DefaultDetails, ConditionDetails,
- IntExprDetails>+ IntExprDetails, VarListDetails>
Details = std::monostate{}; Details = std::monostate{};
public: public:
@@ -112,6 +116,16 @@ public:
return const_cast<OpenACCParsedClause *>(this)->getIntExprs(); return const_cast<OpenACCParsedClause *>(this)->getIntExprs();
} }
+ ArrayRef<Expr *> getVarList() {
+ assert(ClauseKind == OpenACCClauseKind::Private &&
+ "Parsed clause kind does not have a var-list");
+ return std::get<VarListDetails>(Details).VarList;
+ }
+
+ ArrayRef<Expr *> getVarList() const {
+ return const_cast<OpenACCParsedClause *>(this)->getVarList();
+ }
+
void setLParenLoc(SourceLocation EndLoc) { LParenLoc = EndLoc; } void setLParenLoc(SourceLocation EndLoc) { LParenLoc = EndLoc; }
void setEndLoc(SourceLocation EndLoc) { ClauseRange.setEnd(EndLoc); } void setEndLoc(SourceLocation EndLoc) { ClauseRange.setEnd(EndLoc); }
@@ -147,7 +161,19 @@ public:
ClauseKind == OpenACCClauseKind::NumWorkers || ClauseKind == OpenACCClauseKind::NumWorkers ||
ClauseKind == OpenACCClauseKind::VectorLength) && ClauseKind == OpenACCClauseKind::VectorLength) &&
"Parsed clause kind does not have a int exprs"); "Parsed clause kind does not have a int exprs");
- Details = IntExprDetails{IntExprs};+ Details = IntExprDetails{std::move(IntExprs)};
+ }
+
+ void setVarListDetails(ArrayRef<Expr *> VarList) {
+ assert(ClauseKind == OpenACCClauseKind::Private &&
+ "Parsed clause kind does not have a var-list");
+ Details = VarListDetails{{VarList.begin(), VarList.end()}};
+ }
+
+ void setVarListDetails(llvm::SmallVector<Expr *> &&VarList) {
+ assert(ClauseKind == OpenACCClauseKind::Private &&
+ "Parsed clause kind does not have a var-list");
+ Details = VarListDetails{std::move(VarList)};
} }
}; };
@@ -193,6 +219,16 @@ public:
/// conversions and diagnostics to 'int'. /// conversions and diagnostics to 'int'.
ExprResult ActOnIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK, ExprResult ActOnIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
SourceLocation Loc, Expr *IntExpr); SourceLocation Loc, Expr *IntExpr);
+
+ /// Called when encountering a 'var' for OpenACC, ensures it is actually a
+ /// declaration reference to a variable of the correct type.
+ ExprResult ActOnVar(Expr *VarExpr);
+
+ /// Checks and creates an Array Section used in an OpenACC construct/clause.
+ ExprResult ActOnArraySectionExpr(Expr *Base, SourceLocation LBLoc,
+ Expr *LowerBound,
+ SourceLocation ColonLocFirst, Expr *Length,
+ SourceLocation RBLoc);
}; };
} // namespace clang } // namespace clang
clang/include/clang/Serialization/ASTBitCodes.h
@@ -17,6 +17,7 @@
#ifndef LLVM_CLANG_SERIALIZATION_ASTBITCODES_H #ifndef LLVM_CLANG_SERIALIZATION_ASTBITCODES_H
#define LLVM_CLANG_SERIALIZATION_ASTBITCODES_H #define LLVM_CLANG_SERIALIZATION_ASTBITCODES_H
+#include "clang/AST/DeclID.h"
#include "clang/AST/DeclarationName.h" #include "clang/AST/DeclarationName.h"
#include "clang/AST/Type.h" #include "clang/AST/Type.h"
#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/IdentifierTable.h"
@@ -59,91 +60,9 @@ const unsigned VERSION_MINOR = 1;
/// and start at 1. 0 is reserved for NULL. /// and start at 1. 0 is reserved for NULL.
using IdentifierID = uint32_t; using IdentifierID = uint32_t;
-/// An ID number that refers to a declaration in an AST file.+/// An ID number that refers to a declaration in an AST file. See the comments
-///+/// in DeclIDBase for details.
-/// The ID numbers of declarations are consecutive (in order of+using DeclID = DeclIDBase::DeclID;
-/// discovery), with values below NUM_PREDEF_DECL_IDS being reserved.
-/// At the start of a chain of precompiled headers, declaration ID 1 is
-/// used for the translation unit declaration.
-///
-/// FIXME: Merge with Decl::DeclID
-using DeclID = uint32_t;
-
-class LocalDeclID {
-public:
- explicit LocalDeclID(DeclID ID) : ID(ID) {}
-
- DeclID get() const { return ID; }
-
-private:
- DeclID ID;
-};
-
-/// Wrapper class for DeclID. This is helpful to not mix the use of LocalDeclID
-/// and GlobalDeclID to improve the type safety.
-class GlobalDeclID {
-public:
- GlobalDeclID() : ID(0) {}
- explicit GlobalDeclID(DeclID ID) : ID(ID) {}
-
- DeclID get() const { return ID; }
-
- explicit operator DeclID() const { return ID; }
-
- friend bool operator==(const GlobalDeclID &LHS, const GlobalDeclID &RHS) {
- return LHS.ID == RHS.ID;
- }
- friend bool operator!=(const GlobalDeclID &LHS, const GlobalDeclID &RHS) {
- return LHS.ID != RHS.ID;
- }
- // We may sort the global decl ID.
- friend bool operator<(const GlobalDeclID &LHS, const GlobalDeclID &RHS) {
- return LHS.ID < RHS.ID;
- }
- friend bool operator>(const GlobalDeclID &LHS, const GlobalDeclID &RHS) {
- return LHS.ID > RHS.ID;
- }
- friend bool operator<=(const GlobalDeclID &LHS, const GlobalDeclID &RHS) {
- return LHS.ID <= RHS.ID;
- }
- friend bool operator>=(const GlobalDeclID &LHS, const GlobalDeclID &RHS) {
- return LHS.ID >= RHS.ID;
- }
-
-private:
- DeclID ID;
-};
-
-/// A helper iterator adaptor to convert the iterators to `SmallVector<DeclID>`
-/// to the iterators to `SmallVector<GlobalDeclID>`.
-class GlobalDeclIDIterator
- : public llvm::iterator_adaptor_base<GlobalDeclIDIterator, const DeclID *,
- std::forward_iterator_tag,
- GlobalDeclID> {
-public:
- GlobalDeclIDIterator() : iterator_adaptor_base(nullptr) {}
-
- GlobalDeclIDIterator(const DeclID *ID) : iterator_adaptor_base(ID) {}
-
- value_type operator*() const { return GlobalDeclID(*I); }
-
- bool operator==(const GlobalDeclIDIterator &RHS) const { return I == RHS.I; }
-};
-
-/// A helper iterator adaptor to convert the iterators to
-/// `SmallVector<GlobalDeclID>` to the iterators to `SmallVector<DeclID>`.
-class DeclIDIterator
- : public llvm::iterator_adaptor_base<DeclIDIterator, const GlobalDeclID *,
- std::forward_iterator_tag, DeclID> {
-public:
- DeclIDIterator() : iterator_adaptor_base(nullptr) {}
-
- DeclIDIterator(const GlobalDeclID *ID) : iterator_adaptor_base(ID) {}
-
- value_type operator*() const { return DeclID(*I); }
-
- bool operator==(const DeclIDIterator &RHS) const { return I == RHS.I; }
-};
/// An ID number that refers to a type in an AST file. /// An ID number that refers to a type in an AST file.
/// ///
@@ -1054,8 +973,8 @@ enum PredefinedTypeIDs {
/// OpenCL reserve_id type. /// OpenCL reserve_id type.
PREDEF_TYPE_RESERVE_ID_ID = 41, PREDEF_TYPE_RESERVE_ID_ID = 41,
- /// The placeholder type for OpenMP array section.+ /// The placeholder type for an array section.
- PREDEF_TYPE_OMP_ARRAY_SECTION = 42,+ PREDEF_TYPE_ARRAY_SECTION = 42,
/// The '__float128' type /// The '__float128' type
PREDEF_TYPE_FLOAT128_ID = 43, PREDEF_TYPE_FLOAT128_ID = 43,
@@ -1238,74 +1157,6 @@ enum SpecialTypeIDs {
/// The number of special type IDs. /// The number of special type IDs.
const unsigned NumSpecialTypeIDs = 8; const unsigned NumSpecialTypeIDs = 8;
-/// Predefined declaration IDs.
-///
-/// These declaration IDs correspond to predefined declarations in the AST
-/// context, such as the NULL declaration ID. Such declarations are never
-/// actually serialized, since they will be built by the AST context when
-/// it is created.
-enum PredefinedDeclIDs {
- /// The NULL declaration.
- PREDEF_DECL_NULL_ID = 0,
-
- /// The translation unit.
- PREDEF_DECL_TRANSLATION_UNIT_ID = 1,
-
- /// The Objective-C 'id' type.
- PREDEF_DECL_OBJC_ID_ID = 2,
-
- /// The Objective-C 'SEL' type.
- PREDEF_DECL_OBJC_SEL_ID = 3,
-
- /// The Objective-C 'Class' type.
- PREDEF_DECL_OBJC_CLASS_ID = 4,
-
- /// The Objective-C 'Protocol' type.
- PREDEF_DECL_OBJC_PROTOCOL_ID = 5,
-
- /// The signed 128-bit integer type.
- PREDEF_DECL_INT_128_ID = 6,
-
- /// The unsigned 128-bit integer type.
- PREDEF_DECL_UNSIGNED_INT_128_ID = 7,
-
- /// The internal 'instancetype' typedef.
- PREDEF_DECL_OBJC_INSTANCETYPE_ID = 8,
-
- /// The internal '__builtin_va_list' typedef.
- PREDEF_DECL_BUILTIN_VA_LIST_ID = 9,
-
- /// The internal '__va_list_tag' struct, if any.
- PREDEF_DECL_VA_LIST_TAG = 10,
-
- /// The internal '__builtin_ms_va_list' typedef.
- PREDEF_DECL_BUILTIN_MS_VA_LIST_ID = 11,
-
- /// The predeclared '_GUID' struct.
- PREDEF_DECL_BUILTIN_MS_GUID_ID = 12,
-
- /// The extern "C" context.
- PREDEF_DECL_EXTERN_C_CONTEXT_ID = 13,
-
- /// The internal '__make_integer_seq' template.
- PREDEF_DECL_MAKE_INTEGER_SEQ_ID = 14,
-
- /// The internal '__NSConstantString' typedef.
- PREDEF_DECL_CF_CONSTANT_STRING_ID = 15,
-
- /// The internal '__NSConstantString' tag type.
- PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID = 16,
-
- /// The internal '__type_pack_element' template.
- PREDEF_DECL_TYPE_PACK_ELEMENT_ID = 17,
-};
-
-/// The number of declaration IDs that are predefined.
-///
-/// For more information about predefined declarations, see the
-/// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants.
-const unsigned int NUM_PREDEF_DECL_IDS = 18;
-
/// Record of updates for a declaration that was modified after /// Record of updates for a declaration that was modified after
/// being deserialized. This can occur within DECLTYPES_BLOCK_ID. /// being deserialized. This can occur within DECLTYPES_BLOCK_ID.
const unsigned int DECL_UPDATES = 49; const unsigned int DECL_UPDATES = 49;
@@ -2075,7 +1926,7 @@ enum StmtCode {
STMT_OMP_TARGET_TEAMS_GENERIC_LOOP_DIRECTIVE, STMT_OMP_TARGET_TEAMS_GENERIC_LOOP_DIRECTIVE,
STMT_OMP_PARALLEL_GENERIC_LOOP_DIRECTIVE, STMT_OMP_PARALLEL_GENERIC_LOOP_DIRECTIVE,
STMT_OMP_TARGET_PARALLEL_GENERIC_LOOP_DIRECTIVE, STMT_OMP_TARGET_PARALLEL_GENERIC_LOOP_DIRECTIVE,
- EXPR_OMP_ARRAY_SECTION,+ EXPR_ARRAY_SECTION,
EXPR_OMP_ARRAY_SHAPING, EXPR_OMP_ARRAY_SHAPING,
EXPR_OMP_ITERATOR, EXPR_OMP_ITERATOR,
@@ -2132,7 +1983,7 @@ enum CleanupObjectKind { COK_Block, COK_CompoundLiteral };
/// Describes the categories of an Objective-C class. /// Describes the categories of an Objective-C class.
struct ObjCCategoriesInfo { struct ObjCCategoriesInfo {
// The ID of the definition // The ID of the definition
- DeclID DefinitionID;+ LocalDeclID DefinitionID;
// Offset into the array of category lists. // Offset into the array of category lists.
unsigned Offset; unsigned Offset;
@@ -2231,27 +2082,6 @@ template <> struct DenseMapInfo<clang::serialization::DeclarationNameKey> {
} }
}; };
-template <> struct DenseMapInfo<clang::serialization::GlobalDeclID> {
- using DeclID = clang::serialization::DeclID;
- using GlobalDeclID = clang::serialization::GlobalDeclID;
-
- static GlobalDeclID getEmptyKey() {
- return GlobalDeclID(DenseMapInfo<DeclID>::getEmptyKey());
- }
-
- static GlobalDeclID getTombstoneKey() {
- return GlobalDeclID(DenseMapInfo<DeclID>::getTombstoneKey());
- }
-
- static unsigned getHashValue(const GlobalDeclID &Key) {
- return DenseMapInfo<DeclID>::getHashValue(Key.get());
- }
-
- static bool isEqual(const GlobalDeclID &L, const GlobalDeclID &R) {
- return L == R;
- }
-};
-
} // namespace llvm } // namespace llvm
#endif // LLVM_CLANG_SERIALIZATION_ASTBITCODES_H #endif // LLVM_CLANG_SERIALIZATION_ASTBITCODES_H
clang/include/clang/Serialization/ASTDeserializationListener.h
@@ -44,7 +44,7 @@ public:
/// unqualified. /// unqualified.
virtual void TypeRead(serialization::TypeIdx Idx, QualType T) { } virtual void TypeRead(serialization::TypeIdx Idx, QualType T) { }
/// A decl was deserialized from the AST file. /// A decl was deserialized from the AST file.
- virtual void DeclRead(serialization::DeclID ID, const Decl *D) { }+ virtual void DeclRead(GlobalDeclID ID, const Decl *D) {}
/// A selector was read from the AST file. /// A selector was read from the AST file.
virtual void SelectorRead(serialization::SelectorID iD, Selector Sel) {} virtual void SelectorRead(serialization::SelectorID iD, Selector Sel) {}
/// A macro definition was read from the AST file. /// A macro definition was read from the AST file.
clang/include/clang/Serialization/ASTReader.h
@@ -501,10 +501,7 @@ private:
/// = I + 1 has already been loaded. /// = I + 1 has already been loaded.
llvm::PagedVector<Decl *> DeclsLoaded; llvm::PagedVector<Decl *> DeclsLoaded;
- static_assert(std::is_same_v<serialization::DeclID, Decl::DeclID>);+ using GlobalDeclMapType = ContinuousRangeMap<GlobalDeclID, ModuleFile *, 4>;
-
- using GlobalDeclMapType =
- ContinuousRangeMap<serialization::GlobalDeclID, ModuleFile *, 4>;
/// Mapping from global declaration IDs to the module in which the /// Mapping from global declaration IDs to the module in which the
/// declaration resides. /// declaration resides.
@@ -512,16 +509,15 @@ private:
using FileOffset = std::pair<ModuleFile *, uint64_t>; using FileOffset = std::pair<ModuleFile *, uint64_t>;
using FileOffsetsTy = SmallVector<FileOffset, 2>; using FileOffsetsTy = SmallVector<FileOffset, 2>;
- using DeclUpdateOffsetsMap =+ using DeclUpdateOffsetsMap = llvm::DenseMap<GlobalDeclID, FileOffsetsTy>;
- llvm::DenseMap<serialization::GlobalDeclID, FileOffsetsTy>;
/// Declarations that have modifications residing in a later file /// Declarations that have modifications residing in a later file
/// in the chain. /// in the chain.
DeclUpdateOffsetsMap DeclUpdateOffsets; DeclUpdateOffsetsMap DeclUpdateOffsets;
- using DelayedNamespaceOffsetMapTy = llvm::DenseMap<+ using DelayedNamespaceOffsetMapTy =
- serialization::GlobalDeclID,+ llvm::DenseMap<GlobalDeclID, std::pair</*LexicalOffset*/ uint64_t,
- std::pair</*LexicalOffset*/ uint64_t, /*VisibleOffset*/ uint64_t>>;+ /*VisibleOffset*/ uint64_t>>;
/// Mapping from global declaration IDs to the lexical and visible block /// Mapping from global declaration IDs to the lexical and visible block
/// offset for delayed namespace in reduced BMI. /// offset for delayed namespace in reduced BMI.
@@ -535,13 +531,12 @@ private:
struct PendingUpdateRecord { struct PendingUpdateRecord {
Decl *D; Decl *D;
- serialization::GlobalDeclID ID;+ GlobalDeclID ID;
// Whether the declaration was just deserialized. // Whether the declaration was just deserialized.
bool JustLoaded; bool JustLoaded;
- PendingUpdateRecord(serialization::GlobalDeclID ID, Decl *D,+ PendingUpdateRecord(GlobalDeclID ID, Decl *D, bool JustLoaded)
- bool JustLoaded)
: D(D), ID(ID), JustLoaded(JustLoaded) {} : D(D), ID(ID), JustLoaded(JustLoaded) {}
}; };
@@ -594,10 +589,10 @@ private:
struct FileDeclsInfo { struct FileDeclsInfo {
ModuleFile *Mod = nullptr; ModuleFile *Mod = nullptr;
- ArrayRef<serialization::LocalDeclID> Decls;+ ArrayRef<LocalDeclID> Decls;
FileDeclsInfo() = default; FileDeclsInfo() = default;
- FileDeclsInfo(ModuleFile *Mod, ArrayRef<serialization::LocalDeclID> Decls)+ FileDeclsInfo(ModuleFile *Mod, ArrayRef<LocalDeclID> Decls)
: Mod(Mod), Decls(Decls) {} : Mod(Mod), Decls(Decls) {}
}; };
@@ -635,8 +630,7 @@ private:
/// Updates to the visible declarations of declaration contexts that /// Updates to the visible declarations of declaration contexts that
/// haven't been loaded yet. /// haven't been loaded yet.
- llvm::DenseMap<serialization::GlobalDeclID, DeclContextVisibleUpdates>+ llvm::DenseMap<GlobalDeclID, DeclContextVisibleUpdates> PendingVisibleUpdates;
- PendingVisibleUpdates;
/// The set of C++ or Objective-C classes that have forward /// The set of C++ or Objective-C classes that have forward
/// declarations that have not yet been linked to their definitions. /// declarations that have not yet been linked to their definitions.
@@ -662,8 +656,7 @@ private:
/// Read the record that describes the visible contents of a DC. /// Read the record that describes the visible contents of a DC.
bool ReadVisibleDeclContextStorage(ModuleFile &M, bool ReadVisibleDeclContextStorage(ModuleFile &M,
llvm::BitstreamCursor &Cursor, llvm::BitstreamCursor &Cursor,
- uint64_t Offset,+ uint64_t Offset, GlobalDeclID ID);
- serialization::GlobalDeclID ID);
/// A vector containing identifiers that have already been /// A vector containing identifiers that have already been
/// loaded. /// loaded.
@@ -816,14 +809,14 @@ private:
/// This contains the data loaded from all EAGERLY_DESERIALIZED_DECLS blocks /// This contains the data loaded from all EAGERLY_DESERIALIZED_DECLS blocks
/// in the chain. The referenced declarations are deserialized and passed to /// in the chain. The referenced declarations are deserialized and passed to
/// the consumer eagerly. /// the consumer eagerly.
- SmallVector<serialization::GlobalDeclID, 16> EagerlyDeserializedDecls;+ SmallVector<GlobalDeclID, 16> EagerlyDeserializedDecls;
/// The IDs of all tentative definitions stored in the chain. /// The IDs of all tentative definitions stored in the chain.
/// ///
/// Sema keeps track of all tentative definitions in a TU because it has to /// Sema keeps track of all tentative definitions in a TU because it has to
/// complete them and pass them on to CodeGen. Thus, tentative definitions in /// complete them and pass them on to CodeGen. Thus, tentative definitions in
/// the PCH chain must be eagerly deserialized. /// the PCH chain must be eagerly deserialized.
- SmallVector<serialization::GlobalDeclID, 16> TentativeDefinitions;+ SmallVector<GlobalDeclID, 16> TentativeDefinitions;
/// The IDs of all CXXRecordDecls stored in the chain whose VTables are /// The IDs of all CXXRecordDecls stored in the chain whose VTables are
/// used. /// used.
@@ -831,7 +824,7 @@ private:
/// CodeGen has to emit VTables for these records, so they have to be eagerly /// CodeGen has to emit VTables for these records, so they have to be eagerly
/// deserialized. /// deserialized.
struct VTableUse { struct VTableUse {
- serialization::GlobalDeclID ID;+ GlobalDeclID ID;
SourceLocation::UIntTy RawLoc; SourceLocation::UIntTy RawLoc;
bool Used; bool Used;
}; };
@@ -844,7 +837,7 @@ private:
/// instantiation where the first value is the ID of the decl and the second /// instantiation where the first value is the ID of the decl and the second
/// is the instantiation location. /// is the instantiation location.
struct PendingInstantiation { struct PendingInstantiation {
- serialization::GlobalDeclID ID;+ GlobalDeclID ID;
SourceLocation::UIntTy RawLoc; SourceLocation::UIntTy RawLoc;
}; };
SmallVector<PendingInstantiation, 64> PendingInstantiations; SmallVector<PendingInstantiation, 64> PendingInstantiations;
@@ -857,11 +850,11 @@ private:
/// A snapshot of Sema's unused file-scoped variable tracking, for /// A snapshot of Sema's unused file-scoped variable tracking, for
/// generating warnings. /// generating warnings.
- SmallVector<serialization::GlobalDeclID, 16> UnusedFileScopedDecls;+ SmallVector<GlobalDeclID, 16> UnusedFileScopedDecls;
/// A list of all the delegating constructors we've seen, to diagnose /// A list of all the delegating constructors we've seen, to diagnose
/// cycles. /// cycles.
- SmallVector<serialization::GlobalDeclID, 4> DelegatingCtorDecls;+ SmallVector<GlobalDeclID, 4> DelegatingCtorDecls;
/// Method selectors used in a @selector expression. Used for /// Method selectors used in a @selector expression. Used for
/// implementation of -Wselector. /// implementation of -Wselector.
@@ -874,7 +867,7 @@ private:
/// The IDs of type aliases for ext_vectors that exist in the chain. /// The IDs of type aliases for ext_vectors that exist in the chain.
/// ///
/// Used by Sema for finding sugared names for ext_vectors in diagnostics. /// Used by Sema for finding sugared names for ext_vectors in diagnostics.
- SmallVector<serialization::GlobalDeclID, 4> ExtVectorDecls;+ SmallVector<GlobalDeclID, 4> ExtVectorDecls;
//@} //@}
@@ -885,7 +878,7 @@ private:
/// The IDs of all potentially unused typedef names in the chain. /// The IDs of all potentially unused typedef names in the chain.
/// ///
/// Sema tracks these to emit warnings. /// Sema tracks these to emit warnings.
- SmallVector<serialization::GlobalDeclID, 16> UnusedLocalTypedefNameCandidates;+ SmallVector<GlobalDeclID, 16> UnusedLocalTypedefNameCandidates;
/// Our current depth in #pragma cuda force_host_device begin/end /// Our current depth in #pragma cuda force_host_device begin/end
/// macros. /// macros.
@@ -894,7 +887,7 @@ private:
/// The IDs of the declarations Sema stores directly. /// The IDs of the declarations Sema stores directly.
/// ///
/// Sema tracks a few important decls, such as namespace std, directly. /// Sema tracks a few important decls, such as namespace std, directly.
- SmallVector<serialization::GlobalDeclID, 4> SemaDeclRefs;+ SmallVector<GlobalDeclID, 4> SemaDeclRefs;
/// The IDs of the types ASTContext stores directly. /// The IDs of the types ASTContext stores directly.
/// ///
@@ -905,7 +898,7 @@ private:
/// ///
/// The AST context tracks a few important decls, currently cudaConfigureCall, /// The AST context tracks a few important decls, currently cudaConfigureCall,
/// directly. /// directly.
- SmallVector<serialization::GlobalDeclID, 2> CUDASpecialDeclRefs;+ SmallVector<GlobalDeclID, 2> CUDASpecialDeclRefs;
/// The floating point pragma option settings. /// The floating point pragma option settings.
SmallVector<uint64_t, 1> FPPragmaOptions; SmallVector<uint64_t, 1> FPPragmaOptions;
@@ -954,12 +947,12 @@ private:
llvm::DenseMap<const Decl *, std::set<std::string>> OpenCLDeclExtMap; llvm::DenseMap<const Decl *, std::set<std::string>> OpenCLDeclExtMap;
/// A list of the namespaces we've seen. /// A list of the namespaces we've seen.
- SmallVector<serialization::GlobalDeclID, 4> KnownNamespaces;+ SmallVector<GlobalDeclID, 4> KnownNamespaces;
/// A list of undefined decls with internal linkage followed by the /// A list of undefined decls with internal linkage followed by the
/// SourceLocation of a matching ODR-use. /// SourceLocation of a matching ODR-use.
struct UndefinedButUsedDecl { struct UndefinedButUsedDecl {
- serialization::GlobalDeclID ID;+ GlobalDeclID ID;
SourceLocation::UIntTy RawLoc; SourceLocation::UIntTy RawLoc;
}; };
SmallVector<UndefinedButUsedDecl, 8> UndefinedButUsed; SmallVector<UndefinedButUsedDecl, 8> UndefinedButUsed;
@@ -974,8 +967,7 @@ private:
/// The IDs of all decls to be checked for deferred diags. /// The IDs of all decls to be checked for deferred diags.
/// ///
/// Sema tracks these to emit deferred diags. /// Sema tracks these to emit deferred diags.
- llvm::SmallSetVector<serialization::GlobalDeclID, 4>+ llvm::SmallSetVector<GlobalDeclID, 4> DeclsToCheckForDeferredDiags;
- DeclsToCheckForDeferredDiags;
private: private:
struct ImportedSubmodule { struct ImportedSubmodule {
@@ -1112,7 +1104,7 @@ private:
/// ///
/// The declarations on the identifier chain for these identifiers will be /// The declarations on the identifier chain for these identifiers will be
/// loaded once the recursive loading has completed. /// loaded once the recursive loading has completed.
- llvm::MapVector<IdentifierInfo *, SmallVector<serialization::GlobalDeclID, 4>>+ llvm::MapVector<IdentifierInfo *, SmallVector<GlobalDeclID, 4>>
PendingIdentifierInfos; PendingIdentifierInfos;
/// The set of lookup results that we have faked in order to support /// The set of lookup results that we have faked in order to support
@@ -1157,8 +1149,8 @@ private:
/// been loaded but its DeclContext was not set yet. /// been loaded but its DeclContext was not set yet.
struct PendingDeclContextInfo { struct PendingDeclContextInfo {
Decl *D; Decl *D;
- serialization::GlobalDeclID SemaDC;+ GlobalDeclID SemaDC;
- serialization::GlobalDeclID LexicalDC;+ GlobalDeclID LexicalDC;
}; };
/// The set of Decls that have been loaded but their DeclContexts are /// The set of Decls that have been loaded but their DeclContexts are
@@ -1239,8 +1231,7 @@ private:
/// module is loaded. /// module is loaded.
SmallVector<ObjCInterfaceDecl *, 16> ObjCClassesLoaded; SmallVector<ObjCInterfaceDecl *, 16> ObjCClassesLoaded;
- using KeyDeclsMap =+ using KeyDeclsMap = llvm::DenseMap<Decl *, SmallVector<GlobalDeclID, 2>>;
- llvm::DenseMap<Decl *, SmallVector<serialization::GlobalDeclID, 2>>;
/// A mapping from canonical declarations to the set of global /// A mapping from canonical declarations to the set of global
/// declaration IDs for key declaration that have been merged with that /// declaration IDs for key declaration that have been merged with that
@@ -1449,7 +1440,7 @@ private:
QualType readTypeRecord(unsigned Index); QualType readTypeRecord(unsigned Index);
RecordLocation TypeCursorForIndex(unsigned Index); RecordLocation TypeCursorForIndex(unsigned Index);
void LoadedDecl(unsigned Index, Decl *D); void LoadedDecl(unsigned Index, Decl *D);
- Decl *ReadDeclRecord(serialization::GlobalDeclID ID);+ Decl *ReadDeclRecord(GlobalDeclID ID);
void markIncompleteDeclChain(Decl *D); void markIncompleteDeclChain(Decl *D);
/// Returns the most recent declaration of a declaration (which must be /// Returns the most recent declaration of a declaration (which must be
@@ -1457,11 +1448,10 @@ private:
/// merged into its redecl chain. /// merged into its redecl chain.
Decl *getMostRecentExistingDecl(Decl *D); Decl *getMostRecentExistingDecl(Decl *D);
- RecordLocation DeclCursorForID(serialization::GlobalDeclID ID,+ RecordLocation DeclCursorForID(GlobalDeclID ID, SourceLocation &Location);
- SourceLocation &Location);
void loadDeclUpdateRecords(PendingUpdateRecord &Record); void loadDeclUpdateRecords(PendingUpdateRecord &Record);
void loadPendingDeclChain(Decl *D, uint64_t LocalOffset); void loadPendingDeclChain(Decl *D, uint64_t LocalOffset);
- void loadObjCCategories(serialization::GlobalDeclID ID, ObjCInterfaceDecl *D,+ void loadObjCCategories(GlobalDeclID ID, ObjCInterfaceDecl *D,
unsigned PreviousGeneration = 0); unsigned PreviousGeneration = 0);
RecordLocation getLocalBitOffset(uint64_t GlobalOffset); RecordLocation getLocalBitOffset(uint64_t GlobalOffset);
@@ -1496,11 +1486,10 @@ private:
unsigned ClientLoadCapabilities); unsigned ClientLoadCapabilities);
public: public:
- class ModuleDeclIterator+ class ModuleDeclIterator : public llvm::iterator_adaptor_base<
- : public llvm::iterator_adaptor_base<+ ModuleDeclIterator, const LocalDeclID *,
- ModuleDeclIterator, const serialization::LocalDeclID *,+ std::random_access_iterator_tag, const Decl *,
- std::random_access_iterator_tag, const Decl *, ptrdiff_t,+ ptrdiff_t, const Decl *, const Decl *> {
- const Decl *, const Decl *> {
ASTReader *Reader = nullptr; ASTReader *Reader = nullptr;
ModuleFile *Mod = nullptr; ModuleFile *Mod = nullptr;
@@ -1508,7 +1497,7 @@ public:
ModuleDeclIterator() : iterator_adaptor_base(nullptr) {} ModuleDeclIterator() : iterator_adaptor_base(nullptr) {}
ModuleDeclIterator(ASTReader *Reader, ModuleFile *Mod, ModuleDeclIterator(ASTReader *Reader, ModuleFile *Mod,
- const serialization::LocalDeclID *Pos)+ const LocalDeclID *Pos)
: iterator_adaptor_base(Pos), Reader(Reader), Mod(Mod) {} : iterator_adaptor_base(Pos), Reader(Reader), Mod(Mod) {}
value_type operator*() const { value_type operator*() const {
@@ -1536,9 +1525,8 @@ private:
void pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name); void pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name);
- void addPendingDeclContextInfo(Decl *D,+ void addPendingDeclContextInfo(Decl *D, GlobalDeclID SemaDC,
- serialization::GlobalDeclID SemaDC,+ GlobalDeclID LexicalDC) {
- serialization::GlobalDeclID LexicalDC) {
assert(D); assert(D);
PendingDeclContextInfo Info = { D, SemaDC, LexicalDC }; PendingDeclContextInfo Info = { D, SemaDC, LexicalDC };
PendingDeclContextInfos.push_back(Info); PendingDeclContextInfos.push_back(Info);
@@ -1916,38 +1904,36 @@ public:
/// Map from a local declaration ID within a given module to a /// Map from a local declaration ID within a given module to a
/// global declaration ID. /// global declaration ID.
- serialization::GlobalDeclID+ GlobalDeclID getGlobalDeclID(ModuleFile &F, LocalDeclID LocalID) const;
- getGlobalDeclID(ModuleFile &F, serialization::LocalDeclID LocalID) const;
/// Returns true if global DeclID \p ID originated from module \p M. /// Returns true if global DeclID \p ID originated from module \p M.
- bool isDeclIDFromModule(serialization::GlobalDeclID ID, ModuleFile &M) const;+ bool isDeclIDFromModule(GlobalDeclID ID, ModuleFile &M) const;
/// Retrieve the module file that owns the given declaration, or NULL /// Retrieve the module file that owns the given declaration, or NULL
/// if the declaration is not from a module file. /// if the declaration is not from a module file.
ModuleFile *getOwningModuleFile(const Decl *D); ModuleFile *getOwningModuleFile(const Decl *D);
/// Returns the source location for the decl \p ID. /// Returns the source location for the decl \p ID.
- SourceLocation getSourceLocationForDeclID(serialization::GlobalDeclID ID);+ SourceLocation getSourceLocationForDeclID(GlobalDeclID ID);
/// Resolve a declaration ID into a declaration, potentially /// Resolve a declaration ID into a declaration, potentially
/// building a new declaration. /// building a new declaration.
- Decl *GetDecl(serialization::GlobalDeclID ID);+ Decl *GetDecl(GlobalDeclID ID);
- Decl *GetExternalDecl(Decl::DeclID ID) override;+ Decl *GetExternalDecl(GlobalDeclID ID) override;
/// Resolve a declaration ID into a declaration. Return 0 if it's not /// Resolve a declaration ID into a declaration. Return 0 if it's not
/// been loaded yet. /// been loaded yet.
- Decl *GetExistingDecl(serialization::GlobalDeclID ID);+ Decl *GetExistingDecl(GlobalDeclID ID);
/// Reads a declaration with the given local ID in the given module. /// Reads a declaration with the given local ID in the given module.
- Decl *GetLocalDecl(ModuleFile &F, serialization::LocalDeclID LocalID) {+ Decl *GetLocalDecl(ModuleFile &F, LocalDeclID LocalID) {
return GetDecl(getGlobalDeclID(F, LocalID)); return GetDecl(getGlobalDeclID(F, LocalID));
} }
/// Reads a declaration with the given local ID in the given module. /// Reads a declaration with the given local ID in the given module.
/// ///
/// \returns The requested declaration, casted to the given return type. /// \returns The requested declaration, casted to the given return type.
- template <typename T>+ template <typename T> T *GetLocalDeclAs(ModuleFile &F, LocalDeclID LocalID) {
- T *GetLocalDeclAs(ModuleFile &F, serialization::LocalDeclID LocalID) {
return cast_or_null<T>(GetLocalDecl(F, LocalID)); return cast_or_null<T>(GetLocalDecl(F, LocalID));
} }
@@ -1956,16 +1942,15 @@ public:
/// ///
/// \returns the global ID of the given declaration as known in the given /// \returns the global ID of the given declaration as known in the given
/// module file. /// module file.
- serialization::DeclID+ LocalDeclID mapGlobalIDToModuleFileGlobalID(ModuleFile &M,
- mapGlobalIDToModuleFileGlobalID(ModuleFile &M,+ GlobalDeclID GlobalID);
- serialization::GlobalDeclID GlobalID);
/// Reads a declaration ID from the given position in a record in the /// Reads a declaration ID from the given position in a record in the
/// given module. /// given module.
/// ///
/// \returns The declaration ID read from the record, adjusted to a global ID. /// \returns The declaration ID read from the record, adjusted to a global ID.
- serialization::GlobalDeclID+ GlobalDeclID ReadDeclID(ModuleFile &F, const RecordData &Record,
- ReadDeclID(ModuleFile &F, const RecordData &Record, unsigned &Idx);+ unsigned &Idx);
/// Reads a declaration from the given position in a record in the /// Reads a declaration from the given position in a record in the
/// given module. /// given module.
@@ -2139,10 +2124,9 @@ public:
void LoadSelector(Selector Sel); void LoadSelector(Selector Sel);
void SetIdentifierInfo(unsigned ID, IdentifierInfo *II); void SetIdentifierInfo(unsigned ID, IdentifierInfo *II);
- void SetGloballyVisibleDecls(+ void SetGloballyVisibleDecls(IdentifierInfo *II,
- IdentifierInfo *II,+ const SmallVectorImpl<GlobalDeclID> &DeclIDs,
- const SmallVectorImpl<serialization::GlobalDeclID> &DeclIDs,+ SmallVectorImpl<Decl *> *Decls = nullptr);
- SmallVectorImpl<Decl *> *Decls = nullptr);
/// Report a diagnostic. /// Report a diagnostic.
DiagnosticBuilder Diag(unsigned DiagID) const; DiagnosticBuilder Diag(unsigned DiagID) const;
@@ -2383,7 +2367,7 @@ public:
// Contains the IDs for declarations that were requested before we have // Contains the IDs for declarations that were requested before we have
// access to a Sema object. // access to a Sema object.
- SmallVector<serialization::GlobalDeclID, 16> PreloadedDeclIDs;+ SmallVector<GlobalDeclID, 16> PreloadedDeclIDs;
/// Retrieve the semantic analysis object used to analyze the /// Retrieve the semantic analysis object used to analyze the
/// translation unit in which the precompiled header is being /// translation unit in which the precompiled header is being
clang/include/clang/Serialization/ASTRecordReader.h
@@ -136,7 +136,7 @@ public:
/// Reads a declaration with the given local ID in the given module. /// Reads a declaration with the given local ID in the given module.
/// ///
/// \returns The requested declaration, casted to the given return type. /// \returns The requested declaration, casted to the given return type.
- template <typename T> T *GetLocalDeclAs(serialization::LocalDeclID LocalID) {+ template <typename T> T *GetLocalDeclAs(LocalDeclID LocalID) {
return cast_or_null<T>(Reader->GetLocalDecl(*F, LocalID)); return cast_or_null<T>(Reader->GetLocalDecl(*F, LocalID));
} }
@@ -182,9 +182,7 @@ public:
/// Reads a declaration ID from the given position in this record. /// Reads a declaration ID from the given position in this record.
/// ///
/// \returns The declaration ID read from the record, adjusted to a global ID. /// \returns The declaration ID read from the record, adjusted to a global ID.
- serialization::GlobalDeclID readDeclID() {+ GlobalDeclID readDeclID() { return Reader->ReadDeclID(*F, Record, Idx); }
- return Reader->ReadDeclID(*F, Record, Idx);
- }
/// Reads a declaration from the given position in a record in the /// Reads a declaration from the given position in a record in the
/// given module, advancing Idx. /// given module, advancing Idx.
@@ -271,6 +269,9 @@ public:
/// Read an OpenMP children, advancing Idx. /// Read an OpenMP children, advancing Idx.
void readOMPChildren(OMPChildren *Data); void readOMPChildren(OMPChildren *Data);
+ /// Read a list of Exprs used for a var-list.
+ llvm::SmallVector<Expr *> readOpenACCVarList();
+
/// Read an OpenACC clause, advancing Idx. /// Read an OpenACC clause, advancing Idx.
OpenACCClause *readOpenACCClause(); OpenACCClause *readOpenACCClause();
clang/include/clang/Serialization/ASTRecordWriter.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_SERIALIZATION_ASTRECORDWRITER_H #define LLVM_CLANG_SERIALIZATION_ASTRECORDWRITER_H
#include "clang/AST/AbstractBasicWriter.h" #include "clang/AST/AbstractBasicWriter.h"
+#include "clang/AST/OpenACCClause.h"
#include "clang/AST/OpenMPClause.h" #include "clang/AST/OpenMPClause.h"
#include "clang/Serialization/ASTWriter.h" #include "clang/Serialization/ASTWriter.h"
#include "clang/Serialization/SourceLocationEncoding.h" #include "clang/Serialization/SourceLocationEncoding.h"
@@ -293,6 +294,8 @@ public:
/// Writes data related to the OpenMP directives. /// Writes data related to the OpenMP directives.
void writeOMPChildren(OMPChildren *Data); void writeOMPChildren(OMPChildren *Data);
+ void writeOpenACCVarList(const OpenACCClauseWithVarList *C);
+
/// Writes out a single OpenACC Clause. /// Writes out a single OpenACC Clause.
void writeOpenACCClause(const OpenACCClause *C); void writeOpenACCClause(const OpenACCClause *C);
clang/include/clang/Serialization/ASTWriter.h
@@ -76,6 +76,10 @@ class StoredDeclsList;
class SwitchCase; class SwitchCase;
class Token; class Token;
+namespace SrcMgr {
+class FileInfo;
+} // namespace SrcMgr
+
/// Writes an AST file containing the contents of a translation unit. /// Writes an AST file containing the contents of a translation unit.
/// ///
/// The ASTWriter class produces a bitstream containing the serialized /// The ASTWriter class produces a bitstream containing the serialized
@@ -212,10 +216,10 @@ private:
llvm::SmallVector<NamespaceDecl *, 16> DelayedNamespace; llvm::SmallVector<NamespaceDecl *, 16> DelayedNamespace;
/// The first ID number we can use for our own declarations. /// The first ID number we can use for our own declarations.
- serialization::DeclID FirstDeclID = serialization::NUM_PREDEF_DECL_IDS;+ LocalDeclID FirstDeclID = LocalDeclID(clang::NUM_PREDEF_DECL_IDS);
/// The decl ID that will be assigned to the next new decl. /// The decl ID that will be assigned to the next new decl.
- serialization::DeclID NextDeclID = FirstDeclID;+ LocalDeclID NextDeclID = FirstDeclID;
/// Map that provides the ID numbers of each declaration within /// Map that provides the ID numbers of each declaration within
/// the output stream, as well as those deserialized from a chained PCH. /// the output stream, as well as those deserialized from a chained PCH.
@@ -223,7 +227,7 @@ private:
/// The ID numbers of declarations are consecutive (in order of /// The ID numbers of declarations are consecutive (in order of
/// discovery) and start at 2. 1 is reserved for the translation /// discovery) and start at 2. 1 is reserved for the translation
/// unit, while 0 is reserved for NULL. /// unit, while 0 is reserved for NULL.
- llvm::DenseMap<const Decl *, serialization::DeclID> DeclIDs;+ llvm::DenseMap<const Decl *, LocalDeclID> DeclIDs;
/// Offset of each declaration in the bitstream, indexed by /// Offset of each declaration in the bitstream, indexed by
/// the declaration's ID. /// the declaration's ID.
@@ -233,9 +237,8 @@ private:
/// are relative to this value. /// are relative to this value.
uint64_t DeclTypesBlockStartOffset = 0; uint64_t DeclTypesBlockStartOffset = 0;
- /// Sorted (by file offset) vector of pairs of file offset/DeclID.+ /// Sorted (by file offset) vector of pairs of file offset/LocalDeclID.
- using LocDeclIDsTy =+ using LocDeclIDsTy = SmallVector<std::pair<unsigned, LocalDeclID>, 64>;
- SmallVector<std::pair<unsigned, serialization::DeclID>, 64>;
struct DeclIDInFileInfo { struct DeclIDInFileInfo {
LocDeclIDsTy DeclIDs; LocDeclIDsTy DeclIDs;
@@ -250,7 +253,7 @@ private:
/// that it contains. /// that it contains.
FileDeclIDsTy FileDeclIDs; FileDeclIDsTy FileDeclIDs;
- void associateDeclWithFile(const Decl *D, serialization::DeclID);+ void associateDeclWithFile(const Decl *D, LocalDeclID);
/// The first ID number we can use for our own types. /// The first ID number we can use for our own types.
serialization::TypeID FirstTypeID = serialization::NUM_PREDEF_TYPE_IDS; serialization::TypeID FirstTypeID = serialization::NUM_PREDEF_TYPE_IDS;
@@ -421,8 +424,8 @@ private:
/// headers. The declarations themselves are stored as declaration /// headers. The declarations themselves are stored as declaration
/// IDs, since they will be written out to an EAGERLY_DESERIALIZED_DECLS /// IDs, since they will be written out to an EAGERLY_DESERIALIZED_DECLS
/// record. /// record.
- SmallVector<serialization::DeclID, 16> EagerlyDeserializedDecls;+ RecordData EagerlyDeserializedDecls;
- SmallVector<serialization::DeclID, 16> ModularCodegenDecls;+ RecordData ModularCodegenDecls;
/// DeclContexts that have received extensions since their serialized /// DeclContexts that have received extensions since their serialized
/// form. /// form.
@@ -491,6 +494,11 @@ private:
/// during \c SourceManager serialization. /// during \c SourceManager serialization.
void computeNonAffectingInputFiles(); void computeNonAffectingInputFiles();
+ /// Some affecting files can be included from files that are not affecting.
+ /// This function erases source locations pointing into such files.
+ SourceLocation getAffectingIncludeLoc(const SourceManager &SourceMgr,
+ const SrcMgr::FileInfo &File);
+
/// Returns an adjusted \c FileID, accounting for any non-affecting input /// Returns an adjusted \c FileID, accounting for any non-affecting input
/// files. /// files.
FileID getAdjustedFileID(FileID FID) const; FileID getAdjustedFileID(FileID FID) const;
@@ -526,6 +534,7 @@ private:
/// Calculate hash of the pcm content. /// Calculate hash of the pcm content.
std::pair<ASTFileSignature, ASTFileSignature> createSignature() const; std::pair<ASTFileSignature, ASTFileSignature> createSignature() const;
+ ASTFileSignature createSignatureForNamedModule() const;
void WriteInputFiles(SourceManager &SourceMgr, HeaderSearchOptions &HSOpts); void WriteInputFiles(SourceManager &SourceMgr, HeaderSearchOptions &HSOpts);
void WriteSourceManagerBlock(SourceManager &SourceMgr, void WriteSourceManagerBlock(SourceManager &SourceMgr,
@@ -709,7 +718,7 @@ public:
return false; return false;
auto I = DeclIDs.find(D); auto I = DeclIDs.find(D);
return (I == DeclIDs.end() || return (I == DeclIDs.end() ||
- I->second >= serialization::NUM_PREDEF_DECL_IDS);+ I->second.get() >= clang::NUM_PREDEF_DECL_IDS);
}; };
/// Emit a reference to a declaration. /// Emit a reference to a declaration.
@@ -717,12 +726,13 @@ public:
// Emit a reference to a declaration if the declaration was emitted. // Emit a reference to a declaration if the declaration was emitted.
void AddEmittedDeclRef(const Decl *D, RecordDataImpl &Record); void AddEmittedDeclRef(const Decl *D, RecordDataImpl &Record);
- /// Force a declaration to be emitted and get its ID.+ /// Force a declaration to be emitted and get its local ID to the module file
- serialization::DeclID GetDeclRef(const Decl *D);+ /// been writing.
+ LocalDeclID GetDeclRef(const Decl *D);
- /// Determine the declaration ID of an already-emitted+ /// Determine the local declaration ID of an already-emitted
/// declaration. /// declaration.
- serialization::DeclID getDeclID(const Decl *D);+ LocalDeclID getDeclID(const Decl *D);
/// Whether or not the declaration got emitted. If not, it wouldn't be /// Whether or not the declaration got emitted. If not, it wouldn't be
/// emitted. /// emitted.
@@ -885,6 +895,8 @@ private:
/// AST and semantic-analysis consumer that generates a /// AST and semantic-analysis consumer that generates a
/// precompiled header from the parsed source code. /// precompiled header from the parsed source code.
class PCHGenerator : public SemaConsumer { class PCHGenerator : public SemaConsumer {
+ void anchor() override;
+
Preprocessor &PP; Preprocessor &PP;
std::string OutputFile; std::string OutputFile;
std::string isysroot; std::string isysroot;
@@ -928,17 +940,34 @@ public:
bool hasEmittedPCH() const { return Buffer->IsComplete; } bool hasEmittedPCH() const { return Buffer->IsComplete; }
}; };
-class ReducedBMIGenerator : public PCHGenerator {+class CXX20ModulesGenerator : public PCHGenerator {
+ void anchor() override;
+
protected: protected:
virtual Module *getEmittingModule(ASTContext &Ctx) override; virtual Module *getEmittingModule(ASTContext &Ctx) override;
+ CXX20ModulesGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache,
+ StringRef OutputFile, bool GeneratingReducedBMI);
+
public: public:
- ReducedBMIGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache,+ CXX20ModulesGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache,
- StringRef OutputFile);+ StringRef OutputFile)
+ : CXX20ModulesGenerator(PP, ModuleCache, OutputFile,
+ /*GeneratingReducedBMI=*/false) {}
void HandleTranslationUnit(ASTContext &Ctx) override; void HandleTranslationUnit(ASTContext &Ctx) override;
}; };
+class ReducedBMIGenerator : public CXX20ModulesGenerator {
+ void anchor() override;
+
+public:
+ ReducedBMIGenerator(Preprocessor &PP, InMemoryModuleCache &ModuleCache,
+ StringRef OutputFile)
+ : CXX20ModulesGenerator(PP, ModuleCache, OutputFile,
+ /*GeneratingReducedBMI=*/true) {}
+};
+
/// If we can elide the definition of \param D in reduced BMI. /// If we can elide the definition of \param D in reduced BMI.
/// ///
/// Generally, we can elide the definition of a declaration if it won't affect /// Generally, we can elide the definition of a declaration if it won't affect
clang/include/clang/Serialization/ModuleFile.h
@@ -474,7 +474,7 @@ public:
llvm::DenseMap<ModuleFile *, serialization::DeclID> GlobalToLocalDeclIDs; llvm::DenseMap<ModuleFile *, serialization::DeclID> GlobalToLocalDeclIDs;
/// Array of file-level DeclIDs sorted by file. /// Array of file-level DeclIDs sorted by file.
- const serialization::LocalDeclID *FileSortedDecls = nullptr;+ const LocalDeclID *FileSortedDecls = nullptr;
unsigned NumFileSortedDecls = 0; unsigned NumFileSortedDecls = 0;
/// Array of category list location information within this /// Array of category list location information within this
clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -563,6 +563,20 @@ def MismatchedDeallocatorChecker : Checker<"MismatchedDeallocator">,
Dependencies<[DynamicMemoryModeling]>, Dependencies<[DynamicMemoryModeling]>,
Documentation<HasDocumentation>; Documentation<HasDocumentation>;
+// This must appear before StdCLibraryFunctionsChecker because a dependency.
+def StreamChecker : Checker<"Stream">,
+ HelpText<"Check stream handling functions">,
+ WeakDependencies<[NonNullParamChecker]>,
+ CheckerOptions<[
+ CmdLineOption<Boolean,
+ "Pedantic",
+ "If false, assume that stream operations which are often not "
+ "checked for error do not fail.",
+ "false",
+ InAlpha>
+ ]>,
+ Documentation<HasDocumentation>;
+
def StdCLibraryFunctionsChecker : Checker<"StdCLibraryFunctions">, def StdCLibraryFunctionsChecker : Checker<"StdCLibraryFunctions">,
HelpText<"Check for invalid arguments of C standard library functions, " HelpText<"Check for invalid arguments of C standard library functions, "
"and apply relations between arguments and return value">, "and apply relations between arguments and return value">,
@@ -581,7 +595,7 @@ def StdCLibraryFunctionsChecker : Checker<"StdCLibraryFunctions">,
"true", "true",
InAlpha> InAlpha>
]>, ]>,
- WeakDependencies<[CallAndMessageChecker, NonNullParamChecker]>,+ WeakDependencies<[CallAndMessageChecker, NonNullParamChecker, StreamChecker]>,
Documentation<HasDocumentation>; Documentation<HasDocumentation>;
def VforkChecker : Checker<"Vfork">, def VforkChecker : Checker<"Vfork">,
@@ -601,20 +615,6 @@ def PthreadLockChecker : Checker<"PthreadLock">,
Dependencies<[PthreadLockBase]>, Dependencies<[PthreadLockBase]>,
Documentation<HasDocumentation>; Documentation<HasDocumentation>;
-def StreamChecker : Checker<"Stream">,
- HelpText<"Check stream handling functions">,
- WeakDependencies<[NonNullParamChecker]>,
- CheckerOptions<[
- CmdLineOption<Boolean,
- "Pedantic",
- "If false, assume that stream operations which are often not "
- "checked for error do not fail."
- "fail.",
- "false",
- InAlpha>
- ]>,
- Documentation<HasDocumentation>;
-
def SimpleStreamChecker : Checker<"SimpleStream">, def SimpleStreamChecker : Checker<"SimpleStream">,
HelpText<"Check for misuses of stream APIs">, HelpText<"Check for misuses of stream APIs">,
Documentation<HasDocumentation>; Documentation<HasDocumentation>;
@@ -1628,6 +1628,7 @@ def TaintTesterChecker : Checker<"TaintTest">,
def StreamTesterChecker : Checker<"StreamTester">, def StreamTesterChecker : Checker<"StreamTester">,
HelpText<"Add test functions to StreamChecker for test and debugging " HelpText<"Add test functions to StreamChecker for test and debugging "
"purposes.">, "purposes.">,
+ WeakDependencies<[StreamChecker]>,
Documentation<NotDocumented>; Documentation<NotDocumented>;
def ErrnoTesterChecker : Checker<"ErrnoTest">, def ErrnoTesterChecker : Checker<"ErrnoTest">,
clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -225,15 +225,11 @@ public:
/// invalidated. This should include any regions explicitly invalidated /// invalidated. This should include any regions explicitly invalidated
/// even if they do not currently have bindings. Pass \c NULL if this /// even if they do not currently have bindings. Pass \c NULL if this
/// information will not be used. /// information will not be used.
- virtual StoreRef invalidateRegions(Store store,+ virtual StoreRef invalidateRegions(
- ArrayRef<SVal> Values,+ Store store, ArrayRef<SVal> Values, const Expr *Ex, unsigned Count,
- const Expr *E, unsigned Count,+ const LocationContext *LCtx, const CallEvent *Call,
- const LocationContext *LCtx,+ InvalidatedSymbols &IS, RegionAndSymbolInvalidationTraits &ITraits,
- const CallEvent *Call,+ InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) = 0;
- InvalidatedSymbols &IS,
- RegionAndSymbolInvalidationTraits &ITraits,
- InvalidatedRegions *InvalidatedTopLevel,
- InvalidatedRegions *Invalidated) = 0;
/// enterStackFrame - Let the StoreManager to do something when execution /// enterStackFrame - Let the StoreManager to do something when execution
/// engine is about to execute into a callee. /// engine is about to execute into a callee.
clang/include/clang/Tooling/CommonOptionsParser.h
@@ -49,17 +49,22 @@ namespace tooling {
/// using namespace clang::tooling; /// using namespace clang::tooling;
/// using namespace llvm; /// using namespace llvm;
/// ///
-/// static cl::OptionCategory MyToolCategory("My tool options");+/// static cl::OptionCategory MyToolCategory("my-tool options");
/// static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage); /// static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
/// static cl::extrahelp MoreHelp("\nMore help text...\n"); /// static cl::extrahelp MoreHelp("\nMore help text...\n");
-/// static cl::opt<bool> YourOwnOption(...);
-/// ...
/// ///
/// int main(int argc, const char **argv) { /// int main(int argc, const char **argv) {
-/// CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);+/// auto ExpectedParser =
+/// CommonOptionsParser::create(argc, argv, MyToolCategory);
+/// if (!ExpectedParser) {
+/// llvm::errs() << ExpectedParser.takeError();
+/// return 1;
+/// }
+/// CommonOptionsParser& OptionsParser = ExpectedParser.get();
/// ClangTool Tool(OptionsParser.getCompilations(), /// ClangTool Tool(OptionsParser.getCompilations(),
/// OptionsParser.getSourcePathList()); /// OptionsParser.getSourcePathList());
-/// return Tool.run(newFrontendActionFactory<SyntaxOnlyAction>().get());+/// return Tool.run(
+/// newFrontendActionFactory<clang::SyntaxOnlyAction>().get());
/// } /// }
/// \endcode /// \endcode
class CommonOptionsParser { class CommonOptionsParser {
clang/lib/APINotes/APINotesFormat.h
@@ -24,7 +24,10 @@ const uint16_t VERSION_MAJOR = 0;
/// API notes file minor version number. /// API notes file minor version number.
/// ///
/// When the format changes IN ANY WAY, this number should be incremented. /// When the format changes IN ANY WAY, this number should be incremented.
-const uint16_t VERSION_MINOR = 25; // SwiftImportAs+const uint16_t VERSION_MINOR = 26; // SwiftCopyable
+
+const uint8_t kSwiftCopyable = 1;
+const uint8_t kSwiftNonCopyable = 2;
using IdentifierID = llvm::PointerEmbeddedInt<unsigned, 31>; using IdentifierID = llvm::PointerEmbeddedInt<unsigned, 31>;
using IdentifierIDField = llvm::BCVBR<16>; using IdentifierIDField = llvm::BCVBR<16>;
clang/lib/APINotes/APINotesReader.cpp
@@ -527,6 +527,13 @@ public:
Info.EnumExtensibility = Info.EnumExtensibility =
static_cast<EnumExtensibilityKind>((Payload & 0x3) - 1); static_cast<EnumExtensibilityKind>((Payload & 0x3) - 1);
+ uint8_t Copyable =
+ endian::readNext<uint8_t, llvm::endianness::little>(Data);
+ if (Copyable == kSwiftNonCopyable)
+ Info.setSwiftCopyable(std::optional(false));
+ else if (Copyable == kSwiftCopyable)
+ Info.setSwiftCopyable(std::optional(true));
+
unsigned ImportAsLength = unsigned ImportAsLength =
endian::readNext<uint16_t, llvm::endianness::little>(Data); endian::readNext<uint16_t, llvm::endianness::little>(Data);
if (ImportAsLength > 0) { if (ImportAsLength > 0) {
clang/lib/APINotes/APINotesWriter.cpp
@@ -1128,7 +1128,7 @@ public:
return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) + return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) +
2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) + 2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) +
2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) + 2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) +
- 1 + getCommonTypeInfoSize(TI);+ 2 + getCommonTypeInfoSize(TI);
} }
void emitUnversionedInfo(raw_ostream &OS, const TagInfo &TI) { void emitUnversionedInfo(raw_ostream &OS, const TagInfo &TI) {
@@ -1146,6 +1146,11 @@ public:
writer.write<uint8_t>(Flags); writer.write<uint8_t>(Flags);
+ if (auto Copyable = TI.isSwiftCopyable())
+ writer.write<uint8_t>(*Copyable ? kSwiftCopyable : kSwiftNonCopyable);
+ else
+ writer.write<uint8_t>(0);
+
if (auto ImportAs = TI.SwiftImportAs) { if (auto ImportAs = TI.SwiftImportAs) {
writer.write<uint16_t>(ImportAs->size() + 1); writer.write<uint16_t>(ImportAs->size() + 1);
OS.write(ImportAs->c_str(), ImportAs->size()); OS.write(ImportAs->c_str(), ImportAs->size());
clang/lib/APINotes/APINotesYAMLCompiler.cpp
@@ -419,6 +419,7 @@ struct Tag {
std::optional<EnumExtensibilityKind> EnumExtensibility; std::optional<EnumExtensibilityKind> EnumExtensibility;
std::optional<bool> FlagEnum; std::optional<bool> FlagEnum;
std::optional<EnumConvenienceAliasKind> EnumConvenienceKind; std::optional<EnumConvenienceAliasKind> EnumConvenienceKind;
+ std::optional<bool> SwiftCopyable;
}; };
typedef std::vector<Tag> TagsSeq; typedef std::vector<Tag> TagsSeq;
@@ -452,6 +453,7 @@ template <> struct MappingTraits<Tag> {
IO.mapOptional("EnumExtensibility", T.EnumExtensibility); IO.mapOptional("EnumExtensibility", T.EnumExtensibility);
IO.mapOptional("FlagEnum", T.FlagEnum); IO.mapOptional("FlagEnum", T.FlagEnum);
IO.mapOptional("EnumKind", T.EnumConvenienceKind); IO.mapOptional("EnumKind", T.EnumConvenienceKind);
+ IO.mapOptional("SwiftCopyable", T.SwiftCopyable);
} }
}; };
} // namespace yaml } // namespace yaml
@@ -1009,6 +1011,9 @@ public:
if (Tag.SwiftReleaseOp) if (Tag.SwiftReleaseOp)
TI.SwiftReleaseOp = Tag.SwiftReleaseOp; TI.SwiftReleaseOp = Tag.SwiftReleaseOp;
+ if (Tag.SwiftCopyable)
+ TI.setSwiftCopyable(Tag.SwiftCopyable);
+
if (Tag.EnumConvenienceKind) { if (Tag.EnumConvenienceKind) {
if (Tag.EnumExtensibility) { if (Tag.EnumExtensibility) {
emitError( emitError(
clang/lib/AST/ASTContext.cpp
@@ -1084,7 +1084,7 @@ void ASTContext::addModuleInitializer(Module *M, Decl *D) {
} }
void ASTContext::addLazyModuleInitializers(Module *M, void ASTContext::addLazyModuleInitializers(Module *M,
- ArrayRef<Decl::DeclID> IDs) {+ ArrayRef<GlobalDeclID> IDs) {
auto *&Inits = ModuleInitializers[M]; auto *&Inits = ModuleInitializers[M];
if (!Inits) if (!Inits)
Inits = new (*this) PerModuleInitializers; Inits = new (*this) PerModuleInitializers;
@@ -1321,16 +1321,14 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
// Placeholder type for OMP array sections. // Placeholder type for OMP array sections.
if (LangOpts.OpenMP) { if (LangOpts.OpenMP) {
- InitBuiltinType(OMPArraySectionTy, BuiltinType::OMPArraySection);+ InitBuiltinType(ArraySectionTy, BuiltinType::ArraySection);
InitBuiltinType(OMPArrayShapingTy, BuiltinType::OMPArrayShaping); InitBuiltinType(OMPArrayShapingTy, BuiltinType::OMPArrayShaping);
InitBuiltinType(OMPIteratorTy, BuiltinType::OMPIterator); InitBuiltinType(OMPIteratorTy, BuiltinType::OMPIterator);
} }
- // Placeholder type for OpenACC array sections.+ // Placeholder type for OpenACC array sections, if we are ALSO in OMP mode,
- if (LangOpts.OpenACC) {+ // don't bother, as we're just using the same type as OMP.
- // FIXME: Once we implement OpenACC array sections in Sema, this will either+ if (LangOpts.OpenACC && !LangOpts.OpenMP) {
- // be combined with the OpenMP type, or given its own type. In the meantime,+ InitBuiltinType(ArraySectionTy, BuiltinType::ArraySection);
- // just use the OpenMP type so that parsing can work.
- InitBuiltinType(OMPArraySectionTy, BuiltinType::OMPArraySection);
} }
if (LangOpts.MatrixTypes) if (LangOpts.MatrixTypes)
InitBuiltinType(IncompleteMatrixIdxTy, BuiltinType::IncompleteMatrixIdx); InitBuiltinType(IncompleteMatrixIdxTy, BuiltinType::IncompleteMatrixIdx);
clang/lib/AST/ComputeDependence.cpp
@@ -443,12 +443,17 @@ ExprDependence clang::computeDependence(ObjCIndirectCopyRestoreExpr *E) {
return E->getSubExpr()->getDependence(); return E->getSubExpr()->getDependence();
} }
-ExprDependence clang::computeDependence(OMPArraySectionExpr *E) {+ExprDependence clang::computeDependence(ArraySectionExpr *E) {
auto D = E->getBase()->getDependence(); auto D = E->getBase()->getDependence();
if (auto *LB = E->getLowerBound()) if (auto *LB = E->getLowerBound())
D |= LB->getDependence(); D |= LB->getDependence();
if (auto *Len = E->getLength()) if (auto *Len = E->getLength())
D |= Len->getDependence(); D |= Len->getDependence();
+
+ if (E->isOMPArraySection()) {
+ if (auto *Stride = E->getStride())
+ D |= Stride->getDependence();
+ }
return D; return D;
} }
clang/lib/AST/Decl.cpp
@@ -2151,7 +2151,7 @@ VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartL,
return new (C, DC) VarDecl(Var, C, DC, StartL, IdL, Id, T, TInfo, S); return new (C, DC) VarDecl(Var, C, DC, StartL, IdL, Id, T, TInfo, S);
} }
-VarDecl *VarDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+VarDecl *VarDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) return new (C, ID)
VarDecl(Var, C, nullptr, SourceLocation(), SourceLocation(), nullptr, VarDecl(Var, C, nullptr, SourceLocation(), SourceLocation(), nullptr,
QualType(), nullptr, SC_None); QualType(), nullptr, SC_None);
@@ -2929,7 +2929,7 @@ QualType ParmVarDecl::getOriginalType() const {
return T; return T;
} }
-ParmVarDecl *ParmVarDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+ParmVarDecl *ParmVarDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) return new (C, ID)
ParmVarDecl(ParmVar, C, nullptr, SourceLocation(), SourceLocation(), ParmVarDecl(ParmVar, C, nullptr, SourceLocation(), SourceLocation(),
nullptr, QualType(), nullptr, SC_None, nullptr); nullptr, QualType(), nullptr, SC_None, nullptr);
@@ -4553,7 +4553,7 @@ FieldDecl *FieldDecl::Create(const ASTContext &C, DeclContext *DC,
BW, Mutable, InitStyle); BW, Mutable, InitStyle);
} }
-FieldDecl *FieldDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+FieldDecl *FieldDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) FieldDecl(Field, nullptr, SourceLocation(), return new (C, ID) FieldDecl(Field, nullptr, SourceLocation(),
SourceLocation(), nullptr, QualType(), nullptr, SourceLocation(), nullptr, QualType(), nullptr,
nullptr, false, ICIS_NoInit); nullptr, false, ICIS_NoInit);
@@ -4863,7 +4863,7 @@ EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC,
return Enum; return Enum;
} }
-EnumDecl *EnumDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+EnumDecl *EnumDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
EnumDecl *Enum = EnumDecl *Enum =
new (C, ID) EnumDecl(C, nullptr, SourceLocation(), SourceLocation(), new (C, ID) EnumDecl(C, nullptr, SourceLocation(), SourceLocation(),
nullptr, nullptr, false, false, false); nullptr, nullptr, false, false, false);
@@ -5025,7 +5025,8 @@ RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC,
return R; return R;
} }
-RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, Decl::DeclID ID) {+RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C,
+ GlobalDeclID ID) {
RecordDecl *R = new (C, ID) RecordDecl *R = new (C, ID)
RecordDecl(Record, TagTypeKind::Struct, C, nullptr, SourceLocation(), RecordDecl(Record, TagTypeKind::Struct, C, nullptr, SourceLocation(),
SourceLocation(), nullptr, nullptr); SourceLocation(), nullptr, nullptr);
@@ -5297,7 +5298,7 @@ PragmaCommentDecl *PragmaCommentDecl::Create(const ASTContext &C,
} }
PragmaCommentDecl *PragmaCommentDecl::CreateDeserialized(ASTContext &C, PragmaCommentDecl *PragmaCommentDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID,+ GlobalDeclID ID,
unsigned ArgSize) { unsigned ArgSize) {
return new (C, ID, additionalSizeToAlloc<char>(ArgSize + 1)) return new (C, ID, additionalSizeToAlloc<char>(ArgSize + 1))
PragmaCommentDecl(nullptr, SourceLocation(), PCK_Unknown); PragmaCommentDecl(nullptr, SourceLocation(), PCK_Unknown);
@@ -5322,7 +5323,7 @@ PragmaDetectMismatchDecl::Create(const ASTContext &C, TranslationUnitDecl *DC,
} }
PragmaDetectMismatchDecl * PragmaDetectMismatchDecl *
-PragmaDetectMismatchDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID,+PragmaDetectMismatchDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID,
unsigned NameValueSize) { unsigned NameValueSize) {
return new (C, ID, additionalSizeToAlloc<char>(NameValueSize + 1)) return new (C, ID, additionalSizeToAlloc<char>(NameValueSize + 1))
PragmaDetectMismatchDecl(nullptr, SourceLocation(), 0); PragmaDetectMismatchDecl(nullptr, SourceLocation(), 0);
@@ -5349,7 +5350,7 @@ LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC,
return new (C, DC) LabelDecl(DC, IdentL, II, nullptr, GnuLabelL); return new (C, DC) LabelDecl(DC, IdentL, II, nullptr, GnuLabelL);
} }
-LabelDecl *LabelDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+LabelDecl *LabelDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) LabelDecl(nullptr, SourceLocation(), nullptr, nullptr, return new (C, ID) LabelDecl(nullptr, SourceLocation(), nullptr, nullptr,
SourceLocation()); SourceLocation());
} }
@@ -5390,7 +5391,7 @@ ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, QualType Type,
} }
ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C, ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) ImplicitParamDecl(C, QualType(), ImplicitParamKind::Other); return new (C, ID) ImplicitParamDecl(C, QualType(), ImplicitParamKind::Other);
} }
@@ -5408,7 +5409,7 @@ FunctionDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
return New; return New;
} }
-FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) FunctionDecl( return new (C, ID) FunctionDecl(
Function, C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), Function, C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(),
nullptr, SC_None, false, false, ConstexprSpecKind::Unspecified, nullptr); nullptr, SC_None, false, false, ConstexprSpecKind::Unspecified, nullptr);
@@ -5418,7 +5419,7 @@ BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
return new (C, DC) BlockDecl(DC, L); return new (C, DC) BlockDecl(DC, L);
} }
-BlockDecl *BlockDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+BlockDecl *BlockDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) BlockDecl(nullptr, SourceLocation()); return new (C, ID) BlockDecl(nullptr, SourceLocation());
} }
@@ -5432,7 +5433,7 @@ CapturedDecl *CapturedDecl::Create(ASTContext &C, DeclContext *DC,
CapturedDecl(DC, NumParams); CapturedDecl(DC, NumParams);
} }
-CapturedDecl *CapturedDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID,+CapturedDecl *CapturedDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID,
unsigned NumParams) { unsigned NumParams) {
return new (C, ID, additionalSizeToAlloc<ImplicitParamDecl *>(NumParams)) return new (C, ID, additionalSizeToAlloc<ImplicitParamDecl *>(NumParams))
CapturedDecl(nullptr, NumParams); CapturedDecl(nullptr, NumParams);
@@ -5458,8 +5459,8 @@ EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
return new (C, CD) EnumConstantDecl(C, CD, L, Id, T, E, V); return new (C, CD) EnumConstantDecl(C, CD, L, Id, T, E, V);
} }
-EnumConstantDecl *+EnumConstantDecl *EnumConstantDecl::CreateDeserialized(ASTContext &C,
-EnumConstantDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) EnumConstantDecl(C, nullptr, SourceLocation(), nullptr, return new (C, ID) EnumConstantDecl(C, nullptr, SourceLocation(), nullptr,
QualType(), nullptr, llvm::APSInt()); QualType(), nullptr, llvm::APSInt());
} }
@@ -5486,7 +5487,7 @@ IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
} }
IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C, IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) return new (C, ID)
IndirectFieldDecl(C, nullptr, SourceLocation(), DeclarationName(), IndirectFieldDecl(C, nullptr, SourceLocation(), DeclarationName(),
QualType(), std::nullopt); QualType(), std::nullopt);
@@ -5547,7 +5548,7 @@ bool TypedefNameDecl::isTransparentTagSlow() const {
return isTransparent; return isTransparent;
} }
-TypedefDecl *TypedefDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+TypedefDecl *TypedefDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) TypedefDecl(C, nullptr, SourceLocation(), SourceLocation(), return new (C, ID) TypedefDecl(C, nullptr, SourceLocation(), SourceLocation(),
nullptr, nullptr); nullptr, nullptr);
} }
@@ -5560,7 +5561,8 @@ TypeAliasDecl *TypeAliasDecl::Create(ASTContext &C, DeclContext *DC,
return new (C, DC) TypeAliasDecl(C, DC, StartLoc, IdLoc, Id, TInfo); return new (C, DC) TypeAliasDecl(C, DC, StartLoc, IdLoc, Id, TInfo);
} }
-TypeAliasDecl *TypeAliasDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+TypeAliasDecl *TypeAliasDecl::CreateDeserialized(ASTContext &C,
+ GlobalDeclID ID) {
return new (C, ID) TypeAliasDecl(C, nullptr, SourceLocation(), return new (C, ID) TypeAliasDecl(C, nullptr, SourceLocation(),
SourceLocation(), nullptr, nullptr); SourceLocation(), nullptr, nullptr);
} }
@@ -5591,7 +5593,7 @@ FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC,
} }
FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C, FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) FileScopeAsmDecl(nullptr, nullptr, SourceLocation(), return new (C, ID) FileScopeAsmDecl(nullptr, nullptr, SourceLocation(),
SourceLocation()); SourceLocation());
} }
@@ -5609,7 +5611,7 @@ TopLevelStmtDecl *TopLevelStmtDecl::Create(ASTContext &C, Stmt *Statement) {
} }
TopLevelStmtDecl *TopLevelStmtDecl::CreateDeserialized(ASTContext &C, TopLevelStmtDecl *TopLevelStmtDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) return new (C, ID)
TopLevelStmtDecl(/*DC=*/nullptr, SourceLocation(), /*S=*/nullptr); TopLevelStmtDecl(/*DC=*/nullptr, SourceLocation(), /*S=*/nullptr);
} }
@@ -5630,7 +5632,7 @@ EmptyDecl *EmptyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
return new (C, DC) EmptyDecl(DC, L); return new (C, DC) EmptyDecl(DC, L);
} }
-EmptyDecl *EmptyDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+EmptyDecl *EmptyDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) EmptyDecl(nullptr, SourceLocation()); return new (C, ID) EmptyDecl(nullptr, SourceLocation());
} }
@@ -5663,7 +5665,8 @@ HLSLBufferDecl *HLSLBufferDecl::Create(ASTContext &C,
return Result; return Result;
} }
-HLSLBufferDecl *HLSLBufferDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+HLSLBufferDecl *HLSLBufferDecl::CreateDeserialized(ASTContext &C,
+ GlobalDeclID ID) {
return new (C, ID) HLSLBufferDecl(nullptr, false, SourceLocation(), nullptr, return new (C, ID) HLSLBufferDecl(nullptr, false, SourceLocation(), nullptr,
SourceLocation(), SourceLocation()); SourceLocation(), SourceLocation());
} }
@@ -5719,7 +5722,7 @@ ImportDecl *ImportDecl::CreateImplicit(ASTContext &C, DeclContext *DC,
return Import; return Import;
} }
-ImportDecl *ImportDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID,+ImportDecl *ImportDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID,
unsigned NumLocations) { unsigned NumLocations) {
return new (C, ID, additionalSizeToAlloc<SourceLocation>(NumLocations)) return new (C, ID, additionalSizeToAlloc<SourceLocation>(NumLocations))
ImportDecl(EmptyShell()); ImportDecl(EmptyShell());
@@ -5752,6 +5755,6 @@ ExportDecl *ExportDecl::Create(ASTContext &C, DeclContext *DC,
return new (C, DC) ExportDecl(DC, ExportLoc); return new (C, DC) ExportDecl(DC, ExportLoc);
} }
-ExportDecl *ExportDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+ExportDecl *ExportDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) ExportDecl(nullptr, SourceLocation()); return new (C, ID) ExportDecl(nullptr, SourceLocation());
} }
clang/lib/AST/DeclBase.cpp
@@ -71,7 +71,7 @@ void Decl::updateOutOfDate(IdentifierInfo &II) const {
#include "clang/AST/DeclNodes.inc" #include "clang/AST/DeclNodes.inc"
void *Decl::operator new(std::size_t Size, const ASTContext &Context, void *Decl::operator new(std::size_t Size, const ASTContext &Context,
- Decl::DeclID ID, std::size_t Extra) {+ GlobalDeclID ID, std::size_t Extra) {
// Allocate an extra 8 bytes worth of storage, which ensures that the // Allocate an extra 8 bytes worth of storage, which ensures that the
// resulting pointer will still be 8-byte aligned. // resulting pointer will still be 8-byte aligned.
static_assert(sizeof(unsigned) * 2 >= alignof(Decl), static_assert(sizeof(unsigned) * 2 >= alignof(Decl),
@@ -85,7 +85,7 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Context,
PrefixPtr[0] = 0; PrefixPtr[0] = 0;
// Store the global declaration ID in the second 4 bytes. // Store the global declaration ID in the second 4 bytes.
- PrefixPtr[1] = ID;+ PrefixPtr[1] = ID.get();
return Result; return Result;
} }
@@ -1115,7 +1115,9 @@ int64_t Decl::getID() const {
const FunctionType *Decl::getFunctionType(bool BlocksToo) const { const FunctionType *Decl::getFunctionType(bool BlocksToo) const {
QualType Ty; QualType Ty;
- if (const auto *D = dyn_cast<ValueDecl>(this))+ if (isa<BindingDecl>(this))
+ return nullptr;
+ else if (const auto *D = dyn_cast<ValueDecl>(this))
Ty = D->getType(); Ty = D->getType();
else if (const auto *D = dyn_cast<TypedefNameDecl>(this)) else if (const auto *D = dyn_cast<TypedefNameDecl>(this))
Ty = D->getUnderlyingType(); Ty = D->getUnderlyingType();
clang/lib/AST/DeclCXX.cpp
@@ -57,7 +57,8 @@ using namespace clang;
void AccessSpecDecl::anchor() {} void AccessSpecDecl::anchor() {}
-AccessSpecDecl *AccessSpecDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+AccessSpecDecl *AccessSpecDecl::CreateDeserialized(ASTContext &C,
+ GlobalDeclID ID) {
return new (C, ID) AccessSpecDecl(EmptyShell()); return new (C, ID) AccessSpecDecl(EmptyShell());
} }
@@ -68,7 +69,7 @@ void LazyASTUnresolvedSet::getFromExternalSource(ASTContext &C) const {
for (ASTUnresolvedSet::iterator I = Impl.begin(); I != Impl.end(); ++I) for (ASTUnresolvedSet::iterator I = Impl.begin(); I != Impl.end(); ++I)
I.setDecl(cast<NamedDecl>(Source->GetExternalDecl( I.setDecl(cast<NamedDecl>(Source->GetExternalDecl(
- reinterpret_cast<uintptr_t>(I.getDecl()) >> 2)));+ GlobalDeclID(reinterpret_cast<uintptr_t>(I.getDecl()) >> 2))));
Impl.Decls.setLazy(false); Impl.Decls.setLazy(false);
} }
@@ -160,8 +161,8 @@ CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC,
return R; return R;
} }
-CXXRecordDecl *+CXXRecordDecl *CXXRecordDecl::CreateDeserialized(const ASTContext &C,
-CXXRecordDecl::CreateDeserialized(const ASTContext &C, Decl::DeclID ID) {+ GlobalDeclID ID) {
auto *R = new (C, ID) auto *R = new (C, ID)
CXXRecordDecl(CXXRecord, TagTypeKind::Struct, C, nullptr, CXXRecordDecl(CXXRecord, TagTypeKind::Struct, C, nullptr,
SourceLocation(), SourceLocation(), nullptr, nullptr); SourceLocation(), SourceLocation(), nullptr, nullptr);
@@ -2162,8 +2163,8 @@ CXXDeductionGuideDecl *CXXDeductionGuideDecl::Create(
TInfo, EndLocation, Ctor, Kind); TInfo, EndLocation, Ctor, Kind);
} }
-CXXDeductionGuideDecl *CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C,+CXXDeductionGuideDecl *
- Decl::DeclID ID) {+CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) CXXDeductionGuideDecl( return new (C, ID) CXXDeductionGuideDecl(
C, nullptr, SourceLocation(), ExplicitSpecifier(), DeclarationNameInfo(), C, nullptr, SourceLocation(), ExplicitSpecifier(), DeclarationNameInfo(),
QualType(), nullptr, SourceLocation(), nullptr, QualType(), nullptr, SourceLocation(), nullptr,
@@ -2175,8 +2176,8 @@ RequiresExprBodyDecl *RequiresExprBodyDecl::Create(
return new (C, DC) RequiresExprBodyDecl(C, DC, StartLoc); return new (C, DC) RequiresExprBodyDecl(C, DC, StartLoc);
} }
-RequiresExprBodyDecl *RequiresExprBodyDecl::CreateDeserialized(ASTContext &C,+RequiresExprBodyDecl *
- Decl::DeclID ID) {+RequiresExprBodyDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) RequiresExprBodyDecl(C, nullptr, SourceLocation()); return new (C, ID) RequiresExprBodyDecl(C, nullptr, SourceLocation());
} }
@@ -2281,7 +2282,8 @@ CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
isInline, ConstexprKind, EndLocation, TrailingRequiresClause); isInline, ConstexprKind, EndLocation, TrailingRequiresClause);
} }
-CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+CXXMethodDecl *CXXMethodDecl::CreateDeserialized(ASTContext &C,
+ GlobalDeclID ID) {
return new (C, ID) CXXMethodDecl( return new (C, ID) CXXMethodDecl(
CXXMethod, C, nullptr, SourceLocation(), DeclarationNameInfo(), CXXMethod, C, nullptr, SourceLocation(), DeclarationNameInfo(),
QualType(), nullptr, SC_None, false, false, QualType(), nullptr, SC_None, false, false,
@@ -2699,7 +2701,7 @@ CXXConstructorDecl::CXXConstructorDecl(
void CXXConstructorDecl::anchor() {} void CXXConstructorDecl::anchor() {}
CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C, CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID,+ GlobalDeclID ID,
uint64_t AllocKind) { uint64_t AllocKind) {
bool hasTrailingExplicit = static_cast<bool>(AllocKind & TAKHasTailExplicit); bool hasTrailingExplicit = static_cast<bool>(AllocKind & TAKHasTailExplicit);
bool isInheritingConstructor = bool isInheritingConstructor =
@@ -2845,8 +2847,8 @@ bool CXXConstructorDecl::isSpecializationCopyingObject() const {
void CXXDestructorDecl::anchor() {} void CXXDestructorDecl::anchor() {}
-CXXDestructorDecl *+CXXDestructorDecl *CXXDestructorDecl::CreateDeserialized(ASTContext &C,
-CXXDestructorDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) CXXDestructorDecl( return new (C, ID) CXXDestructorDecl(
C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
false, false, false, ConstexprSpecKind::Unspecified, nullptr); false, false, false, ConstexprSpecKind::Unspecified, nullptr);
@@ -2877,8 +2879,8 @@ void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) {
void CXXConversionDecl::anchor() {} void CXXConversionDecl::anchor() {}
-CXXConversionDecl *+CXXConversionDecl *CXXConversionDecl::CreateDeserialized(ASTContext &C,
-CXXConversionDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) CXXConversionDecl( return new (C, ID) CXXConversionDecl(
C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr, C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
false, false, ExplicitSpecifier(), ConstexprSpecKind::Unspecified, false, false, ExplicitSpecifier(), ConstexprSpecKind::Unspecified,
@@ -2924,7 +2926,7 @@ LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, DeclContext *DC,
} }
LinkageSpecDecl *LinkageSpecDecl::CreateDeserialized(ASTContext &C, LinkageSpecDecl *LinkageSpecDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) return new (C, ID)
LinkageSpecDecl(nullptr, SourceLocation(), SourceLocation(), LinkageSpecDecl(nullptr, SourceLocation(), SourceLocation(),
LinkageSpecLanguageIDs::C, false); LinkageSpecLanguageIDs::C, false);
@@ -2946,7 +2948,7 @@ UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC,
} }
UsingDirectiveDecl *UsingDirectiveDecl::CreateDeserialized(ASTContext &C, UsingDirectiveDecl *UsingDirectiveDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) UsingDirectiveDecl(nullptr, SourceLocation(), return new (C, ID) UsingDirectiveDecl(nullptr, SourceLocation(),
SourceLocation(), SourceLocation(),
NestedNameSpecifierLoc(), NestedNameSpecifierLoc(),
@@ -2985,7 +2987,8 @@ NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC,
NamespaceDecl(C, DC, Inline, StartLoc, IdLoc, Id, PrevDecl, Nested); NamespaceDecl(C, DC, Inline, StartLoc, IdLoc, Id, PrevDecl, Nested);
} }
-NamespaceDecl *NamespaceDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+NamespaceDecl *NamespaceDecl::CreateDeserialized(ASTContext &C,
+ GlobalDeclID ID) {
return new (C, ID) NamespaceDecl(C, nullptr, false, SourceLocation(), return new (C, ID) NamespaceDecl(C, nullptr, false, SourceLocation(),
SourceLocation(), nullptr, nullptr, false); SourceLocation(), nullptr, nullptr, false);
} }
@@ -3046,8 +3049,8 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
QualifierLoc, IdentLoc, Namespace); QualifierLoc, IdentLoc, Namespace);
} }
-NamespaceAliasDecl *+NamespaceAliasDecl *NamespaceAliasDecl::CreateDeserialized(ASTContext &C,
-NamespaceAliasDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) NamespaceAliasDecl(C, nullptr, SourceLocation(), return new (C, ID) NamespaceAliasDecl(C, nullptr, SourceLocation(),
SourceLocation(), nullptr, SourceLocation(), nullptr,
NestedNameSpecifierLoc(), NestedNameSpecifierLoc(),
@@ -3102,8 +3105,8 @@ UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, EmptyShell Empty)
: NamedDecl(K, nullptr, SourceLocation(), DeclarationName()), : NamedDecl(K, nullptr, SourceLocation(), DeclarationName()),
redeclarable_base(C) {} redeclarable_base(C) {}
-UsingShadowDecl *+UsingShadowDecl *UsingShadowDecl::CreateDeserialized(ASTContext &C,
-UsingShadowDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) UsingShadowDecl(UsingShadow, C, EmptyShell()); return new (C, ID) UsingShadowDecl(UsingShadow, C, EmptyShell());
} }
@@ -3126,7 +3129,7 @@ ConstructorUsingShadowDecl::Create(ASTContext &C, DeclContext *DC,
} }
ConstructorUsingShadowDecl * ConstructorUsingShadowDecl *
-ConstructorUsingShadowDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+ConstructorUsingShadowDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) ConstructorUsingShadowDecl(C, EmptyShell()); return new (C, ID) ConstructorUsingShadowDecl(C, EmptyShell());
} }
@@ -3174,7 +3177,7 @@ UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UL,
return new (C, DC) UsingDecl(DC, UL, QualifierLoc, NameInfo, HasTypename); return new (C, DC) UsingDecl(DC, UL, QualifierLoc, NameInfo, HasTypename);
} }
-UsingDecl *UsingDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+UsingDecl *UsingDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) UsingDecl(nullptr, SourceLocation(), return new (C, ID) UsingDecl(nullptr, SourceLocation(),
NestedNameSpecifierLoc(), DeclarationNameInfo(), NestedNameSpecifierLoc(), DeclarationNameInfo(),
false); false);
@@ -3198,7 +3201,8 @@ UsingEnumDecl *UsingEnumDecl::Create(ASTContext &C, DeclContext *DC,
UsingEnumDecl(DC, EnumType->getType()->getAsTagDecl()->getDeclName(), UL, EL, NL, EnumType); UsingEnumDecl(DC, EnumType->getType()->getAsTagDecl()->getDeclName(), UL, EL, NL, EnumType);
} }
-UsingEnumDecl *UsingEnumDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+UsingEnumDecl *UsingEnumDecl::CreateDeserialized(ASTContext &C,
+ GlobalDeclID ID) {
return new (C, ID) return new (C, ID)
UsingEnumDecl(nullptr, DeclarationName(), SourceLocation(), UsingEnumDecl(nullptr, DeclarationName(), SourceLocation(),
SourceLocation(), SourceLocation(), nullptr); SourceLocation(), SourceLocation(), nullptr);
@@ -3217,7 +3221,7 @@ UsingPackDecl *UsingPackDecl::Create(ASTContext &C, DeclContext *DC,
return new (C, DC, Extra) UsingPackDecl(DC, InstantiatedFrom, UsingDecls); return new (C, DC, Extra) UsingPackDecl(DC, InstantiatedFrom, UsingDecls);
} }
-UsingPackDecl *UsingPackDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID,+UsingPackDecl *UsingPackDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID,
unsigned NumExpansions) { unsigned NumExpansions) {
size_t Extra = additionalSizeToAlloc<NamedDecl *>(NumExpansions); size_t Extra = additionalSizeToAlloc<NamedDecl *>(NumExpansions);
auto *Result = auto *Result =
@@ -3243,7 +3247,7 @@ UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC,
} }
UnresolvedUsingValueDecl * UnresolvedUsingValueDecl *
-UnresolvedUsingValueDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+UnresolvedUsingValueDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) UnresolvedUsingValueDecl(nullptr, QualType(), return new (C, ID) UnresolvedUsingValueDecl(nullptr, QualType(),
SourceLocation(), SourceLocation(),
NestedNameSpecifierLoc(), NestedNameSpecifierLoc(),
@@ -3273,7 +3277,8 @@ UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC,
} }
UnresolvedUsingTypenameDecl * UnresolvedUsingTypenameDecl *
-UnresolvedUsingTypenameDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+UnresolvedUsingTypenameDecl::CreateDeserialized(ASTContext &C,
+ GlobalDeclID ID) {
return new (C, ID) UnresolvedUsingTypenameDecl( return new (C, ID) UnresolvedUsingTypenameDecl(
nullptr, SourceLocation(), SourceLocation(), NestedNameSpecifierLoc(), nullptr, SourceLocation(), SourceLocation(), NestedNameSpecifierLoc(),
SourceLocation(), nullptr, SourceLocation()); SourceLocation(), nullptr, SourceLocation());
@@ -3286,7 +3291,8 @@ UnresolvedUsingIfExistsDecl::Create(ASTContext &Ctx, DeclContext *DC,
} }
UnresolvedUsingIfExistsDecl * UnresolvedUsingIfExistsDecl *
-UnresolvedUsingIfExistsDecl::CreateDeserialized(ASTContext &Ctx, Decl::DeclID ID) {+UnresolvedUsingIfExistsDecl::CreateDeserialized(ASTContext &Ctx,
+ GlobalDeclID ID) {
return new (Ctx, ID) return new (Ctx, ID)
UnresolvedUsingIfExistsDecl(nullptr, SourceLocation(), DeclarationName()); UnresolvedUsingIfExistsDecl(nullptr, SourceLocation(), DeclarationName());
} }
@@ -3310,7 +3316,7 @@ StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC,
} }
StaticAssertDecl *StaticAssertDecl::CreateDeserialized(ASTContext &C, StaticAssertDecl *StaticAssertDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) StaticAssertDecl(nullptr, SourceLocation(), nullptr, return new (C, ID) StaticAssertDecl(nullptr, SourceLocation(), nullptr,
nullptr, SourceLocation(), false); nullptr, SourceLocation(), false);
} }
@@ -3332,7 +3338,7 @@ BindingDecl *BindingDecl::Create(ASTContext &C, DeclContext *DC,
return new (C, DC) BindingDecl(DC, IdLoc, Id); return new (C, DC) BindingDecl(DC, IdLoc, Id);
} }
-BindingDecl *BindingDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+BindingDecl *BindingDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) BindingDecl(nullptr, SourceLocation(), nullptr); return new (C, ID) BindingDecl(nullptr, SourceLocation(), nullptr);
} }
@@ -3363,7 +3369,7 @@ DecompositionDecl *DecompositionDecl::Create(ASTContext &C, DeclContext *DC,
} }
DecompositionDecl *DecompositionDecl::CreateDeserialized(ASTContext &C, DecompositionDecl *DecompositionDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID,+ GlobalDeclID ID,
unsigned NumBindings) { unsigned NumBindings) {
size_t Extra = additionalSizeToAlloc<BindingDecl *>(NumBindings); size_t Extra = additionalSizeToAlloc<BindingDecl *>(NumBindings);
auto *Result = new (C, ID, Extra) auto *Result = new (C, ID, Extra)
@@ -3402,7 +3408,7 @@ MSPropertyDecl *MSPropertyDecl::Create(ASTContext &C, DeclContext *DC,
} }
MSPropertyDecl *MSPropertyDecl::CreateDeserialized(ASTContext &C, MSPropertyDecl *MSPropertyDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) MSPropertyDecl(nullptr, SourceLocation(), return new (C, ID) MSPropertyDecl(nullptr, SourceLocation(),
DeclarationName(), QualType(), nullptr, DeclarationName(), QualType(), nullptr,
SourceLocation(), nullptr, nullptr); SourceLocation(), nullptr, nullptr);
@@ -3419,7 +3425,7 @@ MSGuidDecl *MSGuidDecl::Create(const ASTContext &C, QualType T, Parts P) {
return new (C, DC) MSGuidDecl(DC, T, P); return new (C, DC) MSGuidDecl(DC, T, P);
} }
-MSGuidDecl *MSGuidDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+MSGuidDecl *MSGuidDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) MSGuidDecl(nullptr, QualType(), Parts()); return new (C, ID) MSGuidDecl(nullptr, QualType(), Parts());
} }
@@ -3529,7 +3535,7 @@ UnnamedGlobalConstantDecl::Create(const ASTContext &C, QualType T,
} }
UnnamedGlobalConstantDecl * UnnamedGlobalConstantDecl *
-UnnamedGlobalConstantDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+UnnamedGlobalConstantDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) return new (C, ID)
UnnamedGlobalConstantDecl(C, nullptr, QualType(), APValue()); UnnamedGlobalConstantDecl(C, nullptr, QualType(), APValue());
} }
clang/lib/AST/DeclFriend.cpp
@@ -62,7 +62,7 @@ FriendDecl *FriendDecl::Create(ASTContext &C, DeclContext *DC,
return FD; return FD;
} }
-FriendDecl *FriendDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID,+FriendDecl *FriendDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID,
unsigned FriendTypeNumTPLists) { unsigned FriendTypeNumTPLists) {
std::size_t Extra = std::size_t Extra =
additionalSizeToAlloc<TemplateParameterList *>(FriendTypeNumTPLists); additionalSizeToAlloc<TemplateParameterList *>(FriendTypeNumTPLists);
clang/lib/AST/DeclObjC.cpp
@@ -862,7 +862,8 @@ ObjCMethodDecl *ObjCMethodDecl::Create(
isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType); isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType);
} }
-ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C,
+ GlobalDeclID ID) {
return new (C, ID) ObjCMethodDecl(SourceLocation(), SourceLocation(), return new (C, ID) ObjCMethodDecl(SourceLocation(), SourceLocation(),
Selector(), QualType(), nullptr, nullptr); Selector(), QualType(), nullptr, nullptr);
} }
@@ -1486,7 +1487,7 @@ ObjCTypeParamDecl *ObjCTypeParamDecl::Create(ASTContext &ctx, DeclContext *dc,
} }
ObjCTypeParamDecl *ObjCTypeParamDecl::CreateDeserialized(ASTContext &ctx, ObjCTypeParamDecl *ObjCTypeParamDecl::CreateDeserialized(ASTContext &ctx,
- Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (ctx, ID) ObjCTypeParamDecl(ctx, nullptr, return new (ctx, ID) ObjCTypeParamDecl(ctx, nullptr,
ObjCTypeParamVariance::Invariant, ObjCTypeParamVariance::Invariant,
SourceLocation(), 0, SourceLocation(), SourceLocation(), 0, SourceLocation(),
@@ -1551,7 +1552,7 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::Create(
} }
ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(const ASTContext &C, ObjCInterfaceDecl *ObjCInterfaceDecl::CreateDeserialized(const ASTContext &C,
- Decl::DeclID ID) {+ GlobalDeclID ID) {
auto *Result = new (C, ID) auto *Result = new (C, ID)
ObjCInterfaceDecl(C, nullptr, SourceLocation(), nullptr, nullptr, ObjCInterfaceDecl(C, nullptr, SourceLocation(), nullptr, nullptr,
SourceLocation(), nullptr, false); SourceLocation(), nullptr, false);
@@ -1865,7 +1866,7 @@ ObjCIvarDecl *ObjCIvarDecl::Create(ASTContext &C, ObjCContainerDecl *DC,
synthesized); synthesized);
} }
-ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+ObjCIvarDecl *ObjCIvarDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) ObjCIvarDecl(nullptr, SourceLocation(), SourceLocation(), return new (C, ID) ObjCIvarDecl(nullptr, SourceLocation(), SourceLocation(),
nullptr, QualType(), nullptr, nullptr, QualType(), nullptr,
ObjCIvarDecl::None, nullptr, false); ObjCIvarDecl::None, nullptr, false);
@@ -1914,7 +1915,7 @@ ObjCAtDefsFieldDecl
} }
ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::CreateDeserialized(ASTContext &C, ObjCAtDefsFieldDecl *ObjCAtDefsFieldDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) ObjCAtDefsFieldDecl(nullptr, SourceLocation(), return new (C, ID) ObjCAtDefsFieldDecl(nullptr, SourceLocation(),
SourceLocation(), nullptr, QualType(), SourceLocation(), nullptr, QualType(),
nullptr); nullptr);
@@ -1949,7 +1950,7 @@ ObjCProtocolDecl *ObjCProtocolDecl::Create(ASTContext &C, DeclContext *DC,
} }
ObjCProtocolDecl *ObjCProtocolDecl::CreateDeserialized(ASTContext &C, ObjCProtocolDecl *ObjCProtocolDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID) {+ GlobalDeclID ID) {
ObjCProtocolDecl *Result = ObjCProtocolDecl *Result =
new (C, ID) ObjCProtocolDecl(C, nullptr, nullptr, SourceLocation(), new (C, ID) ObjCProtocolDecl(C, nullptr, nullptr, SourceLocation(),
SourceLocation(), nullptr); SourceLocation(), nullptr);
@@ -2148,7 +2149,7 @@ ObjCCategoryDecl *ObjCCategoryDecl::Create(
} }
ObjCCategoryDecl *ObjCCategoryDecl::CreateDeserialized(ASTContext &C, ObjCCategoryDecl *ObjCCategoryDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) ObjCCategoryDecl(nullptr, SourceLocation(), return new (C, ID) ObjCCategoryDecl(nullptr, SourceLocation(),
SourceLocation(), SourceLocation(), SourceLocation(), SourceLocation(),
nullptr, nullptr, nullptr); nullptr, nullptr, nullptr);
@@ -2188,8 +2189,8 @@ ObjCCategoryImplDecl *ObjCCategoryImplDecl::Create(
atStartLoc, CategoryNameLoc); atStartLoc, CategoryNameLoc);
} }
-ObjCCategoryImplDecl *ObjCCategoryImplDecl::CreateDeserialized(ASTContext &C,+ObjCCategoryImplDecl *
- Decl::DeclID ID) {+ObjCCategoryImplDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) ObjCCategoryImplDecl(nullptr, nullptr, nullptr, return new (C, ID) ObjCCategoryImplDecl(nullptr, nullptr, nullptr,
SourceLocation(), SourceLocation(), SourceLocation(), SourceLocation(),
SourceLocation()); SourceLocation());
@@ -2296,7 +2297,7 @@ ObjCImplementationDecl::Create(ASTContext &C, DeclContext *DC,
} }
ObjCImplementationDecl * ObjCImplementationDecl *
-ObjCImplementationDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+ObjCImplementationDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) ObjCImplementationDecl(nullptr, nullptr, nullptr, return new (C, ID) ObjCImplementationDecl(nullptr, nullptr, nullptr,
SourceLocation(), SourceLocation()); SourceLocation(), SourceLocation());
} }
@@ -2339,7 +2340,7 @@ ObjCCompatibleAliasDecl::Create(ASTContext &C, DeclContext *DC,
} }
ObjCCompatibleAliasDecl * ObjCCompatibleAliasDecl *
-ObjCCompatibleAliasDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+ObjCCompatibleAliasDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) ObjCCompatibleAliasDecl(nullptr, SourceLocation(), return new (C, ID) ObjCCompatibleAliasDecl(nullptr, SourceLocation(),
nullptr, nullptr); nullptr, nullptr);
} }
@@ -2360,7 +2361,7 @@ ObjCPropertyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
} }
ObjCPropertyDecl *ObjCPropertyDecl::CreateDeserialized(ASTContext &C, ObjCPropertyDecl *ObjCPropertyDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) ObjCPropertyDecl(nullptr, SourceLocation(), nullptr, return new (C, ID) ObjCPropertyDecl(nullptr, SourceLocation(), nullptr,
SourceLocation(), SourceLocation(), SourceLocation(), SourceLocation(),
QualType(), nullptr, None); QualType(), nullptr, None);
@@ -2392,8 +2393,8 @@ ObjCPropertyImplDecl *ObjCPropertyImplDecl::Create(ASTContext &C,
ivarLoc); ivarLoc);
} }
-ObjCPropertyImplDecl *ObjCPropertyImplDecl::CreateDeserialized(ASTContext &C,+ObjCPropertyImplDecl *
- Decl::DeclID ID) {+ObjCPropertyImplDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) ObjCPropertyImplDecl(nullptr, SourceLocation(), return new (C, ID) ObjCPropertyImplDecl(nullptr, SourceLocation(),
SourceLocation(), nullptr, Dynamic, SourceLocation(), nullptr, Dynamic,
nullptr, SourceLocation()); nullptr, SourceLocation());
clang/lib/AST/DeclOpenMP.cpp
@@ -36,7 +36,7 @@ OMPThreadPrivateDecl *OMPThreadPrivateDecl::Create(ASTContext &C,
} }
OMPThreadPrivateDecl *OMPThreadPrivateDecl::CreateDeserialized(ASTContext &C, OMPThreadPrivateDecl *OMPThreadPrivateDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID,+ GlobalDeclID ID,
unsigned N) { unsigned N) {
return OMPDeclarativeDirective::createEmptyDirective<OMPThreadPrivateDecl>( return OMPDeclarativeDirective::createEmptyDirective<OMPThreadPrivateDecl>(
C, ID, 0, N); C, ID, 0, N);
@@ -63,7 +63,8 @@ OMPAllocateDecl *OMPAllocateDecl::Create(ASTContext &C, DeclContext *DC,
return D; return D;
} }
-OMPAllocateDecl *OMPAllocateDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID,+OMPAllocateDecl *OMPAllocateDecl::CreateDeserialized(ASTContext &C,
+ GlobalDeclID ID,
unsigned NVars, unsigned NVars,
unsigned NClauses) { unsigned NClauses) {
return OMPDeclarativeDirective::createEmptyDirective<OMPAllocateDecl>( return OMPDeclarativeDirective::createEmptyDirective<OMPAllocateDecl>(
@@ -89,7 +90,8 @@ OMPRequiresDecl *OMPRequiresDecl::Create(ASTContext &C, DeclContext *DC,
L); L);
} }
-OMPRequiresDecl *OMPRequiresDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID,+OMPRequiresDecl *OMPRequiresDecl::CreateDeserialized(ASTContext &C,
+ GlobalDeclID ID,
unsigned N) { unsigned N) {
return OMPDeclarativeDirective::createEmptyDirective<OMPRequiresDecl>( return OMPDeclarativeDirective::createEmptyDirective<OMPRequiresDecl>(
C, ID, N, 0, SourceLocation()); C, ID, N, 0, SourceLocation());
@@ -117,7 +119,7 @@ OMPDeclareReductionDecl *OMPDeclareReductionDecl::Create(
} }
OMPDeclareReductionDecl * OMPDeclareReductionDecl *
-OMPDeclareReductionDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+OMPDeclareReductionDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) OMPDeclareReductionDecl( return new (C, ID) OMPDeclareReductionDecl(
OMPDeclareReduction, /*DC=*/nullptr, SourceLocation(), DeclarationName(), OMPDeclareReduction, /*DC=*/nullptr, SourceLocation(), DeclarationName(),
QualType(), /*PrevDeclInScope=*/nullptr); QualType(), /*PrevDeclInScope=*/nullptr);
@@ -148,7 +150,7 @@ OMPDeclareMapperDecl *OMPDeclareMapperDecl::Create(
} }
OMPDeclareMapperDecl *OMPDeclareMapperDecl::CreateDeserialized(ASTContext &C, OMPDeclareMapperDecl *OMPDeclareMapperDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID,+ GlobalDeclID ID,
unsigned N) { unsigned N) {
return OMPDeclarativeDirective::createEmptyDirective<OMPDeclareMapperDecl>( return OMPDeclarativeDirective::createEmptyDirective<OMPDeclareMapperDecl>(
C, ID, N, 1, SourceLocation(), DeclarationName(), QualType(), C, ID, N, 1, SourceLocation(), DeclarationName(), QualType(),
@@ -179,7 +181,7 @@ OMPCapturedExprDecl *OMPCapturedExprDecl::Create(ASTContext &C, DeclContext *DC,
} }
OMPCapturedExprDecl *OMPCapturedExprDecl::CreateDeserialized(ASTContext &C, OMPCapturedExprDecl *OMPCapturedExprDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) OMPCapturedExprDecl(C, nullptr, nullptr, QualType(), return new (C, ID) OMPCapturedExprDecl(C, nullptr, nullptr, QualType(),
/*TInfo=*/nullptr, SourceLocation()); /*TInfo=*/nullptr, SourceLocation());
} }
clang/lib/AST/DeclTemplate.cpp
@@ -337,9 +337,10 @@ void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const {
CommonBase *CommonBasePtr = getMostRecentDecl()->getCommonPtr(); CommonBase *CommonBasePtr = getMostRecentDecl()->getCommonPtr();
if (CommonBasePtr->LazySpecializations) { if (CommonBasePtr->LazySpecializations) {
ASTContext &Context = getASTContext(); ASTContext &Context = getASTContext();
- Decl::DeclID *Specs = CommonBasePtr->LazySpecializations;+ GlobalDeclID *Specs = CommonBasePtr->LazySpecializations;
CommonBasePtr->LazySpecializations = nullptr; CommonBasePtr->LazySpecializations = nullptr;
- for (uint32_t I = 0, N = *Specs++; I != N; ++I)+ unsigned SpecSize = (*Specs++).get();
+ for (unsigned I = 0; I != SpecSize; ++I)
(void)Context.getExternalSource()->GetExternalDecl(Specs[I]); (void)Context.getExternalSource()->GetExternalDecl(Specs[I]);
} }
} }
@@ -417,8 +418,8 @@ FunctionTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
return TD; return TD;
} }
-FunctionTemplateDecl *FunctionTemplateDecl::CreateDeserialized(ASTContext &C,+FunctionTemplateDecl *
- Decl::DeclID ID) {+FunctionTemplateDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) FunctionTemplateDecl(C, nullptr, SourceLocation(), return new (C, ID) FunctionTemplateDecl(C, nullptr, SourceLocation(),
DeclarationName(), nullptr, nullptr); DeclarationName(), nullptr, nullptr);
} }
@@ -503,7 +504,7 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, DeclContext *DC,
} }
ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C, ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) ClassTemplateDecl(C, nullptr, SourceLocation(), return new (C, ID) ClassTemplateDecl(C, nullptr, SourceLocation(),
DeclarationName(), nullptr, nullptr); DeclarationName(), nullptr, nullptr);
} }
@@ -652,14 +653,14 @@ TemplateTypeParmDecl *TemplateTypeParmDecl::Create(
} }
TemplateTypeParmDecl * TemplateTypeParmDecl *
-TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, Decl::DeclID ID) {+TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, GlobalDeclID ID) {
return new (C, ID) return new (C, ID)
TemplateTypeParmDecl(nullptr, SourceLocation(), SourceLocation(), nullptr, TemplateTypeParmDecl(nullptr, SourceLocation(), SourceLocation(), nullptr,
false, false, std::nullopt); false, false, std::nullopt);
} }
TemplateTypeParmDecl * TemplateTypeParmDecl *
-TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, Decl::DeclID ID,+TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, GlobalDeclID ID,
bool HasTypeConstraint) { bool HasTypeConstraint) {
return new (C, ID, return new (C, ID,
additionalSizeToAlloc<TypeConstraint>(HasTypeConstraint ? 1 : 0)) additionalSizeToAlloc<TypeConstraint>(HasTypeConstraint ? 1 : 0))
@@ -759,7 +760,7 @@ NonTypeTemplateParmDecl *NonTypeTemplateParmDecl::Create(
} }
NonTypeTemplateParmDecl * NonTypeTemplateParmDecl *
-NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID,+NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID,
bool HasTypeConstraint) { bool HasTypeConstraint) {
return new (C, ID, additionalSizeToAlloc<std::pair<QualType, return new (C, ID, additionalSizeToAlloc<std::pair<QualType,
TypeSourceInfo *>, TypeSourceInfo *>,
@@ -770,7 +771,7 @@ NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID,
} }
NonTypeTemplateParmDecl * NonTypeTemplateParmDecl *
-NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID,+NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID,
unsigned NumExpandedTypes, unsigned NumExpandedTypes,
bool HasTypeConstraint) { bool HasTypeConstraint) {
auto *NTTP = auto *NTTP =
@@ -836,13 +837,13 @@ TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
} }
TemplateTemplateParmDecl * TemplateTemplateParmDecl *
-TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, return new (C, ID) TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0,
false, nullptr, false, nullptr); false, nullptr, false, nullptr);
} }
TemplateTemplateParmDecl * TemplateTemplateParmDecl *
-TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID,+TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID,
unsigned NumExpansions) { unsigned NumExpansions) {
auto *TTP = auto *TTP =
new (C, ID, additionalSizeToAlloc<TemplateParameterList *>(NumExpansions)) new (C, ID, additionalSizeToAlloc<TemplateParameterList *>(NumExpansions))
@@ -949,7 +950,7 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,
ClassTemplateSpecializationDecl * ClassTemplateSpecializationDecl *
ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C, ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID) {+ GlobalDeclID ID) {
auto *Result = auto *Result =
new (C, ID) ClassTemplateSpecializationDecl(C, ClassTemplateSpecialization); new (C, ID) ClassTemplateSpecializationDecl(C, ClassTemplateSpecialization);
Result->setMayHaveOutOfDateDef(false); Result->setMayHaveOutOfDateDef(false);
@@ -1035,8 +1036,7 @@ ConceptDecl *ConceptDecl::Create(ASTContext &C, DeclContext *DC,
return TD; return TD;
} }
-ConceptDecl *ConceptDecl::CreateDeserialized(ASTContext &C,+ConceptDecl *ConceptDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
- Decl::DeclID ID) {
ConceptDecl *Result = new (C, ID) ConceptDecl(nullptr, SourceLocation(), ConceptDecl *Result = new (C, ID) ConceptDecl(nullptr, SourceLocation(),
DeclarationName(), DeclarationName(),
nullptr, nullptr); nullptr, nullptr);
@@ -1070,7 +1070,7 @@ ImplicitConceptSpecializationDecl *ImplicitConceptSpecializationDecl::Create(
ImplicitConceptSpecializationDecl * ImplicitConceptSpecializationDecl *
ImplicitConceptSpecializationDecl::CreateDeserialized( ImplicitConceptSpecializationDecl::CreateDeserialized(
- const ASTContext &C, Decl::DeclID ID, unsigned NumTemplateArgs) {+ const ASTContext &C, GlobalDeclID ID, unsigned NumTemplateArgs) {
return new (C, ID, additionalSizeToAlloc<TemplateArgument>(NumTemplateArgs)) return new (C, ID, additionalSizeToAlloc<TemplateArgument>(NumTemplateArgs))
ImplicitConceptSpecializationDecl(EmptyShell{}, NumTemplateArgs); ImplicitConceptSpecializationDecl(EmptyShell{}, NumTemplateArgs);
} }
@@ -1133,7 +1133,7 @@ Create(ASTContext &Context, TagKind TK,DeclContext *DC,
ClassTemplatePartialSpecializationDecl * ClassTemplatePartialSpecializationDecl *
ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C, ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID) {+ GlobalDeclID ID) {
auto *Result = new (C, ID) ClassTemplatePartialSpecializationDecl(C); auto *Result = new (C, ID) ClassTemplatePartialSpecializationDecl(C);
Result->setMayHaveOutOfDateDef(false); Result->setMayHaveOutOfDateDef(false);
return Result; return Result;
@@ -1160,7 +1160,7 @@ FriendTemplateDecl::Create(ASTContext &Context, DeclContext *DC,
} }
FriendTemplateDecl *FriendTemplateDecl::CreateDeserialized(ASTContext &C, FriendTemplateDecl *FriendTemplateDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) FriendTemplateDecl(EmptyShell()); return new (C, ID) FriendTemplateDecl(EmptyShell());
} }
@@ -1179,8 +1179,8 @@ TypeAliasTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
return TD; return TD;
} }
-TypeAliasTemplateDecl *TypeAliasTemplateDecl::CreateDeserialized(ASTContext &C,+TypeAliasTemplateDecl *
- Decl::DeclID ID) {+TypeAliasTemplateDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
return new (C, ID) TypeAliasTemplateDecl(C, nullptr, SourceLocation(), return new (C, ID) TypeAliasTemplateDecl(C, nullptr, SourceLocation(),
DeclarationName(), nullptr, nullptr); DeclarationName(), nullptr, nullptr);
} }
@@ -1218,7 +1218,7 @@ VarTemplateDecl *VarTemplateDecl::Create(ASTContext &C, DeclContext *DC,
} }
VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C, VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) VarTemplateDecl(C, nullptr, SourceLocation(), return new (C, ID) VarTemplateDecl(C, nullptr, SourceLocation(),
DeclarationName(), nullptr, nullptr); DeclarationName(), nullptr, nullptr);
} }
@@ -1340,7 +1340,8 @@ VarTemplateSpecializationDecl *VarTemplateSpecializationDecl::Create(
} }
VarTemplateSpecializationDecl * VarTemplateSpecializationDecl *
-VarTemplateSpecializationDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+VarTemplateSpecializationDecl::CreateDeserialized(ASTContext &C,
+ GlobalDeclID ID) {
return new (C, ID) return new (C, ID)
VarTemplateSpecializationDecl(VarTemplateSpecialization, C); VarTemplateSpecializationDecl(VarTemplateSpecialization, C);
} }
@@ -1432,7 +1433,7 @@ VarTemplatePartialSpecializationDecl::Create(
VarTemplatePartialSpecializationDecl * VarTemplatePartialSpecializationDecl *
VarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C, VarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
- Decl::DeclID ID) {+ GlobalDeclID ID) {
return new (C, ID) VarTemplatePartialSpecializationDecl(C); return new (C, ID) VarTemplatePartialSpecializationDecl(C);
} }
@@ -1546,7 +1547,7 @@ TemplateParamObjectDecl *TemplateParamObjectDecl::Create(const ASTContext &C,
} }
TemplateParamObjectDecl * TemplateParamObjectDecl *
-TemplateParamObjectDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {+TemplateParamObjectDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
auto *TPOD = new (C, ID) TemplateParamObjectDecl(nullptr, QualType(), APValue()); auto *TPOD = new (C, ID) TemplateParamObjectDecl(nullptr, QualType(), APValue());
C.addDestruction(&TPOD->Value); C.addDestruction(&TPOD->Value);
return TPOD; return TPOD;
clang/lib/AST/Expr.cpp
@@ -103,7 +103,7 @@ const Expr *Expr::skipRValueSubobjectAdjustments(
} }
} else if (const auto *ME = dyn_cast<MemberExpr>(E)) { } else if (const auto *ME = dyn_cast<MemberExpr>(E)) {
if (!ME->isArrow()) { if (!ME->isArrow()) {
- assert(ME->getBase()->getType()->isRecordType());+ assert(ME->getBase()->getType()->getAsRecordDecl());
if (const auto *Field = dyn_cast<FieldDecl>(ME->getMemberDecl())) { if (const auto *Field = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
if (!Field->isBitField() && !Field->getType()->isReferenceType()) { if (!Field->isBitField() && !Field->getType()->isReferenceType()) {
E = ME->getBase(); E = ME->getBase();
@@ -3680,7 +3680,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case ParenExprClass: case ParenExprClass:
case ArraySubscriptExprClass: case ArraySubscriptExprClass:
case MatrixSubscriptExprClass: case MatrixSubscriptExprClass:
- case OMPArraySectionExprClass:+ case ArraySectionExprClass:
case OMPArrayShapingExprClass: case OMPArrayShapingExprClass:
case OMPIteratorExprClass: case OMPIteratorExprClass:
case MemberExprClass: case MemberExprClass:
@@ -3893,9 +3893,14 @@ namespace {
} }
void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *E) { void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *E) {
- if (E->getTemporary()->getDestructor()->isTrivial()) {+ // Destructor of the temporary might be null if destructor declaration
- Inherited::VisitStmt(E);+ // is not valid.
- return;+ if (const CXXDestructorDecl *DtorDecl =
+ E->getTemporary()->getDestructor()) {
+ if (DtorDecl->isTrivial()) {
+ Inherited::VisitStmt(E);
+ return;
+ }
} }
NonTrivial = true; NonTrivial = true;
@@ -5060,9 +5065,9 @@ QualType AtomicExpr::getValueType() const {
return T; return T;
} }
-QualType OMPArraySectionExpr::getBaseOriginalType(const Expr *Base) {+QualType ArraySectionExpr::getBaseOriginalType(const Expr *Base) {
unsigned ArraySectionCount = 0; unsigned ArraySectionCount = 0;
- while (auto *OASE = dyn_cast<OMPArraySectionExpr>(Base->IgnoreParens())) {+ while (auto *OASE = dyn_cast<ArraySectionExpr>(Base->IgnoreParens())) {
Base = OASE->getBase(); Base = OASE->getBase();
++ArraySectionCount; ++ArraySectionCount;
} }
clang/lib/AST/ExprClassification.cpp
@@ -145,7 +145,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::FunctionParmPackExprClass: case Expr::FunctionParmPackExprClass:
case Expr::MSPropertyRefExprClass: case Expr::MSPropertyRefExprClass:
case Expr::MSPropertySubscriptExprClass: case Expr::MSPropertySubscriptExprClass:
- case Expr::OMPArraySectionExprClass:+ case Expr::ArraySectionExprClass:
case Expr::OMPArrayShapingExprClass: case Expr::OMPArrayShapingExprClass:
case Expr::OMPIteratorExprClass: case Expr::OMPIteratorExprClass:
return Cl::CL_LValue; return Cl::CL_LValue;
@@ -216,8 +216,13 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
return ClassifyInternal(Ctx, return ClassifyInternal(Ctx,
cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement()); cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement());
- case Expr::PackIndexingExprClass:+ case Expr::PackIndexingExprClass: {
+ // A pack-index-expression always expands to an id-expression.
+ // Consider it as an LValue expression.
+ if (cast<PackIndexingExpr>(E)->isInstantiationDependent())
+ return Cl::CL_LValue;
return ClassifyInternal(Ctx, cast<PackIndexingExpr>(E)->getSelectedExpr()); return ClassifyInternal(Ctx, cast<PackIndexingExpr>(E)->getSelectedExpr());
+ }
// C, C++98 [expr.sub]p1: The result is an lvalue of type "T". // C, C++98 [expr.sub]p1: The result is an lvalue of type "T".
// C++11 (DR1213): in the case of an array operand, the result is an lvalue // C++11 (DR1213): in the case of an array operand, the result is an lvalue
clang/lib/AST/ExprConstant.cpp
@@ -2706,7 +2706,11 @@ static bool checkFloatingPointResult(EvalInfo &Info, const Expr *E,
static bool HandleFloatToFloatCast(EvalInfo &Info, const Expr *E, static bool HandleFloatToFloatCast(EvalInfo &Info, const Expr *E,
QualType SrcType, QualType DestType, QualType SrcType, QualType DestType,
APFloat &Result) { APFloat &Result) {
- assert(isa<CastExpr>(E) || isa<CompoundAssignOperator>(E));+ assert((isa<CastExpr>(E) || isa<CompoundAssignOperator>(E) ||
+ isa<ConvertVectorExpr>(E)) &&
+ "HandleFloatToFloatCast has been checked with only CastExpr, "
+ "CompoundAssignOperator and ConvertVectorExpr. Please either validate "
+ "the new expression or address the root cause of this usage.");
llvm::RoundingMode RM = getActiveRoundingMode(Info, E); llvm::RoundingMode RM = getActiveRoundingMode(Info, E);
APFloat::opStatus St; APFloat::opStatus St;
APFloat Value = Result; APFloat Value = Result;
@@ -9237,9 +9241,10 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) {
bool HasValidResult = !Result.InvalidBase && !Result.Designator.Invalid && bool HasValidResult = !Result.InvalidBase && !Result.Designator.Invalid &&
!Result.IsNullPtr; !Result.IsNullPtr;
bool VoidPtrCastMaybeOK = bool VoidPtrCastMaybeOK =
- HasValidResult &&+ Result.IsNullPtr ||
- Info.Ctx.hasSameUnqualifiedType(Result.Designator.getType(Info.Ctx),+ (HasValidResult &&
- E->getType()->getPointeeType());+ Info.Ctx.hasSimilarType(Result.Designator.getType(Info.Ctx),
+ E->getType()->getPointeeType()));
// 1. We'll allow it in std::allocator::allocate, and anything which that // 1. We'll allow it in std::allocator::allocate, and anything which that
// calls. // calls.
// 2. HACK 2022-03-28: Work around an issue with libstdc++'s // 2. HACK 2022-03-28: Work around an issue with libstdc++'s
@@ -10709,8 +10714,11 @@ namespace {
bool VisitUnaryImag(const UnaryOperator *E); bool VisitUnaryImag(const UnaryOperator *E);
bool VisitBinaryOperator(const BinaryOperator *E); bool VisitBinaryOperator(const BinaryOperator *E);
bool VisitUnaryOperator(const UnaryOperator *E); bool VisitUnaryOperator(const UnaryOperator *E);
+ bool VisitConvertVectorExpr(const ConvertVectorExpr *E);
+ bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E);
+
// FIXME: Missing: conditional operator (for GNU // FIXME: Missing: conditional operator (for GNU
- // conditional select), shufflevector, ExtVectorElementExpr+ // conditional select), ExtVectorElementExpr
}; };
} // end anonymous namespace } // end anonymous namespace
@@ -10961,6 +10969,122 @@ bool VectorExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
return Success(APValue(ResultElements.data(), ResultElements.size()), E); return Success(APValue(ResultElements.data(), ResultElements.size()), E);
} }
+static bool handleVectorElementCast(EvalInfo &Info, const FPOptions FPO,
+ const Expr *E, QualType SourceTy,
+ QualType DestTy, APValue const &Original,
+ APValue &Result) {
+ if (SourceTy->isIntegerType()) {
+ if (DestTy->isRealFloatingType()) {
+ Result = APValue(APFloat(0.0));
+ return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+ DestTy, Result.getFloat());
+ }
+ if (DestTy->isIntegerType()) {
+ Result = APValue(
+ HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+ return true;
+ }
+ } else if (SourceTy->isRealFloatingType()) {
+ if (DestTy->isRealFloatingType()) {
+ Result = Original;
+ return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+ Result.getFloat());
+ }
+ if (DestTy->isIntegerType()) {
+ Result = APValue(APSInt());
+ return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+ DestTy, Result.getInt());
+ }
+ }
+
+ Info.FFDiag(E, diag::err_convertvector_constexpr_unsupported_vector_cast)
+ << SourceTy << DestTy;
+ return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+ APValue Source;
+ QualType SourceVecType = E->getSrcExpr()->getType();
+ if (!EvaluateAsRValue(Info, E->getSrcExpr(), Source))
+ return false;
+
+ QualType DestTy = E->getType()->castAs<VectorType>()->getElementType();
+ QualType SourceTy = SourceVecType->castAs<VectorType>()->getElementType();
+
+ const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+ auto SourceLen = Source.getVectorLength();
+ SmallVector<APValue, 4> ResultElements;
+ ResultElements.reserve(SourceLen);
+ for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+ APValue Elt;
+ if (!handleVectorElementCast(Info, FPO, E, SourceTy, DestTy,
+ Source.getVectorElt(EltNum), Elt))
+ return false;
+ ResultElements.push_back(std::move(Elt));
+ }
+
+ return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo &Info, const ShuffleVectorExpr *E,
+ QualType ElemType, APValue const &VecVal1,
+ APValue const &VecVal2, unsigned EltNum,
+ APValue &Result) {
+ unsigned const TotalElementsInInputVector1 = VecVal1.getVectorLength();
+ unsigned const TotalElementsInInputVector2 = VecVal2.getVectorLength();
+
+ APSInt IndexVal = E->getShuffleMaskIdx(Info.Ctx, EltNum);
+ int64_t index = IndexVal.getExtValue();
+ // The spec says that -1 should be treated as undef for optimizations,
+ // but in constexpr we'd have to produce an APValue::Indeterminate,
+ // which is prohibited from being a top-level constant value. Emit a
+ // diagnostic instead.
+ if (index == -1) {
+ Info.FFDiag(
+ E, diag::err_shufflevector_minus_one_is_undefined_behavior_constexpr)
+ << EltNum;
+ return false;
+ }
+
+ if (index < 0 ||
+ index >= TotalElementsInInputVector1 + TotalElementsInInputVector2)
+ llvm_unreachable("Out of bounds shuffle index");
+
+ if (index >= TotalElementsInInputVector1)
+ Result = VecVal2.getVectorElt(index - TotalElementsInInputVector1);
+ else
+ Result = VecVal1.getVectorElt(index);
+ return true;
+}
+
+bool VectorExprEvaluator::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {
+ APValue VecVal1;
+ const Expr *Vec1 = E->getExpr(0);
+ if (!EvaluateAsRValue(Info, Vec1, VecVal1))
+ return false;
+ APValue VecVal2;
+ const Expr *Vec2 = E->getExpr(1);
+ if (!EvaluateAsRValue(Info, Vec2, VecVal2))
+ return false;
+
+ VectorType const *DestVecTy = E->getType()->castAs<VectorType>();
+ QualType DestElTy = DestVecTy->getElementType();
+
+ auto TotalElementsInOutputVector = DestVecTy->getNumElements();
+
+ SmallVector<APValue, 4> ResultElements;
+ ResultElements.reserve(TotalElementsInOutputVector);
+ for (unsigned EltNum = 0; EltNum < TotalElementsInOutputVector; ++EltNum) {
+ APValue Elt;
+ if (!handleVectorShuffle(Info, E, DestElTy, VecVal1, VecVal2, EltNum, Elt))
+ return false;
+ ResultElements.push_back(std::move(Elt));
+ }
+
+ return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Array Evaluation // Array Evaluation
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@@ -16130,7 +16254,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::StringLiteralClass: case Expr::StringLiteralClass:
case Expr::ArraySubscriptExprClass: case Expr::ArraySubscriptExprClass:
case Expr::MatrixSubscriptExprClass: case Expr::MatrixSubscriptExprClass:
- case Expr::OMPArraySectionExprClass:+ case Expr::ArraySectionExprClass:
case Expr::OMPArrayShapingExprClass: case Expr::OMPArrayShapingExprClass:
case Expr::OMPIteratorExprClass: case Expr::OMPIteratorExprClass:
case Expr::MemberExprClass: case Expr::MemberExprClass:
clang/lib/AST/ExternalASTSource.cpp
@@ -68,7 +68,7 @@ bool ExternalASTSource::layoutRecordType(
return false; return false;
} }
-Decl *ExternalASTSource::GetExternalDecl(Decl::DeclID ID) { return nullptr; }+Decl *ExternalASTSource::GetExternalDecl(GlobalDeclID ID) { return nullptr; }
Selector ExternalASTSource::GetExternalSelector(uint32_t ID) { Selector ExternalASTSource::GetExternalSelector(uint32_t ID) {
return Selector(); return Selector();
clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -110,18 +110,37 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
if (!this->visit(SubExpr)) if (!this->visit(SubExpr))
return false; return false;
- unsigned DerivedOffset = collectBaseOffset(getRecordTy(CE->getType()),+ const auto extractRecordDecl = [](QualType Ty) -> const CXXRecordDecl * {
- getRecordTy(SubExpr->getType()));+ if (const auto *PT = dyn_cast<PointerType>(Ty))
+ return PT->getPointeeType()->getAsCXXRecordDecl();
+ return Ty->getAsCXXRecordDecl();
+ };
- return this->emitGetPtrBasePop(DerivedOffset, CE);+ // FIXME: We can express a series of non-virtual casts as a single
+ // GetPtrBasePop op.
+ QualType CurType = SubExpr->getType();
+ for (const CXXBaseSpecifier *B : CE->path()) {
+ if (B->isVirtual()) {
+ if (!this->emitGetPtrVirtBasePop(extractRecordDecl(B->getType()), CE))
+ return false;
+ CurType = B->getType();
+ } else {
+ unsigned DerivedOffset = collectBaseOffset(B->getType(), CurType);
+ if (!this->emitGetPtrBasePop(DerivedOffset, CE))
+ return false;
+ CurType = B->getType();
+ }
+ }
+
+ return true;
} }
case CK_BaseToDerived: { case CK_BaseToDerived: {
if (!this->visit(SubExpr)) if (!this->visit(SubExpr))
return false; return false;
- unsigned DerivedOffset = collectBaseOffset(getRecordTy(SubExpr->getType()),+ unsigned DerivedOffset =
- getRecordTy(CE->getType()));+ collectBaseOffset(SubExpr->getType(), CE->getType());
return this->emitGetPtrDerivedPop(DerivedOffset, CE); return this->emitGetPtrDerivedPop(DerivedOffset, CE);
} }
@@ -193,6 +212,13 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
if (!this->visit(SubExpr)) if (!this->visit(SubExpr))
return false; return false;
+ // If SubExpr doesn't result in a pointer, make it one.
+ if (PrimType FromT = classifyPrim(SubExpr->getType()); FromT != PT_Ptr) {
+ assert(isPtrType(FromT));
+ if (!this->emitDecayPtr(FromT, PT_Ptr, CE))
+ return false;
+ }
+
PrimType T = classifyPrim(CE->getType()); PrimType T = classifyPrim(CE->getType());
if (T == PT_IntAP) if (T == PT_IntAP)
return this->emitCastPointerIntegralAP(Ctx.getBitWidth(CE->getType()), return this->emitCastPointerIntegralAP(Ctx.getBitWidth(CE->getType()),
@@ -905,8 +931,31 @@ bool ByteCodeExprGen<Emitter>::VisitImplicitValueInitExpr(const ImplicitValueIni
if (std::optional<PrimType> T = classify(QT)) if (std::optional<PrimType> T = classify(QT))
return this->visitZeroInitializer(*T, QT, E); return this->visitZeroInitializer(*T, QT, E);
- if (QT->isRecordType())+ if (QT->isRecordType()) {
- return false;+ const RecordDecl *RD = QT->getAsRecordDecl();
+ assert(RD);
+ if (RD->isInvalidDecl())
+ return false;
+ if (RD->isUnion()) {
+ // C++11 [dcl.init]p5: If T is a (possibly cv-qualified) union type, the
+ // object's first non-static named data member is zero-initialized
+ // FIXME
+ return false;
+ }
+
+ if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
+ CXXRD && CXXRD->getNumVBases() > 0) {
+ // TODO: Diagnose.
+ return false;
+ }
+
+ const Record *R = getRecord(QT);
+ if (!R)
+ return false;
+
+ assert(Initializing);
+ return this->visitZeroRecordInitializer(R, E);
+ }
if (QT->isIncompleteArrayType()) if (QT->isIncompleteArrayType())
return true; return true;
@@ -981,122 +1030,98 @@ bool ByteCodeExprGen<Emitter>::VisitArraySubscriptExpr(
template <class Emitter> template <class Emitter>
bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits, bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
+ const Expr *ArrayFiller,
const Expr *E) { const Expr *E) {
- assert(E->getType()->isRecordType());+ if (E->getType()->isVoidType())
- const Record *R = getRecord(E->getType());+ return this->emitInvalid(E);
- if (Inits.size() == 1 && E->getType() == Inits[0]->getType()) {+ // Handle discarding first.
- return this->visitInitializer(Inits[0]);+ if (DiscardResult) {
+ for (const Expr *Init : Inits) {
+ if (!this->discard(Init))
+ return false;
+ }
+ return true;
} }
- unsigned InitIndex = 0;+ // Primitive values.
- for (const Expr *Init : Inits) {+ if (std::optional<PrimType> T = classify(E->getType())) {
- // Skip unnamed bitfields.+ assert(!DiscardResult);
- while (InitIndex < R->getNumFields() &&+ if (Inits.size() == 0)
- R->getField(InitIndex)->Decl->isUnnamedBitField())+ return this->visitZeroInitializer(*T, E->getType(), E);
- ++InitIndex;+ assert(Inits.size() == 1);
+ return this->delegate(Inits[0]);
+ }
- if (!this->emitDupPtr(E))+ QualType T = E->getType();
- return false;+ if (T->isRecordType()) {
+ const Record *R = getRecord(E->getType());
- if (std::optional<PrimType> T = classify(Init)) {+ if (Inits.size() == 1 && E->getType() == Inits[0]->getType()) {
- const Record::Field *FieldToInit = R->getField(InitIndex);+ return this->visitInitializer(Inits[0]);
- if (!this->visit(Init))+ }
- return false;
- if (FieldToInit->isBitField()) {+ unsigned InitIndex = 0;
- if (!this->emitInitBitField(*T, FieldToInit, E))+ for (const Expr *Init : Inits) {
- return false;+ // Skip unnamed bitfields.
- } else {+ while (InitIndex < R->getNumFields() &&
- if (!this->emitInitField(*T, FieldToInit->Offset, E))+ R->getField(InitIndex)->Decl->isUnnamedBitField())
- return false;+ ++InitIndex;
- }
- if (!this->emitPopPtr(E))+ if (!this->emitDupPtr(E))
return false; return false;
- ++InitIndex;
- } else {
- // Initializer for a direct base class.
- if (const Record::Base *B = R->getBase(Init->getType())) {
- if (!this->emitGetPtrBasePop(B->Offset, Init))
- return false;
-
- if (!this->visitInitializer(Init))
- return false;
- if (!this->emitFinishInitPop(E))+ if (std::optional<PrimType> T = classify(Init)) {
- return false;
- // Base initializers don't increase InitIndex, since they don't count
- // into the Record's fields.
- } else {
const Record::Field *FieldToInit = R->getField(InitIndex); const Record::Field *FieldToInit = R->getField(InitIndex);
- // Non-primitive case. Get a pointer to the field-to-initialize+ if (!this->visit(Init))
- // on the stack and recurse into visitInitializer().
- if (!this->emitGetPtrField(FieldToInit->Offset, Init))
return false; return false;
- if (!this->visitInitializer(Init))+ if (FieldToInit->isBitField()) {
- return false;+ if (!this->emitInitBitField(*T, FieldToInit, E))
+ return false;
+ } else {
+ if (!this->emitInitField(*T, FieldToInit->Offset, E))
+ return false;
+ }
if (!this->emitPopPtr(E)) if (!this->emitPopPtr(E))
return false; return false;
++InitIndex; ++InitIndex;
- }+ } else {
- }+ // Initializer for a direct base class.
- }+ if (const Record::Base *B = R->getBase(Init->getType())) {
- return true;+ if (!this->emitGetPtrBasePop(B->Offset, Init))
-}+ return false;
-/// Pointer to the array(not the element!) must be on the stack when calling+ if (!this->visitInitializer(Init))
-/// this.+ return false;
-template <class Emitter>
-bool ByteCodeExprGen<Emitter>::visitArrayElemInit(unsigned ElemIndex,
- const Expr *Init) {
- if (std::optional<PrimType> T = classify(Init->getType())) {
- // Visit the primitive element like normal.
- if (!this->visit(Init))
- return false;
- return this->emitInitElem(*T, ElemIndex, Init);
- }
- // Advance the pointer currently on the stack to the given+ if (!this->emitFinishInitPop(E))
- // dimension.+ return false;
- if (!this->emitConstUint32(ElemIndex, Init))+ // Base initializers don't increase InitIndex, since they don't count
- return false;+ // into the Record's fields.
- if (!this->emitArrayElemPtrUint32(Init))+ } else {
- return false;+ const Record::Field *FieldToInit = R->getField(InitIndex);
- if (!this->visitInitializer(Init))+ // Non-primitive case. Get a pointer to the field-to-initialize
- return false;+ // on the stack and recurse into visitInitializer().
- return this->emitFinishInitPop(Init);+ if (!this->emitGetPtrField(FieldToInit->Offset, Init))
-}+ return false;
-template <class Emitter>+ if (!this->visitInitializer(Init))
-bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {+ return false;
- // Handle discarding first.+
- if (DiscardResult) {+ if (!this->emitPopPtr(E))
- for (const Expr *Init : E->inits()) {+ return false;
- if (!this->discard(Init))+ ++InitIndex;
- return false;+ }
+ }
} }
return true; return true;
} }
- // Primitive values.
- if (std::optional<PrimType> T = classify(E->getType())) {
- assert(!DiscardResult);
- if (E->getNumInits() == 0)
- return this->visitZeroInitializer(*T, E->getType(), E);
- assert(E->getNumInits() == 1);
- return this->delegate(E->inits()[0]);
- }
-
- QualType T = E->getType();
- if (T->isRecordType())
- return this->visitInitList(E->inits(), E);
-
if (T->isArrayType()) { if (T->isArrayType()) {
unsigned ElementIndex = 0; unsigned ElementIndex = 0;
- for (const Expr *Init : E->inits()) {+ for (const Expr *Init : Inits) {
[diff truncated]