From 397eb71dad205a19313f9afc23628f82a9f6c4cd Mon Sep 17 00:00:00 2001 From: ykiko Date: Sun, 2 Nov 2025 22:23:11 +0800 Subject: [PATCH] build: update llvm to 21.1.4 (#292) --- .github/workflows/xmake.yml | 12 +++++----- CMakeLists.txt | 11 ++++----- cmake/llvm_setup.cmake | 40 ++++++++++++++++++--------------- cmake/package.cmake | 2 +- config/prebuilt-llvm.json | 26 ++++++++++----------- include/AST/Resolver.h | 9 +++++++- include/AST/Semantic.h | 1 - include/Compiler/Diagnostic.h | 3 ++- include/Support/FileSystem.h | 8 +++---- src/AST/Resolver.cpp | 41 +++++++++++++++++++++------------- src/Compiler/Compilation.cpp | 27 +++++++++++++--------- src/Compiler/Diagnostic.cpp | 5 +++-- src/Compiler/Directive.cpp | 6 ++--- src/Compiler/Tidy.cpp | 28 ++++++++++------------- src/Feature/CodeCompletion.cpp | 5 ++++- src/Index/USRGeneration.cpp | 9 ++++---- tests/unit/Compiler/Tidy.cpp | 23 ++++++++++++++----- xmake.lua | 13 +++++------ 18 files changed, 154 insertions(+), 115 deletions(-) diff --git a/.github/workflows/xmake.yml b/.github/workflows/xmake.yml index feb417f9..623f67cd 100644 --- a/.github/workflows/xmake.yml +++ b/.github/workflows/xmake.yml @@ -34,10 +34,10 @@ jobs: - name: Setup xmake uses: xmake-io/github-action-setup-xmake@v1 with: - xmake-version: branch@master + xmake-version: 3.0.0 actions-cache-folder: ".xmake-cache" actions-cache-key: ${{ matrix.os }} - package-cache: true + package-cache: false package-cache-key: ${{ matrix.os }} build-cache: true build-cache-key: ${{ matrix.os }}-${{ matrix.build_type }} @@ -86,10 +86,10 @@ jobs: - name: Setup xmake uses: xmake-io/github-action-setup-xmake@v1 with: - xmake-version: branch@master + xmake-version: 3.0.0 actions-cache-folder: ".xmake-cache" actions-cache-key: ${{ matrix.os }} - package-cache: true + package-cache: false package-cache-key: ${{ matrix.os }} build-cache: true build-cache-key: ${{ matrix.os }}-${{ matrix.build_type }} @@ -127,10 +127,10 @@ jobs: - name: Setup xmake uses: xmake-io/github-action-setup-xmake@v1 with: - xmake-version: branch@master + xmake-version: 3.0.0 actions-cache-folder: ".xmake-cache" actions-cache-key: ${{ matrix.os }} - package-cache: true + package-cache: false package-cache-key: ${{ matrix.os }} build-cache: true build-cache-key: ${{ matrix.os }}-${{ matrix.build_type }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 887f1a41..cc7eafd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,12 +116,13 @@ target_link_libraries(clice PRIVATE clice-core) install(TARGETS clice RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) message(STATUS "Copying resource directory for development build") -file(COPY - "${LLVM_INSTALL_PATH}/lib/clang/20/" - DESTINATION "${PROJECT_BINARY_DIR}/lib/clang/20" +file( + COPY "${LLVM_INSTALL_PATH}/lib/clang" + DESTINATION "${PROJECT_BINARY_DIR}/lib" ) -install(DIRECTORY "${LLVM_INSTALL_PATH}/lib/clang/20/" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/clang/20" +install( + DIRECTORY "${LLVM_INSTALL_PATH}/lib/clang" + DESTINATION "${CMAKE_INSTALL_LIBDIR}" ) if(CLICE_ENABLE_TEST) diff --git a/cmake/llvm_setup.cmake b/cmake/llvm_setup.cmake index 73ee1895..f2aae0a6 100644 --- a/cmake/llvm_setup.cmake +++ b/cmake/llvm_setup.cmake @@ -3,12 +3,12 @@ include_guard() include(${CMAKE_CURRENT_LIST_DIR}/github.cmake) # Check if LLVM version is supported -function(check_llvm_version llvm_ver OUTPUT_VAR) - if((NOT DEFINED llvm_ver) OR (llvm_ver STREQUAL "")) +function(check_llvm_version LOCAL_LLVM_VERSION LLVM_VERSION OUTPUT_VAR) + if((NOT DEFINED LOCAL_LLVM_VERSION) OR (LOCAL_LLVM_VERSION STREQUAL "")) message(WARNING "LLVM version is not set.") set(${OUTPUT_VAR} FALSE PARENT_SCOPE) - elseif(NOT (llvm_ver VERSION_GREATER_EQUAL "20.1" AND llvm_ver VERSION_LESS "20.2")) - message(WARNING "Unsupported LLVM version: ${llvm_ver}. Only LLVM 20.1.x is supported.") + elseif(NOT (LOCAL_LLVM_VERSION VERSION_GREATER_EQUAL LLVM_VERSION)) + message(WARNING "Unsupported LLVM version: ${LOCAL_LLVM_VERSION}. Only LLVM ${LLVM_VERSION} is supported.") set(${OUTPUT_VAR} FALSE PARENT_SCOPE) else() set(${OUTPUT_VAR} TRUE PARENT_SCOPE) @@ -16,14 +16,14 @@ function(check_llvm_version llvm_ver OUTPUT_VAR) endfunction() # Look up LLVM version's corresponding commit SHA -function(lookup_commit llvm_ver OUTPUT_VAR) - set(LLVM_TAG "llvmorg-${llvm_ver}") +function(lookup_commit LLVM_VERSION OUTPUT_VAR) + set(LLVM_TAG "llvmorg-${LLVM_VERSION}") github_lookup_tag_commit("llvm" "llvm-project" ${LLVM_TAG} COMMIT_SHA) set(${OUTPUT_VAR} ${COMMIT_SHA} PARENT_SCOPE) endfunction() # Fetch private Clang header files from LLVM source -function(fetch_private_clang_files llvm_ver) +function(fetch_private_clang_files LLVM_VERSION) set(PRIVATE_CLANG_FILE_LIST "Sema/CoroutineStmtBuilder.h" "Sema/TypeLocBuilder.h" @@ -58,13 +58,13 @@ function(fetch_private_clang_files llvm_ver) message(WARNING "Required private clang files incomplete, fetching from llvm-project source...") # Get the commit SHA for this LLVM version - lookup_commit(${llvm_ver} LLVM_COMMIT) + lookup_commit(${LLVM_VERSION} LLVM_COMMIT) if(LLVM_COMMIT STREQUAL "NOTFOUND") - message(WARNING "Failed to lookup commit for LLVM ${llvm_ver}, skipping private clang files download") + message(WARNING "Failed to lookup commit for LLVM ${LLVM_VERSION}, skipping private clang files download") return() endif() - message(STATUS "LLVM ${llvm_ver} corresponds to commit ${LLVM_COMMIT}") + message(STATUS "LLVM ${LLVM_VERSION} corresponds to commit ${LLVM_COMMIT}") # Download missing files file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/include/clang") @@ -117,14 +117,14 @@ function(detect_llvm OUTPUT_VAR) endfunction() # Download and install prebuilt LLVM binaries with error checking -function(install_prebuilt_llvm llvm_ver) +function(install_prebuilt_llvm LLVM_VERSION) file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.llvm") # Determine platform-specific package name if(CMAKE_BUILD_TYPE STREQUAL "Debug") set(LLVM_BUILD_TYPE "debug") elseif(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") - set(LLVM_BUILD_TYPE "release") + set(LLVM_BUILD_TYPE "releasedbg") else() set(LLVM_BUILD_TYPE "release-lto") endif() @@ -146,7 +146,7 @@ function(install_prebuilt_llvm llvm_ver) # Download if file does not exist if(NOT EXISTS "${DOWNLOAD_PATH}") message(STATUS "Downloading prebuilt LLVM package: ${LLVM_PACKAGE}") - set(DOWNLOAD_URL "https://github.com/clice-io/llvm-binary/releases/download/${llvm_ver}/${LLVM_PACKAGE}") + set(DOWNLOAD_URL "https://github.com/clice-io/llvm-binary/releases/download/${LLVM_VERSION}/${LLVM_PACKAGE}") file(DOWNLOAD "${DOWNLOAD_URL}" "${DOWNLOAD_PATH}" STATUS DOWNLOAD_STATUS @@ -187,7 +187,11 @@ function(install_prebuilt_llvm llvm_ver) endfunction() # Main function to set up LLVM for the project -function(setup_llvm) +function(setup_llvm LLVM_VERSION) + if(NOT DEFINED LLVM_VERSION OR LLVM_VERSION STREQUAL "") + message(FATAL_ERROR "setup_llvm() requires a LLVM_VERSION argument (e.g., '21.1.4').") + endif() + # Use existing LLVM installation if path is already set if(DEFINED LLVM_INSTALL_PATH AND NOT LLVM_INSTALL_PATH STREQUAL "") message(STATUS "LLVM_INSTALL_PATH is set to ${LLVM_INSTALL_PATH}, using it directly.") @@ -197,14 +201,14 @@ function(setup_llvm) set(LLVM_VERSION_OK false) if (CMAKE_BUILD_TYPE STREQUAL "Release") # Try to detect system LLVM - detect_llvm(LLVM_VERSION) - check_llvm_version("${LLVM_VERSION}" LLVM_VERSION_OK) + detect_llvm(LOCAL_LLVM_VERSION) + check_llvm_version("${LOCAL_LLVM_VERSION}" "${LLVM_VERSION}" LLVM_VERSION_OK) endif() # Download prebuilt LLVM if system version is not suitable if(NOT LLVM_VERSION_OK) - set(LLVM_VERSION "20.1.5") - message(WARNING "System LLVM not found, version mismatch or incompatible build type, downloading prebuilt LLVM...") + message(WARNING "System LLVM not found, version mismatch or incompatible build type.") + message(WARNING "Downloading prebuilt LLVM ${LLVM_VERSION} ...") install_prebuilt_llvm("${LLVM_VERSION}") endif() diff --git a/cmake/package.cmake b/cmake/package.cmake index 8eddc9e4..b182b666 100644 --- a/cmake/package.cmake +++ b/cmake/package.cmake @@ -2,7 +2,7 @@ include_guard() include(${CMAKE_CURRENT_LIST_DIR}/llvm_setup.cmake) -setup_llvm() +setup_llvm("21.1.4") get_filename_component(LLVM_INSTALL_PATH "${LLVM_INSTALL_PATH}" ABSOLUTE) diff --git a/config/prebuilt-llvm.json b/config/prebuilt-llvm.json index 31f5861f..adb91a0b 100644 --- a/config/prebuilt-llvm.json +++ b/config/prebuilt-llvm.json @@ -3,9 +3,9 @@ "platform": "Windows", "build_type": "Release", "is_lto": false, - "filename": "x64-windows-msvc-release.7z", - "version": "20.1.5", - "sha256": "499b2e1e37c6dcccbc9d538cea5a222b552d599f54bb523adea8594d7837d02b" + "filename": "x64-windows-msvc-releasedbg.7z", + "version": "21.1.4", + "sha256": "324ec6b3634c32e1e999dae505f6ae83386f2a6b9ab96ac03ccfa029fb68b496" }, { "platform": "Windows", @@ -20,16 +20,16 @@ "build_type": "Debug", "is_lto": false, "filename": "x86_64-linux-gnu-debug.tar.xz", - "version": "20.1.5", - "sha256": "c04dddbe1d43d006f1ac52db01ab1776b8686fb8d4a1d13f2e07df37ae1ed47e" + "version": "21.1.4", + "sha256": "7bd68b14f147e291c9af8c32a8e78d57cc7b0e1f9c733df67e963e7062651f10" }, { "platform": "Linux", "build_type": "Release", "is_lto": false, - "filename": "x86_64-linux-gnu-release.tar.xz", - "version": "20.1.5", - "sha256": "5ff442434e9c1fbe67c9c2bd13284ef73590aa984bb74bcdfcec4404e5074b70" + "filename": "x86_64-linux-gnu-releasedbg.tar.xz", + "version": "21.1.4", + "sha256": "d4bf7ca08b07164637595ea3988330305e36354e466832a0fe7c4406fee3ac40" }, { "platform": "Linux", @@ -44,16 +44,16 @@ "build_type": "Debug", "is_lto": false, "filename": "arm64-macosx-apple-debug.tar.xz", - "version": "20.1.5", - "sha256": "899d15d0678c1099bccb41098355b938d3bb6dd20870763758b70db01b31a709" + "version": "21.1.4", + "sha256": "fd77af5a767ac7f4dc682602cfd6c84fbd5082021200e5cd8bd30379f4fd4a4d" }, { "platform": "macosx", "build_type": "Release", "is_lto": false, - "filename": "arm64-macosx-apple-release.tar.xz", - "version": "20.1.5", - "sha256": "47d89ed747b9946b4677ff902b5889b47d07b5cd92b0daf12db9abc6d284f955" + "filename": "arm64-macosx-apple-releasedbg.tar.xz", + "version": "21.1.4", + "sha256": "87f7667166496639ad60f02a22505296b09e458530a72d52b792ffb29d96a82b" }, { "platform": "macosx", diff --git a/include/AST/Resolver.h b/include/AST/Resolver.h index 34a02c9f..f0395e7d 100644 --- a/include/AST/Resolver.h +++ b/include/AST/Resolver.h @@ -45,7 +45,14 @@ public: } lookup_result lookup(const clang::DependentTemplateSpecializationType* type) { - return lookup(type->getQualifier(), type->getIdentifier()); + auto& template_name = type->getDependentTemplateName(); + auto identifier = template_name.getName().getIdentifier(); + if(identifier) { + return lookup(template_name.getQualifier(), identifier); + } else { + /// FIXME: Operators does't have a name. + return {}; + } } lookup_result lookup(const clang::DependentScopeDeclRefExpr* expr) { diff --git a/include/AST/Semantic.h b/include/AST/Semantic.h index c2ad3e46..394ac3aa 100644 --- a/include/AST/Semantic.h +++ b/include/AST/Semantic.h @@ -627,7 +627,6 @@ public: } case clang::NestedNameSpecifier::TypeSpec: - case clang::NestedNameSpecifier::TypeSpecWithTemplate: case clang::NestedNameSpecifier::Global: case clang::NestedNameSpecifier::Super: { break; diff --git a/include/Compiler/Diagnostic.h b/include/Compiler/Diagnostic.h index 48d38121..3cd90c0b 100644 --- a/include/Compiler/Diagnostic.h +++ b/include/Compiler/Diagnostic.h @@ -75,7 +75,8 @@ struct Diagnostic { /// The error message of this diagnostic. std::string message; - static DiagnosticCollector* create(std::shared_ptr> diagnostics); + static std::unique_ptr + create(std::shared_ptr> diagnostics); }; } // namespace clice diff --git a/include/Support/FileSystem.h b/include/Support/FileSystem.h index 28dfd4cd..fa22c1b1 100644 --- a/include/Support/FileSystem.h +++ b/include/Support/FileSystem.h @@ -39,15 +39,15 @@ using namespace llvm::sys::fs; inline std::string resource_dir = ""; -inline std::expected init_resource_dir(llvm::StringRef execute) { +inline std::expected init_resource_dir(llvm::StringRef execute) { llvm::SmallString<128> path; path::append(path, path::parent_path(execute), ".."); - path::append(path, "lib", "clang", "20"); + path::append(path, "lib", "clang", "21"); if(auto error = real_path(path, path)) { - return std::unexpected(error); + return std::unexpected(std::format("{}:{}", error, path.str())); } resource_dir = path.str(); - return std::expected(); + return std::expected(); } inline std::expected createTemporaryFile(llvm::StringRef prefix, diff --git a/src/AST/Resolver.cpp b/src/AST/Resolver.cpp index 2c4bafa0..dae22fa7 100644 --- a/src/AST/Resolver.cpp +++ b/src/AST/Resolver.cpp @@ -318,7 +318,14 @@ public: TD = TST->getTemplateName().getAsTemplateDecl(); args = TST->template_arguments(); } else if(auto DTST = type->getAs()) { - if(auto decl = preferred(lookup(DTST->getQualifier(), DTST->getIdentifier()))) { + auto& template_name = DTST->getDependentTemplateName(); + /// FIXME: operators does't have the name. + auto name = template_name.getName().getIdentifier(); + if(!name) { + return {}; + } + + if(auto decl = preferred(lookup(template_name.getQualifier(), name))) { TD = decl; args = DTST->template_arguments(); } @@ -371,9 +378,8 @@ public: return lookup(type, name); } - case clang::NestedNameSpecifier::TypeSpec: - case clang::NestedNameSpecifier::TypeSpecWithTemplate: { - /// If the prefix is `TypeSpec` or `TypeSpecWithTemplate`, it must be a type. + case clang::NestedNameSpecifier::TypeSpec: { + /// If the prefix is `TypeSpec`, it must be a type. return lookup(clang::QualType(NNS->getAsType(), 0), name); } @@ -597,18 +603,16 @@ public: /// Alloc::rebind::other auto prefix = - clang::NestedNameSpecifier::Create(context, nullptr, false, Alloc.getTypePtr()); + clang::NestedNameSpecifier::Create(context, nullptr, Alloc.getTypePtr()); auto rebind = sema.getPreprocessor().getIdentifierInfo("rebind"); auto DTST = context.getDependentTemplateSpecializationType( clang::ElaboratedTypeKeyword::None, - prefix, - rebind, + clang::DependentTemplateStorage(prefix, rebind, false), arguments); - prefix = - clang::NestedNameSpecifier::Create(context, prefix, true, DTST.getTypePtr()); + prefix = clang::NestedNameSpecifier::Create(context, prefix, DTST.getTypePtr()); auto other = sema.getPreprocessor().getIdentifierInfo("other"); auto DNT = context.getDependentNameType(clang::ElaboratedTypeKeyword::Typename, @@ -624,6 +628,7 @@ public: if(auto TST = Alloc->getAs()) { llvm::SmallVector replaceArguments = {T}; return context.getTemplateSpecializationType(TST->getTemplateName(), + replaceArguments, replaceArguments); } } @@ -721,8 +726,14 @@ public: arguments.push_back(arg.getArgument()); } + /// FIXME: operator does't have a name. + auto name = DTST->getDependentTemplateName().getName().getIdentifier(); + if(!name) { + return clang::QualType(); + } + /// Try resolve the hole. - if(auto result = hole(NNS, DTST->getIdentifier(), arguments); !result.isNull()) { + if(auto result = hole(NNS, name, arguments); !result.isNull()) { resolved.try_emplace(DTST, result); TLB.pushTrivial(context, result, {}); return result; @@ -730,7 +741,7 @@ public: /// The `lookup` may change the instantiation stack, save the current state. auto state = stack.state(); - if(auto decl = preferred(lookup(NNS, DTST->getIdentifier()))) { + if(auto decl = preferred(lookup(NNS, name))) { /// FIXME: Current implementation results in duplicated lookup. /// Cache the result of `lookup` to avoid duplicated lookup. if(auto TATD = llvm::dyn_cast(decl)) { @@ -746,10 +757,10 @@ public: } /// FIXME: figure out here. - auto result = context.getDependentTemplateSpecializationType(DTST->getKeyword(), - NNS, - DTST->getIdentifier(), - arguments); + auto result = context.getDependentTemplateSpecializationType( + DTST->getKeyword(), + clang::DependentTemplateStorage(NNS, name, false), + arguments); return TLB.push(result).getType(); } diff --git a/src/Compiler/Compilation.cpp b/src/Compiler/Compilation.cpp index 34bc016b..76a8b813 100644 --- a/src/Compiler/Compilation.cpp +++ b/src/Compiler/Compilation.cpp @@ -164,20 +164,24 @@ CompilationResult run_clang(CompilationParams& params, auto diagnostics = params.diagnostics ? params.diagnostics : std::make_shared>(); - auto diagnostic_collector = Diagnostic::create(diagnostics); - auto diagnostic_engine = - clang::CompilerInstance::createDiagnostics(*params.vfs, - new clang::DiagnosticOptions(), - diagnostic_collector); + auto diagnostic_consumer = Diagnostic::create(diagnostics); + + /// Temporary diagnostic engine, only used for command line parsing. + /// For compilation, we need to create a new diagnostic engine. See also + /// https://github.com/llvm/llvm-project/pull/139584#issuecomment-2920704282. + clang::DiagnosticOptions options; + auto diagnostic_engine = clang::CompilerInstance::createDiagnostics(*params.vfs, + options, + diagnostic_consumer.get(), + false); auto invocation = create_invocation(params, diagnostic_engine); if(!invocation) { return std::unexpected("Fail to create compilation invocation!"); } - auto instance = std::make_unique(); - instance->setInvocation(std::move(invocation)); - instance->setDiagnostics(diagnostic_engine.get()); + auto instance = std::make_unique(std::move(invocation)); + instance->createDiagnostics(*params.vfs, diagnostic_consumer.release(), true); if(auto remapping = clang::createVFSFromCompilerInvocation(instance->getInvocation(), instance->getDiagnostics(), @@ -215,7 +219,8 @@ CompilationResult run_clang(CompilationParams& params, if(params.clang_tidy) { tidy::TidyParams tidy_params; checker = tidy::configure(*instance, tidy_params); - diagnostic_collector->checker = checker.get(); + /// TODO: We should make the lifetime of diagnostic consumer more explicit. + static_cast(instance->getDiagnosticClient()).checker = checker.get(); } /// `BeginSourceFile` may create new preprocessor, so all operations related to preprocessor @@ -277,7 +282,7 @@ CompilationResult run_clang(CompilationParams& params, if(checker) { /// Avoid dangling pointer. - diagnostic_collector->checker = nullptr; + static_cast(instance->getDiagnosticClient()).checker = nullptr; } auto build_end = chrono::steady_clock::now().time_since_epoch(); @@ -292,7 +297,7 @@ CompilationResult run_clang(CompilationParams& params, .directives = std::move(directives), .path_cache = llvm::DenseMap(), .symbol_hash_cache = llvm::DenseMap(), - .diagnostics = diagnostics, + .diagnostics = std::move(diagnostics), .top_level_decls = std::move(top_level_decls), .build_at = chrono::duration_cast(build_at), .build_duration = chrono::duration_cast(build_end - build_start), diff --git a/src/Compiler/Diagnostic.cpp b/src/Compiler/Diagnostic.cpp index ee85a1cc..644fcd42 100644 --- a/src/Compiler/Diagnostic.cpp +++ b/src/Compiler/Diagnostic.cpp @@ -257,8 +257,9 @@ private: clang::SourceManager* src_mgr; }; -DiagnosticCollector* Diagnostic::create(std::shared_ptr> diagnostics) { - return new DiagnosticCollectorImpl(diagnostics); +std::unique_ptr + Diagnostic::create(std::shared_ptr> diagnostics) { + return std::make_unique(std::move(diagnostics)); } } // namespace clice diff --git a/src/Compiler/Directive.cpp b/src/Compiler/Directive.cpp index 688a21c7..eb3fc13e 100644 --- a/src/Compiler/Directive.cpp +++ b/src/Compiler/Directive.cpp @@ -123,9 +123,9 @@ public: auto fid = sm.getFileID(sm.getExpansionLoc(import_location)); auto& import = directives[fid].imports.emplace_back(); import.location = import_location; - for(auto& [name, location]: names) { - import.name += name->getName(); - import.name_locations.emplace_back(location); + for(auto name: names) { + import.name += name.getIdentifierInfo()->getName(); + import.name_locations.emplace_back(name.getLoc()); } } diff --git a/src/Compiler/Tidy.cpp b/src/Compiler/Tidy.cpp index 4b1b2a4f..4cb5fa03 100644 --- a/src/Compiler/Tidy.cpp +++ b/src/Compiler/Tidy.cpp @@ -11,27 +11,20 @@ /// https://github.com/llvm/llvm-project//blob/0865ecc5150b9a55ba1f9e30b6d463a66ac362a6/clang-tools-extra/clangd/TidyProvider.cpp #include "TidyImpl.h" - #include "AST/Utility.h" #include "Compiler/Diagnostic.h" #include "Compiler/Tidy.h" #include "Support/Logging.h" - -#include "clang-tidy/ClangTidyModuleRegistry.h" -#include "clang-tidy/ClangTidyOptions.h" -#include "clang-tidy/ClangTidyCheck.h" -#include "clang-tidy/ClangTidyDiagnosticConsumer.h" - -#include "clang/Frontend/CompilerInstance.h" - #include "llvm/ADT/StringSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Process.h" #include "llvm/Support/StringSaver.h" - -// Force the linker to link in Clang-tidy modules. -// clangd doesn't support the static analyzer. +#include "clang/Frontend/CompilerInstance.h" +#include "clang-tidy/ClangTidyOptions.h" +#include "clang-tidy/ClangTidyCheck.h" +#include "clang-tidy/ClangTidyModuleRegistry.h" +#include "clang-tidy/ClangTidyDiagnosticConsumer.h" #define CLANG_TIDY_DISABLE_STATIC_ANALYZER_CHECKS #include "clang-tidy/ClangTidyForceLinker.h" @@ -59,14 +52,16 @@ bool is_registered_tidy_check(llvm::StringRef check) { } std::optional is_fast_tidy_check(llvm::StringRef check) { - static auto& fast = *new llvm::StringMap{ + static auto fast = llvm::StringMap{ #define FAST(CHECK, TIME) {#CHECK, true}, #define SLOW(CHECK, TIME) {#CHECK, false}, // todo: move me to llvm toolchain headers. #include "TidyFastChecks.inc" }; - if(auto it = fast.find(check); it != fast.end()) + + if(auto it = fast.find(check); it != fast.end()) { return it->second; + } return std::nullopt; } @@ -388,7 +383,9 @@ std::unique_ptr configure(clang::CompilerInstance& instance, std::unique_ptr checker = std::make_unique( std::make_unique(tidy::ClangTidyGlobalOptions(), opts)); - checker->context.setDiagnosticsEngine(&instance.getDiagnostics()); + checker->context.setDiagnosticsEngine( + std::make_unique(instance.getDiagnosticOpts()), + &instance.getDiagnostics()); checker->context.setASTContext(&instance.getASTContext()); // TODO: is `file_name` always the file to check? checker->context.setCurrentFile(file_name); @@ -400,7 +397,6 @@ std::unique_ptr configure(clang::CompilerInstance& instance, check->registerPPCallbacks(instance.getSourceManager(), pp, pp); check->registerMatchers(&checker->finder); } - return checker; } diff --git a/src/Feature/CodeCompletion.cpp b/src/Feature/CodeCompletion.cpp index 7ba3ce82..edd18834 100644 --- a/src/Feature/CodeCompletion.cpp +++ b/src/Feature/CodeCompletion.cpp @@ -180,7 +180,10 @@ CompletionItemKind completion_kind(const clang::NamedDecl* decl) { case clang::Decl::ObjCCompatibleAlias: case clang::Decl::OutlinedFunction: - case clang::Decl::HLSLBuffer: { + case clang::Decl::HLSLBuffer: + case clang::Decl::OpenACCRoutine: + case clang::Decl::OpenACCDeclare: + case clang::Decl::HLSLRootSignature: { std::unreachable(); } } diff --git a/src/Index/USRGeneration.cpp b/src/Index/USRGeneration.cpp index bb875899..ef233646 100644 --- a/src/Index/USRGeneration.cpp +++ b/src/Index/USRGeneration.cpp @@ -206,9 +206,9 @@ void USRGenerator::VisitFunctionDecl(const FunctionDecl* D) { IsTemplate = true; Out << "@FT@"; VisitTemplateParameterList(FunTmpl->getTemplateParameters()); - if(auto RC = D->getTrailingRequiresClause()) { + if(auto& RC = D->getTrailingRequiresClause()) { Out << ":RC"; - AppendExprODRHash(RC, Out); + AppendExprODRHash(RC.ConstraintExpr, Out); } } else Out << "@F@"; @@ -580,7 +580,7 @@ void USRGenerator::VisitType(QualType T) { case BuiltinType::OCLSampler: Out << "@BT@OCLSampler"; break; #define SVE_TYPE(Name, Id, SingletonId) \ case BuiltinType::Id: Out << "@BT@" << #Name; break; -#include "clang/Basic/AArch64SVEACLETypes.def" +#include "clang/Basic/AArch64ACLETypes.def" #define PPC_VECTOR_TYPE(Name, Id, Size) \ case BuiltinType::Id: Out << "@BT@" << #Name; break; #include "clang/Basic/PPCTypes.def" @@ -828,7 +828,8 @@ void USRGenerator::VisitTemplateName(TemplateName Name) { if(auto DT = Name.getAsDependentTemplateName()) { Out << '^'; printQualifier(Out, LangOpts, DT->getQualifier()); - Out << ':' << DT->getIdentifier()->getName(); + /// FIXME: This may be operators. + Out << ':' << DT->getName().getIdentifier(); } } diff --git a/tests/unit/Compiler/Tidy.cpp b/tests/unit/Compiler/Tidy.cpp index a28935ec..070e1f38 100644 --- a/tests/unit/Compiler/Tidy.cpp +++ b/tests/unit/Compiler/Tidy.cpp @@ -1,19 +1,30 @@ #include "Test/Test.h" #include "Compiler/Tidy.h" +#include "Compiler/Compilation.h" namespace clice::testing { namespace { suite<"ClangTidy"> clang_tidy = [] { - test("is_fast_tidy_check") = [] { - expect(that % tidy::is_fast_tidy_check("readability-misleading-indentation")); - expect(that % tidy::is_fast_tidy_check("bugprone-unused-return-value")); + test("FastCheck") = [] { + expect(tidy::is_fast_tidy_check("readability-misleading-indentation")); + expect(tidy::is_fast_tidy_check("bugprone-unused-return-value")); // clangd/unittests/TidyProviderTests.cpp - expect(that % tidy::is_fast_tidy_check("misc-const-correctness") == false); - expect(that % tidy::is_fast_tidy_check("bugprone-suspicious-include") == true); - expect(that % tidy::is_fast_tidy_check("replay-preamble-check") == std::nullopt); + expect(tidy::is_fast_tidy_check("misc-const-correctness") == false); + expect(tidy::is_fast_tidy_check("bugprone-suspicious-include") == true); + expect(tidy::is_fast_tidy_check("replay-preamble-check") == std::nullopt); + }; + + test("Tidy") = [] { + CompilationParams params; + params.clang_tidy = true; + params.arguments = {"clang++", "main.cpp"}; + params.add_remapped_file("main.cpp", "int main() { return 0 }"); + auto unit = compile(params); + expect(unit.has_value()); + expect(!unit->diagnostics().empty()); }; }; diff --git a/xmake.lua b/xmake.lua index e1bd74a6..618a196a 100644 --- a/xmake.lua +++ b/xmake.lua @@ -1,4 +1,4 @@ -set_xmakever("3.0.3") +set_xmakever("3.0.0") set_project("clice") set_allowedplats("windows", "linux", "macosx") @@ -127,7 +127,7 @@ target("clice") end) after_build(function (target) - local res_dir = path.join(target:targetdir(), "lib/clang") + local res_dir = path.join(target:targetdir(), "../lib/clang") if not os.exists(res_dir) then local llvm_dir = target:dep("clice-core"):pkg("llvm"):installdir() os.vcp(path.join(llvm_dir, "lib/clang"), res_dir) @@ -146,8 +146,7 @@ target("unit_tests") after_load(function (target) target:set("runargs", - "--test-dir=" .. path.absolute("tests/data"), - "--resource-dir=" .. path.join(target:dep("clice-core"):pkg("llvm"):installdir(), "lib/clang/20") + "--test-dir=" .. path.absolute("tests/data") ) end) @@ -169,7 +168,6 @@ target("integration_tests") "--log-cli-level=INFO", "-s", "tests/integration", "--executable=" .. target:dep("clice"):targetfile(), - "--resource-dir=" .. path.join(target:pkg("llvm"):installdir(), "lib/clang/20"), } local opt = {envs = envs, curdir = os.projectdir()} os.vrunv(uv.program, argv, opt) @@ -271,8 +269,9 @@ package("clice-llvm") local info = json.loadfile("./config/prebuilt-llvm.json") for _, info in ipairs(info) do - if get_config("mode") == info.build_type:lower() - and get_config("plat") == info.platform:lower() + if info.platform:lower() == get_config("plat") + and (info.build_type:lower() == get_config("mode") + or info.build_type:lower() == "release" and get_config("mode") == "releasedbg") and (info.is_lto == has_config("release")) then package:add("urls", format("https://github.com/clice-io/llvm-binary/releases/download/%s/%s", info.version, info.filename)) package:add("versions", info.version, info.sha256)