diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 02303c5e6cc570..0da482457ad706 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -86,7 +86,6 @@ clang/test/AST/Interp/ @tbaederr /mlir/**/*VectorToLLVM* @banach-space @dcaballe @nicolasvasilache /mlir/**/*X86Vector* @aartbik @dcaballe @nicolasvasilache /mlir/include/mlir/Dialect/Vector @banach-space @dcaballe @nicolasvasilache -/mlir/include/mlir/Dialect/Vector/IR @kuhar /mlir/lib/Dialect/Vector @banach-space @dcaballe @nicolasvasilache /mlir/lib/Dialect/Vector/Transforms/* @banach-space @dcaballe @hanhanW @nicolasvasilache /mlir/lib/Dialect/Vector/Transforms/VectorEmulateNarrowType.cpp @banach-space @dcaballe @MaheshRavishankar @nicolasvasilache diff --git a/.github/workflows/version-check.yml b/.github/workflows/version-check.yml index 894e07d323ca92..4ce6119a407f52 100644 --- a/.github/workflows/version-check.yml +++ b/.github/workflows/version-check.yml @@ -27,5 +27,5 @@ jobs: - name: Version Check run: | - version=$(grep -o 'LLVM_VERSION_\(MAJOR\|MINOR\|PATCH\) [0-9]\+' cmake/Modules/LLVMVersion.cmake | cut -d ' ' -f 2 | tr "\n" "." | sed 's/.$//g') + version=$(grep -o 'LLVM_VERSION_\(MAJOR\|MINOR\|PATCH\) [0-9]\+' llvm/CMakeLists.txt | cut -d ' ' -f 2 | tr "\n" "." | sed 's/.$//g') .github/workflows/version-check.py "$version" diff --git a/bolt/docs/CommandLineArgumentReference.md b/bolt/docs/CommandLineArgumentReference.md index 0c8935457366db..ea51b77d838a11 100644 --- a/bolt/docs/CommandLineArgumentReference.md +++ b/bolt/docs/CommandLineArgumentReference.md @@ -88,7 +88,7 @@ - `--comp-dir-override=` - Overrides DW_AT_comp_dir, and provides an alternative base location, which is + Overrides DW_AT_comp_dir, and provides an alterantive base location, which is used with DW_AT_dwo_name to construct a path to *.dwo files. - `--create-debug-names-section` diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp index 6a1106f23e4857..83a5484f097ef7 100644 --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -71,7 +71,7 @@ PrintMemData("print-mem-data", cl::opt CompDirOverride( "comp-dir-override", - cl::desc("overrides DW_AT_comp_dir, and provides an alternative base " + cl::desc("overrides DW_AT_comp_dir, and provides an alterantive base " "location, which is used with DW_AT_dwo_name to construct a path " "to *.dwo files."), cl::Hidden, cl::init(""), cl::cat(BoltCategory)); diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp index 1ec216b39e95c3..ccb45f40c5c7ac 100644 --- a/bolt/lib/Rewrite/DWARFRewriter.cpp +++ b/bolt/lib/Rewrite/DWARFRewriter.cpp @@ -620,9 +620,10 @@ void DWARFRewriter::updateDebugInfo() { uint32_t CUIndex = 0; std::mutex AccessMutex; // Needs to be invoked in the same order as CUs are processed. - auto createRangeLocListAddressWriters = - [&](DWARFUnit &CU) -> DebugLocWriter * { + llvm::DenseMap LocListWritersIndexByCU; + auto createRangeLocListAddressWriters = [&](DWARFUnit &CU) { std::lock_guard Lock(AccessMutex); + const uint16_t DwarfVersion = CU.getVersion(); if (DwarfVersion >= 5) { auto AddrW = std::make_unique( @@ -641,7 +642,6 @@ void DWARFRewriter::updateDebugInfo() { RangeListsWritersByCU[*DWOId] = std::move(DWORangeListsSectionWriter); } AddressWritersByCU[CU.getOffset()] = std::move(AddrW); - } else { auto AddrW = std::make_unique(&BC, CU.getAddressByteSize()); @@ -657,7 +657,7 @@ void DWARFRewriter::updateDebugInfo() { std::move(LegacyRangesSectionWriterByCU); } } - return LocListWritersByCU[CUIndex++].get(); + LocListWritersIndexByCU[CU.getOffset()] = CUIndex++; }; DWARF5AcceleratorTable DebugNamesTable(opts::CreateDebugNames, BC, @@ -666,74 +666,68 @@ void DWARFRewriter::updateDebugInfo() { DWPState State; if (opts::WriteDWP) initDWPState(State); - auto processUnitDIE = [&](DWARFUnit *Unit, DIEBuilder *DIEBlder) { - // Check if the unit is a skeleton and we need special updates for it and - // its matching split/DWO CU. - std::optional SplitCU; + auto processSplitCU = [&](DWARFUnit &Unit, DWARFUnit &SplitCU, + DIEBuilder &DIEBlder, + DebugRangesSectionWriter &TempRangesSectionWriter, + DebugAddrWriter &AddressWriter) { + DIEBuilder DWODIEBuilder(BC, &(SplitCU).getContext(), DebugNamesTable, + &Unit); + DWODIEBuilder.buildDWOUnit(SplitCU); + std::string DWOName = ""; + std::optional DwarfOutputPath = + opts::DwarfOutputPath.empty() + ? std::nullopt + : std::optional(opts::DwarfOutputPath.c_str()); + { + std::lock_guard Lock(AccessMutex); + DWOName = DIEBlder.updateDWONameCompDir( + *StrOffstsWriter, *StrWriter, Unit, DwarfOutputPath, std::nullopt); + } + DebugStrOffsetsWriter DWOStrOffstsWriter(BC); + DebugStrWriter DWOStrWriter((SplitCU).getContext(), true); + DWODIEBuilder.updateDWONameCompDirForTypes( + DWOStrOffstsWriter, DWOStrWriter, SplitCU, DwarfOutputPath, DWOName); + DebugLoclistWriter DebugLocDWoWriter(Unit, Unit.getVersion(), true, + AddressWriter); + + updateUnitDebugInfo(SplitCU, DWODIEBuilder, DebugLocDWoWriter, + TempRangesSectionWriter, AddressWriter); + DebugLocDWoWriter.finalize(DWODIEBuilder, + *DWODIEBuilder.getUnitDIEbyUnit(SplitCU)); + if (Unit.getVersion() >= 5) + TempRangesSectionWriter.finalizeSection(); + + emitDWOBuilder(DWOName, DWODIEBuilder, *this, SplitCU, Unit, State, + DebugLocDWoWriter, DWOStrOffstsWriter, DWOStrWriter, + GDBIndexSection); + }; + auto processMainBinaryCU = [&](DWARFUnit &Unit, DIEBuilder &DIEBlder) { + DebugAddrWriter &AddressWriter = + *AddressWritersByCU[Unit.getOffset()].get(); + DebugRangesSectionWriter &RangesSectionWriter = + Unit.getVersion() >= 5 ? *RangeListsSectionWriter.get() + : *LegacyRangesSectionWriter.get(); + DebugLocWriter &DebugLocWriter = + *LocListWritersByCU[LocListWritersIndexByCU[Unit.getOffset()]].get(); std::optional RangesBase; - std::optional DWOId = Unit->getDWOId(); + std::optional SplitCU; + std::optional DWOId = Unit.getDWOId(); if (DWOId) SplitCU = BC.getDWOCU(*DWOId); - DebugLocWriter *DebugLocWriter = createRangeLocListAddressWriters(*Unit); - DebugRangesSectionWriter *RangesSectionWriter = - Unit->getVersion() >= 5 ? RangeListsSectionWriter.get() - : LegacyRangesSectionWriter.get(); - DebugAddrWriter *AddressWriter = - AddressWritersByCU[Unit->getOffset()].get(); - // Skipping CUs that failed to load. - if (SplitCU) { - DIEBuilder DWODIEBuilder(BC, &(*SplitCU)->getContext(), DebugNamesTable, - Unit); - DWODIEBuilder.buildDWOUnit(**SplitCU); - std::string DWOName = ""; - std::optional DwarfOutputPath = - opts::DwarfOutputPath.empty() - ? std::nullopt - : std::optional(opts::DwarfOutputPath.c_str()); - { - std::lock_guard Lock(AccessMutex); - DWOName = DIEBlder->updateDWONameCompDir( - *StrOffstsWriter, *StrWriter, *Unit, DwarfOutputPath, std::nullopt); - } - DebugStrOffsetsWriter DWOStrOffstsWriter(BC); - DebugStrWriter DWOStrWriter((*SplitCU)->getContext(), true); - DWODIEBuilder.updateDWONameCompDirForTypes(DWOStrOffstsWriter, - DWOStrWriter, **SplitCU, - DwarfOutputPath, DWOName); - DebugLoclistWriter DebugLocDWoWriter(*Unit, Unit->getVersion(), true, - *AddressWriter); - DebugRangesSectionWriter *TempRangesSectionWriter = RangesSectionWriter; - if (Unit->getVersion() >= 5) { - TempRangesSectionWriter = RangeListsWritersByCU[*DWOId].get(); - } else { - TempRangesSectionWriter = LegacyRangesWritersByCU[*DWOId].get(); - RangesBase = RangesSectionWriter->getSectionOffset(); - } - - updateUnitDebugInfo(*(*SplitCU), DWODIEBuilder, DebugLocDWoWriter, - *TempRangesSectionWriter, *AddressWriter); - DebugLocDWoWriter.finalize(DWODIEBuilder, - *DWODIEBuilder.getUnitDIEbyUnit(**SplitCU)); - if (Unit->getVersion() >= 5) - TempRangesSectionWriter->finalizeSection(); - - emitDWOBuilder(DWOName, DWODIEBuilder, *this, **SplitCU, *Unit, State, - DebugLocDWoWriter, DWOStrOffstsWriter, DWOStrWriter, - GDBIndexSection); - } - - if (Unit->getVersion() >= 5) { - RangesBase = RangesSectionWriter->getSectionOffset() + + if (Unit.getVersion() >= 5) { + RangesBase = RangesSectionWriter.getSectionOffset() + getDWARF5RngListLocListHeaderSize(); - RangesSectionWriter->initSection(*Unit); - StrOffstsWriter->finalizeSection(*Unit, *DIEBlder); + RangesSectionWriter.initSection(Unit); + StrOffstsWriter->finalizeSection(Unit, DIEBlder); + } else if (SplitCU) { + RangesBase = LegacyRangesSectionWriter.get()->getSectionOffset(); } - updateUnitDebugInfo(*Unit, *DIEBlder, *DebugLocWriter, *RangesSectionWriter, - *AddressWriter, RangesBase); - DebugLocWriter->finalize(*DIEBlder, *DIEBlder->getUnitDIEbyUnit(*Unit)); - if (Unit->getVersion() >= 5) - RangesSectionWriter->finalizeSection(); + updateUnitDebugInfo(Unit, DIEBlder, DebugLocWriter, RangesSectionWriter, + AddressWriter, RangesBase); + DebugLocWriter.finalize(DIEBlder, *DIEBlder.getUnitDIEbyUnit(Unit)); + if (Unit.getVersion() >= 5) + RangesSectionWriter.finalizeSection(); }; DIEBuilder DIEBlder(BC, BC.DwCtx.get(), DebugNamesTable); @@ -751,8 +745,24 @@ void DWARFRewriter::updateDebugInfo() { CUPartitionVector PartVec = partitionCUs(*BC.DwCtx); for (std::vector &Vec : PartVec) { DIEBlder.buildCompileUnits(Vec); + for (DWARFUnit *CU : DIEBlder.getProcessedCUs()) { + createRangeLocListAddressWriters(*CU); + std::optional SplitCU; + std::optional DWOId = CU->getDWOId(); + if (DWOId) + SplitCU = BC.getDWOCU(*DWOId); + if (!SplitCU) + continue; + DebugAddrWriter &AddressWriter = + *AddressWritersByCU[CU->getOffset()].get(); + DebugRangesSectionWriter *TempRangesSectionWriter = + CU->getVersion() >= 5 ? RangeListsWritersByCU[*DWOId].get() + : LegacyRangesWritersByCU[*DWOId].get(); + processSplitCU(*CU, **SplitCU, DIEBlder, *TempRangesSectionWriter, + AddressWriter); + } for (DWARFUnit *CU : DIEBlder.getProcessedCUs()) - processUnitDIE(CU, &DIEBlder); + processMainBinaryCU(*CU, DIEBlder); finalizeCompileUnits(DIEBlder, *Streamer, OffsetMap, DIEBlder.getProcessedCUs(), *FinalAddrWriter); } diff --git a/clang-tools-extra/clang-tidy/add_new_check.py b/clang-tools-extra/clang-tidy/add_new_check.py index 3a62df1f510bac..3b14d5d158d2d0 100755 --- a/clang-tools-extra/clang-tidy/add_new_check.py +++ b/clang-tools-extra/clang-tidy/add_new_check.py @@ -552,8 +552,8 @@ def format_link_alias(doc_file): f.write(' :header: "Name", "Offers fixes"\n\n') f.writelines(checks) # and the aliases - f.write("\nCheck aliases\n-------------\n\n") - f.write(".. csv-table::\n") + f.write("\n\n") + f.write(".. csv-table:: Aliases..\n") f.write(' :header: "Name", "Redirect", "Offers fixes"\n\n') f.writelines(checks_alias) break diff --git a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp index 8b5be9cd95f767..ffb62b409b29bc 100644 --- a/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp @@ -49,183 +49,183 @@ namespace { // with NULL argument and in this case the check is not applicable: // `mblen, mbrlen, mbrtowc, mbtowc, wctomb, wctomb_s`. // FIXME: The check can be improved to handle such cases. -const llvm::StringRef CertErr33CCheckedFunctions = "^::aligned_alloc;" - "^::asctime_s;" - "^::at_quick_exit;" - "^::atexit;" - "^::bsearch;" - "^::bsearch_s;" - "^::btowc;" - "^::c16rtomb;" - "^::c32rtomb;" - "^::calloc;" - "^::clock;" - "^::cnd_broadcast;" - "^::cnd_init;" - "^::cnd_signal;" - "^::cnd_timedwait;" - "^::cnd_wait;" - "^::ctime_s;" - "^::fclose;" - "^::fflush;" - "^::fgetc;" - "^::fgetpos;" - "^::fgets;" - "^::fgetwc;" - "^::fopen;" - "^::fopen_s;" - "^::fprintf;" - "^::fprintf_s;" - "^::fputc;" - "^::fputs;" - "^::fputwc;" - "^::fputws;" - "^::fread;" - "^::freopen;" - "^::freopen_s;" - "^::fscanf;" - "^::fscanf_s;" - "^::fseek;" - "^::fsetpos;" - "^::ftell;" - "^::fwprintf;" - "^::fwprintf_s;" - "^::fwrite;" - "^::fwscanf;" - "^::fwscanf_s;" - "^::getc;" - "^::getchar;" - "^::getenv;" - "^::getenv_s;" - "^::gets_s;" - "^::getwc;" - "^::getwchar;" - "^::gmtime;" - "^::gmtime_s;" - "^::localtime;" - "^::localtime_s;" - "^::malloc;" - "^::mbrtoc16;" - "^::mbrtoc32;" - "^::mbsrtowcs;" - "^::mbsrtowcs_s;" - "^::mbstowcs;" - "^::mbstowcs_s;" - "^::memchr;" - "^::mktime;" - "^::mtx_init;" - "^::mtx_lock;" - "^::mtx_timedlock;" - "^::mtx_trylock;" - "^::mtx_unlock;" - "^::printf_s;" - "^::putc;" - "^::putwc;" - "^::raise;" - "^::realloc;" - "^::remove;" - "^::rename;" - "^::scanf;" - "^::scanf_s;" - "^::setlocale;" - "^::setvbuf;" - "^::signal;" - "^::snprintf;" - "^::snprintf_s;" - "^::sprintf;" - "^::sprintf_s;" - "^::sscanf;" - "^::sscanf_s;" - "^::strchr;" - "^::strerror_s;" - "^::strftime;" - "^::strpbrk;" - "^::strrchr;" - "^::strstr;" - "^::strtod;" - "^::strtof;" - "^::strtoimax;" - "^::strtok;" - "^::strtok_s;" - "^::strtol;" - "^::strtold;" - "^::strtoll;" - "^::strtoul;" - "^::strtoull;" - "^::strtoumax;" - "^::strxfrm;" - "^::swprintf;" - "^::swprintf_s;" - "^::swscanf;" - "^::swscanf_s;" - "^::thrd_create;" - "^::thrd_detach;" - "^::thrd_join;" - "^::thrd_sleep;" - "^::time;" - "^::timespec_get;" - "^::tmpfile;" - "^::tmpfile_s;" - "^::tmpnam;" - "^::tmpnam_s;" - "^::tss_create;" - "^::tss_get;" - "^::tss_set;" - "^::ungetc;" - "^::ungetwc;" - "^::vfprintf;" - "^::vfprintf_s;" - "^::vfscanf;" - "^::vfscanf_s;" - "^::vfwprintf;" - "^::vfwprintf_s;" - "^::vfwscanf;" - "^::vfwscanf_s;" - "^::vprintf_s;" - "^::vscanf;" - "^::vscanf_s;" - "^::vsnprintf;" - "^::vsnprintf_s;" - "^::vsprintf;" - "^::vsprintf_s;" - "^::vsscanf;" - "^::vsscanf_s;" - "^::vswprintf;" - "^::vswprintf_s;" - "^::vswscanf;" - "^::vswscanf_s;" - "^::vwprintf_s;" - "^::vwscanf;" - "^::vwscanf_s;" - "^::wcrtomb;" - "^::wcschr;" - "^::wcsftime;" - "^::wcspbrk;" - "^::wcsrchr;" - "^::wcsrtombs;" - "^::wcsrtombs_s;" - "^::wcsstr;" - "^::wcstod;" - "^::wcstof;" - "^::wcstoimax;" - "^::wcstok;" - "^::wcstok_s;" - "^::wcstol;" - "^::wcstold;" - "^::wcstoll;" - "^::wcstombs;" - "^::wcstombs_s;" - "^::wcstoul;" - "^::wcstoull;" - "^::wcstoumax;" - "^::wcsxfrm;" - "^::wctob;" - "^::wctrans;" - "^::wctype;" - "^::wmemchr;" - "^::wprintf_s;" - "^::wscanf;" - "^::wscanf_s;"; +const llvm::StringRef CertErr33CCheckedFunctions = "::aligned_alloc;" + "::asctime_s;" + "::at_quick_exit;" + "::atexit;" + "::bsearch;" + "::bsearch_s;" + "::btowc;" + "::c16rtomb;" + "::c32rtomb;" + "::calloc;" + "::clock;" + "::cnd_broadcast;" + "::cnd_init;" + "::cnd_signal;" + "::cnd_timedwait;" + "::cnd_wait;" + "::ctime_s;" + "::fclose;" + "::fflush;" + "::fgetc;" + "::fgetpos;" + "::fgets;" + "::fgetwc;" + "::fopen;" + "::fopen_s;" + "::fprintf;" + "::fprintf_s;" + "::fputc;" + "::fputs;" + "::fputwc;" + "::fputws;" + "::fread;" + "::freopen;" + "::freopen_s;" + "::fscanf;" + "::fscanf_s;" + "::fseek;" + "::fsetpos;" + "::ftell;" + "::fwprintf;" + "::fwprintf_s;" + "::fwrite;" + "::fwscanf;" + "::fwscanf_s;" + "::getc;" + "::getchar;" + "::getenv;" + "::getenv_s;" + "::gets_s;" + "::getwc;" + "::getwchar;" + "::gmtime;" + "::gmtime_s;" + "::localtime;" + "::localtime_s;" + "::malloc;" + "::mbrtoc16;" + "::mbrtoc32;" + "::mbsrtowcs;" + "::mbsrtowcs_s;" + "::mbstowcs;" + "::mbstowcs_s;" + "::memchr;" + "::mktime;" + "::mtx_init;" + "::mtx_lock;" + "::mtx_timedlock;" + "::mtx_trylock;" + "::mtx_unlock;" + "::printf_s;" + "::putc;" + "::putwc;" + "::raise;" + "::realloc;" + "::remove;" + "::rename;" + "::scanf;" + "::scanf_s;" + "::setlocale;" + "::setvbuf;" + "::signal;" + "::snprintf;" + "::snprintf_s;" + "::sprintf;" + "::sprintf_s;" + "::sscanf;" + "::sscanf_s;" + "::strchr;" + "::strerror_s;" + "::strftime;" + "::strpbrk;" + "::strrchr;" + "::strstr;" + "::strtod;" + "::strtof;" + "::strtoimax;" + "::strtok;" + "::strtok_s;" + "::strtol;" + "::strtold;" + "::strtoll;" + "::strtoul;" + "::strtoull;" + "::strtoumax;" + "::strxfrm;" + "::swprintf;" + "::swprintf_s;" + "::swscanf;" + "::swscanf_s;" + "::thrd_create;" + "::thrd_detach;" + "::thrd_join;" + "::thrd_sleep;" + "::time;" + "::timespec_get;" + "::tmpfile;" + "::tmpfile_s;" + "::tmpnam;" + "::tmpnam_s;" + "::tss_create;" + "::tss_get;" + "::tss_set;" + "::ungetc;" + "::ungetwc;" + "::vfprintf;" + "::vfprintf_s;" + "::vfscanf;" + "::vfscanf_s;" + "::vfwprintf;" + "::vfwprintf_s;" + "::vfwscanf;" + "::vfwscanf_s;" + "::vprintf_s;" + "::vscanf;" + "::vscanf_s;" + "::vsnprintf;" + "::vsnprintf_s;" + "::vsprintf;" + "::vsprintf_s;" + "::vsscanf;" + "::vsscanf_s;" + "::vswprintf;" + "::vswprintf_s;" + "::vswscanf;" + "::vswscanf_s;" + "::vwprintf_s;" + "::vwscanf;" + "::vwscanf_s;" + "::wcrtomb;" + "::wcschr;" + "::wcsftime;" + "::wcspbrk;" + "::wcsrchr;" + "::wcsrtombs;" + "::wcsrtombs_s;" + "::wcsstr;" + "::wcstod;" + "::wcstof;" + "::wcstoimax;" + "::wcstok;" + "::wcstok_s;" + "::wcstol;" + "::wcstold;" + "::wcstoll;" + "::wcstombs;" + "::wcstombs_s;" + "::wcstoul;" + "::wcstoull;" + "::wcstoumax;" + "::wcsxfrm;" + "::wctob;" + "::wctrans;" + "::wctype;" + "::wmemchr;" + "::wprintf_s;" + "::wscanf;" + "::wscanf_s;"; } // namespace diff --git a/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp b/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp index e20cf6fbcb55a7..8b500de0c028c4 100644 --- a/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.cpp @@ -93,12 +93,13 @@ void ConstCorrectnessCheck::registerMatchers(MatchFinder *Finder) { // shall be run. const auto FunctionScope = functionDecl( - hasBody(stmt(forEachDescendant( - declStmt(containsAnyDeclaration( - LocalValDecl.bind("local-value")), - unless(has(decompositionDecl()))) - .bind("decl-stmt"))) - .bind("scope"))) + hasBody( + compoundStmt(forEachDescendant( + declStmt(containsAnyDeclaration( + LocalValDecl.bind("local-value")), + unless(has(decompositionDecl()))) + .bind("decl-stmt"))) + .bind("scope"))) .bind("function-decl"); Finder->addMatcher(FunctionScope, this); @@ -108,7 +109,7 @@ void ConstCorrectnessCheck::registerMatchers(MatchFinder *Finder) { enum class VariableCategory { Value, Reference, Pointer }; void ConstCorrectnessCheck::check(const MatchFinder::MatchResult &Result) { - const auto *LocalScope = Result.Nodes.getNodeAs("scope"); + const auto *LocalScope = Result.Nodes.getNodeAs("scope"); const auto *Variable = Result.Nodes.getNodeAs("local-value"); const auto *Function = Result.Nodes.getNodeAs("function-decl"); @@ -197,7 +198,7 @@ void ConstCorrectnessCheck::check(const MatchFinder::MatchResult &Result) { } } -void ConstCorrectnessCheck::registerScope(const Stmt *LocalScope, +void ConstCorrectnessCheck::registerScope(const CompoundStmt *LocalScope, ASTContext *Context) { auto &Analyzer = ScopesCache[LocalScope]; if (!Analyzer) diff --git a/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.h b/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.h index bba060e555d001..08ffde524522a0 100644 --- a/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.h +++ b/clang-tools-extra/clang-tidy/misc/ConstCorrectnessCheck.h @@ -32,10 +32,10 @@ class ConstCorrectnessCheck : public ClangTidyCheck { void check(const ast_matchers::MatchFinder::MatchResult &Result) override; private: - void registerScope(const Stmt *LocalScope, ASTContext *Context); + void registerScope(const CompoundStmt *LocalScope, ASTContext *Context); using MutationAnalyzer = std::unique_ptr; - llvm::DenseMap ScopesCache; + llvm::DenseMap ScopesCache; llvm::DenseSet TemplateDiagnosticsCache; const bool AnalyzeValues; diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp index 3a255c5c133f1d..5a4c2363bd8af0 100644 --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp @@ -119,72 +119,65 @@ void UnnecessaryValueParamCheck::check(const MatchFinder::MatchResult &Result) { } } - handleConstRefFix(*Function, *Param, *Result.Context); -} - -void UnnecessaryValueParamCheck::registerPPCallbacks( - const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) { - Inserter.registerPreprocessor(PP); -} - -void UnnecessaryValueParamCheck::storeOptions( - ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "IncludeStyle", Inserter.getStyle()); - Options.store(Opts, "AllowedTypes", - utils::options::serializeStringList(AllowedTypes)); -} - -void UnnecessaryValueParamCheck::onEndOfTranslationUnit() { - MutationAnalyzerCache.clear(); -} - -void UnnecessaryValueParamCheck::handleConstRefFix(const FunctionDecl &Function, - const ParmVarDecl &Param, - ASTContext &Context) { - const size_t Index = - llvm::find(Function.parameters(), &Param) - Function.parameters().begin(); - const bool IsConstQualified = - Param.getType().getCanonicalType().isConstQualified(); + const size_t Index = llvm::find(Function->parameters(), Param) - + Function->parameters().begin(); auto Diag = - diag(Param.getLocation(), + diag(Param->getLocation(), "the %select{|const qualified }0parameter %1 is copied for each " "invocation%select{ but only used as a const reference|}0; consider " "making it a %select{const |}0reference") - << IsConstQualified << paramNameOrIndex(Param.getName(), Index); + << IsConstQualified << paramNameOrIndex(Param->getName(), Index); // Do not propose fixes when: // 1. the ParmVarDecl is in a macro, since we cannot place them correctly // 2. the function is virtual as it might break overrides // 3. the function is referenced outside of a call expression within the // compilation unit as the signature change could introduce build errors. // 4. the function is an explicit template/ specialization. - const auto *Method = llvm::dyn_cast(&Function); - if (Param.getBeginLoc().isMacroID() || (Method && Method->isVirtual()) || - isReferencedOutsideOfCallExpr(Function, Context) || - Function.getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + const auto *Method = llvm::dyn_cast(Function); + if (Param->getBeginLoc().isMacroID() || (Method && Method->isVirtual()) || + isReferencedOutsideOfCallExpr(*Function, *Result.Context) || + Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) return; - for (const auto *FunctionDecl = &Function; FunctionDecl != nullptr; + for (const auto *FunctionDecl = Function; FunctionDecl != nullptr; FunctionDecl = FunctionDecl->getPreviousDecl()) { const auto &CurrentParam = *FunctionDecl->getParamDecl(Index); - Diag << utils::fixit::changeVarDeclToReference(CurrentParam, Context); + Diag << utils::fixit::changeVarDeclToReference(CurrentParam, + *Result.Context); // The parameter of each declaration needs to be checked individually as to // whether it is const or not as constness can differ between definition and // declaration. if (!CurrentParam.getType().getCanonicalType().isConstQualified()) { if (std::optional Fix = utils::fixit::addQualifierToVarDecl( - CurrentParam, Context, DeclSpec::TQ::TQ_const)) + CurrentParam, *Result.Context, DeclSpec::TQ::TQ_const)) Diag << *Fix; } } } -void UnnecessaryValueParamCheck::handleMoveFix(const ParmVarDecl &Param, +void UnnecessaryValueParamCheck::registerPPCallbacks( + const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) { + Inserter.registerPreprocessor(PP); +} + +void UnnecessaryValueParamCheck::storeOptions( + ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "IncludeStyle", Inserter.getStyle()); + Options.store(Opts, "AllowedTypes", + utils::options::serializeStringList(AllowedTypes)); +} + +void UnnecessaryValueParamCheck::onEndOfTranslationUnit() { + MutationAnalyzerCache.clear(); +} + +void UnnecessaryValueParamCheck::handleMoveFix(const ParmVarDecl &Var, const DeclRefExpr &CopyArgument, - ASTContext &Context) { + const ASTContext &Context) { auto Diag = diag(CopyArgument.getBeginLoc(), "parameter %0 is passed by value and only copied once; " "consider moving it to avoid unnecessary copies") - << &Param; + << &Var; // Do not propose fixes in macros since we cannot place them correctly. if (CopyArgument.getBeginLoc().isMacroID()) return; diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.h b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.h index 8bfd814d163571..7250bffd20b2f9 100644 --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.h +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.h @@ -33,16 +33,10 @@ class UnnecessaryValueParamCheck : public ClangTidyCheck { void storeOptions(ClangTidyOptions::OptionMap &Opts) override; void onEndOfTranslationUnit() override; -protected: - // Create diagnostics. These are virtual so that derived classes can change - // behaviour. - virtual void handleMoveFix(const ParmVarDecl &Param, - const DeclRefExpr &CopyArgument, - ASTContext &Context); - virtual void handleConstRefFix(const FunctionDecl &Function, - const ParmVarDecl &Param, ASTContext &Context); - private: + void handleMoveFix(const ParmVarDecl &Var, const DeclRefExpr &CopyArgument, + const ASTContext &Context); + ExprMutationAnalyzer::Memoized MutationAnalyzerCache; utils::IncludeInserter Inserter; const std::vector AllowedTypes; diff --git a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py index 48401ba5ea42a9..0dc35ad5873629 100755 --- a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py +++ b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py @@ -34,32 +34,29 @@ http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html """ +from __future__ import print_function + import argparse -import asyncio -from dataclasses import dataclass import glob import json import multiprocessing import os +import queue import re import shutil import subprocess import sys import tempfile -import time +import threading import traceback -from types import ModuleType -from typing import Any, Awaitable, Callable, List, Optional, Tuple, TypeVar - -yaml: Optional[ModuleType] = None try: import yaml except ImportError: yaml = None -def strtobool(val: str) -> bool: +def strtobool(val): """Convert a string representation of truth to a bool following LLVM's CLI argument parsing.""" val = val.lower() @@ -70,11 +67,11 @@ def strtobool(val: str) -> bool: # Return ArgumentTypeError so that argparse does not substitute its own error message raise argparse.ArgumentTypeError( - f"'{val}' is invalid value for boolean argument! Try 0 or 1." + "'{}' is invalid value for boolean argument! Try 0 or 1.".format(val) ) -def find_compilation_database(path: str) -> str: +def find_compilation_database(path): """Adjusts the directory until a compilation database is found.""" result = os.path.realpath("./") while not os.path.isfile(os.path.join(result, path)): @@ -86,43 +83,49 @@ def find_compilation_database(path: str) -> str: return result +def make_absolute(f, directory): + if os.path.isabs(f): + return f + return os.path.normpath(os.path.join(directory, f)) + + def get_tidy_invocation( - f: str, - clang_tidy_binary: str, - checks: str, - tmpdir: Optional[str], - build_path: str, - header_filter: Optional[str], - allow_enabling_alpha_checkers: bool, - extra_arg: List[str], - extra_arg_before: List[str], - quiet: bool, - config_file_path: str, - config: str, - line_filter: Optional[str], - use_color: bool, - plugins: List[str], - warnings_as_errors: Optional[str], - exclude_header_filter: Optional[str], - allow_no_checks: bool, -) -> List[str]: + f, + clang_tidy_binary, + checks, + tmpdir, + build_path, + header_filter, + allow_enabling_alpha_checkers, + extra_arg, + extra_arg_before, + quiet, + config_file_path, + config, + line_filter, + use_color, + plugins, + warnings_as_errors, + exclude_header_filter, + allow_no_checks, +): """Gets a command line for clang-tidy.""" start = [clang_tidy_binary] if allow_enabling_alpha_checkers: start.append("-allow-enabling-analyzer-alpha-checkers") if exclude_header_filter is not None: - start.append(f"--exclude-header-filter={exclude_header_filter}") + start.append("--exclude-header-filter=" + exclude_header_filter) if header_filter is not None: - start.append(f"-header-filter={header_filter}") + start.append("-header-filter=" + header_filter) if line_filter is not None: - start.append(f"-line-filter={line_filter}") + start.append("-line-filter=" + line_filter) if use_color is not None: if use_color: start.append("--use-color") else: start.append("--use-color=false") if checks: - start.append(f"-checks={checks}") + start.append("-checks=" + checks) if tmpdir is not None: start.append("-export-fixes") # Get a temporary file. We immediately close the handle so clang-tidy can @@ -131,29 +134,28 @@ def get_tidy_invocation( os.close(handle) start.append(name) for arg in extra_arg: - start.append(f"-extra-arg={arg}") + start.append("-extra-arg=%s" % arg) for arg in extra_arg_before: - start.append(f"-extra-arg-before={arg}") - start.append(f"-p={build_path}") + start.append("-extra-arg-before=%s" % arg) + start.append("-p=" + build_path) if quiet: start.append("-quiet") if config_file_path: - start.append(f"--config-file={config_file_path}") + start.append("--config-file=" + config_file_path) elif config: - start.append(f"-config={config}") + start.append("-config=" + config) for plugin in plugins: - start.append(f"-load={plugin}") + start.append("-load=" + plugin) if warnings_as_errors: - start.append(f"--warnings-as-errors={warnings_as_errors}") + start.append("--warnings-as-errors=" + warnings_as_errors) if allow_no_checks: start.append("--allow-no-checks") start.append(f) return start -def merge_replacement_files(tmpdir: str, mergefile: str) -> None: +def merge_replacement_files(tmpdir, mergefile): """Merge all replacement files in a directory into a single file""" - assert yaml # The fixes suggested by clang-tidy >= 4.0.0 are given under # the top level key 'Diagnostics' in the output yaml files mergekey = "Diagnostics" @@ -177,14 +179,16 @@ def merge_replacement_files(tmpdir: str, mergefile: str) -> None: open(mergefile, "w").close() -def find_binary(arg: str, name: str, build_path: str) -> str: +def find_binary(arg, name, build_path): """Get the path for a binary or exit""" if arg: if shutil.which(arg): return arg else: raise SystemExit( - f"error: passed binary '{arg}' was not found or is not executable" + "error: passed binary '{}' was not found or is not executable".format( + arg + ) ) built_path = os.path.join(build_path, "bin", name) @@ -192,102 +196,66 @@ def find_binary(arg: str, name: str, build_path: str) -> str: if binary: return binary else: - raise SystemExit(f"error: failed to find {name} in $PATH or at {built_path}") + raise SystemExit( + "error: failed to find {} in $PATH or at {}".format(name, built_path) + ) -def apply_fixes( - args: argparse.Namespace, clang_apply_replacements_binary: str, tmpdir: str -) -> None: +def apply_fixes(args, clang_apply_replacements_binary, tmpdir): """Calls clang-apply-fixes on a given directory.""" invocation = [clang_apply_replacements_binary] invocation.append("-ignore-insert-conflict") if args.format: invocation.append("-format") if args.style: - invocation.append(f"-style={args.style}") + invocation.append("-style=" + args.style) invocation.append(tmpdir) subprocess.call(invocation) -# FIXME Python 3.12: This can be simplified out with run_with_semaphore[T](...). -T = TypeVar("T") - - -async def run_with_semaphore( - semaphore: asyncio.Semaphore, - f: Callable[..., Awaitable[T]], - *args: Any, - **kwargs: Any, -) -> T: - async with semaphore: - return await f(*args, **kwargs) - - -@dataclass -class ClangTidyResult: - filename: str - invocation: List[str] - returncode: int - stdout: str - stderr: str - elapsed: float - - -async def run_tidy( - args: argparse.Namespace, - name: str, - clang_tidy_binary: str, - tmpdir: str, - build_path: str, -) -> ClangTidyResult: - """ - Runs clang-tidy on a single file and returns the result. - """ - invocation = get_tidy_invocation( - name, - clang_tidy_binary, - args.checks, - tmpdir, - build_path, - args.header_filter, - args.allow_enabling_alpha_checkers, - args.extra_arg, - args.extra_arg_before, - args.quiet, - args.config_file, - args.config, - args.line_filter, - args.use_color, - args.plugins, - args.warnings_as_errors, - args.exclude_header_filter, - args.allow_no_checks, - ) - - try: - process = await asyncio.create_subprocess_exec( - *invocation, stdout=subprocess.PIPE, stderr=subprocess.PIPE +def run_tidy(args, clang_tidy_binary, tmpdir, build_path, queue, lock, failed_files): + """Takes filenames out of queue and runs clang-tidy on them.""" + while True: + name = queue.get() + invocation = get_tidy_invocation( + name, + clang_tidy_binary, + args.checks, + tmpdir, + build_path, + args.header_filter, + args.allow_enabling_alpha_checkers, + args.extra_arg, + args.extra_arg_before, + args.quiet, + args.config_file, + args.config, + args.line_filter, + args.use_color, + args.plugins, + args.warnings_as_errors, + args.exclude_header_filter, + args.allow_no_checks, ) - start = time.time() - stdout, stderr = await process.communicate() - end = time.time() - except asyncio.CancelledError: - process.terminate() - await process.wait() - raise - - assert process.returncode is not None - return ClangTidyResult( - name, - invocation, - process.returncode, - stdout.decode("UTF-8"), - stderr.decode("UTF-8"), - end - start, - ) - -async def main() -> None: + proc = subprocess.Popen( + invocation, stdout=subprocess.PIPE, stderr=subprocess.PIPE + ) + output, err = proc.communicate() + if proc.returncode != 0: + if proc.returncode < 0: + msg = "%s: terminated by signal %d\n" % (name, -proc.returncode) + err += msg.encode("utf-8") + failed_files.append(name) + with lock: + sys.stdout.write(" ".join(invocation) + "\n" + output.decode("utf-8")) + if len(err) > 0: + sys.stdout.flush() + sys.stderr.write(err.decode("utf-8")) + queue.task_done() + + +def main(): parser = argparse.ArgumentParser( description="Runs clang-tidy over all files " "in a compilation database. Requires " @@ -464,7 +432,7 @@ async def main() -> None: ) combine_fixes = False - export_fixes_dir: Optional[str] = None + export_fixes_dir = None delete_fixes_dir = False if args.export_fixes is not None: # if a directory is given, create it if it does not exist @@ -522,10 +490,10 @@ async def main() -> None: sys.exit(1) # Load the database and extract all files. - with open(os.path.join(build_path, db_path)) as f: - database = json.load(f) - files = {os.path.abspath(os.path.join(e["directory"], e["file"])) for e in database} - number_files_in_database = len(files) + database = json.load(open(os.path.join(build_path, db_path))) + files = set( + [make_absolute(entry["file"], entry["directory"]) for entry in database] + ) # Filter source files from compilation database. if args.source_filter: @@ -546,81 +514,70 @@ async def main() -> None: # Build up a big regexy filter from all command line arguments. file_name_re = re.compile("|".join(args.files)) - files = {f for f in files if file_name_re.search(f)} - - print( - "Running clang-tidy for", - len(files), - "files out of", - number_files_in_database, - "in compilation database ...", - ) - - returncode = 0 - semaphore = asyncio.Semaphore(max_task) - tasks = [ - asyncio.create_task( - run_with_semaphore( - semaphore, - run_tidy, - args, - f, - clang_tidy_binary, - export_fixes_dir, - build_path, - ) - ) - for f in files - ] + return_code = 0 try: - for i, coro in enumerate(asyncio.as_completed(tasks)): - result = await coro - if result.returncode != 0: - returncode = 1 - if result.returncode < 0: - result.stderr += f"{result.filename}: terminated by signal {-result.returncode}\n" - progress = f"[{i + 1: >{len(f'{len(files)}')}}/{len(files)}]" - runtime = f"[{result.elapsed:.1f}s]" - print(f"{progress}{runtime} {' '.join(result.invocation)}") - if result.stdout: - print(result.stdout, end=("" if result.stderr else "\n")) - if result.stderr: - print(result.stderr) - except asyncio.CancelledError: + # Spin up a bunch of tidy-launching threads. + task_queue = queue.Queue(max_task) + # List of files with a non-zero return code. + failed_files = [] + lock = threading.Lock() + for _ in range(max_task): + t = threading.Thread( + target=run_tidy, + args=( + args, + clang_tidy_binary, + export_fixes_dir, + build_path, + task_queue, + lock, + failed_files, + ), + ) + t.daemon = True + t.start() + + # Fill the queue with files. + for name in files: + if file_name_re.search(name): + task_queue.put(name) + + # Wait for all threads to be done. + task_queue.join() + if len(failed_files): + return_code = 1 + + except KeyboardInterrupt: + # This is a sad hack. Unfortunately subprocess goes + # bonkers with ctrl-c and we start forking merrily. print("\nCtrl-C detected, goodbye.") - for task in tasks: - task.cancel() if delete_fixes_dir: - assert export_fixes_dir shutil.rmtree(export_fixes_dir) - return + os.kill(0, 9) if combine_fixes: - print(f"Writing fixes to {args.export_fixes} ...") + print("Writing fixes to " + args.export_fixes + " ...") try: - assert export_fixes_dir merge_replacement_files(export_fixes_dir, args.export_fixes) except: print("Error exporting fixes.\n", file=sys.stderr) traceback.print_exc() - returncode = 1 + return_code = 1 if args.fix: print("Applying fixes ...") try: - assert export_fixes_dir apply_fixes(args, clang_apply_replacements_binary, export_fixes_dir) except: print("Error applying fixes.\n", file=sys.stderr) traceback.print_exc() - returncode = 1 + return_code = 1 if delete_fixes_dir: - assert export_fixes_dir shutil.rmtree(export_fixes_dir) - sys.exit(returncode) + sys.exit(return_code) if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/clang-tools-extra/clang-tidy/utils/ASTUtils.cpp b/clang-tools-extra/clang-tidy/utils/ASTUtils.cpp index 0cdc7d08abc99e..fd5dadc9b01db1 100644 --- a/clang-tools-extra/clang-tidy/utils/ASTUtils.cpp +++ b/clang-tools-extra/clang-tidy/utils/ASTUtils.cpp @@ -96,7 +96,7 @@ bool areStatementsIdentical(const Stmt *FirstStmt, const Stmt *SecondStmt, if (FirstStmt == SecondStmt) return true; - if (FirstStmt->getStmtClass() != SecondStmt->getStmtClass()) + if (FirstStmt->getStmtClass() != FirstStmt->getStmtClass()) return false; if (isa(FirstStmt) && isa(SecondStmt)) { diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp index 9bfb7e2677533a..6ae46e2b1262a4 100644 --- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp +++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp @@ -141,10 +141,7 @@ bool isStandardPointerConvertible(QualType From, QualType To) { if (RD->isCompleteDefinition() && isBaseOf(From->getPointeeType().getTypePtr(), To->getPointeeType().getTypePtr())) { - // If B is an inaccessible or ambiguous base class of D, a program - // that necessitates this conversion is ill-formed - return isUnambiguousPublicBaseClass(From->getPointeeType().getTypePtr(), - To->getPointeeType().getTypePtr()); + return true; } } @@ -378,7 +375,10 @@ bool ExceptionAnalyzer::ExceptionInfo::filterByCatch( isPointerOrPointerToMember(ExceptionCanTy->getTypePtr())) { // A standard pointer conversion not involving conversions to pointers to // private or protected or ambiguous classes ... - if (isStandardPointerConvertible(ExceptionCanTy, HandlerCanTy)) { + if (isStandardPointerConvertible(ExceptionCanTy, HandlerCanTy) && + isUnambiguousPublicBaseClass( + ExceptionCanTy->getTypePtr()->getPointeeType().getTypePtr(), + HandlerCanTy->getTypePtr()->getPointeeType().getTypePtr())) { TypesToDelete.push_back(ExceptionTy); } // A function pointer conversion ... diff --git a/clang-tools-extra/clangd/IncludeCleaner.cpp b/clang-tools-extra/clangd/IncludeCleaner.cpp index e34706172f0bf6..dc5b7ec95db5ff 100644 --- a/clang-tools-extra/clangd/IncludeCleaner.cpp +++ b/clang-tools-extra/clangd/IncludeCleaner.cpp @@ -401,26 +401,6 @@ computeIncludeCleanerFindings(ParsedAST &AST, bool AnalyzeAngledIncludes) { Ref.RT != include_cleaner::RefType::Explicit) return; - // Check if we have any headers with the same spelling, in edge cases - // like `#include_next "foo.h"`, the user can't ever include the - // physical foo.h, but can have a spelling that refers to it. - // We postpone this check because spelling a header for every usage is - // expensive. - std::string Spelling = include_cleaner::spellHeader( - {Providers.front(), AST.getPreprocessor().getHeaderSearchInfo(), - MainFile}); - for (auto *Inc : - ConvertedIncludes.match(include_cleaner::Header{Spelling})) { - Satisfied = true; - auto HeaderID = - AST.getIncludeStructure().getID(&Inc->Resolved->getFileEntry()); - assert(HeaderID.has_value() && - "ConvertedIncludes only contains resolved includes."); - Used.insert(*HeaderID); - } - if (Satisfied) - return; - // We actually always want to map usages to their spellings, but // spelling locations can point into preamble section. Using these // offsets could lead into crashes in presence of stale preambles. Hence diff --git a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp index 0ee748c1ed2d02..7027232460354c 100644 --- a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp +++ b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp @@ -644,28 +644,6 @@ TEST(IncludeCleaner, ResourceDirIsIgnored) { EXPECT_THAT(Findings.MissingIncludes, IsEmpty()); } -TEST(IncludeCleaner, DifferentHeaderSameSpelling) { - // `foo` is declared in foo_inner/foo.h, but there's no way to spell it - // directly. Make sure we don't generate unusued/missing include findings in - // such cases. - auto TU = TestTU::withCode(R"cpp( - #include - void baz() { - foo(); - } - )cpp"); - TU.AdditionalFiles["foo/foo.h"] = guard("#include_next "); - TU.AdditionalFiles["foo_inner/foo.h"] = guard(R"cpp( - void foo(); - )cpp"); - TU.ExtraArgs.push_back("-Ifoo"); - TU.ExtraArgs.push_back("-Ifoo_inner"); - - auto AST = TU.build(); - auto Findings = computeIncludeCleanerFindings(AST); - EXPECT_THAT(Findings.UnusedIncludes, IsEmpty()); - EXPECT_THAT(Findings.MissingIncludes, IsEmpty()); -} } // namespace } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 642ad39cc0c1c5..a23483e6df6d20 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -48,6 +48,10 @@ Major New Features Improvements to clangd ---------------------- +- Introduced exmperimental support for C++20 Modules. The experimental support can + be enabled by `-experimental-modules-support` option. It is in an early development + stage and may not perform efficiently in real-world scenarios. + Inlay hints ^^^^^^^^^^^ @@ -69,6 +73,9 @@ Code completion Code actions ^^^^^^^^^^^^ +- The tweak for turning unscoped into scoped enums now removes redundant prefixes + from the enum values. + Signature help ^^^^^^^^^^^^^^ @@ -81,12 +88,23 @@ Objective-C Miscellaneous ^^^^^^^^^^^^^ +- Added a boolean option `AnalyzeAngledIncludes` to `Includes` config section, + which allows to enable unused includes detection for all angled ("system") headers. + At this moment umbrella headers are not supported, so enabling this option + may result in false-positives. + Improvements to clang-doc ------------------------- Improvements to clang-query --------------------------- +- Added the `file` command to dynamically load a list of commands and matchers + from an external file, allowing the cost of reading the compilation database + and building the AST to be imposed just once for faster prototyping. + +- Removed support for ``enable output srcloc``. Fixes #GH82591 + Improvements to clang-rename ---------------------------- @@ -95,21 +113,424 @@ The improvements are... Improvements to clang-tidy -------------------------- +- Improved :program:`run-clang-tidy.py` script. Added argument `-source-filter` + to filter source files from the compilation database, via a RegEx. In a + similar fashion to what `-header-filter` does for header files. + +- Improved :program:`check_clang_tidy.py` script. Added argument `-export-fixes` + to aid in clang-tidy and test development. + +- Fixed bug where big values for unsigned check options overflowed into negative values + when being printed with `--dump-config`. + +- Fixed `--verify-config` option not properly parsing checks when using the + literal operator in the `.clang-tidy` config. + +- Added argument `--exclude-header-filter` and config option `ExcludeHeaderFilterRegex` + to exclude headers from analysis via a RegEx. + +- Added argument `--allow-no-checks` to suppress "no checks enabled" error + when disabling all of the checks by `--checks='-*'`. + New checks ^^^^^^^^^^ +- New :doc:`boost-use-ranges + ` check. + + Detects calls to standard library iterator algorithms that could be replaced + with a Boost ranges version instead. + +- New :doc:`bugprone-crtp-constructor-accessibility + ` check. + + Detects error-prone Curiously Recurring Template Pattern usage, when the CRTP + can be constructed outside itself and the derived class. + +- New :doc:`bugprone-pointer-arithmetic-on-polymorphic-object + ` check. + + Finds pointer arithmetic performed on classes that contain a virtual function. + +- New :doc:`bugprone-return-const-ref-from-parameter + ` check. + + Detects return statements that return a constant reference parameter as constant + reference. This may cause use-after-free errors if the caller uses xvalues as + arguments. + +- New :doc:`bugprone-suspicious-stringview-data-usage + ` check. + + Identifies suspicious usages of ``std::string_view::data()`` that could lead + to reading out-of-bounds data due to inadequate or incorrect string null + termination. + +- New :doc:`misc-use-internal-linkage + ` check. + + Detects variables and functions that can be marked as static or moved into + an anonymous namespace to enforce internal linkage. + +- New :doc:`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 + ` check. + + Finds initializer lists for aggregate types that could be + written as designated initializers instead. + +- New :doc:`modernize-use-ranges + ` check. + + Detects calls to standard library iterator algorithms that could be replaced + with a ranges version instead. + +- New :doc:`modernize-use-std-format + ` check. + + Converts calls to ``absl::StrFormat``, or other functions via + configuration options, to C++20's ``std::format``, or another function + via a configuration option, modifying the format string appropriately and + removing now-unnecessary calls to ``std::string::c_str()`` and + ``std::string::data()``. + +- New :doc:`readability-enum-initial-value + ` check. + + Enforces consistent style for enumerators' initialization, covering three + styles: none, first only, or all initialized explicitly. + +- New :doc:`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 + ` check. + + Replaces certain conditional statements with equivalent calls to + ``std::min`` or ``std::max``. + New check aliases ^^^^^^^^^^^^^^^^^ +- New alias :doc:`cert-ctr56-cpp ` to + :doc:`bugprone-pointer-arithmetic-on-polymorphic-object + ` + was added. + +- New alias :doc:`cert-int09-c ` to + :doc:`readability-enum-initial-value ` + was added. + Changes in existing checks ^^^^^^^^^^^^^^^^^^^^^^^^^^ +- Improved :doc:`bugprone-assert-side-effect + ` check by detecting side + effect from calling a method with non-const reference parameters. + +- Improved :doc:`bugprone-assignment-in-if-condition + ` check by ignoring + assignments in the C++20 ``requires`` clause. + +- Improved :doc:`bugprone-casting-through-void + ` check by ignoring casts + where source is already a ``void``` pointer, making middle ``void`` pointer + casts bug-free. + +- Improved :doc:`bugprone-forwarding-reference-overload + ` + check to ignore deleted constructors which won't hide other overloads. + +- Improved :doc:`bugprone-implicit-widening-of-multiplication-result + ` check + by adding an option to ignore constant expressions of signed integer types + that fit in the source expression type. + +- Improved :doc:`bugprone-inc-dec-in-conditions + ` check to ignore code + within unevaluated contexts, such as ``decltype``. + +- Improved :doc:`bugprone-lambda-function-name` + check by ignoring ``__func__`` macro in lambda captures, initializers of + default parameters and nested function declarations. + +- Improved :doc:`bugprone-multi-level-implicit-pointer-conversion + ` check + by ignoring implicit pointer conversions that are part of a cast expression. + +- Improved :doc:`bugprone-non-zero-enum-to-bool-conversion + ` check by + eliminating false positives resulting from direct usage of bitwise operators + within parentheses. + +- Improved :doc:`bugprone-optional-value-conversion + ` check by eliminating + false positives resulting from use of optionals in unevaluated context. + +- Improved :doc:`bugprone-sizeof-expression + ` check by clarifying the + diagnostics, eliminating some false positives and adding a new + (off-by-default) option `WarnOnSizeOfPointer` that reports all + ``sizeof(pointer)`` expressions (except for a few that are idiomatic). + +- Improved :doc:`bugprone-suspicious-include + ` check by replacing the local + options `HeaderFileExtensions` and `ImplementationFileExtensions` by the + global options of the same name. + +- Improved :doc:`bugprone-too-small-loop-variable + ` check by incorporating + better support for ``const`` loop boundaries. + +- Improved :doc:`bugprone-unused-local-non-trivial-variable + ` check by + ignoring local variable with ``[maybe_unused]`` attribute. + +- Improved :doc:`bugprone-unused-return-value + ` check by updating the + parameter `CheckedFunctions` to support regexp, avoiding false positive for + function with the same prefix as the default argument, e.g. ``std::unique_ptr`` + and ``std::unique``, avoiding false positive for assignment operator overloading. + +- Improved :doc:`bugprone-use-after-move + ` check to also handle + calls to ``std::forward``. Fixed sequencing of designated initializers. Fixed + sequencing of callees: In C++17 and later, the callee of a function is guaranteed + to be sequenced before the arguments, so don't warn if the use happens in the + callee and the move happens in one of the arguments. + +- Improved :doc:`cppcoreguidelines-avoid-non-const-global-variables + ` check + with a new option `AllowInternalLinkage` to disable the warning for variables + with internal linkage. + +- Improved :doc:`cppcoreguidelines-macro-usage + ` check by ignoring macro with + hash preprocessing token. + +- Improved :doc:`cppcoreguidelines-missing-std-forward + ` check by no longer + giving false positives for deleted functions, by fixing false negatives when only + a few parameters are forwarded and by ignoring parameters without a name (unused + arguments). + +- Improved :doc:`cppcoreguidelines-owning-memory + ` check to properly handle + return type in lambdas and in nested functions. + +- Improved :doc:`cppcoreguidelines-prefer-member-initializer + ` check + by removing enforcement of rule `C.48 + `_, + which was deprecated since :program:`clang-tidy` 17. This rule is now covered + by :doc:`cppcoreguidelines-use-default-member-init + `. Fixed + incorrect hints when using list-initialization. + +- Improved :doc:`cppcoreguidelines-special-member-functions + ` check with a + new option `AllowImplicitlyDeletedCopyOrMove`, which removes the requirement + for explicit copy or move special member functions when they are already + implicitly deleted. + +- Improved :doc:`google-build-namespaces + ` check by replacing the local + option `HeaderFileExtensions` by the global option of the same name. + +- Improved :doc:`google-explicit-constructor + ` check to better handle + C++20 `explicit(bool)`. + +- Improved :doc:`google-global-names-in-headers + ` check by replacing the local + option `HeaderFileExtensions` by the global option of the same name. + +- Improved :doc:`google-runtime-int ` + check performance through optimizations. + +- Improved :doc:`hicpp-signed-bitwise ` + check by ignoring false positives involving positive integer literals behind + implicit casts when `IgnorePositiveIntegerLiterals` is enabled. + +- Improved :doc:`hicpp-ignored-remove-result ` + check by ignoring other functions with same prefixes as the target specific + functions. + +- Improved :doc:`linuxkernel-must-check-errs + ` check documentation to + consistently use the check's proper name. + +- Improved :doc:`llvm-header-guard + ` check by replacing the local + option `HeaderFileExtensions` by the global option of the same name. + +- Improved :doc:`misc-const-correctness + ` check by avoiding infinite recursion + for recursive functions with forwarding reference parameters and reference + variables which refer to themselves. + +- Improved :doc:`misc-definitions-in-headers + ` check by replacing the local + option `HeaderFileExtensions` by the global option of the same name. + Additionally, the option `UseHeaderFileExtensions` is removed, so that the + check uses the `HeaderFileExtensions` option unconditionally. + +- Improved :doc:`misc-header-include-cycle + ` check by avoiding crash for self + include cycles. + +- Improved :doc:`misc-unused-using-decls + ` check by replacing the local + option `HeaderFileExtensions` by the global option of the same name. + +- Improved :doc:`misc-use-anonymous-namespace + ` check by replacing the local + option `HeaderFileExtensions` by the global option of the same name. + +- Improved :doc:`modernize-avoid-c-arrays + ` check by introducing the new + `AllowStringArrays` option, enabling the exclusion of array types with deduced + length initialized from string literals. + +- Improved :doc:`modernize-loop-convert + ` check by ensuring that fix-its + don't remove parentheses used in ``sizeof`` calls when they have array index + accesses as arguments. + +- Improved :doc:`modernize-use-constraints + ` check by fixing a crash that + occurred in some scenarios and excluding system headers from analysis. + +- Improved :doc:`modernize-use-nullptr + ` check to include support for C23, + which also has introduced the ``nullptr`` keyword. + +- Improved :doc:`modernize-use-override + ` check to also remove any trailing + whitespace when deleting the ``virtual`` keyword. + +- Improved :doc:`modernize-use-starts-ends-with + ` check to also handle + calls to ``compare`` method. + +- Improved :doc:`modernize-use-std-print + ` check to not crash if the + format string parameter of the function to be replaced is not of the + expected type. + +- Improved :doc:`modernize-use-using ` + check by adding support for detection of typedefs declared on function level. + +- Improved :doc:`performance-inefficient-vector-operation + ` fixing false + negatives caused by different variable definition type and variable initial + value type in loop initialization expression. + +- Improved :doc:`performance-move-const-arg + ` check by ignoring + ``std::move()`` calls when their target is used as an rvalue. + +- Improved :doc:`performance-unnecessary-copy-initialization + ` check by + detecting more cases of constant access. In particular, pointers can be + analyzed, so the check now handles the common patterns + `const auto e = (*vector_ptr)[i]` and `const auto e = vector_ptr->at(i);`. + Calls to mutable function where there exists a `const` overload are also + handled. Fix crash in the case of a non-member operator call. + +- Improved :doc:`performance-unnecessary-value-param + ` check + detecting more cases for template functions including lambdas with ``auto``. + E.g., ``std::sort(a.begin(), a.end(), [](auto x, auto y) { return a > b; });`` + will be detected for expensive to copy types. Fixed false positives for + dependent call expressions. + +- Improved :doc:`readability-avoid-return-with-void-value + ` check by adding + fix-its. + +- Improved :doc:`readability-const-return-type + ` check to eliminate false + positives when returning types with const not at the top level. + +- Improved :doc:`readability-container-size-empty + ` check to prevent false + positives when utilizing ``size`` or ``length`` methods that accept parameter. + Fixed crash when facing template user defined literals. + +- Improved :doc:`readability-duplicate-include + ` check by excluding include + directives that form the filename using macro. + +- Improved :doc:`readability-else-after-return + ` check to ignore + `if consteval` statements, for which the `else` branch must not be removed. + +- Improved :doc:`readability-identifier-naming + ` check in `GetConfigPerFile` + mode by resolving symbolic links to header files. Fixed handling of Hungarian + Prefix when configured to `LowerCase`. Added support for renaming designated + initializers. Added support for renaming macro arguments. Fixed renaming + conflicts arising from out-of-line member function template definitions. + +- Improved :doc:`readability-implicit-bool-conversion + ` check to provide + valid fix suggestions for ``static_cast`` without a preceding space and + fixed problem with duplicate parentheses in double implicit casts. Corrected + the fix suggestions for C23 and later by using C-style casts instead of + ``static_cast``. Fixed false positives in C++20 spaceship operator by ignoring + casts in implicit and defaulted functions. + +- Improved :doc:`readability-redundant-inline-specifier + ` check to properly + emit warnings for static data member with an in-class initializer. + +- Improved :doc:`readability-redundant-member-init + ` check to avoid + false-positives when type of the member does not match the type of the + initializer. + +- Improved :doc:`readability-static-accessed-through-instance + ` check to + support calls to overloaded operators as base expression and provide fixes to + expressions with side-effects. + +- Improved :doc:`readability-simplify-boolean-expr + ` check to avoid to emit + warning for macro when IgnoreMacro option is enabled and improve messages + when auto-fix does not work. + +- Improved :doc:`readability-static-definition-in-anonymous-namespace + ` + check by resolving fix-it overlaps in template code by disregarding implicit + instances. + +- Improved :doc:`readability-string-compare + ` check to also detect + usages of ``std::string_view::compare``. Added a `StringLikeClasses` option + to detect usages of ``compare`` method in custom string-like classes. + Removed checks ^^^^^^^^^^^^^^ +- Removed `cert-dcl21-cpp`, which was deprecated since :program:`clang-tidy` 17, + since the rule DCL21-CPP has been removed from the CERT guidelines. + Miscellaneous ^^^^^^^^^^^^^ +- Fixed incorrect formatting in :program:`clang-apply-replacements` when no + `--format` option is specified. Now :program:`clang-apply-replacements` + applies formatting only with the option. + Improvements to include-fixer ----------------------------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.Move.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.Move.rst index f478598bb4e6c0..e723f21f6bc605 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.Move.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/cplusplus.Move.rst @@ -1,13 +1,9 @@ .. title:: clang-tidy - clang-analyzer-cplusplus.Move -.. meta:: - :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#cplusplus-move clang-analyzer-cplusplus.Move ============================= Find use-after-move bugs in C++. -The `clang-analyzer-cplusplus.Move` check is an alias, please see -`Clang Static Analyzer Available Checkers -`_ -for more information. +The clang-analyzer-cplusplus.Move check is an alias of +Clang Static Analyzer cplusplus.Move. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.taint.TaintedAlloc.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.taint.TaintedAlloc.rst deleted file mode 100644 index 9732333c61aa7f..00000000000000 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/optin.taint.TaintedAlloc.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. title:: clang-tidy - clang-analyzer-optin.taint.TaintedAlloc -.. meta:: - :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#optin-taint-taintedalloc - -clang-analyzer-optin.taint.TaintedAlloc -======================================= - -Check for memory allocations, where the size parameter might be a tainted -(attacker controlled) value. - -The `clang-analyzer-optin.taint.TaintedAlloc` check is an alias, please see -`Clang Static Analyzer Available Checkers -`_ -for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.PutenvStackArray.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.PutenvStackArray.rst deleted file mode 100644 index 0a5feff8d3ca82..00000000000000 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/security.PutenvStackArray.rst +++ /dev/null @@ -1,10 +0,0 @@ -.. title:: clang-tidy - clang-analyzer-security.PutenvStackArray - -clang-analyzer-security.PutenvStackArray -======================================== - -Finds calls to the function 'putenv' which pass a pointer to an automatic -(stack-allocated) array as the argument. - -The clang-analyzer-security.PutenvStackArray check is an alias of -Clang Static Analyzer security.PutenvStackArray. diff --git a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.BlockInCriticalSection.rst b/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.BlockInCriticalSection.rst deleted file mode 100644 index 40d2d3d8b8aac7..00000000000000 --- a/clang-tools-extra/docs/clang-tidy/checks/clang-analyzer/unix.BlockInCriticalSection.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. title:: clang-tidy - clang-analyzer-unix.BlockInCriticalSection -.. meta:: - :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#unix-blockincriticalsection - -clang-analyzer-unix.BlockInCriticalSection -========================================== - -Check for calls to blocking functions inside a critical section. - -The `clang-analyzer-unix.BlockInCriticalSection` check is an alias, please see -`Clang Static Analyzer Available Checkers -`_ -for more information. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index a931ebf025a10e..dd2887edb0f8da 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -118,7 +118,6 @@ Clang-Tidy Checks :doc:`bugprone-not-null-terminated-result `, "Yes" :doc:`bugprone-optional-value-conversion `, "Yes" :doc:`bugprone-parent-virtual-call `, "Yes" - :doc:`bugprone-pointer-arithmetic-on-polymorphic-object `, :doc:`bugprone-posix-return `, "Yes" :doc:`bugprone-redundant-branch-condition `, "Yes" :doc:`bugprone-reserved-identifier `, "Yes" @@ -159,6 +158,7 @@ Clang-Tidy Checks :doc:`bugprone-unused-raii `, "Yes" :doc:`bugprone-unused-return-value `, :doc:`bugprone-use-after-move `, + :doc:`bugprone-pointer-arithmetic-on-polymorphic-object `, :doc:`bugprone-virtual-near-miss `, "Yes" :doc:`cert-dcl50-cpp `, :doc:`cert-dcl58-cpp `, @@ -269,7 +269,7 @@ Clang-Tidy Checks :doc:`misc-unused-parameters `, "Yes" :doc:`misc-unused-using-decls `, "Yes" :doc:`misc-use-anonymous-namespace `, - :doc:`misc-use-internal-linkage `, "Yes" + :doc:`misc-use-internal-linkage `, :doc:`modernize-avoid-bind `, "Yes" :doc:`modernize-avoid-c-arrays `, :doc:`modernize-concat-nested-namespaces `, "Yes" @@ -409,7 +409,6 @@ Check aliases :doc:`bugprone-narrowing-conversions `, :doc:`cppcoreguidelines-narrowing-conversions `, :doc:`cert-con36-c `, :doc:`bugprone-spuriously-wake-up-functions `, :doc:`cert-con54-cpp `, :doc:`bugprone-spuriously-wake-up-functions `, - :doc:`cert-ctr56-cpp `, :doc:`bugprone-pointer-arithmetic-on-polymorphic-object `, :doc:`cert-dcl03-c `, :doc:`misc-static-assert `, "Yes" :doc:`cert-dcl16-c `, :doc:`readability-uppercase-literal-suffix `, "Yes" :doc:`cert-dcl37-c `, :doc:`bugprone-reserved-identifier `, "Yes" @@ -449,7 +448,7 @@ Check aliases :doc:`clang-analyzer-core.uninitialized.UndefReturn `, `Clang Static Analyzer core.uninitialized.UndefReturn `_, :doc:`clang-analyzer-cplusplus.ArrayDelete `, `Clang Static Analyzer cplusplus.ArrayDelete `_, :doc:`clang-analyzer-cplusplus.InnerPointer `, `Clang Static Analyzer cplusplus.InnerPointer `_, - :doc:`clang-analyzer-cplusplus.Move `, `Clang Static Analyzer cplusplus.Move `_, + :doc:`clang-analyzer-cplusplus.Move `, Clang Static Analyzer cplusplus.Move, :doc:`clang-analyzer-cplusplus.NewDelete `, `Clang Static Analyzer cplusplus.NewDelete `_, :doc:`clang-analyzer-cplusplus.NewDeleteLeaks `, `Clang Static Analyzer cplusplus.NewDeleteLeaks `_, :doc:`clang-analyzer-cplusplus.PlacementNew `, `Clang Static Analyzer cplusplus.PlacementNew `_, @@ -472,7 +471,6 @@ Check aliases :doc:`clang-analyzer-optin.performance.GCDAntipattern `, `Clang Static Analyzer optin.performance.GCDAntipattern `_, :doc:`clang-analyzer-optin.performance.Padding `, `Clang Static Analyzer optin.performance.Padding `_, :doc:`clang-analyzer-optin.portability.UnixAPI `, `Clang Static Analyzer optin.portability.UnixAPI `_, - :doc:`clang-analyzer-optin.taint.TaintedAlloc `, `Clang Static Analyzer optin.taint.TaintedAlloc `_, :doc:`clang-analyzer-osx.API `, `Clang Static Analyzer osx.API `_, :doc:`clang-analyzer-osx.MIG `, Clang Static Analyzer osx.MIG, :doc:`clang-analyzer-osx.NumberObjectConversion `, `Clang Static Analyzer osx.NumberObjectConversion `_, @@ -503,7 +501,6 @@ Check aliases :doc:`clang-analyzer-osx.coreFoundation.containers.OutOfBounds `, `Clang Static Analyzer osx.coreFoundation.containers.OutOfBounds `_, :doc:`clang-analyzer-osx.coreFoundation.containers.PointerSizedValues `, `Clang Static Analyzer osx.coreFoundation.containers.PointerSizedValues `_, :doc:`clang-analyzer-security.FloatLoopCounter `, `Clang Static Analyzer security.FloatLoopCounter `_, - :doc:`clang-analyzer-security.PutenvStackArray `, Clang Static Analyzer security.PutenvStackArray, :doc:`clang-analyzer-security.SetgidSetuidOrder `, Clang Static Analyzer security.SetgidSetuidOrder, :doc:`clang-analyzer-security.cert.env.InvalidPtr `, `Clang Static Analyzer security.cert.env.InvalidPtr `_, :doc:`clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling `, `Clang Static Analyzer security.insecureAPI.DeprecatedOrUnsafeBufferHandling `_, @@ -520,7 +517,6 @@ Check aliases :doc:`clang-analyzer-security.insecureAPI.strcpy `, `Clang Static Analyzer security.insecureAPI.strcpy `_, :doc:`clang-analyzer-security.insecureAPI.vfork `, `Clang Static Analyzer security.insecureAPI.vfork `_, :doc:`clang-analyzer-unix.API `, `Clang Static Analyzer unix.API `_, - :doc:`clang-analyzer-unix.BlockInCriticalSection `, `Clang Static Analyzer unix.BlockInCriticalSection `_, :doc:`clang-analyzer-unix.Errno `, `Clang Static Analyzer unix.Errno `_, :doc:`clang-analyzer-unix.Malloc `, `Clang Static Analyzer unix.Malloc `_, :doc:`clang-analyzer-unix.MallocSizeof `, `Clang Static Analyzer unix.MallocSizeof `_, diff --git a/clang-tools-extra/include-cleaner/lib/Analysis.cpp b/clang-tools-extra/include-cleaner/lib/Analysis.cpp index 68fe79d6929f6b..f1cd72f877ca21 100644 --- a/clang-tools-extra/include-cleaner/lib/Analysis.cpp +++ b/clang-tools-extra/include-cleaner/lib/Analysis.cpp @@ -105,20 +105,9 @@ analyze(llvm::ArrayRef ASTRoots, } if (!Satisfied && !Providers.empty() && Ref.RT == RefType::Explicit && - !HeaderFilter(Providers.front().resolvedPath())) { - // Check if we have any headers with the same spelling, in edge - // cases like `#include_next "foo.h"`, the user can't ever - // include the physical foo.h, but can have a spelling that - // refers to it. - auto Spelling = spellHeader( - {Providers.front(), PP.getHeaderSearchInfo(), MainFile}); - for (const Include *I : Inc.match(Header{Spelling})) { - Used.insert(I); - Satisfied = true; - } - if (!Satisfied) - Missing.insert(std::move(Spelling)); - } + !HeaderFilter(Providers.front().resolvedPath())) + Missing.insert(spellHeader( + {Providers.front(), PP.getHeaderSearchInfo(), MainFile})); }); AnalysisResults Results; diff --git a/clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp b/clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp index 5696c380758f85..6558b680876846 100644 --- a/clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp +++ b/clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp @@ -12,7 +12,6 @@ #include "clang-include-cleaner/Record.h" #include "clang-include-cleaner/Types.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/DeclBase.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceLocation.h" @@ -297,31 +296,6 @@ TEST_F(AnalyzeTest, ResourceDirIsIgnored) { EXPECT_THAT(Results.Missing, testing::IsEmpty()); } -TEST_F(AnalyzeTest, DifferentHeaderSameSpelling) { - Inputs.ExtraArgs.push_back("-Ifoo"); - Inputs.ExtraArgs.push_back("-Ifoo_inner"); - // `foo` is declared in foo_inner/foo.h, but there's no way to spell it - // directly. Make sure we don't generate unusued/missing include findings in - // such cases. - Inputs.Code = R"cpp( - #include - void baz() { - foo(); - } - )cpp"; - Inputs.ExtraFiles["foo/foo.h"] = guard("#include_next "); - Inputs.ExtraFiles["foo_inner/foo.h"] = guard(R"cpp( - void foo(); - )cpp"); - TestAST AST(Inputs); - std::vector DeclsInTU; - for (auto *D : AST.context().getTranslationUnitDecl()->decls()) - DeclsInTU.push_back(D); - auto Results = analyze(DeclsInTU, {}, PP.Includes, &PI, AST.preprocessor()); - EXPECT_THAT(Results.Unused, testing::IsEmpty()); - EXPECT_THAT(Results.Missing, testing::IsEmpty()); -} - TEST(FixIncludes, Basic) { llvm::StringRef Code = R"cpp(#include "d.h" #include "a.h" diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp index 26c443b1396294..f5e74df1621cee 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp @@ -756,21 +756,3 @@ struct test_implicit_throw { }; }} - -void pointer_exception_can_not_escape_with_const_void_handler() noexcept { - // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'pointer_exception_can_not_escape_with_const_void_handler' which should not throw exceptions - const int value = 42; - try { - throw &value; - } catch (const void *) { - } -} - -void pointer_exception_can_not_escape_with_void_handler() noexcept { - // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'pointer_exception_can_not_escape_with_void_handler' which should not throw exceptions - int value = 42; - try { - throw &value; - } catch (void *) { - } -} diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-values.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-values.cpp index 0d1ff0db58371a..cb6bfcc1dccba3 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-values.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/misc/const-correctness-values.cpp @@ -3,7 +3,7 @@ // RUN: misc-const-correctness.TransformValues: true, \ // RUN: misc-const-correctness.WarnPointersAsValues: false, \ // RUN: misc-const-correctness.TransformPointersAsValues: false \ -// RUN: }}" -- -fno-delayed-template-parsing -fexceptions +// RUN: }}" -- -fno-delayed-template-parsing // ------- Provide test samples for primitive builtins --------- // - every 'p_*' variable is a 'potential_const_*' variable @@ -56,15 +56,6 @@ void some_function(double np_arg0, wchar_t np_arg1) { np_local6--; } -int function_try_block() try { - int p_local0 = 0; - // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const' - // CHECK-FIXES: int const p_local0 - return p_local0; -} catch (...) { - return 0; -} - void nested_scopes() { int p_local0 = 2; // CHECK-MESSAGES: [[@LINE-1]]:3: warning: variable 'p_local0' of type 'int' can be declared 'const' diff --git a/clang/cmake/caches/Fuchsia-stage2.cmake b/clang/cmake/caches/Fuchsia-stage2.cmake index 8e0835cb3158f2..0218f0b21eb282 100644 --- a/clang/cmake/caches/Fuchsia-stage2.cmake +++ b/clang/cmake/caches/Fuchsia-stage2.cmake @@ -334,7 +334,6 @@ foreach(target armv6m-unknown-eabi;armv7m-unknown-eabi;armv8m.main-unknown-eabi) endforeach() set(RUNTIMES_${target}_LLVM_LIBC_FULL_BUILD ON CACHE BOOL "") set(RUNTIMES_${target}_LIBC_ENABLE_USE_BY_CLANG ON CACHE BOOL "") - set(RUNTIMES_${target}_LIBC_USE_NEW_HEADER_GEN OFF CACHE BOOL "") set(RUNTIMES_${target}_LIBCXX_ABI_VERSION 2 CACHE STRING "") set(RUNTIMES_${target}_LIBCXX_CXX_ABI none CACHE STRING "") set(RUNTIMES_${target}_LIBCXX_ENABLE_SHARED OFF CACHE BOOL "") @@ -386,7 +385,6 @@ foreach(target riscv32-unknown-elf) endforeach() set(RUNTIMES_${target}_LLVM_LIBC_FULL_BUILD ON CACHE BOOL "") set(RUNTIMES_${target}_LIBC_ENABLE_USE_BY_CLANG ON CACHE BOOL "") - set(RUNTIMES_${target}_LIBC_USE_NEW_HEADER_GEN OFF CACHE BOOL "") set(RUNTIMES_${target}_LIBCXX_ABI_VERSION 2 CACHE STRING "") set(RUNTIMES_${target}_LIBCXX_CXX_ABI none CACHE STRING "") set(RUNTIMES_${target}_LIBCXX_ENABLE_SHARED OFF CACHE BOOL "") diff --git a/clang/docs/ClangNVLinkWrapper.rst b/clang/docs/ClangNVLinkWrapper.rst deleted file mode 100644 index 2acdb054572f86..00000000000000 --- a/clang/docs/ClangNVLinkWrapper.rst +++ /dev/null @@ -1,74 +0,0 @@ -==================== -Clang nvlink Wrapper -==================== - -.. contents:: - :local: - -.. _clang-nvlink-wrapper: - -Introduction -============ - -This tools works as a wrapper around the NVIDIA ``nvlink`` linker. The purpose -of this wrapper is to provide an interface similar to the ``ld.lld`` linker -while still relying on NVIDIA's proprietary linker to produce the final output. - -``nvlink`` has a number of known quirks that make it difficult to use in a -unified offloading setting. For example, it does not accept ``.o`` files as they -must be named ``.cubin``. Static archives do not work, so passing a ``.a`` will -provide a linker error. ``nvlink`` also does not support link time optimization -and ignores many standard linker arguments. This tool works around these issues. - -Usage -===== - -This tool can be used with the following options. Any arguments not intended -only for the linker wrapper will be forwarded to ``nvlink``. - -.. code-block:: console - - OVERVIEW: A utility that wraps around the NVIDIA 'nvlink' linker. - This enables static linking and LTO handling for NVPTX targets. - - USAGE: clang-nvlink-wrapper [options] - - OPTIONS: - --arch Specify the 'sm_' name of the target architecture. - --cuda-path= Set the system CUDA path - --dry-run Print generated commands without running. - --feature Specify the '+ptx' freature to use for LTO. - -g Specify that this was a debug compile. - -help-hidden Display all available options - -help Display available options (--help-hidden for more) - -L Add to the library search path - -l Search for library - -mllvm Arguments passed to LLVM, including Clang invocations, - for which the '-mllvm' prefix is preserved. Use '-mllvm - --help' for a list of options. - -o Path to file to write output - --plugin-opt=jobs= - Number of LTO codegen partitions - --plugin-opt=lto-partitions= - Number of LTO codegen partitions - --plugin-opt=O - Optimization level for LTO - --plugin-opt=thinlto - Enable the thin-lto backend - --plugin-opt= Arguments passed to LLVM, including Clang invocations, - for which the '-mllvm' prefix is preserved. Use '-mllvm - --help' for a list of options. - --save-temps Save intermediate results - --version Display the version number and exit - -v Print verbose information - -Example -======= - -This tool is intended to be invoked when targeting the NVPTX toolchain directly -as a cross-compiling target. This can be used to create standalone GPU -executables with normal linking semantics similar to standard compilation. - -.. code-block:: console - - clang --target=nvptx64-nvidia-cuda -march=native -flto=full input.c diff --git a/clang/docs/HLSL/AvailabilityDiagnostics.rst b/clang/docs/HLSL/AvailabilityDiagnostics.rst index c2f260f268e7bd..bb9d02f21dde62 100644 --- a/clang/docs/HLSL/AvailabilityDiagnostics.rst +++ b/clang/docs/HLSL/AvailabilityDiagnostics.rst @@ -52,6 +52,7 @@ If the compilation target is a shader library, only availability based on shader As a result, availability based on specific shader stage will only be diagnosed in code that is reachable from a shader entry point or library export function. It also means that function bodies might be scanned multiple time. When that happens, care should be taken not to produce duplicated diagnostics. +======== Examples ======== @@ -61,7 +62,7 @@ For the example below, the ``WaveActiveCountBits`` API function became available The availability of ``ddx`` function depends on a shader stage. It is available for pixel shaders in shader model 2.1 and higher, for compute, mesh and amplification shaders in shader model 6.6 and higher. For any other shader stages it is not available. Compute shader example ----------------------- +====================== .. code-block:: c++ @@ -93,7 +94,7 @@ With strict diagnostic mode, in addition to the 2 errors above Clang will also e <>:7:13: error: 'WaveActiveCountBits' is only available on Shader Model 6.5 or newer Shader library example ----------------------- +====================== .. code-block:: c++ diff --git a/clang/docs/HLSL/ExpectedDifferences.rst b/clang/docs/HLSL/ExpectedDifferences.rst index 4782eb3cda754a..a29b6348e0b8e7 100644 --- a/clang/docs/HLSL/ExpectedDifferences.rst +++ b/clang/docs/HLSL/ExpectedDifferences.rst @@ -1,4 +1,4 @@ -=================================== + Expected Differences vs DXC and FXC =================================== diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index ac1de0db9ce486..481b6313974ea5 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -37,23 +37,135 @@ These changes are ones which we think may surprise users when upgrading to Clang |release| because of the opportunity they pose for disruption to existing code bases. +- Setting the deprecated CMake variable ``GCC_INSTALL_PREFIX`` (which sets the + default ``--gcc-toolchain=``) now leads to a fatal error. + C/C++ Language Potentially Breaking Changes ------------------------------------------- +- Clang now supports raw string literals in ``-std=gnuXY`` mode as an extension in + C99 and later. This behaviour can also be overridden using ``-f[no-]raw-string-literals``. + Support of raw string literals in C++ is not affected. Fixes (#GH85703). + C++ Specific Potentially Breaking Changes ----------------------------------------- +- Clang now diagnoses function/variable templates that shadow their own template parameters, e.g. ``template void T();``. + This error can be disabled via `-Wno-strict-primary-template-shadow` for compatibility with previous versions of clang. + +- The behavior controlled by the `-frelaxed-template-template-args` flag is now + on by default, and the flag is deprecated. Until the flag is finally removed, + it's negative spelling can be used to obtain compatibility with previous + versions of clang. The deprecation warning for the negative spelling can be + disabled with `-Wno-deprecated-no-relaxed-template-template-args`. + +- Clang now rejects pointer to member from parenthesized expression in unevaluated context such as ``decltype(&(foo::bar))``. (#GH40906). + +- Clang now performs semantic analysis for unary operators with dependent operands + that are known to be of non-class non-enumeration type prior to instantiation. + + This change uncovered a bug in libstdc++ 14.1.0 which may cause compile failures + on systems using that version of libstdc++ and Clang 19, with an error that looks + something like this: + + .. code-block:: text + + :4:5: error: expression is not assignable + 4 | ++this; + | ^ ~~~~ + + To fix this, update libstdc++ to version 14.1.1 or greater. ABI Changes in This Version --------------------------- +- Fixed Microsoft name mangling of implicitly defined variables used for thread + safe static initialization of static local variables. This change resolves + incompatibilities with code compiled by MSVC but might introduce + incompatibilities with code compiled by earlier versions of Clang when an + inline member function that contains a static local variable with a dynamic + initializer is declared with ``__declspec(dllimport)``. (#GH83616). + +- Fixed Microsoft name mangling of lifetime extended temporary objects. This + change corrects missing back reference registrations that could result in + incorrect back reference indexes and suprising demangled name results. Since + MSVC uses a different mangling for these objects, compatibility is not affected. + (#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). + +- Fixed Microsoft calling convention when returning classes that have a deleted + copy assignment operator. Such a class should be returned indirectly. + +- Removed the global alias that was pointing to AArch64 Function Multiversioning + ifuncs. Its purpose was to preserve backwards compatibility when the ".ifunc" + suffix got removed from the name mangling. The alias interacts badly with + GlobalOpt (see the issue #96197). + +- Fixed Microsoft name mangling for auto non-type template arguments of pointer + type for MSVC 1920+. This change resolves incompatibilities with code compiled + by MSVC 1920+ but will introduce incompatibilities with code compiled by + earlier versions of Clang unless such code is built with the compiler option + `-fms-compatibility-version=19.14` to imitate the MSVC 1914 mangling behavior. + +- Fixed Microsoft name mangling for auto non-type template arguments of pointer + to member type for MSVC 1920+. This change resolves incompatibilities with code + compiled by MSVC 1920+ but will introduce incompatibilities with code compiled by + earlier versions of Clang unless such code is built with the compiler option + `-fms-compatibility-version=19.14` to imitate the MSVC 1914 mangling behavior. + (GH#70899). AST Dumping Potentially Breaking Changes ---------------------------------------- +- The text ast-dumper has improved printing of TemplateArguments. +- The text decl-dumper prints template parameters' trailing requires expressions now. + Clang Frontend Potentially Breaking Changes ------------------------------------------- +- Removed support for constructing on-stack ``TemplateArgumentList``\ s; interfaces should instead + use ``ArrayRef`` to pass template arguments. Transitioning internal uses to + ``ArrayRef`` reduces AST memory usage by 0.4% when compiling clang, and is + expected to show similar improvements on other workloads. + +- The ``-Wgnu-binary-literal`` diagnostic group no longer controls any + diagnostics. Binary literals are no longer a GNU extension, they're now a C23 + extension which is controlled via ``-pedantic`` or ``-Wc23-extensions``. Use + of ``-Wno-gnu-binary-literal`` will no longer silence this pedantic warning, + which may break existing uses with ``-Werror``. + +- The normalization of 3 element target triples where ``-none-`` is the middle + element has changed. For example, ``armv7m-none-eabi`` previously normalized + to ``armv7m-none-unknown-eabi``, with ``none`` for the vendor and ``unknown`` + for the operating system. It now normalizes to ``armv7m-unknown-none-eabi``, + which has ``unknown`` vendor and ``none`` operating system. + + The affected triples are primarily for bare metal Arm where it is intended + that ``none`` means that there is no operating system. As opposed to an unknown + type of operating system. + + This change my cause clang to not find libraries, or libraries to be built at + different file system locations. This can be fixed by changing your builds to + use the new normalized triple. However, we recommend instead getting the + normalized triple from clang itself, as this will make your builds more + robust in case of future changes:: + + $ clang --target= -print-target-triple + + +- The ``hasTypeLoc`` AST matcher will no longer match a ``classTemplateSpecializationDecl``; + existing uses should switch to ``templateArgumentLoc`` or ``hasAnyTemplateArgumentLoc`` instead. Clang Python Bindings Potentially Breaking Changes -------------------------------------------------- +- Renamed ``CursorKind`` variant 272 from ``OMP_TEAMS_DISTRIBUTE_DIRECTIVE`` + to ``OMP_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE``. The previous name was incorrect, it was a duplicate + of variant 271. +- Renamed ``TypeKind`` variant 162 from ``OBJCCLASS`` to ``OBJCTYPEPARAM``. + The previous name was incorrect, it was a duplicate of variant 28. +- Refactored enum implementation, switching to the standard library `Enum` type. What's New in Clang |release|? ============================== @@ -62,91 +174,941 @@ here. Generic improvements to Clang as a whole or to its underlying infrastructure are described first, followed by language-specific sections with improvements to Clang's support for those languages. +- Implemented improvements to BMIs for C++20 Modules that can reduce + the number of rebuilds during incremental recompilation. We are seeking + feedback from Build System authors and other interested users, especially + when you feel Clang changes the BMI and misses an opportunity to avoid + recompilations or causes correctness issues. See StandardCPlusPlusModules + `StandardCPlusPlusModules `_ for more details. + +- The ``\par`` documentation comment command now supports an optional + argument, which denotes the header of the paragraph started by + an instance of the ``\par`` command comment. The implementation + of the argument handling matches its semantics + `in Doxygen `. + Namely, any text on the same line as the ``\par`` command will become + a header for the paragaph, and if there is no text then the command + will start a new paragraph. + C++ Language Changes -------------------- +- C++17 support is now completed, with the enablement of the + relaxed temlate template argument matching rules introduced in P0522, + which was retroactively applied as a defect report. + While the implementation already existed since Clang 4, it was turned off by + default, and was controlled with the `-frelaxed-template-template-args` flag. + In this release, we implement provisional wording for a core defect on + P0522 (CWG2398), which avoids the most serious compatibility issues caused + by it, allowing us to enable it by default in this release. + The flag is now deprecated, and will be removed in the next release, but can + still be used to turn it off and regain compatibility with previous versions + (#GH36505). +- 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++14 Feature Support ^^^^^^^^^^^^^^^^^^^^^ +- Sized deallocation is enabled by default in C++14 onwards. The user may specify + ``-fno-sized-deallocation`` to disable it if there are some regressions. C++20 Feature Support ^^^^^^^^^^^^^^^^^^^^^ +- Clang won't perform ODR checks for decls in the global module fragment any + more to ease the implementation and improve the user's using experience. + This follows the MSVC's behavior. Users interested in testing the more strict + behavior can use the flag '-Xclang -fno-skip-odr-check-in-gmf'. + (#GH79240). + +- Implemented the `__is_layout_compatible` and `__is_pointer_interconvertible_base_of` + intrinsics to support + `P0466R5: Layout-compatibility and Pointer-interconvertibility Traits `_. + +- Clang now implements [module.import]p7 fully. Clang now will import module + units transitively for the module units coming from the same module of the + current module units. Fixes #GH84002 + +- Initial support for class template argument deduction (CTAD) for type alias + templates (`P1814R0 `_). + (#GH54051). + +- We have sufficient confidence and experience with the concepts implementation + to update the ``__cpp_concepts`` macro to `202002L`. This enables + ```` from libstdc++ to work correctly with Clang. + +- User defined constructors are allowed for copy-list-initialization with CTAD. + (#GH62925). + C++23 Feature Support ^^^^^^^^^^^^^^^^^^^^^ +- Implemented `P2718R0: Lifetime extension in range-based for loops `_. Also + materialize temporary object which is a prvalue in discarded-value expression. +- Implemented `P1774R8: Portable assumptions `_. + +- Implemented `P2448R2: Relaxing some constexpr restrictions `_. + Note, the ``-Winvalid-constexpr`` diagnostic is now disabled in C++23 mode, + but can be explicitly specified to retain the old diagnostic checking + behavior. + +- Added a ``__reference_converts_from_temporary`` builtin, completing the necessary compiler support for + `P2255R2: Type trait to determine if a reference binds to a temporary `_. + +- Implemented `P2797R0: Static and explicit object member functions with the same parameter-type-lists `_. + This completes the support for "deducing this". + C++2c Feature Support ^^^^^^^^^^^^^^^^^^^^^ +- Implemented `P2662R3 Pack Indexing `_. + +- Implemented `P2573R2: = delete("should have a reason"); `_ + +- Implemented `P0609R3: Attributes for Structured Bindings `_ + +- Implemented `P2748R5 Disallow Binding a Returned Glvalue to a Temporary `_. + +- Implemented `P2809R3: Trivial infinite loops are not Undefined Behavior `_. + +- Implemented `P3144R2 Deleting a Pointer to an Incomplete Type Should be Ill-formed `_. + +- Implemented `P2963R3 Ordering of constraints involving fold expressions `_. + +- Implemented `P3034R1 Module Declarations Shouldn’t be Macros `_. + + Resolutions to C++ Defect Reports ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- Substitute template parameter pack, when it is not explicitly specified + in the template parameters, but is deduced from a previous argument. (#GH78449) + +- Type qualifications are now ignored when evaluating layout compatibility + of two types. + (`CWG1719: Layout compatibility and cv-qualification revisited `_). + +- Alignment of members is now respected when evaluating layout compatibility + of structs. + (`CWG2583: Common initial sequence should consider over-alignment `_). + +- ``[[no_unique_address]]`` is now respected when evaluating layout + compatibility of two types. + (`CWG2759: [[no_unique_address] and common initial sequence `_). + +- Clang now diagnoses declarative nested-name-specifiers with pack-index-specifiers. + (`CWG2858: Declarative nested-name-specifiers and pack-index-specifiers `_). + +- Clang now allows attributes on concepts. + (`CWG2428: Deprecating a concept `_). + +- P0522 implementation is enabled by default in all language versions, and + provisional wording for CWG2398 is implemented. + +- Clang now performs type-only lookup for the name in ``using enum`` declaration. + (`CWG2877: Type-only lookup for using-enum-declarator `_). + +- Clang now requires a template argument list after a template keyword. + (`CWG96: Syntactic disambiguation using the template keyword `_). + +- Clang now considers ``noexcept(typeid(expr))`` more carefully, instead of always assuming that ``std::bad_typeid`` can be thrown. + (`CWG2191: Incorrect result for noexcept(typeid(v)) `_). C Language Changes ------------------ C2y Feature Support ^^^^^^^^^^^^^^^^^^^ +- Clang now enables C2y mode with ``-std=c2y``. This sets ``__STDC_VERSION__`` + to ``202400L`` so that it's greater than the value for C23. The value of this + macro is subject to change in the future. C23 Feature Support ^^^^^^^^^^^^^^^^^^^ +- No longer diagnose use of binary literals as an extension in C23 mode. Fixes + #GH72017. + +- Corrected parsing behavior for the ``alignas`` specifier/qualifier in C23. We + previously handled it as an attribute as in C++, but there are parsing + differences. The behavioral differences are: + + .. code-block:: c + + struct alignas(8) /* was accepted, now rejected */ S { + char alignas(8) /* was rejected, now accepted */ C; + }; + int i alignas(8) /* was accepted, now rejected */ ; + + Fixes (#GH81472). + +- Clang now generates predefined macros of the form ``__TYPE_FMTB__`` and + ``__TYPE_FMTb__`` (e.g., ``__UINT_FAST64_FMTB__``) in C23 mode for use with + macros typically exposed from ````, such as ``PRIb8``. (#GH81896) + +- Clang now supports `N3018 The constexpr specifier for object definitions` + `_. + +- Properly promote bit-fields of bit-precise integer types to the field's type + rather than to ``int``. #GH87641 + +- Added the ``INFINITY`` and ``NAN`` macros to Clang's ```` + freestanding implementation; these macros were defined in ```` in C99 + but C23 added them to ```` in + `WG14 N2848 `_. + +- Clang now supports `N3017 `_ + ``#embed`` - a scannable, tooling-friendly binary resource inclusion mechanism. + +- Added the ``FLT_NORM_MAX``, ``DBL_NORM_MAX``, and ``LDBL_NORM_MAX`` to the + freestanding implementation of ```` that ships with Clang. + +- Compiler support for `N2653 char8_t: A type for UTF-8 characters and strings` + `_: ``u8`` string + literals are now of type ``char8_t[N]`` in C23 and expose + ``__CLANG_ATOMIC_CHAR8_T_LOCK_FREE``/``__GCC_ATOMIC_CHAR8_T_LOCK_FREE`` to + implement the corresponding macro in ````. + +Non-comprehensive list of changes in this release +------------------------------------------------- + +- Added ``__builtin_readsteadycounter`` for reading fixed frequency hardware + counters. + +- ``__builtin_addc``, ``__builtin_subc``, and the other sizes of those + builtins are now constexpr and may be used in constant expressions. + +- Added ``__builtin_popcountg`` as a type-generic alternative to + ``__builtin_popcount{,l,ll}`` with support for any unsigned integer type. Like + the previous builtins, this new builtin is constexpr and may be used in + constant expressions. + +- Lambda expressions are now accepted in C++03 mode as an extension. + +- Added ``__builtin_clzg`` and ``__builtin_ctzg`` as type-generic alternatives + to ``__builtin_clz{,s,l,ll}`` and ``__builtin_ctz{,s,l,ll}`` respectively, + with support for any unsigned integer type. Like the previous builtins, these + new builtins are constexpr and may be used in constant expressions. + +- ``__typeof_unqual__`` is available in all C modes as an extension, which behaves + 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 `_) + +* ``-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. + +- When compiling a constexpr function, Clang will check to see whether the + function can *never* be used in a constant expression context and issues a + diagnostic under the ``-Winvalid-constexpr`` diagostic flag (which defaults + to an error). This check can be expensive because the mere presence of a + function marked ``constexpr`` will cause us to undergo constant expression + evaluation, even if the function is not called within the translation unit + being compiled. Due to the expense, Clang no longer checks constexpr function + bodies when the function is defined in a system header file or when + ``-Winvalid-constexpr`` is not enabled for the function definition, which + should result in mild compile-time performance improvements. + +- Added ``__is_bitwise_cloneable`` which is used to check whether a type + can be safely copied by memcpy/memmove. + +- ``#pragma GCC diagnostic warning "-Wfoo"`` can now downgrade ``-Werror=foo`` + errors and certain default-to-error ``-W`` diagnostics to warnings. + +- Support importing C++20 modules in clang-repl. + +- Added support for ``TypeLoc::dump()`` for easier debugging, and improved + textual and JSON dumping for various ``TypeLoc``-related nodes. + +- Clang can now emit distinct type-based alias analysis tags for incompatible + pointers, enabling more powerful alias analysis when accessing pointer types. + The new behavior can be enabled using ``-fpointer-tbaa``. New Compiler Flags ------------------ +- ``-fsanitize=implicit-bitfield-conversion`` checks implicit truncation and + sign change. +- ``-fsanitize=implicit-integer-conversion`` a group that replaces the previous + group ``-fsanitize=implicit-conversion``. + +- ``-Wmissing-designated-field-initializers``, grouped under ``-Wmissing-field-initializers``. + This diagnostic can be disabled to make ``-Wmissing-field-initializers`` behave + like it did before Clang 18.x. Fixes #GH56628 + +- ``-fexperimental-modules-reduced-bmi`` enables the Reduced BMI for C++20 named modules. + 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. Currently this allows late parsing the + `counted_by` attribute in C. See `Attribute Changes in Clang`_. + +- ``-fseparate-named-sections`` uses separate unique sections for global + symbols in named special sections (i.e. symbols annotated with + ``__attribute__((section(...)))``. This enables linker GC to collect unused + symbols without having to use a per-symbol section. + +- ``-fms-define-stdc`` and its clang-cl counterpart ``/Zc:__STDC__``. + Matches MSVC behaviour by defining ``__STDC__`` to ``1`` when + MSVC compatibility mode is used. It has no effect for C++ code. + +- ``-Wc++23-compat`` group was added to help migrating existing codebases + to C++23. + +- ``-Wc++2c-compat`` group was added to help migrating existing codebases + to upcoming C++26. + +- ``-fdisable-block-signature-string`` instructs clang not to emit the signature + string for blocks. Disabling the string can potentially break existing code + that relies on it. Users should carefully consider this possibiilty when using + the flag. + +- For the ARM target, added ``-Warm-interrupt-vfp-clobber`` that will emit a + diagnostic when an interrupt handler is declared and VFP is enabled. + +- ``-fpointer-tbaa`` enables emission of distinct type-based alias + analysis tags for incompatible pointers. Deprecated Compiler Flags ------------------------- +- The ``-Ofast`` command-line option has been deprecated. This option both + enables the ``-O3`` optimization-level, as well as enabling non-standard + ``-ffast-math`` behaviors. As such, it is somewhat misleading as an + "optimization level". Users are advised to switch to ``-O3 -ffast-math`` if + the use of non-standard math behavior is intended, and ``-O3`` otherwise. + See `RFC `_ for details. + Modified Compiler Flags ----------------------- +- Added a new diagnostic flag ``-Wreturn-mismatch`` which is grouped under + ``-Wreturn-type``, and moved some of the diagnostics previously controlled by + ``-Wreturn-type`` under this new flag. Fixes #GH72116. +- ``-fsanitize=implicit-conversion`` is now a group for both + ``-fsanitize=implicit-integer-conversion`` and + ``-fsanitize=implicit-bitfield-conversion``. + +- Added ``-Wcast-function-type-mismatch`` under the ``-Wcast-function-type`` + warning group. Moved the diagnostic previously controlled by + ``-Wcast-function-type`` to the new warning group and added + ``-Wcast-function-type-mismatch`` to ``-Wextra``. #GH76872 + + .. code-block:: c + + int x(long); + typedef int (f2)(void*); + typedef int (f3)(); + + void func(void) { + // Diagnoses under -Wcast-function-type, -Wcast-function-type-mismatch, + // -Wcast-function-type-strict, -Wextra + f2 *b = (f2 *)x; + // Diagnoses under -Wcast-function-type, -Wcast-function-type-strict + f3 *c = (f3 *)x; + } + +- Carved out ``-Wformat`` warning about scoped enums into a subwarning and + make it controlled by ``-Wformat-pedantic``. Fixes #GH88595. + +- Trivial infinite loops (i.e loops with a constant controlling expresion + evaluating to ``true`` and an empty body such as ``while(1);``) + are considered infinite, even when the ``-ffinite-loop`` flag is set. + +- Diagnostics groups about compatibility with a particular C++ Standard version + now include dianostics about C++26 features that are not present in older + versions. + +- Removed the "arm interrupt calling convention" warning that was included in + ``-Wextra`` without its own flag. This warning suggested adding + ``__attribute__((interrupt))`` to functions that are called from interrupt + handlers to prevent clobbering VFP registers. Following this suggestion leads + to unpredictable behavior by causing multiple exception returns from one + exception. Fixes #GH34876. Removed Compiler Flags ------------------------- +- The ``-freroll-loops`` flag has been removed. It had no effect since Clang 13. +- ``-m[no-]unaligned-access`` is removed for RISC-V and LoongArch. + ``-m[no-]strict-align``, also supported by GCC, should be used instead. (#GH85350) + Attribute Changes in Clang -------------------------- +- Introduced a new function attribute ``__attribute__((amdgpu_max_num_work_groups(x, y, z)))`` or + ``[[clang::amdgpu_max_num_work_groups(x, y, z)]]`` for the AMDGPU target. This attribute can be + attached to HIP or OpenCL kernel function definitions to provide an optimization hint. The parameters + ``x``, ``y``, and ``z`` specify the maximum number of workgroups for the respective dimensions, + and each must be a positive integer when provided. The parameter ``x`` is required, while ``y`` and + ``z`` are optional with default value of 1. + +- The ``swiftasynccc`` attribute is now considered to be a Clang extension + rather than a language standard feature. Please use + ``__has_extension(swiftasynccc)`` to check the availability of this attribute + for the target platform instead of ``__has_feature(swiftasynccc)``. Also, + added a new extension query ``__has_extension(swiftcc)`` corresponding to the + ``__attribute__((swiftcc))`` attribute. + +- The ``_Nullable`` and ``_Nonnull`` family of type attributes can now apply + to certain C++ class types, such as smart pointers: + ``void useObject(std::unique_ptr _Nonnull obj);``. + + This works for standard library types including ``unique_ptr``, ``shared_ptr``, + and ``function``. See + `the attribute reference documentation `_ + for the full list. + +- The ``_Nullable`` attribute can be applied to C++ class declarations: + ``template class _Nullable MySmartPointer {};``. + + This allows the ``_Nullable`` and ``_Nonnull`` family of type attributes to + apply to this class. + +- Clang now warns that the ``exclude_from_explicit_instantiation`` attribute + is ignored when applied to a local class or a member thereof. + +- The ``clspv_libclc_builtin`` attribute has been added to allow clspv + (`OpenCL-C to Vulkan SPIR-V compiler `_) to identify functions coming from libclc + (`OpenCL-C builtin library `_). +- The ``counted_by`` attribute is now allowed on pointers that are members of a + struct in C. + +- The ``counted_by`` attribute can now be late parsed in C when + ``-fexperimental-late-parse-attributes`` is passed but only when attribute is + used in the declaration attribute position. This allows using the + attribute on existing code where it previously impossible to do so without + re-ordering struct field declarations would break ABI as shown below. + + .. code-block:: c + + struct BufferTy { + /* Refering to `count` requires late parsing */ + char* buffer __counted_by(count); + /* Swapping `buffer` and `count` to avoid late parsing would break ABI */ + size_t count; + }; + +- The attributes ``sized_by``, ``counted_by_or_null`` and ``sized_by_or_null``` + have been added as variants on ``counted_by``, each with slightly different semantics. + ``sized_by`` takes a byte size parameter instead of an element count, allowing pointees + with unknown size. The ``counted_by_or_null`` and ``sized_by_or_null`` variants are equivalent + to their base variants, except the pointer can be null regardless of count/size value. + If the pointer is null the size is effectively 0. ``sized_by_or_null`` is needed to properly + annotate allocator functions like ``malloc`` that return a buffer of a given byte size, but can + also return null. + +- The ``guarded_by``, ``pt_guarded_by``, ``acquired_after``, ``acquired_before`` + attributes now support referencing struct members in C. The arguments are also + now late parsed when ``-fexperimental-late-parse-attributes`` is passed like + for ``counted_by``. + +- Introduced new function type attributes ``[[clang::nonblocking]]``, ``[[clang::nonallocating]]``, + ``[[clang::blocking]]``, and ``[[clang::allocating]]``, with GNU-style variants as well. + The attributes declare constraints about a function's behavior pertaining to blocking and + heap memory allocation. Improvements to Clang's diagnostics ----------------------------------- +- Clang now emits an error instead of a warning for ``-Wundefined-internal`` + when compiling with `-pedantic-errors` to conform to the C standard + +- Clang now applies syntax highlighting to the code snippets it + prints. + +- Clang now diagnoses member template declarations with multiple declarators. + +- Clang now diagnoses use of the ``template`` keyword after declarative nested + name specifiers. + +- The ``-Wshorten-64-to-32`` diagnostic is now grouped under ``-Wimplicit-int-conversion`` instead + of ``-Wconversion``. Fixes #GH69444. + +- Clang now uses thousand separators when printing large numbers in integer overflow diagnostics. + Fixes #GH80939. + +- Clang now diagnoses friend declarations with an ``enum`` elaborated-type-specifier in language modes after C++98. + +- Added diagnostics for C11 keywords being incompatible with language standards + before C11, under a new warning group: ``-Wpre-c11-compat``. + +- Now diagnoses an enumeration constant whose value is larger than can be + represented by ``unsigned long long``, which can happen with a large constant + using the ``wb`` or ``uwb`` suffix. The maximal underlying type is currently + ``unsigned long long``, but this behavior may change in the future when Clang + implements + `WG14 N3029 `_. + (#GH69352). + +- Clang now diagnoses extraneous template parameter lists as a language extension. + +- Clang now diagnoses declarative nested name specifiers that name alias templates. -- Some template related diagnostics have been improved. +- Clang now diagnoses lambda function expressions being implicitly cast to boolean values, under ``-Wpointer-bool-conversion``. + Fixes #GH82512. + +- Clang now provides improved warnings for the ``cleanup`` attribute to detect misuse scenarios, + such as attempting to call ``free`` on an unallocated object. Fixes #GH79443. + +- Clang no longer warns when the ``bitand`` operator is used with boolean + operands, distinguishing it from potential typographical errors or unintended + bitwise operations. Fixes #GH77601. + +- Clang now correctly diagnoses no arguments to a variadic macro parameter as a C23/C++20 extension. + Fixes #GH84495. + +- Clang no longer emits a ``-Wexit-time destructors`` warning on static variables explicitly + annotated with the ``clang::always_destroy`` attribute. + Fixes #GH68686, #GH86486 + +- ``-Wmicrosoft``, ``-Wgnu``, or ``-pedantic`` is now required to diagnose C99 + flexible array members in a union or alone in a struct. Fixes GH#84565. + +- Clang now no longer diagnoses type definitions in ``offsetof`` in C23 mode. + Fixes #GH83658. + +- New ``-Wformat-signedness`` diagnostic that warn if the format string requires an + unsigned argument and the argument is signed and vice versa. + +- Clang now emits ``unused argument`` warning when the -fmodule-output flag is used + with an input that is not of type c++-module. + +- Clang emits a ``-Wreturn-stack-address`` warning if a function returns a pointer or + reference to a struct literal. Fixes #GH8678 + +- Clang emits a ``-Wunused-but-set-variable`` warning on C++ variables whose declaration + (with initializer) entirely consist the condition expression of a if/while/for construct + but are not actually used in the body of the if/while/for construct. Fixes #GH41447 + +- Clang emits a diagnostic when a tentative array definition is assumed to have + a single element, but that diagnostic was never given a diagnostic group. + Added the ``-Wtentative-definition-array`` warning group to cover this. + Fixes #GH87766 + +- Clang now uses the correct type-parameter-key (``class`` or ``typename``) when printing + template template parameter declarations. + +- 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++ - - void foo() { template int i; } // error: templates can only be declared in namespace or class scope - struct S { - template int i; // error: non-static data member 'i' cannot be declared as a template + template + struct A { + int f() { + return this->x; // error: no member named 'x' in 'A' + } }; +- Clang emits a ``-Wparentheses`` warning for expressions with consecutive comparisons like ``x < y < z``. + Fixes #GH20456. + +- Clang no longer emits a "declared here" note for a builtin function that has no declaration in source. + Fixes #GH93369. + +- Clang now has an improved error message for captures that refer to a class member. + Fixes #GH94764. + +- Clang now diagnoses unsupported class declarations for ``std::initializer_list`` when they are + used rather than when they are needed for constant evaluation or when code is generated for them. + The check is now stricter to prevent crashes for some unsupported declarations (Fixes #GH95495). + +- Clang now diagnoses dangling cases where a pointer is assigned to a temporary + that will be destroyed at the end of the full expression. + Fixes #GH54492. + +- Clang now shows implicit deduction guides when diagnosing overload resolution failure. #GH92393. + +- Clang no longer emits a "no previous prototype" warning for Win32 entry points under ``-Wmissing-prototypes``. + Fixes #GH94366. + +- For the ARM target, calling an interrupt handler from another function is now an error. #GH95359. + +- Clang now diagnoses integer constant expressions that are folded to a constant value as an extension in more circumstances. Fixes #GH59863 + +- Clang now diagnoses dangling assignments for pointer-like objects (annotated with `[[gsl::Pointer]]`) under `-Wdangling-assignment-gsl` (off by default) + Fixes #GH63310. + +- Clang now has improved diagnostics for functions with explicit 'this' parameters. Fixes #GH97878 + Improvements to Clang's time-trace ---------------------------------- +- Clang now specifies that using ``auto`` in a lambda parameter is a C++14 extension when + appropriate. (`#46059: `_). + Improvements to Coverage Mapping -------------------------------- +- Macros defined in system headers are not expanded in coverage + mapping. Conditional expressions in system header macros are no + longer taken into account for branch coverage. They can be included + with ``-mllvm -system-headers-coverage``. + (`#78920: `_) +- MC/DC Coverage has been improved. + (`#82448: `_) + + - The maximum number of conditions is no longer limited to 6. See + `this ` for + more details. + Bug Fixes in This Version ------------------------- +- Clang's ``-Wundefined-func-template`` no longer warns on pure virtual + functions. (#GH74016) + +- Fixed missing warnings when comparing mismatched enumeration constants + in C (#GH29217) + +- Clang now accepts elaborated-type-specifiers that explicitly specialize + a member class template for an implicit instantiation of a class template. + +- Fixed missing warnings when doing bool-like conversions in C23 (#GH79435). +- Clang's ``-Wshadow`` no longer warns when an init-capture is named the same as + a class field unless the lambda can capture this. + Fixes (#GH71976) + +- Clang now accepts qualified partial/explicit specializations of variable templates that + are not nominable in the lookup context of the specialization. + +- Clang now doesn't produce false-positive warning `-Wconstant-logical-operand` + for logical operators in C23. + Fixes (#GH64356). + +- ``__is_trivially_relocatable`` no longer returns ``false`` for volatile-qualified types. + Fixes (#GH77091). + +- Clang no longer produces a false-positive `-Wunused-variable` warning + for variables created through copy initialization having side-effects in C++17 and later. + Fixes (#GH64356) (#GH79518). + +- Fix value of predefined macro ``__FUNCTION__`` in MSVC compatibility mode. + Fixes (#GH66114). + +- Clang now emits errors for explicit specializations/instatiations of lambda call + operator. + Fixes (#GH83267). + +- Fix crash on ill-formed partial specialization with CRTP. + Fixes (#GH89374). + +- Clang now correctly generates overloads for bit-precise integer types for + 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, + 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 + as ``_Complex float / float`` rather than ``_Complex float / _Complex float``), as mandated + by the C standard. This significantly improves codegen of `*` and `/` especially. + Fixes #GH31205. + +- Fixes an assertion failure on invalid code when trying to define member + functions in lambdas. + +- Fixed a regression in CTAD that a friend declaration that befriends itself may cause + incorrect constraint substitution. (#GH86769). + +- 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 + during instantiation, and instead will only diagnose it once, during checking + of the function template. + +- Clang now allows the value of unroll count to be zero in ``#pragma GCC unroll`` and ``#pragma unroll``. + The values of 0 and 1 block any unrolling of the loop. This keeps the same behavior with GCC. + Fixes (`#88624 `_). + +- Clang will no longer emit a duplicate -Wunused-value warning for an expression + `(A, B)` which evaluates to glvalue `B` that can be converted to non ODR-use. (#GH45783) + +- Clang now correctly disallows VLA type compound literals, e.g. ``(int[size]){}``, + as the C standard mandates. (#GH89835) + +- ``__is_array`` and ``__is_bounded_array`` no longer return ``true`` for + zero-sized arrays. Fixes (#GH54705). + +- Correctly reject declarations where a statement is required in C. + Fixes #GH92775 + +- Fixed `static_cast` to array of unknown bound. Fixes (#GH62863). + +- Fixed Clang crashing when failing to perform some C++ Initialization Sequences. (#GH98102) + +- ``__is_trivially_equality_comparable`` no longer returns true for types which + have a constrained defaulted comparison operator (#GH89293). + +- Fixed Clang from generating dangling StringRefs when deserializing Exprs & Stmts (#GH98667) + +- ``__has_unique_object_representations`` correctly handles arrays of unknown bounds of + types by ensuring they are complete and instantiating them if needed. Fixes (#GH95311). + +- ``typeof_unqual`` now properly removes type qualifiers from arrays and their element types. (#GH92667) + +- Fixed an assertion failure when a template non-type parameter contains + an invalid expression. Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- Fix crash when atomic builtins are called with pointer to zero-size struct (#GH90330) + +- Clang now allows pointee types of atomic builtin arguments to be complete template types + that was not instantiated elsewhere. + Bug Fixes to Attribute Support ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Bug Fixes to C++ Support ^^^^^^^^^^^^^^^^^^^^^^^^ +- Fix crash when calling the constructor of an invalid class. + (#GH10518) (#GH67914) (#GH78388) +- Fix crash when using lifetimebound attribute in function with trailing return. + (#GH73619) +- Addressed an issue where constraints involving injected class types are perceived + distinct from its specialization types. (#GH56482) +- Fixed a bug where variables referenced by requires-clauses inside + nested generic lambdas were not properly injected into the constraint scope. (#GH73418) +- Fixed a crash where substituting into a requires-expression that refers to function + parameters during the equivalence determination of two constraint expressions. + (#GH74447) +- Fixed deducing auto& from const int in template parameters of partial + specializations. (#GH77189) +- Fix for crash when using a erroneous type in a return statement. + (#GH63244) (#GH79745) +- Fixed an out-of-bounds error caused by building a recovery expression for ill-formed + function calls while substituting into constraints. (#GH58548) +- Fix incorrect code generation caused by the object argument + of ``static operator()`` and ``static operator[]`` calls not being evaluated. (#GH67976) +- Fix crash and diagnostic with const qualified member operator new. + Fixes (#GH79748) +- Fixed a crash where substituting into a requires-expression that involves parameter packs + during the equivalence determination of two constraint expressions. (#GH72557) +- Fix a crash when specializing an out-of-line member function with a default + parameter where we did an incorrect specialization of the initialization of + the default parameter. (#GH68490) +- Fix a crash when trying to call a varargs function that also has an explicit object parameter. + Fixes (#GH80971) +- Reject explicit object parameters on `new` and `delete` operators. (#GH82249) +- Fix a crash when trying to call a varargs function that also has an explicit object parameter. (#GH80971) +- Fixed a bug where abbreviated function templates would append their invented template parameters to + an empty template parameter lists. +- Fix parsing of abominable function types inside type traits. Fixes #GH77585 +- Clang now classifies aggregate initialization in C++17 and newer as constant + or non-constant more accurately. Previously, only a subset of the initializer + elements were considered, misclassifying some initializers as constant. Partially fixes + #GH80510. +- Clang now ignores top-level cv-qualifiers on function parameters in template partial orderings. (#GH75404) +- No longer reject valid use of the ``_Alignas`` specifier when declaring a + local variable, which is supported as a C11 extension in C++. Previously, it + was only accepted at namespace scope but not at local function scope. +- Clang no longer tries to call consteval constructors at runtime when they appear in a member initializer. (#GH82154) +- Fix crash when using an immediate-escalated function at global scope. (#GH82258) +- Correctly immediate-escalate lambda conversion functions. (#GH82258) +- Fixed an issue where template parameters of a nested abbreviated generic lambda within + a requires-clause lie at the same depth as those of the surrounding lambda. This, + in turn, results in the wrong template argument substitution during constraint checking. + (#GH78524) +- Clang no longer instantiates the exception specification of discarded candidate function + templates when determining the primary template of an explicit specialization. +- Fixed a crash in Microsoft compatibility mode where unqualified dependent base class + lookup searches the bases of an incomplete class. +- Fix a crash when an unresolved overload set is encountered on the RHS of a ``.*`` operator. + (#GH53815) +- In ``__restrict``-qualified member functions, attach ``__restrict`` to the pointer type of + ``this`` rather than the pointee type. + Fixes (#GH82941), (#GH42411) and (#GH18121). +- Clang now properly reports supported C++11 attributes when using + ``__has_cpp_attribute`` and parses attributes with arguments in C++03 (#GH82995) +- Clang now properly diagnoses missing 'default' template arguments on a variety + of templates. Previously we were diagnosing on any non-function template + instead of only on class, alias, and variable templates, as last updated by + CWG2032. Fixes (#GH83461) +- Fixed an issue where an attribute on a declarator would cause the attribute to + be destructed prematurely. This fixes a pair of Chromium that were brought to + our attention by an attempt to fix in (#GH77703). Fixes (#GH83385). +- Fix evaluation of some immediate calls in default arguments. + Fixes (#GH80630) +- Fixed an issue where the ``RequiresExprBody`` was involved in the lambda dependency + calculation. (#GH56556), (#GH82849). +- Fix a bug where overload resolution falsely reported an ambiguity when it was comparing + a member-function against a non member function or a member-function with an + explicit object parameter against a member function with no explicit object parameter + when one of the function had more specialized templates. Fixes #GH82509 and #GH74494 +- Clang now supports direct lambda calls inside of a type alias template declarations. + This addresses (#GH70601), (#GH76674), (#GH79555), (#GH81145) and (#GH82104). +- Allow access to a public template alias declaration that refers to friend's + private nested type. (#GH25708). +- Fixed a crash in constant evaluation when trying to access a + captured ``this`` pointer in a lambda with an explicit object parameter. + Fixes (#GH80997) +- Fix an issue where missing set friend declaration in template class instantiation. + Fixes (#GH84368). +- Fixed a crash while checking constraints of a trailing requires-expression of a lambda, that the + expression references to an entity declared outside of the lambda. (#GH64808) +- Clang's __builtin_bit_cast will now produce a constant value for records with empty bases. See: + (#GH82383) +- Fix a crash when instantiating a lambda that captures ``this`` outside of its context. Fixes (#GH85343). +- Fix an issue where a namespace alias could be defined using a qualified name (all name components + following the first `::` were ignored). +- Fix an out-of-bounds crash when checking the validity of template partial specializations. (part of #GH86757). +- Fix an issue caused by not handling invalid cases when substituting into the parameter mapping of a constraint. Fixes (#GH86757). +- Fixed a bug that prevented member function templates of class templates declared with a deduced return type + from being explicitly specialized for a given implicit instantiation of the class template. +- Fixed a crash when ``this`` is used in a dependent class scope function template specialization + that instantiates to a static member function. +- Fix crash when inheriting from a cv-qualified type. Fixes #GH35603 +- Fix a crash when the using enum declaration uses an anonymous enumeration. Fixes (#GH86790). +- Handled an edge case in ``getFullyPackExpandedSize`` so that we now avoid a false-positive diagnostic. (#GH84220) +- Clang now correctly tracks type dependence of by-value captures in lambdas with an explicit + object parameter. + Fixes (#GH70604), (#GH79754), (#GH84163), (#GH84425), (#GH86054), (#GH86398), and (#GH86399). +- Fix a crash when deducing ``auto`` from an invalid dereference (#GH88329). +- Fix a crash in requires expression with templated base class member function. Fixes (#GH84020). +- Fix a crash caused by defined struct in a type alias template when the structure + has fields with dependent type. Fixes (#GH75221). +- Fix the Itanium mangling of lambdas defined in a member of a local class (#GH88906) +- Fixed a crash when trying to evaluate a user-defined ``static_assert`` message whose ``size()`` + 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 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`` 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. +- Fix an assertion failure when parsing an invalid members of an anonymous class. (#GH85447) +- Fixed a misuse of ``UnresolvedLookupExpr`` for ill-formed templated expressions. Fixes (#GH48673), (#GH63243) + and (#GH88832). +- Clang now defers all substitution into the exception specification of a function template specialization + until the noexcept-specifier is instantiated. +- Fix a crash when an implicitly declared ``operator==`` function with a trailing requires-clause has its + constraints compared to that of another declaration. +- Fix a bug where explicit specializations of member functions/function templates would have substitution + performed incorrectly when checking constraints. Fixes (#GH90349). +- Clang now allows constrained member functions to be explicitly specialized for an implicit instantiation + of a class template. +- Fix a C++23 bug in implementation of P2564R3 which evaluates immediate invocations in place + within initializers for variables that are usable in constant expressions or are constant + initialized, rather than evaluating them as a part of the larger manifestly constant evaluated + expression. +- Fix a bug in access control checking due to dealyed checking of friend declaration. Fixes (#GH12361). +- Correctly treat the compound statement of an ``if consteval`` as an immediate context. Fixes (#GH91509). +- When partial ordering alias templates against template template parameters, + allow pack expansions when the alias has a fixed-size parameter list. Fixes (#GH62529). +- Clang now ignores template parameters only used within the exception specification of candidate function + templates during partial ordering when deducing template arguments from a function declaration or when + taking the address of a function template. +- Fix a bug with checking constrained non-type template parameters for equivalence. Fixes (#GH77377). +- Fix a bug where the last argument was not considered when considering the most viable function for + explicit object argument member functions. Fixes (#GH92188). +- Fix a C++11 crash when a non-const non-static member function is defined out-of-line with + the ``constexpr`` specifier. Fixes (#GH61004). +- Clang no longer transforms dependent qualified names into implicit class member access expressions + until it can be determined whether the name is that of a non-static member. +- Clang now correctly diagnoses when the current instantiation is used as an incomplete base class. +- Clang no longer treats ``constexpr`` class scope function template specializations of non-static members + as implicitly ``const`` in language modes after C++11. +- Fixed a crash when trying to emit captures in a lambda call operator with an explicit object + parameter that is called on a derived type of the lambda. + Fixes (#GH87210), (GH89541). +- Clang no longer tries to check if an expression is immediate-escalating in an unevaluated context. + Fixes (#GH91308). +- Fix a crash caused by a regression in the handling of ``source_location`` + in dependent contexts. Fixes (#GH92680). +- Fixed a crash when diagnosing failed conversions involving template parameter + packs. (#GH93076) +- Fixed a regression introduced in Clang 18 causing a static function overloading a non-static function + with the same parameters not to be diagnosed. (Fixes #GH93456). +- Clang now diagnoses unexpanded parameter packs in attributes. (Fixes #GH93269). +- Clang now allows ``@$``` in raw string literals. Fixes (#GH93130). +- Fix an assertion failure when checking invalid ``this`` usage in the wrong context. (Fixes #GH91536). +- Clang no longer models dependent NTTP arguments as ``TemplateParamObjectDecl`` s. Fixes (#GH84052). +- Fix incorrect merging of modules which contain using declarations which shadow + other declarations. This could manifest as ODR checker false positives. + Fixes (`#80252 `_) +- Fix a regression introduced in Clang 18 causing incorrect overload resolution in the presence of functions only + differering by their constraints when only one of these function was variadic. +- Fix a crash when a variable is captured by a block nested inside a lambda. (Fixes #GH93625). +- Fixed a type constraint substitution issue involving a generic lambda expression. (#GH93821) +- Fix a crash caused by improper use of ``__array_extent``. (#GH80474) +- Fixed several bugs in capturing variables within unevaluated contexts. (#GH63845), (#GH67260), (#GH69307), + (#GH88081), (#GH89496), (#GH90669), (#GH91633) and (#GH97453). +- Fixed a crash in constraint instantiation under nested lambdas with dependent parameters. +- Fixed handling of brace ellison when building deduction guides. (#GH64625), (#GH83368). +- Fixed a failed assertion when attempting to convert an integer representing the difference + between the addresses of two labels (a GNU extension) to a pointer within a constant expression. (#GH95366). +- Fix immediate escalation bugs in the presence of dependent call arguments. (#GH94935) +- Clang now diagnoses explicit specializations with storage class specifiers in all contexts. +- Fix an assertion failure caused by parsing a lambda used as a default argument for the value of a + forward-declared class. (#GH93512). +- Fixed a bug in access checking inside return-type-requirement of compound requirements. (#GH93788). +- Fixed an assertion failure about invalid conversion when calling lambda. (#GH96205). +- Fixed a bug where the first operand of binary ``operator&`` would be transformed as if it was the operand + of the address of operator. (#GH97483). +- Fixed an assertion failure about a constant expression which is a known integer but is not + evaluated to an integer. (#GH96670). +- Fixed a bug where references to lambda capture inside a ``noexcept`` specifier were not correctly + instantiated. (#GH95735). +- Fixed a CTAD substitution bug involving type aliases that reference outer template parameters. (#GH94614). +- Clang now correctly handles unexpanded packs in the template parameter list of a generic lambda expression + (#GH48937) +- Fix a crash when parsing an invalid type-requirement in a requires expression. (#GH51868) +- Fix parsing of built-in type-traits such as ``__is_pointer`` in libstdc++ headers. (#GH95598) +- Fixed failed assertion when resolving context of defaulted comparison method outside of struct. (#GH96043). +- Clang now diagnoses explicit object parameters in member pointers and other contexts where they should not appear. + Fixes (#GH85992). +- Fixed a crash-on-invalid bug involving extraneous template parameter with concept substitution. (#GH73885) + Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ +- Clang now properly preserves ``FoundDecls`` within a ``ConceptReference``. (#GH82628) +- The presence of the ``typename`` keyword is now stored in ``TemplateTemplateParmDecl``. +- Fixed malformed AST generated for anonymous union access in templates. (#GH90842) +- Improved preservation of qualifiers and sugar in `TemplateNames`, including + template keyword. Miscellaneous Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^ +- Fixed an infinite recursion in ASTImporter, on return type declared inside + body of C++11 lambda without trailing return (#GH68775). +- Fixed declaration name source location of instantiated function definitions (GH71161). +- Improve diagnostic output to print an expression instead of 'no argument` when comparing Values as template arguments. + Miscellaneous Clang Crashes Fixed ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- Do not attempt to dump the layout of dependent types or invalid declarations + when ``-fdump-record-layouts-complete`` is passed. Fixes #GH83684. +- Unhandled StructuralValues in the template differ (#GH93068). + OpenACC Specific Changes ------------------------ @@ -159,36 +1121,131 @@ AMDGPU Support X86 Support ^^^^^^^^^^^ +- Remove knl/knm specific ISA supports: AVX512PF, AVX512ER, PREFETCHWT1 +- Support has been removed for the AMD "3DNow!" instruction-set. + Neither modern AMD CPUs, nor any Intel CPUs implement these + instructions, and they were never widely used. + + * The options ``-m3dnow`` and ``-m3dnowa`` are no longer honored, and will emit a warning if used. + * The macros ``__3dNOW__`` and ``__3dNOW_A__`` are no longer ever set by the compiler. + * The header ```` is deprecated, and emits a warning if included. + * The 3dNow intrinsic functions have been removed: ``_m_femms``, + ``_m_pavgusb``, ``_m_pf2id``, ``_m_pfacc``, ``_m_pfadd``, + ``_m_pfcmpeq``, ``_m_pfcmpge``, ``_m_pfcmpgt``, ``_m_pfmax``, + ``_m_pfmin``, ``_m_pfmul``, ``_m_pfrcp``, ``_m_pfrcpit1``, + ``_m_pfrcpit2``, ``_m_pfrsqrt``, ``_m_pfrsqrtit1``, ``_m_pfsub``, + ``_m_pfsubr``, ``_m_pi2fd``, ``_m_pmulhrw``, ``_m_pf2iw``, + ``_m_pfnacc``, ``_m_pfpnacc``, ``_m_pi2fw``, ``_m_pswapdsf``, + ``_m_pswapdsi``. + * The compiler builtins corresponding to each of the above + intrinsics have also been removed (``__builtin_ia32_femms``, and so on). + * "3DNow!" instructions remain supported in assembly code, including + inside inline-assembly. + Arm and AArch64 Support ^^^^^^^^^^^^^^^^^^^^^^^ +- ARMv7+ targets now default to allowing unaligned access, except Armv6-M, and + Armv8-M without the Main Extension. Baremetal targets should check that the + new default will work with their system configurations, since it requires + that SCTLR.A is 0, SCTLR.U is 1, and that the memory in question is + configured as "normal" memory. This brings Clang in-line with the default + settings for GCC and Arm Compiler. Aside from making Clang align with other + compilers, changing the default brings major performance and code size + improvements for most targets. We have not changed the default behavior for + ARMv6, but may revisit that decision in the future. Users can restore the old + behavior with -m[no-]unaligned-access. +- An alias identifier (rdma) has been added for targeting the AArch64 + Architecture Extension which uses Rounding Doubling Multiply Accumulate + instructions (rdm). The identifier is available on the command line as + a feature modifier for -march and -mcpu as well as via target attributes + like ``target_version`` or ``target_clones``. +- Support has been added for the following processors (-mcpu identifiers in parenthesis): + * Arm Cortex-R52+ (cortex-r52plus). + * Arm Cortex-R82AE (cortex-r82ae). + * Arm Cortex-A78AE (cortex-a78ae). + * Arm Cortex-A520AE (cortex-a520ae). + * Arm Cortex-A720AE (cortex-a720ae). + * Arm Cortex-A725 (cortex-a725). + * Arm Cortex-X925 (cortex-x925). + * Arm Neoverse-N3 (neoverse-n3). + * Arm Neoverse-V3 (neoverse-v3). + * Arm Neoverse-V3AE (neoverse-v3ae). + Android Support ^^^^^^^^^^^^^^^ Windows Support ^^^^^^^^^^^^^^^ +- The clang-cl ``/Ot`` compiler option ("optimize for speed", also implied by + ``/O2``) now maps to clang's ``-O3`` optimizataztion level instead of ``-O2``. + Users who prefer the old behavior can use ``clang-cl /Ot /clang:-O2 ...``. + +- Clang-cl now supports function targets with intrinsic headers. This allows + for runtime feature detection of intrinsics. Previously under clang-cl + ``immintrin.h`` and similar intrinsic headers would only include the intrinsics + if building with that feature enabled at compile time, e.g. ``avxintrin.h`` + would only be included if AVX was enabled at compile time. This was done to work + around include times from MSVC STL including ``intrin.h`` under clang-cl. + Clang-cl now provides ``intrin0.h`` for MSVC STL and therefore all intrinsic + features without requiring enablement at compile time. Fixes #GH53520 + +- Improved compile times with MSVC STL. MSVC provides ``intrin0.h`` which is a + header that only includes intrinsics that are used by MSVC STL to avoid the + use of ``intrin.h``. MSVC STL when compiled under clang uses ``intrin.h`` + instead. Clang-cl now provides ``intrin0.h`` for the same compiler throughput + purposes as MSVC. Clang-cl also provides ``yvals_core.h`` to redefine + ``_STL_INTRIN_HEADER`` to expand to ``intrin0.h`` instead of ``intrin.h``. + This also means that if all intrinsic features are enabled at compile time + including STL headers will no longer slow down compile times since ``intrin.h`` + is not included from MSVC STL. + +- When the target triple is `*-windows-msvc` strict aliasing is now disabled by default + to ensure compatibility with msvc. Previously strict aliasing was only disabled if the + driver mode was cl. + LoongArch Support ^^^^^^^^^^^^^^^^^ RISC-V Support ^^^^^^^^^^^^^^ +- ``__attribute__((rvv_vector_bits(N)))`` is now supported for RVV vbool*_t types. +- Profile names in ``-march`` option are now supported. +- Passing empty structs/unions as arguments in C++ is now handled correctly. The behavior is similar to GCC's. +- ``-m[no-]scalar-strict-align`` and ``-m[no-]vector-strict-align`` options have + been added to give separate control of whether scalar or vector misaligned + accesses may be created. ``-m[no-]strict-align`` applies to both scalar and + vector. + CUDA/HIP Language Changes ^^^^^^^^^^^^^^^^^^^^^^^^^ +- PTX is no longer included by default when compiling for CUDA. Using + ``--cuda-include-ptx=all`` will return the old behavior. + CUDA Support ^^^^^^^^^^^^ +- Clang now supports CUDA SDK up to 12.5 AIX Support ^^^^^^^^^^^ -NetBSD Support -^^^^^^^^^^^^^^ +- Introduced the ``-maix-small-local-dynamic-tls`` option to produce a faster + access sequence for local-dynamic TLS variables where the offset from the TLS + base is encoded as an immediate operand. + This access sequence is not used for TLS variables larger than 32KB, and is + currently only supported on 64-bit mode. 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 ^^^^^^^^^^^ @@ -198,44 +1255,134 @@ DWARF Support in Clang Floating Point Support in Clang ------------------------------- +- Add ``__builtin__fmaf16`` builtin for floating point types. + Fixed Point Support in Clang ---------------------------- +- Support fixed point precision macros according to ``7.18a.3`` of + `ISO/IEC TR 18037:2008 `_. + AST Matchers ------------ +- Fixes a long-standing performance issue in parent map generation for + ancestry-based matchers such as ``hasParent`` and ``hasAncestor``, making + them significantly faster. +- ``isInStdNamespace`` now supports Decl declared with ``extern "C++"``. +- Add ``isExplicitObjectMemberFunction``. +- Fixed ``forEachArgumentWithParam`` and ``forEachArgumentWithParamType`` to + not skip the explicit object parameter for operator calls. +- Fixed captureVars assertion failure if not capturesVariables. (#GH76425) +- ``forCallable`` now properly preserves binding on successful match. (#GH89657) + clang-format ------------ +- ``AlwaysBreakTemplateDeclarations`` is deprecated and renamed to + ``BreakTemplateDeclarations``. +- ``AlwaysBreakAfterReturnType`` is deprecated and renamed to + ``BreakAfterReturnType``. +- Handles Java switch expressions. +- Adds ``AllowShortCaseExpressionOnASingleLine`` option. +- Adds ``AlignCaseArrows`` suboption to ``AlignConsecutiveShortCaseStatements``. +- Adds ``LeftWithLastLine`` suboption to ``AlignEscapedNewlines``. +- Adds ``KeepEmptyLines`` option to deprecate ``KeepEmptyLinesAtEOF`` + and ``KeepEmptyLinesAtTheStartOfBlocks``. +- Add ``ExceptDoubleParentheses`` sub-option for ``SpacesInParensOptions`` + to override addition of spaces between multiple, non-redundant parentheses + similar to the rules used for ``RemoveParentheses``. + libclang -------- +- ``clang_getSpellingLocation`` now correctly resolves macro expansions; that + is, it returns the spelling location instead of the expansion location. + Static Analyzer --------------- New features ^^^^^^^^^^^^ +- The attribute ``[[clang::suppress]]`` can now be applied to declarations. + (#GH80371) + +- Support C++23 static operator calls. (#GH84972) + Crash and bug fixes ^^^^^^^^^^^^^^^^^^^ +- Fixed crashing on loops if the loop variable was declared in switch blocks + but not under any case blocks if ``unroll-loops=true`` analyzer config is + set. (#GH68819) + +- Fixed a crash in ``security.cert.env.InvalidPtr`` checker when accidentally + matched user-defined ``strerror`` and similar library functions. (#GH88181) + +- Fixed a crash when storing through an address that refers to the address of + a label. (#GH89185) + +- Z3 crosschecking (aka. Z3 refutation) is now bounded, and can't consume + more total time than the eymbolic execution itself. (#GH97298) + Improvements ^^^^^^^^^^^^ Moved checkers ^^^^^^^^^^^^^^ +- Moved ``alpha.cplusplus.ArrayDelete`` out of the ``alpha`` package + to ``cplusplus.ArrayDelete``. (#GH83985) + `Documentation `__. + +- Moved ``alpha.unix.Stream`` out of the ``alpha`` package to + ``unix.Stream``. (#GH89247) + `Documentation `__. + +- Moved ``alpha.unix.BlockInCriticalSection`` out of the ``alpha`` package to + ``unix.BlockInCriticalSection``. (#GH93815) + `Documentation `__. + +- Moved ``alpha.security.cert.pos.34c`` out of the ``alpha`` package to + ``security.PutenvStackArray``. (#GH92424, #GH93815) + `Documentation `__. + +- Moved ``alpha.core.SizeofPtr`` into ``clang-tidy`` + ``bugprone-sizeof-expression``. (#GH95118, #GH94356) + `Documentation `__. + .. _release-notes-sanitizers: Sanitizers ---------- +- ``-fsanitize=signed-integer-overflow`` now instruments signed arithmetic even + when ``-fwrapv`` is enabled. Previously, only division checks were enabled. + + Users with ``-fwrapv`` as well as a sanitizer group like + ``-fsanitize=undefined`` or ``-fsanitize=integer`` enabled may want to + manually disable potentially noisy signed integer overflow checks with + ``-fno-sanitize=signed-integer-overflow`` + +- ``-fsanitize=cfi -fsanitize-cfi-cross-dso`` (cross-DSO CFI instrumentation) + now generates the ``__cfi_check`` function with proper target-specific + attributes, for example allowing unwind table generation. + Python Binding Changes ---------------------- +- Exposed `CXRewriter` API as `class Rewriter`. +- Add some missing kinds from Index.h (CursorKind: 149-156, 272-320, 420-437. + TemplateArgumentKind: 5-9. TypeKind: 161-175 and 178). +- Add support for retrieving binary operator information through + Cursor.binary_operator(). + OpenMP Support -------------- +- Added support for the `[[omp::assume]]` attribute. + Additional Information ====================== diff --git a/clang/docs/index.rst b/clang/docs/index.rst index 9bae0bd83243bd..a35a867b96bd7e 100644 --- a/clang/docs/index.rst +++ b/clang/docs/index.rst @@ -92,7 +92,6 @@ Using Clang Tools ClangFormatStyleOptions ClangFormattedStatus ClangLinkerWrapper - ClangNVLinkWrapper ClangOffloadBundler ClangOffloadPackager ClangRepl diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 6d1c8ca8a2f961..608bd90fcc3ff9 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -738,12 +738,6 @@ class ASTContext : public RefCountedBase { } void Deallocate(void *Ptr) const {} - llvm::StringRef backupStr(llvm::StringRef S) const { - char *Buf = new (*this) char[S.size()]; - std::copy(S.begin(), S.end(), Buf); - return llvm::StringRef(Buf, S.size()); - } - /// Allocates a \c DeclListNode or returns one from the \c ListNodeFreeList /// pool. DeclListNode *AllocateDeclListNode(clang::NamedDecl *ND) { @@ -1293,7 +1287,7 @@ class ASTContext : public RefCountedBase { getPointerAuthVTablePointerDiscriminator(const CXXRecordDecl *RD); /// Return the "other" type-specific discriminator for the given type. - uint16_t getPointerAuthTypeDiscriminator(QualType T); + uint16_t getPointerAuthTypeDiscriminator(QualType T) const; /// Apply Objective-C protocol qualifiers to the given type. /// \param allowOnPointerType specifies if we can apply protocol diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index f86f1818110e6c..c2feac525c1ea6 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -4854,7 +4854,15 @@ class CXXFoldExpr : public Expr { CXXFoldExpr(QualType T, UnresolvedLookupExpr *Callee, SourceLocation LParenLoc, Expr *LHS, BinaryOperatorKind Opcode, SourceLocation EllipsisLoc, Expr *RHS, SourceLocation RParenLoc, - std::optional NumExpansions); + std::optional NumExpansions) + : Expr(CXXFoldExprClass, T, VK_PRValue, OK_Ordinary), + LParenLoc(LParenLoc), EllipsisLoc(EllipsisLoc), RParenLoc(RParenLoc), + NumExpansions(NumExpansions ? *NumExpansions + 1 : 0), Opcode(Opcode) { + SubExprs[SubExpr::Callee] = Callee; + SubExprs[SubExpr::LHS] = LHS; + SubExprs[SubExpr::RHS] = RHS; + setDependence(computeDependence(this)); + } CXXFoldExpr(EmptyShell Empty) : Expr(CXXFoldExprClass, Empty) {} diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 4825979a974d22..1293d0ddbc117d 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -902,7 +902,7 @@ def PatchableFunctionEntry : InheritableAttr, TargetSpecificAttr> { + "riscv64", "x86", "x86_64"]>> { let Spellings = [GCC<"patchable_function_entry">]; let Subjects = SubjectList<[Function, ObjCMethod]>; let Args = [UnsignedArgument<"Count">, DefaultIntArgument<"Offset", 0>]; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 99738812c81579..09cf4f80bd999d 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -5800,8 +5800,7 @@ takes precedence over the command line option ``-fpatchable-function-entry=N,M`` ``M`` defaults to 0 if omitted. This attribute is only supported on -aarch64/aarch64-be/loongarch32/loongarch64/riscv32/riscv64/i386/x86-64/ppc/ppc64 targets. -For ppc/ppc64 targets, AIX is still not supported. +aarch64/aarch64-be/loongarch32/loongarch64/riscv32/riscv64/i386/x86-64 targets. }]; } diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td index 12d7b8c0205ee9..08ece01009387d 100644 --- a/clang/include/clang/Basic/DiagnosticLexKinds.td +++ b/clang/include/clang/Basic/DiagnosticLexKinds.td @@ -952,6 +952,11 @@ def warn_module_conflict : Warning< InGroup; // C++20 modules +def err_module_decl_cannot_be_macros : Error< + "the module name in a module%select{| partition}0 declaration cannot contain " + "an object-like macro %1">; +def err_unxepected_paren_in_module_decl : Error< + "unexpected '(' after the module name in a module%select{| partition}0 declaration">; def err_header_import_semi_in_macro : Error< "semicolon terminating header import declaration cannot be produced " "by a macro">; diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index f8d50d12bb9351..12aab09f285567 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1260,9 +1260,6 @@ def warn_pragma_intrinsic_builtin : Warning< def warn_pragma_unused_expected_var : Warning< "expected '#pragma unused' argument to be a variable name">, InGroup; -// - #pragma mc_func -def err_pragma_mc_func_not_supported : - Error<"#pragma mc_func is not supported">; // - #pragma init_seg def warn_pragma_init_seg_unsupported_target : Warning< "'#pragma init_seg' is only supported when targeting a " diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 00affee1ea67f7..d60f32674ca3a6 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -949,9 +949,6 @@ def note_ptrauth_virtual_function_pointer_incomplete_arg_ret : def note_ptrauth_virtual_function_incomplete_arg_ret_type : Note<"%0 is incomplete">; -def err_ptrauth_indirect_goto_addrlabel_arithmetic : Error< - "%select{subtraction|addition}0 of address-of-label expressions is not " - "supported with ptrauth indirect gotos">; /// main() // static main() is not an error in C, just in C++. @@ -3495,7 +3492,7 @@ def err_attr_tlsmodel_arg : Error<"tls_model must be \"global-dynamic\", " def err_attr_codemodel_arg : Error<"code model '%0' is not supported on this target">; -def err_aix_attr_unsupported : Error<"%0 attribute is not yet supported on AIX">; +def err_aix_attr_unsupported_tls_model : Error<"TLS model '%0' is not yet supported on AIX">; def err_tls_var_aligned_over_maximum : Error< "alignment (%0) of thread-local variable %1 is greater than the maximum supported " @@ -5168,7 +5165,7 @@ def warn_cxx11_compat_variable_template : Warning< InGroup, DefaultIgnore; def err_template_variable_noparams : Error< "extraneous 'template<>' in declaration of variable %0">; -def err_template_member : Error<"non-static data member %0 cannot be declared as a template">; +def err_template_member : Error<"member %0 declared as a template">; def err_member_with_template_arguments : Error<"member %0 cannot have template arguments">; def err_template_member_noparams : Error< "extraneous 'template<>' in declaration of member %0">; @@ -7599,6 +7596,9 @@ def err_nested_non_static_member_use : Error< def warn_cxx98_compat_non_static_member_use : Warning< "use of non-static data member %0 in an unevaluated context is " "incompatible with C++98">, InGroup, DefaultIgnore; +def err_form_ptr_to_member_from_parenthesized_expr : Error< + "cannot form pointer to member from a parenthesized expression; " + "did you mean to remove the parentheses?">; def err_invalid_incomplete_type_use : Error< "invalid use of incomplete type %0">; def err_builtin_func_cast_more_than_one_arg : Error< diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def index dc71ef8f986923..2f864ff1c0edfe 100644 --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -108,11 +108,9 @@ FEATURE(ptrauth_calls, LangOpts.PointerAuthCalls) FEATURE(ptrauth_returns, LangOpts.PointerAuthReturns) FEATURE(ptrauth_vtable_pointer_address_discrimination, LangOpts.PointerAuthVTPtrAddressDiscrimination) FEATURE(ptrauth_vtable_pointer_type_discrimination, LangOpts.PointerAuthVTPtrTypeDiscrimination) -FEATURE(ptrauth_type_info_vtable_pointer_discrimination, LangOpts.PointerAuthTypeInfoVTPtrDiscrimination) FEATURE(ptrauth_member_function_pointer_type_discrimination, LangOpts.PointerAuthCalls) FEATURE(ptrauth_init_fini, LangOpts.PointerAuthInitFini) FEATURE(ptrauth_function_pointer_type_discrimination, LangOpts.PointerAuthFunctionTypeDiscrimination) -FEATURE(ptrauth_indirect_gotos, LangOpts.PointerAuthIndirectGotos) EXTENSION(swiftcc, PP.getTargetInfo().checkCallingConvention(CC_Swift) == clang::TargetInfo::CCCR_OK) diff --git a/clang/include/clang/Basic/IdentifierTable.h b/clang/include/clang/Basic/IdentifierTable.h index ae9ebd9f59154e..f40f74d0355ade 100644 --- a/clang/include/clang/Basic/IdentifierTable.h +++ b/clang/include/clang/Basic/IdentifierTable.h @@ -180,6 +180,10 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo { LLVM_PREFERRED_TYPE(bool) unsigned IsModulesImport : 1; + // True if this is the 'module' contextual keyword. + LLVM_PREFERRED_TYPE(bool) + unsigned IsModulesDecl : 1; + // True if this is a mangled OpenMP variant name. LLVM_PREFERRED_TYPE(bool) unsigned IsMangledOpenMPVariantName : 1; @@ -196,7 +200,7 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo { LLVM_PREFERRED_TYPE(bool) unsigned IsFinal : 1; - // 22 bits left in a 64-bit word. + // 21 bits left in a 64-bit word. // Managed by the language front-end. void *FETokenInfo = nullptr; @@ -212,8 +216,8 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo { IsCPPOperatorKeyword(false), NeedsHandleIdentifier(false), IsFromAST(false), ChangedAfterLoad(false), FEChangedAfterLoad(false), RevertedTokenID(false), OutOfDate(false), IsModulesImport(false), - IsMangledOpenMPVariantName(false), IsDeprecatedMacro(false), - IsRestrictExpansion(false), IsFinal(false) {} + IsModulesDecl(false), IsMangledOpenMPVariantName(false), + IsDeprecatedMacro(false), IsRestrictExpansion(false), IsFinal(false) {} public: IdentifierInfo(const IdentifierInfo &) = delete; @@ -520,6 +524,18 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo { RecomputeNeedsHandleIdentifier(); } + /// Determine whether this is the contextual keyword \c module. + bool isModulesDeclaration() const { return IsModulesDecl; } + + /// Set whether this identifier is the contextual keyword \c module. + void setModulesDeclaration(bool I) { + IsModulesDecl = I; + if (I) + NeedsHandleIdentifier = true; + else + RecomputeNeedsHandleIdentifier(); + } + /// Determine whether this is the mangled name of an OpenMP variant. bool isMangledOpenMPVariantName() const { return IsMangledOpenMPVariantName; } @@ -740,6 +756,8 @@ class IdentifierTable { // If this is the 'import' contextual keyword, mark it as such. if (Name == "import") II->setModulesImport(true); + else if (Name == "module") + II->setModulesDeclaration(true); return *II; } diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 834a6f6cd43e32..a6f36b23f07dc8 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -165,11 +165,9 @@ LANGOPT(ExperimentalLibrary, 1, 0, "enable unstable and experimental library fea LANGOPT(PointerAuthIntrinsics, 1, 0, "pointer authentication intrinsics") LANGOPT(PointerAuthCalls , 1, 0, "function pointer authentication") LANGOPT(PointerAuthReturns, 1, 0, "return pointer authentication") -LANGOPT(PointerAuthIndirectGotos, 1, 0, "indirect gotos pointer authentication") LANGOPT(PointerAuthAuthTraps, 1, 0, "pointer authentication failure traps") LANGOPT(PointerAuthVTPtrAddressDiscrimination, 1, 0, "incorporate address discrimination in authenticated vtable pointers") LANGOPT(PointerAuthVTPtrTypeDiscrimination, 1, 0, "incorporate type discrimination in authenticated vtable pointers") -LANGOPT(PointerAuthTypeInfoVTPtrDiscrimination, 1, 0, "incorporate type and address discrimination in authenticated vtable pointers for std::type_info") LANGOPT(PointerAuthInitFini, 1, 0, "sign function pointers in init/fini arrays") BENIGN_LANGOPT(PointerAuthFunctionTypeDiscrimination, 1, 0, "Use type discrimination when signing function pointers") diff --git a/clang/include/clang/Basic/PointerAuthOptions.h b/clang/include/clang/Basic/PointerAuthOptions.h index 417b4b00648c78..197d63642ca6d2 100644 --- a/clang/include/clang/Basic/PointerAuthOptions.h +++ b/clang/include/clang/Basic/PointerAuthOptions.h @@ -25,11 +25,6 @@ namespace clang { constexpr unsigned PointerAuthKeyNone = -1; -/// Constant discriminator for std::type_info vtable pointers: 0xB1EA/45546 -/// The value is ptrauth_string_discriminator("_ZTVSt9type_info"), i.e., -/// the vtable type discriminator for classes derived from std::type_info. -constexpr uint16_t StdTypeInfoVTablePointerConstantDiscrimination = 0xB1EA; - class PointerAuthSchema { public: enum class Kind : unsigned { @@ -159,9 +154,6 @@ class PointerAuthSchema { }; struct PointerAuthOptions { - /// Do indirect goto label addresses need to be authenticated? - bool IndirectGotos = false; - /// The ABI for C function pointers. PointerAuthSchema FunctionPointers; @@ -183,9 +175,6 @@ struct PointerAuthOptions { /// The ABI for variadic C++ virtual function pointers. PointerAuthSchema CXXVirtualVariadicFunctionPointers; - - /// The ABI for C++ member function pointers. - PointerAuthSchema CXXMemberFunctionPointers; }; } // end namespace clang diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 7f4912b9bcd961..8db18c049b6d07 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -1003,6 +1003,9 @@ ANNOTATION(module_include) ANNOTATION(module_begin) ANNOTATION(module_end) +// Annotations for C++, Clang and Objective-C named modules. +ANNOTATION(module_name) + // Annotation for a header_name token that has been looked up and transformed // into the name of a header unit. ANNOTATION(header_unit) diff --git a/clang/include/clang/Basic/arm_neon.td b/clang/include/clang/Basic/arm_neon.td index 3098fa67e6a512..6390ba3f9fe5e5 100644 --- a/clang/include/clang/Basic/arm_neon.td +++ b/clang/include/clang/Basic/arm_neon.td @@ -289,7 +289,7 @@ def SPLATQ : WInst<"splat_laneq", ".(!Q)I", "UcUsUicsilPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUlhdQhQdPlQPl"> { let isLaneQ = 1; } -let TargetGuard = "bf16,neon" in { +let TargetGuard = "bf16" in { def SPLAT_BF : WInst<"splat_lane", ".(!q)I", "bQb">; def SPLATQ_BF : WInst<"splat_laneq", ".(!Q)I", "bQb"> { let isLaneQ = 1; @@ -323,7 +323,7 @@ def VMLSL : SOpInst<"vmlsl", "(>Q)(>Q)..", "csiUcUsUi", OP_MLSL>; def VQDMULH : SInst<"vqdmulh", "...", "siQsQi">; def VQRDMULH : SInst<"vqrdmulh", "...", "siQsQi">; -let TargetGuard = "v8.1a,neon" in { +let TargetGuard = "v8.1a" in { def VQRDMLAH : SInst<"vqrdmlah", "....", "siQsQi">; def VQRDMLSH : SInst<"vqrdmlsh", "....", "siQsQi">; } @@ -614,7 +614,7 @@ def A64_VQDMULH_LANE : SInst<"vqdmulh_lane", "..(!q)I", "siQsQi">; def A64_VQRDMULH_LANE : SInst<"vqrdmulh_lane", "..(!q)I", "siQsQi">; } -let TargetGuard = "v8.1a,neon" in { +let TargetGuard = "v8.1a" in { def VQRDMLAH_LANE : SOpInst<"vqrdmlah_lane", "...qI", "siQsQi", OP_QRDMLAH_LN>; def VQRDMLSH_LANE : SOpInst<"vqrdmlsh_lane", "...qI", "siQsQi", OP_QRDMLSH_LN>; } @@ -957,7 +957,7 @@ def VQDMLAL_HIGH : SOpInst<"vqdmlal_high", "(>Q)(>Q)QQ", "si", OP_QDMLALHi>; def VQDMLAL_HIGH_N : SOpInst<"vqdmlal_high_n", "(>Q)(>Q)Q1", "si", OP_QDMLALHi_N>; def VQDMLSL_HIGH : SOpInst<"vqdmlsl_high", "(>Q)(>Q)QQ", "si", OP_QDMLSLHi>; def VQDMLSL_HIGH_N : SOpInst<"vqdmlsl_high_n", "(>Q)(>Q)Q1", "si", OP_QDMLSLHi_N>; -let TargetGuard = "aes,neon" in { +let TargetGuard = "aes" in { def VMULL_P64 : SInst<"vmull", "(1>)11", "Pl">; def VMULL_HIGH_P64 : SOpInst<"vmull_high", "(1>)..", "HPl", OP_MULLHi_P64>; } @@ -1091,7 +1091,7 @@ let isLaneQ = 1 in { def VQDMULH_LANEQ : SInst<"vqdmulh_laneq", "..QI", "siQsQi">; def VQRDMULH_LANEQ : SInst<"vqrdmulh_laneq", "..QI", "siQsQi">; } -let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "v8.1a,neon" in { +let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "v8.1a" in { def VQRDMLAH_LANEQ : SOpInst<"vqrdmlah_laneq", "...QI", "siQsQi", OP_QRDMLAH_LN> { let isLaneQ = 1; } @@ -1122,14 +1122,14 @@ def VEXT_A64 : WInst<"vext", "...I", "dQdPlQPl">; //////////////////////////////////////////////////////////////////////////////// // Crypto -let ArchGuard = "__ARM_ARCH >= 8", TargetGuard = "aes,neon" in { +let ArchGuard = "__ARM_ARCH >= 8", TargetGuard = "aes" in { def AESE : SInst<"vaese", "...", "QUc">; def AESD : SInst<"vaesd", "...", "QUc">; def AESMC : SInst<"vaesmc", "..", "QUc">; def AESIMC : SInst<"vaesimc", "..", "QUc">; } -let ArchGuard = "__ARM_ARCH >= 8", TargetGuard = "sha2,neon" in { +let ArchGuard = "__ARM_ARCH >= 8", TargetGuard = "sha2" in { def SHA1H : SInst<"vsha1h", "11", "Ui">; def SHA1SU1 : SInst<"vsha1su1", "...", "QUi">; def SHA256SU0 : SInst<"vsha256su0", "...", "QUi">; @@ -1143,7 +1143,7 @@ def SHA256H2 : SInst<"vsha256h2", "....", "QUi">; def SHA256SU1 : SInst<"vsha256su1", "....", "QUi">; } -let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "sha3,neon" in { +let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "sha3" in { def BCAX : SInst<"vbcax", "....", "QUcQUsQUiQUlQcQsQiQl">; def EOR3 : SInst<"veor3", "....", "QUcQUsQUiQUlQcQsQiQl">; def RAX1 : SInst<"vrax1", "...", "QUl">; @@ -1153,14 +1153,14 @@ def XAR : SInst<"vxar", "...I", "QUl">; } } -let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "sha3,neon" in { +let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "sha3" in { def SHA512SU0 : SInst<"vsha512su0", "...", "QUl">; def SHA512su1 : SInst<"vsha512su1", "....", "QUl">; def SHA512H : SInst<"vsha512h", "....", "QUl">; def SHA512H2 : SInst<"vsha512h2", "....", "QUl">; } -let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "sm4,neon" in { +let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "sm4" in { def SM3SS1 : SInst<"vsm3ss1", "....", "QUi">; def SM3TT1A : SInst<"vsm3tt1a", "....I", "QUi">; def SM3TT1B : SInst<"vsm3tt1b", "....I", "QUi">; @@ -1170,7 +1170,7 @@ def SM3PARTW1 : SInst<"vsm3partw1", "....", "QUi">; def SM3PARTW2 : SInst<"vsm3partw2", "....", "QUi">; } -let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "sm4,neon" in { +let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "sm4" in { def SM4E : SInst<"vsm4e", "...", "QUi">; def SM4EKEY : SInst<"vsm4ekey", "...", "QUi">; } @@ -1227,7 +1227,7 @@ def FRINTZ_S64 : SInst<"vrnd", "..", "dQd">; def FRINTI_S64 : SInst<"vrndi", "..", "dQd">; } -let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "v8.5a,neon" in { +let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "v8.5a" in { def FRINT32X_S32 : SInst<"vrnd32x", "..", "fQf">; def FRINT32Z_S32 : SInst<"vrnd32z", "..", "fQf">; def FRINT64X_S32 : SInst<"vrnd64x", "..", "fQf">; @@ -1401,7 +1401,7 @@ def SCALAR_SQDMULH : SInst<"vqdmulh", "111", "SsSi">; // Scalar Integer Saturating Rounding Doubling Multiply Half High def SCALAR_SQRDMULH : SInst<"vqrdmulh", "111", "SsSi">; -let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "v8.1a,neon" in { +let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "v8.1a" in { //////////////////////////////////////////////////////////////////////////////// // Signed Saturating Rounding Doubling Multiply Accumulate Returning High Half def SCALAR_SQRDMLAH : SInst<"vqrdmlah", "1111", "SsSi">; @@ -1632,7 +1632,7 @@ def SCALAR_SQRDMULH_LANEQ : SOpInst<"vqrdmulh_laneq", "11QI", "SsSi", OP_SCALAR_ let isLaneQ = 1; } -let TargetGuard = "v8.1a,neon" in { +let TargetGuard = "v8.1a" in { // Signed Saturating Rounding Doubling Multiply Accumulate Returning High Half def SCALAR_SQRDMLAH_LANE : SOpInst<"vqrdmlah_lane", "111.I", "SsSi", OP_SCALAR_QRDMLAH_LN>; def SCALAR_SQRDMLAH_LANEQ : SOpInst<"vqrdmlah_laneq", "111QI", "SsSi", OP_SCALAR_QRDMLAH_LN> { @@ -1654,7 +1654,7 @@ def SCALAR_VDUP_LANEQ : IInst<"vdup_laneq", "1QI", "ScSsSiSlSfSdSUcSUsSUiSUlSPcS } // ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)" // ARMv8.2-A FP16 vector intrinsics for A32/A64. -let TargetGuard = "fullfp16,neon" in { +let TargetGuard = "fullfp16" in { // ARMv8.2-A FP16 one-operand vector intrinsics. @@ -1679,7 +1679,7 @@ let TargetGuard = "fullfp16,neon" in { def VCVTP_U16 : SInst<"vcvtp_u16", "U.", "hQh">; // Vector rounding - let ArchGuard = "__ARM_ARCH >= 8 && defined(__ARM_FEATURE_DIRECTED_ROUNDING)", TargetGuard = "fullfp16,neon" in { + let ArchGuard = "__ARM_ARCH >= 8 && defined(__ARM_FEATURE_DIRECTED_ROUNDING)", TargetGuard = "fullfp16" in { def FRINTZH : SInst<"vrnd", "..", "hQh">; def FRINTNH : SInst<"vrndn", "..", "hQh">; def FRINTAH : SInst<"vrnda", "..", "hQh">; @@ -1728,7 +1728,7 @@ let TargetGuard = "fullfp16,neon" in { // Max/Min def VMAXH : SInst<"vmax", "...", "hQh">; def VMINH : SInst<"vmin", "...", "hQh">; - let ArchGuard = "__ARM_ARCH >= 8 && defined(__ARM_FEATURE_NUMERIC_MAXMIN)", TargetGuard = "fullfp16,neon" in { + let ArchGuard = "__ARM_ARCH >= 8 && defined(__ARM_FEATURE_NUMERIC_MAXMIN)", TargetGuard = "fullfp16" in { def FMAXNMH : SInst<"vmaxnm", "...", "hQh">; def FMINNMH : SInst<"vminnm", "...", "hQh">; } @@ -1775,7 +1775,7 @@ def VEXTH : WInst<"vext", "...I", "hQh">; def VREV64H : WOpInst<"vrev64", "..", "hQh", OP_REV64>; // ARMv8.2-A FP16 vector intrinsics for A64 only. -let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "fullfp16,neon" in { +let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "fullfp16" in { // Vector rounding def FRINTIH : SInst<"vrndi", "..", "hQh">; @@ -1872,11 +1872,11 @@ let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)" in { } // v8.2-A dot product instructions. -let TargetGuard = "dotprod,neon" in { +let TargetGuard = "dotprod" in { def DOT : SInst<"vdot", "..(<<)(<<)", "iQiUiQUi">; def DOT_LANE : SOpInst<"vdot_lane", "..(<<)(<; } -let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "dotprod,neon" in { +let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "dotprod" in { // Variants indexing into a 128-bit vector are A64 only. def UDOT_LANEQ : SOpInst<"vdot_laneq", "..(<<)(< { let isLaneQ = 1; @@ -1884,7 +1884,7 @@ let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "d } // v8.2-A FP16 fused multiply-add long instructions. -let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "fp16fml,neon" in { +let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "fp16fml" in { def VFMLAL_LOW : SInst<"vfmlal_low", ">>..", "hQh">; def VFMLSL_LOW : SInst<"vfmlsl_low", ">>..", "hQh">; def VFMLAL_HIGH : SInst<"vfmlal_high", ">>..", "hQh">; @@ -1909,7 +1909,7 @@ let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "f } } -let TargetGuard = "i8mm,neon" in { +let TargetGuard = "i8mm" in { def VMMLA : SInst<"vmmla", "..(<<)(<<)", "QUiQi">; def VUSMMLA : SInst<"vusmmla", "..(<; @@ -1926,7 +1926,7 @@ let TargetGuard = "i8mm,neon" in { } } -let TargetGuard = "bf16,neon" in { +let TargetGuard = "bf16" in { def VDOT_BF : SInst<"vbfdot", "..BB", "fQf">; def VDOT_LANE_BF : SOpInst<"vbfdot_lane", "..B(Bq)I", "fQf", OP_BFDOT_LN>; def VDOT_LANEQ_BF : SOpInst<"vbfdot_laneq", "..B(BQ)I", "fQf", OP_BFDOT_LNQ> { @@ -1970,7 +1970,7 @@ multiclass VCMLA_ROTS { } // v8.3-A Vector complex addition intrinsics -let TargetGuard = "v8.3a,fullfp16,neon" in { +let TargetGuard = "v8.3a,fullfp16" in { def VCADD_ROT90_FP16 : SInst<"vcadd_rot90", "...", "h">; def VCADD_ROT270_FP16 : SInst<"vcadd_rot270", "...", "h">; def VCADDQ_ROT90_FP16 : SInst<"vcaddq_rot90", "QQQ", "h">; @@ -1978,7 +1978,7 @@ let TargetGuard = "v8.3a,fullfp16,neon" in { defm VCMLA_FP16 : VCMLA_ROTS<"h", "uint32x2_t", "uint32x4_t">; } -let TargetGuard = "v8.3a,neon" in { +let TargetGuard = "v8.3a" in { def VCADD_ROT90 : SInst<"vcadd_rot90", "...", "f">; def VCADD_ROT270 : SInst<"vcadd_rot270", "...", "f">; def VCADDQ_ROT90 : SInst<"vcaddq_rot90", "QQQ", "f">; @@ -1986,7 +1986,7 @@ let TargetGuard = "v8.3a,neon" in { defm VCMLA_F32 : VCMLA_ROTS<"f", "uint64x1_t", "uint64x2_t">; } -let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "v8.3a,neon" in { +let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "v8.3a" in { def VCADDQ_ROT90_FP64 : SInst<"vcaddq_rot90", "QQQ", "d">; def VCADDQ_ROT270_FP64 : SInst<"vcaddq_rot270", "QQQ", "d">; @@ -1994,7 +1994,7 @@ let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "v } // V8.2-A BFloat intrinsics -let TargetGuard = "bf16,neon" in { +let TargetGuard = "bf16" in { def VCREATE_BF : NoTestOpInst<"vcreate", ".(IU>)", "b", OP_CAST> { let BigEndianSafe = 1; } @@ -2058,14 +2058,14 @@ let TargetGuard = "bf16,neon" in { def SCALAR_CVT_F32_BF16 : SOpInst<"vcvtah_f32", "(1F>)(1!)", "b", OP_CVT_F32_BF16>; } -let ArchGuard = "!defined(__aarch64__) && !defined(__arm64ec__)", TargetGuard = "bf16,neon" in { +let ArchGuard = "!defined(__aarch64__) && !defined(__arm64ec__)", TargetGuard = "bf16" in { def VCVT_BF16_F32_A32_INTERNAL : WInst<"__a32_vcvt_bf16", "BQ", "f">; def VCVT_BF16_F32_A32 : SOpInst<"vcvt_bf16", "BQ", "f", OP_VCVT_BF16_F32_A32>; def VCVT_LOW_BF16_F32_A32 : SOpInst<"vcvt_low_bf16", "BQ", "Qf", OP_VCVT_BF16_F32_LO_A32>; def VCVT_HIGH_BF16_F32_A32 : SOpInst<"vcvt_high_bf16", "BBQ", "Qf", OP_VCVT_BF16_F32_HI_A32>; } -let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "bf16,neon" in { +let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "bf16" in { def VCVT_LOW_BF16_F32_A64_INTERNAL : WInst<"__a64_vcvtq_low_bf16", "BQ", "Hf">; def VCVT_LOW_BF16_F32_A64 : SOpInst<"vcvt_low_bf16", "BQ", "Qf", OP_VCVT_BF16_F32_LO_A64>; def VCVT_HIGH_BF16_F32_A64 : SInst<"vcvt_high_bf16", "BBQ", "Qf">; @@ -2077,14 +2077,14 @@ let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "b def COPYQ_LANEQ_BF16 : IOpInst<"vcopy_laneq", "..I.I", "Qb", OP_COPY_LN>; } -let ArchGuard = "!defined(__aarch64__) && !defined(__arm64ec__)", TargetGuard = "bf16,neon" in { +let ArchGuard = "!defined(__aarch64__) && !defined(__arm64ec__)", TargetGuard = "bf16" in { let BigEndianSafe = 1 in { defm VREINTERPRET_BF : REINTERPRET_CROSS_TYPES< "csilUcUsUiUlhfPcPsPlQcQsQiQlQUcQUsQUiQUlQhQfQPcQPsQPl", "bQb">; } } -let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "bf16,neon" in { +let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "bf16" in { let BigEndianSafe = 1 in { defm VVREINTERPRET_BF : REINTERPRET_CROSS_TYPES< "csilUcUsUiUlhfdPcPsPlQcQsQiQlQUcQUsQUiQUlQhQfQdQPcQPsQPlQPk", "bQb">; @@ -2092,7 +2092,7 @@ let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "b } // v8.9a/v9.4a LRCPC3 intrinsics -let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "rcpc3,neon" in { +let ArchGuard = "defined(__aarch64__) || defined(__arm64ec__)", TargetGuard = "rcpc3" in { def VLDAP1_LANE : WInst<"vldap1_lane", ".(c*!).I", "QUlQlUlldQdPlQPl">; def VSTL1_LANE : WInst<"vstl1_lane", "v*(.!)I", "QUlQlUlldQdPlQPl">; } diff --git a/clang/include/clang/Basic/arm_neon_incl.td b/clang/include/clang/Basic/arm_neon_incl.td index 3b8015daee6d90..b8155c187d1bcc 100644 --- a/clang/include/clang/Basic/arm_neon_incl.td +++ b/clang/include/clang/Basic/arm_neon_incl.td @@ -265,7 +265,7 @@ class Inst { string Prototype = p; string Types = t; string ArchGuard = ""; - string TargetGuard = "neon"; + string TargetGuard = ""; Operation Operation = o; bit BigEndianSafe = 0; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 69269cf7537b0d..8707e71f2a3199 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3998,10 +3998,6 @@ def ftime_trace_granularity_EQ : Joined<["-"], "ftime-trace-granularity=">, Grou HelpText<"Minimum time granularity (in microseconds) traced by time profiler">, Visibility<[ClangOption, CC1Option, CLOption, DXCOption]>, MarshallingInfoInt, "500u">; -def ftime_trace_verbose : Joined<["-"], "ftime-trace-verbose">, Group, - HelpText<"Make time trace capture verbose event details (e.g. source filenames). This can increase the size of the output by 2-3 times">, - Visibility<[ClangOption, CC1Option, CLOption, DXCOption]>, - MarshallingInfoFlag>; def ftime_trace_EQ : Joined<["-"], "ftime-trace=">, Group, HelpText<"Similar to -ftime-trace. Specify the JSON file or a directory which will contain the JSON file">, Visibility<[ClangOption, CC1Option, CLOption, DXCOption]>, @@ -4249,13 +4245,9 @@ defm ptrauth_vtable_pointer_address_discrimination : OptInCC1FFlag<"ptrauth-vtable-pointer-address-discrimination", "Enable address discrimination of vtable pointers">; defm ptrauth_vtable_pointer_type_discrimination : OptInCC1FFlag<"ptrauth-vtable-pointer-type-discrimination", "Enable type discrimination of vtable pointers">; -defm ptrauth_type_info_vtable_pointer_discrimination : - OptInCC1FFlag<"ptrauth-type-info-vtable-pointer-discrimination", "Enable type and address discrimination of vtable pointer of std::type_info">; defm ptrauth_init_fini : OptInCC1FFlag<"ptrauth-init-fini", "Enable signing of function pointers in init/fini arrays">; defm ptrauth_function_pointer_type_discrimination : OptInCC1FFlag<"ptrauth-function-pointer-type-discrimination", "Enable type discrimination on C function pointers">; -defm ptrauth_indirect_gotos : OptInCC1FFlag<"ptrauth-indirect-gotos", - "Enable signing and authentication of indirect goto targets">; } def fenable_matrix : Flag<["-"], "fenable-matrix">, Group, @@ -8086,13 +8078,6 @@ def source_date_epoch : Separate<["-"], "source-date-epoch">, } // let Visibility = [CC1Option] -defm err_pragma_mc_func_aix : BoolFOption<"err-pragma-mc-func-aix", - PreprocessorOpts<"ErrorOnPragmaMcfuncOnAIX">, DefaultFalse, - PosFlag, - NegFlag>; - //===----------------------------------------------------------------------===// // CUDA Options //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index 8241925c984763..5e5034fe01eb54 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -580,11 +580,6 @@ class FrontendOptions { /// Minimum time granularity (in microseconds) traced by time profiler. unsigned TimeTraceGranularity; - /// Make time trace capture verbose event details (e.g. source filenames). - /// This can increase the size of the output by 2-3 times. - LLVM_PREFERRED_TYPE(bool) - unsigned TimeTraceVerbose : 1; - /// Path which stores the output files for -ftime-trace std::string TimeTracePath; @@ -606,8 +601,7 @@ class FrontendOptions { EmitSymbolGraph(false), EmitExtensionSymbolGraphs(false), EmitSymbolGraphSymbolLabelsForTesting(false), EmitPrettySymbolGraphs(false), GenReducedBMI(false), - UseClangIRPipeline(false), TimeTraceGranularity(500), - TimeTraceVerbose(false) {} + UseClangIRPipeline(false), TimeTraceGranularity(500) {} /// getInputKindForExtension - Return the appropriate input kind for a file /// extension. For example, "c" would return Language::C. diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index fc7d0053f2323b..56aef99a3f38aa 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -615,10 +615,6 @@ class Preprocessor { ModuleDeclSeq ModuleDeclState; - /// Whether the module import expects an identifier next. Otherwise, - /// it expects a '.' or ';'. - bool ModuleImportExpectsIdentifier = false; - /// The identifier and source location of the currently-active /// \#pragma clang arc_cf_code_audited begin. std::pair PragmaARCCFCodeAuditedInfo; @@ -1744,11 +1740,14 @@ class Preprocessor { /// Lex a token, forming a header-name token if possible. bool LexHeaderName(Token &Result, bool AllowMacroExpansion = true); + /// Lex a module name or a partition name. + bool LexModuleName(Token &Result, bool IsImport); + /// Lex the parameters for an #embed directive, returns nullopt on error. std::optional LexEmbedParameters(Token &Current, bool ForHasEmbed); - bool LexAfterModuleImport(Token &Result); + bool LexAfterModuleDecl(Token &Result); void CollectPpImportSuffix(SmallVectorImpl &Toks); void makeModuleVisible(Module *M, SourceLocation Loc); @@ -3039,6 +3038,9 @@ class Preprocessor { static bool CLK_LexAfterModuleImport(Preprocessor &P, Token &Result) { return P.LexAfterModuleImport(Result); } + static bool CLK_LexAfterModuleDecl(Preprocessor &P, Token &Result) { + return P.LexAfterModuleDecl(Result); + } }; /// Abstract base class that describes a handler that will receive @@ -3071,6 +3073,77 @@ struct EmbedAnnotationData { /// Registry of pragma handlers added by plugins using PragmaHandlerRegistry = llvm::Registry; +/// Represents module or partition name token sequance. +/// +/// module-name: +/// module-name-qualifier[opt] identifier +/// +/// partition-name: [C++20] +/// : module-name-qualifier[opt] identifier +/// +/// module-name-qualifier +/// module-name-qualifier[opt] identifier . +/// +/// This class can only be created by the preprocessor and guarantees that the +/// two source array being contiguous in memory and only contains 3 kind of +/// tokens (identifier, '.' and ':'). And only available when the preprocessor +/// returns annot_module_name token. +/// +/// For exmaple: +/// +/// export module m.n:c.d +/// +/// The module name array has 3 tokens ['m', '.', 'n']. +/// The partition name array has 4 tokens [':', 'c', '.', 'd']. +/// +/// When import a partition in a named module fragment (Eg. import :part1;), +/// the module name array will be empty, and the partition name array has 2 +/// tokens. +/// +/// When we meet a private-module-fragment (Eg. module :private;), preprocessor +/// will not return a annot_module_name token, but will return 2 separate tokens +/// [':', 'kw_private']. + +class ModuleNameInfo { + friend class Preprocessor; + ArrayRef ModuleName; + ArrayRef PartitionName; + + ModuleNameInfo(ArrayRef AnnotToks, std::optional ColonIndex); + +public: + /// Return the contiguous token array. + ArrayRef getTokens() const { + if (ModuleName.empty()) + return PartitionName; + if (PartitionName.empty()) + return ModuleName; + return ArrayRef(ModuleName.begin(), PartitionName.end()); + } + bool hasModuleName() const { return !ModuleName.empty(); } + bool hasPartitionName() const { return !PartitionName.empty(); } + ArrayRef getModuleName() const { return ModuleName; } + ArrayRef getPartitionName() const { return PartitionName; } + Token getColonToken() const { + assert(hasPartitionName() && "Do not have a partition name"); + return getPartitionName().front(); + } + + /// Under the standard C++ Modules, the dot is just part of the module name, + /// and not a real hierarchy separator. Flatten such module names now. + std::string getFlatName() const; + + /// Build a module id path from the contiguous token array, both include + /// module name and partition name. + void getModuleIdPath( + SmallVectorImpl> &Path) const; + + /// Build a module id path from \param ModuleName. + static void getModuleIdPath( + ArrayRef ModuleName, + SmallVectorImpl> &Path); +}; + } // namespace clang #endif // LLVM_CLANG_LEX_PREPROCESSOR_H diff --git a/clang/include/clang/Lex/PreprocessorOptions.h b/clang/include/clang/Lex/PreprocessorOptions.h index 3f7dd9db18ba7d..c2e3d68333024a 100644 --- a/clang/include/clang/Lex/PreprocessorOptions.h +++ b/clang/include/clang/Lex/PreprocessorOptions.h @@ -211,10 +211,6 @@ class PreprocessorOptions { /// If set, the UNIX timestamp specified by SOURCE_DATE_EPOCH. std::optional SourceDateEpoch; - /// If set, the preprocessor reports an error when processing #pragma mc_func - /// on AIX. - bool ErrorOnPragmaMcfuncOnAIX = false; - public: PreprocessorOptions() : PrecompiledPreambleBytes(0, false) {} @@ -252,7 +248,6 @@ class PreprocessorOptions { PrecompiledPreambleBytes.first = 0; PrecompiledPreambleBytes.second = false; RetainExcludedConditionalBlocks = false; - ErrorOnPragmaMcfuncOnAIX = false; } }; diff --git a/clang/include/clang/Lex/Token.h b/clang/include/clang/Lex/Token.h index 4f29fb7d114159..2be3ad39529f05 100644 --- a/clang/include/clang/Lex/Token.h +++ b/clang/include/clang/Lex/Token.h @@ -235,6 +235,9 @@ class Token { assert(isAnnotation() && "Used AnnotVal on non-annotation token"); return PtrData; } + template T getAnnotationValueAs() const { + return static_cast(getAnnotationValue()); + } void setAnnotationValue(void *val) { assert(isAnnotation() && "Used AnnotVal on non-annotation token"); PtrData = val; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 613bab9120dfc0..afcdacf02583ae 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -221,7 +221,6 @@ class Parser : public CodeCompletionHandler { std::unique_ptr MaxTokensHerePragmaHandler; std::unique_ptr MaxTokensTotalPragmaHandler; std::unique_ptr RISCVPragmaHandler; - std::unique_ptr MCFuncPragmaHandler; std::unique_ptr CommentSemaHandler; @@ -3877,7 +3876,7 @@ class Parser : public CodeCompletionHandler { } bool ParseModuleName( - SourceLocation UseLoc, + SourceLocation UseLoc, ArrayRef ModuleName, SmallVectorImpl> &Path, bool IsImport); diff --git a/clang/lib/APINotes/APINotesFormat.h b/clang/lib/APINotes/APINotesFormat.h index 9d254dcc1c9eff..cd6456dbe37b27 100644 --- a/clang/lib/APINotes/APINotesFormat.h +++ b/clang/lib/APINotes/APINotesFormat.h @@ -24,7 +24,7 @@ const uint16_t VERSION_MAJOR = 0; /// API notes file minor version number. /// /// When the format changes IN ANY WAY, this number should be incremented. -const uint16_t VERSION_MINOR = 28; // nested tags +const uint16_t VERSION_MINOR = 27; // SingleDeclTableKey const uint8_t kSwiftCopyable = 1; const uint8_t kSwiftNonCopyable = 2; diff --git a/clang/lib/APINotes/APINotesYAMLCompiler.cpp b/clang/lib/APINotes/APINotesYAMLCompiler.cpp index 11cccc94a15f03..060e1fdaf2fd95 100644 --- a/clang/lib/APINotes/APINotesYAMLCompiler.cpp +++ b/clang/lib/APINotes/APINotesYAMLCompiler.cpp @@ -406,9 +406,6 @@ template <> struct ScalarEnumerationTraits { } // namespace llvm namespace { -struct Tag; -typedef std::vector TagsSeq; - struct Tag { StringRef Name; AvailabilityItem Availability; @@ -424,11 +421,9 @@ struct Tag { std::optional EnumConvenienceKind; std::optional SwiftCopyable; FunctionsSeq Methods; - - /// Tags that are declared within the current tag. Only the tags that have - /// corresponding API Notes will be listed. - TagsSeq Tags; }; + +typedef std::vector TagsSeq; } // namespace LLVM_YAML_IS_SEQUENCE_VECTOR(Tag) @@ -461,7 +456,6 @@ template <> struct MappingTraits { IO.mapOptional("EnumKind", T.EnumConvenienceKind); IO.mapOptional("SwiftCopyable", T.SwiftCopyable); IO.mapOptional("Methods", T.Methods); - IO.mapOptional("Tags", T.Tags); } }; } // namespace yaml @@ -964,17 +958,12 @@ class YAMLConverter { ContextInfo CI; auto TagCtxID = Writer.addContext(ParentContextID, T.Name, ContextKind::Tag, CI, SwiftVersion); - Context TagCtx(TagCtxID, ContextKind::Tag); for (const auto &CXXMethod : T.Methods) { CXXMethodInfo MI; convertFunction(CXXMethod, MI); Writer.addCXXMethod(TagCtxID, CXXMethod.Name, MI, SwiftVersion); } - - // Convert nested tags. - for (const auto &Tag : T.Tags) - convertTagContext(TagCtx, Tag, SwiftVersion); } void convertTopLevelItems(std::optional Ctx, diff --git a/clang/lib/AST/ASTConcept.cpp b/clang/lib/AST/ASTConcept.cpp index d8efbe44dbecbb..95e7ac1a3d775d 100644 --- a/clang/lib/AST/ASTConcept.cpp +++ b/clang/lib/AST/ASTConcept.cpp @@ -28,9 +28,11 @@ CreateUnsatisfiedConstraintRecord(const ASTContext &C, else { auto &SubstitutionDiagnostic = *Detail.get *>(); - StringRef Message = C.backupStr(SubstitutionDiagnostic.second); + unsigned MessageSize = SubstitutionDiagnostic.second.size(); + char *Mem = new (C) char[MessageSize]; + memcpy(Mem, SubstitutionDiagnostic.second.data(), MessageSize); auto *NewSubstDiag = new (C) std::pair( - SubstitutionDiagnostic.first, Message); + SubstitutionDiagnostic.first, StringRef(Mem, MessageSize)); new (TrailingObject) UnsatisfiedConstraintRecord(NewSubstDiag); } } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 7af9ea7105bb08..90bcbea072e397 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3407,7 +3407,7 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx, } } -uint16_t ASTContext::getPointerAuthTypeDiscriminator(QualType T) { +uint16_t ASTContext::getPointerAuthTypeDiscriminator(QualType T) const { assert(!T->isDependentType() && "cannot compute type discriminator of a dependent type"); @@ -3417,13 +3417,11 @@ uint16_t ASTContext::getPointerAuthTypeDiscriminator(QualType T) { if (T->isFunctionPointerType() || T->isFunctionReferenceType()) T = T->getPointeeType(); - if (T->isFunctionType()) { + if (T->isFunctionType()) encodeTypeForFunctionPointerAuth(*this, Out, T); - } else { - T = T.getUnqualifiedType(); - std::unique_ptr MC(createMangleContext()); - MC->mangleCanonicalTypeName(T, Out); - } + else + llvm_unreachable( + "type discrimination of non-function type not implemented yet"); return llvm::getPointerAuthStableSipHash(Str); } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 08ef09d353afc9..0c27f6f5df2da3 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -2949,7 +2949,7 @@ ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { if (auto *FoundEnum = dyn_cast(FoundDecl)) { if (!hasSameVisibilityContextAndLinkage(FoundEnum, D)) continue; - if (IsStructuralMatch(D, FoundEnum, !SearchName.isEmpty())) { + if (IsStructuralMatch(D, FoundEnum)) { EnumDecl *FoundDef = FoundEnum->getDefinition(); if (D->isThisDeclarationADefinition() && FoundDef) return Importer.MapImported(D, FoundDef); @@ -2960,12 +2960,7 @@ ExpectedDecl ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { } } - // In case of unnamed enums, we try to find an existing similar one, if none - // was found, perform the import always. - // Structural in-equivalence is not detected in this way here, but it may - // be found when the parent decl is imported (if the enum is part of a - // class). To make this totally exact a more difficult solution is needed. - if (SearchName && !ConflictingDecls.empty()) { + if (!ConflictingDecls.empty()) { ExpectedName NameOrErr = Importer.HandleNameConflict( SearchName, DC, IDNS, ConflictingDecls.data(), ConflictingDecls.size()); diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index b573c2713a3aaa..72d68f39a97a53 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -675,9 +675,6 @@ bool CXXRecordDecl::hasSubobjectAtOffsetZeroOfEmptyBaseType( if (!IsFirstField && !FD->isZeroSize(Ctx)) continue; - if (FD->isInvalidDecl()) - continue; - // -- If X is n array type, [visit the element type] QualType T = Ctx.getBaseElementType(FD->getType()); if (auto *RD = T->getAsCXXRecordDecl()) diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index e2c96431511262..8d2a1b5611ccc6 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -1944,22 +1944,3 @@ CXXParenListInitExpr *CXXParenListInitExpr::CreateEmpty(ASTContext &C, alignof(CXXParenListInitExpr)); return new (Mem) CXXParenListInitExpr(Empty, NumExprs); } - -CXXFoldExpr::CXXFoldExpr(QualType T, UnresolvedLookupExpr *Callee, - SourceLocation LParenLoc, Expr *LHS, - BinaryOperatorKind Opcode, - SourceLocation EllipsisLoc, Expr *RHS, - SourceLocation RParenLoc, - std::optional NumExpansions) - : Expr(CXXFoldExprClass, T, VK_PRValue, OK_Ordinary), LParenLoc(LParenLoc), - EllipsisLoc(EllipsisLoc), RParenLoc(RParenLoc), - NumExpansions(NumExpansions ? *NumExpansions + 1 : 0), Opcode(Opcode) { - // We rely on asserted invariant to distinguish left and right folds. - assert(((LHS && LHS->containsUnexpandedParameterPack()) != - (RHS && RHS->containsUnexpandedParameterPack())) && - "Exactly one of LHS or RHS should contain an unexpanded pack"); - SubExprs[SubExpr::Callee] = Callee; - SubExprs[SubExpr::LHS] = LHS; - SubExprs[SubExpr::RHS] = RHS; - setDependence(computeDependence(this)); -} diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index fcb382474ea624..5af712dd7257b1 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -12949,35 +12949,19 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, Info.Ctx.getTargetInfo().getMaxAtomicInlineWidth(); if (Size <= Info.Ctx.toCharUnitsFromBits(InlineWidthBits)) { if (BuiltinOp == Builtin::BI__c11_atomic_is_lock_free || - Size == CharUnits::One()) + Size == CharUnits::One() || + E->getArg(1)->isNullPointerConstant(Info.Ctx, + Expr::NPC_NeverValueDependent)) + // OK, we will inline appropriately-aligned operations of this size, + // and _Atomic(T) is appropriately-aligned. return Success(1, E); - // If the pointer argument can be evaluated to a compile-time constant - // integer (or nullptr), check if that value is appropriately aligned. - const Expr *PtrArg = E->getArg(1); - Expr::EvalResult ExprResult; - APSInt IntResult; - if (PtrArg->EvaluateAsRValue(ExprResult, Info.Ctx) && - ExprResult.Val.toIntegralConstant(IntResult, PtrArg->getType(), - Info.Ctx) && - IntResult.isAligned(Size.getAsAlign())) + QualType PointeeType = E->getArg(1)->IgnoreImpCasts()->getType()-> + castAs()->getPointeeType(); + if (!PointeeType->isIncompleteType() && + Info.Ctx.getTypeAlignInChars(PointeeType) >= Size) { + // OK, we will inline operations on this object. return Success(1, E); - - // Otherwise, check if the type's alignment against Size. - if (auto *ICE = dyn_cast(PtrArg)) { - // Drop the potential implicit-cast to 'const volatile void*', getting - // the underlying type. - if (ICE->getCastKind() == CK_BitCast) - PtrArg = ICE->getSubExpr(); - } - - if (auto PtrTy = PtrArg->getType()->getAs()) { - QualType PointeeType = PtrTy->getPointeeType(); - if (!PointeeType->isIncompleteType() && - Info.Ctx.getTypeAlignInChars(PointeeType) >= Size) { - // OK, we will inline operations on this object. - return Success(1, E); - } } } } diff --git a/clang/lib/AST/Interp/ByteCodeEmitter.cpp b/clang/lib/AST/Interp/ByteCodeEmitter.cpp index fee4432a8f6614..a3d4c7d7392da4 100644 --- a/clang/lib/AST/Interp/ByteCodeEmitter.cpp +++ b/clang/lib/AST/Interp/ByteCodeEmitter.cpp @@ -27,8 +27,7 @@ using namespace clang::interp; /// Similar information is available via ASTContext::BuiltinInfo, /// but that is not correct for our use cases. static bool isUnevaluatedBuiltin(unsigned BuiltinID) { - return BuiltinID == Builtin::BI__builtin_classify_type || - BuiltinID == Builtin::BI__builtin_os_log_format_buffer_size; + return BuiltinID == Builtin::BI__builtin_classify_type; } Function *ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) { diff --git a/clang/lib/AST/Interp/Compiler.cpp b/clang/lib/AST/Interp/Compiler.cpp index 0fc93c14131e68..ef579bc5d8972a 100644 --- a/clang/lib/AST/Interp/Compiler.cpp +++ b/clang/lib/AST/Interp/Compiler.cpp @@ -1698,8 +1698,10 @@ bool Compiler::VisitUnaryExprOrTypeTraitExpr( if (Kind == UETT_VectorElements) { if (const auto *VT = E->getTypeOfArgument()->getAs()) return this->emitConst(VT->getNumElements(), E); + + // FIXME: Apparently we need to catch the fact that a sizeless vector type + // has been passed and diagnose that (at run time). assert(E->getTypeOfArgument()->isSizelessVectorType()); - return this->emitSizelessVectorElementSize(E); } if (Kind == UETT_VecStep) { diff --git a/clang/lib/AST/Interp/Descriptor.cpp b/clang/lib/AST/Interp/Descriptor.cpp index 4f7e9eac76a323..f7d1201f625bb3 100644 --- a/clang/lib/AST/Interp/Descriptor.cpp +++ b/clang/lib/AST/Interp/Descriptor.cpp @@ -162,8 +162,7 @@ static void initField(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, } static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, - bool IsActive, const Descriptor *D, unsigned FieldOffset, - bool IsVirtualBase) { + bool IsActive, const Descriptor *D, unsigned FieldOffset) { assert(D); assert(D->ElemRecord); @@ -173,14 +172,13 @@ static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, Desc->Desc = D; Desc->IsInitialized = D->IsArray; Desc->IsBase = true; - Desc->IsVirtualBase = IsVirtualBase; Desc->IsActive = IsActive && !IsUnion; Desc->IsConst = IsConst || D->IsConst; Desc->IsFieldMutable = IsMutable || D->IsMutable; for (const auto &V : D->ElemRecord->bases()) initBase(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, V.Desc, - V.Offset, false); + V.Offset); for (const auto &F : D->ElemRecord->fields()) initField(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, IsUnion, F.Desc, F.Offset); @@ -189,11 +187,11 @@ static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsActive, const Descriptor *D) { for (const auto &V : D->ElemRecord->bases()) - initBase(B, Ptr, IsConst, IsMutable, IsActive, V.Desc, V.Offset, false); + initBase(B, Ptr, IsConst, IsMutable, IsActive, V.Desc, V.Offset); for (const auto &F : D->ElemRecord->fields()) initField(B, Ptr, IsConst, IsMutable, IsActive, D->ElemRecord->isUnion(), F.Desc, F.Offset); for (const auto &V : D->ElemRecord->virtual_bases()) - initBase(B, Ptr, IsConst, IsMutable, IsActive, V.Desc, V.Offset, true); + initBase(B, Ptr, IsConst, IsMutable, IsActive, V.Desc, V.Offset); } static void destroyField(Block *B, std::byte *Ptr, const Descriptor *D, diff --git a/clang/lib/AST/Interp/Descriptor.h b/clang/lib/AST/Interp/Descriptor.h index 0cc5d77c407e34..0dd97812e5a5c9 100644 --- a/clang/lib/AST/Interp/Descriptor.h +++ b/clang/lib/AST/Interp/Descriptor.h @@ -83,8 +83,6 @@ struct InlineDescriptor { /// Flag indicating if the field is an embedded base class. LLVM_PREFERRED_TYPE(bool) unsigned IsBase : 1; - LLVM_PREFERRED_TYPE(bool) - unsigned IsVirtualBase : 1; /// Flag indicating if the field is the active member of a union. LLVM_PREFERRED_TYPE(bool) unsigned IsActive : 1; diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index 8e96f78d905683..b2581b5f7b5d01 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -187,15 +187,10 @@ template bool CheckDivRem(InterpState &S, CodePtr OpPC, const T &LHS, const T &RHS) { if (RHS.isZero()) { const auto *Op = cast(S.Current->getExpr(OpPC)); - if constexpr (std::is_same_v) { - S.CCEDiag(Op, diag::note_expr_divide_by_zero) - << Op->getRHS()->getSourceRange(); - return true; - } - S.FFDiag(Op, diag::note_expr_divide_by_zero) << Op->getRHS()->getSourceRange(); - return false; + if constexpr (!std::is_same_v) + return false; } if (LHS.isSigned() && LHS.isMin() && RHS.isNegative() && RHS.isMinusOne()) { @@ -2741,15 +2736,6 @@ inline bool InvalidDeclRef(InterpState &S, CodePtr OpPC, return CheckDeclRef(S, OpPC, DR); } -inline bool SizelessVectorElementSize(InterpState &S, CodePtr OpPC) { - if (S.inConstantContext()) { - const SourceRange &ArgRange = S.Current->getRange(OpPC); - const Expr *E = S.Current->getExpr(OpPC); - S.CCEDiag(E, diag::note_constexpr_non_const_vectorelements) << ArgRange; - } - return false; -} - inline bool Assume(InterpState &S, CodePtr OpPC) { const auto Val = S.Stk.pop(); diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp index c170042144acca..98928b3c22d7c6 100644 --- a/clang/lib/AST/Interp/InterpBuiltin.cpp +++ b/clang/lib/AST/Interp/InterpBuiltin.cpp @@ -942,29 +942,15 @@ static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC, if (Ptr.isZero()) return returnBool(true); - if (Ptr.isIntegralPointer()) { - uint64_t IntVal = Ptr.getIntegerRepresentation(); - if (APSInt(APInt(64, IntVal, false), true).isAligned(Size.getAsAlign())) - return returnBool(true); - } - - const Expr *PtrArg = Call->getArg(1); - // Otherwise, check if the type's alignment against Size. - if (const auto *ICE = dyn_cast(PtrArg)) { - // Drop the potential implicit-cast to 'const volatile void*', getting - // the underlying type. - if (ICE->getCastKind() == CK_BitCast) - PtrArg = ICE->getSubExpr(); - } - - if (auto PtrTy = PtrArg->getType()->getAs()) { - QualType PointeeType = PtrTy->getPointeeType(); - if (!PointeeType->isIncompleteType() && - S.getCtx().getTypeAlignInChars(PointeeType) >= Size) { - // OK, we will inline operations on this object. - return returnBool(true); - } - } + QualType PointeeType = Call->getArg(1) + ->IgnoreImpCasts() + ->getType() + ->castAs() + ->getPointeeType(); + // OK, we will inline operations on this object. + if (!PointeeType->isIncompleteType() && + S.getCtx().getTypeAlignInChars(PointeeType) >= Size) + return returnBool(true); } } diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td index 9f29fa9272711a..49ebb156ab2fbd 100644 --- a/clang/lib/AST/Interp/Opcodes.td +++ b/clang/lib/AST/Interp/Opcodes.td @@ -733,8 +733,6 @@ def InvalidDeclRef : Opcode { let Args = [ArgDeclRef]; } -def SizelessVectorElementSize : Opcode; - def Assume : Opcode; def ArrayDecay : Opcode; diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp index 29579f5db40b64..229007c6d720a0 100644 --- a/clang/lib/AST/Interp/Pointer.cpp +++ b/clang/lib/AST/Interp/Pointer.cpp @@ -149,10 +149,6 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const { CharUnits Offset = CharUnits::Zero(); auto getFieldOffset = [&](const FieldDecl *FD) -> CharUnits { - // This shouldn't happen, but if it does, don't crash inside - // getASTRecordLayout. - if (FD->getParent()->isInvalidDecl()) - return CharUnits::Zero(); const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(FD->getParent()); unsigned FieldIndex = FD->getFieldIndex(); return ASTCtx.toCharUnitsFromBits(Layout.getFieldOffset(FieldIndex)); @@ -180,30 +176,18 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const { Path.push_back(APValue::LValuePathEntry::ArrayIndex(Index)); Ptr = Ptr.getArray(); } else { + // TODO: figure out if base is virtual bool IsVirtual = false; // Create a path entry for the field. const Descriptor *Desc = Ptr.getFieldDesc(); if (const auto *BaseOrMember = Desc->asDecl()) { - if (const auto *FD = dyn_cast(BaseOrMember)) { - Ptr = Ptr.getBase(); + Path.push_back(APValue::LValuePathEntry({BaseOrMember, IsVirtual})); + Ptr = Ptr.getBase(); + + if (const auto *FD = dyn_cast(BaseOrMember)) Offset += getFieldOffset(FD); - } else if (const auto *RD = dyn_cast(BaseOrMember)) { - IsVirtual = Ptr.isVirtualBaseClass(); - Ptr = Ptr.getBase(); - const Record *BaseRecord = Ptr.getRecord(); - - const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout( - cast(BaseRecord->getDecl())); - if (IsVirtual) - Offset += Layout.getVBaseClassOffset(RD); - else - Offset += Layout.getBaseClassOffset(RD); - } else { - Ptr = Ptr.getBase(); - } - Path.push_back(APValue::LValuePathEntry({BaseOrMember, IsVirtual})); continue; } llvm_unreachable("Invalid field type"); diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h index e351699023ba5c..7fa6a3230a4f95 100644 --- a/clang/lib/AST/Interp/Pointer.h +++ b/clang/lib/AST/Interp/Pointer.h @@ -487,9 +487,6 @@ class Pointer { } /// Checks if a structure is a base class. bool isBaseClass() const { return isField() && getInlineDesc()->IsBase; } - bool isVirtualBaseClass() const { - return isField() && getInlineDesc()->IsVirtualBase; - } /// Checks if the pointer points to a dummy value. bool isDummy() const { if (!isBlockPointer()) diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp index 8d7fe184882171..f734168e647bd9 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp @@ -524,21 +524,12 @@ void Environment::initialize() { assert(VarDecl != nullptr); setStorageLocation(*VarDecl, createObject(*VarDecl, nullptr)); } else if (Capture.capturesThis()) { - if (auto *Ancestor = InitialTargetFunc->getNonClosureAncestor()) { - const auto *SurroundingMethodDecl = cast(Ancestor); - QualType ThisPointeeType = - SurroundingMethodDecl->getFunctionObjectParameterType(); - setThisPointeeStorageLocation( - cast(createObject(ThisPointeeType))); - } else if (auto *FieldBeingInitialized = - dyn_cast(Parent->getLambdaContextDecl())) { - // This is in a field initializer, rather than a method. - setThisPointeeStorageLocation( - cast(createObject(QualType( - FieldBeingInitialized->getParent()->getTypeForDecl(), 0)))); - } else { - assert(false && "Unexpected this-capturing lambda context."); - } + const auto *SurroundingMethodDecl = + cast(InitialTargetFunc->getNonClosureAncestor()); + QualType ThisPointeeType = + SurroundingMethodDecl->getFunctionObjectParameterType(); + setThisPointeeStorageLocation( + cast(createObject(ThisPointeeType))); } } } else if (MethodDecl->isImplicitObjectMemberFunction()) { diff --git a/clang/lib/Basic/IdentifierTable.cpp b/clang/lib/Basic/IdentifierTable.cpp index 4f7ccaf4021d63..97d830214f8900 100644 --- a/clang/lib/Basic/IdentifierTable.cpp +++ b/clang/lib/Basic/IdentifierTable.cpp @@ -322,8 +322,9 @@ void IdentifierTable::AddKeywords(const LangOptions &LangOpts) { if (LangOpts.IEEE128) AddKeyword("__ieee128", tok::kw___float128, KEYALL, LangOpts, *this); - // Add the 'import' contextual keyword. + // Add the 'import' and 'module' contextual keyword. get("import").setModulesImport(true); + get("module").setModulesDeclaration(true); } /// Checks if the specified token kind represents a keyword in the diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index 6ba31cc05a0d75..6349fcf3dadd75 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -204,8 +204,7 @@ AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple, StringRef AArch64TargetInfo::getABI() const { return ABI; } bool AArch64TargetInfo::setABI(const std::string &Name) { - if (Name != "aapcs" && Name != "aapcs-soft" && Name != "darwinpcs" && - Name != "pauthtest") + if (Name != "aapcs" && Name != "aapcs-soft" && Name != "darwinpcs") return false; ABI = Name; @@ -219,12 +218,6 @@ bool AArch64TargetInfo::validateTarget(DiagnosticsEngine &Diags) const { Diags.Report(diag::err_target_unsupported_abi_with_fpu) << ABI; return false; } - if (getTriple().getEnvironment() == llvm::Triple::PAuthTest && - getTriple().getOS() != llvm::Triple::Linux) { - Diags.Report(diag::err_target_unsupported_abi_for_triple) - << getTriple().getEnvironmentName() << getTriple().getTriple(); - return false; - } return true; } diff --git a/clang/lib/Basic/Targets/LoongArch.cpp b/clang/lib/Basic/Targets/LoongArch.cpp index cb3fd12c48ddb6..75f71a337b7a49 100644 --- a/clang/lib/Basic/Targets/LoongArch.cpp +++ b/clang/lib/Basic/Targets/LoongArch.cpp @@ -200,24 +200,7 @@ void LoongArchTargetInfo::getTargetDefines(const LangOptions &Opts, // Define __loongarch_arch. StringRef ArchName = getCPU(); - if (ArchName == "loongarch64") { - if (HasFeatureLSX) { - // TODO: As more features of the V1.1 ISA are supported, a unified "v1.1" - // arch feature set will be used to include all sub-features belonging to - // the V1.1 ISA version. - if (HasFeatureFrecipe) - Builder.defineMacro("__loongarch_arch", - Twine('"') + "la64v1.1" + Twine('"')); - else - Builder.defineMacro("__loongarch_arch", - Twine('"') + "la64v1.0" + Twine('"')); - } else { - Builder.defineMacro("__loongarch_arch", - Twine('"') + ArchName + Twine('"')); - } - } else { - Builder.defineMacro("__loongarch_arch", Twine('"') + ArchName + Twine('"')); - } + Builder.defineMacro("__loongarch_arch", Twine('"') + ArchName + Twine('"')); // Define __loongarch_tune. StringRef TuneCPU = getTargetOpts().TuneCPU; @@ -233,8 +216,6 @@ void LoongArchTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__loongarch_simd_width", "128"); Builder.defineMacro("__loongarch_sx", Twine(1)); } - if (HasFeatureFrecipe) - Builder.defineMacro("__loongarch_frecipe", Twine(1)); StringRef ABI = getABI(); if (ABI == "lp64d" || ABI == "lp64f" || ABI == "lp64s") @@ -310,8 +291,6 @@ bool LoongArchTargetInfo::handleTargetFeatures( HasFeatureLASX = true; else if (Feature == "-ual") HasUnalignedAccess = false; - else if (Feature == "+frecipe") - HasFeatureFrecipe = true; } return true; } diff --git a/clang/lib/Basic/Targets/LoongArch.h b/clang/lib/Basic/Targets/LoongArch.h index c668ca7eca047a..5fc223483951e9 100644 --- a/clang/lib/Basic/Targets/LoongArch.h +++ b/clang/lib/Basic/Targets/LoongArch.h @@ -29,7 +29,6 @@ class LLVM_LIBRARY_VISIBILITY LoongArchTargetInfo : public TargetInfo { bool HasFeatureF; bool HasFeatureLSX; bool HasFeatureLASX; - bool HasFeatureFrecipe; public: LoongArchTargetInfo(const llvm::Triple &Triple, const TargetOptions &) @@ -38,7 +37,6 @@ class LLVM_LIBRARY_VISIBILITY LoongArchTargetInfo : public TargetInfo { HasFeatureF = false; HasFeatureLSX = false; HasFeatureLASX = false; - HasFeatureFrecipe = false; LongDoubleWidth = 128; LongDoubleAlign = 128; LongDoubleFormat = &llvm::APFloat::IEEEquad(); diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h index ba34ab2c7f3365..cdec41afd1a4b2 100644 --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -513,6 +513,15 @@ class LLVM_LIBRARY_VISIBILITY NetBSDI386TargetInfo public: NetBSDI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) : NetBSDTargetInfo(Triple, Opts) {} + + LangOptions::FPEvalMethodKind getFPEvalMethod() const override { + VersionTuple OsVersion = getTriple().getOSVersion(); + // New NetBSD uses the default rounding mode. + if (OsVersion >= VersionTuple(6, 99, 26) || OsVersion.getMajor() == 0) + return X86_32TargetInfo::getFPEvalMethod(); + // NetBSD before 6.99.26 defaults to "double" rounding. + return LangOptions::FPEvalMethodKind::FEM_Double; + } }; class LLVM_LIBRARY_VISIBILITY OpenBSDI386TargetInfo diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 234a9c16e39dfd..d582aba679ddc4 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -5034,8 +5034,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, ReturnValueSlot ReturnValue, const CallArgList &CallArgs, llvm::CallBase **callOrInvoke, bool IsMustTail, - SourceLocation Loc, - bool IsVirtualFunctionPointerThunk) { + SourceLocation Loc) { // FIXME: We no longer need the types from CallArgs; lift up and simplify. assert(Callee.isOrdinary() || Callee.isVirtual()); @@ -5099,11 +5098,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, RawAddress SRetAlloca = RawAddress::invalid(); llvm::Value *UnusedReturnSizePtr = nullptr; if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) { - if (IsVirtualFunctionPointerThunk && RetAI.isIndirect()) { - SRetPtr = makeNaturalAddressForPointer(CurFn->arg_begin() + - IRFunctionArgs.getSRetArgNo(), - RetTy, CharUnits::fromQuantity(1)); - } else if (!ReturnValue.isNull()) { + if (!ReturnValue.isNull()) { SRetPtr = ReturnValue.getAddress(); } else { SRetPtr = CreateMemTemp(RetTy, "tmp", &SRetAlloca); @@ -5882,131 +5877,119 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, CallArgs.freeArgumentMemory(*this); // Extract the return value. - RValue Ret; + RValue Ret = [&] { + switch (RetAI.getKind()) { + case ABIArgInfo::CoerceAndExpand: { + auto coercionType = RetAI.getCoerceAndExpandType(); - // If the current function is a virtual function pointer thunk, avoid copying - // the return value of the musttail call to a temporary. - if (IsVirtualFunctionPointerThunk) { - Ret = RValue::get(CI); - } else { - Ret = [&] { - switch (RetAI.getKind()) { - case ABIArgInfo::CoerceAndExpand: { - auto coercionType = RetAI.getCoerceAndExpandType(); - - Address addr = SRetPtr.withElementType(coercionType); - - assert(CI->getType() == RetAI.getUnpaddedCoerceAndExpandType()); - bool requiresExtract = isa(CI->getType()); - - unsigned unpaddedIndex = 0; - for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { - llvm::Type *eltType = coercionType->getElementType(i); - if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType)) - continue; - Address eltAddr = Builder.CreateStructGEP(addr, i); - llvm::Value *elt = CI; - if (requiresExtract) - elt = Builder.CreateExtractValue(elt, unpaddedIndex++); - else - assert(unpaddedIndex == 0); - Builder.CreateStore(elt, eltAddr); - } - [[fallthrough]]; - } + Address addr = SRetPtr.withElementType(coercionType); + + assert(CI->getType() == RetAI.getUnpaddedCoerceAndExpandType()); + bool requiresExtract = isa(CI->getType()); - case ABIArgInfo::InAlloca: - case ABIArgInfo::Indirect: { - RValue ret = convertTempToRValue(SRetPtr, RetTy, SourceLocation()); - if (UnusedReturnSizePtr) - PopCleanupBlock(); - return ret; + unsigned unpaddedIndex = 0; + for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { + llvm::Type *eltType = coercionType->getElementType(i); + if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType)) continue; + Address eltAddr = Builder.CreateStructGEP(addr, i); + llvm::Value *elt = CI; + if (requiresExtract) + elt = Builder.CreateExtractValue(elt, unpaddedIndex++); + else + assert(unpaddedIndex == 0); + Builder.CreateStore(elt, eltAddr); } + [[fallthrough]]; + } - case ABIArgInfo::Ignore: - // If we are ignoring an argument that had a result, make sure to - // construct the appropriate return value for our caller. - return GetUndefRValue(RetTy); - - case ABIArgInfo::Extend: - case ABIArgInfo::Direct: { - llvm::Type *RetIRTy = ConvertType(RetTy); - if (RetAI.getCoerceToType() == RetIRTy && - RetAI.getDirectOffset() == 0) { - switch (getEvaluationKind(RetTy)) { - case TEK_Complex: { - llvm::Value *Real = Builder.CreateExtractValue(CI, 0); - llvm::Value *Imag = Builder.CreateExtractValue(CI, 1); - return RValue::getComplex(std::make_pair(Real, Imag)); - } - case TEK_Aggregate: { - Address DestPtr = ReturnValue.getAddress(); - bool DestIsVolatile = ReturnValue.isVolatile(); + case ABIArgInfo::InAlloca: + case ABIArgInfo::Indirect: { + RValue ret = convertTempToRValue(SRetPtr, RetTy, SourceLocation()); + if (UnusedReturnSizePtr) + PopCleanupBlock(); + return ret; + } - if (!DestPtr.isValid()) { - DestPtr = CreateMemTemp(RetTy, "agg.tmp"); - DestIsVolatile = false; - } - EmitAggregateStore(CI, DestPtr, DestIsVolatile); - return RValue::getAggregate(DestPtr); - } - case TEK_Scalar: { - // If the argument doesn't match, perform a bitcast to coerce it. - // This can happen due to trivial type mismatches. - llvm::Value *V = CI; - if (V->getType() != RetIRTy) - V = Builder.CreateBitCast(V, RetIRTy); - return RValue::get(V); - } - } - llvm_unreachable("bad evaluation kind"); + case ABIArgInfo::Ignore: + // If we are ignoring an argument that had a result, make sure to + // construct the appropriate return value for our caller. + return GetUndefRValue(RetTy); + + case ABIArgInfo::Extend: + case ABIArgInfo::Direct: { + llvm::Type *RetIRTy = ConvertType(RetTy); + if (RetAI.getCoerceToType() == RetIRTy && RetAI.getDirectOffset() == 0) { + switch (getEvaluationKind(RetTy)) { + case TEK_Complex: { + llvm::Value *Real = Builder.CreateExtractValue(CI, 0); + llvm::Value *Imag = Builder.CreateExtractValue(CI, 1); + return RValue::getComplex(std::make_pair(Real, Imag)); } + case TEK_Aggregate: { + Address DestPtr = ReturnValue.getAddress(); + bool DestIsVolatile = ReturnValue.isVolatile(); - // If coercing a fixed vector from a scalable vector for ABI - // compatibility, and the types match, use the llvm.vector.extract - // intrinsic to perform the conversion. - if (auto *FixedDstTy = dyn_cast(RetIRTy)) { - llvm::Value *V = CI; - if (auto *ScalableSrcTy = - dyn_cast(V->getType())) { - if (FixedDstTy->getElementType() == - ScalableSrcTy->getElementType()) { - llvm::Value *Zero = llvm::Constant::getNullValue(CGM.Int64Ty); - V = Builder.CreateExtractVector(FixedDstTy, V, Zero, - "cast.fixed"); - return RValue::get(V); - } + if (!DestPtr.isValid()) { + DestPtr = CreateMemTemp(RetTy, "agg.tmp"); + DestIsVolatile = false; } + EmitAggregateStore(CI, DestPtr, DestIsVolatile); + return RValue::getAggregate(DestPtr); + } + case TEK_Scalar: { + // If the argument doesn't match, perform a bitcast to coerce it. This + // can happen due to trivial type mismatches. + llvm::Value *V = CI; + if (V->getType() != RetIRTy) + V = Builder.CreateBitCast(V, RetIRTy); + return RValue::get(V); } - - Address DestPtr = ReturnValue.getValue(); - bool DestIsVolatile = ReturnValue.isVolatile(); - - if (!DestPtr.isValid()) { - DestPtr = CreateMemTemp(RetTy, "coerce"); - DestIsVolatile = false; } + llvm_unreachable("bad evaluation kind"); + } - // An empty record can overlap other data (if declared with - // no_unique_address); omit the store for such types - as there is no - // actual data to store. - if (!isEmptyRecord(getContext(), RetTy, true)) { - // If the value is offset in memory, apply the offset now. - Address StorePtr = emitAddressAtOffset(*this, DestPtr, RetAI); - CreateCoercedStore(CI, StorePtr, DestIsVolatile, *this); + // If coercing a fixed vector from a scalable vector for ABI + // compatibility, and the types match, use the llvm.vector.extract + // intrinsic to perform the conversion. + if (auto *FixedDstTy = dyn_cast(RetIRTy)) { + llvm::Value *V = CI; + if (auto *ScalableSrcTy = + dyn_cast(V->getType())) { + if (FixedDstTy->getElementType() == ScalableSrcTy->getElementType()) { + llvm::Value *Zero = llvm::Constant::getNullValue(CGM.Int64Ty); + V = Builder.CreateExtractVector(FixedDstTy, V, Zero, "cast.fixed"); + return RValue::get(V); + } } + } - return convertTempToRValue(DestPtr, RetTy, SourceLocation()); + Address DestPtr = ReturnValue.getValue(); + bool DestIsVolatile = ReturnValue.isVolatile(); + + if (!DestPtr.isValid()) { + DestPtr = CreateMemTemp(RetTy, "coerce"); + DestIsVolatile = false; } - case ABIArgInfo::Expand: - case ABIArgInfo::IndirectAliased: - llvm_unreachable("Invalid ABI kind for return argument"); + // An empty record can overlap other data (if declared with + // no_unique_address); omit the store for such types - as there is no + // actual data to store. + if (!isEmptyRecord(getContext(), RetTy, true)) { + // If the value is offset in memory, apply the offset now. + Address StorePtr = emitAddressAtOffset(*this, DestPtr, RetAI); + CreateCoercedStore(CI, StorePtr, DestIsVolatile, *this); } - llvm_unreachable("Unhandled ABIArgInfo::Kind"); - }(); - } + return convertTempToRValue(DestPtr, RetTy, SourceLocation()); + } + + case ABIArgInfo::Expand: + case ABIArgInfo::IndirectAliased: + llvm_unreachable("Invalid ABI kind for return argument"); + } + + llvm_unreachable("Unhandled ABIArgInfo::Kind"); + } (); // Emit the assume_aligned check on the return value. if (Ret.isScalar() && TargetDecl) { diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 5f58a64d8386c3..aa53f963580440 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1076,11 +1076,6 @@ static bool getGEPIndicesToField(CodeGenFunction &CGF, const RecordDecl *RD, const CGRecordLayout &Layout = CGF.CGM.getTypes().getCGRecordLayout(RD); int64_t FieldNo = -1; for (const FieldDecl *FD : RD->fields()) { - if (!Layout.containsFieldDecl(FD)) - // This could happen if the field has a struct type that's empty. I don't - // know why either. - continue; - FieldNo = Layout.getLLVMFieldNo(FD); if (FD == Field) { Indices.emplace_back(std::make_pair(RD, CGF.Builder.getInt32(FieldNo))); diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index f22321f0e738a1..7c65fccb608551 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -814,7 +814,8 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD, llvm::Constant *VTableAddressPoint = CGM.getCXXABI().getVTableAddressPoint(BaseSubobject(CD, Offset), VTableClass); - if (auto Authentication = CGM.getVTablePointerAuthentication(CD)) { + if (auto Authentication = + CGM.getVTablePointerAuthentication(VTableClass)) { VTableAddressPoint = Emitter.tryEmitConstantSignedPointer( VTableAddressPoint, *Authentication); if (!VTableAddressPoint) diff --git a/clang/lib/CodeGen/CGPointerAuth.cpp b/clang/lib/CodeGen/CGPointerAuth.cpp index 0c63b9d6bb7e75..72aed9f24d595e 100644 --- a/clang/lib/CodeGen/CGPointerAuth.cpp +++ b/clang/lib/CodeGen/CGPointerAuth.cpp @@ -365,40 +365,6 @@ llvm::Constant *CodeGenModule::getFunctionPointer(GlobalDecl GD, return getFunctionPointer(getRawFunctionPointer(GD, Ty), FuncType); } -CGPointerAuthInfo CodeGenModule::getMemberFunctionPointerAuthInfo(QualType FT) { - assert(FT->getAs() && "MemberPointerType expected"); - const auto &Schema = getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers; - if (!Schema) - return CGPointerAuthInfo(); - - assert(!Schema.isAddressDiscriminated() && - "function pointers cannot use address-specific discrimination"); - - llvm::ConstantInt *Discriminator = - getPointerAuthOtherDiscriminator(Schema, GlobalDecl(), FT); - return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(), - /* IsIsaPointer */ false, - /* AuthenticatesNullValues */ false, Discriminator); -} - -llvm::Constant *CodeGenModule::getMemberFunctionPointer(llvm::Constant *Pointer, - QualType FT) { - if (CGPointerAuthInfo PointerAuth = getMemberFunctionPointerAuthInfo(FT)) - return getConstantSignedPointer( - Pointer, PointerAuth.getKey(), nullptr, - cast_or_null(PointerAuth.getDiscriminator())); - - return Pointer; -} - -llvm::Constant *CodeGenModule::getMemberFunctionPointer(const FunctionDecl *FD, - llvm::Type *Ty) { - QualType FT = FD->getType(); - FT = getContext().getMemberPointerType( - FT, cast(FD)->getParent()->getTypeForDecl()); - return getMemberFunctionPointer(getRawFunctionPointer(FD, Ty), FT); -} - std::optional CodeGenModule::computeVTPointerAuthentication(const CXXRecordDecl *ThisClass) { auto DefaultAuthentication = getCodeGenOpts().PointerAuth.CXXVTablePointers; diff --git a/clang/lib/CodeGen/CGRecordLayout.h b/clang/lib/CodeGen/CGRecordLayout.h index 44e888c93108fb..6c06ad20fbe56b 100644 --- a/clang/lib/CodeGen/CGRecordLayout.h +++ b/clang/lib/CodeGen/CGRecordLayout.h @@ -193,10 +193,6 @@ class CGRecordLayout { return IsZeroInitializableAsBase; } - bool containsFieldDecl(const FieldDecl *FD) const { - return FieldInfo.count(FD) != 0; - } - /// Return llvm::StructType element number that corresponds to the /// field FD. unsigned getLLVMFieldNo(const FieldDecl *FD) const { diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index d6078696a7d91f..1e98bea8c8ce3a 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -882,8 +882,6 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, const CodeGenOptions &CodeGenOpts = CGM.getCodeGenOpts(); if (CodeGenOpts.PointerAuth.FunctionPointers) Fn->addFnAttr("ptrauth-calls"); - if (CodeGenOpts.PointerAuth.IndirectGotos) - Fn->addFnAttr("ptrauth-indirect-gotos"); // Apply xray attributes to the function (as a string, for now) bool AlwaysXRayAttr = false; diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index ba7b565d975599..eebb865e8f42c6 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4374,8 +4374,7 @@ class CodeGenFunction : public CodeGenTypeCache { RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **callOrInvoke, bool IsMustTail, - SourceLocation Loc, - bool IsVirtualFunctionPointerThunk = false); + SourceLocation Loc); RValue EmitCall(const CGFunctionInfo &CallInfo, const CGCallee &Callee, ReturnValueSlot ReturnValue, const CallArgList &Args, llvm::CallBase **callOrInvoke = nullptr, diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 63ed5b4dd0c310..71192cb0e8c4a1 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -149,8 +149,6 @@ createTargetCodeGenInfo(CodeGenModule &CGM) { return createWindowsAArch64TargetCodeGenInfo(CGM, AArch64ABIKind::Win64); else if (Target.getABI() == "aapcs-soft") Kind = AArch64ABIKind::AAPCSSoft; - else if (Target.getABI() == "pauthtest") - Kind = AArch64ABIKind::PAuthTest; return createAArch64TargetCodeGenInfo(CGM, Kind); } diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 284bba823baeb4..657e681730c3ad 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -973,16 +973,8 @@ class CodeGenModule : public CodeGenTypeCache { llvm::Constant *getFunctionPointer(llvm::Constant *Pointer, QualType FunctionType); - llvm::Constant *getMemberFunctionPointer(const FunctionDecl *FD, - llvm::Type *Ty = nullptr); - - llvm::Constant *getMemberFunctionPointer(llvm::Constant *Pointer, - QualType FT); - CGPointerAuthInfo getFunctionPointerAuthInfo(QualType T); - CGPointerAuthInfo getMemberFunctionPointerAuthInfo(QualType FT); - CGPointerAuthInfo getPointerAuthInfoForPointeeType(QualType type); CGPointerAuthInfo getPointerAuthInfoForType(QualType type); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index cd76f8406e7b72..37b436a21fbc0d 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -388,9 +388,6 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI { bool NeedsVTTParameter(GlobalDecl GD) override; - llvm::Constant * - getOrCreateVirtualFunctionPointerThunk(const CXXMethodDecl *MD); - /**************************** RTTI Uniqueness ******************************/ protected: @@ -429,9 +426,6 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI { const CXXRecordDecl *RD) override; private: - llvm::Constant * - getSignedVirtualMemberFunctionPointer(const CXXMethodDecl *MD); - bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const { const auto &VtableLayout = CGM.getItaniumVTableContext().getVTableLayout(RD); @@ -841,25 +835,7 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( CalleePtr->addIncoming(VirtualFn, FnVirtual); CalleePtr->addIncoming(NonVirtualFn, FnNonVirtual); - CGPointerAuthInfo PointerAuth; - - if (const auto &Schema = - CGM.getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers) { - llvm::PHINode *DiscriminatorPHI = Builder.CreatePHI(CGF.IntPtrTy, 2); - DiscriminatorPHI->addIncoming(llvm::ConstantInt::get(CGF.IntPtrTy, 0), - FnVirtual); - const auto &AuthInfo = - CGM.getMemberFunctionPointerAuthInfo(QualType(MPT, 0)); - assert(Schema.getKey() == AuthInfo.getKey() && - "Keys for virtual and non-virtual member functions must match"); - auto *NonVirtualDiscriminator = AuthInfo.getDiscriminator(); - DiscriminatorPHI->addIncoming(NonVirtualDiscriminator, FnNonVirtual); - PointerAuth = CGPointerAuthInfo( - Schema.getKey(), Schema.getAuthenticationMode(), Schema.isIsaPointer(), - Schema.authenticatesNullValues(), DiscriminatorPHI); - } - - CGCallee Callee(FPT, CalleePtr, PointerAuth); + CGCallee Callee(FPT, CalleePtr); return Callee; } @@ -877,25 +853,6 @@ llvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress( "memptr.offset"); } -// See if it's possible to return a constant signed pointer. -static llvm::Constant *pointerAuthResignConstant( - llvm::Value *Ptr, const CGPointerAuthInfo &CurAuthInfo, - const CGPointerAuthInfo &NewAuthInfo, CodeGenModule &CGM) { - const auto *CPA = dyn_cast(Ptr); - - if (!CPA) - return nullptr; - - assert(CPA->getKey()->getZExtValue() == CurAuthInfo.getKey() && - CPA->getAddrDiscriminator()->isZeroValue() && - CPA->getDiscriminator() == CurAuthInfo.getDiscriminator() && - "unexpected key or discriminators"); - - return CGM.getConstantSignedPointer( - CPA->getPointer(), NewAuthInfo.getKey(), nullptr, - cast(NewAuthInfo.getDiscriminator())); -} - /// Perform a bitcast, derived-to-base, or base-to-derived member pointer /// conversion. /// @@ -923,63 +880,21 @@ llvm::Value * ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, const CastExpr *E, llvm::Value *src) { - // Use constant emission if we can. - if (isa(src)) - return EmitMemberPointerConversion(E, cast(src)); - assert(E->getCastKind() == CK_DerivedToBaseMemberPointer || E->getCastKind() == CK_BaseToDerivedMemberPointer || E->getCastKind() == CK_ReinterpretMemberPointer); - CGBuilderTy &Builder = CGF.Builder; - QualType DstType = E->getType(); - - if (DstType->isMemberFunctionPointerType()) { - if (const auto &NewAuthInfo = - CGM.getMemberFunctionPointerAuthInfo(DstType)) { - QualType SrcType = E->getSubExpr()->getType(); - assert(SrcType->isMemberFunctionPointerType()); - const auto &CurAuthInfo = CGM.getMemberFunctionPointerAuthInfo(SrcType); - llvm::Value *MemFnPtr = Builder.CreateExtractValue(src, 0, "memptr.ptr"); - llvm::Type *OrigTy = MemFnPtr->getType(); - - llvm::BasicBlock *StartBB = Builder.GetInsertBlock(); - llvm::BasicBlock *ResignBB = CGF.createBasicBlock("resign"); - llvm::BasicBlock *MergeBB = CGF.createBasicBlock("merge"); - - // Check whether we have a virtual offset or a pointer to a function. - assert(UseARMMethodPtrABI && "ARM ABI expected"); - llvm::Value *Adj = Builder.CreateExtractValue(src, 1, "memptr.adj"); - llvm::Constant *Ptrdiff_1 = llvm::ConstantInt::get(CGM.PtrDiffTy, 1); - llvm::Value *AndVal = Builder.CreateAnd(Adj, Ptrdiff_1); - llvm::Value *IsVirtualOffset = - Builder.CreateIsNotNull(AndVal, "is.virtual.offset"); - Builder.CreateCondBr(IsVirtualOffset, MergeBB, ResignBB); - - CGF.EmitBlock(ResignBB); - llvm::Type *PtrTy = llvm::PointerType::getUnqual(CGM.Int8Ty); - MemFnPtr = Builder.CreateIntToPtr(MemFnPtr, PtrTy); - MemFnPtr = - CGF.emitPointerAuthResign(MemFnPtr, SrcType, CurAuthInfo, NewAuthInfo, - isa(src)); - MemFnPtr = Builder.CreatePtrToInt(MemFnPtr, OrigTy); - llvm::Value *ResignedVal = Builder.CreateInsertValue(src, MemFnPtr, 0); - ResignBB = Builder.GetInsertBlock(); - - CGF.EmitBlock(MergeBB); - llvm::PHINode *NewSrc = Builder.CreatePHI(src->getType(), 2); - NewSrc->addIncoming(src, StartBB); - NewSrc->addIncoming(ResignedVal, ResignBB); - src = NewSrc; - } - } - // Under Itanium, reinterprets don't require any additional processing. if (E->getCastKind() == CK_ReinterpretMemberPointer) return src; + // Use constant emission if we can. + if (isa(src)) + return EmitMemberPointerConversion(E, cast(src)); + llvm::Constant *adj = getMemberPointerAdjustment(E); if (!adj) return src; + CGBuilderTy &Builder = CGF.Builder; bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer); const MemberPointerType *destTy = @@ -1017,34 +932,6 @@ ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, return Builder.CreateInsertValue(src, dstAdj, 1); } -static llvm::Constant * -pointerAuthResignMemberFunctionPointer(llvm::Constant *Src, QualType DestType, - QualType SrcType, CodeGenModule &CGM) { - assert(DestType->isMemberFunctionPointerType() && - SrcType->isMemberFunctionPointerType() && - "member function pointers expected"); - if (DestType == SrcType) - return Src; - - const auto &NewAuthInfo = CGM.getMemberFunctionPointerAuthInfo(DestType); - const auto &CurAuthInfo = CGM.getMemberFunctionPointerAuthInfo(SrcType); - - if (!NewAuthInfo && !CurAuthInfo) - return Src; - - llvm::Constant *MemFnPtr = Src->getAggregateElement(0u); - if (MemFnPtr->getNumOperands() == 0) { - // src must be a pair of null pointers. - assert(isa(MemFnPtr) && "constant int expected"); - return Src; - } - - llvm::Constant *ConstPtr = pointerAuthResignConstant( - cast(MemFnPtr)->getOperand(0), CurAuthInfo, NewAuthInfo, CGM); - ConstPtr = llvm::ConstantExpr::getPtrToInt(ConstPtr, MemFnPtr->getType()); - return ConstantFoldInsertValueInstruction(Src, ConstPtr, 0); -} - llvm::Constant * ItaniumCXXABI::EmitMemberPointerConversion(const CastExpr *E, llvm::Constant *src) { @@ -1052,12 +939,6 @@ ItaniumCXXABI::EmitMemberPointerConversion(const CastExpr *E, E->getCastKind() == CK_BaseToDerivedMemberPointer || E->getCastKind() == CK_ReinterpretMemberPointer); - QualType DstType = E->getType(); - - if (DstType->isMemberFunctionPointerType()) - src = pointerAuthResignMemberFunctionPointer( - src, DstType, E->getSubExpr()->getType(), CGM); - // Under Itanium, reinterprets don't require any additional processing. if (E->getCastKind() == CK_ReinterpretMemberPointer) return src; @@ -1155,32 +1036,9 @@ llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD, // least significant bit of adj then makes exactly the same // discrimination as the least significant bit of ptr does for // Itanium. - - // We cannot use the Itanium ABI's representation for virtual member - // function pointers under pointer authentication because it would - // require us to store both the virtual offset and the constant - // discriminator in the pointer, which would be immediately vulnerable - // to attack. Instead we introduce a thunk that does the virtual dispatch - // and store it as if it were a non-virtual member function. This means - // that virtual function pointers may not compare equal anymore, but - // fortunately they aren't required to by the standard, and we do make - // a best-effort attempt to re-use the thunk. - // - // To support interoperation with code in which pointer authentication - // is disabled, derefencing a member function pointer must still handle - // the virtual case, but it can use a discriminator which should never - // be valid. - const auto &Schema = - CGM.getCodeGenOpts().PointerAuth.CXXMemberFunctionPointers; - if (Schema) - MemPtr[0] = llvm::ConstantExpr::getPtrToInt( - getSignedVirtualMemberFunctionPointer(MD), CGM.PtrDiffTy); - else - MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset); - // Don't set the LSB of adj to 1 if pointer authentication for member - // function pointers is enabled. - MemPtr[1] = llvm::ConstantInt::get( - CGM.PtrDiffTy, 2 * ThisAdjustment.getQuantity() + !Schema); + MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset); + MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy, + 2 * ThisAdjustment.getQuantity() + 1); } else { // Itanium C++ ABI 2.3: // For a virtual function, [the pointer field] is 1 plus the @@ -1202,7 +1060,7 @@ llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD, // function type is incomplete. Ty = CGM.PtrDiffTy; } - llvm::Constant *addr = CGM.getMemberFunctionPointer(MD, Ty); + llvm::Constant *addr = CGM.GetAddrOfFunction(MD, Ty); MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, CGM.PtrDiffTy); MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy, @@ -1222,12 +1080,8 @@ llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP, CharUnits ThisAdjustment = getContext().getMemberPointerPathAdjustment(MP); - if (const CXXMethodDecl *MD = dyn_cast(MPD)) { - llvm::Constant *Src = BuildMemberPointer(MD, ThisAdjustment); - QualType SrcType = getContext().getMemberPointerType( - MD->getType(), MD->getParent()->getTypeForDecl()); - return pointerAuthResignMemberFunctionPointer(Src, MPType, SrcType, CGM); - } + if (const CXXMethodDecl *MD = dyn_cast(MPD)) + return BuildMemberPointer(MD, ThisAdjustment); CharUnits FieldOffset = getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD)); @@ -3331,78 +3185,6 @@ bool ItaniumCXXABI::NeedsVTTParameter(GlobalDecl GD) { return false; } -llvm::Constant * -ItaniumCXXABI::getOrCreateVirtualFunctionPointerThunk(const CXXMethodDecl *MD) { - SmallString<256> MethodName; - llvm::raw_svector_ostream Out(MethodName); - getMangleContext().mangleCXXName(MD, Out); - MethodName += "_vfpthunk_"; - StringRef ThunkName = MethodName.str(); - llvm::Function *ThunkFn; - if ((ThunkFn = cast_or_null( - CGM.getModule().getNamedValue(ThunkName)))) - return ThunkFn; - - const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeCXXMethodDeclaration(MD); - llvm::FunctionType *ThunkTy = CGM.getTypes().GetFunctionType(FnInfo); - llvm::GlobalValue::LinkageTypes Linkage = - MD->isExternallyVisible() ? llvm::GlobalValue::LinkOnceODRLinkage - : llvm::GlobalValue::InternalLinkage; - ThunkFn = - llvm::Function::Create(ThunkTy, Linkage, ThunkName, &CGM.getModule()); - if (Linkage == llvm::GlobalValue::LinkOnceODRLinkage) - ThunkFn->setVisibility(llvm::GlobalValue::HiddenVisibility); - assert(ThunkFn->getName() == ThunkName && "name was uniqued!"); - - CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn, /*IsThunk=*/true); - CGM.SetLLVMFunctionAttributesForDefinition(MD, ThunkFn); - - // Stack protection sometimes gets inserted after the musttail call. - ThunkFn->removeFnAttr(llvm::Attribute::StackProtect); - ThunkFn->removeFnAttr(llvm::Attribute::StackProtectStrong); - ThunkFn->removeFnAttr(llvm::Attribute::StackProtectReq); - - // Start codegen. - CodeGenFunction CGF(CGM); - CGF.CurGD = GlobalDecl(MD); - CGF.CurFuncIsThunk = true; - - // Build FunctionArgs. - FunctionArgList FunctionArgs; - CGF.BuildFunctionArgList(CGF.CurGD, FunctionArgs); - - CGF.StartFunction(GlobalDecl(), FnInfo.getReturnType(), ThunkFn, FnInfo, - FunctionArgs, MD->getLocation(), SourceLocation()); - llvm::Value *ThisVal = loadIncomingCXXThis(CGF); - setCXXABIThisValue(CGF, ThisVal); - - CallArgList CallArgs; - for (const VarDecl *VD : FunctionArgs) - CGF.EmitDelegateCallArg(CallArgs, VD, SourceLocation()); - - const FunctionProtoType *FPT = MD->getType()->getAs(); - RequiredArgs Required = RequiredArgs::forPrototypePlus(FPT, /*this*/ 1); - const CGFunctionInfo &CallInfo = - CGM.getTypes().arrangeCXXMethodCall(CallArgs, FPT, Required, 0); - CGCallee Callee = CGCallee::forVirtual(nullptr, GlobalDecl(MD), - getThisAddress(CGF), ThunkTy); - llvm::CallBase *CallOrInvoke; - CGF.EmitCall(CallInfo, Callee, ReturnValueSlot(), CallArgs, &CallOrInvoke, - /*IsMustTail=*/true, SourceLocation(), true); - auto *Call = cast(CallOrInvoke); - Call->setTailCallKind(llvm::CallInst::TCK_MustTail); - if (Call->getType()->isVoidTy()) - CGF.Builder.CreateRetVoid(); - else - CGF.Builder.CreateRet(Call); - - // Finish the function to maintain CodeGenFunction invariants. - // FIXME: Don't emit unreachable code. - CGF.EmitBlock(CGF.createBasicBlock()); - CGF.FinishFunction(); - return ThunkFn; -} - namespace { class ItaniumRTTIBuilder { CodeGenModule &CGM; // Per-module state. @@ -5093,18 +4875,6 @@ ItaniumCXXABI::LoadVTablePtr(CodeGenFunction &CGF, Address This, return {CGF.GetVTablePtr(This, CGM.Int8PtrTy, RD), RD}; } -llvm::Constant * -ItaniumCXXABI::getSignedVirtualMemberFunctionPointer(const CXXMethodDecl *MD) { - const CXXMethodDecl *origMD = - cast(CGM.getItaniumVTableContext() - .findOriginalMethod(MD->getCanonicalDecl()) - .getDecl()); - llvm::Constant *thunk = getOrCreateVirtualFunctionPointerThunk(origMD); - QualType funcType = CGM.getContext().getMemberPointerType( - MD->getType(), MD->getParent()->getTypeForDecl()); - return CGM.getMemberFunctionPointer(thunk, funcType); -} - void WebAssemblyCXXABI::emitBeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *C) { if (CGF.getTarget().hasFeature("exception-handling")) diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h index 2f2138582ba1e3..0925609cc74aa5 100644 --- a/clang/lib/CodeGen/TargetInfo.h +++ b/clang/lib/CodeGen/TargetInfo.h @@ -437,7 +437,6 @@ enum class AArch64ABIKind { DarwinPCS, Win64, AAPCSSoft, - PAuthTest, }; std::unique_ptr diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 20a555afb8092f..85ae4d2a26fee2 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -1031,12 +1031,11 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, } case llvm::Triple::aarch64: { llvm::Triple Triple = getTriple(); - tools::aarch64::setPAuthABIInTriple(getDriver(), Args, Triple); if (!Triple.isOSBinFormatMachO()) - return Triple.getTriple(); + return getTripleString(); if (Triple.isArm64e()) - return Triple.getTriple(); + return getTripleString(); // FIXME: older versions of ld64 expect the "arm64" component in the actual // triple string and query it to determine whether an LTO file can be diff --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp index fb780fb75651d2..b04502a57a9f7a 100644 --- a/clang/lib/Driver/ToolChains/AIX.cpp +++ b/clang/lib/Driver/ToolChains/AIX.cpp @@ -557,12 +557,6 @@ void AIX::addClangTargetOptions( if (!Args.getLastArgNoClaim(options::OPT_fsized_deallocation, options::OPT_fno_sized_deallocation)) CC1Args.push_back("-fno-sized-deallocation"); - - if (Args.hasFlag(options::OPT_ferr_pragma_mc_func_aix, - options::OPT_fno_err_pragma_mc_func_aix, false)) - CC1Args.push_back("-ferr-pragma-mc-func-aix"); - else - CC1Args.push_back("-fno-err-pragma-mc-func-aix"); } void AIX::addProfileRTLibs(const llvm::opt::ArgList &Args, diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp index f083e40df13144..5fbf38cdda12b1 100644 --- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp +++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp @@ -449,24 +449,3 @@ void aarch64::getAArch64TargetFeatures(const Driver &D, if (Args.getLastArg(options::OPT_mno_bti_at_return_twice)) Features.push_back("+no-bti-at-return-twice"); } - -void aarch64::setPAuthABIInTriple(const Driver &D, const ArgList &Args, - llvm::Triple &Triple) { - Arg *ABIArg = Args.getLastArg(options::OPT_mabi_EQ); - bool HasPAuthABI = - ABIArg ? (StringRef(ABIArg->getValue()) == "pauthtest") : false; - - switch (Triple.getEnvironment()) { - case llvm::Triple::UnknownEnvironment: - if (HasPAuthABI) - Triple.setEnvironment(llvm::Triple::PAuthTest); - break; - case llvm::Triple::PAuthTest: - break; - default: - if (HasPAuthABI) - D.Diag(diag::err_drv_unsupported_opt_for_target) - << ABIArg->getAsString(Args) << Triple.getTriple(); - break; - } -} diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.h b/clang/lib/Driver/ToolChains/Arch/AArch64.h index 6d071167bd3921..d47c402d4a42d4 100644 --- a/clang/lib/Driver/ToolChains/Arch/AArch64.h +++ b/clang/lib/Driver/ToolChains/Arch/AArch64.h @@ -28,9 +28,6 @@ void getAArch64TargetFeatures(const Driver &D, const llvm::Triple &Triple, std::string getAArch64TargetCPU(const llvm::opt::ArgList &Args, const llvm::Triple &Triple, llvm::opt::Arg *&A); -void setPAuthABIInTriple(const Driver &D, const llvm::opt::ArgList &Args, - llvm::Triple &triple); - } // end namespace aarch64 } // end namespace target } // end namespace driver diff --git a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp index 1e8aac71dc9ba7..4a2b9efc9ffadb 100644 --- a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp +++ b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp @@ -127,11 +127,6 @@ void loongarch::getLoongArchTargetFeatures(const Driver &D, const llvm::Triple &Triple, const ArgList &Args, std::vector &Features) { - // Enable the `lsx` feature on 64-bit LoongArch by default. - if (Triple.isLoongArch64() && - (!Args.hasArgNoClaim(clang::driver::options::OPT_march_EQ))) - Features.push_back("+lsx"); - std::string ArchName; if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) ArchName = A->getValue(); @@ -150,11 +145,9 @@ void loongarch::getLoongArchTargetFeatures(const Driver &D, } else if (A->getOption().matches(options::OPT_msingle_float)) { Features.push_back("+f"); Features.push_back("-d"); - Features.push_back("-lsx"); } else /*Soft-float*/ { Features.push_back("-f"); Features.push_back("-d"); - Features.push_back("-lsx"); } } else if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) { StringRef FPU = A->getValue(); @@ -164,11 +157,9 @@ void loongarch::getLoongArchTargetFeatures(const Driver &D, } else if (FPU == "32") { Features.push_back("+f"); Features.push_back("-d"); - Features.push_back("-lsx"); } else if (FPU == "0" || FPU == "none") { Features.push_back("-f"); Features.push_back("-d"); - Features.push_back("-lsx"); } else { D.Diag(diag::err_drv_loongarch_invalid_mfpu_EQ) << FPU; } @@ -183,42 +174,6 @@ void loongarch::getLoongArchTargetFeatures(const Driver &D, A->ignoreTargetSpecific(); if (Arg *A = Args.getLastArgNoClaim(options::OPT_mfpu_EQ)) A->ignoreTargetSpecific(); - if (Arg *A = Args.getLastArgNoClaim(options::OPT_msimd_EQ)) - A->ignoreTargetSpecific(); - - // Select lsx/lasx feature determined by -msimd=. - // Option -msimd= precedes -m[no-]lsx and -m[no-]lasx. - if (const Arg *A = Args.getLastArg(options::OPT_msimd_EQ)) { - StringRef MSIMD = A->getValue(); - if (MSIMD == "lsx") { - // Option -msimd=lsx depends on 64-bit FPU. - // -m*-float and -mfpu=none/0/32 conflict with -msimd=lsx. - if (llvm::find(Features, "-d") != Features.end()) - D.Diag(diag::err_drv_loongarch_wrong_fpu_width) << /*LSX*/ 0; - else - Features.push_back("+lsx"); - } else if (MSIMD == "lasx") { - // Option -msimd=lasx depends on 64-bit FPU and LSX. - // -m*-float, -mfpu=none/0/32 and -mno-lsx conflict with -msimd=lasx. - if (llvm::find(Features, "-d") != Features.end()) - D.Diag(diag::err_drv_loongarch_wrong_fpu_width) << /*LASX*/ 1; - else if (llvm::find(Features, "-lsx") != Features.end()) - D.Diag(diag::err_drv_loongarch_invalid_simd_option_combination); - - // The command options do not contain -mno-lasx. - if (!Args.getLastArg(options::OPT_mno_lasx)) { - Features.push_back("+lsx"); - Features.push_back("+lasx"); - } - } else if (MSIMD == "none") { - if (llvm::find(Features, "+lsx") != Features.end()) - Features.push_back("-lsx"); - if (llvm::find(Features, "+lasx") != Features.end()) - Features.push_back("-lasx"); - } else { - D.Diag(diag::err_drv_loongarch_invalid_msimd_EQ) << MSIMD; - } - } // Select lsx feature determined by -m[no-]lsx. if (const Arg *A = Args.getLastArg(options::OPT_mlsx, options::OPT_mno_lsx)) { @@ -242,6 +197,8 @@ void loongarch::getLoongArchTargetFeatures(const Driver &D, if (A->getOption().matches(options::OPT_mlasx)) { if (llvm::find(Features, "-d") != Features.end()) D.Diag(diag::err_drv_loongarch_wrong_fpu_width) << /*LASX*/ 1; + else if (llvm::find(Features, "-lsx") != Features.end()) + D.Diag(diag::err_drv_loongarch_invalid_simd_option_combination); else { /*-mlasx*/ Features.push_back("+lsx"); Features.push_back("+lasx"); @@ -249,6 +206,35 @@ void loongarch::getLoongArchTargetFeatures(const Driver &D, } else /*-mno-lasx*/ Features.push_back("-lasx"); } + + // Select lsx/lasx feature determined by -msimd=. + // Option -msimd= has lower priority than -m[no-]lsx and -m[no-]lasx. + if (const Arg *A = Args.getLastArg(options::OPT_msimd_EQ)) { + StringRef MSIMD = A->getValue(); + if (MSIMD == "lsx") { + // Option -msimd=lsx depends on 64-bit FPU. + // -m*-float and -mfpu=none/0/32 conflict with -mlsx. + if (llvm::find(Features, "-d") != Features.end()) + D.Diag(diag::err_drv_loongarch_wrong_fpu_width) << /*LSX*/ 0; + // The previous option does not contain feature -lsx. + else if (llvm::find(Features, "-lsx") == Features.end()) + Features.push_back("+lsx"); + } else if (MSIMD == "lasx") { + // Option -msimd=lasx depends on 64-bit FPU and LSX. + // -m*-float and -mfpu=none/0/32 conflict with -mlsx. + if (llvm::find(Features, "-d") != Features.end()) + D.Diag(diag::err_drv_loongarch_wrong_fpu_width) << /*LASX*/ 1; + else if (llvm::find(Features, "-lsx") != Features.end()) + D.Diag(diag::err_drv_loongarch_invalid_simd_option_combination); + // The previous option does not contain feature -lasx. + else if (llvm::find(Features, "-lasx") == Features.end()) { + Features.push_back("+lsx"); + Features.push_back("+lasx"); + } + } else if (MSIMD != "none") { + D.Diag(diag::err_drv_loongarch_invalid_msimd_EQ) << MSIMD; + } + } } std::string loongarch::postProcessTargetCPUString(const std::string &CPU, @@ -267,14 +253,8 @@ std::string loongarch::postProcessTargetCPUString(const std::string &CPU, std::string loongarch::getLoongArchTargetCPU(const llvm::opt::ArgList &Args, const llvm::Triple &Triple) { std::string CPU; - std::string Arch; // If we have -march, use that. - if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { - Arch = A->getValue(); - if (Arch == "la64v1.0" || Arch == "la64v1.1") - CPU = llvm::LoongArch::getDefaultArch(Triple.isLoongArch64()); - else - CPU = Arch; - } + if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) + CPU = A->getValue(); return postProcessTargetCPUString(CPU, Triple); } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 78936fd634f339..71cdaa10416f47 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1486,41 +1486,6 @@ void AddUnalignedAccessWarning(ArgStringList &CmdArgs) { } } -// Each combination of options here forms a signing schema, and in most cases -// each signing schema is its own incompatible ABI. The default values of the -// options represent the default signing schema. -static void handlePAuthABI(const ArgList &DriverArgs, ArgStringList &CC1Args) { - if (!DriverArgs.hasArg(options::OPT_fptrauth_intrinsics, - options::OPT_fno_ptrauth_intrinsics)) - CC1Args.push_back("-fptrauth-intrinsics"); - - if (!DriverArgs.hasArg(options::OPT_fptrauth_calls, - options::OPT_fno_ptrauth_calls)) - CC1Args.push_back("-fptrauth-calls"); - - if (!DriverArgs.hasArg(options::OPT_fptrauth_returns, - options::OPT_fno_ptrauth_returns)) - CC1Args.push_back("-fptrauth-returns"); - - if (!DriverArgs.hasArg(options::OPT_fptrauth_auth_traps, - options::OPT_fno_ptrauth_auth_traps)) - CC1Args.push_back("-fptrauth-auth-traps"); - - if (!DriverArgs.hasArg( - options::OPT_fptrauth_vtable_pointer_address_discrimination, - options::OPT_fno_ptrauth_vtable_pointer_address_discrimination)) - CC1Args.push_back("-fptrauth-vtable-pointer-address-discrimination"); - - if (!DriverArgs.hasArg( - options::OPT_fptrauth_vtable_pointer_type_discrimination, - options::OPT_fno_ptrauth_vtable_pointer_type_discrimination)) - CC1Args.push_back("-fptrauth-vtable-pointer-type-discrimination"); - - if (!DriverArgs.hasArg(options::OPT_fptrauth_init_fini, - options::OPT_fno_ptrauth_init_fini)) - CC1Args.push_back("-fptrauth-init-fini"); -} - static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs, bool isAArch64) { const Arg *A = isAArch64 @@ -1583,30 +1548,16 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args, CmdArgs.push_back( Args.MakeArgString(Twine("-msign-return-address=") + Scope)); - if (Scope != "none") { - if (Triple.getEnvironment() == llvm::Triple::PAuthTest) - D.Diag(diag::err_drv_unsupported_opt_for_target) - << A->getAsString(Args) << Triple.getTriple(); + if (Scope != "none") CmdArgs.push_back( Args.MakeArgString(Twine("-msign-return-address-key=") + Key)); - } - if (BranchProtectionPAuthLR) { - if (Triple.getEnvironment() == llvm::Triple::PAuthTest) - D.Diag(diag::err_drv_unsupported_opt_for_target) - << A->getAsString(Args) << Triple.getTriple(); + if (BranchProtectionPAuthLR) CmdArgs.push_back( Args.MakeArgString(Twine("-mbranch-protection-pauth-lr"))); - } if (IndirectBranches) CmdArgs.push_back("-mbranch-target-enforce"); - // GCS is currently untested with PAuthABI, but enabling this could be allowed - // in future after testing with a suitable system. - if (GuardedControlStack) { - if (Triple.getEnvironment() == llvm::Triple::PAuthTest) - D.Diag(diag::err_drv_unsupported_opt_for_target) - << A->getAsString(Args) << Triple.getTriple(); + if (GuardedControlStack) CmdArgs.push_back("-mguarded-control-stack"); - } } void Clang::AddARMTargetArgs(const llvm::Triple &Triple, const ArgList &Args, @@ -1750,8 +1701,6 @@ void RenderAArch64ABI(const llvm::Triple &Triple, const ArgList &Args, ABIName = A->getValue(); else if (Triple.isOSDarwin()) ABIName = "darwinpcs"; - else if (Triple.getEnvironment() == llvm::Triple::PAuthTest) - ABIName = "pauthtest"; else ABIName = "aapcs"; @@ -1788,9 +1737,6 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, // Enable/disable return address signing and indirect branch targets. CollectARMPACBTIOptions(getToolChain(), Args, CmdArgs, true /*isAArch64*/); - if (Triple.getEnvironment() == llvm::Triple::PAuthTest) - handlePAuthABI(Args, CmdArgs); - // Handle -msve_vector_bits= if (Arg *A = Args.getLastArg(options::OPT_msve_vector_bits_EQ)) { StringRef Val = A->getValue(); @@ -1848,9 +1794,6 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, Args.addOptInFlag( CmdArgs, options::OPT_fptrauth_function_pointer_type_discrimination, options::OPT_fno_ptrauth_function_pointer_type_discrimination); - - Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_indirect_gotos, - options::OPT_fno_ptrauth_indirect_gotos); } void Clang::AddLoongArchTargetArgs(const ArgList &Args, @@ -6723,9 +6666,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, StringRef S0 = A->getValue(), S = S0; unsigned Size, Offset = 0; if (!Triple.isAArch64() && !Triple.isLoongArch() && !Triple.isRISCV() && - !Triple.isX86() && - !(!Triple.isOSAIX() && (Triple.getArch() == llvm::Triple::ppc || - Triple.getArch() == llvm::Triple::ppc64))) + !Triple.isX86()) D.Diag(diag::err_drv_unsupported_opt_for_target) << A->getAsString(Args) << TripleStr; else if (S.consumeInteger(10, Size) || @@ -6818,7 +6759,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (const char *Name = C.getTimeTraceFile(&JA)) { CmdArgs.push_back(Args.MakeArgString("-ftime-trace=" + Twine(Name))); Args.AddLastArg(CmdArgs, options::OPT_ftime_trace_granularity_EQ); - Args.AddLastArg(CmdArgs, options::OPT_ftime_trace_verbose); } if (Arg *A = Args.getLastArg(options::OPT_ftrapv_handler_EQ)) { diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp index 59453c484ae4f4..08a4633902654d 100644 --- a/clang/lib/Driver/ToolChains/Cuda.cpp +++ b/clang/lib/Driver/ToolChains/Cuda.cpp @@ -461,6 +461,13 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("--output-file"); std::string OutputFileName = TC.getInputFilename(Output); + // If we are invoking `nvlink` internally we need to output a `.cubin` file. + // FIXME: This should hopefully be removed if NVIDIA updates their tooling. + if (!C.getInputArgs().getLastArg(options::OPT_c)) { + SmallString<256> Filename(Output.getFilename()); + llvm::sys::path::replace_extension(Filename, "cubin"); + OutputFileName = Filename.str(); + } if (Output.isFilename() && OutputFileName != Output.getFilename()) C.addTempFile(Args.MakeArgString(OutputFileName)); @@ -605,21 +612,12 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-arch"); CmdArgs.push_back(Args.MakeArgString(GPUArch)); - if (Args.hasArg(options::OPT_ptxas_path_EQ)) - CmdArgs.push_back(Args.MakeArgString( - "--pxtas-path=" + Args.getLastArgValue(options::OPT_ptxas_path_EQ))); - // Add paths specified in LIBRARY_PATH environment variable as -L options. addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH"); // Add standard library search paths passed on the command line. Args.AddAllArgs(CmdArgs, options::OPT_L); getToolChain().AddFilePathLibArgs(Args, CmdArgs); - AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); - - if (C.getDriver().isUsingLTO()) - addLTOOptions(getToolChain(), Args, CmdArgs, Output, Inputs[0], - C.getDriver().getLTOMode() == LTOK_Thin); // Add paths for the default clang library path. SmallString<256> DefaultLibPath = @@ -627,12 +625,51 @@ void NVPTX::Linker::ConstructJob(Compilation &C, const JobAction &JA, llvm::sys::path::append(DefaultLibPath, CLANG_INSTALL_LIBDIR_BASENAME); CmdArgs.push_back(Args.MakeArgString(Twine("-L") + DefaultLibPath)); + for (const auto &II : Inputs) { + if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR || + II.getType() == types::TY_LTO_BC || II.getType() == types::TY_LLVM_BC) { + C.getDriver().Diag(diag::err_drv_no_linker_llvm_support) + << getToolChain().getTripleString(); + continue; + } + + // The 'nvlink' application performs RDC-mode linking when given a '.o' + // file and device linking when given a '.cubin' file. We always want to + // perform device linking, so just rename any '.o' files. + // FIXME: This should hopefully be removed if NVIDIA updates their tooling. + if (II.isFilename()) { + auto InputFile = getToolChain().getInputFilename(II); + if (llvm::sys::path::extension(InputFile) != ".cubin") { + // If there are no actions above this one then this is direct input and + // we can copy it. Otherwise the input is internal so a `.cubin` file + // should exist. + if (II.getAction() && II.getAction()->getInputs().size() == 0) { + const char *CubinF = + Args.MakeArgString(getToolChain().getDriver().GetTemporaryPath( + llvm::sys::path::stem(InputFile), "cubin")); + if (llvm::sys::fs::copy_file(InputFile, C.addTempFile(CubinF))) + continue; + + CmdArgs.push_back(CubinF); + } else { + SmallString<256> Filename(InputFile); + llvm::sys::path::replace_extension(Filename, "cubin"); + CmdArgs.push_back(Args.MakeArgString(Filename)); + } + } else { + CmdArgs.push_back(Args.MakeArgString(InputFile)); + } + } else if (!II.isNothing()) { + II.getInputArg().renderAsInput(Args, CmdArgs); + } + } + C.addCommand(std::make_unique( JA, *this, ResponseFileSupport{ResponseFileSupport::RF_Full, llvm::sys::WEM_UTF8, "--options-file"}, - Args.MakeArgString(getToolChain().GetProgramPath("clang-nvlink-wrapper")), - CmdArgs, Inputs, Output)); + Args.MakeArgString(getToolChain().GetProgramPath("nvlink")), CmdArgs, + Inputs, Output)); } void NVPTX::getNVPTXTargetFeatures(const Driver &D, const llvm::Triple &Triple, @@ -912,7 +949,11 @@ std::string CudaToolChain::getInputFilename(const InputInfo &Input) const { if (Input.getType() != types::TY_Object || getDriver().offloadDeviceOnly()) return ToolChain::getInputFilename(Input); - return ToolChain::getInputFilename(Input); + // Replace extension for object files with cubin because nvlink relies on + // these particular file names. + SmallString<256> Filename(ToolChain::getInputFilename(Input)); + llvm::sys::path::replace_extension(Filename, "cubin"); + return std::string(Filename); } llvm::opt::DerivedArgList * diff --git a/clang/lib/Driver/ToolChains/Cuda.h b/clang/lib/Driver/ToolChains/Cuda.h index 7a6a6fb209012e..7464d88cb350ba 100644 --- a/clang/lib/Driver/ToolChains/Cuda.h +++ b/clang/lib/Driver/ToolChains/Cuda.h @@ -155,7 +155,6 @@ class LLVM_LIBRARY_VISIBILITY NVPTXToolChain : public ToolChain { bool isPIEDefault(const llvm::opt::ArgList &Args) const override { return false; } - bool HasNativeLLVMSupport() const override { return true; } bool isPICDefaultForced() const override { return false; } bool SupportsProfiling() const override { return false; } @@ -193,8 +192,6 @@ class LLVM_LIBRARY_VISIBILITY CudaToolChain : public NVPTXToolChain { return &HostTC.getTriple(); } - bool HasNativeLLVMSupport() const override { return false; } - std::string getInputFilename(const InputInfo &Input) const override; llvm::opt::DerivedArgList * diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp index 2265138edbffbe..98a878e1d764db 100644 --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -86,9 +86,6 @@ std::string Linux::getMultiarchTriple(const Driver &D, case llvm::Triple::aarch64: if (IsAndroid) return "aarch64-linux-android"; - if (hasEffectiveTriple() && - getEffectiveTriple().getEnvironment() == llvm::Triple::PAuthTest) - return "aarch64-linux-pauthtest"; return "aarch64-linux-gnu"; case llvm::Triple::aarch64_be: return "aarch64_be-linux-gnu"; diff --git a/clang/lib/Driver/ToolChains/PS4CPU.h b/clang/lib/Driver/ToolChains/PS4CPU.h index a33728bce5186a..0be90183c637c8 100644 --- a/clang/lib/Driver/ToolChains/PS4CPU.h +++ b/clang/lib/Driver/ToolChains/PS4CPU.h @@ -179,7 +179,7 @@ class LLVM_LIBRARY_VISIBILITY PS5CPU : public PS4PS5Base { llvm::opt::ArgStringList &CmdArgs, const char *Prefix, const char *Suffix) const override; const char *getProfileRTLibName() const override { - return "libclang_rt.profile_nosubmission.a"; + return "libclang_rt.profile-x86_64_nosubmission.a"; } protected: diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 21924a8fe17d17..db66911f00f63b 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2467,9 +2467,9 @@ class AnnotatingParser { Current.setType(TT_CastRParen); if (Current.MatchingParen && Current.Next && !Current.Next->isBinaryOperator() && - !Current.Next->isOneOf( - tok::semi, tok::colon, tok::l_brace, tok::l_paren, tok::comma, - tok::period, tok::arrow, tok::coloncolon, tok::kw_noexcept)) { + !Current.Next->isOneOf(tok::semi, tok::colon, tok::l_brace, + tok::comma, tok::period, tok::arrow, + tok::coloncolon, tok::kw_noexcept)) { if (FormatToken *AfterParen = Current.MatchingParen->Next; AfterParen && AfterParen->isNot(tok::caret)) { // Make sure this isn't the return type of an Obj-C block declaration. @@ -2625,10 +2625,8 @@ class AnnotatingParser { return false; // int a or auto a. - if (PreviousNotConst->isOneOf(tok::identifier, tok::kw_auto) && - PreviousNotConst->isNot(TT_StatementAttributeLikeMacro)) { + if (PreviousNotConst->isOneOf(tok::identifier, tok::kw_auto)) return true; - } // *a or &a or &&a. if (PreviousNotConst->is(TT_PointerOrReference)) diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index f6b6c44a4cab6a..bf57addff1c6df 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1488,30 +1488,20 @@ void CompilerInvocation::setDefaultPointerAuthOptions( Key::ASDA, LangOpts.PointerAuthVTPtrAddressDiscrimination, LangOpts.PointerAuthVTPtrTypeDiscrimination ? Discrimination::Type : Discrimination::None); - - if (LangOpts.PointerAuthTypeInfoVTPtrDiscrimination) - Opts.CXXTypeInfoVTablePointer = - PointerAuthSchema(Key::ASDA, true, Discrimination::Constant, - StdTypeInfoVTablePointerConstantDiscrimination); - else - Opts.CXXTypeInfoVTablePointer = - PointerAuthSchema(Key::ASDA, false, Discrimination::None); - + Opts.CXXTypeInfoVTablePointer = + PointerAuthSchema(Key::ASDA, false, Discrimination::None); Opts.CXXVTTVTablePointers = PointerAuthSchema(Key::ASDA, false, Discrimination::None); Opts.CXXVirtualFunctionPointers = Opts.CXXVirtualVariadicFunctionPointers = PointerAuthSchema(Key::ASIA, true, Discrimination::Decl); - Opts.CXXMemberFunctionPointers = - PointerAuthSchema(Key::ASIA, false, Discrimination::Type); } - Opts.IndirectGotos = LangOpts.PointerAuthIndirectGotos; } static void parsePointerAuthOptions(PointerAuthOptions &Opts, const LangOptions &LangOpts, const llvm::Triple &Triple, DiagnosticsEngine &Diags) { - if (!LangOpts.PointerAuthCalls && !LangOpts.PointerAuthIndirectGotos) + if (!LangOpts.PointerAuthCalls) return; CompilerInvocation::setDefaultPointerAuthOptions(Opts, LangOpts, Triple); @@ -3415,17 +3405,12 @@ static void GeneratePointerAuthArgs(const LangOptions &Opts, GenerateArg(Consumer, OPT_fptrauth_calls); if (Opts.PointerAuthReturns) GenerateArg(Consumer, OPT_fptrauth_returns); - if (Opts.PointerAuthIndirectGotos) - GenerateArg(Consumer, OPT_fptrauth_indirect_gotos); if (Opts.PointerAuthAuthTraps) GenerateArg(Consumer, OPT_fptrauth_auth_traps); if (Opts.PointerAuthVTPtrAddressDiscrimination) GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_address_discrimination); if (Opts.PointerAuthVTPtrTypeDiscrimination) GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_type_discrimination); - if (Opts.PointerAuthTypeInfoVTPtrDiscrimination) - GenerateArg(Consumer, OPT_fptrauth_type_info_vtable_pointer_discrimination); - if (Opts.PointerAuthInitFini) GenerateArg(Consumer, OPT_fptrauth_init_fini); if (Opts.PointerAuthFunctionTypeDiscrimination) @@ -3437,15 +3422,11 @@ static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args, Opts.PointerAuthIntrinsics = Args.hasArg(OPT_fptrauth_intrinsics); Opts.PointerAuthCalls = Args.hasArg(OPT_fptrauth_calls); Opts.PointerAuthReturns = Args.hasArg(OPT_fptrauth_returns); - Opts.PointerAuthIndirectGotos = Args.hasArg(OPT_fptrauth_indirect_gotos); Opts.PointerAuthAuthTraps = Args.hasArg(OPT_fptrauth_auth_traps); Opts.PointerAuthVTPtrAddressDiscrimination = Args.hasArg(OPT_fptrauth_vtable_pointer_address_discrimination); Opts.PointerAuthVTPtrTypeDiscrimination = Args.hasArg(OPT_fptrauth_vtable_pointer_type_discrimination); - Opts.PointerAuthTypeInfoVTPtrDiscrimination = - Args.hasArg(OPT_fptrauth_type_info_vtable_pointer_discrimination); - Opts.PointerAuthInitFini = Args.hasArg(OPT_fptrauth_init_fini); Opts.PointerAuthFunctionTypeDiscrimination = Args.hasArg(OPT_fptrauth_function_pointer_type_discrimination); diff --git a/clang/lib/Frontend/PrintPreprocessedOutput.cpp b/clang/lib/Frontend/PrintPreprocessedOutput.cpp index 0592423c12eca4..1fff88ccf0405f 100644 --- a/clang/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/clang/lib/Frontend/PrintPreprocessedOutput.cpp @@ -758,9 +758,10 @@ void PrintPPOutputPPCallbacks::HandleWhitespaceBeforeTok(const Token &Tok, // These tokens are not expanded to anything and don't need whitespace before // them. if (Tok.is(tok::eof) || - (Tok.isAnnotation() && !Tok.is(tok::annot_header_unit) && - !Tok.is(tok::annot_module_begin) && !Tok.is(tok::annot_module_end) && - !Tok.is(tok::annot_repl_input_end) && !Tok.is(tok::annot_embed))) + (Tok.isAnnotation() && Tok.isNot(tok::annot_header_unit) && + Tok.isNot(tok::annot_module_begin) && Tok.isNot(tok::annot_module_end) && + Tok.isNot(tok::annot_module_name) && + Tok.isNot(tok::annot_repl_input_end) && Tok.isNot(tok::annot_embed))) return; // EmittedDirectiveOnThisLine takes priority over RequireSameLine. @@ -951,6 +952,11 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, PP.Lex(Tok); IsStartOfLine = true; continue; + } else if (Tok.is(tok::annot_module_name)) { + auto *Info = static_cast(Tok.getAnnotationValue()); + *Callbacks->OS << Info->getFlatName(); + PP.Lex(Tok); + continue; } else if (Tok.is(tok::annot_header_unit)) { // This is a header-name that has been (effectively) converted into a // module-name. diff --git a/clang/lib/Lex/DependencyDirectivesScanner.cpp b/clang/lib/Lex/DependencyDirectivesScanner.cpp index 31a4c0f52b4653..8a020d0e95fe33 100644 --- a/clang/lib/Lex/DependencyDirectivesScanner.cpp +++ b/clang/lib/Lex/DependencyDirectivesScanner.cpp @@ -88,8 +88,8 @@ struct Scanner { [[nodiscard]] dependency_directives_scan::Token & lexToken(const char *&First, const char *const End); - [[nodiscard]] dependency_directives_scan::Token & - lexIncludeFilename(const char *&First, const char *const End); + dependency_directives_scan::Token &lexIncludeFilename(const char *&First, + const char *const End); void skipLine(const char *&First, const char *const End); void skipDirective(StringRef Name, const char *&First, const char *const End); @@ -544,7 +544,7 @@ Scanner::lexIncludeFilename(const char *&First, const char *const End) { void Scanner::lexPPDirectiveBody(const char *&First, const char *const End) { while (true) { const dependency_directives_scan::Token &Tok = lexToken(First, End); - if (Tok.is(tok::eod) || Tok.is(tok::eof)) + if (Tok.is(tok::eod)) break; } } @@ -912,11 +912,7 @@ bool Scanner::lexPPLine(const char *&First, const char *const End) { case pp___include_macros: case pp_include_next: case pp_import: - // Ignore missing filenames in include or import directives. - if (lexIncludeFilename(First, End).is(tok::eod)) { - skipDirective(Id, First, End); - return true; - } + lexIncludeFilename(First, End); break; default: break; diff --git a/clang/lib/Lex/PPLexerChange.cpp b/clang/lib/Lex/PPLexerChange.cpp index 8221db46e06acc..c3a903917e9ce1 100644 --- a/clang/lib/Lex/PPLexerChange.cpp +++ b/clang/lib/Lex/PPLexerChange.cpp @@ -122,7 +122,8 @@ void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer, CurPPLexer = TheLexer; CurDirLookup = CurDir; CurLexerSubmodule = nullptr; - if (CurLexerCallback != CLK_LexAfterModuleImport) + if (CurLexerCallback != CLK_LexAfterModuleImport && + CurLexerCallback != CLK_LexAfterModuleDecl) CurLexerCallback = TheLexer->isDependencyDirectivesLexer() ? CLK_DependencyDirectivesLexer : CLK_Lexer; @@ -161,8 +162,7 @@ void Preprocessor::EnterMacro(Token &Tok, SourceLocation ILEnd, PushIncludeMacroStack(); CurDirLookup = nullptr; CurTokenLexer = std::move(TokLexer); - if (CurLexerCallback != CLK_LexAfterModuleImport) - CurLexerCallback = CLK_TokenLexer; + CurLexerCallback = CLK_TokenLexer; } /// EnterTokenStream - Add a "macro" context to the top of the include stack, @@ -216,7 +216,8 @@ void Preprocessor::EnterTokenStream(const Token *Toks, unsigned NumToks, PushIncludeMacroStack(); CurDirLookup = nullptr; CurTokenLexer = std::move(TokLexer); - if (CurLexerCallback != CLK_LexAfterModuleImport) + if (CurLexerCallback != CLK_LexAfterModuleImport && + CurLexerCallback != CLK_LexAfterModuleDecl) CurLexerCallback = CLK_TokenLexer; } diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index 63e27e62cffc87..2726fae3443373 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -860,9 +860,15 @@ bool Preprocessor::HandleIdentifier(Token &Identifier) { ModuleImportLoc = Identifier.getLocation(); NamedModuleImportPath.clear(); IsAtImport = true; - ModuleImportExpectsIdentifier = true; CurLexerCallback = CLK_LexAfterModuleImport; } + + if ((II.isModulesDeclaration() || Identifier.is(tok::kw_module)) && + !InMacroArgs && !DisableMacroExpansion && + (getLangOpts().CPlusPlusModules || getLangOpts().DebuggerSupport) && + CurLexerCallback != CLK_CachingLexer) { + CurLexerCallback = CLK_LexAfterModuleDecl; + } return true; } @@ -905,6 +911,7 @@ void Preprocessor::Lex(Token &Result) { // This token is injected to represent the translation of '#include "a.h"' // into "import a.h;". Mimic the notional ';'. case tok::annot_module_include: + case tok::annot_repl_input_end: case tok::semi: TrackGMFState.handleSemi(); StdCXXImportSeqState.handleSemi(); @@ -919,12 +926,30 @@ void Preprocessor::Lex(Token &Result) { StdCXXImportSeqState.handleExport(); ModuleDeclState.handleExport(); break; - case tok::colon: - ModuleDeclState.handleColon(); - break; - case tok::period: - ModuleDeclState.handlePeriod(); + case tok::annot_module_name: { + auto *Info = static_cast(Result.getAnnotationValue()); + for (const auto &Tok : Info->getTokens()) { + switch (Tok.getKind()) { + case tok::identifier: + ModuleDeclState.handleIdentifier(Tok.getIdentifierInfo()); + break; + case tok::period: + ModuleDeclState.handlePeriod(); + break; + case tok::colon: + ModuleDeclState.handleColon(); + break; + default: + llvm_unreachable("Unexpected token in module name"); + } + } + if (ModuleDeclState.isModuleCandidate()) + break; + TrackGMFState.handleMisc(); + StdCXXImportSeqState.handleMisc(); + ModuleDeclState.handleMisc(); break; + } case tok::identifier: // Check "import" and "module" when there is no open bracket. The two // identifiers are not meaningful with open brackets. @@ -936,17 +961,17 @@ void Preprocessor::Lex(Token &Result) { ModuleImportLoc = Result.getLocation(); NamedModuleImportPath.clear(); IsAtImport = false; - ModuleImportExpectsIdentifier = true; CurLexerCallback = CLK_LexAfterModuleImport; } break; - } else if (Result.getIdentifierInfo() == getIdentifierInfo("module")) { + } + if (Result.getIdentifierInfo()->isModulesDeclaration()) { TrackGMFState.handleModule(StdCXXImportSeqState.afterTopLevelSeq()); ModuleDeclState.handleModule(); + CurLexerCallback = CLK_LexAfterModuleDecl; break; } } - ModuleDeclState.handleIdentifier(Result.getIdentifierInfo()); if (ModuleDeclState.isModuleCandidate()) break; [[fallthrough]]; @@ -1121,6 +1146,151 @@ void Preprocessor::CollectPpImportSuffix(SmallVectorImpl &Toks) { } } +ModuleNameInfo::ModuleNameInfo(ArrayRef AnnotToks, + std::optional ColonIndex) { + assert(!AnnotToks.empty() && "Named module token cannot be empty."); + if (!ColonIndex.has_value()) + ColonIndex = AnnotToks.size(); + ModuleName = ArrayRef(AnnotToks.begin(), AnnotToks.begin() + *ColonIndex); + PartitionName = ArrayRef(AnnotToks.begin() + *ColonIndex, AnnotToks.end()); + assert(ModuleName.end() == PartitionName.begin()); +} + +std::string ModuleNameInfo::getFlatName() const { + std::string FlatModuleName; + for (auto &Tok : getTokens()) { + switch (Tok.getKind()) { + case tok::identifier: + FlatModuleName += Tok.getIdentifierInfo()->getName(); + break; + case tok::period: + FlatModuleName += '.'; + break; + case tok::colon: + FlatModuleName += ':'; + break; + default: + llvm_unreachable("Unexpected token in module name"); + } + } + return FlatModuleName; +} + +void ModuleNameInfo::getModuleIdPath( + SmallVectorImpl> &Path) const { + return getModuleIdPath(getTokens(), Path); +} + +void ModuleNameInfo::getModuleIdPath( + ArrayRef ModuleName, + SmallVectorImpl> &Path) { + for (const auto &Tok : ModuleName) { + if (Tok.is(tok::identifier)) + Path.push_back( + std::make_pair(Tok.getIdentifierInfo(), Tok.getLocation())); + } +} + +/// Lex a module name or a partition name. +/// +/// module-name: +/// module-name-qualifier[opt] identifier +/// +/// partition-name: [C++20] +/// : module-name-qualifier[opt] identifier +/// +/// module-name-qualifier +/// module-name-qualifier[opt] identifier . +bool Preprocessor::LexModuleName(Token &Result, bool IsImport) { + bool ExpectsIdentifier = true, IsLexingPartition = false; + SmallVector ModuleName; + std::optional ColonTokIndex; + auto LexNextToken = [&](Token &Tok) { + if (IsImport) + Lex(Tok); + else + LexUnexpandedToken(Tok); + }; + + while (true) { + LexNextToken(Result); + if (ExpectsIdentifier && Result.is(tok::identifier)) { + auto *MI = getMacroInfo(Result.getIdentifierInfo()); + if (getLangOpts().CPlusPlusModules && !IsImport && MI && + MI->isObjectLike()) { + Diag(Result, diag::err_module_decl_cannot_be_macros) + << Result.getLocation() << IsLexingPartition + << Result.getIdentifierInfo(); + } + ModuleName.push_back(Result); + ExpectsIdentifier = false; + continue; + } + + if (!ExpectsIdentifier && Result.is(tok::period)) { + ModuleName.push_back(Result); + ExpectsIdentifier = true; + continue; + } + + // Module partition only allowed in C++20 Modules. + if (getLangOpts().CPlusPlusModules && Result.is(tok::colon)) { + // Handle the form like: import :P; + // If the token after ':' is not an identifier, this is a invalid module + // name. + if (ModuleName.empty()) { + Token Tmp; + LexNextToken(Tmp); + EnterToken(Tmp, /*IsReiject=*/false); + // A private-module-fragment: + // export module :private; + if (!IsImport && Tmp.is(tok::kw_private)) + return true; + // import :N; + if (IsImport && Tmp.isNot(tok::identifier)) + return false; + } else if (!ExpectsIdentifier) { + ExpectsIdentifier = true; + } + IsLexingPartition = true; + ColonTokIndex = ModuleName.size(); + ModuleName.push_back(Result); + continue; + } + + // [cpp.module]/p2: where the pp-tokens (if any) shall not begin with a ( + // preprocessing token [...] + // + // We only emit diagnostic in the preprocessor, and in the parser we skip + // invalid tokens and recover from errors. + if (getLangOpts().CPlusPlusModules && !ExpectsIdentifier && + Result.is(tok::l_paren)) + Diag(Result, diag::err_unxepected_paren_in_module_decl) + << IsLexingPartition; + break; + } + + // Put the last token back to stream, it's not a valid part of module name. + // We lexed it unexpanded but it might be a valid macro expansion + Result.clearFlag(Token::DisableExpand); + auto ToksCopy = std::make_unique(1); + *ToksCopy.get() = Result; + EnterTokenStream(std::move(ToksCopy), 1, + /*DisableMacroExpansion=*/false, + /*IsReinject=*/false); + + if (ModuleName.empty()) + return false; + Result.startToken(); + Result.setKind(tok::annot_module_name); + Result.setLocation(ModuleName.front().getLocation()); + Result.setAnnotationEndLoc(ModuleName.back().getLocation()); + auto AnnotToks = ArrayRef(ModuleName).copy(getPreprocessorAllocator()); + ModuleNameInfo *Info = + new (getPreprocessorAllocator()) ModuleNameInfo(AnnotToks, ColonTokIndex); + Result.setAnnotationValue(static_cast(Info)); + return true; +} /// Lex a token following the 'import' contextual keyword. /// @@ -1145,6 +1315,17 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) { // Figure out what kind of lexer we actually have. recomputeCurLexerKind(); + // Allocate a holding buffer for a sequence of tokens and introduce it into + // the token stream. + auto EnterTokens = [this](ArrayRef Toks) { + auto ToksCopy = std::make_unique(Toks.size()); + std::copy(Toks.begin(), Toks.end(), ToksCopy.get()); + EnterTokenStream(std::move(ToksCopy), Toks.size(), + /*DisableMacroExpansion*/ true, /*IsReinject*/ false); + }; + + SmallVector Suffix; + // Lex the next token. The header-name lexing rules are used at the start of // a pp-import. // @@ -1155,122 +1336,108 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) { if (LexHeaderName(Result)) return true; - if (Result.is(tok::colon) && ModuleDeclState.isNamedModule()) { - std::string Name = ModuleDeclState.getPrimaryName().str(); - Name += ":"; - NamedModuleImportPath.push_back( - {getIdentifierInfo(Name), Result.getLocation()}); - CurLexerCallback = CLK_LexAfterModuleImport; - return true; - } - } else { - Lex(Result); - } + // Check for a header-name. + if (Result.is(tok::header_name)) { + // Enter the header-name token into the token stream; a Lex action cannot + // both return a token and cache tokens (doing so would corrupt the token + // cache if the call to Lex comes from CachingLex / PeekAhead). + Suffix.push_back(Result); + + // Consume the pp-import-suffix and expand any macros in it now. We'll add + // it back into the token stream later. + CollectPpImportSuffix(Suffix); + if (Suffix.back().isNot(tok::semi)) { + // This is not a pp-import after all. + EnterTokens(Suffix); + return false; + } - // Allocate a holding buffer for a sequence of tokens and introduce it into - // the token stream. - auto EnterTokens = [this](ArrayRef Toks) { - auto ToksCopy = std::make_unique(Toks.size()); - std::copy(Toks.begin(), Toks.end(), ToksCopy.get()); - EnterTokenStream(std::move(ToksCopy), Toks.size(), - /*DisableMacroExpansion*/ true, /*IsReinject*/ false); - }; + // C++2a [cpp.module]p1: + // The ';' preprocessing-token terminating a pp-import shall not have + // been produced by macro replacement. + SourceLocation SemiLoc = Suffix.back().getLocation(); + if (SemiLoc.isMacroID()) + Diag(SemiLoc, diag::err_header_import_semi_in_macro); + + // Reconstitute the import token. + Token ImportTok; + ImportTok.startToken(); + ImportTok.setKind(tok::kw_import); + ImportTok.setLocation(ModuleImportLoc); + ImportTok.setIdentifierInfo(getIdentifierInfo("import")); + ImportTok.setLength(6); + + auto Action = HandleHeaderIncludeOrImport( + /*HashLoc*/ SourceLocation(), ImportTok, Suffix.front(), SemiLoc); + switch (Action.Kind) { + case ImportAction::None: + break; - bool ImportingHeader = Result.is(tok::header_name); - // Check for a header-name. - SmallVector Suffix; - if (ImportingHeader) { - // Enter the header-name token into the token stream; a Lex action cannot - // both return a token and cache tokens (doing so would corrupt the token - // cache if the call to Lex comes from CachingLex / PeekAhead). - Suffix.push_back(Result); + case ImportAction::ModuleBegin: + // Let the parser know we're textually entering the module. + Suffix.emplace_back(); + Suffix.back().startToken(); + Suffix.back().setKind(tok::annot_module_begin); + Suffix.back().setLocation(SemiLoc); + Suffix.back().setAnnotationEndLoc(SemiLoc); + Suffix.back().setAnnotationValue(Action.ModuleForHeader); + [[fallthrough]]; + + case ImportAction::ModuleImport: + case ImportAction::HeaderUnitImport: + case ImportAction::SkippedModuleImport: + // We chose to import (or textually enter) the file. Convert the + // header-name token into a header unit annotation token. + Suffix[0].setKind(tok::annot_header_unit); + Suffix[0].setAnnotationEndLoc(Suffix[0].getLocation()); + Suffix[0].setAnnotationValue(Action.ModuleForHeader); + // FIXME: Call the moduleImport callback? + break; + case ImportAction::Failure: + assert(TheModuleLoader.HadFatalFailure && + "This should be an early exit only to a fatal error"); + Result.setKind(tok::eof); + CurLexer->cutOffLexing(); + EnterTokens(Suffix); + return true; + } - // Consume the pp-import-suffix and expand any macros in it now. We'll add - // it back into the token stream later. - CollectPpImportSuffix(Suffix); - if (Suffix.back().isNot(tok::semi)) { - // This is not a pp-import after all. EnterTokens(Suffix); return false; } + } else { + Lex(Result); + } - // C++2a [cpp.module]p1: - // The ';' preprocessing-token terminating a pp-import shall not have - // been produced by macro replacement. - SourceLocation SemiLoc = Suffix.back().getLocation(); - if (SemiLoc.isMacroID()) - Diag(SemiLoc, diag::err_header_import_semi_in_macro); - - // Reconstitute the import token. - Token ImportTok; - ImportTok.startToken(); - ImportTok.setKind(tok::kw_import); - ImportTok.setLocation(ModuleImportLoc); - ImportTok.setIdentifierInfo(getIdentifierInfo("import")); - ImportTok.setLength(6); - - auto Action = HandleHeaderIncludeOrImport( - /*HashLoc*/ SourceLocation(), ImportTok, Suffix.front(), SemiLoc); - switch (Action.Kind) { - case ImportAction::None: - break; - - case ImportAction::ModuleBegin: - // Let the parser know we're textually entering the module. - Suffix.emplace_back(); - Suffix.back().startToken(); - Suffix.back().setKind(tok::annot_module_begin); - Suffix.back().setLocation(SemiLoc); - Suffix.back().setAnnotationEndLoc(SemiLoc); - Suffix.back().setAnnotationValue(Action.ModuleForHeader); - [[fallthrough]]; - - case ImportAction::ModuleImport: - case ImportAction::HeaderUnitImport: - case ImportAction::SkippedModuleImport: - // We chose to import (or textually enter) the file. Convert the - // header-name token into a header unit annotation token. - Suffix[0].setKind(tok::annot_header_unit); - Suffix[0].setAnnotationEndLoc(Suffix[0].getLocation()); - Suffix[0].setAnnotationValue(Action.ModuleForHeader); - // FIXME: Call the moduleImport callback? - break; - case ImportAction::Failure: - assert(TheModuleLoader.HadFatalFailure && - "This should be an early exit only to a fatal error"); - Result.setKind(tok::eof); - CurLexer->cutOffLexing(); - EnterTokens(Suffix); + if (Result.isOneOf(tok::identifier, tok::colon)) { + EnterToken(Result, /*IsReinject=*/false); + if (!LexModuleName(Result, /*IsImport=*/true)) return true; + auto *Info = Result.getAnnotationValueAs(); + if (getLangOpts().CPlusPlusModules) { + // Under the standard C++ Modules, the dot is just part of the module + // name, and not a real hierarchy separator. Flatten such module names + // now. + // + // FIXME: Is this the right level to be performing this transformation? + std::string FlatModuleName; + if (Info->getTokens().front().is(tok::colon)) { + // Import a module partition allowed in C++20 Modules. + // We can import a partition in named module TU. + if (NamedModuleImportPath.empty() && ModuleDeclState.isNamedModule()) + FlatModuleName = llvm::Twine(ModuleDeclState.getPrimaryName()) + .concat(Info->getFlatName()) + .str(); + else + return true; + } else { + FlatModuleName = Info->getFlatName(); + } + NamedModuleImportPath.emplace_back(getIdentifierInfo(FlatModuleName), + Result.getLocation()); + } else { + Info->getModuleIdPath(NamedModuleImportPath); } - - EnterTokens(Suffix); - return false; - } - - // The token sequence - // - // import identifier (. identifier)* - // - // indicates a module import directive. We already saw the 'import' - // contextual keyword, so now we're looking for the identifiers. - if (ModuleImportExpectsIdentifier && Result.getKind() == tok::identifier) { - // We expected to see an identifier here, and we did; continue handling - // identifiers. - NamedModuleImportPath.push_back( - std::make_pair(Result.getIdentifierInfo(), Result.getLocation())); - ModuleImportExpectsIdentifier = false; - CurLexerCallback = CLK_LexAfterModuleImport; - return true; - } - - // If we're expecting a '.' or a ';', and we got a '.', then wait until we - // see the next identifier. (We can also see a '[[' that begins an - // attribute-specifier-seq here under the Standard C++ Modules.) - if (!ModuleImportExpectsIdentifier && Result.getKind() == tok::period) { - ModuleImportExpectsIdentifier = true; - CurLexerCallback = CLK_LexAfterModuleImport; - return true; } // If we didn't recognize a module name at all, this is not a (valid) import. @@ -1291,24 +1458,6 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) { SemiLoc = Suffix.back().getLocation(); } - // Under the standard C++ Modules, the dot is just part of the module name, - // and not a real hierarchy separator. Flatten such module names now. - // - // FIXME: Is this the right level to be performing this transformation? - std::string FlatModuleName; - if (getLangOpts().CPlusPlusModules) { - for (auto &Piece : NamedModuleImportPath) { - // If the FlatModuleName ends with colon, it implies it is a partition. - if (!FlatModuleName.empty() && FlatModuleName.back() != ':') - FlatModuleName += "."; - FlatModuleName += Piece.first->getName(); - } - SourceLocation FirstPathLoc = NamedModuleImportPath[0].second; - NamedModuleImportPath.clear(); - NamedModuleImportPath.push_back( - std::make_pair(getIdentifierInfo(FlatModuleName), FirstPathLoc)); - } - Module *Imported = nullptr; // We don't/shouldn't load the standard c++20 modules when preprocessing. if (getLangOpts().Modules && !isInImportingCXXNamedModules()) { @@ -1330,6 +1479,33 @@ bool Preprocessor::LexAfterModuleImport(Token &Result) { return true; } +/// Lex a token following the 'module' contextual keyword. +/// +/// [cpp.module]/p2: +/// The pp-tokens, if any, of a pp-module shall be of the form: +/// pp-module-name pp-module-partition[opt] pp-tokens[opt] +/// +/// where the pp-tokens (if any) shall not begin with a ( preprocessing token +/// and the grammar non-terminals are defined as: +/// pp-module-name: +/// pp-module-name-qualifierp[opt] identifier +/// pp-module-partition: +/// : pp-module-name-qualifier[opt] identifier +/// pp-module-name-qualifier: +/// identifier . +/// pp-module-name-qualifier identifier . +/// No identifier in the pp-module-name or pp-module-partition shall currently +/// be defined as an object-like macro. +/// +/// [cpp.module]/p3: +/// Any preprocessing tokens after the module preprocessing token in the module +/// directive are processed just as in normal text. +bool Preprocessor::LexAfterModuleDecl(Token &Result) { + // Figure out what kind of lexer we actually have. + recomputeCurLexerKind(); + return LexModuleName(Result, /*IsImport=*/false); +} + void Preprocessor::makeModuleVisible(Module *M, SourceLocation Loc) { CurSubmoduleState->VisibleModules.setVisible( M, Loc, [](Module *) {}, diff --git a/clang/lib/Lex/TokenConcatenation.cpp b/clang/lib/Lex/TokenConcatenation.cpp index 865879d1805336..cdb636923b9e91 100644 --- a/clang/lib/Lex/TokenConcatenation.cpp +++ b/clang/lib/Lex/TokenConcatenation.cpp @@ -160,6 +160,13 @@ static char GetFirstChar(const Preprocessor &PP, const Token &Tok) { bool TokenConcatenation::AvoidConcat(const Token &PrevPrevTok, const Token &PrevTok, const Token &Tok) const { + // If previous token is a module name, we need avoid concat it with current + // token, otherwise, there will has an extra space between 'M' and ';' for the + // following code: + // + // import M; + if (PrevTok.is(tok::annot_module_name)) + return false; // Conservatively assume that every annotation token that has a printable // form requires whitespace. if (PrevTok.isAnnotation()) @@ -190,6 +197,9 @@ bool TokenConcatenation::AvoidConcat(const Token &PrevPrevTok, return true; ConcatInfo &= ~aci_avoid_equal; } + + if (Tok.is(tok::annot_module_name)) + return true; if (Tok.isAnnotation()) { // Modules annotation can show up when generated automatically for includes. assert(Tok.isOneOf(tok::annot_module_include, tok::annot_module_begin, diff --git a/clang/lib/Parse/ParseAST.cpp b/clang/lib/Parse/ParseAST.cpp index e008cc0e38ceda..77ab3b556da58c 100644 --- a/clang/lib/Parse/ParseAST.cpp +++ b/clang/lib/Parse/ParseAST.cpp @@ -152,15 +152,7 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { bool HaveLexer = S.getPreprocessor().getCurrentLexer(); if (HaveLexer) { - llvm::TimeTraceScope TimeScope("Frontend", [&]() { - llvm::TimeTraceMetadata M; - if (llvm::isTimeTraceVerbose()) { - const SourceManager &SM = S.getSourceManager(); - if (const auto *FE = SM.getFileEntryForID(SM.getMainFileID())) - M.File = FE->tryGetRealPathName(); - } - return M; - }); + llvm::TimeTraceScope TimeScope("Frontend"); P.Initialize(); Parser::DeclGroupPtrTy ADecl; Sema::ModuleImportState ImportState; diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 7ce9a9cea1c7af..577527d0318f2a 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3958,7 +3958,13 @@ void Parser::ParseDeclarationSpecifiers( // We're done with the declaration-specifiers. goto DoneWithDeclSpec; - + case tok::annot_module_name: { + PP.EnterTokenStream( + Tok.getAnnotationValueAs()->getTokens(), + /*DisableMacroExpansion=*/true, /*IsReinject=*/false); + ConsumeAnyToken(); + [[fallthrough]]; + } // typedef-name case tok::kw___super: case tok::kw_decltype: diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index a12c375c8d48c7..3d7c58e5b3c3cd 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -3597,7 +3597,7 @@ void Parser::injectEmbedTokens() { I += 2; } PP.EnterTokenStream(std::move(Toks), /*DisableMacroExpansion=*/true, - /*IsReinject=*/true); + /*IsReinject=*/false); ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); } diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index aef4ddb7588164..cc6f18b5b319f9 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -14,7 +14,6 @@ #include "clang/Basic/PragmaKinds.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" -#include "clang/Lex/PreprocessorOptions.h" #include "clang/Lex/Token.h" #include "clang/Parse/LoopHint.h" #include "clang/Parse/ParseDiagnostic.h" @@ -412,19 +411,6 @@ struct PragmaRISCVHandler : public PragmaHandler { Sema &Actions; }; -struct PragmaMCFuncHandler : public PragmaHandler { - PragmaMCFuncHandler(bool ReportError) - : PragmaHandler("mc_func"), ReportError(ReportError) {} - void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, - Token &Tok) override { - if (ReportError) - PP.Diag(Tok, diag::err_pragma_mc_func_not_supported); - } - -private: - bool ReportError = false; -}; - void markAsReinjectedForRelexing(llvm::MutableArrayRef Toks) { for (auto &T : Toks) T.setFlag(clang::Token::IsReinjected); @@ -582,12 +568,6 @@ void Parser::initializePragmaHandlers() { RISCVPragmaHandler = std::make_unique(Actions); PP.AddPragmaHandler("clang", RISCVPragmaHandler.get()); } - - if (getTargetInfo().getTriple().isOSAIX()) { - MCFuncPragmaHandler = std::make_unique( - PP.getPreprocessorOpts().ErrorOnPragmaMcfuncOnAIX); - PP.AddPragmaHandler(MCFuncPragmaHandler.get()); - } } void Parser::resetPragmaHandlers() { @@ -722,11 +702,6 @@ void Parser::resetPragmaHandlers() { PP.RemovePragmaHandler("clang", RISCVPragmaHandler.get()); RISCVPragmaHandler.reset(); } - - if (getTargetInfo().getTriple().isOSAIX()) { - PP.RemovePragmaHandler(MCFuncPragmaHandler.get()); - MCFuncPragmaHandler.reset(); - } } /// Handle the annotation token produced for #pragma unused(...) diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index bdb3fc051d0b35..22d38adc28ebe9 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -299,15 +299,6 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes( goto Retry; } - case tok::kw_template: { - SourceLocation DeclEnd; - ParsedAttributes Attrs(AttrFactory); - ParseTemplateDeclarationOrSpecialization(DeclaratorContext::Block, DeclEnd, - Attrs, - getAccessSpecifierIfPresent()); - return StmtError(); - } - case tok::kw_case: // C99 6.8.1: labeled-statement return ParseCaseStatement(StmtCtx); case tok::kw_default: // C99 6.8.1: labeled-statement diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 5ebe71e496a2e8..afb2e1e4161682 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -2511,18 +2511,28 @@ Parser::ParseModuleDecl(Sema::ModuleImportState &ImportState) { } SmallVector, 2> Path; - if (ParseModuleName(ModuleLoc, Path, /*IsImport*/ false)) + if (Tok.isNot(tok::annot_module_name)) { + Diag(Tok, diag::err_module_expected_ident) << /*IsImport=*/false; + SkipUntil(tok::semi, StopBeforeMatch); + return nullptr; + } + + auto *Info = Tok.getAnnotationValueAs(); + ConsumeAnnotationToken(); + if (ParseModuleName(ModuleLoc, Info->getModuleName(), Path, + /*IsImport=*/false)) return nullptr; // Parse the optional module-partition. SmallVector, 2> Partition; - if (Tok.is(tok::colon)) { - SourceLocation ColonLoc = ConsumeToken(); + if (Info->hasPartitionName()) { + SourceLocation ColonLoc = Info->getColonToken().getLocation(); if (!getLangOpts().CPlusPlusModules) Diag(ColonLoc, diag::err_unsupported_module_partition) << SourceRange(ColonLoc, Partition.back().second); // Recover by ignoring the partition name. - else if (ParseModuleName(ModuleLoc, Partition, /*IsImport*/ false)) + else if (ParseModuleName(ModuleLoc, Info->getPartitionName(), Partition, + /*IsImport=*/false)) return nullptr; } @@ -2581,18 +2591,32 @@ Decl *Parser::ParseModuleImport(SourceLocation AtLoc, // This is a header import that the preprocessor mapped to a module import. HeaderUnit = reinterpret_cast(Tok.getAnnotationValue()); ConsumeAnnotationToken(); - } else if (Tok.is(tok::colon)) { - SourceLocation ColonLoc = ConsumeToken(); - if (!getLangOpts().CPlusPlusModules) - Diag(ColonLoc, diag::err_unsupported_module_partition) - << SourceRange(ColonLoc, Path.back().second); - // Recover by leaving partition empty. - else if (ParseModuleName(ColonLoc, Path, /*IsImport*/ true)) - return nullptr; - else - IsPartition = true; } else { - if (ParseModuleName(ImportLoc, Path, /*IsImport*/ true)) + if (Tok.isNot(tok::annot_module_name)) { + if (Tok.is(tok::code_completion)) { + cutOffParsing(); + Actions.CodeCompletion().CodeCompleteModuleImport(ImportLoc, Path); + return nullptr; + } + Diag(Tok, diag::err_module_expected_ident) << /*IsImport=*/true; + SkipUntil(tok::semi, StopBeforeMatch); + return nullptr; + } + auto *Info = Tok.getAnnotationValueAs(); + ConsumeAnnotationToken(); + if (Info->hasPartitionName()) { + SourceLocation ColonLoc = Info->getColonToken().getLocation(); + if (!getLangOpts().CPlusPlusModules) + Diag(ColonLoc, diag::err_unsupported_module_partition) + << SourceRange(ColonLoc, Path.back().second); + // Recover by leaving partition empty. + else if (ParseModuleName(ColonLoc, Info->getPartitionName(), Path, + /*IsImport=*/true)) + return nullptr; + else + IsPartition = true; + } else if (ParseModuleName(ImportLoc, Info->getModuleName(), Path, + /*IsImport=*/true)) return nullptr; } @@ -2689,32 +2713,31 @@ Decl *Parser::ParseModuleImport(SourceLocation AtLoc, /// module-name-qualifier: /// module-name-qualifier[opt] identifier '.' bool Parser::ParseModuleName( - SourceLocation UseLoc, + SourceLocation UseLoc, ArrayRef ModuleName, SmallVectorImpl> &Path, bool IsImport) { - // Parse the module path. - while (true) { - if (!Tok.is(tok::identifier)) { - if (Tok.is(tok::code_completion)) { - cutOffParsing(); - Actions.CodeCompletion().CodeCompleteModuleImport(UseLoc, Path); - return true; - } - - Diag(Tok, diag::err_module_expected_ident) << IsImport; - SkipUntil(tok::semi); + ModuleNameInfo::getModuleIdPath(ModuleName, Path); + // Eg. import A.B. + if (ModuleName.back().isNot(tok::identifier)) { + if (Tok.is(tok::code_completion)) { + cutOffParsing(); + Actions.CodeCompletion().CodeCompleteModuleImport(UseLoc, Path); return true; } + Diag(ModuleName.back(), diag::err_module_expected_ident) << IsImport; + SkipUntil(tok::semi, StopBeforeMatch); + return true; + } - // Record this part of the module path. - Path.push_back(std::make_pair(Tok.getIdentifierInfo(), Tok.getLocation())); - ConsumeToken(); - - if (Tok.isNot(tok::period)) - return false; - - ConsumeToken(); + // [cpp.module]/p2: where the pp-tokens (if any) shall not begin with a ( + // preprocessing token [...] + // + // Skip unitl ';' to recovery. + if (getLangOpts().CPlusPlusModules && Tok.is(tok::l_paren)) { + SkipUntil(tok::semi, StopBeforeMatch); + return true; } + return false; } /// Try recover parser when module annotation appears where it must not diff --git a/clang/lib/Sema/SemaAPINotes.cpp b/clang/lib/Sema/SemaAPINotes.cpp index be5b7b92dfe6f1..055e66a0c34861 100644 --- a/clang/lib/Sema/SemaAPINotes.cpp +++ b/clang/lib/Sema/SemaAPINotes.cpp @@ -783,77 +783,51 @@ static void ProcessVersionedAPINotes( } } -static std::optional -UnwindNamespaceContext(DeclContext *DC, api_notes::APINotesManager &APINotes) { - if (auto NamespaceContext = dyn_cast(DC)) { - for (auto Reader : APINotes.findAPINotes(NamespaceContext->getLocation())) { - // Retrieve the context ID for the parent namespace of the decl. - std::stack NamespaceStack; - { - for (auto CurrentNamespace = NamespaceContext; CurrentNamespace; - CurrentNamespace = - dyn_cast(CurrentNamespace->getParent())) { - if (!CurrentNamespace->isInlineNamespace()) - NamespaceStack.push(CurrentNamespace); - } - } - std::optional NamespaceID; - while (!NamespaceStack.empty()) { - auto CurrentNamespace = NamespaceStack.top(); - NamespaceStack.pop(); - NamespaceID = - Reader->lookupNamespaceID(CurrentNamespace->getName(), NamespaceID); - if (!NamespaceID) - return std::nullopt; - } - if (NamespaceID) - return api_notes::Context(*NamespaceID, - api_notes::ContextKind::Namespace); - } - } - return std::nullopt; -} - -static std::optional -UnwindTagContext(TagDecl *DC, api_notes::APINotesManager &APINotes) { - assert(DC && "tag context must not be null"); - for (auto Reader : APINotes.findAPINotes(DC->getLocation())) { - // Retrieve the context ID for the parent tag of the decl. - std::stack TagStack; - { - for (auto CurrentTag = DC; CurrentTag; - CurrentTag = dyn_cast(CurrentTag->getParent())) - TagStack.push(CurrentTag); - } - assert(!TagStack.empty()); - std::optional Ctx = - UnwindNamespaceContext(TagStack.top()->getDeclContext(), APINotes); - while (!TagStack.empty()) { - auto CurrentTag = TagStack.top(); - TagStack.pop(); - auto CtxID = Reader->lookupTagID(CurrentTag->getName(), Ctx); - if (!CtxID) - return std::nullopt; - Ctx = api_notes::Context(*CtxID, api_notes::ContextKind::Tag); - } - return Ctx; - } - return std::nullopt; -} - /// Process API notes that are associated with this declaration, mapping them /// to attributes as appropriate. void Sema::ProcessAPINotes(Decl *D) { if (!D) return; + auto GetNamespaceContext = + [&](DeclContext *DC) -> std::optional { + if (auto NamespaceContext = dyn_cast(DC)) { + for (auto Reader : + APINotes.findAPINotes(NamespaceContext->getLocation())) { + // Retrieve the context ID for the parent namespace of the decl. + std::stack NamespaceStack; + { + for (auto CurrentNamespace = NamespaceContext; CurrentNamespace; + CurrentNamespace = + dyn_cast(CurrentNamespace->getParent())) { + if (!CurrentNamespace->isInlineNamespace()) + NamespaceStack.push(CurrentNamespace); + } + } + std::optional NamespaceID; + while (!NamespaceStack.empty()) { + auto CurrentNamespace = NamespaceStack.top(); + NamespaceStack.pop(); + NamespaceID = Reader->lookupNamespaceID(CurrentNamespace->getName(), + NamespaceID); + if (!NamespaceID) + break; + } + if (NamespaceID) + return api_notes::Context(*NamespaceID, + api_notes::ContextKind::Namespace); + } + } + return std::nullopt; + }; + // Globals. if (D->getDeclContext()->isFileContext() || D->getDeclContext()->isNamespace() || D->getDeclContext()->isExternCContext() || D->getDeclContext()->isExternCXXContext()) { std::optional APINotesContext = - UnwindNamespaceContext(D->getDeclContext(), APINotes); + GetNamespaceContext(D->getDeclContext()); // Global variables. if (auto VD = dyn_cast(D)) { for (auto Reader : APINotes.findAPINotes(D->getLocation())) { @@ -925,8 +899,6 @@ void Sema::ProcessAPINotes(Decl *D) { } for (auto Reader : APINotes.findAPINotes(D->getLocation())) { - if (auto ParentTag = dyn_cast(Tag->getDeclContext())) - APINotesContext = UnwindTagContext(ParentTag, APINotes); auto Info = Reader->lookupTag(LookupName, APINotesContext); ProcessVersionedAPINotes(*this, Tag, Info); } @@ -1042,24 +1014,23 @@ void Sema::ProcessAPINotes(Decl *D) { } } - if (auto TagContext = dyn_cast(D->getDeclContext())) { + if (auto CXXRecord = dyn_cast(D->getDeclContext())) { + auto GetRecordContext = [&](api_notes::APINotesReader *Reader) + -> std::optional { + auto ParentContext = GetNamespaceContext(CXXRecord->getDeclContext()); + if (auto Found = Reader->lookupTagID(CXXRecord->getName(), ParentContext)) + return *Found; + + return std::nullopt; + }; + if (auto CXXMethod = dyn_cast(D)) { for (auto Reader : APINotes.findAPINotes(D->getLocation())) { - if (auto Context = UnwindTagContext(TagContext, APINotes)) { - auto Info = - Reader->lookupCXXMethod(Context->id, CXXMethod->getName()); + if (auto Context = GetRecordContext(Reader)) { + auto Info = Reader->lookupCXXMethod(*Context, CXXMethod->getName()); ProcessVersionedAPINotes(*this, CXXMethod, Info); } } } - - if (auto Tag = dyn_cast(D)) { - for (auto Reader : APINotes.findAPINotes(D->getLocation())) { - if (auto Context = UnwindTagContext(TagContext, APINotes)) { - auto Info = Reader->lookupTag(Tag->getName(), Context); - ProcessVersionedAPINotes(*this, Tag, Info); - } - } - } } } diff --git a/clang/lib/Sema/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp index 17566c226ec807..df83bbfb7aac82 100644 --- a/clang/lib/Sema/SemaAvailability.cpp +++ b/clang/lib/Sema/SemaAvailability.cpp @@ -107,12 +107,6 @@ ShouldDiagnoseAvailabilityOfDecl(Sema &S, const NamedDecl *D, break; } - // For alias templates, get the underlying declaration. - if (const auto *ADecl = dyn_cast(D)) { - D = ADecl->getTemplatedDecl(); - Result = D->getAvailability(Message); - } - // Forward class declarations get their attributes from their definition. if (const auto *IDecl = dyn_cast(D)) { if (IDecl->getDefinition()) { diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 5fd8622c90dd8e..50e7be9ea60207 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5247,10 +5247,6 @@ static void handleXRayLogArgsAttr(Sema &S, Decl *D, const ParsedAttr &AL) { static void handlePatchableFunctionEntryAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (S.Context.getTargetInfo().getTriple().isOSAIX()) { - S.Diag(AL.getLoc(), diag::err_aix_attr_unsupported) << AL; - return; - } uint32_t Count = 0, Offset = 0; if (!S.checkUInt32Argument(AL, AL.getArgAsExpr(0), Count, 0, true)) return; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 439db55668cc6d..8d24e34520e778 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -10909,14 +10909,6 @@ QualType Sema::CheckAdditionOperands(ExprResult &LHS, ExprResult &RHS, if (isObjCPointer && checkArithmeticOnObjCPointer(*this, Loc, PExp)) return QualType(); - // Arithmetic on label addresses is normally allowed, except when we add - // a ptrauth signature to the addresses. - if (isa(PExp) && getLangOpts().PointerAuthIndirectGotos) { - Diag(Loc, diag::err_ptrauth_indirect_goto_addrlabel_arithmetic) - << /*addition*/ 1; - return QualType(); - } - // Check array bounds for pointer arithemtic CheckArrayAccess(PExp, IExp); @@ -10991,15 +10983,6 @@ QualType Sema::CheckSubtractionOperands(ExprResult &LHS, ExprResult &RHS, checkArithmeticOnObjCPointer(*this, Loc, LHS.get())) return QualType(); - // Arithmetic on label addresses is normally allowed, except when we add - // a ptrauth signature to the addresses. - if (isa(LHS.get()) && - getLangOpts().PointerAuthIndirectGotos) { - Diag(Loc, diag::err_ptrauth_indirect_goto_addrlabel_arithmetic) - << /*subtraction*/ 0; - return QualType(); - } - // The result type of a pointer-int computation is the pointer type. if (RHS.get()->getType()->isIntegerType()) { // Subtracting from a null pointer should produce a warning. @@ -14134,14 +14117,7 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { // Okay: we can take the address of a field. // Could be a pointer to member, though, if there is an explicit // scope qualifier for the class. - - // [C++26] [expr.prim.id.general] - // If an id-expression E denotes a non-static non-type member - // of some class C [...] and if E is a qualified-id, E is - // not the un-parenthesized operand of the unary & operator [...] - // the id-expression is transformed into a class member access expression. - if (isa(op) && cast(op)->getQualifier() && - !isa(OrigOp.get())) { + if (isa(op) && cast(op)->getQualifier()) { DeclContext *Ctx = dcl->getDeclContext(); if (Ctx && Ctx->isRecord()) { if (dcl->getType()->isReferenceType()) { @@ -14151,6 +14127,22 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { return QualType(); } + // C++11 [expr.unary.op] p4: + // A pointer to member is only formed when an explicit & is used and + // its operand is a qualified-id not enclosed in parentheses. + if (isa(OrigOp.get())) { + SourceLocation LeftParenLoc = OrigOp.get()->getBeginLoc(), + RightParenLoc = OrigOp.get()->getEndLoc(); + + Diag(LeftParenLoc, + diag::err_form_ptr_to_member_from_parenthesized_expr) + << SourceRange(OpLoc, RightParenLoc) + << FixItHint::CreateRemoval(LeftParenLoc) + << FixItHint::CreateRemoval(RightParenLoc); + + // Continuing might lead to better error recovery. + } + while (cast(Ctx)->isAnonymousStructOrUnion()) Ctx = Ctx->getParent(); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 67e3c1d9067f37..3bd981cb442aaf 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -6168,14 +6168,14 @@ StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective( DMC->getDefaultmapModifierLoc(); } for (unsigned VC = 0; VC < DefaultmapKindNum; ++VC) { - auto K = static_cast(VC); + auto Kind = static_cast(VC); for (unsigned I = 0; I < OMPC_MAP_delete; ++I) { - ArrayRef ImplicitMap = - DSAChecker.getImplicitMap(K, static_cast(I)); + ArrayRef ImplicitMap = DSAChecker.getImplicitMap( + Kind, static_cast(I)); ImplicitMaps[VC][I].append(ImplicitMap.begin(), ImplicitMap.end()); } ArrayRef ImplicitModifier = - DSAChecker.getImplicitMapModifier(K); + DSAChecker.getImplicitMapModifier(Kind); ImplicitMapModifiers[VC].append(ImplicitModifier.begin(), ImplicitModifier.end()); std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[VC]), @@ -6249,10 +6249,10 @@ StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective( continue; CXXScopeSpec MapperIdScopeSpec; DeclarationNameInfo MapperId; - auto K = static_cast(ClauseKindCnt); + auto Kind = static_cast(ClauseKindCnt); if (OMPClause *Implicit = ActOnOpenMPMapClause( nullptr, ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I], - MapperIdScopeSpec, MapperId, K, /*IsMapTypeImplicit=*/true, + MapperIdScopeSpec, MapperId, Kind, /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), ImplicitMap, OMPVarListLocTy())) { ClausesWithImplicit.emplace_back(Implicit); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index a8d250fbabfed4..ac90ccd5643c1c 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -11149,7 +11149,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, if (isa(Fn) && !isa(Fn)) { if (I == 0) isObjectArgument = true; - else + else if (!Fn->hasCXXExplicitFunctionObjectParameter()) I--; } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 87b1f98bbe5ac9..9d96201625389f 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -3344,10 +3344,6 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, *this, /*PointOfInstantiation=*/TemplateLoc, /*Entity=*/AliasTemplate, /*TemplateArgs=*/TemplateArgLists.getInnermost()); - - // Diagnose uses of this alias. - (void)DiagnoseUseOfDecl(AliasTemplate, TemplateLoc); - if (Inst.isInvalid()) return QualType(); diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index 0602d07c6b9b0d..7dff2c8f985895 100644 --- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp +++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp @@ -363,7 +363,8 @@ struct ConvertConstructorToDeductionGuideTransform { return nullptr; // Constraints require that we substitute depth-1 arguments // to match depths when substituted for evaluation later - Depth1Args.push_back(SemaRef.Context.getInjectedTemplateArg(NewParam)); + Depth1Args.push_back(SemaRef.Context.getCanonicalTemplateArgument( + SemaRef.Context.getInjectedTemplateArg(NewParam))); if (NestedPattern) { TemplateDeclInstantiator Instantiator(SemaRef, DC, @@ -378,7 +379,8 @@ struct ConvertConstructorToDeductionGuideTransform { "Unexpected template parameter depth"); AllParams.push_back(NewParam); - SubstArgs.push_back(SemaRef.Context.getInjectedTemplateArg(NewParam)); + SubstArgs.push_back(SemaRef.Context.getCanonicalTemplateArgument( + SemaRef.Context.getInjectedTemplateArg(NewParam))); } // Substitute new template parameters into requires-clause if present. @@ -793,8 +795,8 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F, /*NewIndex=*/AdjustedAliasTemplateArgs.size(), getTemplateParameterDepth(TP) + AdjustDepth); - TemplateArgument NewTemplateArgument = - Context.getInjectedTemplateArg(NewParam); + auto NewTemplateArgument = Context.getCanonicalTemplateArgument( + Context.getInjectedTemplateArg(NewParam)); AdjustedAliasTemplateArgs.push_back(NewTemplateArgument); } // Template arguments used to transform the template arguments in @@ -820,8 +822,8 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F, getTemplateParameterDepth(TP) + AdjustDepth); FirstUndeducedParamIdx += 1; assert(TemplateArgsForBuildingRC[Index].isNull()); - TemplateArgsForBuildingRC[Index] = - Context.getInjectedTemplateArg(NewParam); + TemplateArgsForBuildingRC[Index] = Context.getCanonicalTemplateArgument( + Context.getInjectedTemplateArg(NewParam)); continue; } TemplateArgumentLoc Input = @@ -921,8 +923,8 @@ Expr *buildIsDeducibleConstraint(Sema &SemaRef, /*NewIndex=*/TransformedTemplateArgs.size(), getTemplateParameterDepth(TP) + AdjustDepth); - TemplateArgument NewTemplateArgument = - Context.getInjectedTemplateArg(NewParam); + auto NewTemplateArgument = Context.getCanonicalTemplateArgument( + Context.getInjectedTemplateArg(NewParam)); TransformedTemplateArgs.push_back(NewTemplateArgument); } // Transformed the ReturnType to restore the uninstantiated depth. @@ -1085,8 +1087,8 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef, getTemplateParameterDepth(TP)); FPrimeTemplateParams.push_back(NewParam); - TemplateArgument NewTemplateArgument = - Context.getInjectedTemplateArg(NewParam); + auto NewTemplateArgument = Context.getCanonicalTemplateArgument( + Context.getInjectedTemplateArg(NewParam)); TransformedDeducedAliasArgs[AliasTemplateParamIdx] = NewTemplateArgument; } unsigned FirstUndeducedParamIdx = FPrimeTemplateParams.size(); @@ -1107,7 +1109,8 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef, assert(TemplateArgsForBuildingFPrime[FTemplateParamIdx].isNull() && "The argument must be null before setting"); TemplateArgsForBuildingFPrime[FTemplateParamIdx] = - Context.getInjectedTemplateArg(NewParam); + Context.getCanonicalTemplateArgument( + Context.getInjectedTemplateArg(NewParam)); } // To form a deduction guide f' from f, we leverage clang's instantiation diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 8995d461362d70..a7bc6749c58520 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2576,12 +2576,16 @@ createSubstDiag(Sema &S, TemplateDeductionInfo &Info, } else { ErrorLoc = Info.getLocation(); } + char *MessageBuf = new (S.Context) char[Message.size()]; + std::copy(Message.begin(), Message.end(), MessageBuf); SmallString<128> Entity; llvm::raw_svector_ostream OS(Entity); Printer(OS); - const ASTContext &C = S.Context; - return new (C) concepts::Requirement::SubstitutionDiagnostic{ - C.backupStr(Entity), ErrorLoc, C.backupStr(Message)}; + char *EntityBuf = new (S.Context) char[Entity.size()]; + std::copy(Entity.begin(), Entity.end(), EntityBuf); + return new (S.Context) concepts::Requirement::SubstitutionDiagnostic{ + StringRef(EntityBuf, Entity.size()), ErrorLoc, + StringRef(MessageBuf, Message.size())}; } concepts::Requirement::SubstitutionDiagnostic * @@ -2590,9 +2594,10 @@ concepts::createSubstDiagAt(Sema &S, SourceLocation Location, SmallString<128> Entity; llvm::raw_svector_ostream OS(Entity); Printer(OS); - const ASTContext &C = S.Context; - return new (C) concepts::Requirement::SubstitutionDiagnostic{ - /*SubstitutedEntity=*/C.backupStr(Entity), + char *EntityBuf = new (S.Context) char[Entity.size()]; + llvm::copy(Entity, EntityBuf); + return new (S.Context) concepts::Requirement::SubstitutionDiagnostic{ + /*SubstitutedEntity=*/StringRef(EntityBuf, Entity.size()), /*DiagLoc=*/Location, /*DiagMessage=*/StringRef()}; } @@ -2768,21 +2773,23 @@ TemplateInstantiator::TransformNestedRequirement( assert(!Trap.hasErrorOccurred() && "Substitution failures must be handled " "by CheckConstraintSatisfaction."); } - ASTContext &C = SemaRef.Context; if (TransConstraint.isUsable() && TransConstraint.get()->isInstantiationDependent()) - return new (C) concepts::NestedRequirement(TransConstraint.get()); + return new (SemaRef.Context) + concepts::NestedRequirement(TransConstraint.get()); if (TransConstraint.isInvalid() || !TransConstraint.get() || Satisfaction.HasSubstitutionFailure()) { SmallString<128> Entity; llvm::raw_svector_ostream OS(Entity); Req->getConstraintExpr()->printPretty(OS, nullptr, SemaRef.getPrintingPolicy()); - return new (C) concepts::NestedRequirement( - SemaRef.Context, C.backupStr(Entity), Satisfaction); + char *EntityBuf = new (SemaRef.Context) char[Entity.size()]; + std::copy(Entity.begin(), Entity.end(), EntityBuf); + return new (SemaRef.Context) concepts::NestedRequirement( + SemaRef.Context, StringRef(EntityBuf, Entity.size()), Satisfaction); } - return new (C) - concepts::NestedRequirement(C, TransConstraint.get(), Satisfaction); + return new (SemaRef.Context) concepts::NestedRequirement( + SemaRef.Context, TransConstraint.get(), Satisfaction); } TypeSourceInfo *Sema::SubstType(TypeSourceInfo *T, @@ -3419,16 +3426,11 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, return true; llvm::TimeTraceScope TimeScope("InstantiateClass", [&]() { - llvm::TimeTraceMetadata M; - llvm::raw_string_ostream OS(M.Detail); + std::string Name; + llvm::raw_string_ostream OS(Name); Instantiation->getNameForDiagnostic(OS, getPrintingPolicy(), /*Qualified=*/true); - if (llvm::isTimeTraceVerbose()) { - auto Loc = SourceMgr.getExpansionLoc(Instantiation->getLocation()); - M.File = SourceMgr.getFilename(Loc); - M.Line = SourceMgr.getExpansionLineNumber(Loc); - } - return M; + return Name; }); Pattern = PatternDef; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index a12d2eff1d2c81..97161febc15f7f 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4966,16 +4966,11 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, } llvm::TimeTraceScope TimeScope("InstantiateFunction", [&]() { - llvm::TimeTraceMetadata M; - llvm::raw_string_ostream OS(M.Detail); + std::string Name; + llvm::raw_string_ostream OS(Name); Function->getNameForDiagnostic(OS, getPrintingPolicy(), /*Qualified=*/true); - if (llvm::isTimeTraceVerbose()) { - auto Loc = SourceMgr.getExpansionLoc(Function->getLocation()); - M.File = SourceMgr.getFilename(Loc); - M.Line = SourceMgr.getExpansionLineNumber(Loc); - } - return M; + return Name; }); // If we're performing recursive template instantiation, create our own diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index c1361efd8c5f25..a7fe20bd0a4669 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -785,22 +785,29 @@ void ASTStmtReader::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { E->setRParenLoc(readSourceLocation()); } +static StringRef saveStrToCtx(const std::string &S, ASTContext &Ctx) { + char *Buf = new (Ctx) char[S.size()]; + std::copy(S.begin(), S.end(), Buf); + return StringRef(Buf, S.size()); +} + static ConstraintSatisfaction readConstraintSatisfaction(ASTRecordReader &Record) { ConstraintSatisfaction Satisfaction; Satisfaction.IsSatisfied = Record.readInt(); Satisfaction.ContainsErrors = Record.readInt(); - const ASTContext &C = Record.getContext(); if (!Satisfaction.IsSatisfied) { unsigned NumDetailRecords = Record.readInt(); for (unsigned i = 0; i != NumDetailRecords; ++i) { if (/* IsDiagnostic */Record.readInt()) { SourceLocation DiagLocation = Record.readSourceLocation(); - StringRef DiagMessage = C.backupStr(Record.readString()); + StringRef DiagMessage = + saveStrToCtx(Record.readString(), Record.getContext()); Satisfaction.Details.emplace_back( - new (C) ConstraintSatisfaction::SubstitutionDiagnostic( - DiagLocation, DiagMessage)); + new (Record.getContext()) + ConstraintSatisfaction::SubstitutionDiagnostic(DiagLocation, + DiagMessage)); } else Satisfaction.Details.emplace_back(Record.readExpr()); } @@ -821,10 +828,12 @@ void ASTStmtReader::VisitConceptSpecializationExpr( static concepts::Requirement::SubstitutionDiagnostic * readSubstitutionDiagnostic(ASTRecordReader &Record) { - const ASTContext &C = Record.getContext(); - StringRef SubstitutedEntity = C.backupStr(Record.readString()); + StringRef SubstitutedEntity = + saveStrToCtx(Record.readString(), Record.getContext()); + SourceLocation DiagLoc = Record.readSourceLocation(); - StringRef DiagMessage = C.backupStr(Record.readString()); + StringRef DiagMessage = + saveStrToCtx(Record.readString(), Record.getContext()); return new (Record.getContext()) concepts::Requirement::SubstitutionDiagnostic{SubstitutedEntity, DiagLoc, @@ -910,21 +919,22 @@ void ASTStmtReader::VisitRequiresExpr(RequiresExpr *E) { std::move(*Req)); } break; case concepts::Requirement::RK_Nested: { - ASTContext &C = Record.getContext(); bool HasInvalidConstraint = Record.readInt(); if (HasInvalidConstraint) { - StringRef InvalidConstraint = C.backupStr(Record.readString()); - R = new (C) concepts::NestedRequirement( + StringRef InvalidConstraint = + saveStrToCtx(Record.readString(), Record.getContext()); + R = new (Record.getContext()) concepts::NestedRequirement( Record.getContext(), InvalidConstraint, readConstraintSatisfaction(Record)); break; } Expr *E = Record.readExpr(); if (E->isInstantiationDependent()) - R = new (C) concepts::NestedRequirement(E); + R = new (Record.getContext()) concepts::NestedRequirement(E); else - R = new (C) concepts::NestedRequirement( - C, E, readConstraintSatisfaction(Record)); + R = new (Record.getContext()) + concepts::NestedRequirement(Record.getContext(), E, + readConstraintSatisfaction(Record)); } break; } if (!R) diff --git a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp index 3f837564cf47c4..f82288f1099e88 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp @@ -373,14 +373,14 @@ static std::optional getConcreteValue(std::optional SV) { } static Messages getPrecedesMsgs(const SubRegion *Region, NonLoc Offset) { - std::string RegName = getRegionName(Region), OffsetStr = ""; - - if (auto ConcreteOffset = getConcreteValue(Offset)) - OffsetStr = formatv(" {0}", ConcreteOffset); - - return { - formatv("Out of bound access to memory preceding {0}", RegName), - formatv("Access of {0} at negative byte offset{1}", RegName, OffsetStr)}; + std::string RegName = getRegionName(Region); + SmallString<128> Buf; + llvm::raw_svector_ostream Out(Buf); + Out << "Access of " << RegName << " at negative byte offset"; + if (auto ConcreteIdx = Offset.getAs()) + Out << ' ' << ConcreteIdx->getValue(); + return {formatv("Out of bound access to memory preceding {0}", RegName), + std::string(Buf)}; } /// Try to divide `Val1` and `Val2` (in place) by `Divisor` and return true if @@ -609,7 +609,7 @@ void ArrayBoundCheckerV2::performCheck(const Expr *E, CheckerContext &C) const { // CHECK UPPER BOUND DefinedOrUnknownSVal Size = getDynamicExtent(State, Reg, SVB); if (auto KnownSize = Size.getAs()) { - // In a situation where both underflow and overflow are possible (but the + // In a situation where both overflow and overflow are possible (but the // index is either tainted or known to be invalid), the logic of this // checker will first assume that the offset is non-negative, and then // (with this additional assumption) it will detect an overflow error. diff --git a/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp index b198b1c2ff4d11..1a75d7b52ad6e9 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp @@ -18,7 +18,6 @@ #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h" @@ -31,40 +30,8 @@ namespace { class BuiltinFunctionChecker : public Checker { public: bool evalCall(const CallEvent &Call, CheckerContext &C) const; - -private: - // From: clang/include/clang/Basic/Builtins.def - // C++ standard library builtins in namespace 'std'. - const CallDescriptionSet BuiltinLikeStdFunctions{ - {CDM::SimpleFunc, {"std", "addressof"}}, // - {CDM::SimpleFunc, {"std", "__addressof"}}, // - {CDM::SimpleFunc, {"std", "as_const"}}, // - {CDM::SimpleFunc, {"std", "forward"}}, // - {CDM::SimpleFunc, {"std", "forward_like"}}, // - {CDM::SimpleFunc, {"std", "move"}}, // - {CDM::SimpleFunc, {"std", "move_if_noexcept"}}, // - }; - - bool isBuiltinLikeFunction(const CallEvent &Call) const; }; -} // namespace - -bool BuiltinFunctionChecker::isBuiltinLikeFunction( - const CallEvent &Call) const { - const auto *FD = llvm::dyn_cast_or_null(Call.getDecl()); - if (!FD || FD->getNumParams() != 1) - return false; - - if (QualType RetTy = FD->getReturnType(); - !RetTy->isPointerType() && !RetTy->isReferenceType()) - return false; - - if (QualType ParmTy = FD->getParamDecl(0)->getType(); - !ParmTy->isPointerType() && !ParmTy->isReferenceType()) - return false; - - return BuiltinLikeStdFunctions.contains(Call); } bool BuiltinFunctionChecker::evalCall(const CallEvent &Call, @@ -77,11 +44,6 @@ bool BuiltinFunctionChecker::evalCall(const CallEvent &Call, const LocationContext *LCtx = C.getLocationContext(); const Expr *CE = Call.getOriginExpr(); - if (isBuiltinLikeFunction(Call)) { - C.addTransition(state->BindExpr(CE, LCtx, Call.getArgSVal(0))); - return true; - } - switch (FD->getBuiltinID()) { default: return false; diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp index 53770532609d5a..e8d538388e56ce 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -254,8 +254,7 @@ inline void assertStreamStateOpened(const StreamState *SS) { } class StreamChecker : public Checker> { + check::DeadSymbols, check::PointerEscape> { BugType BT_FileNull{this, "NULL stream pointer", "Stream handling error"}; BugType BT_UseAfterClose{this, "Closed stream", "Stream handling error"}; BugType BT_UseAfterOpenFailed{this, "Invalid stream", @@ -277,21 +276,11 @@ class StreamChecker : public Checker ProgramStateRef { - if (!Var) - return State; - const auto *LCtx = C.getLocationContext(); - auto &StoreMgr = C.getStoreManager(); - auto &SVB = C.getSValBuilder(); - SVal VarValue = State->getSVal(StoreMgr.getLValueVar(Var, LCtx)); - auto NoAliasState = - SVB.evalBinOp(State, BO_NE, RetVal, VarValue, SVB.getConditionType()) - .castAs(); - return State->assume(NoAliasState, true); - }; - - assert(State); - State = assumeRetNE(State, StdinDecl); - State = assumeRetNE(State, StdoutDecl); - State = assumeRetNE(State, StderrDecl); - assert(State); - return State; -} - void StreamChecker::evalFopen(const FnDescription *Desc, const CallEvent &Call, CheckerContext &C) const { ProgramStateRef State = C.getState(); @@ -938,7 +899,6 @@ void StreamChecker::evalFopen(const FnDescription *Desc, const CallEvent &Call, assert(RetSym && "RetVal must be a symbol here."); State = State->BindExpr(CE, C.getLocationContext(), RetVal); - State = assumeNoAliasingWithStdStreams(State, RetVal, C); // Bifurcate the state into two: one with a valid FILE* pointer, the other // with a NULL. @@ -2057,36 +2017,6 @@ ProgramStateRef StreamChecker::checkPointerEscape( return State; } -static const VarDecl * -getGlobalStreamPointerByName(const TranslationUnitDecl *TU, StringRef VarName) { - ASTContext &Ctx = TU->getASTContext(); - const auto &SM = Ctx.getSourceManager(); - const QualType FileTy = Ctx.getFILEType(); - - if (FileTy.isNull()) - return nullptr; - - const QualType FilePtrTy = Ctx.getPointerType(FileTy).getCanonicalType(); - - auto LookupRes = TU->lookup(&Ctx.Idents.get(VarName)); - for (const Decl *D : LookupRes) { - if (auto *VD = dyn_cast_or_null(D)) { - if (SM.isInSystemHeader(VD->getLocation()) && VD->hasExternalStorage() && - VD->getType().getCanonicalType() == FilePtrTy) { - return VD; - } - } - } - return nullptr; -} - -void StreamChecker::checkASTDecl(const TranslationUnitDecl *TU, - AnalysisManager &, BugReporter &) const { - StdinDecl = getGlobalStreamPointerByName(TU, "stdin"); - StdoutDecl = getGlobalStreamPointerByName(TU, "stdout"); - StderrDecl = getGlobalStreamPointerByName(TU, "stderr"); -} - //===----------------------------------------------------------------------===// // Checker registration. //===----------------------------------------------------------------------===// diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp index d73dc40cf03fbb..e2002bfbe594a9 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -2198,7 +2198,7 @@ const Decl *PathSensitiveBugReport::getDeclWithIssue() const { void BasicBugReport::Profile(llvm::FoldingSetNodeID& hash) const { hash.AddInteger(static_cast(getKind())); hash.AddPointer(&BT); - hash.AddString(getShortDescription()); + hash.AddString(Description); assert(Location.isValid()); Location.Profile(hash); @@ -2213,7 +2213,7 @@ void BasicBugReport::Profile(llvm::FoldingSetNodeID& hash) const { void PathSensitiveBugReport::Profile(llvm::FoldingSetNodeID &hash) const { hash.AddInteger(static_cast(getKind())); hash.AddPointer(&BT); - hash.AddString(getShortDescription()); + hash.AddString(Description); PathDiagnosticLocation UL = getUniqueingLocation(); if (UL.isValid()) { UL.Profile(hash); diff --git a/clang/test/APINotes/Inputs/Headers/Methods.apinotes b/clang/test/APINotes/Inputs/Headers/Methods.apinotes index 618c2cb14b47f4..0fa6991a51ff4c 100644 --- a/clang/test/APINotes/Inputs/Headers/Methods.apinotes +++ b/clang/test/APINotes/Inputs/Headers/Methods.apinotes @@ -6,27 +6,3 @@ Tags: - Name: getIncremented Availability: none AvailabilityMsg: "oh no" - - Name: getDecremented - Availability: none - AvailabilityMsg: "this should have no effect" -- Name: Outer - Tags: - - Name: Inner - Methods: - - Name: getDecremented - Availability: none - AvailabilityMsg: "nope" - - Name: getIncremented - Availability: none - AvailabilityMsg: "this should have no effect" - Methods: - - Name: getDecremented - Availability: none - AvailabilityMsg: "this should have no effect" -Functions: -- Name: getIncremented - Availability: none - AvailabilityMsg: "this should have no effect" -- Name: getDecremented - Availability: none - AvailabilityMsg: "this should have no effect" diff --git a/clang/test/APINotes/Inputs/Headers/Methods.h b/clang/test/APINotes/Inputs/Headers/Methods.h index 6a96b127628711..f46fe31533e5d6 100644 --- a/clang/test/APINotes/Inputs/Headers/Methods.h +++ b/clang/test/APINotes/Inputs/Headers/Methods.h @@ -4,6 +4,7 @@ struct IntWrapper { IntWrapper getIncremented() const { return {value + 1}; } }; +// TODO: support nested tags struct Outer { struct Inner { int value; diff --git a/clang/test/APINotes/Inputs/Headers/Namespaces.apinotes b/clang/test/APINotes/Inputs/Headers/Namespaces.apinotes index b7d962e0efda66..68073932d600eb 100644 --- a/clang/test/APINotes/Inputs/Headers/Namespaces.apinotes +++ b/clang/test/APINotes/Inputs/Headers/Namespaces.apinotes @@ -41,9 +41,6 @@ Namespaces: Methods: - Name: methodInNestedNamespace SwiftName: swiftMethodInNestedNamespace() - Tags: - - Name: inner_char_box - SwiftName: InnerCharBox Namespaces: - Name: Namespace1 Tags: diff --git a/clang/test/APINotes/Inputs/Headers/Namespaces.h b/clang/test/APINotes/Inputs/Headers/Namespaces.h index c7a891f205c06f..e996b8ffa6b6e1 100644 --- a/clang/test/APINotes/Inputs/Headers/Namespaces.h +++ b/clang/test/APINotes/Inputs/Headers/Namespaces.h @@ -10,9 +10,6 @@ void funcInNestedNamespace(int i); struct char_box { char c; void methodInNestedNamespace(); - struct inner_char_box { - char c; - }; }; } diff --git a/clang/test/APINotes/methods.cpp b/clang/test/APINotes/methods.cpp index 910565745bea24..692f750ed66c75 100644 --- a/clang/test/APINotes/methods.cpp +++ b/clang/test/APINotes/methods.cpp @@ -1,17 +1,9 @@ // RUN: rm -rf %t && mkdir -p %t // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Methods -fdisable-module-hash -fapinotes-modules -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -x c++ // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Methods -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter IntWrapper::getIncremented -x c++ | FileCheck --check-prefix=CHECK-METHOD %s -// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Methods -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Outer::Inner::getDecremented -x c++ | FileCheck --check-prefix=CHECK-DEEP-METHOD %s #include "Methods.h" // CHECK-METHOD: Dumping IntWrapper::getIncremented: // CHECK-METHOD-NEXT: CXXMethodDecl {{.+}} getIncremented // CHECK-METHOD: UnavailableAttr {{.+}} <> "oh no" - -// CHECK-DEEP-METHOD: Dumping Outer::Inner::getDecremented: -// CHECK-DEEP-METHOD-NEXT: CXXMethodDecl {{.+}} getDecremented -// CHECK-DEEP-METHOD: UnavailableAttr {{.+}} <> "nope" - -// CHECK-METHOD-NOT: this should have no effect -// CHECK-DEEP-METHOD-NOT: this should have no effect diff --git a/clang/test/APINotes/namespaces.cpp b/clang/test/APINotes/namespaces.cpp index df108b02e63011..a6517a324b9c53 100644 --- a/clang/test/APINotes/namespaces.cpp +++ b/clang/test/APINotes/namespaces.cpp @@ -8,7 +8,6 @@ // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested1::varInNestedNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-GLOBAL-IN-NESTED-NAMESPACE %s // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested2::varInNestedNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-ANOTHER-GLOBAL-IN-NESTED-NAMESPACE %s // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested1::char_box -x objective-c++ | FileCheck -check-prefix=CHECK-STRUCT-IN-NESTED-NAMESPACE %s -// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested1::char_box::inner_char_box -x objective-c++ | FileCheck -check-prefix=CHECK-STRUCT-IN-STRUCT-IN-NESTED-NAMESPACE %s // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested1::funcInNestedNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-FUNC-IN-NESTED-NAMESPACE %s // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested1::char_box::methodInNestedNamespace -x objective-c++ | FileCheck -check-prefix=CHECK-METHOD-IN-NESTED-NAMESPACE %s // RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/CxxInterop -fdisable-module-hash -fapinotes-modules -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s -ast-dump -ast-dump-filter Namespace1::Nested1::Namespace1::char_box -x objective-c++ | FileCheck -check-prefix=CHECK-STRUCT-IN-DEEP-NESTED-NAMESPACE %s @@ -57,10 +56,6 @@ // CHECK-STRUCT-IN-NESTED-NAMESPACE-NEXT: CXXRecordDecl {{.+}} imported in Namespaces struct char_box // CHECK-STRUCT-IN-NESTED-NAMESPACE: SwiftNameAttr {{.+}} <> "NestedCharBox" -// CHECK-STRUCT-IN-STRUCT-IN-NESTED-NAMESPACE: Dumping Namespace1::Nested1::char_box::inner_char_box: -// CHECK-STRUCT-IN-STRUCT-IN-NESTED-NAMESPACE-NEXT: CXXRecordDecl {{.+}} imported in Namespaces struct inner_char_box -// CHECK-STRUCT-IN-STRUCT-IN-NESTED-NAMESPACE: SwiftNameAttr {{.+}} <> "InnerCharBox" - // CHECK-METHOD-IN-NESTED-NAMESPACE: Dumping Namespace1::Nested1::char_box::methodInNestedNamespace: // CHECK-METHOD-IN-NESTED-NAMESPACE-NEXT: CXXMethodDecl {{.+}} imported in Namespaces methodInNestedNamespace // CHECK-METHOD-IN-NESTED-NAMESPACE: SwiftNameAttr {{.+}} <> "swiftMethodInNestedNamespace()" diff --git a/clang/test/AST/Interp/atomic.c b/clang/test/AST/Interp/atomic.c index c8469d4a938b88..c5fd9ab2229341 100644 --- a/clang/test/AST/Interp/atomic.c +++ b/clang/test/AST/Interp/atomic.c @@ -58,16 +58,3 @@ _Static_assert(atomic_is_lock_free((atomic_short*)0), ""); _Static_assert(atomic_is_lock_free((atomic_int*)0), ""); _Static_assert(atomic_is_lock_free((atomic_long*)0), ""); _Static_assert(atomic_is_lock_free(0 + (atomic_char*)0), ""); - -_Static_assert(__atomic_always_lock_free(1, (void*)1), ""); -_Static_assert(__atomic_always_lock_free(1, (void*)-1), ""); -_Static_assert(!__atomic_always_lock_free(4, (void*)2), ""); -_Static_assert(!__atomic_always_lock_free(4, (void*)-2), ""); -_Static_assert(__atomic_always_lock_free(4, (void*)4), ""); -_Static_assert(__atomic_always_lock_free(4, (void*)-4), ""); - -_Static_assert(__atomic_always_lock_free(1, "string"), ""); -_Static_assert(!__atomic_always_lock_free(2, "string"), ""); -_Static_assert(__atomic_always_lock_free(2, (int[2]){}), ""); -void dummyfn(); -_Static_assert(__atomic_always_lock_free(2, dummyfn) || 1, ""); diff --git a/clang/test/AST/Interp/codegen.cpp b/clang/test/AST/Interp/codegen.cpp index a5583d953d234f..8a0d070d19da33 100644 --- a/clang/test/AST/Interp/codegen.cpp +++ b/clang/test/AST/Interp/codegen.cpp @@ -18,16 +18,3 @@ struct S { S s; // CHECK: @sp = constant ptr getelementptr (i8, ptr @s, i64 16), align 8 float &sp = s.c[3]; - - -namespace BaseClassOffsets { - struct A { int a; }; - struct B { int b; }; - struct C : A, B { int c; }; - - extern C c; - // CHECK: @_ZN16BaseClassOffsets1aE = global ptr @_ZN16BaseClassOffsets1cE, align 8 - A* a = &c; - // CHECK: @_ZN16BaseClassOffsets1bE = global ptr getelementptr (i8, ptr @_ZN16BaseClassOffsets1cE, i64 4), align 8 - B* b = &c; -} diff --git a/clang/test/AST/ast-dump-ctad-alias.cpp b/clang/test/AST/ast-dump-ctad-alias.cpp index b1631f7822ce01..a088c0a7b02729 100644 --- a/clang/test/AST/ast-dump-ctad-alias.cpp +++ b/clang/test/AST/ast-dump-ctad-alias.cpp @@ -32,24 +32,22 @@ Out2::AInner t(1.0); // CHECK-NEXT: | | |-UnresolvedLookupExpr {{.*}} '' lvalue (no ADL) = 'Concept' // CHECK-NEXT: | | | |-TemplateArgument type 'int' // CHECK-NEXT: | | | | `-BuiltinType {{.*}} 'int' -// CHECK-NEXT: | | | `-TemplateArgument type 'Y':'type-parameter-1-0' -// CHECK-NEXT: | | | `-TemplateTypeParmType {{.*}} 'Y' dependent depth 1 index 0 -// CHECK-NEXT: | | | `-TemplateTypeParm {{.*}} 'Y' +// CHECK-NEXT: | | | `-TemplateArgument type 'type-parameter-1-0' +// CHECK-NEXT: | | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent depth 1 index 0 // CHECK-NEXT: | | `-TypeTraitExpr {{.*}} 'bool' __is_deducible // CHECK-NEXT: | | |-DeducedTemplateSpecializationType {{.*}} 'Out2::AInner' dependent // CHECK-NEXT: | | | `-name: 'Out2::AInner' // CHECK-NEXT: | | | `-TypeAliasTemplateDecl {{.+}} AInner{{$}} -// CHECK-NEXT: | | `-ElaboratedType {{.*}} 'Inner' sugar dependent -// CHECK-NEXT: | | `-TemplateSpecializationType {{.*}} 'Inner' dependent +// CHECK-NEXT: | | `-ElaboratedType {{.*}} 'Inner' sugar dependent +// CHECK-NEXT: | | `-TemplateSpecializationType {{.*}} 'Inner' dependent // CHECK-NEXT: | | |-name: 'Inner':'Out::Inner' qualified // CHECK-NEXT: | | | `-ClassTemplateDecl {{.+}} Inner{{$}} -// CHECK-NEXT: | | `-TemplateArgument type 'Y' -// CHECK-NEXT: | | `-SubstTemplateTypeParmType {{.*}} 'Y' +// CHECK-NEXT: | | `-TemplateArgument type 'type-parameter-1-0' +// CHECK-NEXT: | | `-SubstTemplateTypeParmType {{.*}} 'type-parameter-1-0' // CHECK-NEXT: | | |-FunctionTemplate {{.*}} '' -// CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'Y' dependent depth 1 index 0 -// CHECK-NEXT: | | `-TemplateTypeParm {{.*}} 'Y' -// CHECK-NEXT: | |-CXXDeductionGuideDecl {{.*}} 'auto (Y) -> Inner' -// CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'Y' +// CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'type-parameter-1-0' dependent depth 1 index 0 +// CHECK-NEXT: | |-CXXDeductionGuideDecl {{.*}} 'auto (type-parameter-0-0) -> Inner' +// CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'type-parameter-0-0' // CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} used 'auto (double) -> Inner' implicit_instantiation // CHECK-NEXT: | |-TemplateArgument type 'double' // CHECK-NEXT: | | `-BuiltinType {{.*}} 'double' @@ -79,8 +77,8 @@ AFoo3 afoo3{0, 1}; // CHECK-NEXT: | |-UnresolvedLookupExpr {{.*}} '' lvalue (no ADL) = 'Concept' // CHECK-NEXT: | | |-TemplateArgument type 'int' // CHECK-NEXT: | | | `-BuiltinType {{.*}} 'int' -// CHECK-NEXT: | | `-TemplateArgument type 'V' -// CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'V' dependent depth 0 index 1 +// CHECK-NEXT: | | `-TemplateArgument type 'type-parameter-0-1' +// CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'type-parameter-0-1' dependent depth 0 index 1 template struct Foo { @@ -90,16 +88,16 @@ struct Foo { template using AFoo = Foo; AFoo a(1, 2); -// CHECK: |-CXXDeductionGuideDecl {{.*}} implicit 'auto (T2...) -> Foo' -// CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'T2...' pack +// CHECK: |-CXXDeductionGuideDecl {{.*}} implicit 'auto (type-parameter-0-0...) -> Foo' +// CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'type-parameter-0-0...' pack // CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} implicit used 'auto (int, int) -> Foo' implicit_instantiation template using BFoo = Foo; BFoo b2(1.0, 2.0); -// CHECK: |-CXXDeductionGuideDecl {{.*}} implicit 'auto (T, T) -> Foo' -// CHECK-NEXT: | | |-ParmVarDecl {{.*}} 'T' -// CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'T' +// CHECK: |-CXXDeductionGuideDecl {{.*}} implicit 'auto (type-parameter-0-0, type-parameter-0-0) -> Foo' +// CHECK-NEXT: | | |-ParmVarDecl {{.*}} 'type-parameter-0-0' +// CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'type-parameter-0-0' // CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} implicit used 'auto (double, double) -> Foo' implicit_instantiation namespace GH90209 { diff --git a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h index a379a475156685..29326ec1f9280d 100644 --- a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h +++ b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h @@ -263,13 +263,11 @@ namespace std { template< class T > struct remove_reference {typedef T type;}; template< class T > struct remove_reference {typedef T type;}; - template typename remove_reference::type&& move(T&& a); - template T *__addressof(T &x); - template T *addressof(T &x); - template const T& as_const(T& x); - template T&& forward(T&& x); - // FIXME: Declare forward_like - // FIXME: Declare move_if_noexcept + template + typename remove_reference::type&& move(T&& a) { + typedef typename remove_reference::type&& RvalRef; + return static_cast(a); + } template< class T > using remove_reference_t = typename remove_reference::type; @@ -756,7 +754,7 @@ namespace std { template OutputIter __copy(InputIter II, InputIter IE, OutputIter OI) { while (II != IE) - *OI++ = *II++; // #system_header_simulator_cxx_std_copy_impl_loop + *OI++ = *II++; return OI; } diff --git a/clang/test/Analysis/builtin-functions.cpp b/clang/test/Analysis/builtin-functions.cpp index f7bafabd23cbcc..8719193e405c4c 100644 --- a/clang/test/Analysis/builtin-functions.cpp +++ b/clang/test/Analysis/builtin-functions.cpp @@ -1,16 +1,6 @@ // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10 -analyzer-checker=core,debug.ExprInspection %s -std=c++11 -verify // RUN: %clang_analyze_cc1 -triple x86_64-pc-windows-msvc19.11.0 -fms-extensions -analyzer-checker=core,debug.ExprInspection %s -std=c++11 -verify -#include "Inputs/system-header-simulator-cxx.h" - -namespace std { -// Intentionally not using an "auto" return type here, as such must also have a definition. -template constexpr int&& forward_like(U&& x) noexcept; -template const T& move_if_noexcept(T& x) noexcept; -} // namespace std - -template void clang_analyzer_dump_ref(T&&); -template void clang_analyzer_dump_ptr(T*); void clang_analyzer_eval(bool); void clang_analyzer_warnIfReached(); @@ -18,16 +8,6 @@ void testAddressof(int x) { clang_analyzer_eval(&x == __builtin_addressof(x)); // expected-warning{{TRUE}} } -void testStdBuiltinLikeFunctions(int x) { - clang_analyzer_dump_ptr(std::addressof(x)); // expected-warning{{&x}} - clang_analyzer_dump_ptr(std::__addressof(x)); // expected-warning{{&x}} - clang_analyzer_dump_ref(std::as_const(x)); // expected-warning{{&x}} - clang_analyzer_dump_ref(std::forward(x)); // expected-warning{{&x}} - clang_analyzer_dump_ref(std::forward_like(x)); // expected-warning{{&x}} - clang_analyzer_dump_ref(std::move(x)); // expected-warning{{&x}} - clang_analyzer_dump_ref(std::move_if_noexcept(x)); // expected-warning{{&x}} -} - void testSize() { struct { int x; diff --git a/clang/test/Analysis/diagnostics/explicit-suppression.cpp b/clang/test/Analysis/diagnostics/explicit-suppression.cpp index 3a904dac1c0fe8..24586e37fe207a 100644 --- a/clang/test/Analysis/diagnostics/explicit-suppression.cpp +++ b/clang/test/Analysis/diagnostics/explicit-suppression.cpp @@ -19,6 +19,6 @@ class C { void testCopyNull(C *I, C *E) { std::copy(I, E, (C *)0); #ifndef SUPPRESSED - // expected-warning@#system_header_simulator_cxx_std_copy_impl_loop {{Called C++ object pointer is null}} + // expected-warning@../Inputs/system-header-simulator-cxx.h:757 {{Called C++ object pointer is null}} #endif } diff --git a/clang/test/Analysis/issue-94193.cpp b/clang/test/Analysis/issue-94193.cpp deleted file mode 100644 index 97acfdd8685bea..00000000000000 --- a/clang/test/Analysis/issue-94193.cpp +++ /dev/null @@ -1,41 +0,0 @@ -// RUN: %clang_analyze_cc1 %s -verify -analyzer-checker=core - -#include "Inputs/system-header-simulator-cxx.h" - - -namespace GH94193 { -template class optional { - union { - char x; - T uvalue; - }; - bool holds_value = false; -public: - optional() = default; - optional(const optional&) = delete; - optional(optional&&) = delete; - template explicit optional(U&& value) : holds_value(true) { - new (static_cast(std::addressof(uvalue))) T(std::forward(value)); - } - optional& operator=(const optional&) = delete; - optional& operator=(optional&&) = delete; - explicit operator bool() const { - return holds_value; - } - T& unwrap() & { - return uvalue; // no-warning: returns a valid value - } -}; - -int top1(int x) { - optional opt{x}; // note: Ctor was inlined. - return opt.unwrap(); // no-warning: returns a valid value -} - -std::string *top2() { - std::string a = "123"; - // expected-warning@+2 {{address of stack memory associated with local variable 'a' returned}} diagnosed by -Wreturn-stack-address - // expected-warning@+1 {{Address of stack memory associated with local variable 'a' returned to caller [core.StackAddressEscape]}} - return std::addressof(a); -} -} // namespace GH94193 diff --git a/clang/test/Analysis/out-of-bounds-diagnostics.c b/clang/test/Analysis/out-of-bounds-diagnostics.c index de70e483add1c0..92f983d8b15612 100644 --- a/clang/test/Analysis/out-of-bounds-diagnostics.c +++ b/clang/test/Analysis/out-of-bounds-diagnostics.c @@ -17,27 +17,6 @@ int underflowWithDeref(void) { // expected-note@-2 {{Access of 'TenElements' at negative byte offset -4}} } -int rng(void); -int getIndex(void) { - switch (rng()) { - case 1: return -152; - case 2: return -160; - case 3: return -168; - default: return -172; - } -} - -void gh86959(void) { - // Previously code like this produced many almost-identical bug reports that - // only differed in the offset value. Verify that now we only see one report. - - // expected-note@+1 {{Entering loop body}} - while (rng()) - TenElements[getIndex()] = 10; - // expected-warning@-1 {{Out of bound access to memory preceding 'TenElements'}} - // expected-note@-2 {{Access of 'TenElements' at negative byte offset -688}} -} - int scanf(const char *restrict fmt, ...); void taintedIndex(void) { diff --git a/clang/test/Analysis/stream.c b/clang/test/Analysis/stream.c index b3a47ce4153d36..c924cbd36f7599 100644 --- a/clang/test/Analysis/stream.c +++ b/clang/test/Analysis/stream.c @@ -498,15 +498,3 @@ void gh_93408_regression_ZeroSized(struct ZeroSized *buffer) { fread(buffer, 1, 1, f); // expected-warning {{Stream pointer might be NULL}} no-crash fclose(f); } - -extern FILE *stdout_like_ptr; -void no_aliasing(void) { - FILE *f = fopen("file", "r"); - clang_analyzer_eval(f == stdin); // expected-warning {{FALSE}} no-TRUE - clang_analyzer_eval(f == stdout); // expected-warning {{FALSE}} no-TRUE - clang_analyzer_eval(f == stderr); // expected-warning {{FALSE}} no-TRUE - clang_analyzer_eval(f == stdout_like_ptr); // expected-warning {{FALSE}} expected-warning {{TRUE}} - if (f && f != stdout) { - fclose(f); - } -} // no-leak: 'fclose()' is always called because 'f' cannot be 'stdout'. diff --git a/clang/test/Analysis/use-after-move.cpp b/clang/test/Analysis/use-after-move.cpp index 24d5dd8a8b3d27..33980e6ea2b8b9 100644 --- a/clang/test/Analysis/use-after-move.cpp +++ b/clang/test/Analysis/use-after-move.cpp @@ -570,8 +570,13 @@ void differentBranchesTest(int i) { { A a; a.foo() > 0 ? a.foo() : A(std::move(a)).foo(); - // peaceful-note@-1 {{Assuming the condition is true}} - // peaceful-note@-2 {{'?' condition is true}} +#ifdef DFS + // peaceful-note@-2 {{Assuming the condition is false}} + // peaceful-note@-3 {{'?' condition is false}} +#else + // peaceful-note@-5 {{Assuming the condition is true}} + // peaceful-note@-6 {{'?' condition is true}} +#endif } // Same thing, but with a switch statement. { diff --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt index 299a35723b59d5..8303269a9ad074 100644 --- a/clang/test/CMakeLists.txt +++ b/clang/test/CMakeLists.txt @@ -78,7 +78,6 @@ list(APPEND CLANG_TEST_DEPS clang-installapi clang-scan-deps clang-linker-wrapper - clang-nvlink-wrapper clang-offload-bundler clang-offload-packager diagtool diff --git a/clang/test/CXX/cpp/cpp.module/p2.cppm b/clang/test/CXX/cpp/cpp.module/p2.cppm new file mode 100644 index 00000000000000..966a88ccfa972d --- /dev/null +++ b/clang/test/CXX/cpp/cpp.module/p2.cppm @@ -0,0 +1,88 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -std=c++20 %t/A.cppm -triple x86_64-linux-gnu -verify +// RUN: %clang_cc1 -std=c++20 %t/B.cppm -triple x86_64-linux-gnu -verify +// RUN: %clang_cc1 -std=c++20 %t/C.cppm -triple x86_64-linux-gnu -verify +// RUN: %clang_cc1 -std=c++20 %t/D.cppm -triple x86_64-linux-gnu -verify +// RUN: %clang_cc1 -std=c++20 %t/E.cppm -triple x86_64-linux-gnu -verify +// RUN: %clang_cc1 -std=c++20 %t/F.cppm -triple x86_64-linux-gnu -verify +// RUN: %clang_cc1 -std=c++20 %t/G.cppm -triple x86_64-linux-gnu -verify +// RUN: %clang_cc1 -std=c++20 %t/H.cppm -triple x86_64-linux-gnu -verify +// RUN: %clang_cc1 -std=c++20 %t/I.cppm -triple x86_64-linux-gnu -verify +// RUN: %clang_cc1 -std=c++20 %t/J.cppm -triple x86_64-linux-gnu -verify + +//--- version.h +#ifndef VERSION_H +#define VERSION_H + +#define VERSION libv5 +#define A a +#define B b +#define C c +#define FUNC_LIKE(X) function_like_##X +#define ATTRS [[]] +#define SEMICOLON ; + +#endif // VERSION_H + +//--- A.cppm +module; +#include "version.h" +export module VERSION; // expected-error {{the module name in a module declaration cannot contain an object-like macro 'VERSION'}} + +//--- B.cppm +module; +#include "version.h" +export module A.B; // expected-error {{the module name in a module declaration cannot contain an object-like macro 'A'}} \ + // expected-error {{the module name in a module declaration cannot contain an object-like macro 'B'}} + +//--- C.cppm +module; // expected-error {{missing 'module' declaration at end of global module fragment introduced here}} +#include "version.h" +export module A.FUNC_LIKE(foo):C; // expected-error {{the module name in a module declaration cannot contain an object-like macro 'A'}} \ + // expected-error {{unexpected '(' after the module name in a module declaration}} + +//--- D.cppm +module; // expected-error {{missing 'module' declaration at end of global module fragment introduced here}} +#include "version.h" +export module B.A.FUNC_LIKE(bar):C; // expected-error {{the module name in a module declaration cannot contain an object-like macro 'B'}} \ + // expected-error {{the module name in a module declaration cannot contain an object-like macro 'A'}} \ + // expected-error {{unexpected '(' after the module name in a module declaration}} + +//--- E.cppm +module; +#include "version.h" +export module a.FUNC_LIKE:c; // OK, FUNC_LIKE would not be treated as a macro name. +// expected-no-diagnostics + +//--- F.cppm +module; +#include "version.h" +export module a.FUNC_LIKE:c ATTRS; // OK, FUNC_LIKE would not be treated as a macro name. +// expected-no-diagnostics + +//--- G.cppm +module; // expected-error {{missing 'module' declaration at end of global module fragment introduced here}} +#include "version.h" +export module A.FUNC_LIKE(B c:C ATTRS // expected-error {{the module name in a module declaration cannot contain an object-like macro 'A'}} \ + // expected-error {{unexpected '(' after the module name in a module declaration}} + +//--- H.cppm +module; // expected-error {{missing 'module' declaration at end of global module fragment introduced here}} +#include "version.h" +export module A.FUNC_LIKE(B,). c:C ATTRS // expected-error {{the module name in a module declaration cannot contain an object-like macro 'A'}} \ + // expected-error {{unexpected '(' after the module name in a module declaration}} + +//--- I.cppm +module; // expected-error {{missing 'module' declaration at end of global module fragment introduced here}} +#include "version.h" +export module A.FUNC_LIKE(B,) c:C ATTRS // expected-error {{the module name in a module declaration cannot contain an object-like macro 'A'}} \ + // expected-error {{unexpected '(' after the module name in a module declaration}} + +//--- J.cppm +module; +#include "version.h" +export module unexpanded : unexpanded ATTRS SEMICOLON // OK, ATTRS and SEMICOLON can be expanded. +// expected-no-diagnostics diff --git a/clang/test/CXX/drs/cwg6xx.cpp b/clang/test/CXX/drs/cwg6xx.cpp index 1c56dd3907152e..069102d9c59750 100644 --- a/clang/test/CXX/drs/cwg6xx.cpp +++ b/clang/test/CXX/drs/cwg6xx.cpp @@ -1265,7 +1265,7 @@ namespace cwg687 { // cwg687 (9 c++20, but the issue is still considered open) // This is not. template g(a); - // expected-error@-1 {{expected '<' after 'template'}} + // expected-error@-1 {{expected expression}} } } diff --git a/clang/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp b/clang/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp index 170ca0a3f1c6b0..162d59439d08ee 100644 --- a/clang/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp +++ b/clang/test/CXX/expr/expr.unary/expr.unary.op/p4.cpp @@ -43,36 +43,18 @@ namespace test2 { } namespace GH40906 { -struct S { - int x; - void func(); - static_assert(__is_same_as(decltype((S::x)), int&), ""); - static_assert(__is_same_as(decltype(&(S::x)), int*), ""); - - // FIXME: provide better error messages - static_assert(__is_same_as(decltype((S::func)), int&), ""); // expected-error {{call to non-static member function without an object argument}} - static_assert(__is_same_as(decltype(&(S::func)), int*), ""); // expected-error {{call to non-static member function without an object argument}} -}; -static_assert(__is_same_as(decltype((S::x)), int&), ""); -static_assert(__is_same_as(decltype(&(S::x)), int*), ""); -static_assert(__is_same_as(decltype((S::func)), int&), ""); // expected-error {{call to non-static member function without an object argument}} -static_assert(__is_same_as(decltype(&(S::func)), int*), ""); // expected-error {{call to non-static member function without an object argument}} - -struct A { int x;}; - -char q(int *); -short q(int A::*); - -template -constexpr int f(char (*)[sizeof(q(&T::x))]) { return 1; } - -template -constexpr int f(char (*)[sizeof(q(&(T::x)))]) { return 2; } - -constexpr int g(char (*p)[sizeof(char)] = 0) { return f(p); } -constexpr int h(char (*p)[sizeof(short)] = 0) { return f(p); } + struct A { + int val; + void func() {} + }; -static_assert(g() == 2); -static_assert(h() == 1); + void test() { + decltype(&(A::val)) ptr1; // expected-error {{cannot form pointer to member from a parenthesized expression; did you mean to remove the parentheses?}} + int A::* ptr2 = &(A::val); // expected-error {{invalid use of non-static data member 'val'}} + // FIXME: Error messages in these cases are less than clear, we can do + // better. + int size = sizeof(&(A::func)); // expected-error {{call to non-static member function without an object argument}} + void (A::* ptr3)() = &(A::func); // expected-error {{call to non-static member function without an object argument}} + } } diff --git a/clang/test/CXX/module/basic/basic.link/module-declaration.cpp b/clang/test/CXX/module/basic/basic.link/module-declaration.cpp index d71358cc7a571f..14bbc911febfcd 100644 --- a/clang/test/CXX/module/basic/basic.link/module-declaration.cpp +++ b/clang/test/CXX/module/basic/basic.link/module-declaration.cpp @@ -8,27 +8,19 @@ // RUN: %clang_cc1 -std=c++20 -emit-module-interface -fmodule-file=x=%t/x.pcm %t/x.y.cppm -o %t/x.y.pcm // // Module implementation for unknown and known module. (The former is ill-formed.) -// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify -x c++ %t/M.cpp \ -// RUN: -DTEST=1 -DEXPORT= -DMODULE_NAME=z -// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x=%t/x.pcm -fmodule-file=x.y=%t/x.y.pcm -verify -x c++ %t/M.cpp \ -// RUN: -DTEST=2 -DEXPORT= -DMODULE_NAME=x +// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify -x c++ %t/M1.cpp +// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x=%t/x.pcm -fmodule-file=x.y=%t/x.y.pcm -verify -x c++ %t/M2.cpp // // Module interface for unknown and known module. (The latter is ill-formed due to // redefinition.) -// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify %t/M.cpp \ -// RUN: -DTEST=3 -DEXPORT=export -DMODULE_NAME=z -// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify %t/M.cpp \ -// RUN: -DTEST=4 -DEXPORT=export -DMODULE_NAME=x +// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify %t/M3.cpp +// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify %t/M4.cpp // // Miscellaneous syntax. -// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify %t/M.cpp \ -// RUN: -DTEST=7 -DEXPORT=export -DMODULE_NAME='z elderberry' -// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify %t/M.cpp \ -// RUN: -DTEST=8 -DEXPORT=export -DMODULE_NAME='z [[]]' -// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify %t/M.cpp \ -// RUN: -DTEST=9 -DEXPORT=export -DMODULE_NAME='z [[fancy]]' -// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify %t/M.cpp \ -// RUN: -DTEST=10 -DEXPORT=export -DMODULE_NAME='z [[maybe_unused]]' +// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify %t/M5.cpp +// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify %t/M6.cpp +// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify %t/M7.cpp +// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -verify %t/M8.cpp //--- x.cppm export module x; @@ -38,17 +30,26 @@ int a, b; export module x.y; int c; -//--- M.cpp - -EXPORT module MODULE_NAME; -#if TEST == 7 -// expected-error@-2 {{expected ';'}} expected-error@-2 {{a type specifier is required}} -#elif TEST == 9 -// expected-warning@-4 {{unknown attribute 'fancy' ignored}} -#elif TEST == 10 -// expected-error-re@-6 {{'maybe_unused' attribute cannot be applied to a module{{$}}}} -#elif TEST == 1 -// expected-error@-8 {{module 'z' not found}} -#else -// expected-no-diagnostics -#endif +//--- M1.cpp +module z; // expected-error {{module 'z' not found}} + +//--- M2.cpp +module x; // expected-no-diagnostics + +//--- M3.cpp +export module z; // expected-no-diagnostics + +//--- M4.cpp +export module x; // expected-no-diagnostics + +//--- M5.cpp +export module z elderberry; // expected-error {{expected ';'}} expected-error {{a type specifier is required}} + +//--- M6.cpp +export module z [[]]; // expected-no-diagnostics + +//--- M7.cpp +export module z [[fancy]]; // expected-warning {{unknown attribute 'fancy' ignored}} + +//--- M8.cpp +export module z [[maybe_unused]]; // expected-error-re {{'maybe_unused' attribute cannot be applied to a module{{$}}}} diff --git a/clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.import/p1.cppm b/clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.import/p1.cppm index 873e4c0edeac25..ecad4db32a7e94 100644 --- a/clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.import/p1.cppm +++ b/clang/test/CXX/module/dcl.dcl/dcl.module/dcl.module.import/p1.cppm @@ -6,10 +6,12 @@ // RUN: %clang_cc1 -std=c++20 -emit-module-interface -fmodule-file=x=%t/x.pcm %t/x.y.cppm -o %t/x.y.pcm // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/a.b.cppm -o %t/a.b.pcm // -// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -fmodule-file=x=%t/x.pcm -verify %t/test.cpp \ -// RUN: -DMODULE_NAME=z -DINTERFACE +// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -fmodule-file=x=%t/x.pcm -verify %t/test-interface.cpp \ +// RUN: -DINTERFACE // RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -fmodule-file=x=%t/x.pcm \ -// RUN: -fmodule-file=a.b=%t/a.b.pcm -verify %t/test.cpp -DMODULE_NAME=a.b +// RUN: -fmodule-file=a.b=%t/a.b.pcm -verify %t/test.cpp +// RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -fmodule-file=x=%t/x.pcm \ +// RUN: -verify %t/test-module-not-found.cpp // RUN: %clang_cc1 -std=c++20 -I%t -fmodule-file=x.y=%t/x.y.pcm -fmodule-file=x=%t/x.pcm -verify %t/test.x.cpp //--- x.cppm @@ -34,11 +36,8 @@ int use_2 = b; // ok int use_3 = c; // expected-error {{use of undeclared identifier 'c'}} //--- test.cpp -#ifdef INTERFACE -export module MODULE_NAME; -#else -module MODULE_NAME; -#endif +module; +module a.b; import x; @@ -51,6 +50,28 @@ import x.y; import x.; // expected-error {{expected a module name after 'import'}} import .x; // expected-error {{expected a module name after 'import'}} -import blarg; // expected-error {{module 'blarg' not found}} +int use_4 = c; // ok + + +//--- test-interface.cpp +module; +export module z; + +import x; + +import x [[]]; +import x [[foo]]; // expected-warning {{unknown attribute 'foo' ignored}} +import x [[noreturn]]; // expected-error {{'noreturn' attribute cannot be applied to a module import}} +import x [[blarg::noreturn]]; // expected-warning {{unknown attribute 'noreturn' ignored}} + +import x.y; +import x.; // expected-error {{expected a module name after 'import'}} +import .x; // expected-error {{expected a module name after 'import'}} int use_4 = c; // ok + +//--- test-module-not-found.cpp +module; + +import blarg; // expected-error {{module 'blarg' not found}} + diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp index 19793fe8263726..51489c5eac5adf 100644 --- a/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp +++ b/clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp @@ -38,13 +38,3 @@ X1 inst_x1a; X1 inst_x1b; X1 inst_x1c; X1 inst_x1d; // expected-error{{template template argument has different template parameters than its corresponding template template paramete}} - -template class X2; // expected-note{{template is declared here}} \ - // expected-note{{template is declared here}} -class X3 : X2<1> {}; // expected-error{{implicit instantiation of undefined template 'X2<1>'}} - -template class X4 : X3 { - struct { - X2<1> e; // expected-error{{implicit instantiation of undefined template 'X2<1>'}} - } f; -}; diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp index b9ff26a7620dbe..ed445360c4fdd5 100644 --- a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp +++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3-0x.cpp @@ -78,7 +78,7 @@ namespace std_example { template struct A { // expected-note {{candidate}} expected-note {{implicit deduction guide}} template A(T &&, U &&, int *); // expected-note {{[with T = int, U = int] not viable: expects an rvalue}} \ - // expected-note {{implicit deduction guide declared as 'template A(T &&, U &&, int *) -> A'}} + // expected-note {{implicit deduction guide declared as 'template A(T &&, type-parameter-0-1 &&, int *) -> A'}} A(T &&, int *); // expected-note {{requires 2}} \ // expected-note {{implicit deduction guide declared as 'template A(T &&, int *) -> A'}} }; diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-20.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-20.cpp index 935dd360847bc4..7a261fef27361a 100644 --- a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-20.cpp +++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-20.cpp @@ -56,7 +56,7 @@ struct B { static int y; template - int z; // expected-error {{non-static data member 'z' cannot be declared as a template}} + int z; // expected-error {{member 'z' declared as a template}} template static int x; @@ -65,7 +65,7 @@ struct B { static int y; template - int x; // expected-error {{non-static data member 'x' cannot be declared as a template}} + int x; // expected-error {{member 'x' declared as a template}} template<> int x; @@ -169,7 +169,7 @@ struct D { static int y; template - int z; // expected-error {{non-static data member 'z' cannot be declared as a template}} + int z; // expected-error {{member 'z' declared as a template}} template static int x; @@ -178,7 +178,7 @@ struct D { static int y; template - int x; // expected-error {{non-static data member 'x' cannot be declared as a template}} + int x; // expected-error {{member 'x' declared as a template}} template<> int x; diff --git a/clang/test/CodeGen/attr-counted-by.c b/clang/test/CodeGen/attr-counted-by.c index 46a6c2b492dbe1..32db136076d7d7 100644 --- a/clang/test/CodeGen/attr-counted-by.c +++ b/clang/test/CodeGen/attr-counted-by.c @@ -1906,51 +1906,3 @@ struct test30_struct { void test30(struct test30_struct *ptr, int idx) { ptr->pcpu_refcnt.__padding[idx] = __builtin_dynamic_object_size(ptr, 1); } - -struct test31_empty {}; - -struct test31_struct { - struct test31_empty y; - int s; - int x[] __counted_by(s); -}; - -// SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test31( -// SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR2]] { -// SANITIZE-WITH-ATTR-NEXT: entry: -// SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[PTR]], align 4 -// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64 -// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl nsw i64 [[TMP0]], 2 -// SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = tail call i64 @llvm.smax.i64(i64 [[TMP1]], i64 0) -// SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = trunc i64 [[TMP2]] to i32 -// SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = add i32 [[TMP3]], 4 -// SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[DOT_COUNTED_BY_LOAD]], 0 -// SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP4]] -// SANITIZE-WITH-ATTR-NEXT: ret i32 [[CONV]] -// -// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local i32 @test31( -// NO-SANITIZE-WITH-ATTR-SAME: ptr nocapture noundef readonly [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR2]] { -// NO-SANITIZE-WITH-ATTR-NEXT: entry: -// NO-SANITIZE-WITH-ATTR-NEXT: [[DOT_COUNTED_BY_LOAD:%.*]] = load i32, ptr [[PTR]], align 4 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = sext i32 [[DOT_COUNTED_BY_LOAD]] to i64 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = shl nsw i64 [[TMP0]], 2 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP2:%.*]] = tail call i64 @llvm.smax.i64(i64 [[TMP1]], i64 0) -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP3:%.*]] = trunc i64 [[TMP2]] to i32 -// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP4:%.*]] = add i32 [[TMP3]], 4 -// NO-SANITIZE-WITH-ATTR-NEXT: [[DOTINV:%.*]] = icmp slt i32 [[DOT_COUNTED_BY_LOAD]], 0 -// NO-SANITIZE-WITH-ATTR-NEXT: [[CONV:%.*]] = select i1 [[DOTINV]], i32 0, i32 [[TMP4]] -// NO-SANITIZE-WITH-ATTR-NEXT: ret i32 [[CONV]] -// -// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test31( -// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR2]] { -// SANITIZE-WITHOUT-ATTR-NEXT: entry: -// SANITIZE-WITHOUT-ATTR-NEXT: ret i32 -1 -// -// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local i32 @test31( -// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[PTR:%.*]], i32 noundef [[IDX:%.*]]) local_unnamed_addr #[[ATTR1]] { -// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: -// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i32 -1 -// -int test31(struct test31_struct *ptr, int idx) { - return __builtin_dynamic_object_size(ptr, 0); -} diff --git a/clang/test/CodeGen/ptrauth-function-attributes.c b/clang/test/CodeGen/ptrauth-function-attributes.c index 7f93ccc7c4bceb..7ec30498b9d35e 100644 --- a/clang/test/CodeGen/ptrauth-function-attributes.c +++ b/clang/test/CodeGen/ptrauth-function-attributes.c @@ -4,15 +4,10 @@ // RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -emit-llvm %s -o - | FileCheck %s --check-prefixes=ALL,CALLS // RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -emit-llvm %s -o - | FileCheck %s --check-prefixes=ALL,CALLS -// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-indirect-gotos -emit-llvm %s -o - | FileCheck %s --check-prefixes=ALL,GOTOS -// RUN: %clang_cc1 -triple arm64e-apple-ios -fptrauth-indirect-gotos -emit-llvm %s -o - | FileCheck %s --check-prefixes=ALL,GOTOS - // ALL: define {{(dso_local )?}}void @test() #0 void test() { } // CALLS: attributes #0 = {{{.*}} "ptrauth-calls" {{.*}}} -// GOTOS: attributes #0 = {{{.*}} "ptrauth-indirect-gotos" {{.*}}} - // OFF-NOT: attributes {{.*}} "ptrauth- diff --git a/clang/test/CodeGenCXX/ptrauth-global-constant-initializers.cpp b/clang/test/CodeGenCXX/ptrauth-global-constant-initializers.cpp deleted file mode 100644 index f0c3ea83d8958d..00000000000000 --- a/clang/test/CodeGenCXX/ptrauth-global-constant-initializers.cpp +++ /dev/null @@ -1,234 +0,0 @@ -// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fno-rtti -fptrauth-vtable-pointer-type-discrimination -fptrauth-vtable-pointer-address-discrimination -emit-llvm -o - %s | FileCheck %s - -// CHECK: %struct.Base1 = type { ptr } -// CHECK: %struct.Base2 = type { ptr } -// CHECK: %struct.Derived1 = type { %struct.Base1, %struct.Base2 } -// CHECK: %struct.Derived2 = type { %struct.Base2, %struct.Base1 } -// CHECK: %struct.Derived3 = type { %struct.Base1, %struct.Base2 } - -// CHECK: @_ZTV5Base1 = linkonce_odr unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr ptrauth (ptr @_ZN5Base11aEv, i32 0, i64 [[BASE1_A_DISC:38871]], ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV5Base1, i32 0, i32 0, i32 2))] }, align 8 -// CHECK: @g_b1 = global %struct.Base1 { ptr ptrauth (ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV5Base1, i32 0, i32 0, i32 2), i32 2, i64 [[BASE1_VTABLE_DISC:6511]], ptr @g_b1) }, align 8 -// CHECK: @_ZTV5Base2 = linkonce_odr unnamed_addr constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr null, ptr ptrauth (ptr @_ZN5Base21bEv, i32 0, i64 [[BASE2_B_DISC:27651]], ptr getelementptr inbounds ({ [3 x ptr] }, ptr @_ZTV5Base2, i32 0, i32 0, i32 2))] }, align 8 -// CHECK: @g_b2 = global %struct.Base2 { ptr ptrauth (ptr getelementptr inbounds inrange(-16, 8) ({ [3 x ptr] }, ptr @_ZTV5Base2, i32 0, i32 0, i32 2), i32 2, i64 [[BASE2_VTABLE_DISC:63631]], ptr @g_b2) }, align 8 -// CHECK: @_ZTV8Derived1 = linkonce_odr unnamed_addr constant { [5 x ptr], [3 x ptr] } { [5 x ptr] [ptr null, ptr null, ptr ptrauth (ptr @_ZN5Base11aEv, i32 0, i64 [[BASE1_A_DISC]], ptr getelementptr inbounds ({ [5 x ptr], [3 x ptr] }, ptr @_ZTV8Derived1, i32 0, i32 0, i32 2)), ptr ptrauth (ptr @_ZN8Derived11cEv, i32 0, i64 [[DERIVED1_C_DISC:54092]], ptr getelementptr inbounds ({ [5 x ptr], [3 x ptr] }, ptr @_ZTV8Derived1, i32 0, i32 0, i32 3)), ptr ptrauth (ptr @_ZN8Derived11dEv, i32 0, i64 [[DERIVED1_D_DISC:37391]], ptr getelementptr inbounds ({ [5 x ptr], [3 x ptr] }, ptr @_ZTV8Derived1, i32 0, i32 0, i32 4))], [3 x ptr] [ptr inttoptr (i64 -8 to ptr), ptr null, ptr ptrauth (ptr @_ZN5Base21bEv, i32 0, i64 [[BASE2_B_DISC]], ptr getelementptr inbounds ({ [5 x ptr], [3 x ptr] }, ptr @_ZTV8Derived1, i32 0, i32 1, i32 2))] }, align 8 -// CHECK: @g_d1 = global { ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds inrange(-16, 24) ({ [5 x ptr], [3 x ptr] }, ptr @_ZTV8Derived1, i32 0, i32 0, i32 2), i32 2, i64 [[BASE1_VTABLE_DISC]], ptr @g_d1), ptr ptrauth (ptr getelementptr inbounds inrange(-16, 8) ({ [5 x ptr], [3 x ptr] }, ptr @_ZTV8Derived1, i32 0, i32 1, i32 2), i32 2, i64 [[BASE2_VTABLE_DISC]], ptr getelementptr inbounds ({ ptr, ptr }, ptr @g_d1, i32 0, i32 1)) }, align 8 -// CHECK: @_ZTV8Derived2 = linkonce_odr unnamed_addr constant { [5 x ptr], [3 x ptr] } { [5 x ptr] [ptr null, ptr null, ptr ptrauth (ptr @_ZN5Base21bEv, i32 0, i64 [[BASE2_B_DISC]], ptr getelementptr inbounds ({ [5 x ptr], [3 x ptr] }, ptr @_ZTV8Derived2, i32 0, i32 0, i32 2)), ptr ptrauth (ptr @_ZN8Derived21cEv, i32 0, i64 [[DERIVED2_C_DISC:15537]], ptr getelementptr inbounds ({ [5 x ptr], [3 x ptr] }, ptr @_ZTV8Derived2, i32 0, i32 0, i32 3)), ptr ptrauth (ptr @_ZN8Derived21eEv, i32 0, i64 209, ptr getelementptr inbounds ({ [5 x ptr], [3 x ptr] }, ptr @_ZTV8Derived2, i32 0, i32 0, i32 4))], [3 x ptr] [ptr inttoptr (i64 -8 to ptr), ptr null, ptr ptrauth (ptr @_ZN5Base11aEv, i32 0, i64 [[BASE1_A_DISC]], ptr getelementptr inbounds ({ [5 x ptr], [3 x ptr] }, ptr @_ZTV8Derived2, i32 0, i32 1, i32 2))] }, align 8 -// CHECK: @g_d2 = global { ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds inrange(-16, 24) ({ [5 x ptr], [3 x ptr] }, ptr @_ZTV8Derived2, i32 0, i32 0, i32 2), i32 2, i64 [[BASE2_VTABLE_DISC]], ptr @g_d2), ptr ptrauth (ptr getelementptr inbounds inrange(-16, 8) ({ [5 x ptr], [3 x ptr] }, ptr @_ZTV8Derived2, i32 0, i32 1, i32 2), i32 2, i64 [[BASE1_VTABLE_DISC]], ptr getelementptr inbounds ({ ptr, ptr }, ptr @g_d2, i32 0, i32 1)) }, align 8 -// CHECK: @_ZTV8Derived3 = linkonce_odr unnamed_addr constant { [4 x ptr], [3 x ptr] } { [4 x ptr] [ptr null, ptr null, ptr ptrauth (ptr @_ZN5Base11aEv, i32 0, i64 [[BASE1_A_DISC]], ptr getelementptr inbounds ({ [4 x ptr], [3 x ptr] }, ptr @_ZTV8Derived3, i32 0, i32 0, i32 2)), ptr ptrauth (ptr @_ZN8Derived31iEv, i32 0, i64 [[DERIVED3_I_DISC:19084]], ptr getelementptr inbounds ({ [4 x ptr], [3 x ptr] }, ptr @_ZTV8Derived3, i32 0, i32 0, i32 3))], [3 x ptr] [ptr inttoptr (i64 -8 to ptr), ptr null, ptr ptrauth (ptr @_ZN5Base21bEv, i32 0, i64 [[BASE2_B_DISC]], ptr getelementptr inbounds ({ [4 x ptr], [3 x ptr] }, ptr @_ZTV8Derived3, i32 0, i32 1, i32 2))] }, align 8 -// CHECK: @g_d3 = global { ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds inrange(-16, 16) ({ [4 x ptr], [3 x ptr] }, ptr @_ZTV8Derived3, i32 0, i32 0, i32 2), i32 2, i64 [[BASE1_VTABLE_DISC]], ptr @g_d3), ptr ptrauth (ptr getelementptr inbounds inrange(-16, 8) ({ [4 x ptr], [3 x ptr] }, ptr @_ZTV8Derived3, i32 0, i32 1, i32 2), i32 2, i64 [[BASE2_VTABLE_DISC]], ptr getelementptr inbounds ({ ptr, ptr }, ptr @g_d3, i32 0, i32 1)) }, align 8 -// CHECK: @g_vb1 = global %struct.VirtualBase1 zeroinitializer, align 8 -// CHECK: @g_vb2 = global %struct.VirtualBase2 zeroinitializer, align 8 -// CHECK: @g_d4 = global %struct.Derived4 zeroinitializer, align 8 -// CHECK: @_ZTV12VirtualBase1 = linkonce_odr unnamed_addr constant { [6 x ptr] } { [6 x ptr] [ptr null, ptr null, ptr null, ptr null, ptr ptrauth (ptr @_ZN5Base11aEv, i32 0, i64 [[BASE1_A_DISC]], ptr getelementptr inbounds ({ [6 x ptr] }, ptr @_ZTV12VirtualBase1, i32 0, i32 0, i32 4)), ptr ptrauth (ptr @_ZN12VirtualBase11fEv, i32 0, i64 [[VIRTUALBASE1_F_DISC:7987]], ptr getelementptr inbounds ({ [6 x ptr] }, ptr @_ZTV12VirtualBase1, i32 0, i32 0, i32 5))] }, align 8 -// CHECK: @_ZTT12VirtualBase1 = linkonce_odr unnamed_addr constant [2 x ptr] [ptr ptrauth (ptr getelementptr inbounds inrange(-32, 16) ({ [6 x ptr] }, ptr @_ZTV12VirtualBase1, i32 0, i32 0, i32 4), i32 2), ptr ptrauth (ptr getelementptr inbounds inrange(-32, 16) ({ [6 x ptr] }, ptr @_ZTV12VirtualBase1, i32 0, i32 0, i32 4), i32 2)], align 8 -// CHECK: @_ZTV12VirtualBase2 = linkonce_odr unnamed_addr constant { [5 x ptr], [4 x ptr] } { [5 x ptr] [ptr inttoptr (i64 8 to ptr), ptr null, ptr null, ptr ptrauth (ptr @_ZN5Base21bEv, i32 0, i64 [[BASE2_B_DISC]], ptr getelementptr inbounds ({ [5 x ptr], [4 x ptr] }, ptr @_ZTV12VirtualBase2, i32 0, i32 0, i32 3)), ptr ptrauth (ptr @_ZN12VirtualBase21gEv, i32 0, i64 [[VIRTUALBASE2_G_DISC:51224]], ptr getelementptr inbounds ({ [5 x ptr], [4 x ptr] }, ptr @_ZTV12VirtualBase2, i32 0, i32 0, i32 4))], [4 x ptr] [ptr null, ptr inttoptr (i64 -8 to ptr), ptr null, ptr ptrauth (ptr @_ZN5Base11aEv, i32 0, i64 [[BASE1_A_DISC]], ptr getelementptr inbounds ({ [5 x ptr], [4 x ptr] }, ptr @_ZTV12VirtualBase2, i32 0, i32 1, i32 3))] }, align 8 -// CHECK: @_ZTT12VirtualBase2 = linkonce_odr unnamed_addr constant [2 x ptr] [ptr ptrauth (ptr getelementptr inbounds inrange(-24, 16) ({ [5 x ptr], [4 x ptr] }, ptr @_ZTV12VirtualBase2, i32 0, i32 0, i32 3), i32 2), ptr ptrauth (ptr getelementptr inbounds inrange(-24, 8) ({ [5 x ptr], [4 x ptr] }, ptr @_ZTV12VirtualBase2, i32 0, i32 1, i32 3), i32 2)], align 8 -// CHECK: @_ZTV8Derived4 = linkonce_odr unnamed_addr constant { [7 x ptr], [5 x ptr] } { [7 x ptr] [ptr null, ptr null, ptr null, ptr null, ptr ptrauth (ptr @_ZN5Base11aEv, i32 0, i64 [[BASE1_A_DISC]], ptr getelementptr inbounds ({ [7 x ptr], [5 x ptr] }, ptr @_ZTV8Derived4, i32 0, i32 0, i32 4)), ptr ptrauth (ptr @_ZN12VirtualBase11fEv, i32 0, i64 [[VIRTUALBASE1_F_DISC]], ptr getelementptr inbounds ({ [7 x ptr], [5 x ptr] }, ptr @_ZTV8Derived4, i32 0, i32 0, i32 5)), ptr ptrauth (ptr @_ZN8Derived41hEv, i32 0, i64 [[DERIVED4_H_DISC:31844]], ptr getelementptr inbounds ({ [7 x ptr], [5 x ptr] }, ptr @_ZTV8Derived4, i32 0, i32 0, i32 6))], [5 x ptr] [ptr inttoptr (i64 -8 to ptr), ptr inttoptr (i64 -8 to ptr), ptr null, ptr ptrauth (ptr @_ZN5Base21bEv, i32 0, i64 [[BASE2_B_DISC]], ptr getelementptr inbounds ({ [7 x ptr], [5 x ptr] }, ptr @_ZTV8Derived4, i32 0, i32 1, i32 3)), ptr ptrauth (ptr @_ZN12VirtualBase21gEv, i32 0, i64 [[VIRTUALBASE2_G_DISC]], ptr getelementptr inbounds ({ [7 x ptr], [5 x ptr] }, ptr @_ZTV8Derived4, i32 0, i32 1, i32 4))] }, align 8 -// CHECK: @_ZTT8Derived4 = linkonce_odr unnamed_addr constant [7 x ptr] [ptr ptrauth (ptr getelementptr inbounds inrange(-32, 24) ({ [7 x ptr], [5 x ptr] }, ptr @_ZTV8Derived4, i32 0, i32 0, i32 4), i32 2), ptr ptrauth (ptr getelementptr inbounds inrange(-32, 16) ({ [6 x ptr] }, ptr @_ZTC8Derived40_12VirtualBase1, i32 0, i32 0, i32 4), i32 2), ptr ptrauth (ptr getelementptr inbounds inrange(-32, 16) ({ [6 x ptr] }, ptr @_ZTC8Derived40_12VirtualBase1, i32 0, i32 0, i32 4), i32 2), ptr ptrauth (ptr getelementptr inbounds inrange(-24, 16) ({ [5 x ptr], [4 x ptr] }, ptr @_ZTC8Derived48_12VirtualBase2, i32 0, i32 0, i32 3), i32 2), ptr ptrauth (ptr getelementptr inbounds inrange(-24, 8) ({ [5 x ptr], [4 x ptr] }, ptr @_ZTC8Derived48_12VirtualBase2, i32 0, i32 1, i32 3), i32 2), ptr ptrauth (ptr getelementptr inbounds inrange(-32, 24) ({ [7 x ptr], [5 x ptr] }, ptr @_ZTV8Derived4, i32 0, i32 0, i32 4), i32 2), ptr ptrauth (ptr getelementptr inbounds inrange(-24, 16) ({ [7 x ptr], [5 x ptr] }, ptr @_ZTV8Derived4, i32 0, i32 1, i32 3), i32 2)], align 8 -// CHECK: @_ZTC8Derived40_12VirtualBase1 = linkonce_odr unnamed_addr constant { [6 x ptr] } { [6 x ptr] [ptr null, ptr null, ptr null, ptr null, ptr ptrauth (ptr @_ZN5Base11aEv, i32 0, i64 [[BASE1_A_DISC]], ptr getelementptr inbounds ({ [6 x ptr] }, ptr @_ZTC8Derived40_12VirtualBase1, i32 0, i32 0, i32 4)), ptr ptrauth (ptr @_ZN12VirtualBase11fEv, i32 0, i64 [[VIRTUALBASE1_F_DISC]], ptr getelementptr inbounds ({ [6 x ptr] }, ptr @_ZTC8Derived40_12VirtualBase1, i32 0, i32 0, i32 5))] }, align 8 -// CHECK: @_ZTC8Derived48_12VirtualBase2 = linkonce_odr unnamed_addr constant { [5 x ptr], [4 x ptr] } { [5 x ptr] [ptr inttoptr (i64 -8 to ptr), ptr null, ptr null, ptr ptrauth (ptr @_ZN5Base21bEv, i32 0, i64 [[BASE2_B_DISC]], ptr getelementptr inbounds ({ [5 x ptr], [4 x ptr] }, ptr @_ZTC8Derived48_12VirtualBase2, i32 0, i32 0, i32 3)), ptr ptrauth (ptr @_ZN12VirtualBase21gEv, i32 0, i64 [[VIRTUALBASE2_G_DISC]], ptr getelementptr inbounds ({ [5 x ptr], [4 x ptr] }, ptr @_ZTC8Derived48_12VirtualBase2, i32 0, i32 0, i32 4))], [4 x ptr] [ptr null, ptr inttoptr (i64 8 to ptr), ptr null, ptr ptrauth (ptr @_ZN5Base11aEv, i32 0, i64 [[BASE1_A_DISC]], ptr getelementptr inbounds ({ [5 x ptr], [4 x ptr] }, ptr @_ZTC8Derived48_12VirtualBase2, i32 0, i32 1, i32 3))] }, align 8 - -struct Base1 { virtual void a() {} }; -struct Base2 { virtual void b() {} }; -struct Derived1 : public Base1, public Base2 { - virtual void c() {} - virtual void d() {} -}; -struct Derived2 : public Base2, public Base1 { - virtual void c() {} - virtual void e() {} -}; - -struct Derived3 : public Base1, public Base2 { - constexpr Derived3(){} - virtual void i() {} -}; - -Base1 g_b1; -Base2 g_b2; -Derived1 g_d1; -Derived2 g_d2; -Derived3 g_d3; - -extern "C" void test_basic_inheritance() { - Base1 g_b1; - Base2 g_b2; - Derived1 g_d1; - Derived2 g_d2; - Derived3 g_d3; -} - -struct VirtualBase1 : virtual Base1 { - VirtualBase1(){} - virtual void f() {} -}; -struct VirtualBase2 : virtual Base1, Base2 { - VirtualBase2(){} - virtual void g() {} -}; -struct Derived4 : VirtualBase1, VirtualBase2 { - virtual void h() {} -}; -struct Derived5 : VirtualBase2, VirtualBase1 { - virtual void h() {} -}; - -// CHECK-LABEL: define {{.*}} ptr @_ZN12VirtualBase1C1Ev -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) - -// CHECK-LABEL: define {{.*}} ptr @_ZN12VirtualBase2C1Ev -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE2_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) - -// CHECK-LABEL: define {{.*}} ptr @_ZN8Derived4C1Ev -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE2_VTABLE_DISC]]) - -// CHECK-LABEL: define {{.*}} ptr @_ZN8Derived5C1Ev -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE2_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) - - -VirtualBase1 g_vb1; -VirtualBase2 g_vb2; -Derived4 g_d4; -Derived5 g_d5; - - -extern "C" void cross_check_vtables(Base1 *b1, - Base2 *b2, - Derived1 *d1, - Derived2 *d2, - Derived3 *d3, - VirtualBase1 *vb1, - VirtualBase2 *vb2, - Derived4 *d4, - Derived4 *d5) { - asm("; b1->a()" ::: "memory"); - b1->a(); - asm("; b2->b()" ::: "memory"); - b2->b(); - asm("; d1->a()" ::: "memory"); - d1->a(); - asm("; d1->c()" ::: "memory"); - d1->c(); - asm("; d2->a()" ::: "memory"); - d2->a(); - asm("; d2->c()" ::: "memory"); - d2->c(); - asm("; d3->a()" ::: "memory"); - d3->a(); - asm("; d3->b()" ::: "memory"); - d3->b(); - asm("; d3->i()" ::: "memory"); - d3->i(); - asm("; vb1->a()" ::: "memory"); - vb1->a(); - asm("; vb1->f()" ::: "memory"); - vb1->f(); - asm("; vb2->a()" ::: "memory"); - vb2->a(); - asm("; vb2->g()" ::: "memory"); - vb2->g(); - asm("; d4->a()" ::: "memory"); - d4->a(); - asm("; d4->b()" ::: "memory"); - d4->b(); - asm("; d4->f()" ::: "memory"); - d4->f(); - asm("; d4->g()" ::: "memory"); - d4->g(); - asm("; d4->h()" ::: "memory"); - d4->h(); - asm("; d5->a()" ::: "memory"); - d5->a(); - asm("; d5->b()" ::: "memory"); - d5->b(); - asm("; d5->f()" ::: "memory"); - d5->f(); - asm("; d5->g()" ::: "memory"); - d5->g(); - asm("; d5->h()" ::: "memory"); - d5->h(); -} - -// CHECK-LABEL: define void @cross_check_vtables( -// CHECK: "; b1->a()", -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_A_DISC]]) -// CHECK: "; b2->b()" -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE2_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE2_B_DISC]]) -// CHECK: "; d1->a()" -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_A_DISC]]) -// CHECK: "; d1->c()" -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[DERIVED1_C_DISC]]) -// CHECK: "; d2->a()" -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_A_DISC]]) -// CHECK: "; d2->c()" -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE2_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[DERIVED2_C_DISC]]) -// CHECK: "; d3->a()" -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_A_DISC]]) -// CHECK: "; d3->b()" -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE2_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE2_B_DISC]]) -// CHECK: "; d3->i()" -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[DERIVED3_I_DISC]]) -// CHECK: "; vb1->a()" -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_A_DISC]]) -// CHECK: "; vb1->f()" -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[VIRTUALBASE1_F_DISC]]) -// CHECK: "; vb2->a()" -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE2_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_A_DISC]]) -// CHECK: "; vb2->g()" -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE2_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[VIRTUALBASE2_G_DISC]]) -// CHECK: "; d4->a()" -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_A_DISC]]) -// CHECK: "; d4->b()" -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE2_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE2_B_DISC]]) -// CHECK: "; d4->f()" -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[VIRTUALBASE1_F_DISC]]) -// CHECK: "; d4->g()" -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE2_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[VIRTUALBASE2_G_DISC]]) -// CHECK: "; d4->h()" -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[DERIVED4_H_DISC]]) - -// CHECK-LABEL: define {{.*}} ptr @_ZN5Base1C2Ev -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) - -// CHECK-LABEL: define {{.*}} ptr @_ZN5Base2C2Ev -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE2_VTABLE_DISC]]) - -// CHECK-LABEL: define {{.*}} ptr @_ZN8Derived1C2Ev -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE2_VTABLE_DISC]]) - -// CHECK-LABEL: define {{.*}} ptr @_ZN8Derived2C2Ev -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE2_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) - -// CHECK-LABEL: define {{.*}} ptr @_ZN8Derived3C2Ev -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE1_VTABLE_DISC]]) -// CHECK: call i64 @llvm.ptrauth.blend(i64 {{%.*}}, i64 [[BASE2_VTABLE_DISC]]) - diff --git a/clang/test/CodeGenCXX/ptrauth-member-function-pointer.cpp b/clang/test/CodeGenCXX/ptrauth-member-function-pointer.cpp deleted file mode 100644 index 5e84e3e7bc5e9a..00000000000000 --- a/clang/test/CodeGenCXX/ptrauth-member-function-pointer.cpp +++ /dev/null @@ -1,433 +0,0 @@ -// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -o - %s | FileCheck -check-prefixes=CHECK,NODEBUG %s -// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -debug-info-kind=limited -o - %s | FileCheck -check-prefixes=CHECK %s -// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -stack-protector 1 -o - %s | FileCheck %s -check-prefix=STACK-PROT -// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -stack-protector 2 -o - %s | FileCheck %s -check-prefix=STACK-PROT -// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -emit-llvm -std=c++11 -O1 -disable-llvm-passes -stack-protector 3 -o - %s | FileCheck %s -check-prefix=STACK-PROT - - -// CHECK: @gmethod0 = global { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base011nonvirtual0Ev, i32 0, i64 [[TYPEDISC1:35591]]) to i64), i64 0 }, align 8 -// CHECK: @gmethod1 = global { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN8Derived011nonvirtual5Ev, i32 0, i64 [[TYPEDISC0:22163]]) to i64), i64 0 }, align 8 -// CHECK: @gmethod2 = global { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 [[TYPEDISC0]]) to i64), i64 0 }, align 8 - -// CHECK: @__const._Z13testArrayInitv.p0 = private unnamed_addr constant [1 x { i64, i64 }] [{ i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base011nonvirtual0Ev, i32 0, i64 35591) to i64), i64 0 }], align 8 -// CHECK: @__const._Z13testArrayInitv.p1 = private unnamed_addr constant [1 x { i64, i64 }] [{ i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 35591) to i64), i64 0 }], align 8 -// CHECK: @__const._Z13testArrayInitv.c0 = private unnamed_addr constant %struct.Class0 { { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base011nonvirtual0Ev, i32 0, i64 35591) to i64), i64 0 } }, align 8 -// CHECK: @__const._Z13testArrayInitv.c1 = private unnamed_addr constant %struct.Class0 { { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 35591) to i64), i64 0 } }, align 8 - -// CHECK: @_ZTV5Base0 = unnamed_addr constant { [5 x ptr] } { [5 x ptr] [ptr null, ptr @_ZTI5Base0, -// CHECK-SAME: ptr ptrauth (ptr @_ZN5Base08virtual1Ev, i32 0, i64 55600, ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV5Base0, i32 0, i32 0, i32 2)), -// CHECK-SAME: ptr ptrauth (ptr @_ZN5Base08virtual3Ev, i32 0, i64 53007, ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV5Base0, i32 0, i32 0, i32 3)), -// CHECK-SAME: ptr ptrauth (ptr @_ZN5Base016virtual_variadicEiz, i32 0, i64 7464, ptr getelementptr inbounds ({ [5 x ptr] }, ptr @_ZTV5Base0, i32 0, i32 0, i32 4))] }, align 8 - -typedef __SIZE_TYPE__ size_t; - -namespace std { -template -class initializer_list { - const _Ep *__begin_; - size_t __size_; - - initializer_list(const _Ep *__b, size_t __s); -}; -} // namespace std - -struct Base0 { - void nonvirtual0(); - virtual void virtual1(); - virtual void virtual3(); - virtual void virtual_variadic(int, ...); -}; - -struct A0 { - int d[4]; -}; - -struct A1 { - int d[8]; -}; - -struct __attribute__((trivial_abi)) TrivialS { - TrivialS(const TrivialS &); - ~TrivialS(); - int p[4]; -}; - -struct Derived0 : Base0 { - void virtual1() override; - void nonvirtual5(); - virtual void virtual6(); - virtual A0 return_agg(); - virtual A1 sret(); - virtual void trivial_abi(TrivialS); -}; - -struct Base1 { - virtual void virtual7(); -}; - -struct Derived1 : Base0, Base1 { - void virtual1() override; - void virtual7() override; -}; - -typedef void (Base0::*MethodTy0)(); -typedef void (Base0::*VariadicMethodTy0)(int, ...); -typedef void (Derived0::*MethodTy1)(); - -struct Class0 { - MethodTy1 m0; -}; - -// CHECK: define void @_ZN5Base08virtual1Ev( - -// CHECK: define void @_Z5test0v() -// CHECK: %[[METHOD0:.*]] = alloca { i64, i64 }, align 8 -// CHECK-NEXT: %[[VARMETHOD1:.*]] = alloca { i64, i64 }, align 8 -// CHECK-NEXT: %[[METHOD2:.*]] = alloca { i64, i64 }, align 8 -// CHECK-NEXT: %[[METHOD3:.*]] = alloca { i64, i64 }, align 8 -// CHECK-NEXT: %[[METHOD4:.*]] = alloca { i64, i64 }, align 8 -// CHECK-NEXT: %[[METHOD5:.*]] = alloca { i64, i64 }, align 8 -// CHECK-NEXT: %[[METHOD6:.*]] = alloca { i64, i64 }, align 8 -// CHECK-NEXT: %[[METHOD7:.*]] = alloca { i64, i64 }, align 8 -// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base011nonvirtual0Ev, i32 0, i64 [[TYPEDISC0]]) to i64), i64 0 }, ptr %[[METHOD0]], align 8 -// CHECK-NEXT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 [[TYPEDISC0]]) to i64), i64 0 }, ptr %[[METHOD0]], align 8 -// CHECK-NEXT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual3Ev_vfpthunk_, i32 0, i64 [[TYPEDISC0]]) to i64), i64 0 }, ptr %[[METHOD0]], align 8 -// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base016virtual_variadicEiz_vfpthunk_, i32 0, i64 34368) to i64), i64 0 }, ptr %[[VARMETHOD1]], align 8 -// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base011nonvirtual0Ev, i32 0, i64 [[TYPEDISC1]]) to i64), i64 0 }, ptr %[[METHOD2]], align 8 -// CHECK-NEXT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 [[TYPEDISC1]]) to i64), i64 0 }, ptr %[[METHOD2]], align 8 -// CHECK-NEXT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual3Ev_vfpthunk_, i32 0, i64 [[TYPEDISC1]]) to i64), i64 0 }, ptr %[[METHOD2]], align 8 -// CHECK-NEXT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN8Derived011nonvirtual5Ev, i32 0, i64 [[TYPEDISC1]]) to i64), i64 0 }, ptr %[[METHOD2]], align 8 -// CHECK-NEXT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN8Derived08virtual6Ev_vfpthunk_, i32 0, i64 [[TYPEDISC1]]) to i64), i64 0 }, ptr %[[METHOD2]], align 8 -// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN8Derived010return_aggEv_vfpthunk_, i32 0, i64 64418) to i64), i64 0 }, ptr %[[METHOD3]], align 8 -// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN8Derived04sretEv_vfpthunk_, i32 0, i64 28187) to i64), i64 0 }, ptr %[[METHOD4]], align 8 -// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN8Derived011trivial_abiE8TrivialS_vfpthunk_, i32 0, i64 8992) to i64), i64 0 }, ptr %[[METHOD5]], align 8 -// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base18virtual7Ev_vfpthunk_, i32 0, i64 [[TYPEDISC2:61596]]) to i64), i64 0 }, ptr %[[METHOD6]], align 8 -// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN8Derived18virtual7Ev_vfpthunk_, i32 0, i64 25206) to i64), i64 0 }, ptr %[[METHOD7]], align 8 -// CHECK-NEXT: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 25206) to i64), i64 0 }, ptr %[[METHOD7]], align 8 -// CHECK: ret void - -// CHECK: define linkonce_odr hidden void @_ZN5Base08virtual1Ev_vfpthunk_(ptr noundef %[[THIS:.*]]) -// CHECK: %[[THIS_ADDR:.*]] = alloca ptr, align 8 -// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]], align 8 -// CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8 -// CHECK-NEXT: %[[V0:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8 -// CHECK-NEXT: %[[VTABLE:.*]] = load ptr, ptr %[[THIS1]], align 8 -// CHECK-NEXT: %[[V2:.*]] = ptrtoint ptr %[[VTABLE]] to i64 -// CHECK-NEXT: %[[V3:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V2]], i32 2, i64 0) -// CHECK-NEXT: %[[V4:.*]] = inttoptr i64 %[[V3]] to ptr -// CHECK-NEXT: %[[VFN:.*]] = getelementptr inbounds ptr, ptr %[[V4]], i64 0 -// CHECK-NEXT: %[[V5:.*]] = load ptr, ptr %[[VFN]], align 8 -// CHECK-NEXT: %[[V6:.*]] = ptrtoint ptr %[[VFN]] to i64 -// CHECK-NEXT: %[[V7:.*]] = call i64 @llvm.ptrauth.blend(i64 %[[V6]], i64 55600) -// CHECK-NEXT: musttail call void %[[V5]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(8) %[[V0]]) [ "ptrauth"(i32 0, i64 %[[V7]]) ] -// CHECK-NEXT: ret void - -// CHECK: define linkonce_odr hidden void @_ZN5Base08virtual3Ev_vfpthunk_(ptr noundef %{{.*}}) -// CHECK: load ptr, ptr %{{.*}}, align 8 -// CHECK: load ptr, ptr %{{.*}}, align 8 -// CHECK: %[[VTABLE:.*]] = load ptr, ptr %{{.*}}, align 8 -// CHECK: %[[V2:.*]] = ptrtoint ptr %[[VTABLE]] to i64 -// CHECK: %[[V3:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V2]], i32 2, i64 0) -// CHECK: %[[V4:.*]] = inttoptr i64 %[[V3]] to ptr -// CHECK: getelementptr inbounds ptr, ptr %[[V4]], i64 1 -// CHECK: call i64 @llvm.ptrauth.blend(i64 %{{.*}}, i64 53007) - -// CHECK: define linkonce_odr hidden void @_ZN5Base016virtual_variadicEiz_vfpthunk_(ptr noundef %[[THIS:.*]], i32 noundef %0, ...) -// CHECK: %[[THIS_ADDR:.*]] = alloca ptr, align 8 -// CHECK-NEXT: %[[_ADDR:.*]] = alloca i32, align 4 -// CHECK-NEXT: store ptr %[[THIS]], ptr %[[THIS_ADDR]], align 8 -// CHECK: store i32 %0, ptr %[[_ADDR]], align 4 -// CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8 -// CHECK-NEXT: %[[V1:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8 -// CHECK-NEXT: %[[V2:.*]] = load i32, ptr %[[_ADDR]], align 4 -// CHECK-NEXT: %[[VTABLE:.*]] = load ptr, ptr %[[THIS1]], align 8 -// CHECK-NEXT: %[[V4:.*]] = ptrtoint ptr %[[VTABLE]] to i64 -// CHECK-NEXT: %[[V5:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V4]], i32 2, i64 0) -// CHECK-NEXT: %[[V6:.*]] = inttoptr i64 %[[V5]] to ptr -// CHECK-NEXT: %[[VFN:.*]] = getelementptr inbounds ptr, ptr %[[V6]], i64 2 -// CHECK-NEXT: %[[V7:.*]] = load ptr, ptr %[[VFN]], align 8 -// CHECK-NEXT: %[[V8:.*]] = ptrtoint ptr %[[VFN]] to i64 -// CHECK-NEXT: %[[V9:.*]] = call i64 @llvm.ptrauth.blend(i64 %[[V8]], i64 7464) -// CHECK-NEXT: musttail call void (ptr, i32, ...) %[[V7]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(8) %[[V1]], i32 noundef %[[V2]], ...) [ "ptrauth"(i32 0, i64 %[[V9]]) ] -// CHECK-NEXT: ret void - -// CHECK: define linkonce_odr hidden void @_ZN8Derived08virtual6Ev_vfpthunk_(ptr noundef %[[THIS:.*]]) -// CHECK: %[[THIS_ADDR:.*]] = alloca ptr, align 8 -// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]], align 8 -// CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8 -// CHECK: %[[V0:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8 -// CHECK: %[[VTABLE:.*]] = load ptr, ptr %[[THIS1]], align 8 -// CHECK: %[[V1:.*]] = ptrtoint ptr %[[VTABLE]] to i64 -// CHECK: %[[V2:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V1]], i32 2, i64 0) -// CHECK: %[[V3:.*]] = inttoptr i64 %[[V2]] to ptr -// CHECK: %[[VFN:.*]] = getelementptr inbounds ptr, ptr %[[V3]], i64 3 -// CHECK: %[[V5:.*]] = ptrtoint ptr %[[VFN]] to i64 -// CHECK: call i64 @llvm.ptrauth.blend(i64 %[[V5]], i64 55535) - -// Check that the return value of the musttail call isn't copied to a temporary. - -// CHECK: define linkonce_odr hidden [2 x i64] @_ZN8Derived010return_aggEv_vfpthunk_(ptr noundef %{{.*}}) -// CHECK: %[[CALL:.*]] = musttail call [2 x i64] %{{.*}}(ptr noundef nonnull align {{[0-9]+}} dereferenceable(8) %{{.*}}) [ "ptrauth"(i32 0, i64 %{{.*}}) ] -// CHECK-NEXT: ret [2 x i64] %[[CALL]] - -// Check that the sret pointer passed to the caller is forwarded to the musttail -// call. - -// CHECK: define linkonce_odr hidden void @_ZN8Derived04sretEv_vfpthunk_(ptr dead_on_unwind noalias writable sret(%struct.A1) align 4 %[[AGG_RESULT:.*]], ptr noundef %{{.*}}) -// CHECK: musttail call void %{{.*}}(ptr dead_on_unwind writable sret(%struct.A1) align 4 %[[AGG_RESULT]], ptr noundef nonnull align {{[0-9]+}} dereferenceable(8) %{{.*}}) [ "ptrauth"(i32 0, i64 %{{.*}}) ] -// CHECK-NEXT: ret void - -// Check that the thunk function doesn't destruct the trivial_abi argument. - -// CHECK: define linkonce_odr hidden void @_ZN8Derived011trivial_abiE8TrivialS_vfpthunk_(ptr noundef %{{.*}}, [2 x i64] %{{.*}}) -// NODEBUG-NOT: call -// CHECK: call i64 @llvm.ptrauth.auth( -// NODEBUG-NOT: call -// CHECK: call i64 @llvm.ptrauth.blend( -// NODEBUG-NOT: call -// CHECK: musttail call void -// CHECK-NEXT: ret void - -// CHECK: define linkonce_odr hidden void @_ZN5Base18virtual7Ev_vfpthunk_(ptr noundef %[[THIS:.*]]) -// CHECK: entry: -// CHECK: %[[THIS_ADDR:.*]] = alloca ptr, align 8 -// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]], align 8 -// CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8 -// CHECK: %[[V0:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8 -// CHECK: %[[VTABLE:.*]] = load ptr, ptr %[[THIS1]], align 8 -// CHECK: %[[V1:.*]] = ptrtoint ptr %[[VTABLE]] to i64 -// CHECK: %[[V2:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V1]], i32 2, i64 0) -// CHECK: %[[V3:.*]] = inttoptr i64 %[[V2]] to ptr -// CHECK: getelementptr inbounds ptr, ptr %[[V3]], i64 0 - -// CHECK: define linkonce_odr hidden void @_ZN8Derived18virtual7Ev_vfpthunk_(ptr noundef %[[THIS:.*]]) -// CHECK: %[[THIS_ADDR:.*]] = alloca ptr, align 8 -// CHECK: store ptr %[[THIS]], ptr %[[THIS_ADDR]], align 8 -// CHECK: %[[THIS1:.*]] = load ptr, ptr %[[THIS_ADDR]], align 8 -// CHECK: load ptr, ptr %[[THIS_ADDR]], align 8 -// CHECK: %[[VTABLE:.*]] = load ptr, ptr %[[THIS1]], align 8 -// CHECK: %[[V1:.*]] = ptrtoint ptr %[[VTABLE]] to i64 -// CHECK: %[[V2:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V1]], i32 2, i64 0) -// CHECK: %[[V3:.*]] = inttoptr i64 %[[V2]] to ptr -// CHECK: getelementptr inbounds ptr, ptr %[[V3]], i64 3 - -void Base0::virtual1() {} - -void test0() { - MethodTy0 method0; - method0 = &Base0::nonvirtual0; - method0 = &Base0::virtual1; - method0 = &Base0::virtual3; - - VariadicMethodTy0 varmethod1; - varmethod1 = &Base0::virtual_variadic; - - MethodTy1 method2; - method2 = &Derived0::nonvirtual0; - method2 = &Derived0::virtual1; - method2 = &Derived0::virtual3; - method2 = &Derived0::nonvirtual5; - method2 = &Derived0::virtual6; - - A0 (Derived0::*method3)(); - method3 = &Derived0::return_agg; - - A1 (Derived0::*method4)(); - method4 = &Derived0::sret; - - void (Derived0::*method5)(TrivialS); - method5 = &Derived0::trivial_abi; - - void (Base1::*method6)(); - method6 = &Base1::virtual7; - - void (Derived1::*method7)(); - method7 = &Derived1::virtual7; - method7 = &Derived1::virtual1; -} - -// CHECK: define void @_Z5test1P5Base0MS_FvvE(ptr noundef %[[A0:.*]], [2 x i64] %[[A1_COERCE:.*]]) -// CHECK: %[[A1:.*]] = alloca { i64, i64 }, align 8 -// CHECK: %[[A0_ADDR:.*]] = alloca ptr, align 8 -// CHECK: %[[A1_ADDR:.*]] = alloca { i64, i64 }, align 8 -// CHECK: store [2 x i64] %[[A1_COERCE]], ptr %[[A1]], align 8 -// CHECK: %[[A11:.*]] = load { i64, i64 }, ptr %[[A1]], align 8 -// CHECK: store ptr %[[A0]], ptr %[[A0_ADDR]], align 8 -// CHECK: store { i64, i64 } %[[A11]], ptr %[[A1_ADDR]], align 8 -// CHECK: %[[V1:.*]] = load ptr, ptr %[[A0_ADDR]], align 8 -// CHECK: %[[V2:.*]] = load { i64, i64 }, ptr %[[A1_ADDR]], align 8 -// CHECK: %[[MEMPTR_ADJ:.*]] = extractvalue { i64, i64 } %[[V2]], 1 -// CHECK: %[[MEMPTR_ADJ_SHIFTED:.*]] = ashr i64 %[[MEMPTR_ADJ]], 1 -// CHECK: %[[V4:.*]] = getelementptr inbounds i8, ptr %[[V1]], i64 %[[MEMPTR_ADJ_SHIFTED]] -// CHECK: %[[MEMPTR_PTR:.*]] = extractvalue { i64, i64 } %[[V2]], 0 -// CHECK: %[[V5:.*]] = and i64 %[[MEMPTR_ADJ]], 1 -// CHECK: %[[MEMPTR_ISVIRTUAL:.*]] = icmp ne i64 %[[V5]], 0 -// CHECK: br i1 %[[MEMPTR_ISVIRTUAL]] - -// CHECK: %[[VTABLE:.*]] = load ptr, ptr %[[V4]], align 8 -// CHECK: %[[V7:.*]] = ptrtoint ptr %[[VTABLE]] to i64 -// CHECK: %[[V8:.*]] = call i64 @llvm.ptrauth.auth(i64 %[[V7]], i32 2, i64 0) -// CHECK: %[[V9:.*]] = inttoptr i64 %[[V8]] to ptr -// CHECK: %[[V10:.*]] = trunc i64 %[[MEMPTR_PTR]] to i32 -// CHECK: %[[V11:.*]] = zext i32 %[[V10]] to i64 -// CHECK: %[[V12:.*]] = getelementptr i8, ptr %[[V9]], i64 %[[V11]] -// CHECK: %[[MEMPTR_VIRTUALFN:.*]] = load ptr, ptr %[[V12]], align 8 -// CHECK: br - -// CHECK: %[[MEMPTR_NONVIRTUALFN:.*]] = inttoptr i64 %[[MEMPTR_PTR]] to ptr -// CHECK: br - -// CHECK: %[[V14:.*]] = phi ptr [ %[[MEMPTR_VIRTUALFN]], {{.*}} ], [ %[[MEMPTR_NONVIRTUALFN]], {{.*}} ] -// CHECK: %[[V15:.*]] = phi i64 [ 0, {{.*}} ], [ [[TYPEDISC0]], {{.*}} ] -// CHECK: call void %[[V14]](ptr noundef nonnull align {{[0-9]+}} dereferenceable(8) %[[V4]]) [ "ptrauth"(i32 0, i64 %[[V15]]) ] -// CHECK: ret void - -void test1(Base0 *a0, MethodTy0 a1) { - (a0->*a1)(); -} - -// CHECK: define void @_Z15testConversion0M5Base0FvvEM8Derived0FvvE([2 x i64] %[[METHOD0_COERCE:.*]], [2 x i64] %[[METHOD1_COERCE:.*]]) -// CHECK: %[[METHOD0:.*]] = alloca { i64, i64 }, align 8 -// CHECK: %[[METHOD1:.*]] = alloca { i64, i64 }, align 8 -// CHECK: %[[METHOD0_ADDR:.*]] = alloca { i64, i64 }, align 8 -// CHECK: %[[METHOD1_ADDR:.*]] = alloca { i64, i64 }, align 8 -// CHECK: store [2 x i64] %[[METHOD0_COERCE]], ptr %[[METHOD0]], align 8 -// CHECK: %[[METHOD01:.*]] = load { i64, i64 }, ptr %[[METHOD0]], align 8 -// CHECK: store [2 x i64] %[[METHOD1_COERCE]], ptr %[[METHOD1]], align 8 -// CHECK: %[[METHOD12:.*]] = load { i64, i64 }, ptr %[[METHOD1]], align 8 -// CHECK: store { i64, i64 } %[[METHOD01]], ptr %[[METHOD0_ADDR]], align 8 -// CHECK: store { i64, i64 } %[[METHOD12]], ptr %[[METHOD1_ADDR]], align 8 -// CHECK: %[[V2:.*]] = load { i64, i64 }, ptr %[[METHOD0_ADDR]], align 8 -// CHECK: %[[MEMPTR_PTR:.*]] = extractvalue { i64, i64 } %[[V2]], 0 -// CHECK: %[[MEMPTR_ADJ:.*]] = extractvalue { i64, i64 } %[[V2]], 1 -// CHECK: %[[V3:.*]] = and i64 %[[MEMPTR_ADJ]], 1 -// CHECK: %[[IS_VIRTUAL_OFFSET:.*]] = icmp ne i64 %[[V3]], 0 -// CHECK: br i1 %[[IS_VIRTUAL_OFFSET]] - -// CHECK: %[[V4:.*]] = inttoptr i64 %[[MEMPTR_PTR]] to ptr -// CHECK: %[[V5:.*]] = icmp ne ptr %[[V4]], null -// CHECK: br i1 %[[V5]] - -// CHECK: %[[V6:.*]] = ptrtoint ptr %[[V4]] to i64 -// CHECK: %[[V7:.*]] = call i64 @llvm.ptrauth.resign(i64 %[[V6]], i32 0, i64 [[TYPEDISC0]], i32 0, i64 [[TYPEDISC1]]) -// CHECK: %[[V8:.*]] = inttoptr i64 %[[V7]] to ptr -// CHECK: br - -// CHECK: %[[V9:.*]] = phi ptr [ null, {{.*}} ], [ %[[V8]], {{.*}} ] -// CHECK: %[[V1:.*]] = ptrtoint ptr %[[V9]] to i64 -// CHECK: %[[V11:.*]] = insertvalue { i64, i64 } %[[V2]], i64 %[[V1]], 0 -// CHECK: br - -// CHECK: %[[V12:.*]] = phi { i64, i64 } [ %[[V2]], {{.*}} ], [ %[[V11]], {{.*}} ] -// CHECK: store { i64, i64 } %[[V12]], ptr %[[METHOD1_ADDR]], align 8 -// CHECK: ret void - -void testConversion0(MethodTy0 method0, MethodTy1 method1) { - method1 = method0; -} - -// CHECK: define void @_Z15testConversion1M5Base0FvvE( -// CHECK: call i64 @llvm.ptrauth.resign(i64 %{{.*}}, i32 0, i64 [[TYPEDISC0]], i32 0, i64 [[TYPEDISC1]]) - -void testConversion1(MethodTy0 method0) { - MethodTy1 method1 = reinterpret_cast(method0); -} - -// CHECK: define void @_Z15testConversion2M8Derived0FvvE( -// CHECK: call i64 @llvm.ptrauth.resign(i64 %{{.*}}, i32 0, i64 [[TYPEDISC1]], i32 0, i64 [[TYPEDISC0]]) - -void testConversion2(MethodTy1 method1) { - MethodTy0 method0 = static_cast(method1); -} - -// CHECK: define void @_Z15testConversion3M8Derived0FvvE( -// CHECK: call i64 @llvm.ptrauth.resign(i64 %{{.*}}, i32 0, i64 [[TYPEDISC1]], i32 0, i64 [[TYPEDISC0]]) - -void testConversion3(MethodTy1 method1) { - MethodTy0 method0 = reinterpret_cast(method1); -} - -// No need to call @llvm.ptrauth.resign if the source member function -// pointer is a constant. - -// CHECK: define void @_Z15testConversion4v( -// CHECK: %[[METHOD0:.*]] = alloca { i64, i64 }, align 8 -// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 [[TYPEDISC0]]) to i64), i64 0 }, ptr %[[METHOD0]], align 8 -// CHECK: ret void - -void testConversion4() { - MethodTy0 method0 = reinterpret_cast(&Derived0::virtual1); -} - -// This code used to crash. -namespace testNonVirtualThunk { - struct R {}; - - struct B0 { - virtual void bar(); - }; - - struct B1 { - virtual R foo(); - }; - - struct D : B0, B1 { - virtual R foo(); - }; - - D d; -} - -// CHECK: define internal void @_ZN22TestAnonymousNamespace12_GLOBAL__N_11S3fooEv_vfpthunk_( - -namespace TestAnonymousNamespace { -namespace { -struct S { - virtual void foo(){}; -}; -} // namespace - -void test() { - auto t = &S::foo; -} -} // namespace TestAnonymousNamespace - -MethodTy1 gmethod0 = reinterpret_cast(&Base0::nonvirtual0); -MethodTy0 gmethod1 = reinterpret_cast(&Derived0::nonvirtual5); -MethodTy0 gmethod2 = reinterpret_cast(&Derived0::virtual1); - -// CHECK-LABEL: define void @_Z13testArrayInitv() -// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %p0, ptr align 8 @__const._Z13testArrayInitv.p0, i64 16, i1 false) -// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %p1, ptr align 8 @__const._Z13testArrayInitv.p1, i64 16, i1 false) -// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %c0, ptr align 8 @__const._Z13testArrayInitv.c0, i64 16, i1 false) -// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %c1, ptr align 8 @__const._Z13testArrayInitv.c1, i64 16, i1 false) -// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base011nonvirtual0Ev, i32 0, i64 [[TYPEDISC1]]) to i64), i64 0 }, ptr %{{.*}} align 8 -// CHECK: store { i64, i64 } { i64 ptrtoint (ptr ptrauth (ptr @_ZN5Base08virtual1Ev_vfpthunk_, i32 0, i64 [[TYPEDISC1]]) to i64), i64 0 }, ptr %{{.*}}, align 8 - -void initList(std::initializer_list); - -void testArrayInit() { - MethodTy1 p0[] = {&Base0::nonvirtual0}; - MethodTy1 p1[] = {&Base0::virtual1}; - Class0 c0{&Base0::nonvirtual0}; - Class0 c1{&Base0::virtual1}; - initList({&Base0::nonvirtual0}); - initList({&Base0::virtual1}); -} - - - -// STACK-PROT: define {{.*}}_vfpthunk{{.*}}[[ATTRS:#[0-9]+]] -// STACK-PROT: attributes [[ATTRS]] = -// STACK-PROT-NOT: ssp -// STACK-PROT-NOT: sspstrong -// STACK-PROT-NOT: sspreq -// STACK-PROT-NEXT: attributes - -// CHECK: define void @_Z15testConvertNullv( -// CHECK: %[[T:.*]] = alloca { i64, i64 }, -// store { i64, i64 } zeroinitializer, { i64, i64 }* %[[T]], - -void testConvertNull() { - VariadicMethodTy0 t = (VariadicMethodTy0)(MethodTy0{}); -} diff --git a/clang/test/CodeGenCXX/ptrauth-type-info-vtable.cpp b/clang/test/CodeGenCXX/ptrauth-type-info-vtable.cpp deleted file mode 100644 index d5f69e0485140f..00000000000000 --- a/clang/test/CodeGenCXX/ptrauth-type-info-vtable.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// RUN: %clang_cc1 -DENABLE_TID=0 -I%S -std=c++11 -triple=arm64e-apple-darwin \ -// RUN: -fptrauth-calls -fptrauth-intrinsics \ -// RUN: -fptrauth-vtable-pointer-type-discrimination \ -// RUN: -fptrauth-vtable-pointer-address-discrimination \ -// RUN: %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,NODISC - -// RUN: %clang_cc1 -DENABLE_TID=1 -I%S -std=c++11 -triple=arm64e-apple-darwin \ -// RUN: -fptrauth-calls -fptrauth-intrinsics \ -// RUN: -fptrauth-vtable-pointer-type-discrimination \ -// RUN: -fptrauth-vtable-pointer-address-discrimination \ -// RUN: -fptrauth-type-info-vtable-pointer-discrimination \ -// RUN: %s -emit-llvm -o - | FileCheck %s --check-prefixes=CHECK,DISC - -// copied from typeinfo -namespace std { - -#if __has_cpp_attribute(clang::ptrauth_vtable_pointer) -# if __has_feature(ptrauth_type_info_vtable_pointer_discrimination) -# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH \ - [[clang::ptrauth_vtable_pointer(process_independent, address_discrimination, type_discrimination)]] -# else -# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH \ - [[clang::ptrauth_vtable_pointer(process_independent, no_address_discrimination, no_extra_discrimination)]] -# endif -#else -# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH -#endif - - class _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH type_info - { - type_info& operator=(const type_info&); - type_info(const type_info&); - - protected: - explicit type_info(const char* __n); - - public: - virtual ~type_info(); - - virtual void test_method(); - }; -} // namespace std - -static_assert(__has_feature(ptrauth_type_info_vtable_pointer_discrimination) == ENABLE_TID, "incorrect feature state"); - -// CHECK: @disc_std_type_info = global i32 [[STDTYPEINFO_DISC:45546]] -extern "C" int disc_std_type_info = __builtin_ptrauth_string_discriminator("_ZTVSt9type_info"); - -// CHECK: @_ZTV10TestStruct = unnamed_addr constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr @_ZTI10TestStruct, ptr ptrauth (ptr @_ZN10TestStructD1Ev, i32 0, i64 52216, ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV10TestStruct, i32 0, i32 0, i32 2)), ptr ptrauth (ptr @_ZN10TestStructD0Ev, i32 0, i64 39671, ptr getelementptr inbounds ({ [4 x ptr] }, ptr @_ZTV10TestStruct, i32 0, i32 0, i32 3))] }, align 8 -// CHECK: @_ZTVN10__cxxabiv117__class_type_infoE = external global [0 x ptr] -// CHECK: @_ZTS10TestStruct = constant [13 x i8] c"10TestStruct\00", align 1 - -// NODISC: @_ZTI10TestStruct = constant { ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), i32 2), ptr @_ZTS10TestStruct }, align 8 - -// DISC: @_ZTI10TestStruct = constant { ptr, ptr } { ptr ptrauth (ptr getelementptr inbounds (ptr, ptr @_ZTVN10__cxxabiv117__class_type_infoE, i64 2), i32 2, i64 [[STDTYPEINFO_DISC]]), ptr @_ZTS10TestStruct }, align 8 - -struct TestStruct { - virtual ~TestStruct(); - int a; -}; - -TestStruct::~TestStruct(){} - -extern "C" void test_vtable(std::type_info* t) { - t->test_method(); -} -// NODISC: define void @test_vtable(ptr noundef %t) -// NODISC: [[T_ADDR:%.*]] = alloca ptr, align 8 -// NODISC: store ptr %t, ptr [[T_ADDR]], align 8 -// NODISC: [[T:%.*]] = load ptr, ptr [[T_ADDR]], align 8 -// NODISC: [[VPTR:%.*]] = load ptr, ptr [[T]], align 8 -// NODISC: [[CAST_VPTR:%.*]] = ptrtoint ptr [[VPTR]] to i64 -// NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[CAST_VPTR]], i32 2, i64 0) - -// DISC: define void @test_vtable(ptr noundef %t) -// DISC: [[T_ADDR:%.*]] = alloca ptr, align 8 -// DISC: store ptr %t, ptr [[T_ADDR]], align 8 -// DISC: [[T:%.*]] = load ptr, ptr [[T_ADDR]], align 8 -// DISC: [[VPTR:%.*]] = load ptr, ptr [[T]], align 8 -// DISC: [[ADDR:%.*]] = ptrtoint ptr [[T]] to i64 -// DISC: [[DISCRIMINATOR:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[ADDR]], i64 [[STDTYPEINFO_DISC]]) -// DISC: [[VPTRI:%.*]] = ptrtoint ptr [[VPTR]] to i64 -// DISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VPTRI]], i32 2, i64 [[DISCRIMINATOR]]) - -extern "C" const void *ensure_typeinfo() { - return new TestStruct; -} diff --git a/clang/test/Driver/Inputs/multilib_aarch64_linux_tree/usr/include/aarch64-linux-gnu/.keep b/clang/test/Driver/Inputs/multilib_aarch64_linux_tree/usr/include/aarch64-linux-gnu/.keep deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/clang/test/Driver/Inputs/multilib_aarch64_linux_tree/usr/include/aarch64-linux-pauthtest/.keep b/clang/test/Driver/Inputs/multilib_aarch64_linux_tree/usr/include/aarch64-linux-pauthtest/.keep deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/clang/test/Driver/aarch64-multilib-pauthabi.c b/clang/test/Driver/aarch64-multilib-pauthabi.c deleted file mode 100644 index 3046cb856e83c2..00000000000000 --- a/clang/test/Driver/aarch64-multilib-pauthabi.c +++ /dev/null @@ -1,4 +0,0 @@ -// RUN: %clang --target=aarch64-linux-pauthtest --sysroot=%S/Inputs/multilib_aarch64_linux_tree -### -c %s 2>&1 | FileCheck %s -// RUN: %clang --target=aarch64-linux -mabi=pauthtest --sysroot=%S/Inputs/multilib_aarch64_linux_tree -### -c %s 2>&1 | FileCheck %s - -// CHECK: "-internal-externc-isystem" "{{.*}}/usr/include/aarch64-linux-pauthtest" diff --git a/clang/test/Driver/aarch64-ptrauth.c b/clang/test/Driver/aarch64-ptrauth.c index d13930e8f4b377..fa0125f4b22a9a 100644 --- a/clang/test/Driver/aarch64-ptrauth.c +++ b/clang/test/Driver/aarch64-ptrauth.c @@ -1,7 +1,5 @@ -// REQUIRES: aarch64-registered-target - // RUN: %clang -### -c --target=aarch64 %s 2>&1 | FileCheck %s --check-prefix NONE -// NONE: "-cc1" +// NONE: "-cc1" // NONE-NOT: "-fptrauth- // RUN: %clang -### -c --target=aarch64 \ @@ -15,78 +13,13 @@ // RUN: %s 2>&1 | FileCheck %s --check-prefix=ALL // ALL: "-cc1"{{.*}} "-fptrauth-intrinsics" "-fptrauth-calls" "-fptrauth-returns" "-fptrauth-auth-traps" "-fptrauth-vtable-pointer-address-discrimination" "-fptrauth-vtable-pointer-type-discrimination" "-fptrauth-init-fini" -// RUN: %clang -### -c --target=aarch64-linux -mabi=pauthtest %s 2>&1 | FileCheck %s --check-prefix=PAUTHABI1 -// RUN: %clang -### -c --target=aarch64-linux-pauthtest %s 2>&1 | FileCheck %s --check-prefix=PAUTHABI1 -// PAUTHABI1: "-cc1"{{.*}} "-triple" "aarch64-unknown-linux-pauthtest" -// PAUTHABI1-SAME: "-target-abi" "pauthtest" -// PAUTHABI1-SAME: "-fptrauth-intrinsics" "-fptrauth-calls" "-fptrauth-returns" "-fptrauth-auth-traps" "-fptrauth-vtable-pointer-address-discrimination" "-fptrauth-vtable-pointer-type-discrimination" "-fptrauth-init-fini" - -// RUN: %clang -### -c --target=aarch64 -mabi=pauthtest -fno-ptrauth-intrinsics \ -// RUN: -fno-ptrauth-calls -fno-ptrauth-returns -fno-ptrauth-auth-traps \ -// RUN: -fno-ptrauth-vtable-pointer-address-discrimination -fno-ptrauth-vtable-pointer-type-discrimination \ -// RUN: -fno-ptrauth-init-fini %s 2>&1 | FileCheck %s --check-prefix=PAUTHABI2 -// RUN: %clang -### -c --target=aarch64-pauthtest -fno-ptrauth-intrinsics \ -// RUN: -fno-ptrauth-calls -fno-ptrauth-returns -fno-ptrauth-auth-traps \ -// RUN: -fno-ptrauth-vtable-pointer-address-discrimination -fno-ptrauth-vtable-pointer-type-discrimination \ -// RUN: -fno-ptrauth-init-fini %s 2>&1 | FileCheck %s --check-prefix=PAUTHABI2 -// PAUTHABI2: "-cc1" -// PAUTHABI2-NOT: "-fptrauth- - // RUN: not %clang -### -c --target=x86_64 -fptrauth-intrinsics -fptrauth-calls -fptrauth-returns -fptrauth-auth-traps \ // RUN: -fptrauth-vtable-pointer-address-discrimination -fptrauth-vtable-pointer-type-discrimination \ -// RUN: -fptrauth-init-fini %s 2>&1 | FileCheck %s --check-prefix=ERR1 -// ERR1: error: unsupported option '-fptrauth-intrinsics' for target '{{.*}}' -// ERR1-NEXT: error: unsupported option '-fptrauth-calls' for target '{{.*}}' -// ERR1-NEXT: error: unsupported option '-fptrauth-returns' for target '{{.*}}' -// ERR1-NEXT: error: unsupported option '-fptrauth-auth-traps' for target '{{.*}}' -// ERR1-NEXT: error: unsupported option '-fptrauth-vtable-pointer-address-discrimination' for target '{{.*}}' -// ERR1-NEXT: error: unsupported option '-fptrauth-vtable-pointer-type-discrimination' for target '{{.*}}' -// ERR1-NEXT: error: unsupported option '-fptrauth-init-fini' for target '{{.*}}' - -//// Only support PAuth ABI for Linux as for now. -// RUN: not %clang -c --target=aarch64-unknown -mabi=pauthtest %s 2>&1 | FileCheck %s --check-prefix=ERR2 -// RUN: not %clang -c --target=aarch64-unknown-pauthtest %s 2>&1 | FileCheck %s --check-prefix=ERR2 -// ERR2: error: ABI 'pauthtest' is not supported for 'aarch64-unknown-unknown-pauthtest' - -//// PAuth ABI is encoded as environment part of the triple, so don't allow to explicitly set other environments. -// RUN: not %clang -c --target=aarch64-linux-gnu -mabi=pauthtest %s 2>&1 | FileCheck %s --check-prefix=ERR3 -// ERR3: error: unsupported option '-mabi=pauthtest' for target 'aarch64-unknown-linux-gnu' -// RUN: %clang -c --target=aarch64-linux-pauthtest -mabi=pauthtest %s - -//// The only branch protection option compatible with PAuthABI is BTI. -// RUN: not %clang -### -c --target=aarch64-linux -mabi=pauthtest -mbranch-protection=pac-ret %s 2>&1 | \ -// RUN: FileCheck %s --check-prefix=ERR4 -// RUN: not %clang -### -c --target=aarch64-linux-pauthtest -mbranch-protection=pac-ret %s 2>&1 | \ -// RUN: FileCheck %s --check-prefix=ERR4 -// ERR4: error: unsupported option '-mbranch-protection=pac-ret' for target 'aarch64-unknown-linux-pauthtest' - -// RUN: not %clang -### -c --target=aarch64-linux -mabi=pauthtest -mbranch-protection=gcs %s 2>&1 | \ -// RUN: FileCheck %s --check-prefix=ERR5 -// RUN: not %clang -### -c --target=aarch64-linux-pauthtest -mbranch-protection=gcs %s 2>&1 | \ -// RUN: FileCheck %s --check-prefix=ERR5 -// ERR5: error: unsupported option '-mbranch-protection=gcs' for target 'aarch64-unknown-linux-pauthtest' - -// RUN: not %clang -### -c --target=aarch64-linux -mabi=pauthtest -mbranch-protection=standard %s 2>&1 | \ -// RUN: FileCheck %s --check-prefix=ERR6 -// RUN: not %clang -### -c --target=aarch64-linux-pauthtest -mbranch-protection=standard %s 2>&1 | \ -// RUN: FileCheck %s --check-prefix=ERR6 -// ERR6: error: unsupported option '-mbranch-protection=standard' for target 'aarch64-unknown-linux-pauthtest' - -// RUN: not %clang -### -c --target=aarch64-linux -mabi=pauthtest -msign-return-address=all %s 2>&1 | \ -// RUN: FileCheck %s --check-prefix=ERR7 -// RUN: not %clang -### -c --target=aarch64-linux-pauthtest -msign-return-address=all %s 2>&1 | \ -// RUN: FileCheck %s --check-prefix=ERR7 -// ERR7: error: unsupported option '-msign-return-address=all' for target 'aarch64-unknown-linux-pauthtest' - -// RUN: not %clang -### -c --target=aarch64-linux -mabi=pauthtest -msign-return-address=non-leaf %s 2>&1 | \ -// RUN: FileCheck %s --check-prefix=ERR8 -// RUN: not %clang -### -c --target=aarch64-linux-pauthtest -msign-return-address=non-leaf %s 2>&1 | \ -// RUN: FileCheck %s --check-prefix=ERR8 -// ERR8: error: unsupported option '-msign-return-address=non-leaf' for target 'aarch64-unknown-linux-pauthtest' - -// RUN: %clang -### -c --target=aarch64-linux -mabi=pauthtest -msign-return-address=none %s -// RUN: %clang -### -c --target=aarch64-linux-pauthtest -msign-return-address=none %s -// RUN: %clang -### -c --target=aarch64-linux -mabi=pauthtest -mbranch-protection=bti %s -// RUN: %clang -### -c --target=aarch64-linux-pauthtest -mbranch-protection=bti %s -// RUN: %clang -### -c --target=aarch64-linux -mabi=pauthtest -mbranch-protection=none %s -// RUN: %clang -### -c --target=aarch64-linux-pauthtest -mbranch-protection=none %s +// RUN: -fptrauth-init-fini %s 2>&1 | FileCheck %s --check-prefix=ERR +// ERR: error: unsupported option '-fptrauth-intrinsics' for target '{{.*}}' +// ERR-NEXT: error: unsupported option '-fptrauth-calls' for target '{{.*}}' +// ERR-NEXT: error: unsupported option '-fptrauth-returns' for target '{{.*}}' +// ERR-NEXT: error: unsupported option '-fptrauth-auth-traps' for target '{{.*}}' +// ERR-NEXT: error: unsupported option '-fptrauth-vtable-pointer-address-discrimination' for target '{{.*}}' +// ERR-NEXT: error: unsupported option '-fptrauth-vtable-pointer-type-discrimination' for target '{{.*}}' +// ERR-NEXT: error: unsupported option '-fptrauth-init-fini' for target '{{.*}}' diff --git a/clang/test/Driver/cuda-cross-compiling.c b/clang/test/Driver/cuda-cross-compiling.c index 42d56cbfcc321d..1dc4520f485db5 100644 --- a/clang/test/Driver/cuda-cross-compiling.c +++ b/clang/test/Driver/cuda-cross-compiling.c @@ -32,8 +32,8 @@ // RUN: | FileCheck -check-prefix=ARGS %s // ARGS: -cc1" "-triple" "nvptx64-nvidia-cuda" "-S" {{.*}} "-target-cpu" "sm_61" "-target-feature" "+ptx{{[0-9]+}}" {{.*}} "-o" "[[PTX:.+]].s" -// ARGS-NEXT: ptxas{{.*}}"-m64" "-O0" "--gpu-name" "sm_61" "--output-file" "[[CUBIN:.+]].o" "[[PTX]].s" "-c" -// ARGS-NEXT: clang-nvlink-wrapper{{.*}}"-o" "a.out" "-arch" "sm_61"{{.*}}"[[CUBIN]].o" +// ARGS-NEXT: ptxas{{.*}}"-m64" "-O0" "--gpu-name" "sm_61" "--output-file" "[[CUBIN:.+]].cubin" "[[PTX]].s" "-c" +// ARGS-NEXT: nvlink{{.*}}"-o" "a.out" "-arch" "sm_61" {{.*}} "[[CUBIN]].cubin" // // Test the generated arguments to the CUDA binary utils when targeting NVPTX. @@ -55,7 +55,7 @@ // RUN: %clang -target nvptx64-nvidia-cuda -march=sm_61 -### %t.o 2>&1 \ // RUN: | FileCheck -check-prefix=LINK %s -// LINK: clang-nvlink-wrapper{{.*}}"-o" "a.out" "-arch" "sm_61"{{.*}}[[CUBIN:.+]].o +// LINK: nvlink{{.*}}"-o" "a.out" "-arch" "sm_61" {{.*}} "{{.*}}.cubin" // // Test to ensure that we enable handling global constructors in a freestanding @@ -72,7 +72,7 @@ // RUN: %clang -target nvptx64-nvidia-cuda -Wl,-v -Wl,a,b -march=sm_52 -### %s 2>&1 \ // RUN: | FileCheck -check-prefix=LINKER-ARGS %s -// LINKER-ARGS: clang-nvlink-wrapper{{.*}}"-v"{{.*}}"a" "b" +// LINKER-ARGS: nvlink{{.*}}"-v"{{.*}}"a" "b" // Tests for handling a missing architecture. // diff --git a/clang/test/Driver/fpatchable-function-entry.c b/clang/test/Driver/fpatchable-function-entry.c index 5f07ca99a69de2..ab04fd39ffa1c2 100644 --- a/clang/test/Driver/fpatchable-function-entry.c +++ b/clang/test/Driver/fpatchable-function-entry.c @@ -6,8 +6,6 @@ // RUN: %clang --target=loongarch64 %s -fpatchable-function-entry=1,0 -c -### 2>&1 | FileCheck %s // RUN: %clang --target=riscv32 %s -fpatchable-function-entry=1,0 -c -### 2>&1 | FileCheck %s // RUN: %clang --target=riscv64 %s -fpatchable-function-entry=1,0 -c -### 2>&1 | FileCheck %s -// RUN: %clang --target=powerpc-unknown-linux-gnu %s -fpatchable-function-entry=1,0 -c -### 2>&1 | FileCheck %s -// RUN: %clang --target=powerpc64-unknown-linux-gnu %s -fpatchable-function-entry=1,0 -c -### 2>&1 | FileCheck %s // CHECK: "-fpatchable-function-entry=1" // RUN: %clang --target=aarch64 -fsyntax-only %s -fpatchable-function-entry=1,1 -c -### 2>&1 | FileCheck --check-prefix=11 %s @@ -15,11 +13,8 @@ // RUN: %clang --target=aarch64 -fsyntax-only %s -fpatchable-function-entry=2,1 -c -### 2>&1 | FileCheck --check-prefix=21 %s // 21: "-fpatchable-function-entry=2" "-fpatchable-function-entry-offset=1" -// RUN: not %clang --target=powerpc64-ibm-aix-xcoff -fsyntax-only %s -fpatchable-function-entry=1 2>&1 | FileCheck --check-prefix=AIX64 %s -// AIX64: error: unsupported option '-fpatchable-function-entry=1' for target 'powerpc64-ibm-aix-xcoff' - -// RUN: not %clang --target=powerpc-ibm-aix-xcoff -fsyntax-only %s -fpatchable-function-entry=1 2>&1 | FileCheck --check-prefix=AIX32 %s -// AIX32: error: unsupported option '-fpatchable-function-entry=1' for target 'powerpc-ibm-aix-xcoff' +// RUN: not %clang --target=ppc64 -fsyntax-only %s -fpatchable-function-entry=1 2>&1 | FileCheck --check-prefix=TARGET %s +// TARGET: error: unsupported option '-fpatchable-function-entry=1' for target 'ppc64' // RUN: not %clang --target=x86_64 -fsyntax-only %s -fpatchable-function-entry=1,0, 2>&1 | FileCheck --check-prefix=EXCESS %s // EXCESS: error: invalid argument '1,0,' to -fpatchable-function-entry= diff --git a/clang/test/Driver/ftime-trace-sections.cpp b/clang/test/Driver/ftime-trace-sections.cpp index da7109b9d81a6b..0c16052bc0c3a2 100644 --- a/clang/test/Driver/ftime-trace-sections.cpp +++ b/clang/test/Driver/ftime-trace-sections.cpp @@ -1,5 +1,5 @@ // RUN: rm -rf %t && mkdir %t && cd %t -// RUN: %clangxx -S -ftime-trace -ftime-trace-granularity=0 -ftime-trace-verbose -o out %s +// RUN: %clangxx -S -ftime-trace -ftime-trace-granularity=0 -o out %s // RUN: %python %S/ftime-trace-sections.py < out.json template diff --git a/clang/test/Driver/ftime-trace.cpp b/clang/test/Driver/ftime-trace.cpp index 60c5885704b58e..5fe63de915a718 100644 --- a/clang/test/Driver/ftime-trace.cpp +++ b/clang/test/Driver/ftime-trace.cpp @@ -1,18 +1,18 @@ // RUN: rm -rf %t && mkdir -p %t && cd %t -// RUN: %clangxx -S -no-canonical-prefixes -ftime-trace -ftime-trace-granularity=0 -ftime-trace-verbose -o out %s +// RUN: %clangxx -S -no-canonical-prefixes -ftime-trace -ftime-trace-granularity=0 -o out %s // RUN: cat out.json \ // RUN: | %python -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \ // RUN: | FileCheck %s -// RUN: %clangxx -S -no-canonical-prefixes -ftime-trace=new-name.json -ftime-trace-granularity=0 -ftime-trace-verbose -o out %s +// RUN: %clangxx -S -no-canonical-prefixes -ftime-trace=new-name.json -ftime-trace-granularity=0 -o out %s // RUN: cat new-name.json \ // RUN: | %python -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \ // RUN: | FileCheck %s // RUN: mkdir dir1 dir2 -// RUN: %clangxx -S -no-canonical-prefixes -ftime-trace=dir1 -ftime-trace-granularity=0 -ftime-trace-verbose -o out %s +// RUN: %clangxx -S -no-canonical-prefixes -ftime-trace=dir1 -ftime-trace-granularity=0 -o out %s // RUN: cat dir1/out.json \ // RUN: | %python -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \ // RUN: | FileCheck %s -// RUN: %clangxx -S -no-canonical-prefixes -ftime-trace=dir2/ -ftime-trace-granularity=0 -ftime-trace-verbose -o out %s +// RUN: %clangxx -S -no-canonical-prefixes -ftime-trace=dir2/ -ftime-trace-granularity=0 -o out %s // RUN: cat dir2/out.json \ // RUN: | %python -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \ // RUN: | FileCheck %s @@ -34,33 +34,32 @@ // RUN: mkdir d e f && cp %s d/a.cpp && touch d/b.c /// TODO: Support -fno-integrated-as. -// RUN: %clang -### -c -ftime-trace -ftime-trace-granularity=0 -ftime-trace-verbose -fintegrated-as d/a.cpp -o e/a.o 2>&1 | FileCheck %s --check-prefix=COMPILE1 -// COMPILE1: -cc1{{.*}} "-ftime-trace=e/a.json" "-ftime-trace-granularity=0" "-ftime-trace-verbose" +// RUN: %clang -### -c -ftime-trace -ftime-trace-granularity=0 -fintegrated-as d/a.cpp -o e/a.o 2>&1 | FileCheck %s --check-prefix=COMPILE1 +// COMPILE1: -cc1{{.*}} "-ftime-trace=e/a.json" "-ftime-trace-granularity=0" -// RUN: %clang -### -c -ftime-trace -ftime-trace-granularity=0 -ftime-trace-verbose d/a.cpp d/b.c -dumpdir f/ 2>&1 | FileCheck %s --check-prefix=COMPILE2 -// COMPILE2: -cc1{{.*}} "-ftime-trace=f/a.json" "-ftime-trace-granularity=0" "-ftime-trace-verbose" -// COMPILE2: -cc1{{.*}} "-ftime-trace=f/b.json" "-ftime-trace-granularity=0" "-ftime-trace-verbose" +// RUN: %clang -### -c -ftime-trace -ftime-trace-granularity=0 d/a.cpp d/b.c -dumpdir f/ 2>&1 | FileCheck %s --check-prefix=COMPILE2 +// COMPILE2: -cc1{{.*}} "-ftime-trace=f/a.json" "-ftime-trace-granularity=0" +// COMPILE2: -cc1{{.*}} "-ftime-trace=f/b.json" "-ftime-trace-granularity=0" /// -o specifies the link output. Create ${output}-${basename}.json. -// RUN: %clang -### -ftime-trace -ftime-trace-granularity=0 -ftime-trace-verbose d/a.cpp d/b.c -o e/x 2>&1 | FileCheck %s --check-prefix=LINK1 -// LINK1: -cc1{{.*}} "-ftime-trace=e/x-a.json" "-ftime-trace-granularity=0" "-ftime-trace-verbose" -// LINK1: -cc1{{.*}} "-ftime-trace=e/x-b.json" "-ftime-trace-granularity=0" "-ftime-trace-verbose" +// RUN: %clang -### -ftime-trace -ftime-trace-granularity=0 d/a.cpp d/b.c -o e/x 2>&1 | FileCheck %s --check-prefix=LINK1 +// LINK1: -cc1{{.*}} "-ftime-trace=e/x-a.json" "-ftime-trace-granularity=0" +// LINK1: -cc1{{.*}} "-ftime-trace=e/x-b.json" "-ftime-trace-granularity=0" /// -dumpdir is f/g, not ending with a path separator. We create f/g${basename}.json. -// RUN: %clang -### -ftime-trace -ftime-trace-granularity=0 -ftime-trace-verbose d/a.cpp d/b.c -o e/x -dumpdir f/g 2>&1 | FileCheck %s --check-prefix=LINK2 -// LINK2: -cc1{{.*}} "-ftime-trace=f/ga.json" "-ftime-trace-granularity=0" "-ftime-trace-verbose" -// LINK2: -cc1{{.*}} "-ftime-trace=f/gb.json" "-ftime-trace-granularity=0" "-ftime-trace-verbose" +// RUN: %clang -### -ftime-trace -ftime-trace-granularity=0 d/a.cpp d/b.c -o e/x -dumpdir f/g 2>&1 | FileCheck %s --check-prefix=LINK2 +// LINK2: -cc1{{.*}} "-ftime-trace=f/ga.json" "-ftime-trace-granularity=0" +// LINK2: -cc1{{.*}} "-ftime-trace=f/gb.json" "-ftime-trace-granularity=0" -// RUN: %clang -### -ftime-trace=e -ftime-trace-granularity=0 -ftime-trace-verbose d/a.cpp d/b.c -o f/x -dumpdir f/ 2>&1 | FileCheck %s --check-prefix=LINK3 -// LINK3: -cc1{{.*}} "-ftime-trace=e{{/|\\\\}}a-{{[^.]*}}.json" "-ftime-trace-granularity=0" "-ftime-trace-verbose" -// LINK3: -cc1{{.*}} "-ftime-trace=e{{/|\\\\}}b-{{[^.]*}}.json" "-ftime-trace-granularity=0" "-ftime-trace-verbose" +// RUN: %clang -### -ftime-trace=e -ftime-trace-granularity=0 d/a.cpp d/b.c -o f/x -dumpdir f/ 2>&1 | FileCheck %s --check-prefix=LINK3 +// LINK3: -cc1{{.*}} "-ftime-trace=e{{/|\\\\}}a-{{[^.]*}}.json" "-ftime-trace-granularity=0" +// LINK3: -cc1{{.*}} "-ftime-trace=e{{/|\\\\}}b-{{[^.]*}}.json" "-ftime-trace-granularity=0" -// RUN: %clang -### -ftime-trace -ftime-trace=e -ftime-trace-granularity=1 -ftime-trace-verbose -xassembler d/a.cpp 2>&1 | \ +// RUN: %clang -### -ftime-trace -ftime-trace=e -ftime-trace-granularity=1 -xassembler d/a.cpp 2>&1 | \ // RUN: FileCheck %s --check-prefix=UNUSED // UNUSED: warning: argument unused during compilation: '-ftime-trace' // UNUSED-NEXT: warning: argument unused during compilation: '-ftime-trace=e' // UNUSED-NEXT: warning: argument unused during compilation: '-ftime-trace-granularity=1' -// UNUSED-NEXT: warning: argument unused during compilation: '-ftime-trace-verbose' // UNUSED-NOT: warning: template diff --git a/clang/test/Driver/loongarch-features.c b/clang/test/Driver/loongarch-features.c index 90634bbcf00358..3cdf3ba3d23e14 100644 --- a/clang/test/Driver/loongarch-features.c +++ b/clang/test/Driver/loongarch-features.c @@ -2,7 +2,7 @@ // RUN: %clang --target=loongarch64 -S -emit-llvm %s -o - | FileCheck %s --check-prefix=LA64 // LA32: "target-features"="+32bit" -// LA64: "target-features"="+64bit,+d,+f,+lsx,+ual" +// LA64: "target-features"="+64bit,+d,+f,+ual" int foo(void) { return 3; diff --git a/clang/test/Driver/loongarch-march.c b/clang/test/Driver/loongarch-march.c index 2d5b315d962a1e..9214130cd034fd 100644 --- a/clang/test/Driver/loongarch-march.c +++ b/clang/test/Driver/loongarch-march.c @@ -2,22 +2,10 @@ // RUN: FileCheck %s --check-prefix=CC1-LOONGARCH64 // RUN: %clang --target=loongarch64 -march=la464 -fsyntax-only %s -### 2>&1 | \ // RUN: FileCheck %s --check-prefix=CC1-LA464 -// RUN: %clang --target=loongarch64 -march=la64v1.0 -fsyntax-only %s -### 2>&1 | \ -// RUN: FileCheck %s --check-prefix=CC1-LA64V1P0 -// RUN: %clang --target=loongarch64 -march=la64v1.1 -fsyntax-only %s -### 2>&1 | \ -// RUN: FileCheck %s --check-prefix=CC1-LA64V1P1 -// RUN: %clang --target=loongarch64 -march=la664 -fsyntax-only %s -### 2>&1 | \ -// RUN: FileCheck %s --check-prefix=CC1-LA664 // RUN: %clang --target=loongarch64 -march=loongarch64 -S -emit-llvm %s -o - | \ // RUN: FileCheck %s --check-prefix=IR-LOONGARCH64 // RUN: %clang --target=loongarch64 -march=la464 -S -emit-llvm %s -o - | \ // RUN: FileCheck %s --check-prefix=IR-LA464 -// RUN: %clang --target=loongarch64 -march=la64v1.0 -S -emit-llvm %s -o - | \ -// RUN: FileCheck %s --check-prefix=IR-LA64V1P0 -// RUN: %clang --target=loongarch64 -march=la64v1.1 -S -emit-llvm %s -o - | \ -// RUN: FileCheck %s --check-prefix=IR-LA64V1P1 -// RUN: %clang --target=loongarch64 -march=la664 -S -emit-llvm %s -o - | \ -// RUN: FileCheck %s --check-prefix=IR-LA664 // CC1-LOONGARCH64: "-target-cpu" "loongarch64" // CC1-LOONGARCH64-NOT: "-target-feature" @@ -31,29 +19,8 @@ // CC1-LA464-NOT: "-target-feature" // CC1-LA464: "-target-abi" "lp64d" -// CC1-LA64V1P0: "-target-cpu" "loongarch64" -// CC1-LA64V1P0-NOT: "-target-feature" -// CC1-LA64V1P0: "-target-feature" "+64bit" "-target-feature" "+d" "-target-feature" "+lsx" "-target-feature" "+ual" -// CC1-LA64V1P0-NOT: "-target-feature" -// CC1-LA64V1P0: "-target-abi" "lp64d" - -// CC1-LA64V1P1: "-target-cpu" "loongarch64" -// CC1-LA64V1P1-NOT: "-target-feature" -// CC1-LA64V1P1: "-target-feature" "+64bit" "-target-feature" "+d" "-target-feature" "+lsx" "-target-feature" "+ual" "-target-feature" "+frecipe" -// CC1-LA64V1P1-NOT: "-target-feature" -// CC1-LA64V1P1: "-target-abi" "lp64d" - -// CC1-LA664: "-target-cpu" "la664" -// CC1-LA664-NOT: "-target-feature" -// CC1-LA664: "-target-feature" "+64bit" "-target-feature" "+f" "-target-feature" "+d" "-target-feature" "+lsx" "-target-feature" "+lasx" "-target-feature" "+ual" "-target-feature" "+frecipe" -// CC1-LA664-NOT: "-target-feature" -// CC1-LA664: "-target-abi" "lp64d" - // IR-LOONGARCH64: attributes #[[#]] ={{.*}}"target-cpu"="loongarch64" {{.*}}"target-features"="+64bit,+d,+f,+ual" // IR-LA464: attributes #[[#]] ={{.*}}"target-cpu"="la464" {{.*}}"target-features"="+64bit,+d,+f,+lasx,+lsx,+ual" -// IR-LA64V1P0: attributes #[[#]] ={{.*}}"target-cpu"="loongarch64" {{.*}}"target-features"="+64bit,+d,+lsx,+ual" -// IR-LA64V1P1: attributes #[[#]] ={{.*}}"target-cpu"="loongarch64" {{.*}}"target-features"="+64bit,+d,+frecipe,+lsx,+ual" -// IR-LA664: attributes #[[#]] ={{.*}}"target-cpu"="la664" {{.*}}"target-features"="+64bit,+d,+f,+frecipe,+lasx,+lsx,+ual" int foo(void) { return 3; diff --git a/clang/test/Driver/loongarch-mlasx.c b/clang/test/Driver/loongarch-mlasx.c index 87634ff5a9a40b..0b934f125c9e46 100644 --- a/clang/test/Driver/loongarch-mlasx.c +++ b/clang/test/Driver/loongarch-mlasx.c @@ -5,7 +5,7 @@ // RUN: %clang --target=loongarch64 -mno-lasx -fsyntax-only %s -### 2>&1 | \ // RUN: FileCheck %s --check-prefix=CC1-NOLASX // RUN: %clang --target=loongarch64 -mlasx -mno-lasx -fsyntax-only %s -### 2>&1 | \ -// RUN: FileCheck %s --check-prefix=CC1-LSX +// RUN: FileCheck %s --check-prefix=CC1-NOLASX // RUN: %clang --target=loongarch64 -mno-lasx -mlasx -fsyntax-only %s -### 2>&1 | \ // RUN: FileCheck %s --check-prefix=CC1-LASX // RUN: %clang --target=loongarch64 -mlsx -mlasx -fsyntax-only %s -### 2>&1 | \ @@ -18,7 +18,7 @@ // RUN: %clang --target=loongarch64 -mno-lasx -S -emit-llvm %s -o - | \ // RUN: FileCheck %s --check-prefix=IR-NOLASX // RUN: %clang --target=loongarch64 -mlasx -mno-lasx -S -emit-llvm %s -o - | \ -// RUN: FileCheck %s --check-prefix=IR-LSX +// RUN: FileCheck %s --check-prefix=IR-NOLASX // RUN: %clang --target=loongarch64 -mno-lasx -mlasx -S -emit-llvm %s -o - | \ // RUN: FileCheck %s --check-prefix=IR-LASX // RUN: %clang --target=loongarch64 -mlsx -mlasx -S -emit-llvm %s -o - | \ @@ -26,11 +26,9 @@ // RUN: %clang --target=loongarch64 -mlasx -mlsx -S -emit-llvm %s -o - | \ // RUN: FileCheck %s --check-prefix=IR-LASX -// CC1-LSX: "-target-feature" "+lsx" // CC1-LASX: "-target-feature" "+lsx" "-target-feature" "+lasx" // CC1-NOLASX: "-target-feature" "-lasx" -// IR-LSX: attributes #[[#]] ={{.*}}"target-features"="{{(.*,)?}}+lsx{{(,.*)?}}" // IR-LASX: attributes #[[#]] ={{.*}}"target-features"="{{(.*,)?}}+lasx{{(,.*)?}}" // IR-NOLASX: attributes #[[#]] ={{.*}}"target-features"="{{(.*,)?}}-lasx{{(,.*)?}}" diff --git a/clang/test/Driver/loongarch-msimd.c b/clang/test/Driver/loongarch-msimd.c index 49d298e1b2e3f0..cd463300c87470 100644 --- a/clang/test/Driver/loongarch-msimd.c +++ b/clang/test/Driver/loongarch-msimd.c @@ -75,9 +75,9 @@ // RUN: FileCheck %s --check-prefixes=LSX,LASX // RUN: %clang --target=loongarch64 -mlasx -mno-lasx -msimd=lasx -fsyntax-only %s -### 2>&1 | \ -// RUN: FileCheck %s --check-prefixes=LSX,NOLASX +// RUN: FileCheck %s --check-prefixes=NOLSX,NOLASX // RUN: %clang --target=loongarch64 -mno-lasx -msimd=lasx -fsyntax-only %s -### 2>&1 | \ -// RUN: FileCheck %s --check-prefixes=LSX,NOLASX +// RUN: FileCheck %s --check-prefixes=NOLSX,NOLASX // RUN: %clang --target=loongarch64 -mlasx -mno-lasx -mlsx -msimd=lasx -fsyntax-only %s -### 2>&1 | \ // RUN: FileCheck %s --check-prefixes=LSX,NOLASX diff --git a/clang/test/Driver/loongarch-msingle-float.c b/clang/test/Driver/loongarch-msingle-float.c index 4eb0865b53a59e..bd9b3e8a8c019d 100644 --- a/clang/test/Driver/loongarch-msingle-float.c +++ b/clang/test/Driver/loongarch-msingle-float.c @@ -11,10 +11,10 @@ // WARN: warning: ignoring '-mabi=lp64s' as it conflicts with that implied by '-msingle-float' (lp64f) // WARN: warning: ignoring '-mfpu=64' as it conflicts with that implied by '-msingle-float' (32) -// CC1: "-target-feature" "+f"{{.*}} "-target-feature" "-d" "-target-feature" "-lsx" +// CC1: "-target-feature" "+f"{{.*}} "-target-feature" "-d" // CC1: "-target-abi" "lp64f" -// IR: attributes #[[#]] ={{.*}}"target-features"="{{(.*,)?}}+f,{{(.*,)?}}-d,-lsx" +// IR: attributes #[[#]] ={{.*}}"target-features"="{{(.*,)?}}+f,{{(.*,)?}}-d" int foo(void) { return 3; diff --git a/clang/test/Driver/loongarch-msoft-float.c b/clang/test/Driver/loongarch-msoft-float.c index ebf27fb00e309e..0e5121ac84b4c1 100644 --- a/clang/test/Driver/loongarch-msoft-float.c +++ b/clang/test/Driver/loongarch-msoft-float.c @@ -11,10 +11,10 @@ // WARN: warning: ignoring '-mabi=lp64d' as it conflicts with that implied by '-msoft-float' (lp64s) // WARN: warning: ignoring '-mfpu=64' as it conflicts with that implied by '-msoft-float' (0) -// CC1: "-target-feature" "-f"{{.*}} "-target-feature" "-d" "-target-feature" "-lsx" +// CC1: "-target-feature" "-f"{{.*}} "-target-feature" "-d" // CC1: "-target-abi" "lp64s" -// IR: attributes #[[#]] ={{.*}}"target-features"="{{(.*,)?}}-d,{{(.*,)?}}-f,-lsx" +// IR: attributes #[[#]] ={{.*}}"target-features"="{{(.*,)?}}-d,{{(.*,)?}}-f{{(,.*)?}}" int foo(void) { return 3; diff --git a/clang/test/Driver/loongarch-mtune.c b/clang/test/Driver/loongarch-mtune.c index face12e1a1a82a..6f3f39e9bbd86a 100644 --- a/clang/test/Driver/loongarch-mtune.c +++ b/clang/test/Driver/loongarch-mtune.c @@ -8,11 +8,6 @@ // RUN: %clang --target=loongarch64 -mtune=la464 -S -emit-llvm %s -o - | \ // RUN: FileCheck %s --check-prefix=IRATTR -DCPU=la464 -// RUN: %clang --target=loongarch64 -mtune=la664 -fsyntax-only %s -### 2>&1 | \ -// RUN: FileCheck %s --check-prefix=CC1ARG -DCPU=la664 -// RUN: %clang --target=loongarch64 -mtune=la664 -S -emit-llvm %s -o - | \ -// RUN: FileCheck %s --check-prefix=IRATTR -DCPU=la664 - // RUN: %clang --target=loongarch64 -mtune=invalidcpu -fsyntax-only %s -### 2>&1 | \ // RUN: FileCheck %s --check-prefix=CC1ARG -DCPU=invalidcpu // RUN: not %clang --target=loongarch64 -mtune=invalidcpu -S -emit-llvm %s -o /dev/null 2>&1 | \ diff --git a/clang/test/Driver/nvlink-wrapper.c b/clang/test/Driver/nvlink-wrapper.c deleted file mode 100644 index fdda93f1f9cdc1..00000000000000 --- a/clang/test/Driver/nvlink-wrapper.c +++ /dev/null @@ -1,65 +0,0 @@ -// REQUIRES: x86-registered-target -// REQUIRES: nvptx-registered-target - -#if defined(X) -extern int y; -int foo() { return y; } - -int x = 0; -#elif defined(Y) -int y = 42; -#elif defined(Z) -int z = 42; -#elif defined(W) -int w = 42; -#elif defined(U) -extern int x; -extern int __attribute__((weak)) w; - -int bar() { - return x + w; -} -#else -extern int y; -int __attribute__((visibility("hidden"))) x = 999; -int baz() { return y + x; } -#endif - -// Create various inputs to test basic linking and LTO capabilities. Creating a -// CUDA binary requires access to the `ptxas` executable, so we just use x64. -// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -DX -o %t-x.o -// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -DY -o %t-y.o -// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -DZ -o %t-z.o -// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -DW -o %t-w.o -// RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -DU -o %t-u.o -// RUN: llvm-ar rcs %t-x.a %t-x.o -// RUN: llvm-ar rcs %t-y.a %t-y.o -// RUN: llvm-ar rcs %t-z.a %t-z.o -// RUN: llvm-ar rcs %t-w.a %t-w.o - -// -// Check that we forward any unrecognized argument to 'nvlink'. -// -// RUN: clang-nvlink-wrapper --dry-run -arch sm_52 %t-u.o -foo -o a.out 2>&1 \ -// RUN: | FileCheck %s --check-prefix=ARGS -// ARGS: nvlink{{.*}} -arch sm_52 -foo -o a.out [[INPUT:.+]].cubin - -// -// Check the symbol resolution for static archives. We expect to only link -// `libx.a` and `liby.a` because extern weak symbols do not extract and `libz.a` -// is not used at all. -// -// RUN: clang-nvlink-wrapper --dry-run %t-x.a %t-u.o %t-y.a %t-z.a %t-w.a \ -// RUN: -arch sm_52 -o a.out 2>&1 | FileCheck %s --check-prefix=LINK -// LINK: nvlink{{.*}} -arch sm_52 -o a.out [[INPUT:.+]].cubin {{.*}}-x-{{.*}}.cubin{{.*}}-y-{{.*}}.cubin - -// RUN: %clang -cc1 %s -triple nvptx64-nvidia-cuda -emit-llvm-bc -o %t.o - -// -// Check that the LTO interface works and properly preserves symbols used in a -// regular object file. -// -// RUN: clang-nvlink-wrapper --dry-run %t.o %t-u.o %t-y.a \ -// RUN: -arch sm_52 -o a.out 2>&1 | FileCheck %s --check-prefix=LTO -// LTO: ptxas{{.*}} -m64 -c [[PTX:.+]].s -O3 -arch sm_52 -o [[CUBIN:.+]].cubin -// LTO: nvlink{{.*}} -arch sm_52 -o a.out [[CUBIN]].cubin {{.*}}-u-{{.*}}.cubin {{.*}}-y-{{.*}}.cubin diff --git a/clang/test/Driver/print-supported-extensions-riscv.c b/clang/test/Driver/print-supported-extensions-riscv.c index 91f12b8416b2a4..1dc4580ec202ea 100644 --- a/clang/test/Driver/print-supported-extensions-riscv.c +++ b/clang/test/Driver/print-supported-extensions-riscv.c @@ -35,6 +35,7 @@ // CHECK-NEXT: za64rs 1.0 'Za64rs' (Reservation Set Size of at Most 64 Bytes) // CHECK-NEXT: zaamo 1.0 'Zaamo' (Atomic Memory Operations) // CHECK-NEXT: zabha 1.0 'Zabha' (Byte and Halfword Atomic Memory Operations) +// CHECK-NEXT: zacas 1.0 'Zacas' (Atomic Compare-And-Swap Instructions) // CHECK-NEXT: zalrsc 1.0 'Zalrsc' (Load-Reserved/Store-Conditional) // CHECK-NEXT: zama16b 1.0 'Zama16b' (Atomic 16-byte misaligned loads, stores and AMOs) // CHECK-NEXT: zawrs 1.0 'Zawrs' (Wait on Reservation Set) @@ -170,7 +171,6 @@ // CHECK-NEXT: Experimental extensions // CHECK-NEXT: zicfilp 1.0 'Zicfilp' (Landing pad) // CHECK-NEXT: zicfiss 1.0 'Zicfiss' (Shadow stack) -// CHECK-NEXT: zacas 1.0 'Zacas' (Atomic Compare-And-Swap Instructions) // CHECK-NEXT: zalasr 0.1 'Zalasr' (Load-Acquire and Store-Release Instructions) // CHECK-NEXT: smmpm 1.0 'Smmpm' (Machine-level Pointer Masking for M-mode) // CHECK-NEXT: smnpm 1.0 'Smnpm' (Machine-level Pointer Masking for next lower privilege mode) diff --git a/clang/test/Driver/ps4-ps5-runtime-flags.c b/clang/test/Driver/ps4-ps5-runtime-flags.c index 4b00aead6fe5c1..e75ba97948d234 100644 --- a/clang/test/Driver/ps4-ps5-runtime-flags.c +++ b/clang/test/Driver/ps4-ps5-runtime-flags.c @@ -40,5 +40,5 @@ // RUN: %clang -target x86_64-sie-ps5 -fcs-profile-generate %s -### 2>&1 | FileCheck --check-prefix=CHECK-PS5-PROFILE %s // RUN: %clang -target x86_64-sie-ps5 -fcs-profile-generate -fno-profile-generate %s -### 2>&1 | FileCheck --check-prefix=CHECK-PS5-NO-PROFILE %s // -// CHECK-PS5-PROFILE: "--dependent-lib=libclang_rt.profile_nosubmission.a" -// CHECK-PS5-NO-PROFILE-NOT: "--dependent-lib=libclang_rt.profile_nosubmission.a" +// CHECK-PS5-PROFILE: "--dependent-lib=libclang_rt.profile-x86_64_nosubmission.a" +// CHECK-PS5-NO-PROFILE-NOT: "--dependent-lib=libclang_rt.profile-x86_64_nosubmission.a" diff --git a/clang/test/Parser/cxx-template-decl.cpp b/clang/test/Parser/cxx-template-decl.cpp index 476341686a64b7..734438069b9ae6 100644 --- a/clang/test/Parser/cxx-template-decl.cpp +++ b/clang/test/Parser/cxx-template-decl.cpp @@ -297,7 +297,3 @@ namespace PR46231 { template<> int; // expected-error {{declaration does not declare anything}} template int; // expected-error {{declaration does not declare anything}} } - -namespace PR99933 { - void foo() { template int i; } // expected-error {{templates can only be declared in namespace or class scope}} -} diff --git a/clang/test/Preprocessor/embed_weird.cpp b/clang/test/Preprocessor/embed_weird.cpp index 90180e2d3cc704..6eb2923152f153 100644 --- a/clang/test/Preprocessor/embed_weird.cpp +++ b/clang/test/Preprocessor/embed_weird.cpp @@ -116,14 +116,6 @@ void f1() { } #endif -static_assert(_Generic( -#embed __FILE__ limit(1) - , int : 1, default : 0)); - -static_assert(alignof(typeof( -#embed __FILE__ limit(1) -)) == alignof(int)); - struct HasChar { signed char ch; }; diff --git a/clang/test/Preprocessor/init-loongarch.c b/clang/test/Preprocessor/init-loongarch.c index 771d56ffb1c1b9..182f904b765927 100644 --- a/clang/test/Preprocessor/init-loongarch.c +++ b/clang/test/Preprocessor/init-loongarch.c @@ -798,51 +798,24 @@ // LA64-FPU0-LP64S-NOT: #define __loongarch_single_float // LA64-FPU0-LP64S: #define __loongarch_soft_float 1 -/// Check __loongarch_arch{_tune/_frecipe}. +/// Check __loongarch_arch and __loongarch_tune. // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - | \ -// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la64v1.0 -DTUNE=loongarch64 %s +// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=loongarch64 %s // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 | \ // RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=loongarch64 %s // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la464 | \ // RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la464 -DTUNE=la464 %s // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -mtune=loongarch64 | \ -// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la64v1.0 -DTUNE=loongarch64 %s +// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=loongarch64 %s // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -mtune=la464 | \ -// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la64v1.0 -DTUNE=la464 %s +// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=la464 %s // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 -mtune=la464 | \ // RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=la464 %s // RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la464 -mtune=loongarch64 | \ // RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la464 -DTUNE=loongarch64 %s -// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la64v1.0 | \ -// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la64v1.0 -DTUNE=loongarch64 %s -// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la64v1.0 -Xclang -target-feature -Xclang -lsx | \ -// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=loongarch64 %s -// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la64v1.0 -Xclang -target-feature -Xclang +frecipe | \ -// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=la64v1.1 -DTUNE=loongarch64 %s -// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 -Xclang -target-feature -Xclang +lsx | \ -// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la64v1.0 -DTUNE=loongarch64 %s -// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la64v1.1 | \ -// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=la64v1.1 -DTUNE=loongarch64 %s -// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la64v1.1 -Xclang -target-feature -Xclang -frecipe | \ -// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la64v1.0 -DTUNE=loongarch64 %s -// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la64v1.1 -Xclang -target-feature -Xclang -lsx | \ -// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=loongarch64 -DTUNE=loongarch64 %s -// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 -Xclang -target-feature -Xclang +frecipe | \ -// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=loongarch64 -DTUNE=loongarch64 %s -// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 -Xclang -target-feature -Xclang +lsx -Xclang -target-feature -Xclang +frecipe | \ -// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=la64v1.1 -DTUNE=loongarch64 %s -// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la664 | \ -// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=la664 -DTUNE=la664 %s -// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -mtune=la664 | \ -// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=la64v1.0 -DTUNE=la664 %s -// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=loongarch64 -mtune=la664 | \ -// RUN: FileCheck --match-full-lines --check-prefix=ARCH-TUNE -DARCH=loongarch64 -DTUNE=la664 %s -// RUN: %clang --target=loongarch64 -x c -E -dM %s -o - -march=la664 -mtune=loongarch64 | \ -// RUN: FileCheck --match-full-lines --check-prefixes=ARCH-TUNE,FRECIPE -DARCH=la664 -DTUNE=loongarch64 %s // ARCH-TUNE: #define __loongarch_arch "[[ARCH]]" -// FRECIPE: #define __loongarch_frecipe 1 // ARCH-TUNE: #define __loongarch_tune "[[TUNE]]" // RUN: %clang --target=loongarch64 -mlsx -x c -E -dM %s -o - \ @@ -851,8 +824,6 @@ // RUN: | FileCheck --match-full-lines --check-prefix=MLSX %s // RUN: %clang --target=loongarch64 -mlsx -mno-lasx -x c -E -dM %s -o - \ // RUN: | FileCheck --match-full-lines --check-prefix=MLSX %s -// RUN: %clang --target=loongarch64 -mno-lasx -x c -E -dM %s -o - \ -// RUN: | FileCheck --match-full-lines --check-prefix=MLSX %s // RUN: %clang --target=loongarch64 -mno-lasx -mlsx -x c -E -dM %s -o - \ // RUN: | FileCheck --match-full-lines --check-prefix=MLSX %s // MLSX-NOT: #define __loongarch_asx @@ -861,12 +832,12 @@ // RUN: %clang --target=loongarch64 -mlasx -x c -E -dM %s -o - \ // RUN: | FileCheck --match-full-lines --check-prefix=MLASX %s +// RUN: %clang --target=loongarch64 -mno-lasx -mlasx -x c -E -dM %s -o - \ +// RUN: | FileCheck --match-full-lines --check-prefix=MLASX %s // RUN: %clang --target=loongarch64 -mlsx -mlasx -x c -E -dM %s -o - \ // RUN: | FileCheck --match-full-lines --check-prefix=MLASX %s // RUN: %clang --target=loongarch64 -mlasx -mlsx -x c -E -dM %s -o - \ // RUN: | FileCheck --match-full-lines --check-prefix=MLASX %s -// RUN: %clang --target=loongarch64 -mno-lasx -mlasx -x c -E -dM %s -o - \ -// RUN: | FileCheck --match-full-lines --check-prefix=MLASX %s // MLASX: #define __loongarch_asx 1 // MLASX: #define __loongarch_simd_width 256 // MLASX: #define __loongarch_sx 1 @@ -879,6 +850,8 @@ // RUN: | FileCheck --match-full-lines --check-prefix=MNO-LSX %s // RUN: %clang --target=loongarch64 -mno-lasx -mno-lsx -x c -E -dM %s -o - \ // RUN: | FileCheck --match-full-lines --check-prefix=MNO-LSX %s +// RUN: %clang --target=loongarch64 -mno-lasx -x c -E -dM %s -o - \ +// RUN: | FileCheck --match-full-lines --check-prefix=MNO-LSX %s // MNO-LSX-NOT: #define __loongarch_asx // MNO-LSX-NOT: #define __loongarch_simd_width // MNO-LSX-NOT: #define __loongarch_sx diff --git a/clang/test/Preprocessor/pragma_mc_func.c b/clang/test/Preprocessor/pragma_mc_func.c deleted file mode 100644 index f0d3e49e5dddca..00000000000000 --- a/clang/test/Preprocessor/pragma_mc_func.c +++ /dev/null @@ -1,23 +0,0 @@ -// RUN: not %clang --target=powerpc64-ibm-aix -ferr-pragma-mc-func-aix -fsyntax-only \ -// RUN: %s 2>&1 | FileCheck %s -#pragma mc_func asm_barrier {"60000000"} - -// CHECK: error: #pragma mc_func is not supported - -// Cases where no errors occur. -// RUN: %clang --target=powerpc64-ibm-aix -fno-err-pragma-mc-func-aix -fsyntax-only %s -// RUN: %clang --target=powerpc64-ibm-aix -ferr-pragma-mc-func-aix -fsyntax-only \ -// RUN: -fno-err-pragma-mc-func-aix %s -// RUN: %clang --target=powerpc64-ibm-aix -fsyntax-only %s -// RUN: %clang --target=powerpc64-ibm-aix -Werror=unknown-pragmas \ -// RUN: -fno-err-pragma-mc-func-aix -fsyntax-only %s - -// Cases where we have errors or warnings. -// RUN: not %clang --target=powerpc64le-unknown-linux-gnu \ -// RUN: -Werror=unknown-pragmas -fno-err-pragma-mc-func-aix -fsyntax-only %s 2>&1 | \ -// RUN: FileCheck --check-prefix=UNUSED %s -// RUN: %clang --target=powerpc64le-unknown-linux-gnu \ -// RUN: -fno-err-pragma-mc-func-aix -fsyntax-only %s 2>&1 | \ -// RUN: FileCheck --check-prefix=UNUSED %s - -// UNUSED: clang: warning: argument unused during compilation: '-fno-err-pragma-mc-func-aix' [-Wunused-command-line-argument] diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c index 72131108cb5f6a..fd718a126aaa79 100644 --- a/clang/test/Preprocessor/riscv-target-features.c +++ b/clang/test/Preprocessor/riscv-target-features.c @@ -86,6 +86,7 @@ // CHECK-NOT: __riscv_za64rs {{.*$}} // CHECK-NOT: __riscv_zaamo {{.*$}} // CHECK-NOT: __riscv_zabha {{.*$}} +// CHECK-NOT: __riscv_zacas {{.*$}} // CHECK-NOT: __riscv_zalrsc {{.*$}} // CHECK-NOT: __riscv_zama16b {{.*$}} // CHECK-NOT: __riscv_zawrs {{.*$}} @@ -181,7 +182,6 @@ // CHECK-NOT: __riscv_sspm{{.*$}} // CHECK-NOT: __riscv_ssqosid{{.*$}} // CHECK-NOT: __riscv_supm{{.*$}} -// CHECK-NOT: __riscv_zacas {{.*$}} // CHECK-NOT: __riscv_zalasr {{.*$}} // CHECK-NOT: __riscv_zfbfmin {{.*$}} // CHECK-NOT: __riscv_zicfilp {{.*$}} @@ -747,6 +747,14 @@ // RUN: -o - | FileCheck --check-prefix=CHECK-ZABHA-EXT %s // CHECK-ZABHA-EXT: __riscv_zabha 1000000{{$}} +// RUN: %clang --target=riscv32 \ +// RUN: -march=rv32ia_zacas1p0 -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-ZACAS-EXT %s +// RUN: %clang --target=riscv64 \ +// RUN: -march=rv64ia_zacas1p0 -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-ZACAS-EXT %s +// CHECK-ZACAS-EXT: __riscv_zacas 1000000{{$}} + // RUN: %clang --target=riscv32 \ // RUN: -march=rv32i_zalrsc1p0 -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZALRSC-EXT %s @@ -1618,14 +1626,6 @@ // CHECK-ZVKT-EXT: __riscv_zvkt 1000000{{$}} // Experimental extensions -// RUN: %clang --target=riscv32 -menable-experimental-extensions \ -// RUN: -march=rv32ia_zacas1p0 -E -dM %s \ -// RUN: -o - | FileCheck --check-prefix=CHECK-ZACAS-EXT %s -// RUN: %clang --target=riscv64 -menable-experimental-extensions \ -// RUN: -march=rv64ia_zacas1p0 -E -dM %s \ -// RUN: -o - | FileCheck --check-prefix=CHECK-ZACAS-EXT %s -// CHECK-ZACAS-EXT: __riscv_zacas 1000000{{$}} - // RUN: %clang --target=riscv32 -menable-experimental-extensions \ // RUN: -march=rv32i_zalasr0p1 -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZALASR-EXT %s diff --git a/clang/test/Sema/aarch64-neon-without-target-feature.cpp b/clang/test/Sema/aarch64-neon-without-target-feature.cpp deleted file mode 100644 index 0831eb7c754a73..00000000000000 --- a/clang/test/Sema/aarch64-neon-without-target-feature.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +dotprod -target-feature +fullfp16 -target-feature +fp16fml -target-feature +i8mm -target-feature +bf16 -verify -emit-llvm -o - %s - -// REQUIRES: aarch64-registered-target - -// This test is testing the diagnostics that Clang emits when compiling without '+neon'. - -#include - -void undefined(uint32x2_t v2i32, uint32x4_t v4i32, uint16x8_t v8i16, uint8x16_t v16i8, uint8x8_t v8i8, float32x2_t v2f32, float32x4_t v4f32, float16x4_t v4f16, float64x2_t v2f64, bfloat16x4_t v4bf16, __bf16 bf16, poly64_t poly64, poly64x2_t poly64x2) { - // dotprod - vdot_u32(v2i32, v8i8, v8i8); // expected-error {{always_inline function 'vdot_u32' requires target feature 'neon'}} - vdot_laneq_u32(v2i32, v8i8, v16i8, 1); // expected-error {{always_inline function 'vdot_u32' requires target feature 'neon'}} expected-error {{'__builtin_neon_splat_laneq_v' needs target feature neon}} - // fp16 - vceqz_f16(v4f16); // expected-error {{always_inline function 'vceqz_f16' requires target feature 'neon'}} - vrnd_f16(v4f16); // expected-error {{always_inline function 'vrnd_f16' requires target feature 'neon'}} - vmaxnm_f16(v4f16, v4f16); // expected-error {{always_inline function 'vmaxnm_f16' requires target feature 'neon'}} - vrndi_f16(v4f16); // expected-error {{always_inline function 'vrndi_f16' requires target feature 'neon'}} - // fp16fml depends on fp-armv8 - vfmlal_low_f16(v2f32, v4f16, v4f16); // expected-error {{always_inline function 'vfmlal_low_f16' requires target feature 'neon'}} - // i8mm - vmmlaq_s32(v4i32, v8i16, v8i16); // expected-error {{always_inline function 'vmmlaq_s32' requires target feature 'neon'}} - vusdot_laneq_s32(v2i32, v8i8, v8i16, 0); // expected-error {{always_inline function 'vusdot_s32' requires target feature 'neon'}} expected-error {{'__builtin_neon_splat_laneq_v' needs target feature neon}} - // bf16 - vbfdot_f32(v2f32, v4bf16, v4bf16); // expected-error {{always_inline function 'vbfdot_f32' requires target feature 'neon'}} - vcreate_bf16(10); - vdup_lane_bf16(v4bf16, 2); // expected-error {{'__builtin_neon_splat_lane_bf16' needs target feature bf16,neon}} - vdup_n_bf16(bf16); // expected-error {{always_inline function 'vdup_n_bf16' requires target feature 'neon'}} - vld1_bf16(0); // expected-error {{'__builtin_neon_vld1_bf16' needs target feature bf16,neon}} - vcvt_f32_bf16(v4bf16); // expected-error {{always_inline function 'vcvt_f32_bf16' requires target feature 'neon'}} - vcvt_bf16_f32(v4f32); // expected-error {{always_inline function 'vcvt_bf16_f32' requires target feature 'neon'}} - vmull_p64(poly64, poly64); // expected-error {{always_inline function 'vmull_p64' requires target feature 'neon'}} - vmull_high_p64(poly64x2, poly64x2); // expected-error {{always_inline function 'vmull_high_p64' requires target feature 'neon'}} - vtrn1_s8(v8i8, v8i8); // expected-error {{always_inline function 'vtrn1_s8' requires target feature 'neon'}} - vqabsq_s16(v8i16); // expected-error {{always_inline function 'vqabsq_s16' requires target feature 'neon'}} - vbslq_s16(v8i16, v8i16, v8i16);// expected-error {{always_inline function 'vbslq_s16' requires target feature 'neon'}} -} diff --git a/clang/test/Sema/atomic-ops.c b/clang/test/Sema/atomic-ops.c index 2405f804d0da54..9b82d82ff82697 100644 --- a/clang/test/Sema/atomic-ops.c +++ b/clang/test/Sema/atomic-ops.c @@ -124,31 +124,6 @@ _Static_assert(__atomic_always_lock_free(4, &i64), ""); _Static_assert(!__atomic_always_lock_free(8, &i32), ""); _Static_assert(__atomic_always_lock_free(8, &i64), ""); -// Validate use with fake pointers constants. This mechanism is used to allow -// validating atomicity of a given size and alignment. -_Static_assert(__atomic_is_lock_free(1, (void*)1), ""); -_Static_assert(__atomic_is_lock_free(1, (void*)-1), ""); -_Static_assert(__atomic_is_lock_free(4, (void*)2), ""); // expected-error {{not an integral constant expression}} -_Static_assert(__atomic_is_lock_free(4, (void*)-2), ""); // expected-error {{not an integral constant expression}} -_Static_assert(__atomic_is_lock_free(4, (void*)4), ""); -_Static_assert(__atomic_is_lock_free(4, (void*)-4), ""); - -_Static_assert(__atomic_always_lock_free(1, (void*)1), ""); -_Static_assert(__atomic_always_lock_free(1, (void*)-1), ""); -_Static_assert(!__atomic_always_lock_free(4, (void*)2), ""); -_Static_assert(!__atomic_always_lock_free(4, (void*)-2), ""); -_Static_assert(__atomic_always_lock_free(4, (void*)4), ""); -_Static_assert(__atomic_always_lock_free(4, (void*)-4), ""); - -// Ensure that "weird" constants don't cause trouble. -_Static_assert(__atomic_always_lock_free(1, "string"), ""); -_Static_assert(!__atomic_always_lock_free(2, "string"), ""); -_Static_assert(__atomic_always_lock_free(2, (int[2]){}), ""); -void dummyfn(); -_Static_assert(__atomic_always_lock_free(2, dummyfn) || 1, ""); - - - #define _AS1 __attribute__((address_space(1))) #define _AS2 __attribute__((address_space(2))) diff --git a/clang/test/Sema/patchable-function-entry-attr.cpp b/clang/test/Sema/patchable-function-entry-attr.cpp index bd4d57a7e30936..9134c851da588c 100644 --- a/clang/test/Sema/patchable-function-entry-attr.cpp +++ b/clang/test/Sema/patchable-function-entry-attr.cpp @@ -6,14 +6,9 @@ // RUN: %clang_cc1 -triple loongarch64 -fsyntax-only -verify=silence %s // RUN: %clang_cc1 -triple riscv32 -fsyntax-only -verify=silence %s // RUN: %clang_cc1 -triple riscv64 -fsyntax-only -verify=silence %s -// RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fsyntax-only -verify=silence %s -// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -fsyntax-only -verify=silence %s // RUN: %clang_cc1 -triple ppc64le -fsyntax-only -verify %s -// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fsyntax-only -verify=AIX %s -// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fsyntax-only -verify=AIX %s // silence-no-diagnostics -// AIX-error@+2 {{'patchable_function_entry' attribute is not yet supported on AIX}} // expected-warning@+1 {{unknown attribute 'patchable_function_entry' ignored}} [[gnu::patchable_function_entry(0)]] void f(); diff --git a/clang/test/Sema/ptrauth-indirect-goto.c b/clang/test/Sema/ptrauth-indirect-goto.c deleted file mode 100644 index 47bc76738d23b4..00000000000000 --- a/clang/test/Sema/ptrauth-indirect-goto.c +++ /dev/null @@ -1,18 +0,0 @@ -// RUN: %clang_cc1 -triple arm64e-apple-darwin -fsyntax-only -verify %s -fptrauth-indirect-gotos - -int f() { - static void *addrs[] = { &&l1, &&l2 }; - - static int diffs[] = { - &&l1 - &&l1, // expected-error{{subtraction of address-of-label expressions is not supported with ptrauth indirect gotos}} - &&l1 - &&l2 // expected-error{{subtraction of address-of-label expressions is not supported with ptrauth indirect gotos}} - }; - - int diff_32 = &&l1 - &&l2; // expected-error{{subtraction of address-of-label expressions is not supported with ptrauth indirect gotos}} - goto *(&&l1 + diff_32); // expected-error{{addition of address-of-label expressions is not supported with ptrauth indirect gotos}} - -l1: - return 0; -l2: - return 1; -} diff --git a/clang/test/SemaCXX/builtin_vectorelements.cpp b/clang/test/SemaCXX/builtin_vectorelements.cpp index b23675ea0ac6a7..59ff09ac72e42d 100644 --- a/clang/test/SemaCXX/builtin_vectorelements.cpp +++ b/clang/test/SemaCXX/builtin_vectorelements.cpp @@ -1,9 +1,7 @@ // RUN: %clang_cc1 -triple x86_64 -std=c++20 -fsyntax-only -verify -disable-llvm-passes %s -// RUN: %clang_cc1 -triple x86_64 -std=c++20 -fsyntax-only -verify -disable-llvm-passes -fexperimental-new-constant-interpreter %s // REQUIRES: aarch64-registered-target // RUN: %clang_cc1 -triple aarch64 -target-feature +sve -std=c++20 -fsyntax-only -verify -disable-llvm-passes %s -// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -std=c++20 -fsyntax-only -verify -disable-llvm-passes -fexperimental-new-constant-interpreter %s template using VecT __attribute__((vector_size(16))) = T; diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp index eafadb07b29e1e..5e189b758c61e9 100644 --- a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp +++ b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp @@ -9,12 +9,12 @@ #endif class A { - template CONST T wrong; // expected-error {{non-static data member 'wrong' cannot be declared as a template}} - template CONST T wrong_init = 5; // expected-error {{non-static data member 'wrong_init' cannot be declared as a template}} + template CONST T wrong; // expected-error {{member 'wrong' declared as a template}} + template CONST T wrong_init = 5; // expected-error {{member 'wrong_init' declared as a template}} template static CONST T right = T(100); template static CONST T right = 5; - template CONST int right; // expected-error {{non-static data member 'right' cannot be declared as a template}} - template CONST float right = 5; // expected-error {{non-static data member 'right' cannot be declared as a template}} + template CONST int right; // expected-error {{member 'right' declared as a template}} + template CONST float right = 5; // expected-error {{member 'right' declared as a template}} #ifdef PRECXX11 // expected-warning@-2 {{in-class initializer for static data member of type 'const float' is a GNU extension}} #else @@ -161,14 +161,14 @@ namespace non_const_init { #ifndef PRECXX11 namespace constexpred { class A { - template constexpr T wrong; // expected-error {{non-static data member 'wrong' cannot be declared as a template}} + template constexpr T wrong; // expected-error {{member 'wrong' declared as a template}} // expected-error@-1 {{declaration of constexpr static data member 'wrong' requires an initializer}} - template constexpr T wrong_init = 5; // expected-error {{non-static data member 'wrong_init' cannot be declared as a template}} + template constexpr T wrong_init = 5; // expected-error {{member 'wrong_init' declared as a template}} template static constexpr T right = T(100); template static constexpr T right = 5; - template constexpr int right; // expected-error {{non-static data member 'right' cannot be declared as a template}} + template constexpr int right; // expected-error {{member 'right' declared as a template}} // expected-error@-1 {{declaration of constexpr static data member 'right' requires an initializer}} - template constexpr float right = 5; // expected-error {{non-static data member 'right' cannot be declared as a template}} + template constexpr float right = 5; // expected-error {{member 'right' declared as a template}} template<> constexpr int right = 7; template<> constexpr float right; // expected-error {{declaration of constexpr static data member 'right' requires an initializer}} template static constexpr int right; // expected-error {{expected '<' after 'template'}} diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp index 5392573fcdb9d5..2193be03ad9a3e 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -110,8 +110,8 @@ struct Foo { template using Bar = Foo; // expected-note {{candidate template ignored: couldn't infer template argument 'X'}} \ - // expected-note {{implicit deduction guide declared as 'template requires __is_deducible(test9::Bar, Foo) Bar(Foo) -> Foo'}} \ - // expected-note {{implicit deduction guide declared as 'template requires __is_deducible(test9::Bar, Foo) Bar(const X (&)[sizeof(X)]) -> Foo'}} \ + // expected-note {{implicit deduction guide declared as 'template requires __is_deducible(test9::Bar, Foo) Bar(Foo) -> Foo'}} \ + // expected-note {{implicit deduction guide declared as 'template requires __is_deducible(test9::Bar, Foo) Bar(const type-parameter-0-0 (&)[sizeof(type-parameter-0-0)]) -> Foo'}} \ // expected-note {{candidate template ignored: constraints not satisfied [with X = int]}} \ // expected-note {{cannot deduce template arguments for 'Bar' from 'Foo'}} @@ -138,13 +138,13 @@ namespace test11 { struct A {}; template struct Foo { T c; }; template -using AFoo = Foo; // expected-note {{candidate template ignored: could not match 'Foo' against 'int'}} \ - // expected-note {{implicit deduction guide declared as 'template requires __is_deducible(test11::AFoo, Foo) AFoo(Foo) -> Foo'}} \ +using AFoo = Foo; // expected-note {{candidate template ignored: could not match 'Foo' against 'int'}} \ + // expected-note {{implicit deduction guide declared as 'template requires __is_deducible(test11::AFoo, Foo) AFoo(Foo) -> Foo'}} \ // expected-note {{candidate template ignored: constraints not satisfied [with Y = int]}} \ // expected-note {{cannot deduce template arguments for 'AFoo' from 'Foo'}} \ - // expected-note {{implicit deduction guide declared as 'template requires __is_deducible(test11::AFoo, Foo) AFoo(Y) -> Foo'}} \ + // expected-note {{implicit deduction guide declared as 'template requires __is_deducible(test11::AFoo, Foo) AFoo(type-parameter-0-0) -> Foo'}} \ // expected-note {{candidate function template not viable: requires 0 arguments, but 1 was provided}} \ - // expected-note {{implicit deduction guide declared as 'template requires __is_deducible(test11::AFoo, Foo) AFoo() -> Foo'}} + // expected-note {{implicit deduction guide declared as 'template requires __is_deducible(test11::AFoo, Foo) AFoo() -> Foo'}} AFoo s = {1}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'AFoo'}} } // namespace test11 @@ -211,9 +211,9 @@ template concept False = false; template using BFoo = AFoo; // expected-note {{candidate template ignored: constraints not satisfied [with V = int]}} \ // expected-note {{cannot deduce template arguments for 'BFoo' from 'Foo'}} \ - // expected-note {{implicit deduction guide declared as 'template requires __is_deducible(AFoo, Foo) && __is_deducible(test15::BFoo, Foo) BFoo(V *) -> Foo}} \ - // expected-note {{candidate template ignored: could not match 'Foo' against 'int *'}} \ - // expected-note {{template requires __is_deducible(AFoo, Foo) && __is_deducible(test15::BFoo, Foo) BFoo(Foo) -> Foo}} + // expected-note {{implicit deduction guide declared as 'template requires __is_deducible(AFoo, Foo) && __is_deducible(test15::BFoo, Foo) BFoo(type-parameter-0-0 *) -> Foo}} \ + // expected-note {{candidate template ignored: could not match 'Foo' against 'int *'}} \ + // expected-note {{template requires __is_deducible(AFoo, Foo) && __is_deducible(test15::BFoo, Foo) BFoo(Foo) -> Foo}} int i = 0; AFoo a1(&i); // OK, deduce Foo @@ -263,12 +263,12 @@ template requires False // expected-note {{because 'int' does not Foo(T) -> Foo; template -using Bar = Foo; // expected-note {{could not match 'Foo' against 'int'}} \ - // expected-note {{implicit deduction guide declared as 'template requires __is_deducible(test18::Bar, Foo) Bar(Foo) -> Foo'}} \ +using Bar = Foo; // expected-note {{could not match 'Foo' against 'int'}} \ + // expected-note {{implicit deduction guide declared as 'template requires __is_deducible(test18::Bar, Foo) Bar(Foo) -> Foo'}} \ // expected-note {{candidate template ignored: constraints not satisfied}} \ - // expected-note {{implicit deduction guide declared as 'template requires False && __is_deducible(test18::Bar, Foo) Bar(T) -> Foo'}} \ + // expected-note {{implicit deduction guide declared as 'template requires False && __is_deducible(test18::Bar, Foo) Bar(type-parameter-0-0) -> Foo'}} \ // expected-note {{candidate function template not viable}} \ - // expected-note {{implicit deduction guide declared as 'template requires __is_deducible(test18::Bar, Foo) Bar() -> Foo'}} + // expected-note {{implicit deduction guide declared as 'template requires __is_deducible(test18::Bar, Foo) Bar() -> Foo'}} Bar s = {1}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments}} } // namespace test18 @@ -296,8 +296,8 @@ class Foo {}; // Verify that template template type parameter TTP is referenced/used in the // template arguments of the RHS. template typename TTP> -using Bar = Foo>; // expected-note {{candidate template ignored: could not match 'Foo>' against 'int'}} \ - // expected-note {{implicit deduction guide declared as 'template