diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 10950b2243..fe9a01c697 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -156,6 +156,14 @@ jobs: build-dir: build github-token: ${{ secrets.GITHUB_TOKEN }} + # The extracted LLVM source tree ships its own .profraw test fixtures, + # in an older raw-profile version that llvm-profdata rejects. They are + # not ours, so drop them before the coverage step globs build/ for + # *.profraw. + - name: Prune third-party profraw + if: matrix.coverage + run: find build/third-party -name '*.profraw' -delete + - name: Process Coverage id: process-coverage if: matrix.coverage diff --git a/.github/workflows/ci-matrix.yml b/.github/workflows/ci-matrix.yml index d32e2ca145..f38f664598 100644 --- a/.github/workflows/ci-matrix.yml +++ b/.github/workflows/ci-matrix.yml @@ -42,11 +42,16 @@ jobs: standards: '23' main-entry-factors: | clang Coverage + # MSan builds an instrumented libc++ from the pinned LLVM sources, + # which only a recent Clang can compile, so keep it on the latest + # Clang; an older one (such as 20) fails to build it. ASan does not + # build libc++ (bootstrap builds it for MSan only), so it can stay + # distributed. latest-factors: | - clang UBSan + clang UBSan MSan factors: | gcc UBSan - clang ASan MSan + clang ASan apple-clang UBSan ASan build-types: | gcc: Release @@ -75,14 +80,8 @@ jobs: append-common-cxxflags: | clang: -gz=zstd extra-values: | - # libc++ runtimes: clang + (ASan or MSan) needs instrumented libc++ - # built separately from the main LLVM build - use-libcxx: {{and (ieq compiler 'clang') (or msan asan)}} - libcxx-runtimes: {{select (ne compiler 'msvc') "libcxx;libcxxabi" "libcxx"}} - llvm-runtimes: {{{select (ine use-libcxx 'true') libcxx-runtimes ""}}} - # LLVM build configuration - llvm-hash: dc4cef81d47c7bc4a3c4d58fbacf8a6359683fae + llvm-hash: 77e43ec11cd8fbe1de491118b54de9bba94510a8 llvm-short-hash: {{{substr llvm-hash 0 7}}} llvm-preset-build-type: {{{lowercase build-type}}} llvm-preset-os: {{select (ieq os 'windows') "win" "unix"}} diff --git a/share/mrdocs/headers/libc-stubs/new.h b/share/mrdocs/headers/libc-stubs/new.h index 8366be759f..55d503cc9c 100644 --- a/share/mrdocs/headers/libc-stubs/new.h +++ b/share/mrdocs/headers/libc-stubs/new.h @@ -12,29 +12,7 @@ #define MRDOCS_SHARE_HEADERS_LIBC_STUBS_NEW_H #if defined(_LIBCPP_ABI_VCRUNTIME) -namespace std { - enum class align_val_t : size_t {}; - struct nothrow_t { explicit nothrow_t() = default; }; - extern const std::nothrow_t nothrow; -} - -// Replaceable allocation functions -void* operator new ( std::size_t count ); -void* operator new[]( std::size_t count ); -void* operator new ( std::size_t count, std::align_val_t al ); -void* operator new[]( std::size_t count, std::align_val_t al ); - -// Replaceable non-throwing allocation functions -void* operator new ( std::size_t count, const std::nothrow_t& tag ); -void* operator new[]( std::size_t count, const std::nothrow_t& tag ); -void* operator new ( std::size_t count, std::align_val_t al, - const std::nothrow_t& tag ) noexcept; -void* operator new[]( std::size_t count, std::align_val_t al, - const std::nothrow_t& tag ) noexcept; - -// Non-allocating placement allocation functions -void* operator new ( std::size_t count, void* ptr ); -void* operator new[]( std::size_t count, void* ptr ); +#include #endif #endif // MRDOCS_SHARE_HEADERS_LIBC_STUBS_NEW_H diff --git a/share/mrdocs/headers/libc-stubs/stdalign.h b/share/mrdocs/headers/libc-stubs/stdalign.h index 886fbf6d38..0b0a9b16f7 100644 --- a/share/mrdocs/headers/libc-stubs/stdalign.h +++ b/share/mrdocs/headers/libc-stubs/stdalign.h @@ -11,9 +11,12 @@ #ifndef MRDOCS_SHARE_HEADERS_LIBC_STUBS_STDALIGN_H #define MRDOCS_SHARE_HEADERS_LIBC_STUBS_STDALIGN_H -// Convenience macros for alignment +// Convenience macros for alignment. In C++ alignas/alignof are keywords (and +// _Alignas/_Alignof are not valid), so only define them when compiling as C. +#ifndef __cplusplus #define alignas _Alignas #define alignof _Alignof +#endif // Macro constants indicating the presence of alignment features #define __alignas_is_defined 1 diff --git a/share/mrdocs/headers/libc-stubs/stdbool.h b/share/mrdocs/headers/libc-stubs/stdbool.h index 7dffbc9518..98ab9b70ca 100644 --- a/share/mrdocs/headers/libc-stubs/stdbool.h +++ b/share/mrdocs/headers/libc-stubs/stdbool.h @@ -11,10 +11,13 @@ #ifndef MRDOCS_SHARE_HEADERS_LIBC_STUBS_STDBOOL_H #define MRDOCS_SHARE_HEADERS_LIBC_STUBS_STDBOOL_H -// Convenience macros for boolean values +// Convenience macros for boolean values. In C++ these are keywords (and +// _Bool is not a type), so only define them when compiling as C. +#ifndef __cplusplus #define bool _Bool #define true 1 #define false 0 +#endif // Macro constant indicating the presence of boolean features #define __bool_true_false_are_defined 1 diff --git a/share/mrdocs/headers/libc-stubs/threads.h b/share/mrdocs/headers/libc-stubs/threads.h index 2e2ce49299..2718749851 100644 --- a/share/mrdocs/headers/libc-stubs/threads.h +++ b/share/mrdocs/headers/libc-stubs/threads.h @@ -73,8 +73,11 @@ int cnd_wait(cnd_t *cond, mtx_t *mtx); int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts); void cnd_destroy(cnd_t *cond); -// Thread-local storage +// Thread-local storage. In C++ thread_local is a keyword (and _Thread_local +// is not valid), so only define it when compiling as C. +#ifndef __cplusplus #define thread_local _Thread_local +#endif typedef void (*tss_dtor_t)(void *); typedef struct { diff --git a/share/mrdocs/headers/libc-stubs/vcruntime_new.h b/share/mrdocs/headers/libc-stubs/vcruntime_new.h new file mode 100644 index 0000000000..5626cc58ca --- /dev/null +++ b/share/mrdocs/headers/libc-stubs/vcruntime_new.h @@ -0,0 +1,41 @@ +// +// Licensed under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com) +// +// Official repository: https://github.com/cppalliance/mrdocs +// + +#ifndef MRDOCS_SHARE_HEADERS_LIBC_STUBS_VCRUNTIME_NEW_H +#define MRDOCS_SHARE_HEADERS_LIBC_STUBS_VCRUNTIME_NEW_H + +// libc++ includes this Microsoft runtime header (through <__new/align_val_t.h>) +// when built for the vcruntime ABI, so that std::align_val_t is layout-compatible +// with the platform. Provide just enough of it for parsing. +namespace std { + enum class align_val_t : size_t {}; + struct nothrow_t { explicit nothrow_t() = default; }; + extern const std::nothrow_t nothrow; +} + +// Replaceable allocation functions +void* operator new ( std::size_t count ); +void* operator new[]( std::size_t count ); +void* operator new ( std::size_t count, std::align_val_t al ); +void* operator new[]( std::size_t count, std::align_val_t al ); + +// Replaceable non-throwing allocation functions +void* operator new ( std::size_t count, const std::nothrow_t& tag ); +void* operator new[]( std::size_t count, const std::nothrow_t& tag ); +void* operator new ( std::size_t count, std::align_val_t al, + const std::nothrow_t& tag ) noexcept; +void* operator new[]( std::size_t count, std::align_val_t al, + const std::nothrow_t& tag ) noexcept; + +// Non-allocating placement allocation functions +void* operator new ( std::size_t count, void* ptr ); +void* operator new[]( std::size_t count, void* ptr ); + +#endif // MRDOCS_SHARE_HEADERS_LIBC_STUBS_VCRUNTIME_NEW_H diff --git a/src/lib/AST/ASTVisitor.cpp b/src/lib/AST/ASTVisitor.cpp index 89390556bc..c222e4aaac 100644 --- a/src/lib/AST/ASTVisitor.cpp +++ b/src/lib/AST/ASTVisitor.cpp @@ -32,11 +32,11 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include diff --git a/src/lib/AST/ClangHelpers.cpp b/src/lib/AST/ClangHelpers.cpp index 0b72ce1dd4..cef00e8047 100644 --- a/src/lib/AST/ClangHelpers.cpp +++ b/src/lib/AST/ClangHelpers.cpp @@ -6,6 +6,7 @@ // // Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) // Copyright (c) 2023 Krystian Stasiowski (sdkrystian@gmail.com) +// Copyright (c) 2026 Gennaro Prota (gennaro.prota@gmail.com) // // Official repository: https://github.com/cppalliance/mrdocs // @@ -13,9 +14,12 @@ #include #include #include +#include +#include #include -#include +#include #include +#include #include #include @@ -27,7 +31,7 @@ SubstituteConstraintExpressionWithoutSatisfaction( clang::Expr const* ConstrExpr) { clang::MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( - DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false, + DeclInfo.getDecl(), DeclInfo.getDeclContext(), /*Final=*/false, /*Innermost=*/std::nullopt, /*RelativeToPrimary=*/true, /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true, @@ -38,31 +42,48 @@ SubstituteConstraintExpressionWithoutSatisfaction( return ConstrExpr; } + // Clang's own `AreConstraintExpressionsEqual` wraps the calls to this + // helper in an `SFINAETrap`. MrDocs invokes the helper directly, so the + // trap lives here instead: it traps substitution errors and supplies the + // SFINAE context that `SubstConstraintExprWithoutSatisfaction` expects on + // the instantiation stack. clang::Sema::SFINAETrap const SFINAE(S, /*AccessCheckingSFINAE=*/false); - clang::Sema::InstantiatingTemplate Inst( - S, DeclInfo.getLocation(), - clang::Sema::InstantiatingTemplate::ConstraintNormalization{}, - const_cast(DeclInfo.getDecl()), clang::SourceRange{}); - if (Inst.isInvalid()) - { - return nullptr; - } - // Set up a dummy 'instantiation' scope in the case of reference to function // parameters that the surrounding function hasn't been instantiated yet. Note // this may happen while we're comparing two templates' constraint // equivalence. - clang::LocalInstantiationScope ScopeForParameters(S); - if (auto *FD = DeclInfo.getDecl()->getAsFunction()) - { - for (auto *PVD : FD->parameters()) + std::optional ScopeForParameters; + if (clang::NamedDecl const* ND = DeclInfo.getDecl(); + ND && ND->isFunctionOrFunctionTemplate()) + { + ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true); + clang::FunctionDecl const* FD = ND->getAsFunction(); + if (clang::FunctionTemplateDecl* Template = + FD->getDescribedFunctionTemplate(); + Template && Template->getInstantiatedFromMemberTemplate()) { - ScopeForParameters.InstantiatedLocal(PVD, PVD); + FD = Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl(); + } + for (auto* PVD : FD->parameters()) + { + if (ScopeForParameters->getInstantiationOfIfExists(PVD)) + { + continue; + } + if (!PVD->isParameterPack()) + { + ScopeForParameters->InstantiatedLocal(PVD, PVD); + continue; + } + // Map the parameter pack to a size-of-1 argument so its canonical + // type is used when comparing redeclarations for equivalence. + ScopeForParameters->MakeInstantiatedLocalArgPack(PVD); + ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD); } } - Optional ThisScope; + std::optional ThisScope; // See TreeTransform::RebuildTemplateSpecializationType. A context scope is // essential for having an injected class as the canonical type for a template @@ -71,13 +92,27 @@ SubstituteConstraintExpressionWithoutSatisfaction( // template specializations can be profiled to the same value, which makes it // possible that e.g. constraints involving C> and C are // perceived identical. - Optional ContextScope; - if (auto *RD = dyn_cast(DeclInfo.getDeclContext())) - { - ThisScope.emplace(S, const_cast(RD), clang::Qualifiers()); - ContextScope.emplace(S, const_cast(cast(RD)), - /*NewThisContext=*/false); - } + std::optional ContextScope; + clang::DeclContext const* DC = [&] { + if (!DeclInfo.getDecl()) + { + return DeclInfo.getDeclContext(); + } + return DeclInfo.getDecl()->getFriendObjectKind() + ? DeclInfo.getLexicalDeclContext() + : DeclInfo.getDeclContext(); + }(); + if (auto* RD = dyn_cast(DC)) + { + ThisScope.emplace( + S, const_cast(RD), clang::Qualifiers()); + ContextScope.emplace( + S, const_cast(cast(RD)), + /*NewThisContext=*/false); + } + clang::EnterExpressionEvaluationContext UnevaluatedContext( + S, clang::Sema::ExpressionEvaluationContext::Unevaluated, + clang::Sema::ReuseLambdaContextDecl); clang::ExprResult SubstConstr = S.SubstConstraintExprWithoutSatisfaction( const_cast(ConstrExpr), MLTAL); if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable()) @@ -472,18 +507,215 @@ isStaticFileLevelMember(clang::Decl const* D) return false; } +namespace { + +// The candidate locations at which to search for the documentation comment +// attached to `D`. Ported from Clang's file-local `getLocsForCommentSearch` +// (declaration path; the macro and Objective-C branches do not apply to +// MrDocs). We need the per-declaration lookup that `ASTContext` once exposed +// publicly as `getRawCommentForDeclNoCache`: that accessor is now private, and +// the public `getRawCommentForAnyRedecl` follows the redeclaration chain, +// which collapses the distinct comments of separate declarations into one. +llvm::SmallVector +locsForCommentSearch(clang::Decl const* D) +{ + // Documentation cannot be attached to implicit declarations, implicit + // instantiations, function parameters, or template parameters. + if (D->isImplicit()) + { + return {}; + } + if (clang::FunctionDecl const* FD = dyn_cast(D); + FD && FD->getTemplateSpecializationKind() == + clang::TSK_ImplicitInstantiation) + { + return {}; + } + if (clang::VarDecl const* VD = dyn_cast(D); + VD && VD->isStaticDataMember() && + VD->getTemplateSpecializationKind() == + clang::TSK_ImplicitInstantiation) + { + return {}; + } + if (clang::CXXRecordDecl const* CRD = dyn_cast(D); + CRD && CRD->getTemplateSpecializationKind() == + clang::TSK_ImplicitInstantiation) + { + return {}; + } + if (clang::ClassTemplateSpecializationDecl const* CTSD = + dyn_cast(D)) + { + clang::TemplateSpecializationKind const TSK = + CTSD->getSpecializationKind(); + if (TSK == clang::TSK_ImplicitInstantiation || + TSK == clang::TSK_Undeclared) + { + return {}; + } + } + if (clang::EnumDecl const* ED = dyn_cast(D); + ED && ED->getTemplateSpecializationKind() == + clang::TSK_ImplicitInstantiation) + { + return {}; + } + if (clang::TagDecl const* TD = dyn_cast(D); + TD && TD->isEmbeddedInDeclarator() && !TD->isCompleteDefinition()) + { + // A tag declaration (but not a definition) in the decl-specifier-seq + // of another declaration does not carry a comment. + return {}; + } + if (isa(D) || + isa(D) || + isa(D) || + isa(D)) + { + return {}; + } + + // Templated and typedef declarations use their starting location; other + // declarations, which often share a declarator list, use the location of + // the identifier. + clang::SourceLocation const baseLocation = + (isa(D) || + isa(D) || + isa(D)) + ? D->getBeginLoc() + : D->getLocation(); + + clang::SourceManager const& source = D->getASTContext().getSourceManager(); + llvm::SmallVector locations; + if (!D->getLocation().isMacroID()) + { + locations.emplace_back(baseLocation); + } + else + { + // For a declaration produced by a macro expansion, look first at the + // expansion site, then at the spelling location inside the macro. + clang::DeclContext const* declCtx = D->getDeclContext(); + if (!(declCtx && clang::Decl::castFromDeclContext(declCtx) + ->getLocation().isMacroID())) + { + locations.emplace_back(source.getExpansionLoc(baseLocation)); + } + locations.emplace_back(source.getSpellingLoc(D->getBeginLoc())); + } + return locations; +} + +// The documentation comment attached to `D` at `loc`, if any. Ported from +// Clang's `ASTContext::getRawCommentNoCacheImpl` (declaration path). +clang::RawComment const* +rawCommentAtLoc( + clang::Decl const* D, + clang::SourceLocation loc, + std::map const& commentsInFile) +{ + clang::ASTContext const& ctx = D->getASTContext(); + clang::SourceManager const& source = ctx.getSourceManager(); + clang::LangOptions const& langOpts = ctx.getLangOpts(); + if (loc.isInvalid() || !loc.isFileID() || commentsInFile.empty()) + { + return nullptr; + } + + std::pair const locDecomp = + source.getDecomposedLoc(loc); + auto commentBehind = commentsInFile.lower_bound(locDecomp.second); + + // A trailing comment attaches only to a field, enum constant, or variable, + // and only when it begins on the declaration's own line. + if (commentBehind != commentsInFile.end()) + { + clang::RawComment* candidate = commentBehind->second; + if ((candidate->isDocumentation() || + langOpts.CommentOpts.ParseAllComments) && + candidate->isTrailingComment() && + (isa(D) || isa(D) || + isa(D)) && + source.getLineNumber(locDecomp.first, locDecomp.second) == + ctx.Comments.getCommentBeginLine( + candidate, locDecomp.first, commentBehind->first)) + { + return candidate; + } + } + + // Otherwise use the comment immediately preceding the declaration. + if (commentBehind == commentsInFile.begin()) + { + return nullptr; + } + clang::RawComment* candidate = std::prev(commentBehind)->second; + if (!(candidate->isDocumentation() || + langOpts.CommentOpts.ParseAllComments) || + candidate->isTrailingComment()) + { + return nullptr; + } + + // Reject the comment if anything other than whitespace lies between it and + // the declaration. + bool invalid = false; + char const* buffer = source.getBufferData(locDecomp.first, &invalid).data(); + if (invalid) + { + return nullptr; + } + unsigned const commentEnd = ctx.Comments.getCommentEndOffset(candidate); + llvm::StringRef const between( + buffer + commentEnd, locDecomp.second - commentEnd); + if (between.find_last_of(";{}#@") != llvm::StringRef::npos) + { + return nullptr; + } + return candidate; +} + +// The documentation comment attached to `D` itself, without following its +// redeclaration chain. Reproduces the former public +// `ASTContext::getRawCommentForDeclNoCache` (see @ref locsForCommentSearch). +clang::RawComment const* +rawCommentForDecl(clang::Decl const* D) +{ + clang::ASTContext const& ctx = D->getASTContext(); + clang::RawComment const* result = nullptr; + for (clang::SourceLocation loc : locsForCommentSearch(D)) + { + clang::FileID const file = + ctx.getSourceManager().getDecomposedLoc(loc).first; + std::map const* commentsInFile = + file.isValid() ? ctx.Comments.getCommentsInFile(file) : nullptr; + if (commentsInFile && !commentsInFile->empty()) + { + if (clang::RawComment const* rc = + rawCommentAtLoc(D, loc, *commentsInFile)) + { + result = rc; + break; + } + } + } + return result; +} + +} // (anonymous) + clang::RawComment const* getDocumentation(clang::Decl const* D) { - clang::RawComment const* RC = - D->getASTContext().getRawCommentForDeclNoCache(D); + clang::RawComment const* RC = rawCommentForDecl(D); if (!RC) { auto const* TD = dyn_cast(D); MRDOCS_CHECK_OR(TD, nullptr); clang::NamedDecl const* ND = TD->getTemplatedDecl(); MRDOCS_CHECK_OR(ND, nullptr); - RC = ND->getASTContext().getRawCommentForDeclNoCache(ND); + RC = rawCommentForDecl(ND); } return RC; } diff --git a/src/lib/AST/MissingSymbolSink.hpp b/src/lib/AST/MissingSymbolSink.hpp index 87bbf04e5c..391d307bf5 100644 --- a/src/lib/AST/MissingSymbolSink.hpp +++ b/src/lib/AST/MissingSymbolSink.hpp @@ -423,16 +423,6 @@ class CollectingDiagConsumer : public clang::DiagnosticConsumer { Downstream_->EndSourceFile(); } - - - void - finish() override - { - if (Downstream_) - { - Downstream_->finish(); - } - } }; } // namespace mrdocs diff --git a/src/lib/MrDocsCompilationDatabase.cpp b/src/lib/MrDocsCompilationDatabase.cpp index 730c936b5e..c7aed4e237 100644 --- a/src/lib/MrDocsCompilationDatabase.cpp +++ b/src/lib/MrDocsCompilationDatabase.cpp @@ -18,8 +18,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -96,153 +96,153 @@ isValidMrDocsOption( if (optionMatchesAny(opt, // unknown options - clang::driver::options::OPT_UNKNOWN, + clang::options::OPT_UNKNOWN, // sanitizers - clang::driver::options::OPT_fsanitize_EQ, - clang::driver::options::OPT_fno_sanitize_EQ, - clang::driver::options::OPT_fsanitize_recover_EQ, - clang::driver::options::OPT_fno_sanitize_recover_EQ, - clang::driver::options::OPT_fsanitize_trap_EQ, - clang::driver::options::OPT_fno_sanitize_trap_EQ, - clang::driver::options::OPT_fsanitize_address_use_after_scope, - clang::driver::options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ, - clang::driver::options::OPT_fexperimental_sanitize_metadata_EQ_atomics, - clang::driver::options::OPT_fexperimental_sanitize_metadata_EQ_covered, - clang::driver::options::OPT_fexperimental_sanitize_metadata_EQ, - clang::driver::options::OPT_fgpu_sanitize, - clang::driver::options::OPT_fno_experimental_sanitize_metadata_EQ, - clang::driver::options::OPT_fno_gpu_sanitize, - clang::driver::options::OPT_fno_sanitize_address_globals_dead_stripping, - clang::driver::options::OPT_fno_sanitize_address_outline_instrumentation, - clang::driver::options::OPT_fno_sanitize_address_poison_custom_array_cookie, - clang::driver::options::OPT_fno_sanitize_address_use_after_scope, - clang::driver::options::OPT_fno_sanitize_address_use_odr_indicator, - clang::driver::options::OPT__SLASH_fno_sanitize_address_vcasan_lib, - clang::driver::options::OPT_fno_sanitize_cfi_canonical_jump_tables, - clang::driver::options::OPT_fno_sanitize_cfi_cross_dso, - clang::driver::options::OPT_fno_sanitize_coverage, - clang::driver::options::OPT_fno_sanitize_hwaddress_experimental_aliasing, - clang::driver::options::OPT_fno_sanitize_ignorelist, - clang::driver::options::OPT_fno_sanitize_link_cxx_runtime, - clang::driver::options::OPT_fno_sanitize_link_runtime, - clang::driver::options::OPT_fno_sanitize_memory_param_retval, - clang::driver::options::OPT_fno_sanitize_memory_track_origins, - clang::driver::options::OPT_fno_sanitize_memory_use_after_dtor, - clang::driver::options::OPT_fno_sanitize_minimal_runtime, - clang::driver::options::OPT_fno_sanitize_recover_EQ, - clang::driver::options::OPT_fno_sanitize_recover, - clang::driver::options::OPT_fno_sanitize_stable_abi, - clang::driver::options::OPT_fno_sanitize_stats, - clang::driver::options::OPT_fno_sanitize_thread_atomics, - clang::driver::options::OPT_fno_sanitize_thread_func_entry_exit, - clang::driver::options::OPT_fno_sanitize_thread_memory_access, - clang::driver::options::OPT_fno_sanitize_trap_EQ, - clang::driver::options::OPT_fno_sanitize_trap, - clang::driver::options::OPT_fno_sanitize_undefined_trap_on_error, - clang::driver::options::OPT_fno_sanitize_EQ, - clang::driver::options::OPT_sanitize_address_destructor_EQ, - clang::driver::options::OPT_fsanitize_address_field_padding, - clang::driver::options::OPT_fsanitize_address_globals_dead_stripping, - clang::driver::options::OPT_fsanitize_address_outline_instrumentation, - clang::driver::options::OPT_fsanitize_address_poison_custom_array_cookie, - clang::driver::options::OPT_sanitize_address_use_after_return_EQ, - clang::driver::options::OPT__SLASH_fsanitize_address_use_after_return, - clang::driver::options::OPT_fsanitize_address_use_after_scope, - clang::driver::options::OPT_fsanitize_address_use_odr_indicator, - clang::driver::options::OPT_fsanitize_cfi_canonical_jump_tables, - clang::driver::options::OPT_fsanitize_cfi_cross_dso, - clang::driver::options::OPT_fsanitize_cfi_icall_normalize_integers, - clang::driver::options::OPT_fsanitize_cfi_icall_generalize_pointers, - clang::driver::options::OPT_fsanitize_coverage_8bit_counters, - clang::driver::options::OPT_fsanitize_coverage_allowlist, - clang::driver::options::OPT_fsanitize_coverage_control_flow, - clang::driver::options::OPT_fsanitize_coverage_ignorelist, - clang::driver::options::OPT_fsanitize_coverage_indirect_calls, - clang::driver::options::OPT_fsanitize_coverage_inline_8bit_counters, - clang::driver::options::OPT_fsanitize_coverage_inline_bool_flag, - clang::driver::options::OPT_fsanitize_coverage_no_prune, - clang::driver::options::OPT_fsanitize_coverage_pc_table, - clang::driver::options::OPT_fsanitize_coverage_stack_depth, - clang::driver::options::OPT_fsanitize_coverage_trace_bb, - clang::driver::options::OPT_fsanitize_coverage_trace_cmp, - clang::driver::options::OPT_fsanitize_coverage_trace_div, - clang::driver::options::OPT_fsanitize_coverage_trace_gep, - clang::driver::options::OPT_fsanitize_coverage_trace_loads, - clang::driver::options::OPT_fsanitize_coverage_trace_pc_guard, - clang::driver::options::OPT_fsanitize_coverage_trace_pc, - clang::driver::options::OPT_fsanitize_coverage_trace_stores, - clang::driver::options::OPT_fsanitize_coverage_type, - clang::driver::options::OPT_fsanitize_coverage, - clang::driver::options::OPT_fsanitize_hwaddress_abi_EQ, - clang::driver::options::OPT_fsanitize_hwaddress_experimental_aliasing, - clang::driver::options::OPT_fsanitize_ignorelist_EQ, - clang::driver::options::OPT_fsanitize_link_cxx_runtime, - clang::driver::options::OPT_fsanitize_link_runtime, - clang::driver::options::OPT_fsanitize_memory_param_retval, - clang::driver::options::OPT_fsanitize_memory_track_origins_EQ, - clang::driver::options::OPT_fsanitize_memory_track_origins, - clang::driver::options::OPT_fsanitize_memory_use_after_dtor, - clang::driver::options::OPT_fsanitize_memtag_mode_EQ, - clang::driver::options::OPT_fsanitize_minimal_runtime, - clang::driver::options::OPT_fsanitize_recover_EQ, - clang::driver::options::OPT_fsanitize_recover, - clang::driver::options::OPT_fsanitize_stable_abi, - clang::driver::options::OPT_fsanitize_stats, - clang::driver::options::OPT_fsanitize_system_ignorelist_EQ, - clang::driver::options::OPT_fsanitize_thread_atomics, - clang::driver::options::OPT_fsanitize_thread_func_entry_exit, - clang::driver::options::OPT_fsanitize_thread_memory_access, - clang::driver::options::OPT_fsanitize_trap_EQ, - clang::driver::options::OPT_fsanitize_trap, - clang::driver::options::OPT_fsanitize_undefined_strip_path_components_EQ, - clang::driver::options::OPT_fsanitize_undefined_trap_on_error, - clang::driver::options::OPT__SLASH_fsanitize_EQ_address, - clang::driver::options::OPT_fsanitize_EQ, - clang::driver::options::OPT_shared_libsan, - clang::driver::options::OPT_static_libsan, - clang::driver::options::OPT_static_libsan, + clang::options::OPT_fsanitize_EQ, + clang::options::OPT_fno_sanitize_EQ, + clang::options::OPT_fsanitize_recover_EQ, + clang::options::OPT_fno_sanitize_recover_EQ, + clang::options::OPT_fsanitize_trap_EQ, + clang::options::OPT_fno_sanitize_trap_EQ, + clang::options::OPT_fsanitize_address_use_after_scope, + clang::options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ, + clang::options::OPT_fexperimental_sanitize_metadata_EQ_atomics, + clang::options::OPT_fexperimental_sanitize_metadata_EQ_covered, + clang::options::OPT_fexperimental_sanitize_metadata_EQ, + clang::options::OPT_fgpu_sanitize, + clang::options::OPT_fno_experimental_sanitize_metadata_EQ, + clang::options::OPT_fno_gpu_sanitize, + clang::options::OPT_fno_sanitize_address_globals_dead_stripping, + clang::options::OPT_fno_sanitize_address_outline_instrumentation, + clang::options::OPT_fno_sanitize_address_poison_custom_array_cookie, + clang::options::OPT_fno_sanitize_address_use_after_scope, + clang::options::OPT_fno_sanitize_address_use_odr_indicator, + clang::options::OPT__SLASH_fno_sanitize_address_vcasan_lib, + clang::options::OPT_fno_sanitize_cfi_canonical_jump_tables, + clang::options::OPT_fno_sanitize_cfi_cross_dso, + clang::options::OPT_fno_sanitize_coverage, + clang::options::OPT_fno_sanitize_hwaddress_experimental_aliasing, + clang::options::OPT_fno_sanitize_ignorelist, + clang::options::OPT_fno_sanitize_link_cxx_runtime, + clang::options::OPT_fno_sanitize_link_runtime, + clang::options::OPT_fno_sanitize_memory_param_retval, + clang::options::OPT_fno_sanitize_memory_track_origins, + clang::options::OPT_fno_sanitize_memory_use_after_dtor, + clang::options::OPT_fno_sanitize_minimal_runtime, + clang::options::OPT_fno_sanitize_recover_EQ, + clang::options::OPT_fno_sanitize_recover, + clang::options::OPT_fno_sanitize_stable_abi, + clang::options::OPT_fno_sanitize_stats, + clang::options::OPT_fno_sanitize_thread_atomics, + clang::options::OPT_fno_sanitize_thread_func_entry_exit, + clang::options::OPT_fno_sanitize_thread_memory_access, + clang::options::OPT_fno_sanitize_trap_EQ, + clang::options::OPT_fno_sanitize_trap, + clang::options::OPT_fno_sanitize_undefined_trap_on_error, + clang::options::OPT_fno_sanitize_EQ, + clang::options::OPT_sanitize_address_destructor_EQ, + clang::options::OPT_fsanitize_address_field_padding, + clang::options::OPT_fsanitize_address_globals_dead_stripping, + clang::options::OPT_fsanitize_address_outline_instrumentation, + clang::options::OPT_fsanitize_address_poison_custom_array_cookie, + clang::options::OPT_sanitize_address_use_after_return_EQ, + clang::options::OPT__SLASH_fsanitize_address_use_after_return, + clang::options::OPT_fsanitize_address_use_after_scope, + clang::options::OPT_fsanitize_address_use_odr_indicator, + clang::options::OPT_fsanitize_cfi_canonical_jump_tables, + clang::options::OPT_fsanitize_cfi_cross_dso, + clang::options::OPT_fsanitize_cfi_icall_normalize_integers, + clang::options::OPT_fsanitize_cfi_icall_generalize_pointers, + clang::options::OPT_fsanitize_coverage_8bit_counters, + clang::options::OPT_fsanitize_coverage_allowlist, + clang::options::OPT_fsanitize_coverage_control_flow, + clang::options::OPT_fsanitize_coverage_ignorelist, + clang::options::OPT_fsanitize_coverage_indirect_calls, + clang::options::OPT_fsanitize_coverage_inline_8bit_counters, + clang::options::OPT_fsanitize_coverage_inline_bool_flag, + clang::options::OPT_fsanitize_coverage_no_prune, + clang::options::OPT_fsanitize_coverage_pc_table, + clang::options::OPT_fsanitize_coverage_stack_depth, + clang::options::OPT_fsanitize_coverage_trace_bb, + clang::options::OPT_fsanitize_coverage_trace_cmp, + clang::options::OPT_fsanitize_coverage_trace_div, + clang::options::OPT_fsanitize_coverage_trace_gep, + clang::options::OPT_fsanitize_coverage_trace_loads, + clang::options::OPT_fsanitize_coverage_trace_pc_guard, + clang::options::OPT_fsanitize_coverage_trace_pc, + clang::options::OPT_fsanitize_coverage_trace_stores, + clang::options::OPT_fsanitize_coverage_type, + clang::options::OPT_fsanitize_coverage, + clang::options::OPT_fsanitize_hwaddress_abi_EQ, + clang::options::OPT_fsanitize_hwaddress_experimental_aliasing, + clang::options::OPT_fsanitize_ignorelist_EQ, + clang::options::OPT_fsanitize_link_cxx_runtime, + clang::options::OPT_fsanitize_link_runtime, + clang::options::OPT_fsanitize_memory_param_retval, + clang::options::OPT_fsanitize_memory_track_origins_EQ, + clang::options::OPT_fsanitize_memory_track_origins, + clang::options::OPT_fsanitize_memory_use_after_dtor, + clang::options::OPT_fsanitize_memtag_mode_EQ, + clang::options::OPT_fsanitize_minimal_runtime, + clang::options::OPT_fsanitize_recover_EQ, + clang::options::OPT_fsanitize_recover, + clang::options::OPT_fsanitize_stable_abi, + clang::options::OPT_fsanitize_stats, + clang::options::OPT_fsanitize_system_ignorelist_EQ, + clang::options::OPT_fsanitize_thread_atomics, + clang::options::OPT_fsanitize_thread_func_entry_exit, + clang::options::OPT_fsanitize_thread_memory_access, + clang::options::OPT_fsanitize_trap_EQ, + clang::options::OPT_fsanitize_trap, + clang::options::OPT_fsanitize_undefined_strip_path_components_EQ, + clang::options::OPT_fsanitize_undefined_trap_on_error, + clang::options::OPT__SLASH_fsanitize_EQ_address, + clang::options::OPT_fsanitize_EQ, + clang::options::OPT_shared_libsan, + clang::options::OPT_static_libsan, + clang::options::OPT_static_libsan, // diagnostic options - clang::driver::options::OPT_Diag_Group, - clang::driver::options::OPT_W_value_Group, - clang::driver::options::OPT__SLASH_wd, + clang::options::OPT_Diag_Group, + clang::options::OPT_W_value_Group, + clang::options::OPT__SLASH_wd, // language conformance options - clang::driver::options::OPT_pedantic_Group, - clang::driver::options::OPT__SLASH_permissive, - clang::driver::options::OPT__SLASH_permissive_, + clang::options::OPT_pedantic_Group, + clang::options::OPT__SLASH_permissive, + clang::options::OPT__SLASH_permissive_, // ignored options - clang::driver::options::OPT_cl_ignored_Group, - clang::driver::options::OPT_cl_ignored_Group, - clang::driver::options::OPT_clang_ignored_f_Group, - clang::driver::options::OPT_clang_ignored_gcc_optimization_f_Group, - clang::driver::options::OPT_clang_ignored_legacy_options_Group, - clang::driver::options::OPT_clang_ignored_m_Group, - clang::driver::options::OPT_flang_ignored_w_Group + clang::options::OPT_cl_ignored_Group, + clang::options::OPT_cl_ignored_Group, + clang::options::OPT_clang_ignored_f_Group, + clang::options::OPT_clang_ignored_gcc_optimization_f_Group, + clang::options::OPT_clang_ignored_legacy_options_Group, + clang::options::OPT_clang_ignored_m_Group, + clang::options::OPT_flang_ignored_w_Group #if 0 // input file options - clang::driver::options::OPT_INPUT, + clang::options::OPT_INPUT, // output file options - clang::driver::options::OPT_o, - clang::driver::options::OPT__SLASH_o, - clang::driver::options::OPT__SLASH_Fo, - clang::driver::options::OPT__SLASH_Fe, - clang::driver::options::OPT__SLASH_Fd, - clang::driver::options::OPT__SLASH_FA, - clang::driver::options::OPT__SLASH_Fa, - clang::driver::options::OPT__SLASH_Fi, - clang::driver::options::OPT__SLASH_FR, - clang::driver::options::OPT__SLASH_Fr, - clang::driver::options::OPT__SLASH_Fm, - clang::driver::options::OPT__SLASH_Fx, + clang::options::OPT_o, + clang::options::OPT__SLASH_o, + clang::options::OPT__SLASH_Fo, + clang::options::OPT__SLASH_Fe, + clang::options::OPT__SLASH_Fd, + clang::options::OPT__SLASH_FA, + clang::options::OPT__SLASH_Fa, + clang::options::OPT__SLASH_Fi, + clang::options::OPT__SLASH_FR, + clang::options::OPT__SLASH_Fr, + clang::options::OPT__SLASH_Fm, + clang::options::OPT__SLASH_Fx, #endif - // clang::driver::options::OPT__SLASH_TP - // clang::driver::options::OPT__SLASH_Tp - // clang::driver::options::OPT__SLASH_TC - // clang::driver::options::OPT__SLASH_Tc + // clang::options::OPT__SLASH_TP + // clang::options::OPT__SLASH_Tp + // clang::options::OPT__SLASH_TC + // clang::options::OPT__SLASH_Tc )) { return false; @@ -441,9 +441,9 @@ adjustCommandLine( // Clang option. This will discard any options that // affect warnings, are ignored, or turn warnings into // errors. - llvm::opt::OptTable const& opts_table = clang::driver::getDriverOptTable(); + llvm::opt::OptTable const& opts_table = clang::getDriverOptTable(); llvm::opt::Visibility visibility(is_clang_cl ? - clang::driver::options::CLOption : clang::driver::options::ClangOption); + clang::options::CLOption : clang::options::ClangOption); unsigned idx = 1; while (idx < cmdline.size()) { diff --git a/src/test/TestArgs.cpp b/src/test/TestArgs.cpp index 3dabba75f9..bf5d95b198 100644 --- a/src/test/TestArgs.cpp +++ b/src/test/TestArgs.cpp @@ -79,12 +79,12 @@ hideForeignOptions() const for (auto optionMap = llvm::cl::getRegisteredOptions(); auto& opt : optionMap) { - if (std::ranges::find(ours, opt.getValue()) != ours.end()) + if (std::ranges::find(ours, opt.second) != ours.end()) { - opt.getValue()->setHiddenFlag(llvm::cl::NotHidden); + opt.second->setHiddenFlag(llvm::cl::NotHidden); } else { - opt.getValue()->setHiddenFlag(llvm::cl::ReallyHidden); + opt.second->setHiddenFlag(llvm::cl::ReallyHidden); } } } diff --git a/src/tool/ToolArgs.cpp b/src/tool/ToolArgs.cpp index 229ea87f01..39b6e819b5 100644 --- a/src/tool/ToolArgs.cpp +++ b/src/tool/ToolArgs.cpp @@ -48,8 +48,8 @@ hideForeignOptions() auto optionMap = llvm::cl::getRegisteredOptions(); for(auto& opt : optionMap) { - opt.getValue()->setHiddenFlag( - std::ranges::find(oursOptions, opt.getValue()) != oursOptions.end() ? + opt.second->setHiddenFlag( + std::ranges::find(oursOptions, opt.second) != oursOptions.end() ? llvm::cl::NotHidden : llvm::cl::ReallyHidden); } diff --git a/test-files/golden-tests/javadoc/copydoc/param-types.xml b/test-files/golden-tests/javadoc/copydoc/param-types.xml index f63c1e6365..6f4f41fcfd 100644 --- a/test-files/golden-tests/javadoc/copydoc/param-types.xml +++ b/test-files/golden-tests/javadoc/copydoc/param-types.xml @@ -1328,7 +1328,7 @@ param-types.cpp param-types.cpp - 91 + 90 1 1 @@ -1552,7 +1552,7 @@ param-types.cpp param-types.cpp - 91 + 90 1 1 diff --git a/test-files/golden-tests/symbols/concept/requires-clause.xml b/test-files/golden-tests/symbols/concept/requires-clause.xml index ed2c11e5d2..5a24948122 100644 --- a/test-files/golden-tests/symbols/concept/requires-clause.xml +++ b/test-files/golden-tests/symbols/concept/requires-clause.xml @@ -8,8 +8,8 @@ //////////////////////////8= regular - kkH6jADpFuYV65W9qUpVvq20Cgs= - EBNjyD4nMb0o/Bpkztrno/0a+tA= + hK3x73/Ae4MeCnzwbIjl8ymPv3I= + bRI9ggyD7onLd/oP8QmcF0upggA= PmhXjCXUJYVnj/a7NhfjjSesyp0= 9JfSlZfEThLXiWTez3b8eT/AbZU= @@ -25,7 +25,7 @@ record - kkH6jADpFuYV65W9qUpVvq20Cgs= + hK3x73/Ae4MeCnzwbIjl8ymPv3I= regular //////////////////////////8= struct @@ -57,7 +57,7 @@ record - EBNjyD4nMb0o/Bpkztrno/0a+tA= + bRI9ggyD7onLd/oP8QmcF0upggA= regular //////////////////////////8= struct @@ -147,9 +147,9 @@ regular //////////////////////////8= normal - 3F1b/mMBJYuoAGH+KuNmPxsA7RI= - 9NLZvQibBhjkBj1mm77OINck29I= - vT2JiCSXaImfhLVMvGYQZ34RgLQ= + dMn9/neX/a+6Xf4Zj/trXAbJ3eE= + E8bM7kQ8fDu6ewzy2w4PlX3glWk= + waZu2K22py8SyW2+N49MTmkmhv8= identifier @@ -168,7 +168,7 @@ function - 3F1b/mMBJYuoAGH+KuNmPxsA7RI= + dMn9/neX/a+6Xf4Zj/trXAbJ3eE= regular //////////////////////////8= @@ -198,7 +198,7 @@ function - 9NLZvQibBhjkBj1mm77OINck29I= + E8bM7kQ8fDu6ewzy2w4PlX3glWk= regular //////////////////////////8= @@ -228,7 +228,7 @@ function - vT2JiCSXaImfhLVMvGYQZ34RgLQ= + waZu2K22py8SyW2+N49MTmkmhv8= regular //////////////////////////8= diff --git a/test-files/golden-tests/symbols/function/auto.xml b/test-files/golden-tests/symbols/function/auto.xml index 5d346ae6bf..fc11f081bf 100644 --- a/test-files/golden-tests/symbols/function/auto.xml +++ b/test-files/golden-tests/symbols/function/auto.xml @@ -17,7 +17,7 @@ auto.cpp auto.cpp - 7 + 6 1 1 diff --git a/test-files/golden-tests/symbols/function/function-template.xml b/test-files/golden-tests/symbols/function/function-template.xml index 86768c7dfd..1e9df9b6d7 100644 --- a/test-files/golden-tests/symbols/function/function-template.xml +++ b/test-files/golden-tests/symbols/function/function-template.xml @@ -315,7 +315,7 @@ function-template.cpp function-template.cpp 22 - 6 + 1 function @@ -346,7 +346,7 @@ function-template.cpp function-template.cpp 24 - 6 + 1 function diff --git a/test-files/golden-tests/symbols/record/dtor-overloads.xml b/test-files/golden-tests/symbols/record/dtor-overloads.xml index 017f166557..5d96e30f8f 100644 --- a/test-files/golden-tests/symbols/record/dtor-overloads.xml +++ b/test-files/golden-tests/symbols/record/dtor-overloads.xml @@ -73,8 +73,8 @@ destructor - x5T8zVxBVmg1ModTwgEAXcXWKDg= - uiH+ZSS+bYC5efGHgbdzlzXaV/o= + 3rUOGQX7PF0sqknq7fJH2ekGT1c= + BOrpr6vl5NDQn5Gj3sEhohxrWPU= identifier @@ -93,7 +93,7 @@ function - x5T8zVxBVmg1ModTwgEAXcXWKDg= + 3rUOGQX7PF0sqknq7fJH2ekGT1c= regular 5tUSuMtQqtYE49jBjSYSWp0DJAM= @@ -126,7 +126,7 @@ function - uiH+ZSS+bYC5efGHgbdzlzXaV/o= + BOrpr6vl5NDQn5Gj3sEhohxrWPU= regular 5tUSuMtQqtYE49jBjSYSWp0DJAM= diff --git a/third-party/recipes/llvm.json b/third-party/recipes/llvm.json index 1085723d71..d26e21358f 100644 --- a/third-party/recipes/llvm.json +++ b/third-party/recipes/llvm.json @@ -1,12 +1,12 @@ { "name": "llvm", - "version": "dc4cef81d47c7bc4a3c4d58fbacf8a6359683fae", + "version": "77e43ec11cd8fbe1de491118b54de9bba94510a8", "tags": [], "package_root_var": "LLVM_ROOT", "source": { "type": "archive", - "url": "https://github.com/llvm/llvm-project/archive/dc4cef81d47c7bc4a3c4d58fbacf8a6359683fae.zip", - "commit": "dc4cef81d47c7bc4a3c4d58fbacf8a6359683fae" + "url": "https://github.com/llvm/llvm-project/archive/77e43ec11cd8fbe1de491118b54de9bba94510a8.zip", + "commit": "77e43ec11cd8fbe1de491118b54de9bba94510a8" }, "dependencies": [], "build_type": "Release", diff --git a/util/bootstrap/src/recipes/builder.py b/util/bootstrap/src/recipes/builder.py index 9890f2fcd6..4382693742 100644 --- a/util/bootstrap/src/recipes/builder.py +++ b/util/bootstrap/src/recipes/builder.py @@ -32,8 +32,9 @@ def needs_libcxx_runtimes(sanitizer: str, compiler_id: str) -> bool: """ Check if libc++ runtimes need to be built with sanitizer instrumentation. - Only needed for clang (not apple-clang, gcc, msvc) with address or memory - sanitizers. UBSan and TSan do not require instrumented runtimes. + Only MemorySanitizer needs them, and only with Clang: MSan reports false + positives on any uninstrumented code, libc++ included. ASan works against + the normal libc++, and UBSan and TSan do not need instrumented runtimes. Args: sanitizer: Sanitizer name (e.g., "address", "asan", "memory", "msan"). @@ -45,7 +46,7 @@ def needs_libcxx_runtimes(sanitizer: str, compiler_id: str) -> bool: if not sanitizer: return False san = sanitizer_flag_name(sanitizer.lower()) - if san not in ("address", "memory"): + if san != "memory": return False if compiler_id.lower() != "clang": return False diff --git a/util/bootstrap/tests/test_builder.py b/util/bootstrap/tests/test_builder.py index da0ddc025c..06912bacb7 100644 --- a/util/bootstrap/tests/test_builder.py +++ b/util/bootstrap/tests/test_builder.py @@ -168,11 +168,11 @@ def test_sanitizer_plus_user_flags_merged(self, mock_win, mock_which, mock_ensur class TestNeedsLibcxxRuntimes(unittest.TestCase): """Test needs_libcxx_runtimes() guard function.""" - def test_clang_asan_needs_runtimes(self): - """Clang + ASan should trigger runtimes build.""" + def test_clang_asan_does_not_need_runtimes(self): + """Clang + ASan works against the normal libc++; no runtimes build.""" from src.recipes.builder import needs_libcxx_runtimes - self.assertTrue(needs_libcxx_runtimes("address", "Clang")) - self.assertTrue(needs_libcxx_runtimes("asan", "Clang")) + self.assertFalse(needs_libcxx_runtimes("address", "Clang")) + self.assertFalse(needs_libcxx_runtimes("asan", "Clang")) def test_clang_msan_needs_runtimes(self): """Clang + MSan should trigger runtimes build.""" diff --git a/util/bootstrap/tests/test_cache_keys.py b/util/bootstrap/tests/test_cache_keys.py index 8e2ee440a1..9fbb4f4620 100644 --- a/util/bootstrap/tests/test_cache_keys.py +++ b/util/bootstrap/tests/test_cache_keys.py @@ -24,7 +24,7 @@ ) -LLVM_HASH = "dc4cef81d47c7bc4a3c4d58fbacf8a6359683fae" +LLVM_HASH = "77e43ec11cd8fbe1de491118b54de9bba94510a8" class TestGenerateCacheKey(unittest.TestCase): @@ -38,7 +38,7 @@ def test_basic_release_key(self): build_type="Release", os_key="ubuntu:24.04", ) - self.assertEqual(key, "llvm-dc4cef8-release-ubuntu-24.04") + self.assertEqual(key, "llvm-77e43ec-release-ubuntu-24.04") def test_debug_build_type(self): """Build type should be lowercased.""" @@ -48,7 +48,7 @@ def test_debug_build_type(self): build_type="Debug", os_key="macos-15", ) - self.assertEqual(key, "llvm-dc4cef8-debug-macos-15") + self.assertEqual(key, "llvm-77e43ec-debug-macos-15") def test_relwithdebinfo_build_type(self): """RelWithDebInfo should be lowercased.""" @@ -58,7 +58,7 @@ def test_relwithdebinfo_build_type(self): build_type="RelWithDebInfo", os_key="ubuntu:24.04", ) - self.assertEqual(key, "llvm-dc4cef8-relwithdebinfo-ubuntu-24.04") + self.assertEqual(key, "llvm-77e43ec-relwithdebinfo-ubuntu-24.04") def test_colon_replaced_in_os_key(self): """Colons in os-key should be replaced with hyphens.""" @@ -89,7 +89,7 @@ def test_windows_os_key(self): build_type="Release", os_key="windows-2022", ) - self.assertEqual(key, "llvm-dc4cef8-release-windows-2022") + self.assertEqual(key, "llvm-77e43ec-release-windows-2022") def test_hash_truncated_to_7_chars(self): """Only first 7 characters of hash should be used.""" @@ -99,9 +99,9 @@ def test_hash_truncated_to_7_chars(self): build_type="Release", os_key="ubuntu:24.04", ) - self.assertIn("dc4cef8", key) + self.assertIn("77e43ec", key) # Full hash should NOT appear - self.assertNotIn("dc4cef81", key) + self.assertNotIn("77e43ec1", key) def test_clang_asan_suffix(self): """Clang + ASan should add -clang-{version}-ASan suffix.""" @@ -115,7 +115,7 @@ def test_clang_asan_suffix(self): sanitizer="address", ) self.assertEqual( - key, "llvm-dc4cef8-release-ubuntu-24.04-clang-19-ASan" + key, "llvm-77e43ec-release-ubuntu-24.04-clang-19-ASan" ) def test_clang_asan_short_name(self): @@ -130,7 +130,7 @@ def test_clang_asan_short_name(self): sanitizer="asan", ) self.assertEqual( - key, "llvm-dc4cef8-release-ubuntu-24.04-clang-19-ASan" + key, "llvm-77e43ec-release-ubuntu-24.04-clang-19-ASan" ) def test_clang_msan_suffix(self): @@ -146,7 +146,7 @@ def test_clang_msan_suffix(self): ) # MSan has no archive-sanitizer-str in CI template, so empty after last dash self.assertEqual( - key, "llvm-dc4cef8-release-ubuntu-24.04-clang-19-" + key, "llvm-77e43ec-release-ubuntu-24.04-clang-19-" ) def test_gcc_asan_no_suffix(self): @@ -160,7 +160,7 @@ def test_gcc_asan_no_suffix(self): compiler_version="14", sanitizer="address", ) - self.assertEqual(key, "llvm-dc4cef8-release-ubuntu-24.04") + self.assertEqual(key, "llvm-77e43ec-release-ubuntu-24.04") def test_clang_ubsan_no_suffix(self): """Clang + UBSan should NOT add suffix (only asan/msan trigger it).""" @@ -173,7 +173,7 @@ def test_clang_ubsan_no_suffix(self): compiler_version="19", sanitizer="undefined", ) - self.assertEqual(key, "llvm-dc4cef8-release-ubuntu-24.04") + self.assertEqual(key, "llvm-77e43ec-release-ubuntu-24.04") def test_clang_tsan_no_suffix(self): """Clang + TSan should NOT add suffix.""" @@ -186,7 +186,7 @@ def test_clang_tsan_no_suffix(self): compiler_version="19", sanitizer="thread", ) - self.assertEqual(key, "llvm-dc4cef8-release-ubuntu-24.04") + self.assertEqual(key, "llvm-77e43ec-release-ubuntu-24.04") def test_no_compiler_no_suffix(self): """No compiler specified should produce no suffix.""" @@ -197,7 +197,7 @@ def test_no_compiler_no_suffix(self): os_key="ubuntu:24.04", sanitizer="address", ) - self.assertEqual(key, "llvm-dc4cef8-release-ubuntu-24.04") + self.assertEqual(key, "llvm-77e43ec-release-ubuntu-24.04") def test_no_sanitizer_no_suffix(self): """No sanitizer should produce no suffix even with clang.""" @@ -209,7 +209,7 @@ def test_no_sanitizer_no_suffix(self): compiler="clang", compiler_version="19", ) - self.assertEqual(key, "llvm-dc4cef8-release-ubuntu-24.04") + self.assertEqual(key, "llvm-77e43ec-release-ubuntu-24.04") def test_non_llvm_recipe(self): """Cache keys should work for any recipe, not just llvm.""" @@ -308,7 +308,7 @@ def test_release_ubuntu_gcc(self): compiler_version="14", ) # gcc builds never get the compiler suffix - self.assertEqual(key, "llvm-dc4cef8-release-ubuntu-24.04") + self.assertEqual(key, "llvm-77e43ec-release-ubuntu-24.04") def test_release_ubuntu_clang_asan(self): """Clang ASan release on ubuntu:24.04.""" @@ -322,7 +322,7 @@ def test_release_ubuntu_clang_asan(self): sanitizer="address", ) self.assertEqual( - key, "llvm-dc4cef8-release-ubuntu-24.04-clang-19-ASan" + key, "llvm-77e43ec-release-ubuntu-24.04-clang-19-ASan" ) def test_release_windows(self): @@ -335,7 +335,7 @@ def test_release_windows(self): compiler="msvc", compiler_version="14.42", ) - self.assertEqual(key, "llvm-dc4cef8-release-windows-2022") + self.assertEqual(key, "llvm-77e43ec-release-windows-2022") def test_release_macos(self): """apple-clang release on macos-15.""" @@ -348,7 +348,7 @@ def test_release_macos(self): compiler_version="16", ) # apple-clang never gets suffix (only "clang" does) - self.assertEqual(key, "llvm-dc4cef8-release-macos-15") + self.assertEqual(key, "llvm-77e43ec-release-macos-15") if __name__ == "__main__":