[clang] [Serialization] Remove getMacroID (PR #127413)
https://github.com/ChuanqiXu9 approved this pull request. https://github.com/llvm/llvm-project/pull/127413 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Fix] Speedup -Wunsafe-buffer-usage when using clang modules. (PR #127161)
@@ -2633,7 +2646,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings( SourceLocation()) || (!Diags.isIgnored(diag::warn_unsafe_buffer_libc_call, SourceLocation()) && S.getLangOpts().CPlusPlus /* only warn about libc calls in C++ */)) { -CallableVisitor(CallAnalyzers).TraverseTranslationUnitDecl(TU); +CallableVisitor(CallAnalyzers, TU->getOwningModuleID()).TraverseTranslationUnitDecl(TU); ChuanqiXu9 wrote: ModuleID is implementation detailed that users shouldn't use. Let's use owning module if possible. https://github.com/llvm/llvm-project/pull/127161 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [libcxx] [llvm] [libc++][ranges] P2542R8: Implement `views::concat` (PR #120920)
https://github.com/changkhothuychung updated https://github.com/llvm/llvm-project/pull/120920 error: too big or took too long to generate ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Feat] Allow Finding across only parts of an AST. (PR #127423)
https://github.com/matts1 created https://github.com/llvm/llvm-project/pull/127423 This is relevant for clang modules, as they are imported into the AST, but are actually part of a different TU. It can result in hundreds of milliseconds of additional time to also traverse the AST of these modules, and often for no benefit, as they are frequently already traversed in their own TU. >From fb532e74460c9c6e5830a5a69e1e85aacdb6e358 Mon Sep 17 00:00:00 2001 From: Matt Stark Date: Mon, 17 Feb 2025 12:18:12 +1100 Subject: [PATCH] [Feat] Allow Finding across only parts of an AST. This is relevant for clang modules, as they are imported into the AST, but are actually part of a different TU. It can result in hundreds of milliseconds of additional time to also traverse the AST of these modules, and often for no benefit, as they are frequently already traversed in their own TU. --- clang/include/clang/ASTMatchers/ASTMatchFinder.h | 7 +++ clang/lib/ASTMatchers/ASTMatchFinder.cpp | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/ASTMatchers/ASTMatchFinder.h b/clang/include/clang/ASTMatchers/ASTMatchFinder.h index a387d9037b7da..62d42d9604eff 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchFinder.h +++ b/clang/include/clang/ASTMatchers/ASTMatchFinder.h @@ -139,6 +139,13 @@ class MatchFinder { /// /// It prints a report after match. std::optional CheckProfiling; + +/// Whether to traverse a Decl. This is relevant for clang modules, as they +/// are imported into the AST, but are actually part of a different TU. +/// It can result in hundreds of milliseconds of additional time to also +/// traverse the AST of these modules, and often for no benefit, as they +/// are frequently already traversed in their own TU. +std::optional> ShouldTraverseDecl; }; MatchFinder(MatchFinderOptions Options = MatchFinderOptions()); diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp index 3d01a70395a9b..365ffed7f9471 100644 --- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp @@ -1443,7 +1443,7 @@ bool MatchASTVisitor::objcClassIsDerivedFrom( } bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) { - if (!DeclNode) { + if (!DeclNode || (Options.ShouldTraverseDecl && !(*Options.ShouldTraverseDecl)(DeclNode))) { return true; } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Feat] Allow Finding across only parts of an AST. (PR #127423)
github-actions[bot] wrote: Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using `@` followed by their GitHub username. If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the [LLVM GitHub User Guide](https://llvm.org/docs/GitHub.html). You can also ask questions in a comment on this PR, on the [LLVM Discord](https://discord.com/invite/xS7Z362) or on the [forums](https://discourse.llvm.org/). https://github.com/llvm/llvm-project/pull/127423 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [libcxx] [llvm] [libc++][ranges] P2542R8: Implement `views::concat` (PR #120920)
@@ -0,0 +1,644 @@ +// -*- C++ -*- +//===--===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef _LIBCPP___RANGES_CONCAT_VIEW_H +#define _LIBCPP___RANGES_CONCAT_VIEW_H + +#include <__algorithm/ranges_find_if.h> +#include <__assert> +#include <__concepts/common_reference_with.h> +#include <__concepts/constructible.h> +#include <__concepts/convertible_to.h> +#include <__concepts/copyable.h> +#include <__concepts/derived_from.h> +#include <__concepts/equality_comparable.h> +#include <__concepts/swappable.h> +#include <__config> +#include <__functional/bind_back.h> +#include <__functional/invoke.h> +#include <__functional/reference_wrapper.h> +#include <__iterator/concepts.h> +#include <__iterator/default_sentinel.h> +#include <__iterator/distance.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iter_move.h> +#include <__iterator/iter_swap.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__memory/addressof.h> +#include <__ranges/access.h> +#include <__ranges/all.h> +#include <__ranges/concepts.h> +#include <__ranges/movable_box.h> +#include <__ranges/non_propagating_cache.h> +#include <__ranges/range_adaptor.h> +#include <__ranges/size.h> +#include <__ranges/view_interface.h> +#include <__ranges/zip_view.h> +#include <__type_traits/conditional.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_nothrow_convertible.h> +#include <__type_traits/is_object.h> +#include <__type_traits/make_unsigned.h> +#include <__type_traits/maybe_const.h> +#include <__utility/forward.h> +#include <__utility/in_place.h> +#include <__utility/move.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 26 + +namespace ranges { + +# ifdef __cpp_pack_indexing +template +using __extract_last _LIBCPP_NODEBUG = _Tp...[sizeof...(_Tp) - 1]; +# else +template +struct __extract_last_impl : __extract_last_impl<_Tail...> {}; +template +struct __extract_last_impl<_Tp> { + using type _LIBCPP_NODEBUG = _Tp; +}; + +template +using __extract_last _LIBCPP_NODEBUG = __extract_last_impl<_Tp...>::type; +# endif + +template +constexpr bool __derived_from_pack = +__derived_from_pack<_Tp, __extract_last<_Tail...>> && __derived_from_pack<_Tail...>; + +template +constexpr bool __derived_from_pack<_Tp, _IterCategory> = derived_from<_Tp, _IterCategory>; + +template +struct __last_view : __last_view<_Views...> {}; + +template +struct __last_view<_View> { + using type = _View; +}; + +template +concept __concat_indirectly_readable_impl = requires(const _It __it) { + { *__it } -> convertible_to<_Ref>; + { ranges::iter_move(__it) } -> convertible_to<_RRef>; +}; + +template +using __concat_reference_t _LIBCPP_NODEBUG = common_reference_t...>; + +template +using __concat_value_t _LIBCPP_NODEBUG = common_type_t...>; + +template +using __concat_rvalue_reference_t _LIBCPP_NODEBUG = common_reference_t...>; + +template +concept __concat_indirectly_readable = +common_reference_with<__concat_reference_t<_Rs...>&&, __concat_value_t<_Rs...>&> && +common_reference_with<__concat_reference_t<_Rs...>&&, __concat_rvalue_reference_t<_Rs...>&&> && +common_reference_with<__concat_rvalue_reference_t<_Rs...>&&, __concat_value_t<_Rs...> const&> && +(__concat_indirectly_readable_impl<__concat_reference_t<_Rs...>, + __concat_rvalue_reference_t<_Rs...>, + iterator_t<_Rs>> && + ...); + +template +concept __concatable = requires { + typename __concat_reference_t<_Rs...>; + typename __concat_value_t<_Rs...>; + typename __concat_rvalue_reference_t<_Rs...>; +} && __concat_indirectly_readable<_Rs...>; + +template +concept __concat_is_random_access = +(random_access_range<__maybe_const<_Const, _Rs>> && ...) && (sized_range<__maybe_const<_Const, _Rs>> && ...); + +template +concept __concat_is_bidirectional = +((bidirectional_range<__maybe_const<_Const, _Rs>> && ...) && (common_range<__maybe_const<_Const, _Rs>> && ...)); + +template +concept __all_forward = (forward_range<__maybe_const<_Const, _Views>> && ...); + +template +struct __apply_drop_first; + +template +struct __apply_drop_first<_Const, _Head, _Tail...> { + static constexpr bool value = (sized_range<__maybe_const<_Const, _Tail>> && ...); +}; + +template + requires(view<_Views> && ...) && (sizeof...(_Views) > 0) && __concatable<_Views...> +class concat_view : public view
[clang] [clang-tools-extra] [libcxx] [llvm] [libc++][ranges] P2542R8: Implement `views::concat` (PR #120920)
https://github.com/frederick-vs-ja requested changes to this pull request. https://github.com/llvm/llvm-project/pull/120920 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [libcxx] [llvm] [libc++][ranges] P2542R8: Implement `views::concat` (PR #120920)
@@ -0,0 +1,644 @@ +// -*- C++ -*- +//===--===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef _LIBCPP___RANGES_CONCAT_VIEW_H +#define _LIBCPP___RANGES_CONCAT_VIEW_H + +#include <__algorithm/ranges_find_if.h> +#include <__assert> +#include <__concepts/common_reference_with.h> +#include <__concepts/constructible.h> +#include <__concepts/convertible_to.h> +#include <__concepts/copyable.h> +#include <__concepts/derived_from.h> +#include <__concepts/equality_comparable.h> +#include <__concepts/swappable.h> +#include <__config> +#include <__functional/bind_back.h> +#include <__functional/invoke.h> +#include <__functional/reference_wrapper.h> +#include <__iterator/concepts.h> +#include <__iterator/default_sentinel.h> +#include <__iterator/distance.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iter_move.h> +#include <__iterator/iter_swap.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__memory/addressof.h> +#include <__ranges/access.h> +#include <__ranges/all.h> +#include <__ranges/concepts.h> +#include <__ranges/movable_box.h> +#include <__ranges/non_propagating_cache.h> +#include <__ranges/range_adaptor.h> +#include <__ranges/size.h> +#include <__ranges/view_interface.h> +#include <__ranges/zip_view.h> +#include <__type_traits/conditional.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_nothrow_convertible.h> +#include <__type_traits/is_object.h> +#include <__type_traits/make_unsigned.h> +#include <__type_traits/maybe_const.h> +#include <__utility/forward.h> +#include <__utility/in_place.h> +#include <__utility/move.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 26 + +namespace ranges { + +# ifdef __cpp_pack_indexing +template +using __extract_last _LIBCPP_NODEBUG = _Tp...[sizeof...(_Tp) - 1]; +# else +template +struct __extract_last_impl : __extract_last_impl<_Tail...> {}; +template +struct __extract_last_impl<_Tp> { + using type _LIBCPP_NODEBUG = _Tp; +}; + +template +using __extract_last _LIBCPP_NODEBUG = __extract_last_impl<_Tp...>::type; +# endif + +template +constexpr bool __derived_from_pack = +__derived_from_pack<_Tp, __extract_last<_Tail...>> && __derived_from_pack<_Tail...>; + +template +constexpr bool __derived_from_pack<_Tp, _IterCategory> = derived_from<_Tp, _IterCategory>; + +template +struct __last_view : __last_view<_Views...> {}; + +template +struct __last_view<_View> { + using type = _View; +}; + +template +concept __concat_indirectly_readable_impl = requires(const _It __it) { + { *__it } -> convertible_to<_Ref>; + { ranges::iter_move(__it) } -> convertible_to<_RRef>; +}; + +template +using __concat_reference_t _LIBCPP_NODEBUG = common_reference_t...>; + +template +using __concat_value_t _LIBCPP_NODEBUG = common_type_t...>; + +template +using __concat_rvalue_reference_t _LIBCPP_NODEBUG = common_reference_t...>; + +template +concept __concat_indirectly_readable = +common_reference_with<__concat_reference_t<_Rs...>&&, __concat_value_t<_Rs...>&> && +common_reference_with<__concat_reference_t<_Rs...>&&, __concat_rvalue_reference_t<_Rs...>&&> && +common_reference_with<__concat_rvalue_reference_t<_Rs...>&&, __concat_value_t<_Rs...> const&> && +(__concat_indirectly_readable_impl<__concat_reference_t<_Rs...>, + __concat_rvalue_reference_t<_Rs...>, + iterator_t<_Rs>> && + ...); + +template +concept __concatable = requires { + typename __concat_reference_t<_Rs...>; + typename __concat_value_t<_Rs...>; + typename __concat_rvalue_reference_t<_Rs...>; +} && __concat_indirectly_readable<_Rs...>; + +template +concept __concat_is_random_access = +(random_access_range<__maybe_const<_Const, _Rs>> && ...) && (sized_range<__maybe_const<_Const, _Rs>> && ...); + +template +concept __concat_is_bidirectional = +((bidirectional_range<__maybe_const<_Const, _Rs>> && ...) && (common_range<__maybe_const<_Const, _Rs>> && ...)); + +template +concept __all_forward = (forward_range<__maybe_const<_Const, _Views>> && ...); + +template +struct __apply_drop_first; + +template +struct __apply_drop_first<_Const, _Head, _Tail...> { + static constexpr bool value = (sized_range<__maybe_const<_Const, _Tail>> && ...); +}; + +template + requires(view<_Views> && ...) && (sizeof...(_Views) > 0) && __concatable<_Views...> +class concat_view : public view
[clang] [Fix] Speedup -Wunsafe-buffer-usage when using clang modules. (PR #127161)
@@ -2633,7 +2646,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings( SourceLocation()) || (!Diags.isIgnored(diag::warn_unsafe_buffer_libc_call, SourceLocation()) && S.getLangOpts().CPlusPlus /* only warn about libc calls in C++ */)) { -CallableVisitor(CallAnalyzers).TraverseTranslationUnitDecl(TU); +CallableVisitor(CallAnalyzers, TU->getOwningModuleID()).TraverseTranslationUnitDecl(TU); matts1 wrote: There's no `operator==` on the `Module` class. Would I be correct in assuming that comparing pointers is the correct way to check for equality (in other words, can I assume that each module only has one associated instance)? https://github.com/llvm/llvm-project/pull/127161 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Fix] Speedup -Wunsafe-buffer-usage when using clang modules. (PR #127161)
https://github.com/matts1 updated https://github.com/llvm/llvm-project/pull/127161 >From ec6461f8a44058f588a23cf0c7cd29c528bf4b8e Mon Sep 17 00:00:00 2001 From: Matt Stark Date: Fri, 14 Feb 2025 14:14:03 +1100 Subject: [PATCH] [Fix] Speedup -Wunsafe-buffer-usage when using clang modules. See https://issues.chromium.org/issues/351909443 for details and benchmarks. This improves the performance of a file containing a single line, `#include `, from ~1 second to ~100ms on my machine. --- clang/lib/Sema/AnalysisBasedWarnings.cpp | 19 --- clang/test/Modules/safe_buffers_optout.cpp | 28 +++--- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 589869d018657..ecc7e893c214a 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2546,14 +2546,27 @@ static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) { class CallableVisitor : public DynamicRecursiveASTVisitor { private: llvm::function_ref Callback; + const Module* const TUModule; public: - CallableVisitor(llvm::function_ref Callback) - : Callback(Callback) { + CallableVisitor(llvm::function_ref Callback, + const Module* const TUModule) + : Callback(Callback), TUModule(TUModule) { ShouldVisitTemplateInstantiations = true; ShouldVisitImplicitCode = false; } + bool TraverseDecl(Decl *Node) override { +// For performance reasons, only validate the current translation unit's +// module, and not modules it depends on. +// See https://issues.chromium.org/issues/351909443 for details. +if (Node && Node->getOwningModule() == TUModule) { + return DynamicRecursiveASTVisitor::TraverseDecl(Node); +} else { + return true; +} + } + bool VisitFunctionDecl(FunctionDecl *Node) override { if (cast(Node)->isDependentContext()) return true; // Not to analyze dependent decl @@ -2633,7 +2646,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings( SourceLocation()) || (!Diags.isIgnored(diag::warn_unsafe_buffer_libc_call, SourceLocation()) && S.getLangOpts().CPlusPlus /* only warn about libc calls in C++ */)) { -CallableVisitor(CallAnalyzers).TraverseTranslationUnitDecl(TU); +CallableVisitor(CallAnalyzers, TU->getOwningModule()).TraverseTranslationUnitDecl(TU); } } diff --git a/clang/test/Modules/safe_buffers_optout.cpp b/clang/test/Modules/safe_buffers_optout.cpp index 2129db65da752..8c3d6a235d399 100644 --- a/clang/test/Modules/safe_buffers_optout.cpp +++ b/clang/test/Modules/safe_buffers_optout.cpp @@ -95,18 +95,10 @@ int textual(int *p) { // `safe_buffers_test_optout`, which uses another top-level module // `safe_buffers_test_base`. (So the module dependencies form a DAG.) -// No expected warnings from base.h because base.h is a separate -// module and in a separate TU that is not textually included. The -// explicit command that builds base.h has no `-Wunsafe-buffer-usage`. - -// expected-warning@base.h:3{{unsafe buffer access}} -// expected-note@base.h:3{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} -// expected-warning@test_sub1.h:5{{unsafe buffer access}} -// expected-note@test_sub1.h:5{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} -// expected-warning@test_sub1.h:14{{unsafe buffer access}} -// expected-note@test_sub1.h:14{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} -// expected-warning@test_sub2.h:5{{unsafe buffer access}} -// expected-note@test_sub2.h:5{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} +// No expected warnings from base.h, test_sub1, or test_sub2 because they are +// in seperate modules, and the explicit commands that builds them have no +// `-Wunsafe-buffer-usage`. + int foo(int * p) { int x = p[5]; // expected-warning{{unsafe buffer access}} expected-note{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} #pragma clang unsafe_buffer_usage begin @@ -129,14 +121,10 @@ int foo(int * p) { // `safe_buffers_test_optout`, which uses another top-level module // `safe_buffers_test_base`. (So the module dependencies form a DAG.) -// expected-warning@base.h:3{{unsafe buffer access}} -// expected-note@base.h:3{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} -// expected-warning@test_sub1.h:5{{unsafe buffer access}} -// expected-note@test_sub1.h:5{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} -// expected-warning@test_sub1.h:14{{unsafe buffer access}} -// expected-note@test_sub1.h:14{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} -// expected-warning@test_sub2.h:5{{unsafe buffer access}} -// expected-note@test_sub2.h:5{{pass -fsafe-b
[clang] [Fix] Speedup -Wunsafe-buffer-usage when using clang modules. (PR #127161)
@@ -2633,7 +2646,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings( SourceLocation()) || (!Diags.isIgnored(diag::warn_unsafe_buffer_libc_call, SourceLocation()) && S.getLangOpts().CPlusPlus /* only warn about libc calls in C++ */)) { -CallableVisitor(CallAnalyzers).TraverseTranslationUnitDecl(TU); +CallableVisitor(CallAnalyzers, TU->getOwningModuleID()).TraverseTranslationUnitDecl(TU); ChuanqiXu9 wrote: Yes https://github.com/llvm/llvm-project/pull/127161 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Index] Use HeuristicResolver in libIndex (PR #125153)
https://github.com/HighCommander4 updated https://github.com/llvm/llvm-project/pull/125153 >From 656a47976d1b8699d5f6e0b0b9421866804c8eb2 Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Thu, 30 Jan 2025 21:31:12 -0500 Subject: [PATCH] [clang][Index] Use HeuristicResolver in libIndex The uses replace hand-rolled code that did a subset of what HeuristicResolver does. --- clang/lib/Index/CMakeLists.txt| 1 + clang/lib/Index/IndexBody.cpp | 49 ++- clang/lib/Index/IndexingContext.cpp | 12 + clang/lib/Index/IndexingContext.h | 10 ++-- .../Index/Core/index-dependent-source.cpp | 22 - 5 files changed, 47 insertions(+), 47 deletions(-) diff --git a/clang/lib/Index/CMakeLists.txt b/clang/lib/Index/CMakeLists.txt index b4e294304f115..f0d2b579c8df6 100644 --- a/clang/lib/Index/CMakeLists.txt +++ b/clang/lib/Index/CMakeLists.txt @@ -23,6 +23,7 @@ add_clang_library(clangIndex clangFormat clangFrontend clangLex + clangSema clangSerialization clangToolingCore diff --git a/clang/lib/Index/IndexBody.cpp b/clang/lib/Index/IndexBody.cpp index f1dc4d5831ce7..8b4a8889a9e65 100644 --- a/clang/lib/Index/IndexBody.cpp +++ b/clang/lib/Index/IndexBody.cpp @@ -13,6 +13,7 @@ #include "clang/AST/ExprConcepts.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Type.h" +#include "clang/Sema/HeuristicResolver.h" using namespace clang; using namespace clang::index; @@ -168,51 +169,33 @@ class BodyIndexer : public RecursiveASTVisitor { Parent, ParentDC, Roles, Relations, E); } - bool indexDependentReference( - const Expr *E, const Type *T, const DeclarationNameInfo &NameInfo, - llvm::function_ref Filter) { -if (!T) - return true; -const TemplateSpecializationType *TST = -T->getAs(); -if (!TST) - return true; -TemplateName TN = TST->getTemplateName(); -const ClassTemplateDecl *TD = -dyn_cast_or_null(TN.getAsTemplateDecl()); -if (!TD) - return true; -CXXRecordDecl *RD = TD->getTemplatedDecl(); -if (!RD->hasDefinition()) - return true; -RD = RD->getDefinition(); -std::vector Symbols = -RD->lookupDependentName(NameInfo.getName(), Filter); + bool indexDependentReference(const Expr *E, SourceLocation Loc, + std::vector TargetSymbols) { // FIXME: Improve overload handling. -if (Symbols.size() != 1) +if (TargetSymbols.size() != 1) return true; -SourceLocation Loc = NameInfo.getLoc(); if (Loc.isInvalid()) Loc = E->getBeginLoc(); SmallVector Relations; SymbolRoleSet Roles = getRolesForRef(E, Relations); -return IndexCtx.handleReference(Symbols[0], Loc, Parent, ParentDC, Roles, -Relations, E); +return IndexCtx.handleReference(TargetSymbols[0], Loc, Parent, ParentDC, +Roles, Relations, E); } bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) { -const DeclarationNameInfo &Info = E->getMemberNameInfo(); -return indexDependentReference( -E, E->getBaseType().getTypePtrOrNull(), Info, -[](const NamedDecl *D) { return D->isCXXInstanceMember(); }); +auto *Resolver = IndexCtx.getResolver(); +if (!Resolver) + return true; +return indexDependentReference(E, E->getMemberNameInfo().getLoc(), + Resolver->resolveMemberExpr(E)); } bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { -const DeclarationNameInfo &Info = E->getNameInfo(); -const NestedNameSpecifier *NNS = E->getQualifier(); -return indexDependentReference( -E, NNS->getAsType(), Info, -[](const NamedDecl *D) { return !D->isCXXInstanceMember(); }); +auto *Resolver = IndexCtx.getResolver(); +if (!Resolver) + return true; +return indexDependentReference(E, E->getNameInfo().getLoc(), + Resolver->resolveDeclRefExpr(E)); } bool VisitDesignatedInitExpr(DesignatedInitExpr *E) { diff --git a/clang/lib/Index/IndexingContext.cpp b/clang/lib/Index/IndexingContext.cpp index 2dd68dfcc5a70..bdd6c5acf1d34 100644 --- a/clang/lib/Index/IndexingContext.cpp +++ b/clang/lib/Index/IndexingContext.cpp @@ -14,6 +14,7 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Index/IndexDataConsumer.h" +#include "clang/Sema/HeuristicResolver.h" using namespace clang; using namespace index; @@ -25,6 +26,17 @@ static bool isGeneratedDecl(const Decl *D) { return false; } +IndexingContext::IndexingContext(IndexingOptions IndexOpts, + IndexDataConsumer &DataConsumer) +: IndexOpts(IndexOpts), DataConsumer(DataConsumer) {} + +IndexingContext::~IndexingContext() = default; + +void IndexingContext::setASTContext(ASTCo
[clang] [Fix] Speedup -Wunsafe-buffer-usage when using clang modules. (PR #127161)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff dc79c66f2c6cc2773e38735660d8e0aaedf9702c ec6461f8a44058f588a23cf0c7cd29c528bf4b8e --extensions cpp -- clang/lib/Sema/AnalysisBasedWarnings.cpp clang/test/Modules/safe_buffers_optout.cpp `` View the diff from clang-format here. ``diff diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index ecc7e893c2..fd46d97fec 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2546,11 +2546,11 @@ static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) { class CallableVisitor : public DynamicRecursiveASTVisitor { private: llvm::function_ref Callback; - const Module* const TUModule; + const Module *const TUModule; public: CallableVisitor(llvm::function_ref Callback, - const Module* const TUModule) + const Module *const TUModule) : Callback(Callback), TUModule(TUModule) { ShouldVisitTemplateInstantiations = true; ShouldVisitImplicitCode = false; @@ -2646,7 +2646,8 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings( SourceLocation()) || (!Diags.isIgnored(diag::warn_unsafe_buffer_libc_call, SourceLocation()) && S.getLangOpts().CPlusPlus /* only warn about libc calls in C++ */)) { -CallableVisitor(CallAnalyzers, TU->getOwningModule()).TraverseTranslationUnitDecl(TU); +CallableVisitor(CallAnalyzers, TU->getOwningModule()) +.TraverseTranslationUnitDecl(TU); } } `` https://github.com/llvm/llvm-project/pull/127161 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Fix] Speedup -Wunsafe-buffer-usage when using clang modules. (PR #127161)
@@ -2633,7 +2646,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings( SourceLocation()) || (!Diags.isIgnored(diag::warn_unsafe_buffer_libc_call, SourceLocation()) && S.getLangOpts().CPlusPlus /* only warn about libc calls in C++ */)) { -CallableVisitor(CallAnalyzers).TraverseTranslationUnitDecl(TU); +CallableVisitor(CallAnalyzers, TU->getOwningModuleID()).TraverseTranslationUnitDecl(TU); matts1 wrote: Done, looks like it's working. https://github.com/llvm/llvm-project/pull/127161 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Fix] Speedup -Wunsafe-buffer-usage when using clang modules. (PR #127161)
https://github.com/ChuanqiXu9 approved this pull request. https://github.com/llvm/llvm-project/pull/127161 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [HLSL] Implement the 'and' HLSL function (PR #127098)
@@ -2245,6 +2245,36 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { break; } + case Builtin::BI__builtin_hlsl_and: { +if (SemaRef.checkArgCount(TheCall, 2)) + return true; +if (CheckVectorElementCallArgs(&SemaRef, TheCall)) + return true; + +// CheckVectorElementCallArgs(...) guarantees both args are the same type. +assert(TheCall->getArg(0)->getType() == TheCall->getArg(1)->getType() && + "Both args must be of the same type"); + +// check that the arguments are bools or, if vectors, +// vectors of bools +QualType ArgTy = TheCall->getArg(0)->getType(); +if (const auto *VecTy = ArgTy->getAs()) { + ArgTy = VecTy->getElementType(); +} +if (!getASTContext().hasSameUnqualifiedType(ArgTy, farzonl wrote: > On this point I actually disagree. We should get this PR into a state where > its diagnostics are at the high quality we want, then we can work back to the > other diagnostics and correct them. I’d prefer to take the time to plan a cohesive fix that updates all the tests rather than introducing an ad hoc solution for `and`, which would likely result in another ad hoc fix for the `or` builtin (also scheduled for this sprint). For me, any work scheduled in the current sprint has a high bar for deviating from our established best practices. This is especially important because my primary goal is to ensure a smooth and predictable landing for the intrinsics workstream, as it plays a key role in onboarding new contributors. Next week, I’d like to discuss a change that would either: 1. Consolidate `CheckArgTypeIsCorrect` and `CheckScalarOrVector`. 2. Modify `CheckArgTypeIsCorrect` to use the `err_typecheck_expect_scalar_or_vector` diagnostic and stop constructing the expected vector type. This would mean we stop printing an expected type with the syntactic sugar missing. Additionally, we would update ExpectedType to be a QualType vector or ArrayRef ExpectedTypes, allowing us to properly capture multiple overloads. ie go from ```cpp static bool CheckArgTypeIsCorrect( Sema *S, Expr *Arg, QualType ExpectedType, llvm::function_ref Check) { QualType PassedType = Arg->getType(); if (Check(PassedType)) { if (auto *VecTyA = PassedType->getAs()) ExpectedType = S->Context.getVectorType( ExpectedType, VecTyA->getNumElements(), VecTyA->getVectorKind()); S->Diag(Arg->getBeginLoc(), diag::err_typecheck_convert_incompatible) << PassedType << ExpectedType << 1 << 0 << 0; return true; } return false; } ``` to ```cpp static bool CheckArgTypeIsCorrect( Sema *S, Expr *Arg, llvm::SmallVectorImpl ExpectedTypes, llvm::function_ref Check) { QualType PassedType = Arg->getType(); if (Check(PassedType)) { for (const clang::QualType &ExpectedType : ExpectedTypes) S->Diag(TheCall->getArg(0)->getBeginLoc(), diag::err_typecheck_expect_scalar_or_vector) << ArgType << ExpectedType; ``` My feeling is we can achieve what you want to do here but it would turn out better if these type of fixes had time to be designed outside of the PR process. I hope this better explains where I'm coming from. https://github.com/llvm/llvm-project/pull/127098 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Fix] Speedup -Wunsafe-buffer-usage when using clang modules. (PR #127161)
https://github.com/matts1 updated https://github.com/llvm/llvm-project/pull/127161 >From 17b1184b8fadc851d4040845066b4d53f7700b98 Mon Sep 17 00:00:00 2001 From: Matt Stark Date: Fri, 14 Feb 2025 14:14:03 +1100 Subject: [PATCH] [Fix] Speedup -Wunsafe-buffer-usage when using clang modules. See https://issues.chromium.org/issues/351909443 for details and benchmarks. This improves the performance of a file containing a single line, `#include `, from ~1 second to ~100ms on my machine. --- clang/lib/Sema/AnalysisBasedWarnings.cpp | 20 +--- clang/test/Modules/safe_buffers_optout.cpp | 28 +++--- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 589869d018657..fd46d97fec613 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2546,14 +2546,27 @@ static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) { class CallableVisitor : public DynamicRecursiveASTVisitor { private: llvm::function_ref Callback; + const Module *const TUModule; public: - CallableVisitor(llvm::function_ref Callback) - : Callback(Callback) { + CallableVisitor(llvm::function_ref Callback, + const Module *const TUModule) + : Callback(Callback), TUModule(TUModule) { ShouldVisitTemplateInstantiations = true; ShouldVisitImplicitCode = false; } + bool TraverseDecl(Decl *Node) override { +// For performance reasons, only validate the current translation unit's +// module, and not modules it depends on. +// See https://issues.chromium.org/issues/351909443 for details. +if (Node && Node->getOwningModule() == TUModule) { + return DynamicRecursiveASTVisitor::TraverseDecl(Node); +} else { + return true; +} + } + bool VisitFunctionDecl(FunctionDecl *Node) override { if (cast(Node)->isDependentContext()) return true; // Not to analyze dependent decl @@ -2633,7 +2646,8 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings( SourceLocation()) || (!Diags.isIgnored(diag::warn_unsafe_buffer_libc_call, SourceLocation()) && S.getLangOpts().CPlusPlus /* only warn about libc calls in C++ */)) { -CallableVisitor(CallAnalyzers).TraverseTranslationUnitDecl(TU); +CallableVisitor(CallAnalyzers, TU->getOwningModule()) +.TraverseTranslationUnitDecl(TU); } } diff --git a/clang/test/Modules/safe_buffers_optout.cpp b/clang/test/Modules/safe_buffers_optout.cpp index 2129db65da752..8c3d6a235d399 100644 --- a/clang/test/Modules/safe_buffers_optout.cpp +++ b/clang/test/Modules/safe_buffers_optout.cpp @@ -95,18 +95,10 @@ int textual(int *p) { // `safe_buffers_test_optout`, which uses another top-level module // `safe_buffers_test_base`. (So the module dependencies form a DAG.) -// No expected warnings from base.h because base.h is a separate -// module and in a separate TU that is not textually included. The -// explicit command that builds base.h has no `-Wunsafe-buffer-usage`. - -// expected-warning@base.h:3{{unsafe buffer access}} -// expected-note@base.h:3{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} -// expected-warning@test_sub1.h:5{{unsafe buffer access}} -// expected-note@test_sub1.h:5{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} -// expected-warning@test_sub1.h:14{{unsafe buffer access}} -// expected-note@test_sub1.h:14{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} -// expected-warning@test_sub2.h:5{{unsafe buffer access}} -// expected-note@test_sub2.h:5{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} +// No expected warnings from base.h, test_sub1, or test_sub2 because they are +// in seperate modules, and the explicit commands that builds them have no +// `-Wunsafe-buffer-usage`. + int foo(int * p) { int x = p[5]; // expected-warning{{unsafe buffer access}} expected-note{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} #pragma clang unsafe_buffer_usage begin @@ -129,14 +121,10 @@ int foo(int * p) { // `safe_buffers_test_optout`, which uses another top-level module // `safe_buffers_test_base`. (So the module dependencies form a DAG.) -// expected-warning@base.h:3{{unsafe buffer access}} -// expected-note@base.h:3{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} -// expected-warning@test_sub1.h:5{{unsafe buffer access}} -// expected-note@test_sub1.h:5{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} -// expected-warning@test_sub1.h:14{{unsafe buffer access}} -// expected-note@test_sub1.h:14{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} -// expected-warning@test_sub2.h:5{{unsafe buffer access}} -// expected-note@test_sub2.h:5{{pas
[clang] [Fix] Speedup -Wunsafe-buffer-usage when using clang modules. (PR #127161)
https://github.com/matts1 edited https://github.com/llvm/llvm-project/pull/127161 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Fix] Speedup -Wunsafe-buffer-usage when using clang modules. (PR #127161)
llvmbot wrote: @llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-modules Author: Matt (matts1) Changes Each piece of code should have analysis run on it precisely once. However, if you build a module, and then build another module depending on it, the header file will have `-Wunsafe-buffer-usage` run on it twice. This normally isn't a huge issue, but in the case of using the standard library as a module, simply adding the line `#include` increases compile times by 900ms (from 100ms to 1 second) on my machine. I believe this is because the standard library has massive modules, of which only a small part is used (the AST is ~700k lines), and because if what I've been told is correct, the AST is lazily generated, and `-Wunsafe-buffer-usage` forces it to be evaluated every time. See https://issues.chromium.org/issues/351909443 for details and benchmarks. --- Full diff: https://github.com/llvm/llvm-project/pull/127161.diff 2 Files Affected: - (modified) clang/lib/Sema/AnalysisBasedWarnings.cpp (+16-3) - (modified) clang/test/Modules/safe_buffers_optout.cpp (+8-20) ``diff diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 589869d018657..849c899bbbc8b 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2546,14 +2546,27 @@ static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) { class CallableVisitor : public DynamicRecursiveASTVisitor { private: llvm::function_ref Callback; + const unsigned int TUModuleID; public: - CallableVisitor(llvm::function_ref Callback) - : Callback(Callback) { + CallableVisitor(llvm::function_ref Callback, + unsigned int TUModuleID) + : Callback(Callback), TUModuleID(TUModuleID) { ShouldVisitTemplateInstantiations = true; ShouldVisitImplicitCode = false; } + bool TraverseDecl(Decl *Node) override { +// For performance reasons, only validate the current translation unit's +// module, and not modules it depends on. +// See https://issues.chromium.org/issues/351909443 for details. +if (Node && Node->getOwningModuleID() == TUModuleID) { + return DynamicRecursiveASTVisitor::TraverseDecl(Node); +} else { + return true; +} + } + bool VisitFunctionDecl(FunctionDecl *Node) override { if (cast(Node)->isDependentContext()) return true; // Not to analyze dependent decl @@ -2633,7 +2646,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings( SourceLocation()) || (!Diags.isIgnored(diag::warn_unsafe_buffer_libc_call, SourceLocation()) && S.getLangOpts().CPlusPlus /* only warn about libc calls in C++ */)) { -CallableVisitor(CallAnalyzers).TraverseTranslationUnitDecl(TU); +CallableVisitor(CallAnalyzers, TU->getOwningModuleID()).TraverseTranslationUnitDecl(TU); } } diff --git a/clang/test/Modules/safe_buffers_optout.cpp b/clang/test/Modules/safe_buffers_optout.cpp index 2129db65da752..8c3d6a235d399 100644 --- a/clang/test/Modules/safe_buffers_optout.cpp +++ b/clang/test/Modules/safe_buffers_optout.cpp @@ -95,18 +95,10 @@ int textual(int *p) { // `safe_buffers_test_optout`, which uses another top-level module // `safe_buffers_test_base`. (So the module dependencies form a DAG.) -// No expected warnings from base.h because base.h is a separate -// module and in a separate TU that is not textually included. The -// explicit command that builds base.h has no `-Wunsafe-buffer-usage`. - -// expected-warning@base.h:3{{unsafe buffer access}} -// expected-note@base.h:3{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} -// expected-warning@test_sub1.h:5{{unsafe buffer access}} -// expected-note@test_sub1.h:5{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} -// expected-warning@test_sub1.h:14{{unsafe buffer access}} -// expected-note@test_sub1.h:14{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} -// expected-warning@test_sub2.h:5{{unsafe buffer access}} -// expected-note@test_sub2.h:5{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} +// No expected warnings from base.h, test_sub1, or test_sub2 because they are +// in seperate modules, and the explicit commands that builds them have no +// `-Wunsafe-buffer-usage`. + int foo(int * p) { int x = p[5]; // expected-warning{{unsafe buffer access}} expected-note{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} #pragma clang unsafe_buffer_usage begin @@ -129,14 +121,10 @@ int foo(int * p) { // `safe_buffers_test_optout`, which uses another top-level module // `safe_buffers_test_base`. (So the module dependencies form a DAG.) -// expected-warning@base.h:3{{unsafe buffer access}} -// expected-note@base.h:3{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestio
[clang] [Fix] Speedup -Wunsafe-buffer-usage when using clang modules. (PR #127161)
https://github.com/matts1 ready_for_review https://github.com/llvm/llvm-project/pull/127161 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Fix] Speedup -Wunsafe-buffer-usage when using clang modules. (PR #127161)
https://github.com/matts1 edited https://github.com/llvm/llvm-project/pull/127161 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][analyzer] Teach the BlockInCriticalSectionChecker about O_NONBLOCK streams (PR #127049)
flovent wrote: > I pushed a couple cleanups. I hope you don't mind. Now it looks excellent. > Thank you for your contribution! these commits looks very good, I don't mind at all, and happy to have my first commit to CSA. > Can I merge this? @flovent @Xazax-hun I am ok to merge https://github.com/llvm/llvm-project/pull/127049 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Index] Use HeuristicResolver in libIndex (PR #125153)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Nathan Ridge (HighCommander4) Changes --- Full diff: https://github.com/llvm/llvm-project/pull/125153.diff 5 Files Affected: - (modified) clang/lib/Index/CMakeLists.txt (+1) - (modified) clang/lib/Index/IndexBody.cpp (+16-33) - (modified) clang/lib/Index/IndexingContext.cpp (+12) - (modified) clang/lib/Index/IndexingContext.h (+7-3) - (modified) clang/test/Index/Core/index-dependent-source.cpp (+11-11) ``diff diff --git a/clang/lib/Index/CMakeLists.txt b/clang/lib/Index/CMakeLists.txt index b4e294304f115..f0d2b579c8df6 100644 --- a/clang/lib/Index/CMakeLists.txt +++ b/clang/lib/Index/CMakeLists.txt @@ -23,6 +23,7 @@ add_clang_library(clangIndex clangFormat clangFrontend clangLex + clangSema clangSerialization clangToolingCore diff --git a/clang/lib/Index/IndexBody.cpp b/clang/lib/Index/IndexBody.cpp index f1dc4d5831ce7..8b4a8889a9e65 100644 --- a/clang/lib/Index/IndexBody.cpp +++ b/clang/lib/Index/IndexBody.cpp @@ -13,6 +13,7 @@ #include "clang/AST/ExprConcepts.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Type.h" +#include "clang/Sema/HeuristicResolver.h" using namespace clang; using namespace clang::index; @@ -168,51 +169,33 @@ class BodyIndexer : public RecursiveASTVisitor { Parent, ParentDC, Roles, Relations, E); } - bool indexDependentReference( - const Expr *E, const Type *T, const DeclarationNameInfo &NameInfo, - llvm::function_ref Filter) { -if (!T) - return true; -const TemplateSpecializationType *TST = -T->getAs(); -if (!TST) - return true; -TemplateName TN = TST->getTemplateName(); -const ClassTemplateDecl *TD = -dyn_cast_or_null(TN.getAsTemplateDecl()); -if (!TD) - return true; -CXXRecordDecl *RD = TD->getTemplatedDecl(); -if (!RD->hasDefinition()) - return true; -RD = RD->getDefinition(); -std::vector Symbols = -RD->lookupDependentName(NameInfo.getName(), Filter); + bool indexDependentReference(const Expr *E, SourceLocation Loc, + std::vector TargetSymbols) { // FIXME: Improve overload handling. -if (Symbols.size() != 1) +if (TargetSymbols.size() != 1) return true; -SourceLocation Loc = NameInfo.getLoc(); if (Loc.isInvalid()) Loc = E->getBeginLoc(); SmallVector Relations; SymbolRoleSet Roles = getRolesForRef(E, Relations); -return IndexCtx.handleReference(Symbols[0], Loc, Parent, ParentDC, Roles, -Relations, E); +return IndexCtx.handleReference(TargetSymbols[0], Loc, Parent, ParentDC, +Roles, Relations, E); } bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) { -const DeclarationNameInfo &Info = E->getMemberNameInfo(); -return indexDependentReference( -E, E->getBaseType().getTypePtrOrNull(), Info, -[](const NamedDecl *D) { return D->isCXXInstanceMember(); }); +auto *Resolver = IndexCtx.getResolver(); +if (!Resolver) + return true; +return indexDependentReference(E, E->getMemberNameInfo().getLoc(), + Resolver->resolveMemberExpr(E)); } bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { -const DeclarationNameInfo &Info = E->getNameInfo(); -const NestedNameSpecifier *NNS = E->getQualifier(); -return indexDependentReference( -E, NNS->getAsType(), Info, -[](const NamedDecl *D) { return !D->isCXXInstanceMember(); }); +auto *Resolver = IndexCtx.getResolver(); +if (!Resolver) + return true; +return indexDependentReference(E, E->getNameInfo().getLoc(), + Resolver->resolveDeclRefExpr(E)); } bool VisitDesignatedInitExpr(DesignatedInitExpr *E) { diff --git a/clang/lib/Index/IndexingContext.cpp b/clang/lib/Index/IndexingContext.cpp index 2dd68dfcc5a70..bdd6c5acf1d34 100644 --- a/clang/lib/Index/IndexingContext.cpp +++ b/clang/lib/Index/IndexingContext.cpp @@ -14,6 +14,7 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Index/IndexDataConsumer.h" +#include "clang/Sema/HeuristicResolver.h" using namespace clang; using namespace index; @@ -25,6 +26,17 @@ static bool isGeneratedDecl(const Decl *D) { return false; } +IndexingContext::IndexingContext(IndexingOptions IndexOpts, + IndexDataConsumer &DataConsumer) +: IndexOpts(IndexOpts), DataConsumer(DataConsumer) {} + +IndexingContext::~IndexingContext() = default; + +void IndexingContext::setASTContext(ASTContext &ctx) { + Ctx = &ctx; + Resolver = Ctx ? std::make_unique(*Ctx) : nullptr; +} + bool IndexingContext::shouldIndex(const Decl *D) { return !isGeneratedDecl(D); } diff --git a/clang/lib/Index/IndexingContext.h b/clang/lib/Index/Ind
[clang] [clang][Index] Use HeuristicResolver in libIndex (PR #125153)
https://github.com/HighCommander4 edited https://github.com/llvm/llvm-project/pull/125153 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Index] Use HeuristicResolver in libIndex (PR #125153)
https://github.com/HighCommander4 ready_for_review https://github.com/llvm/llvm-project/pull/125153 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 885382f - [clang-format] Fix a bug in annotating braces (#127306)
Author: Owen Pan Date: 2025-02-16T19:30:33-08:00 New Revision: 885382f4379b3b8060213606a8f7bd8a1750f33a URL: https://github.com/llvm/llvm-project/commit/885382f4379b3b8060213606a8f7bd8a1750f33a DIFF: https://github.com/llvm/llvm-project/commit/885382f4379b3b8060213606a8f7bd8a1750f33a.diff LOG: [clang-format] Fix a bug in annotating braces (#127306) Fixes #107616. Added: Modified: clang/lib/Format/UnwrappedLineParser.cpp clang/unittests/Format/TokenAnnotatorTest.cpp Removed: diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 4e040183f2f0a..3a24d72d83e27 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -510,7 +510,7 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) { break; do { NextTok = Tokens->getNextToken(); -} while (NextTok->NewlinesBefore == 0 && NextTok->isNot(tok::eof)); +} while (!NextTok->HasUnescapedNewline && NextTok->isNot(tok::eof)); while (NextTok->is(tok::comment)) NextTok = Tokens->getNextToken(); diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 7b489b1764cb2..1d0870c818acc 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -3519,6 +3519,19 @@ TEST_F(TokenAnnotatorTest, BraceKind) { EXPECT_BRACE_KIND(Tokens[11], BK_Block); EXPECT_BRACE_KIND(Tokens[12], BK_Block); + Tokens = annotate("class foo {\n" +" foo() {}\n" +"#if defined(_MSC_VER__clangGNUC__FOO_) || \\\n" +"(defined(__GNUC__) && defined(FOO))\n" +" foo() {}\n" +"#endif\n" +"};"); + ASSERT_EQ(Tokens.size(), 36u) << Tokens; + EXPECT_TOKEN(Tokens[6], tok::l_brace, TT_FunctionLBrace); + EXPECT_BRACE_KIND(Tokens[7], BK_Block); + EXPECT_TOKEN(Tokens[26], tok::identifier, TT_CtorDtorDeclName); + EXPECT_TOKEN(Tokens[27], tok::l_paren, TT_FunctionDeclarationLParen); + Tokens = annotate("a = class extends goog.a {};", getGoogleStyle(FormatStyle::LK_JavaScript)); ASSERT_EQ(Tokens.size(), 11u) << Tokens; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Index] Use HeuristicResolver in libIndex (PR #125153)
@@ -168,51 +169,33 @@ class BodyIndexer : public RecursiveASTVisitor { Parent, ParentDC, Roles, Relations, E); } - bool indexDependentReference( - const Expr *E, const Type *T, const DeclarationNameInfo &NameInfo, - llvm::function_ref Filter) { -if (!T) - return true; -const TemplateSpecializationType *TST = -T->getAs(); -if (!TST) - return true; -TemplateName TN = TST->getTemplateName(); -const ClassTemplateDecl *TD = -dyn_cast_or_null(TN.getAsTemplateDecl()); -if (!TD) - return true; -CXXRecordDecl *RD = TD->getTemplatedDecl(); -if (!RD->hasDefinition()) - return true; -RD = RD->getDefinition(); -std::vector Symbols = -RD->lookupDependentName(NameInfo.getName(), Filter); + bool indexDependentReference(const Expr *E, SourceLocation Loc, + std::vector TargetSymbols) { // FIXME: Improve overload handling. -if (Symbols.size() != 1) +if (TargetSymbols.size() != 1) return true; -SourceLocation Loc = NameInfo.getLoc(); if (Loc.isInvalid()) Loc = E->getBeginLoc(); SmallVector Relations; SymbolRoleSet Roles = getRolesForRef(E, Relations); -return IndexCtx.handleReference(Symbols[0], Loc, Parent, ParentDC, Roles, -Relations, E); +return IndexCtx.handleReference(TargetSymbols[0], Loc, Parent, ParentDC, +Roles, Relations, E); } bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) { -const DeclarationNameInfo &Info = E->getMemberNameInfo(); -return indexDependentReference( -E, E->getBaseType().getTypePtrOrNull(), Info, -[](const NamedDecl *D) { return D->isCXXInstanceMember(); }); +auto *Resolver = IndexCtx.getResolver(); +if (!Resolver) + return true; zyn0217 wrote: Do we need to fallback to something if HeuristicResolver isn't present? https://github.com/llvm/llvm-project/pull/125153 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] [NFC] Remove outdated FIXME (PR #126978)
llvm-ci wrote: LLVM Buildbot has detected a new failure on builder `llvm-clang-win-x-armv7l` running on `as-builder-1` while building `clang` at step 10 "test-check-clang". Full details are available at: https://lab.llvm.org/buildbot/#/builders/38/builds/2354 Here is the relevant piece of the build log for the reference ``` Step 10 (test-check-clang) failure: Test just built components: check-clang completed (failure) TEST 'Clang :: Driver/offload-Xarch.c' FAILED Exit Code: 1 Command Output (stdout): -- # RUN: at line 3 c:\buildbot\as-builder-1\x-armv7l\build\bin\clang.exe --target=x86_64-unknown-linux-gnu -x cuda C:\buildbot\as-builder-1\x-armv7l\llvm-project\clang\test\Driver\offload-Xarch.c -Xarch_nvptx64 -O3 -S -nogpulib -nogpuinc -### 2>&1 | c:\buildbot\as-builder-1\x-armv7l\build\bin\filecheck.exe -check-prefix=O3ONCE C:\buildbot\as-builder-1\x-armv7l\llvm-project\clang\test\Driver\offload-Xarch.c # executed command: 'c:\buildbot\as-builder-1\x-armv7l\build\bin\clang.exe' --target=x86_64-unknown-linux-gnu -x cuda 'C:\buildbot\as-builder-1\x-armv7l\llvm-project\clang\test\Driver\offload-Xarch.c' -Xarch_nvptx64 -O3 -S -nogpulib -nogpuinc '-###' # executed command: 'c:\buildbot\as-builder-1\x-armv7l\build\bin\filecheck.exe' -check-prefix=O3ONCE 'C:\buildbot\as-builder-1\x-armv7l\llvm-project\clang\test\Driver\offload-Xarch.c' # RUN: at line 4 c:\buildbot\as-builder-1\x-armv7l\build\bin\clang.exe -x cuda C:\buildbot\as-builder-1\x-armv7l\llvm-project\clang\test\Driver\offload-Xarch.c -Xarch_device -O3 -S -nogpulib -nogpuinc -### 2>&1 | c:\buildbot\as-builder-1\x-armv7l\build\bin\filecheck.exe -check-prefix=O3ONCE C:\buildbot\as-builder-1\x-armv7l\llvm-project\clang\test\Driver\offload-Xarch.c # executed command: 'c:\buildbot\as-builder-1\x-armv7l\build\bin\clang.exe' -x cuda 'C:\buildbot\as-builder-1\x-armv7l\llvm-project\clang\test\Driver\offload-Xarch.c' -Xarch_device -O3 -S -nogpulib -nogpuinc '-###' # executed command: 'c:\buildbot\as-builder-1\x-armv7l\build\bin\filecheck.exe' -check-prefix=O3ONCE 'C:\buildbot\as-builder-1\x-armv7l\llvm-project\clang\test\Driver\offload-Xarch.c' # RUN: at line 5 c:\buildbot\as-builder-1\x-armv7l\build\bin\clang.exe -x hip C:\buildbot\as-builder-1\x-armv7l\llvm-project\clang\test\Driver\offload-Xarch.c -Xarch_amdgcn -O3 -S -nogpulib -nogpuinc -### 2>&1 | c:\buildbot\as-builder-1\x-armv7l\build\bin\filecheck.exe -check-prefix=O3ONCE C:\buildbot\as-builder-1\x-armv7l\llvm-project\clang\test\Driver\offload-Xarch.c # executed command: 'c:\buildbot\as-builder-1\x-armv7l\build\bin\clang.exe' -x hip 'C:\buildbot\as-builder-1\x-armv7l\llvm-project\clang\test\Driver\offload-Xarch.c' -Xarch_amdgcn -O3 -S -nogpulib -nogpuinc '-###' # executed command: 'c:\buildbot\as-builder-1\x-armv7l\build\bin\filecheck.exe' -check-prefix=O3ONCE 'C:\buildbot\as-builder-1\x-armv7l\llvm-project\clang\test\Driver\offload-Xarch.c' # RUN: at line 6 c:\buildbot\as-builder-1\x-armv7l\build\bin\clang.exe -fopenmp=libomp -fopenmp-targets=amdgcn-amd-amdhsa -nogpulib -nogpuinc-Xarch_amdgcn -march=gfx90a -Xarch_amdgcn -O3 -S -### C:\buildbot\as-builder-1\x-armv7l\llvm-project\clang\test\Driver\offload-Xarch.c 2>&1 | c:\buildbot\as-builder-1\x-armv7l\build\bin\filecheck.exe -check-prefix=O3ONCE C:\buildbot\as-builder-1\x-armv7l\llvm-project\clang\test\Driver\offload-Xarch.c # executed command: 'c:\buildbot\as-builder-1\x-armv7l\build\bin\clang.exe' -fopenmp=libomp -fopenmp-targets=amdgcn-amd-amdhsa -nogpulib -nogpuinc -Xarch_amdgcn -march=gfx90a -Xarch_amdgcn -O3 -S '-###' 'C:\buildbot\as-builder-1\x-armv7l\llvm-project\clang\test\Driver\offload-Xarch.c' # executed command: 'c:\buildbot\as-builder-1\x-armv7l\build\bin\filecheck.exe' -check-prefix=O3ONCE 'C:\buildbot\as-builder-1\x-armv7l\llvm-project\clang\test\Driver\offload-Xarch.c' # RUN: at line 9 c:\buildbot\as-builder-1\x-armv7l\build\bin\clang.exe -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -nogpulib -nogpuinc-Xarch_nvptx64 -march=sm_52 -Xarch_nvptx64 -O3 -S -### C:\buildbot\as-builder-1\x-armv7l\llvm-project\clang\test\Driver\offload-Xarch.c 2>&1 | c:\buildbot\as-builder-1\x-armv7l\build\bin\filecheck.exe -check-prefix=O3ONCE C:\buildbot\as-builder-1\x-armv7l\llvm-project\clang\test\Driver\offload-Xarch.c # executed command: 'c:\buildbot\as-builder-1\x-armv7l\build\bin\clang.exe' -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda -nogpulib -nogpuinc -Xarch_nvptx64 -march=sm_52 -Xarch_nvptx64 -O3 -S '-###' 'C:\buildbot\as-builder-1\x-armv7l\llvm-project\clang\test\Driver\offload-Xarch.c' # executed command: 'c:\buildbot\as-builder-1\x-armv7l\build\bin\filecheck.exe' -check-prefix=O3ONCE 'C:\buildbot\as-builder-1\x-armv7l\llvm-project\clang\test\Driver\offload-Xarch.c' # RUN: at line 15 c:\buildbot\as-builder-1\x-armv7l\build\bin\clang.exe -fopenmp=libomp -fopenmp-targets=nvptx64-nvidia-cuda,amdgcn-amd-amdhsa -nogpulib --t
[clang] [clang][bytecode] Add Descriptor::dumpFull (PR #127386)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) Changes This is useful to print all (or most) of the valid offsets into a block of the given descriptor. --- Full diff: https://github.com/llvm/llvm-project/pull/127386.diff 2 Files Affected: - (modified) clang/lib/AST/ByteCode/Descriptor.h (+1) - (modified) clang/lib/AST/ByteCode/Disasm.cpp (+32) ``diff diff --git a/clang/lib/AST/ByteCode/Descriptor.h b/clang/lib/AST/ByteCode/Descriptor.h index 96c82a18913e0..01fa4b198de67 100644 --- a/clang/lib/AST/ByteCode/Descriptor.h +++ b/clang/lib/AST/ByteCode/Descriptor.h @@ -274,6 +274,7 @@ struct Descriptor final { void dump() const; void dump(llvm::raw_ostream &OS) const; + void dumpFull(unsigned Offset = 0, unsigned Indent = 0) const; }; /// Bitfield tracking the initialisation status of elements of primitive arrays. diff --git a/clang/lib/AST/ByteCode/Disasm.cpp b/clang/lib/AST/ByteCode/Disasm.cpp index 92a169a37c365..85fc30482b003 100644 --- a/clang/lib/AST/ByteCode/Disasm.cpp +++ b/clang/lib/AST/ByteCode/Disasm.cpp @@ -251,6 +251,38 @@ LLVM_DUMP_METHOD void Descriptor::dump(llvm::raw_ostream &OS) const { OS << " dummy"; } +/// Dump descriptor, including all valid offsets. +LLVM_DUMP_METHOD void Descriptor::dumpFull(unsigned Offset, + unsigned Indent) const { + unsigned Spaces = Indent * 2; + llvm::raw_ostream &OS = llvm::errs(); + OS.indent(Spaces); + dump(OS); + OS << '\n'; + OS.indent(Spaces) << "Metadata: " << getMetadataSize() << " bytes\n"; + OS.indent(Spaces) << "Size: " << getSize() << " bytes\n"; + OS.indent(Spaces) << "AllocSize: " << getAllocSize() << " bytes\n"; + Offset += getMetadataSize(); + if (isCompositeArray()) { +OS.indent(Spaces) << "Elements: " << getNumElems() << '\n'; +unsigned FO = Offset; +for (unsigned I = 0; I != getNumElems(); ++I) { + FO += sizeof(InlineDescriptor); + assert(ElemDesc->getMetadataSize() == 0); + OS.indent(Spaces) << "Element " << I << " offset: " << FO << '\n'; + ElemDesc->dumpFull(FO, Indent + 1); + + FO += ElemDesc->getAllocSize(); +} + } else if (isRecord()) { +ElemRecord->dump(OS, Indent + 1, Offset); + } else if (isPrimitive()) { + } else { + } + + OS << '\n'; +} + LLVM_DUMP_METHOD void InlineDescriptor::dump(llvm::raw_ostream &OS) const { { ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true}); `` https://github.com/llvm/llvm-project/pull/127386 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][bytecode] Fix dynamic array allocation return values (PR #127387)
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/127387 We need to return a pointer to the first element, not the array itself. >From eb8387d21d1b5455b9450802729cf407bfb9d703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Sun, 16 Feb 2025 09:43:50 +0100 Subject: [PATCH] [clang][bytecode] Fix dynamic array allocation return values We need to return a pointer to the first element, not the array itself. --- clang/lib/AST/ByteCode/DynamicAllocator.cpp | 2 + clang/lib/AST/ByteCode/Interp.h | 9 +--- clang/lib/AST/ByteCode/InterpBuiltin.cpp| 41 +++ clang/lib/AST/ByteCode/Program.cpp | 4 +- clang/test/AST/ByteCode/allocate-arrays.cpp | 55 + 5 files changed, 82 insertions(+), 29 deletions(-) create mode 100644 clang/test/AST/ByteCode/allocate-arrays.cpp diff --git a/clang/lib/AST/ByteCode/DynamicAllocator.cpp b/clang/lib/AST/ByteCode/DynamicAllocator.cpp index 819fbdb8b070b..3ef8c2e1f3e7c 100644 --- a/clang/lib/AST/ByteCode/DynamicAllocator.cpp +++ b/clang/lib/AST/ByteCode/DynamicAllocator.cpp @@ -54,6 +54,7 @@ Block *DynamicAllocator::allocate(const Expr *Source, PrimType T, Block *DynamicAllocator::allocate(const Descriptor *ElementDesc, size_t NumElements, unsigned EvalID, Form AllocForm) { + assert(ElementDesc->getMetadataSize() == 0); // Create a new descriptor for an array of the specified size and // element type. const Descriptor *D = allocateDescriptor( @@ -72,6 +73,7 @@ Block *DynamicAllocator::allocate(const Descriptor *D, unsigned EvalID, auto *B = new (Memory.get()) Block(EvalID, D, /*isStatic=*/false); B->invokeCtor(); + assert(D->getMetadataSize() == sizeof(InlineDescriptor)); InlineDescriptor *ID = reinterpret_cast(B->rawData()); ID->Desc = D; ID->IsActive = true; diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 5cc371c7ee495..73cc107b7dbff 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -2896,9 +2896,7 @@ inline bool Alloc(InterpState &S, CodePtr OpPC, const Descriptor *Desc) { Block *B = Allocator.allocate(Desc, S.Ctx.getEvalID(), DynamicAllocator::Form::NonArray); assert(B); - S.Stk.push(B); - return true; } @@ -2923,8 +2921,7 @@ inline bool AllocN(InterpState &S, CodePtr OpPC, PrimType T, const Expr *Source, Allocator.allocate(Source, T, static_cast(NumElements), S.Ctx.getEvalID(), DynamicAllocator::Form::Array); assert(B); - S.Stk.push(B, sizeof(InlineDescriptor)); - + S.Stk.push(B); return true; } @@ -2950,9 +2947,7 @@ inline bool AllocCN(InterpState &S, CodePtr OpPC, const Descriptor *ElementDesc, Allocator.allocate(ElementDesc, static_cast(NumElements), S.Ctx.getEvalID(), DynamicAllocator::Form::Array); assert(B); - - S.Stk.push(B, sizeof(InlineDescriptor)); - + S.Stk.push(B); return true; } diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 55ac41736344d..b964906fb6594 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -1655,27 +1655,27 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC, return false; } + bool IsArray = NumElems.ugt(1); std::optional ElemT = S.getContext().classify(ElemType); DynamicAllocator &Allocator = S.getAllocator(); if (ElemT) { -if (NumElems.ule(1)) { - const Descriptor *Desc = - S.P.createDescriptor(NewCall, *ElemT, Descriptor::InlineDescMD, - /*IsConst=*/false, /*IsTemporary=*/false, - /*IsMutable=*/false); - Block *B = Allocator.allocate(Desc, S.getContext().getEvalID(), +if (IsArray) { + Block *B = Allocator.allocate(NewCall, *ElemT, NumElems.getZExtValue(), +S.Ctx.getEvalID(), DynamicAllocator::Form::Operator); assert(B); - - S.Stk.push(B); + S.Stk.push(Pointer(B).atIndex(0)); return true; } -assert(NumElems.ugt(1)); -Block *B = -Allocator.allocate(NewCall, *ElemT, NumElems.getZExtValue(), - S.Ctx.getEvalID(), DynamicAllocator::Form::Operator); +const Descriptor *Desc = +S.P.createDescriptor(NewCall, *ElemT, Descriptor::InlineDescMD, + /*IsConst=*/false, /*IsTemporary=*/false, + /*IsMutable=*/false); +Block *B = Allocator.allocate(Desc, S.getContext().getEvalID(), + DynamicAllocator::Form::Operator); assert(B); + S.Stk.push(B); return true; } @@ -1683,21 +1683,22 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr
[clang] [clang][bytecode] Fix dynamic array allocation return values (PR #127387)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) Changes We need to return a pointer to the first element, not the array itself. --- Full diff: https://github.com/llvm/llvm-project/pull/127387.diff 5 Files Affected: - (modified) clang/lib/AST/ByteCode/DynamicAllocator.cpp (+2) - (modified) clang/lib/AST/ByteCode/Interp.h (+2-7) - (modified) clang/lib/AST/ByteCode/InterpBuiltin.cpp (+21-20) - (modified) clang/lib/AST/ByteCode/Program.cpp (+2-2) - (added) clang/test/AST/ByteCode/allocate-arrays.cpp (+55) ``diff diff --git a/clang/lib/AST/ByteCode/DynamicAllocator.cpp b/clang/lib/AST/ByteCode/DynamicAllocator.cpp index 819fbdb8b070b..3ef8c2e1f3e7c 100644 --- a/clang/lib/AST/ByteCode/DynamicAllocator.cpp +++ b/clang/lib/AST/ByteCode/DynamicAllocator.cpp @@ -54,6 +54,7 @@ Block *DynamicAllocator::allocate(const Expr *Source, PrimType T, Block *DynamicAllocator::allocate(const Descriptor *ElementDesc, size_t NumElements, unsigned EvalID, Form AllocForm) { + assert(ElementDesc->getMetadataSize() == 0); // Create a new descriptor for an array of the specified size and // element type. const Descriptor *D = allocateDescriptor( @@ -72,6 +73,7 @@ Block *DynamicAllocator::allocate(const Descriptor *D, unsigned EvalID, auto *B = new (Memory.get()) Block(EvalID, D, /*isStatic=*/false); B->invokeCtor(); + assert(D->getMetadataSize() == sizeof(InlineDescriptor)); InlineDescriptor *ID = reinterpret_cast(B->rawData()); ID->Desc = D; ID->IsActive = true; diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 5cc371c7ee495..73cc107b7dbff 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -2896,9 +2896,7 @@ inline bool Alloc(InterpState &S, CodePtr OpPC, const Descriptor *Desc) { Block *B = Allocator.allocate(Desc, S.Ctx.getEvalID(), DynamicAllocator::Form::NonArray); assert(B); - S.Stk.push(B); - return true; } @@ -2923,8 +2921,7 @@ inline bool AllocN(InterpState &S, CodePtr OpPC, PrimType T, const Expr *Source, Allocator.allocate(Source, T, static_cast(NumElements), S.Ctx.getEvalID(), DynamicAllocator::Form::Array); assert(B); - S.Stk.push(B, sizeof(InlineDescriptor)); - + S.Stk.push(B); return true; } @@ -2950,9 +2947,7 @@ inline bool AllocCN(InterpState &S, CodePtr OpPC, const Descriptor *ElementDesc, Allocator.allocate(ElementDesc, static_cast(NumElements), S.Ctx.getEvalID(), DynamicAllocator::Form::Array); assert(B); - - S.Stk.push(B, sizeof(InlineDescriptor)); - + S.Stk.push(B); return true; } diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 55ac41736344d..b964906fb6594 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -1655,27 +1655,27 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC, return false; } + bool IsArray = NumElems.ugt(1); std::optional ElemT = S.getContext().classify(ElemType); DynamicAllocator &Allocator = S.getAllocator(); if (ElemT) { -if (NumElems.ule(1)) { - const Descriptor *Desc = - S.P.createDescriptor(NewCall, *ElemT, Descriptor::InlineDescMD, - /*IsConst=*/false, /*IsTemporary=*/false, - /*IsMutable=*/false); - Block *B = Allocator.allocate(Desc, S.getContext().getEvalID(), +if (IsArray) { + Block *B = Allocator.allocate(NewCall, *ElemT, NumElems.getZExtValue(), +S.Ctx.getEvalID(), DynamicAllocator::Form::Operator); assert(B); - - S.Stk.push(B); + S.Stk.push(Pointer(B).atIndex(0)); return true; } -assert(NumElems.ugt(1)); -Block *B = -Allocator.allocate(NewCall, *ElemT, NumElems.getZExtValue(), - S.Ctx.getEvalID(), DynamicAllocator::Form::Operator); +const Descriptor *Desc = +S.P.createDescriptor(NewCall, *ElemT, Descriptor::InlineDescMD, + /*IsConst=*/false, /*IsTemporary=*/false, + /*IsMutable=*/false); +Block *B = Allocator.allocate(Desc, S.getContext().getEvalID(), + DynamicAllocator::Form::Operator); assert(B); + S.Stk.push(B); return true; } @@ -1683,21 +1683,22 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC, assert(!ElemT); // Structs etc. const Descriptor *Desc = S.P.createDescriptor( - NewCall, ElemType.getTypePtr(), Descriptor::InlineDescMD, + NewCall, ElemType.getTypePtr(), + IsArray ? std::nullopt : Descriptor::InlineDescMD, /*IsConst=*/false, /*IsTemporary=*/false, /*IsM
[clang] [clang][bytecode] Add Descriptor::dumpFull (PR #127386)
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/127386 This is useful to print all (or most) of the valid offsets into a block of the given descriptor. >From 990d0cf197e94d23fa8d9ef4be295bbb4dbacb84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Sun, 16 Feb 2025 11:41:51 +0100 Subject: [PATCH] [clang][bytecode] Add Descriptor::dumpFull This is useful to print all (or most) of the valid offsets into a block of the given descriptor. --- clang/lib/AST/ByteCode/Descriptor.h | 1 + clang/lib/AST/ByteCode/Disasm.cpp | 32 + 2 files changed, 33 insertions(+) diff --git a/clang/lib/AST/ByteCode/Descriptor.h b/clang/lib/AST/ByteCode/Descriptor.h index 96c82a18913e0..01fa4b198de67 100644 --- a/clang/lib/AST/ByteCode/Descriptor.h +++ b/clang/lib/AST/ByteCode/Descriptor.h @@ -274,6 +274,7 @@ struct Descriptor final { void dump() const; void dump(llvm::raw_ostream &OS) const; + void dumpFull(unsigned Offset = 0, unsigned Indent = 0) const; }; /// Bitfield tracking the initialisation status of elements of primitive arrays. diff --git a/clang/lib/AST/ByteCode/Disasm.cpp b/clang/lib/AST/ByteCode/Disasm.cpp index 92a169a37c365..85fc30482b003 100644 --- a/clang/lib/AST/ByteCode/Disasm.cpp +++ b/clang/lib/AST/ByteCode/Disasm.cpp @@ -251,6 +251,38 @@ LLVM_DUMP_METHOD void Descriptor::dump(llvm::raw_ostream &OS) const { OS << " dummy"; } +/// Dump descriptor, including all valid offsets. +LLVM_DUMP_METHOD void Descriptor::dumpFull(unsigned Offset, + unsigned Indent) const { + unsigned Spaces = Indent * 2; + llvm::raw_ostream &OS = llvm::errs(); + OS.indent(Spaces); + dump(OS); + OS << '\n'; + OS.indent(Spaces) << "Metadata: " << getMetadataSize() << " bytes\n"; + OS.indent(Spaces) << "Size: " << getSize() << " bytes\n"; + OS.indent(Spaces) << "AllocSize: " << getAllocSize() << " bytes\n"; + Offset += getMetadataSize(); + if (isCompositeArray()) { +OS.indent(Spaces) << "Elements: " << getNumElems() << '\n'; +unsigned FO = Offset; +for (unsigned I = 0; I != getNumElems(); ++I) { + FO += sizeof(InlineDescriptor); + assert(ElemDesc->getMetadataSize() == 0); + OS.indent(Spaces) << "Element " << I << " offset: " << FO << '\n'; + ElemDesc->dumpFull(FO, Indent + 1); + + FO += ElemDesc->getAllocSize(); +} + } else if (isRecord()) { +ElemRecord->dump(OS, Indent + 1, Offset); + } else if (isPrimitive()) { + } else { + } + + OS << '\n'; +} + LLVM_DUMP_METHOD void InlineDescriptor::dump(llvm::raw_ostream &OS) const { { ColorScope SC(OS, true, {llvm::raw_ostream::BLUE, true}); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Fix false positive for cppcoreguidelines-pro-bounds-pointer-arithmetic (PR #127394)
llvmbot wrote: @llvm/pr-subscribers-clang-tools-extra Author: None (flovent) Changes this PR fixs #126424 for `ArraySubScriptExpr`, `hasBase` Matcher will get right operand when it is not Integer type, but is not for sure that left operand is interger type. For the example code below `hasBase` will get `r` for the Subsequent matching and causing false positive. ``` templateint f(std::map & map, R* r) { return map[r]; } ``` so is needed to see if index is interger type to avoid this situation. --- Full diff: https://github.com/llvm/llvm-project/pull/127394.diff 3 Files Affected: - (modified) clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp (+2-1) - (modified) clang-tools-extra/docs/ReleaseNotes.rst (+4) - (added) clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic-issue126424.cpp (+19) ``diff diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp index a1494a095f5b6..0d68790349fb5 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp @@ -42,7 +42,8 @@ void ProBoundsPointerArithmeticCheck::registerMatchers(MatchFinder *Finder) { arraySubscriptExpr( hasBase(ignoringImpCasts( anyOf(AllPointerTypes, -hasType(decayedType(hasDecayedType(pointerType( +hasType(decayedType(hasDecayedType(pointerType())), + hasIndex(hasType(isInteger( .bind("expr"), this); } diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 6b8fe22242417..937d710fe6100 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -110,6 +110,10 @@ Changes in existing checks ` check by providing additional examples and fixing some macro related false positives. +- Improved :doc:`cppcoreguidelines-pro-bounds-pointer-arithmetic + ` check by + fix false positives related to operator overloading and templates. + Removed checks ^^ diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic-issue126424.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic-issue126424.cpp new file mode 100644 index 0..b6b7a9664f38d --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic-issue126424.cpp @@ -0,0 +1,19 @@ +// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-pointer-arithmetic %t + +namespace std { +template +class pair {}; + +template +class map { + public: + using value_type = pair; + value_type& operator[](const Key& key); + value_type& operator[](Key&& key); + }; +} + +template +int f(std::map& map, R* r) { + return map[r]; // OK +} \ No newline at end of file `` https://github.com/llvm/llvm-project/pull/127394 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Fix false positive for cppcoreguidelines-pro-bounds-pointer-arithmetic (PR #127394)
https://github.com/flovent updated https://github.com/llvm/llvm-project/pull/127394 >From 1bd661b60dbb350dcefad3556218bbec71a4f366 Mon Sep 17 00:00:00 2001 From: flovent Date: Sun, 16 Feb 2025 21:07:55 +0800 Subject: [PATCH 1/2] [clang-tidy] Fix false positive for cppcoreguidelines-pro-bounds-pointer-arithmetic --- .../ProBoundsPointerArithmeticCheck.cpp | 3 ++- clang-tools-extra/docs/ReleaseNotes.rst | 4 ...-bounds-pointer-arithmetic-issue126424.cpp | 19 +++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic-issue126424.cpp diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp index a1494a095f5b6..0d68790349fb5 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp @@ -42,7 +42,8 @@ void ProBoundsPointerArithmeticCheck::registerMatchers(MatchFinder *Finder) { arraySubscriptExpr( hasBase(ignoringImpCasts( anyOf(AllPointerTypes, -hasType(decayedType(hasDecayedType(pointerType( +hasType(decayedType(hasDecayedType(pointerType())), + hasIndex(hasType(isInteger( .bind("expr"), this); } diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 6b8fe22242417..937d710fe6100 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -110,6 +110,10 @@ Changes in existing checks ` check by providing additional examples and fixing some macro related false positives. +- Improved :doc:`cppcoreguidelines-pro-bounds-pointer-arithmetic + ` check by + fix false positives related to operator overloading and templates. + Removed checks ^^ diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic-issue126424.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic-issue126424.cpp new file mode 100644 index 0..b6b7a9664f38d --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic-issue126424.cpp @@ -0,0 +1,19 @@ +// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-pointer-arithmetic %t + +namespace std { +template +class pair {}; + +template +class map { + public: + using value_type = pair; + value_type& operator[](const Key& key); + value_type& operator[](Key&& key); + }; +} + +template +int f(std::map& map, R* r) { + return map[r]; // OK +} \ No newline at end of file >From ab8a217044821561a738e0ebf71a16b0d91fb897 Mon Sep 17 00:00:00 2001 From: flovent Date: Sun, 16 Feb 2025 21:18:45 +0800 Subject: [PATCH 2/2] add missing new line for testcase --- .../pro-bounds-pointer-arithmetic-issue126424.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic-issue126424.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic-issue126424.cpp index b6b7a9664f38d..a76798423ee17 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic-issue126424.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic-issue126424.cpp @@ -16,4 +16,4 @@ class map { template int f(std::map& map, R* r) { return map[r]; // OK -} \ No newline at end of file +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Fix false positive for cppcoreguidelines-pro-bounds-pointer-arithmetic (PR #127394)
llvmbot wrote: @llvm/pr-subscribers-clang-tidy Author: None (flovent) Changes this PR fixs #126424 for `ArraySubScriptExpr`, `hasBase` Matcher will get right operand when it is not Integer type, but is not for sure that left operand is interger type. For the example code below `hasBase` will get `r` for the Subsequent matching and causing false positive. ``` templateint f(std::map & map, R* r) { return map[r]; } ``` so is needed to see if index is interger type to avoid this situation. --- Full diff: https://github.com/llvm/llvm-project/pull/127394.diff 3 Files Affected: - (modified) clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp (+2-1) - (modified) clang-tools-extra/docs/ReleaseNotes.rst (+4) - (added) clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic-issue126424.cpp (+19) ``diff diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp index a1494a095f5b6..0d68790349fb5 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp @@ -42,7 +42,8 @@ void ProBoundsPointerArithmeticCheck::registerMatchers(MatchFinder *Finder) { arraySubscriptExpr( hasBase(ignoringImpCasts( anyOf(AllPointerTypes, -hasType(decayedType(hasDecayedType(pointerType( +hasType(decayedType(hasDecayedType(pointerType())), + hasIndex(hasType(isInteger( .bind("expr"), this); } diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 6b8fe22242417..937d710fe6100 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -110,6 +110,10 @@ Changes in existing checks ` check by providing additional examples and fixing some macro related false positives. +- Improved :doc:`cppcoreguidelines-pro-bounds-pointer-arithmetic + ` check by + fix false positives related to operator overloading and templates. + Removed checks ^^ diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic-issue126424.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic-issue126424.cpp new file mode 100644 index 0..b6b7a9664f38d --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic-issue126424.cpp @@ -0,0 +1,19 @@ +// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-pointer-arithmetic %t + +namespace std { +template +class pair {}; + +template +class map { + public: + using value_type = pair; + value_type& operator[](const Key& key); + value_type& operator[](Key&& key); + }; +} + +template +int f(std::map& map, R* r) { + return map[r]; // OK +} \ No newline at end of file `` https://github.com/llvm/llvm-project/pull/127394 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [libcxx] [llvm] [libc++][ranges] P2542R8: Implement `views::concat` (PR #120920)
https://github.com/frederick-vs-ja requested changes to this pull request. https://github.com/llvm/llvm-project/pull/120920 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [libcxx] [llvm] [libc++][ranges] P2542R8: Implement `views::concat` (PR #120920)
@@ -0,0 +1,638 @@ +// -*- C++ -*- +//===--===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#ifndef _LIBCPP___RANGES_CONCAT_VIEW_H +#define _LIBCPP___RANGES_CONCAT_VIEW_H + +#include <__algorithm/ranges_find_if.h> +#include <__assert> +#include <__concepts/common_reference_with.h> +#include <__concepts/constructible.h> +#include <__concepts/convertible_to.h> +#include <__concepts/copyable.h> +#include <__concepts/derived_from.h> +#include <__concepts/equality_comparable.h> +#include <__concepts/swappable.h> +#include <__config> +#include <__functional/bind_back.h> +#include <__functional/invoke.h> +#include <__functional/reference_wrapper.h> +#include <__iterator/concepts.h> +#include <__iterator/default_sentinel.h> +#include <__iterator/distance.h> +#include <__iterator/incrementable_traits.h> +#include <__iterator/iter_move.h> +#include <__iterator/iter_swap.h> +#include <__iterator/iterator_traits.h> +#include <__iterator/next.h> +#include <__memory/addressof.h> +#include <__ranges/access.h> +#include <__ranges/all.h> +#include <__ranges/concepts.h> +#include <__ranges/movable_box.h> +#include <__ranges/non_propagating_cache.h> +#include <__ranges/range_adaptor.h> +#include <__ranges/size.h> +#include <__ranges/view_interface.h> +#include <__ranges/zip_view.h> +#include <__type_traits/conditional.h> +#include <__type_traits/decay.h> +#include <__type_traits/is_nothrow_constructible.h> +#include <__type_traits/is_nothrow_convertible.h> +#include <__type_traits/is_object.h> +#include <__type_traits/make_unsigned.h> +#include <__type_traits/maybe_const.h> +#include <__utility/forward.h> +#include <__utility/in_place.h> +#include <__utility/move.h> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 26 + +namespace ranges { + +# ifdef __cpp_pack_indexing +template +using __extract_last _LIBCPP_NODEBUG = _Tp...[sizeof...(_Tp) - 1]; +# else +template +struct __extract_last_impl : __extract_last_impl<_Tail...> {}; +template +struct __extract_last_impl<_Tp> { + using type _LIBCPP_NODEBUG = _Tp; +}; + +template +using __extract_last _LIBCPP_NODEBUG = __extract_last_impl<_Tp...>::type; +# endif + +template +constexpr bool __derived_from_pack = +__derived_from_pack<_Tp, __extract_last<_Tail...>> && __derived_from_pack<_Tail...>; + +template +constexpr bool __derived_from_pack<_Tp, _IterCategory> = derived_from<_Tp, _IterCategory>; + +template +struct __last_view : __last_view<_Views...> {}; + +template +struct __last_view<_View> { + using type = _View; +}; + +template +concept __concat_indirectly_readable_impl = requires(const _It __it) { + { *__it } -> convertible_to<_Ref>; + { ranges::iter_move(__it) } -> convertible_to<_RRef>; +}; + +template +using __concat_reference_t _LIBCPP_NODEBUG = common_reference_t...>; + +template +using __concat_value_t _LIBCPP_NODEBUG = common_type_t...>; + +template +using __concat_rvalue_reference_t _LIBCPP_NODEBUG = common_reference_t...>; + +template +concept __concat_indirectly_readable = +common_reference_with<__concat_reference_t<_Rs...>&&, __concat_value_t<_Rs...>&> && +common_reference_with<__concat_reference_t<_Rs...>&&, __concat_rvalue_reference_t<_Rs...>&&> && +common_reference_with<__concat_rvalue_reference_t<_Rs...>&&, __concat_value_t<_Rs...> const&> && +(__concat_indirectly_readable_impl<__concat_reference_t<_Rs...>, + __concat_rvalue_reference_t<_Rs...>, + iterator_t<_Rs>> && + ...); + +template +concept __concatable = requires { + typename __concat_reference_t<_Rs...>; + typename __concat_value_t<_Rs...>; + typename __concat_rvalue_reference_t<_Rs...>; +} && __concat_indirectly_readable<_Rs...>; + +template +concept __concat_is_random_access = +(random_access_range<__maybe_const<_Const, _Rs>> && ...) && (sized_range<__maybe_const<_Const, _Rs>> && ...); + +template +concept __concat_is_bidirectional = +((bidirectional_range<__maybe_const<_Const, _Rs>> && ...) && (common_range<__maybe_const<_Const, _Rs>> && ...)); + +template +concept __all_forward = (forward_range<__maybe_const<_Const, _Views>> && ...); + +template +struct __apply_drop_first; + +template +struct __apply_drop_first<_Const, _Head, _Tail...> { + static constexpr bool value = (sized_range<__maybe_const<_Const, _Tail>> && ...); +}; + +template + requires(view<_Views> && ...) && (sizeof...(_Views) > 0) && __concatable<_Views...> +class concat_view : public view
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,626 @@ +#!/usr/bin/env python3 + +""" generate_unsupported_in_drivermode.py + +usage: python generate_unsupported_in_drivermode.py /Options.td [/llvm-tblgen] + +This script generates a Lit regression test file that validates that options +are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be +provided on the command line. See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the +script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverController, specifically the check_string. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import sys +import shutil +import os +import json +import subprocess +import math +from pathlib import Path + +LLVM_TABLEGEN = "llvm-tblgen" +LIT_TEST_PATH = "../test/Driver/unsupported_in_drivermode.c" +LIT_TEST_PATH_FLANG = "../test/Driver/flang/unsupported_in_flang.f90" +INCLUDE_PATH = "../../llvm/include" + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Strings used in the commands to be tested +CLANG = "clang" +CLANG_CL = f"{CLANG} --driver-mode=cl" +CLANG_DXC = f"{CLANG} --driver-mode=dxc" +FLANG = f"{CLANG} --driver-mode=flang" +CLANG_LIT = "%clang" +CLANG_CL_LIT = "%clang_cl" +CLANG_DXC_LIT = "%clang_dxc" +FLANG_LIT = f"%{FLANG}" +OPTION_HASH = "-###" +OPTION_X = "-x" +OPTION_WX = "/WX" +OPTION_CPP = "c++" +OPTION_C = "-c" +OPTION_CC1 = "-cc1" +OPTION_CC1AS = "-cc1as" +OPTION_FC1 = "-fc1" +OPTION_SLASH_C = "/c" +OPTION_T = "/T lib_6_7" +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class DriverController: +"""Controller for data specific to each driver +shell_cmd_prefix: The beginning string of the command to be tested +lit_cmd_prefix: The beginning string of the Lit command +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +shell_cmd_suffix: Strings near the end of the command to be tested +check_string: The string or regex to be sent to FileCheck +lit_cmd_end: String at the end of the Lit command + +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind KIND_JOINED*, as defined in Options.td +""" + +def __init__( +self, +shell_cmd_prefix="", +lit_cmd_prefix="", +visibility_str="", +shell_cmd_suffix="", +check_string="{{(unknown argument|n?N?o such file or directory)}}", +lit_cmd_end=" - < /dev/null 2>&1 | FileCheck -check-prefix=", +): +self.shell_cmd_prefix = shell_cmd_prefix +self.lit_cmd_prefix = lit_cmd_prefix +self.visibility_str = visibility_str +self.shell_cmd_suffix = shell_cmd_suffix +self.supported_sequence = [] +self.check_string = check_string +self.lit_cmd_end = lit_cmd_end + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +is_error: Boolean indicating whether the corresponding command generates an error +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix +self.is_error = True + +# For sorting +def __len__(self): +return len(self.option_name) + + +def print_usage(): +"""Print valid usage of this script""" +sys.exit("usage: python " + sys.argv[0] + " /Options.td
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix + +# For sorting +def __len__(self): +return len(self.option_name) + +def __lt__(self, other): +return len(self.option_name) > len(other.option_name) + + +@dataclass +class DriverData: +"""Dataclass for data specific to each driver +lit_cmd_prefix: The beginning string of the Lit command +lit_cmd_options: Strings containing additional options for this driver +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +lit_cmd_end: String at the end of the Lit command +check_str: The string or regex to be sent to FileCheck +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind *JOINED*, as defined in Options.td +test_option_sequence: A list of all the prefix-option pairs that will be tested for this driver +""" + +lit_cmd_prefix: str +lit_cmd_options: str +visibility_str: str +lit_cmd_end: str = " - < /dev/null 2>&1 | FileCheck -check-prefix=CHECK-COUNT-" +check_str: str = "{{(unknown argument|n?N?o such file or directory)}}" +supported_sequence: list[UnsupportedDriverOption] = dataclasses.field( +default_factory=list +) +test_option_sequence: list[str] = dataclasses.field(default_factory=list) + + +def find_groups(options_dictionary, option): +"""Find the groups for a given option +Note that groups can themselves be part of groups, hence the recursion + +For example, considering option "C", it has the following 'Group' list as defined by Options.td: + "Group": { +"def": "Preprocessor_Group", +"kind": "def", +"printable": "Preprocessor_Group" + }, +Preprocessor_Group is itself part of CompileOnly_Group, so option C would be part of both groups + "Group": { +"def": "CompileOnly_Group", +"kind": "def", +"printable": "CompileOnly_Group" + }, + +options_dictionary: The converted Python dictionary from the Options.td json string +option: The option object from Options.td + +Return: A set including the group found for the option +""" +group_list = options_dictionary[option]["Group"] + +if group_list is None: +return None +found_group = group_list["def"] +
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix + +# For sorting +def __len__(self): +return len(self.option_name) + +def __lt__(self, other): +return len(self.option_name) > len(other.option_name) + + +@dataclass +class DriverData: +"""Dataclass for data specific to each driver +lit_cmd_prefix: The beginning string of the Lit command +lit_cmd_options: Strings containing additional options for this driver +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +lit_cmd_end: String at the end of the Lit command +check_str: The string or regex to be sent to FileCheck +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind *JOINED*, as defined in Options.td +test_option_sequence: A list of all the prefix-option pairs that will be tested for this driver +""" + +lit_cmd_prefix: str +lit_cmd_options: str +visibility_str: str +lit_cmd_end: str = " - < /dev/null 2>&1 | FileCheck -check-prefix=CHECK-COUNT-" +check_str: str = "{{(unknown argument|n?N?o such file or directory)}}" +supported_sequence: list[UnsupportedDriverOption] = dataclasses.field( +default_factory=list +) +test_option_sequence: list[str] = dataclasses.field(default_factory=list) + + +def find_groups(options_dictionary, option): +"""Find the groups for a given option +Note that groups can themselves be part of groups, hence the recursion + +For example, considering option "C", it has the following 'Group' list as defined by Options.td: + "Group": { +"def": "Preprocessor_Group", +"kind": "def", +"printable": "Preprocessor_Group" + }, +Preprocessor_Group is itself part of CompileOnly_Group, so option C would be part of both groups + "Group": { +"def": "CompileOnly_Group", +"kind": "def", +"printable": "CompileOnly_Group" + }, + +options_dictionary: The converted Python dictionary from the Options.td json string +option: The option object from Options.td + +Return: A set including the group found for the option +""" +group_list = options_dictionary[option]["Group"] + +if group_list is None: +return None +found_group = group_list["def"] +
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,626 @@ +#!/usr/bin/env python3 + +""" generate_unsupported_in_drivermode.py + +usage: python generate_unsupported_in_drivermode.py /Options.td [/llvm-tblgen] + +This script generates a Lit regression test file that validates that options +are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be +provided on the command line. See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the +script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverController, specifically the check_string. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import sys +import shutil +import os +import json +import subprocess +import math +from pathlib import Path + +LLVM_TABLEGEN = "llvm-tblgen" +LIT_TEST_PATH = "../test/Driver/unsupported_in_drivermode.c" +LIT_TEST_PATH_FLANG = "../test/Driver/flang/unsupported_in_flang.f90" +INCLUDE_PATH = "../../llvm/include" + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Strings used in the commands to be tested +CLANG = "clang" +CLANG_CL = f"{CLANG} --driver-mode=cl" +CLANG_DXC = f"{CLANG} --driver-mode=dxc" +FLANG = f"{CLANG} --driver-mode=flang" +CLANG_LIT = "%clang" +CLANG_CL_LIT = "%clang_cl" +CLANG_DXC_LIT = "%clang_dxc" +FLANG_LIT = f"%{FLANG}" +OPTION_HASH = "-###" +OPTION_X = "-x" +OPTION_WX = "/WX" +OPTION_CPP = "c++" +OPTION_C = "-c" +OPTION_CC1 = "-cc1" +OPTION_CC1AS = "-cc1as" +OPTION_FC1 = "-fc1" +OPTION_SLASH_C = "/c" +OPTION_T = "/T lib_6_7" +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class DriverController: +"""Controller for data specific to each driver +shell_cmd_prefix: The beginning string of the command to be tested +lit_cmd_prefix: The beginning string of the Lit command +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +shell_cmd_suffix: Strings near the end of the command to be tested +check_string: The string or regex to be sent to FileCheck +lit_cmd_end: String at the end of the Lit command + +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind KIND_JOINED*, as defined in Options.td +""" + +def __init__( +self, +shell_cmd_prefix="", +lit_cmd_prefix="", +visibility_str="", +shell_cmd_suffix="", +check_string="{{(unknown argument|n?N?o such file or directory)}}", +lit_cmd_end=" - < /dev/null 2>&1 | FileCheck -check-prefix=", +): +self.shell_cmd_prefix = shell_cmd_prefix +self.lit_cmd_prefix = lit_cmd_prefix +self.visibility_str = visibility_str +self.shell_cmd_suffix = shell_cmd_suffix +self.supported_sequence = [] +self.check_string = check_string +self.lit_cmd_end = lit_cmd_end + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +is_error: Boolean indicating whether the corresponding command generates an error +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix +self.is_error = True + +# For sorting +def __len__(self): +return len(self.option_name) + + +def print_usage(): +"""Print valid usage of this script""" +sys.exit("usage: python " + sys.argv[0] + " /Options.td
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix + +# For sorting +def __len__(self): +return len(self.option_name) + +def __lt__(self, other): +return len(self.option_name) > len(other.option_name) + + +@dataclass +class DriverData: +"""Dataclass for data specific to each driver +lit_cmd_prefix: The beginning string of the Lit command +lit_cmd_options: Strings containing additional options for this driver +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +lit_cmd_end: String at the end of the Lit command +check_str: The string or regex to be sent to FileCheck +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind *JOINED*, as defined in Options.td +test_option_sequence: A list of all the prefix-option pairs that will be tested for this driver +""" + +lit_cmd_prefix: str +lit_cmd_options: str +visibility_str: str +lit_cmd_end: str = " - < /dev/null 2>&1 | FileCheck -check-prefix=CHECK-COUNT-" +check_str: str = "{{(unknown argument|n?N?o such file or directory)}}" +supported_sequence: list[UnsupportedDriverOption] = dataclasses.field( +default_factory=list +) +test_option_sequence: list[str] = dataclasses.field(default_factory=list) + + +def find_groups(options_dictionary, option): +"""Find the groups for a given option +Note that groups can themselves be part of groups, hence the recursion + +For example, considering option "C", it has the following 'Group' list as defined by Options.td: + "Group": { +"def": "Preprocessor_Group", +"kind": "def", +"printable": "Preprocessor_Group" + }, +Preprocessor_Group is itself part of CompileOnly_Group, so option C would be part of both groups + "Group": { +"def": "CompileOnly_Group", +"kind": "def", +"printable": "CompileOnly_Group" + }, + +options_dictionary: The converted Python dictionary from the Options.td json string +option: The option object from Options.td + +Return: A set including the group found for the option +""" +group_list = options_dictionary[option]["Group"] + +if group_list is None: +return None +found_group = group_list["def"] +
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix + +# For sorting +def __len__(self): +return len(self.option_name) + +def __lt__(self, other): +return len(self.option_name) > len(other.option_name) + + +@dataclass +class DriverData: +"""Dataclass for data specific to each driver +lit_cmd_prefix: The beginning string of the Lit command +lit_cmd_options: Strings containing additional options for this driver +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +lit_cmd_end: String at the end of the Lit command +check_str: The string or regex to be sent to FileCheck +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind *JOINED*, as defined in Options.td +test_option_sequence: A list of all the prefix-option pairs that will be tested for this driver +""" + +lit_cmd_prefix: str +lit_cmd_options: str +visibility_str: str +lit_cmd_end: str = " - < /dev/null 2>&1 | FileCheck -check-prefix=CHECK-COUNT-" +check_str: str = "{{(unknown argument|n?N?o such file or directory)}}" +supported_sequence: list[UnsupportedDriverOption] = dataclasses.field( +default_factory=list +) +test_option_sequence: list[str] = dataclasses.field(default_factory=list) + + +def find_groups(options_dictionary, option): +"""Find the groups for a given option +Note that groups can themselves be part of groups, hence the recursion + +For example, considering option "C", it has the following 'Group' list as defined by Options.td: + "Group": { +"def": "Preprocessor_Group", +"kind": "def", +"printable": "Preprocessor_Group" + }, +Preprocessor_Group is itself part of CompileOnly_Group, so option C would be part of both groups + "Group": { +"def": "CompileOnly_Group", +"kind": "def", +"printable": "CompileOnly_Group" + }, + +options_dictionary: The converted Python dictionary from the Options.td json string +option: The option object from Options.td + +Return: A set including the group found for the option +""" +group_list = options_dictionary[option]["Group"] + +if group_list is None: +return None +found_group = group_list["def"] +
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,626 @@ +#!/usr/bin/env python3 + +""" generate_unsupported_in_drivermode.py + +usage: python generate_unsupported_in_drivermode.py /Options.td [/llvm-tblgen] + +This script generates a Lit regression test file that validates that options +are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be +provided on the command line. See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the +script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverController, specifically the check_string. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import sys +import shutil +import os +import json +import subprocess +import math +from pathlib import Path + +LLVM_TABLEGEN = "llvm-tblgen" +LIT_TEST_PATH = "../test/Driver/unsupported_in_drivermode.c" +LIT_TEST_PATH_FLANG = "../test/Driver/flang/unsupported_in_flang.f90" +INCLUDE_PATH = "../../llvm/include" + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Strings used in the commands to be tested +CLANG = "clang" +CLANG_CL = f"{CLANG} --driver-mode=cl" +CLANG_DXC = f"{CLANG} --driver-mode=dxc" +FLANG = f"{CLANG} --driver-mode=flang" +CLANG_LIT = "%clang" +CLANG_CL_LIT = "%clang_cl" +CLANG_DXC_LIT = "%clang_dxc" +FLANG_LIT = f"%{FLANG}" +OPTION_HASH = "-###" +OPTION_X = "-x" +OPTION_WX = "/WX" +OPTION_CPP = "c++" +OPTION_C = "-c" +OPTION_CC1 = "-cc1" +OPTION_CC1AS = "-cc1as" +OPTION_FC1 = "-fc1" +OPTION_SLASH_C = "/c" +OPTION_T = "/T lib_6_7" +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class DriverController: +"""Controller for data specific to each driver +shell_cmd_prefix: The beginning string of the command to be tested +lit_cmd_prefix: The beginning string of the Lit command +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +shell_cmd_suffix: Strings near the end of the command to be tested +check_string: The string or regex to be sent to FileCheck +lit_cmd_end: String at the end of the Lit command + +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind KIND_JOINED*, as defined in Options.td +""" + +def __init__( +self, +shell_cmd_prefix="", +lit_cmd_prefix="", +visibility_str="", +shell_cmd_suffix="", +check_string="{{(unknown argument|n?N?o such file or directory)}}", +lit_cmd_end=" - < /dev/null 2>&1 | FileCheck -check-prefix=", +): +self.shell_cmd_prefix = shell_cmd_prefix +self.lit_cmd_prefix = lit_cmd_prefix +self.visibility_str = visibility_str +self.shell_cmd_suffix = shell_cmd_suffix +self.supported_sequence = [] +self.check_string = check_string +self.lit_cmd_end = lit_cmd_end + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +is_error: Boolean indicating whether the corresponding command generates an error +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix +self.is_error = True + +# For sorting +def __len__(self): +return len(self.option_name) + + +def print_usage(): +"""Print valid usage of this script""" +sys.exit("usage: python " + sys.argv[0] + " /Options.td
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
https://github.com/Maetveis requested changes to this pull request. Thanks, this is starting to look right. I'm sorry for the long response time, I could not justify spending work time on the review this time, and my weekends have been somewhat busy. I'll try to get some other reviewers to look at this too, to approve of the proposed workflow when updating Options.td. I would appreciate if you could make a summary of that as a comment, but if not I'll do it later. https://github.com/llvm/llvm-project/pull/120900 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix + +# For sorting +def __len__(self): +return len(self.option_name) + +def __lt__(self, other): +return len(self.option_name) > len(other.option_name) + + +@dataclass +class DriverData: +"""Dataclass for data specific to each driver +lit_cmd_prefix: The beginning string of the Lit command +lit_cmd_options: Strings containing additional options for this driver +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +lit_cmd_end: String at the end of the Lit command +check_str: The string or regex to be sent to FileCheck +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind *JOINED*, as defined in Options.td +test_option_sequence: A list of all the prefix-option pairs that will be tested for this driver +""" + +lit_cmd_prefix: str +lit_cmd_options: str +visibility_str: str +lit_cmd_end: str = " - < /dev/null 2>&1 | FileCheck -check-prefix=CHECK-COUNT-" +check_str: str = "{{(unknown argument|n?N?o such file or directory)}}" +supported_sequence: list[UnsupportedDriverOption] = dataclasses.field( +default_factory=list +) +test_option_sequence: list[str] = dataclasses.field(default_factory=list) + + +def find_groups(options_dictionary, option): +"""Find the groups for a given option +Note that groups can themselves be part of groups, hence the recursion + +For example, considering option "C", it has the following 'Group' list as defined by Options.td: + "Group": { +"def": "Preprocessor_Group", +"kind": "def", +"printable": "Preprocessor_Group" + }, +Preprocessor_Group is itself part of CompileOnly_Group, so option C would be part of both groups + "Group": { +"def": "CompileOnly_Group", +"kind": "def", +"printable": "CompileOnly_Group" + }, + +options_dictionary: The converted Python dictionary from the Options.td json string +option: The option object from Options.td + +Return: A set including the group found for the option +""" +group_list = options_dictionary[option]["Group"] + +if group_list is None: +return None +found_group = group_list["def"] +
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix Maetveis wrote: This class can also be a `dataclass`. https://github.com/llvm/llvm-project/pull/120900 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix + +# For sorting +def __len__(self): +return len(self.option_name) + +def __lt__(self, other): +return len(self.option_name) > len(other.option_name) + + +@dataclass +class DriverData: +"""Dataclass for data specific to each driver +lit_cmd_prefix: The beginning string of the Lit command +lit_cmd_options: Strings containing additional options for this driver +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +lit_cmd_end: String at the end of the Lit command +check_str: The string or regex to be sent to FileCheck +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind *JOINED*, as defined in Options.td +test_option_sequence: A list of all the prefix-option pairs that will be tested for this driver +""" + +lit_cmd_prefix: str +lit_cmd_options: str +visibility_str: str +lit_cmd_end: str = " - < /dev/null 2>&1 | FileCheck -check-prefix=CHECK-COUNT-" +check_str: str = "{{(unknown argument|n?N?o such file or directory)}}" Maetveis wrote: ```suggestion lit_cmd_end: str = " - < /dev/null 2>&1 | FileCheck -check-prefix=CHECK-COUNT-" check_str: str = "{{(unknown argument|[Nn]o such file or directory)}}" ``` we wish to match either capital or lower case 'n', but shouldn't allow 'o such file or directory'. https://github.com/llvm/llvm-project/pull/120900 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination Maetveis wrote: The name is now a bit redundant and misleading since it's also as elements for `supported_sequence`. ```suggestion class DriverOption: """A driver and option pair ``` https://github.com/llvm/llvm-project/pull/120900 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix + +# For sorting +def __len__(self): +return len(self.option_name) + +def __lt__(self, other): +return len(self.option_name) > len(other.option_name) + + +@dataclass +class DriverData: +"""Dataclass for data specific to each driver +lit_cmd_prefix: The beginning string of the Lit command +lit_cmd_options: Strings containing additional options for this driver +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +lit_cmd_end: String at the end of the Lit command +check_str: The string or regex to be sent to FileCheck +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind *JOINED*, as defined in Options.td +test_option_sequence: A list of all the prefix-option pairs that will be tested for this driver +""" + +lit_cmd_prefix: str +lit_cmd_options: str +visibility_str: str +lit_cmd_end: str = " - < /dev/null 2>&1 | FileCheck -check-prefix=CHECK-COUNT-" +check_str: str = "{{(unknown argument|n?N?o such file or directory)}}" +supported_sequence: list[UnsupportedDriverOption] = dataclasses.field( +default_factory=list +) +test_option_sequence: list[str] = dataclasses.field(default_factory=list) + + +def find_groups(options_dictionary, option): +"""Find the groups for a given option +Note that groups can themselves be part of groups, hence the recursion + +For example, considering option "C", it has the following 'Group' list as defined by Options.td: + "Group": { +"def": "Preprocessor_Group", +"kind": "def", +"printable": "Preprocessor_Group" + }, +Preprocessor_Group is itself part of CompileOnly_Group, so option C would be part of both groups + "Group": { +"def": "CompileOnly_Group", +"kind": "def", +"printable": "CompileOnly_Group" + }, + +options_dictionary: The converted Python dictionary from the Options.td json string +option: The option object from Options.td + +Return: A set including the group found for the option +""" +group_list = options_dictionary[option]["Group"] + +if group_list is None: +return None +found_group = group_list["def"] +
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix + +# For sorting +def __len__(self): +return len(self.option_name) + +def __lt__(self, other): +return len(self.option_name) > len(other.option_name) + + +@dataclass +class DriverData: +"""Dataclass for data specific to each driver +lit_cmd_prefix: The beginning string of the Lit command +lit_cmd_options: Strings containing additional options for this driver +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +lit_cmd_end: String at the end of the Lit command +check_str: The string or regex to be sent to FileCheck +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind *JOINED*, as defined in Options.td +test_option_sequence: A list of all the prefix-option pairs that will be tested for this driver +""" + +lit_cmd_prefix: str +lit_cmd_options: str +visibility_str: str +lit_cmd_end: str = " - < /dev/null 2>&1 | FileCheck -check-prefix=CHECK-COUNT-" +check_str: str = "{{(unknown argument|n?N?o such file or directory)}}" +supported_sequence: list[UnsupportedDriverOption] = dataclasses.field( +default_factory=list +) +test_option_sequence: list[str] = dataclasses.field(default_factory=list) + + +def find_groups(options_dictionary, option): +"""Find the groups for a given option +Note that groups can themselves be part of groups, hence the recursion + +For example, considering option "C", it has the following 'Group' list as defined by Options.td: + "Group": { +"def": "Preprocessor_Group", +"kind": "def", +"printable": "Preprocessor_Group" + }, +Preprocessor_Group is itself part of CompileOnly_Group, so option C would be part of both groups + "Group": { +"def": "CompileOnly_Group", +"kind": "def", +"printable": "CompileOnly_Group" + }, + +options_dictionary: The converted Python dictionary from the Options.td json string +option: The option object from Options.td + +Return: A set including the group found for the option +""" +group_list = options_dictionary[option]["Group"] + +if group_list is None: +return None +found_group = group_list["def"] +
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix + +# For sorting +def __len__(self): +return len(self.option_name) + +def __lt__(self, other): +return len(self.option_name) > len(other.option_name) + + +@dataclass +class DriverData: +"""Dataclass for data specific to each driver +lit_cmd_prefix: The beginning string of the Lit command +lit_cmd_options: Strings containing additional options for this driver +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +lit_cmd_end: String at the end of the Lit command +check_str: The string or regex to be sent to FileCheck +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind *JOINED*, as defined in Options.td +test_option_sequence: A list of all the prefix-option pairs that will be tested for this driver +""" + +lit_cmd_prefix: str +lit_cmd_options: str +visibility_str: str +lit_cmd_end: str = " - < /dev/null 2>&1 | FileCheck -check-prefix=CHECK-COUNT-" +check_str: str = "{{(unknown argument|n?N?o such file or directory)}}" +supported_sequence: list[UnsupportedDriverOption] = dataclasses.field( +default_factory=list +) +test_option_sequence: list[str] = dataclasses.field(default_factory=list) + + +def find_groups(options_dictionary, option): Maetveis wrote: ```suggestion def collect_transitive_groups(option, options_dictionary): ``` - Find in the name implies searching in some set, I think a better name would be `collect_groups` or `collect_transitive_groups` to be even more specific. - Personally I'd make `option` the first parameter, its the "direct object" that the function is operating on, and also the one on which the function is recursive. I think this makes reading the implementation of the function easier. https://github.com/llvm/llvm-project/pull/120900 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix + +# For sorting +def __len__(self): +return len(self.option_name) + +def __lt__(self, other): +return len(self.option_name) > len(other.option_name) + + +@dataclass +class DriverData: +"""Dataclass for data specific to each driver +lit_cmd_prefix: The beginning string of the Lit command +lit_cmd_options: Strings containing additional options for this driver +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +lit_cmd_end: String at the end of the Lit command +check_str: The string or regex to be sent to FileCheck +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind *JOINED*, as defined in Options.td +test_option_sequence: A list of all the prefix-option pairs that will be tested for this driver +""" + +lit_cmd_prefix: str +lit_cmd_options: str +visibility_str: str +lit_cmd_end: str = " - < /dev/null 2>&1 | FileCheck -check-prefix=CHECK-COUNT-" +check_str: str = "{{(unknown argument|n?N?o such file or directory)}}" +supported_sequence: list[UnsupportedDriverOption] = dataclasses.field( +default_factory=list +) +test_option_sequence: list[str] = dataclasses.field(default_factory=list) + + +def find_groups(options_dictionary, option): +"""Find the groups for a given option +Note that groups can themselves be part of groups, hence the recursion + +For example, considering option "C", it has the following 'Group' list as defined by Options.td: + "Group": { +"def": "Preprocessor_Group", +"kind": "def", +"printable": "Preprocessor_Group" + }, +Preprocessor_Group is itself part of CompileOnly_Group, so option C would be part of both groups + "Group": { +"def": "CompileOnly_Group", +"kind": "def", +"printable": "CompileOnly_Group" + }, + +options_dictionary: The converted Python dictionary from the Options.td json string +option: The option object from Options.td + +Return: A set including the group found for the option +""" +group_list = options_dictionary[option]["Group"] + +if group_list is None: +return None +found_group = group_list["def"] +
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix + +# For sorting +def __len__(self): +return len(self.option_name) + +def __lt__(self, other): +return len(self.option_name) > len(other.option_name) + + +@dataclass +class DriverData: +"""Dataclass for data specific to each driver +lit_cmd_prefix: The beginning string of the Lit command +lit_cmd_options: Strings containing additional options for this driver +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +lit_cmd_end: String at the end of the Lit command +check_str: The string or regex to be sent to FileCheck +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind *JOINED*, as defined in Options.td +test_option_sequence: A list of all the prefix-option pairs that will be tested for this driver +""" + +lit_cmd_prefix: str +lit_cmd_options: str +visibility_str: str +lit_cmd_end: str = " - < /dev/null 2>&1 | FileCheck -check-prefix=CHECK-COUNT-" +check_str: str = "{{(unknown argument|n?N?o such file or directory)}}" +supported_sequence: list[UnsupportedDriverOption] = dataclasses.field( +default_factory=list +) +test_option_sequence: list[str] = dataclasses.field(default_factory=list) + + +def find_groups(options_dictionary, option): +"""Find the groups for a given option +Note that groups can themselves be part of groups, hence the recursion + +For example, considering option "C", it has the following 'Group' list as defined by Options.td: + "Group": { +"def": "Preprocessor_Group", +"kind": "def", +"printable": "Preprocessor_Group" + }, +Preprocessor_Group is itself part of CompileOnly_Group, so option C would be part of both groups + "Group": { +"def": "CompileOnly_Group", +"kind": "def", +"printable": "CompileOnly_Group" + }, + +options_dictionary: The converted Python dictionary from the Options.td json string +option: The option object from Options.td + +Return: A set including the group found for the option +""" +group_list = options_dictionary[option]["Group"] + +if group_list is None: +return None +found_group = group_list["def"] +
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix + +# For sorting +def __len__(self): +return len(self.option_name) + +def __lt__(self, other): +return len(self.option_name) > len(other.option_name) + + +@dataclass +class DriverData: +"""Dataclass for data specific to each driver +lit_cmd_prefix: The beginning string of the Lit command +lit_cmd_options: Strings containing additional options for this driver +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +lit_cmd_end: String at the end of the Lit command +check_str: The string or regex to be sent to FileCheck +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind *JOINED*, as defined in Options.td +test_option_sequence: A list of all the prefix-option pairs that will be tested for this driver +""" + +lit_cmd_prefix: str +lit_cmd_options: str +visibility_str: str +lit_cmd_end: str = " - < /dev/null 2>&1 | FileCheck -check-prefix=CHECK-COUNT-" +check_str: str = "{{(unknown argument|n?N?o such file or directory)}}" +supported_sequence: list[UnsupportedDriverOption] = dataclasses.field( +default_factory=list +) +test_option_sequence: list[str] = dataclasses.field(default_factory=list) + + +def find_groups(options_dictionary, option): +"""Find the groups for a given option +Note that groups can themselves be part of groups, hence the recursion + +For example, considering option "C", it has the following 'Group' list as defined by Options.td: + "Group": { +"def": "Preprocessor_Group", +"kind": "def", +"printable": "Preprocessor_Group" + }, +Preprocessor_Group is itself part of CompileOnly_Group, so option C would be part of both groups + "Group": { +"def": "CompileOnly_Group", +"kind": "def", +"printable": "CompileOnly_Group" + }, + +options_dictionary: The converted Python dictionary from the Options.td json string +option: The option object from Options.td + +Return: A set including the group found for the option +""" +group_list = options_dictionary[option]["Group"] + +if group_list is None: +return None +found_group = group_list["def"] +
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix + +# For sorting +def __len__(self): +return len(self.option_name) + +def __lt__(self, other): +return len(self.option_name) > len(other.option_name) + + +@dataclass +class DriverData: +"""Dataclass for data specific to each driver +lit_cmd_prefix: The beginning string of the Lit command +lit_cmd_options: Strings containing additional options for this driver +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +lit_cmd_end: String at the end of the Lit command +check_str: The string or regex to be sent to FileCheck +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind *JOINED*, as defined in Options.td +test_option_sequence: A list of all the prefix-option pairs that will be tested for this driver +""" + +lit_cmd_prefix: str +lit_cmd_options: str +visibility_str: str +lit_cmd_end: str = " - < /dev/null 2>&1 | FileCheck -check-prefix=CHECK-COUNT-" +check_str: str = "{{(unknown argument|n?N?o such file or directory)}}" +supported_sequence: list[UnsupportedDriverOption] = dataclasses.field( +default_factory=list +) +test_option_sequence: list[str] = dataclasses.field(default_factory=list) + + +def find_groups(options_dictionary, option): +"""Find the groups for a given option +Note that groups can themselves be part of groups, hence the recursion + +For example, considering option "C", it has the following 'Group' list as defined by Options.td: + "Group": { +"def": "Preprocessor_Group", +"kind": "def", +"printable": "Preprocessor_Group" + }, +Preprocessor_Group is itself part of CompileOnly_Group, so option C would be part of both groups + "Group": { +"def": "CompileOnly_Group", +"kind": "def", +"printable": "CompileOnly_Group" + }, + +options_dictionary: The converted Python dictionary from the Options.td json string +option: The option object from Options.td + +Return: A set including the group found for the option +""" +group_list = options_dictionary[option]["Group"] + +if group_list is None: +return None +found_group = group_list["def"] +
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
https://github.com/Maetveis edited https://github.com/llvm/llvm-project/pull/120900 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix + +# For sorting +def __len__(self): +return len(self.option_name) + +def __lt__(self, other): +return len(self.option_name) > len(other.option_name) + + +@dataclass +class DriverData: +"""Dataclass for data specific to each driver +lit_cmd_prefix: The beginning string of the Lit command +lit_cmd_options: Strings containing additional options for this driver +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +lit_cmd_end: String at the end of the Lit command +check_str: The string or regex to be sent to FileCheck +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind *JOINED*, as defined in Options.td +test_option_sequence: A list of all the prefix-option pairs that will be tested for this driver +""" + +lit_cmd_prefix: str +lit_cmd_options: str +visibility_str: str +lit_cmd_end: str = " - < /dev/null 2>&1 | FileCheck -check-prefix=CHECK-COUNT-" +check_str: str = "{{(unknown argument|n?N?o such file or directory)}}" +supported_sequence: list[UnsupportedDriverOption] = dataclasses.field( +default_factory=list +) +test_option_sequence: list[str] = dataclasses.field(default_factory=list) + + +def find_groups(options_dictionary, option): +"""Find the groups for a given option +Note that groups can themselves be part of groups, hence the recursion + +For example, considering option "C", it has the following 'Group' list as defined by Options.td: + "Group": { +"def": "Preprocessor_Group", +"kind": "def", +"printable": "Preprocessor_Group" + }, +Preprocessor_Group is itself part of CompileOnly_Group, so option C would be part of both groups + "Group": { +"def": "CompileOnly_Group", +"kind": "def", +"printable": "CompileOnly_Group" + }, + +options_dictionary: The converted Python dictionary from the Options.td json string +option: The option object from Options.td + +Return: A set including the group found for the option +""" +group_list = options_dictionary[option]["Group"] + +if group_list is None: +return None +found_group = group_list["def"] +
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix + +# For sorting +def __len__(self): +return len(self.option_name) + +def __lt__(self, other): +return len(self.option_name) > len(other.option_name) + + +@dataclass +class DriverData: +"""Dataclass for data specific to each driver +lit_cmd_prefix: The beginning string of the Lit command +lit_cmd_options: Strings containing additional options for this driver +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +lit_cmd_end: String at the end of the Lit command +check_str: The string or regex to be sent to FileCheck +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind *JOINED*, as defined in Options.td +test_option_sequence: A list of all the prefix-option pairs that will be tested for this driver +""" + +lit_cmd_prefix: str +lit_cmd_options: str +visibility_str: str +lit_cmd_end: str = " - < /dev/null 2>&1 | FileCheck -check-prefix=CHECK-COUNT-" +check_str: str = "{{(unknown argument|n?N?o such file or directory)}}" +supported_sequence: list[UnsupportedDriverOption] = dataclasses.field( +default_factory=list +) +test_option_sequence: list[str] = dataclasses.field(default_factory=list) + + +def find_groups(options_dictionary, option): +"""Find the groups for a given option +Note that groups can themselves be part of groups, hence the recursion + +For example, considering option "C", it has the following 'Group' list as defined by Options.td: + "Group": { +"def": "Preprocessor_Group", +"kind": "def", +"printable": "Preprocessor_Group" + }, +Preprocessor_Group is itself part of CompileOnly_Group, so option C would be part of both groups + "Group": { +"def": "CompileOnly_Group", +"kind": "def", +"printable": "CompileOnly_Group" + }, + +options_dictionary: The converted Python dictionary from the Options.td json string +option: The option object from Options.td + +Return: A set including the group found for the option +""" +group_list = options_dictionary[option]["Group"] + +if group_list is None: +return None +found_group = group_list["def"] +
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix + +# For sorting +def __len__(self): +return len(self.option_name) + +def __lt__(self, other): +return len(self.option_name) > len(other.option_name) + + +@dataclass +class DriverData: +"""Dataclass for data specific to each driver +lit_cmd_prefix: The beginning string of the Lit command +lit_cmd_options: Strings containing additional options for this driver +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +lit_cmd_end: String at the end of the Lit command +check_str: The string or regex to be sent to FileCheck +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind *JOINED*, as defined in Options.td +test_option_sequence: A list of all the prefix-option pairs that will be tested for this driver +""" + +lit_cmd_prefix: str +lit_cmd_options: str +visibility_str: str +lit_cmd_end: str = " - < /dev/null 2>&1 | FileCheck -check-prefix=CHECK-COUNT-" +check_str: str = "{{(unknown argument|n?N?o such file or directory)}}" +supported_sequence: list[UnsupportedDriverOption] = dataclasses.field( +default_factory=list +) +test_option_sequence: list[str] = dataclasses.field(default_factory=list) + + +def find_groups(options_dictionary, option): Maetveis wrote: `option` is only an option in the first call to the function, during recursive calls it will be a group. This is confusing IMO, maybe just naming it a generic `member` or a generic `record`. https://github.com/llvm/llvm-project/pull/120900 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix + +# For sorting +def __len__(self): +return len(self.option_name) + +def __lt__(self, other): +return len(self.option_name) > len(other.option_name) Maetveis wrote: It would be cleaner IMO to use `bisect_left(supported_seq, -len(unsupported_pair.option_name), key=lambda o:-len(o.option_name))` and drop this code. The current implementation couples `UnsupportedDriverOption` with how its used later. https://github.com/llvm/llvm-project/pull/120900 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix + +# For sorting +def __len__(self): +return len(self.option_name) + +def __lt__(self, other): +return len(self.option_name) > len(other.option_name) + + +@dataclass +class DriverData: +"""Dataclass for data specific to each driver +lit_cmd_prefix: The beginning string of the Lit command +lit_cmd_options: Strings containing additional options for this driver +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +lit_cmd_end: String at the end of the Lit command +check_str: The string or regex to be sent to FileCheck +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind *JOINED*, as defined in Options.td +test_option_sequence: A list of all the prefix-option pairs that will be tested for this driver +""" + +lit_cmd_prefix: str +lit_cmd_options: str +visibility_str: str +lit_cmd_end: str = " - < /dev/null 2>&1 | FileCheck -check-prefix=CHECK-COUNT-" +check_str: str = "{{(unknown argument|n?N?o such file or directory)}}" +supported_sequence: list[UnsupportedDriverOption] = dataclasses.field( +default_factory=list +) +test_option_sequence: list[str] = dataclasses.field(default_factory=list) + + +def find_groups(options_dictionary, option): +"""Find the groups for a given option +Note that groups can themselves be part of groups, hence the recursion + +For example, considering option "C", it has the following 'Group' list as defined by Options.td: + "Group": { +"def": "Preprocessor_Group", +"kind": "def", +"printable": "Preprocessor_Group" + }, +Preprocessor_Group is itself part of CompileOnly_Group, so option C would be part of both groups + "Group": { +"def": "CompileOnly_Group", +"kind": "def", +"printable": "CompileOnly_Group" + }, + +options_dictionary: The converted Python dictionary from the Options.td json string +option: The option object from Options.td + +Return: A set including the group found for the option +""" +group_list = options_dictionary[option]["Group"] + +if group_list is None: +return None +found_group = group_list["def"] +
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix + +# For sorting +def __len__(self): +return len(self.option_name) + +def __lt__(self, other): +return len(self.option_name) > len(other.option_name) + + +@dataclass +class DriverData: +"""Dataclass for data specific to each driver +lit_cmd_prefix: The beginning string of the Lit command +lit_cmd_options: Strings containing additional options for this driver +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +lit_cmd_end: String at the end of the Lit command +check_str: The string or regex to be sent to FileCheck +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind *JOINED*, as defined in Options.td +test_option_sequence: A list of all the prefix-option pairs that will be tested for this driver +""" + +lit_cmd_prefix: str +lit_cmd_options: str +visibility_str: str +lit_cmd_end: str = " - < /dev/null 2>&1 | FileCheck -check-prefix=CHECK-COUNT-" +check_str: str = "{{(unknown argument|n?N?o such file or directory)}}" +supported_sequence: list[UnsupportedDriverOption] = dataclasses.field( +default_factory=list +) +test_option_sequence: list[str] = dataclasses.field(default_factory=list) + + +def find_groups(options_dictionary, option): +"""Find the groups for a given option +Note that groups can themselves be part of groups, hence the recursion + +For example, considering option "C", it has the following 'Group' list as defined by Options.td: + "Group": { +"def": "Preprocessor_Group", +"kind": "def", +"printable": "Preprocessor_Group" + }, +Preprocessor_Group is itself part of CompileOnly_Group, so option C would be part of both groups + "Group": { +"def": "CompileOnly_Group", +"kind": "def", +"printable": "CompileOnly_Group" + }, + +options_dictionary: The converted Python dictionary from the Options.td json string +option: The option object from Options.td + +Return: A set including the group found for the option +""" +group_list = options_dictionary[option]["Group"] + +if group_list is None: +return None +found_group = group_list["def"] +
[clang] Thread Safety Analysis: Support warning on passing/returning pointers to guarded variables (PR #127396)
https://github.com/melver updated https://github.com/llvm/llvm-project/pull/127396 >From a70f021becb2888d6c2a63b2d1e619393a996058 Mon Sep 17 00:00:00 2001 From: Marco Elver Date: Sun, 16 Feb 2025 14:53:41 +0100 Subject: [PATCH 1/2] Thread Safety Analysis: Handle address-of followed by dereference Correctly analyze expressions where the address of a guarded variable is taken and immediately dereferenced, such as (*(type-specifier *)&x). Previously, such patterns would result in false negatives. --- clang/lib/Analysis/ThreadSafety.cpp | 10 ++ clang/test/Sema/warn-thread-safety-analysis.c | 13 + 2 files changed, 23 insertions(+) diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp index bfaf1a0e7c7ff..260505b71c17c 100644 --- a/clang/lib/Analysis/ThreadSafety.cpp +++ b/clang/lib/Analysis/ThreadSafety.cpp @@ -1765,6 +1765,8 @@ void ThreadSafetyAnalyzer::checkAccess(const FactSet &FSet, const Expr *Exp, void ThreadSafetyAnalyzer::checkPtAccess(const FactSet &FSet, const Expr *Exp, AccessKind AK, ProtectedOperationKind POK) { + // Strips off paren- and cast-expressions, checking if we encounter any other + // operator that should be delegated to checkAccess() instead. while (true) { if (const auto *PE = dyn_cast(Exp)) { Exp = PE->getSubExpr(); @@ -1780,6 +1782,14 @@ void ThreadSafetyAnalyzer::checkPtAccess(const FactSet &FSet, const Expr *Exp, Exp = CE->getSubExpr(); continue; } +if (const auto *UO = dyn_cast(Exp)) { + if (UO->getOpcode() == UO_AddrOf) { +// Pointer access via pointer taken of variable, so the dereferenced +// variable is not actually a pointer. +checkAccess(FSet, UO->getSubExpr(), AK, POK); +return; + } +} break; } diff --git a/clang/test/Sema/warn-thread-safety-analysis.c b/clang/test/Sema/warn-thread-safety-analysis.c index 73b4e4798f644..8a0d44cd4bea9 100644 --- a/clang/test/Sema/warn-thread-safety-analysis.c +++ b/clang/test/Sema/warn-thread-safety-analysis.c @@ -24,6 +24,9 @@ __attribute__ ((shared_locks_required(__VA_ARGS__))) #define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis)) +#define __READ_ONCE(x)(*(const volatile __typeof__(x) *)&(x)) +#define __WRITE_ONCE(x, val) do { *(volatile __typeof__(x) *)&(x) = (val); } while (0) + // Define the mutex struct. // Simplified only for test purpose. struct LOCKABLE Mutex {}; @@ -142,9 +145,19 @@ int main(void) { (void)(get_value(b_) == 1); mutex_unlock(foo_.mu_); + a_ = 0; // expected-warning{{writing variable 'a_' requires holding mutex 'foo_.mu_'}} + __WRITE_ONCE(a_, 0); // expected-warning{{writing variable 'a_' requires holding mutex 'foo_.mu_'}} + (void)(a_ == 0); // expected-warning{{reading variable 'a_' requires holding mutex 'foo_.mu_'}} + (void)(__READ_ONCE(a_) == 0); // expected-warning{{reading variable 'a_' requires holding mutex 'foo_.mu_'}} + (void)(*b_ == 0); // expected-warning{{reading the value pointed to by 'b_' requires holding mutex 'foo_.mu_'}} c_ = 0; // expected-warning{{writing variable 'c_' requires holding any mutex exclusively}} (void)(*d_ == 0); // expected-warning{{reading the value pointed to by 'd_' requires holding any mutex}} mutex_exclusive_lock(foo_.mu_); + a_ = 0; + __WRITE_ONCE(a_, 0); + (void)(a_ == 0); + (void)(__READ_ONCE(a_) == 0); + (void)(*b_ == 0); c_ = 1; (void)(*d_ == 1); mutex_unlock(foo_.mu_); >From 6683e2aced3c36af6b672e65bcd6779eb8664ac4 Mon Sep 17 00:00:00 2001 From: Marco Elver Date: Sun, 16 Feb 2025 12:42:06 +0100 Subject: [PATCH 2/2] Thread Safety Analysis: Support warning on passing/returning pointers to guarded variables Introduce `-Wthread-safety-pointer` (under `-Wthread-safety-beta`) to warn when passing or returning pointers to guarded variables or guarded data. This is is analogous to `-Wthread-safety-reference`, which performs similar checks for C++ references. Adding checks for pointer passing is required to avoid false negatives in large C codebases, where data structures are typically implemented through helpers that take pointers to instances of a data structure. --- clang/docs/ReleaseNotes.rst | 5 + clang/docs/ThreadSafetyAnalysis.rst | 6 +- .../clang/Analysis/Analyses/ThreadSafety.h| 12 ++ clang/include/clang/Basic/DiagnosticGroups.td | 4 +- .../clang/Basic/DiagnosticSemaKinds.td| 18 ++ clang/lib/Analysis/ThreadSafety.cpp | 24 ++- clang/lib/Sema/AnalysisBasedWarnings.cpp | 24 +++ clang/test/Sema/warn-thread-safety-analysis.c | 4 + .../SemaCXX/warn-thread-safety-analysis.cpp | 158 +- 9 files changed, 250 insertions(+), 5 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index efaacdf18d50a..830433853437d
[clang] 1c87e47 - [AST] Avoid repeated map lookups (NFC) (#127369)
Author: Kazu Hirata Date: 2025-02-16T08:14:20-08:00 New Revision: 1c87e4739f487aea1fbafa06b92ec1a1c011c6f2 URL: https://github.com/llvm/llvm-project/commit/1c87e4739f487aea1fbafa06b92ec1a1c011c6f2 DIFF: https://github.com/llvm/llvm-project/commit/1c87e4739f487aea1fbafa06b92ec1a1c011c6f2.diff LOG: [AST] Avoid repeated map lookups (NFC) (#127369) Added: Modified: clang/lib/AST/ExternalASTMerger.cpp Removed: diff --git a/clang/lib/AST/ExternalASTMerger.cpp b/clang/lib/AST/ExternalASTMerger.cpp index 257e8338dedef..1c903b5104bf4 100644 --- a/clang/lib/AST/ExternalASTMerger.cpp +++ b/clang/lib/AST/ExternalASTMerger.cpp @@ -206,16 +206,14 @@ class LazyASTImporter : public ASTImporter { << "\n"; Source FromDC( cast(From)->getPrimaryContext()); - if (FromOrigins.count(FromDC) && - Parent.HasImporterForOrigin(*FromOrigins.at(FromDC).AST)) { + if (auto It = FromOrigins.find(FromDC); + It != FromOrigins.end() && + Parent.HasImporterForOrigin(*It->second.AST)) { if (LoggingEnabled) - logs() << "(ExternalASTMerger*)" << (void*)&Parent - << " forced origin (DeclContext*)" - << (void*)FromOrigins.at(FromDC).DC - << ", (ASTContext*)" - << (void*)FromOrigins.at(FromDC).AST - << "\n"; -Parent.ForceRecordOrigin(ToDC, FromOrigins.at(FromDC)); + logs() << "(ExternalASTMerger*)" << (void *)&Parent + << " forced origin (DeclContext*)" << (void *)It->second.DC + << ", (ASTContext*)" << (void *)It->second.AST << "\n"; +Parent.ForceRecordOrigin(ToDC, It->second); } else { if (LoggingEnabled) logs() << "(ExternalASTMerger*)" << (void*)&Parent ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] 0bae0bf - [clang-tidy] Avoid repeated hash lookups (NFC) (#127370)
Author: Kazu Hirata Date: 2025-02-16T08:14:42-08:00 New Revision: 0bae0bf8ba73bd0201c58a6cfd6d9f54aaf39ca2 URL: https://github.com/llvm/llvm-project/commit/0bae0bf8ba73bd0201c58a6cfd6d9f54aaf39ca2 DIFF: https://github.com/llvm/llvm-project/commit/0bae0bf8ba73bd0201c58a6cfd6d9f54aaf39ca2.diff LOG: [clang-tidy] Avoid repeated hash lookups (NFC) (#127370) Added: Modified: clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp Removed: diff --git a/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp index 76fa2d916f0e8..509fce3a38471 100644 --- a/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp @@ -179,15 +179,15 @@ static bool checkOverrideByDerivedMethod(const CXXMethodDecl *BaseMD, bool VirtualNearMissCheck::isPossibleToBeOverridden( const CXXMethodDecl *BaseMD) { - auto Iter = PossibleMap.find(BaseMD); - if (Iter != PossibleMap.end()) + auto [Iter, Inserted] = PossibleMap.try_emplace(BaseMD); + if (!Inserted) return Iter->second; bool IsPossible = !BaseMD->isImplicit() && !isa(BaseMD) && !isa(BaseMD) && BaseMD->isVirtual() && !BaseMD->isOverloadedOperator() && !isa(BaseMD); - PossibleMap[BaseMD] = IsPossible; + Iter->second = IsPossible; return IsPossible; } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Avoid repeated hash lookups (NFC) (PR #127370)
https://github.com/kazutakahirata closed https://github.com/llvm/llvm-project/pull/127370 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [AST] Avoid repeated map lookups (NFC) (PR #127369)
https://github.com/kazutakahirata closed https://github.com/llvm/llvm-project/pull/127369 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] d235b72 - Reapply "[Analyzer][CFG] Correctly handle rebuilt default arg and default init expression" (#127338)
Author: yronglin Date: 2025-02-17T00:36:08+08:00 New Revision: d235b72178adc710bf704078fbe0cd687642f3e0 URL: https://github.com/llvm/llvm-project/commit/d235b72178adc710bf704078fbe0cd687642f3e0 DIFF: https://github.com/llvm/llvm-project/commit/d235b72178adc710bf704078fbe0cd687642f3e0.diff LOG: Reapply "[Analyzer][CFG] Correctly handle rebuilt default arg and default init expression" (#127338) This PR reapply https://github.com/llvm/llvm-project/pull/117437. The issue has been fixed by the 2nd commit, we need to ignore parens in CXXDefaultArgExpr when build CFG, because CXXDefaultArgExpr::getExpr stripped off the top level FullExpr and ConstantExpr, ParenExpr may occurres in the top level. - Signed-off-by: yronglin Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/AST/ParentMap.cpp clang/lib/Analysis/CFG.cpp clang/lib/Analysis/ReachableCode.cpp clang/lib/Sema/SemaExpr.cpp clang/lib/StaticAnalyzer/Core/ExprEngine.cpp clang/test/AST/ast-dump-recovery.cpp clang/test/Analysis/lifetime-extended-regions.cpp clang/test/SemaCXX/cxx2c-placeholder-vars.cpp clang/test/SemaCXX/warn-unreachable.cpp Removed: diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index efaacdf18d50a..6272f32fa845a 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -270,6 +270,10 @@ Code Completion Static Analyzer --- +- Clang currently support extending lifetime of object bound to + reference members of aggregates in CFG and ExprEngine, that are + created from default member initializer. + New features diff --git a/clang/lib/AST/ParentMap.cpp b/clang/lib/AST/ParentMap.cpp index e62e71bf5a514..580613b2618fb 100644 --- a/clang/lib/AST/ParentMap.cpp +++ b/clang/lib/AST/ParentMap.cpp @@ -13,6 +13,7 @@ #include "clang/AST/ParentMap.h" #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/StmtObjC.h" #include "llvm/ADT/DenseMap.h" @@ -103,6 +104,22 @@ static void BuildParentMap(MapTy& M, Stmt* S, BuildParentMap(M, SubStmt, OVMode); } break; + case Stmt::CXXDefaultArgExprClass: +if (auto *Arg = dyn_cast(S)) { + if (Arg->hasRewrittenInit()) { +M[Arg->getExpr()] = S; +BuildParentMap(M, Arg->getExpr(), OVMode); + } +} +break; + case Stmt::CXXDefaultInitExprClass: +if (auto *Init = dyn_cast(S)) { + if (Init->hasRewrittenInit()) { +M[Init->getExpr()] = S; +BuildParentMap(M, Init->getExpr(), OVMode); + } +} +break; default: for (Stmt *SubStmt : S->children()) { if (SubStmt) { diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index 3e144395cffc6..c82dbc42fb9d8 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -556,6 +556,10 @@ class CFGBuilder { private: // Visitors to walk an AST and construct the CFG. + CFGBlock *VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Default, + AddStmtChoice asc); + CFGBlock *VisitCXXDefaultInitExpr(CXXDefaultInitExpr *Default, +AddStmtChoice asc); CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc); CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc); CFGBlock *VisitAttributedStmt(AttributedStmt *A, AddStmtChoice asc); @@ -2263,16 +2267,10 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc, asc, ExternallyDestructed); case Stmt::CXXDefaultArgExprClass: + return VisitCXXDefaultArgExpr(cast(S), asc); + case Stmt::CXXDefaultInitExprClass: - // FIXME: The expression inside a CXXDefaultArgExpr is owned by the - // called function's declaration, not by the caller. If we simply add - // this expression to the CFG, we could end up with the same Expr - // appearing multiple times (PR13385). - // - // It's likewise possible for multiple CXXDefaultInitExprs for the same - // expression to be used in the same function (through aggregate - // initialization). - return VisitStmt(S, asc); + return VisitCXXDefaultInitExpr(cast(S), asc); case Stmt::CXXBindTemporaryExprClass: return VisitCXXBindTemporaryExpr(cast(S), asc); @@ -2442,6 +2440,44 @@ CFGBlock *CFGBuilder::VisitChildren(Stmt *S) { return B; } +CFGBlock *CFGBuilder::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *Arg, + AddStmtChoice asc) { + if (Arg->hasRewrittenInit()) { +if (asc.alwaysAdd(*this, Arg)) { + autoCreateBlock(); + appendStmt(Block, Arg); +} +return VisitStmt(Arg->getExpr()->IgnoreParens(), asc); + } + + // We can't add the default argument if it's not rewritten because the + // expression inside a CXXDefaultArgExpr
[clang] Reapply "[Analyzer][CFG] Correctly handle rebuilt default arg and default init expression" (PR #127338)
https://github.com/yronglin closed https://github.com/llvm/llvm-project/pull/127338 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Fix false positive for cppcoreguidelines-pro-bounds-pointer-arithmetic (PR #127394)
https://github.com/flovent created https://github.com/llvm/llvm-project/pull/127394 this PR fixs #126424 for `ArraySubScriptExpr`, `hasBase` Matcher will get right operand when it is not Integer type, but is not for sure that left operand is interger type. For the example code below `hasBase` will get `r` for the Subsequent matching and causing false positive. ``` template int f(std::map& map, R* r) { return map[r]; } ``` so is needed to see if index is interger type to avoid this situation. >From 1bd661b60dbb350dcefad3556218bbec71a4f366 Mon Sep 17 00:00:00 2001 From: flovent Date: Sun, 16 Feb 2025 21:07:55 +0800 Subject: [PATCH] [clang-tidy] Fix false positive for cppcoreguidelines-pro-bounds-pointer-arithmetic --- .../ProBoundsPointerArithmeticCheck.cpp | 3 ++- clang-tools-extra/docs/ReleaseNotes.rst | 4 ...-bounds-pointer-arithmetic-issue126424.cpp | 19 +++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic-issue126424.cpp diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp index a1494a095f5b6..0d68790349fb5 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp @@ -42,7 +42,8 @@ void ProBoundsPointerArithmeticCheck::registerMatchers(MatchFinder *Finder) { arraySubscriptExpr( hasBase(ignoringImpCasts( anyOf(AllPointerTypes, -hasType(decayedType(hasDecayedType(pointerType( +hasType(decayedType(hasDecayedType(pointerType())), + hasIndex(hasType(isInteger( .bind("expr"), this); } diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 6b8fe22242417..937d710fe6100 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -110,6 +110,10 @@ Changes in existing checks ` check by providing additional examples and fixing some macro related false positives. +- Improved :doc:`cppcoreguidelines-pro-bounds-pointer-arithmetic + ` check by + fix false positives related to operator overloading and templates. + Removed checks ^^ diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic-issue126424.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic-issue126424.cpp new file mode 100644 index 0..b6b7a9664f38d --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic-issue126424.cpp @@ -0,0 +1,19 @@ +// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-pointer-arithmetic %t + +namespace std { +template +class pair {}; + +template +class map { + public: + using value_type = pair; + value_type& operator[](const Key& key); + value_type& operator[](Key&& key); + }; +} + +template +int f(std::map& map, R* r) { + return map[r]; // OK +} \ No newline at end of file ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Fix false positive for cppcoreguidelines-pro-bounds-pointer-arithmetic (PR #127394)
https://github.com/flovent edited https://github.com/llvm/llvm-project/pull/127394 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [lld] [llvm] [Flang] LLVM_ENABLE_RUNTIMES=flang-rt (PR #110217)
https://github.com/Meinersbur closed https://github.com/llvm/llvm-project/pull/110217 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [lld] [llvm] [Flang-RT] Build libflang_rt.so (PR #121782)
https://github.com/Meinersbur edited https://github.com/llvm/llvm-project/pull/121782 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] handle fp options in __builtin_convertvector (PR #125522)
https://github.com/shafik approved this pull request. LGTM Assuming no objections from @tbaederr https://github.com/llvm/llvm-project/pull/125522 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a bug in annotating braces (PR #127306)
https://github.com/HazardyKnusperkeks approved this pull request. https://github.com/llvm/llvm-project/pull/127306 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][Driver][Test] Created test for unsupported driver options (PR #120900)
@@ -0,0 +1,472 @@ +#!/usr/bin/env python3 + +"""generate_unsupported_in_drivermode.py + +This script generates Lit regression test files that validate that options are only exposed to intended driver modes. + +The options and driver modes are parsed from Options.td, whose path should be provided on the command line. +See clang/include/clang/Driver/Options.td + +The path to the TableGen executable can optionally be provided. Otherwise, the script will search for it. + +The primary maintenance task for this script would be updating the expected return message for a driver mode if +there are changes over time. See the instantiations of DriverData, specifically the check_str. + +Logic: +1) For each option, (records of class "Option"), and for each driver, (records of class "OptionVisibility") +a. if the option's "Visibility" field includes the driver flavour, skip processing this option for this driver +b. if the option is part of an option group, (the record has the "Group" property), + and the group's "Visibility" field includes the driver flavour, skip processing this option for this driver +c. otherwise this option is not supported by this driver flavour, and this pairing is saved for testing +2) For each unsupported pairing, generate a Lit RUN line, and a CHECK line to parse for expected output. Ex: "error: unknown argument" +""" + +import shutil +import os +import json +import subprocess +from bisect import bisect_left +from dataclasses import dataclass +import argparse +import dataclasses +from itertools import batched + +# Strings defined in Options.td for the various driver flavours. See "OptionVisibility" +VISIBILITY_CC1AS = "CC1AsOption" +VISIBILITY_CC1 = "CC1Option" +VISIBILITY_CL = "CLOption" +VISIBILITY_DXC = "DXCOption" +VISIBILITY_DEFAULT = "DefaultVis" +VISIBILITY_FC1 = "FC1Option" +VISIBILITY_FLANG = "FlangOption" + +# Lit test prefix strings +SLASH_SLASH = "// " +EXCLAMATION = "! " + +# Invalid usage of the driver options below causes unique output, so skip testing +exceptions_sequence = [ +"cc1", +"cc1as", +] + + +class UnsupportedDriverOption: +"""Defines an unsupported driver-option combination +driver: The driver string as defined by OptionVisibility in Options.td +option: The option object from Options.td +option_name: Corresponding string for an option. See "Name" for a given option in Options.td +prefix: String that precedes the option. Ex. "-" +""" + +def __init__(self, driver, option, option_name, prefix): +self.driver = driver +self.option = option +self.option_name = option_name +self.prefix = prefix + +# For sorting +def __len__(self): +return len(self.option_name) + +def __lt__(self, other): +return len(self.option_name) > len(other.option_name) + + +@dataclass +class DriverData: +"""Dataclass for data specific to each driver +lit_cmd_prefix: The beginning string of the Lit command +lit_cmd_options: Strings containing additional options for this driver +visibility_str: The corresponding visibility string from OptionVisibility in Options.td +lit_cmd_end: String at the end of the Lit command +check_str: The string or regex to be sent to FileCheck +supported_sequence: List of UnsupportedDriverOption objects for supported options +that are Kind *JOINED*, as defined in Options.td +test_option_sequence: A list of all the prefix-option pairs that will be tested for this driver +""" + +lit_cmd_prefix: str +lit_cmd_options: str +visibility_str: str +lit_cmd_end: str = " - < /dev/null 2>&1 | FileCheck -check-prefix=CHECK-COUNT-" +check_str: str = "{{(unknown argument|n?N?o such file or directory)}}" +supported_sequence: list[UnsupportedDriverOption] = dataclasses.field( +default_factory=list +) +test_option_sequence: list[str] = dataclasses.field(default_factory=list) + + +def find_groups(options_dictionary, option): +"""Find the groups for a given option +Note that groups can themselves be part of groups, hence the recursion + +For example, considering option "C", it has the following 'Group' list as defined by Options.td: + "Group": { +"def": "Preprocessor_Group", +"kind": "def", +"printable": "Preprocessor_Group" + }, +Preprocessor_Group is itself part of CompileOnly_Group, so option C would be part of both groups + "Group": { +"def": "CompileOnly_Group", +"kind": "def", +"printable": "CompileOnly_Group" + }, + +options_dictionary: The converted Python dictionary from the Options.td json string +option: The option object from Options.td + +Return: A set including the group found for the option +""" +group_list = options_dictionary[option]["Group"] + +if group_list is None: +return None +found_group = group_list["def"] +
[clang] [Fix] Speedup -Wunsafe-buffer-usage when using clang modules. (PR #127161)
https://github.com/matts1 updated https://github.com/llvm/llvm-project/pull/127161 >From 918e07fa9012c95e9e2f6cf5f49f74b46db9978f Mon Sep 17 00:00:00 2001 From: Matt Stark Date: Fri, 14 Feb 2025 14:14:03 +1100 Subject: [PATCH] [Fix] Speedup -Wunsafe-buffer-usage when using clang modules. See https://issues.chromium.org/issues/351909443 for details and benchmarks. This improves the performance of a file containing a single line, `#include `, from ~1 second to ~100ms on my machine. --- clang/lib/Sema/AnalysisBasedWarnings.cpp | 19 --- clang/test/Modules/safe_buffers_optout.cpp | 28 +++--- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 589869d018657..849c899bbbc8b 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2546,14 +2546,27 @@ static void flushDiagnostics(Sema &S, const sema::FunctionScopeInfo *fscope) { class CallableVisitor : public DynamicRecursiveASTVisitor { private: llvm::function_ref Callback; + const unsigned int TUModuleID; public: - CallableVisitor(llvm::function_ref Callback) - : Callback(Callback) { + CallableVisitor(llvm::function_ref Callback, + unsigned int TUModuleID) + : Callback(Callback), TUModuleID(TUModuleID) { ShouldVisitTemplateInstantiations = true; ShouldVisitImplicitCode = false; } + bool TraverseDecl(Decl *Node) override { +// For performance reasons, only validate the current translation unit's +// module, and not modules it depends on. +// See https://issues.chromium.org/issues/351909443 for details. +if (Node && Node->getOwningModuleID() == TUModuleID) { + return DynamicRecursiveASTVisitor::TraverseDecl(Node); +} else { + return true; +} + } + bool VisitFunctionDecl(FunctionDecl *Node) override { if (cast(Node)->isDependentContext()) return true; // Not to analyze dependent decl @@ -2633,7 +2646,7 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings( SourceLocation()) || (!Diags.isIgnored(diag::warn_unsafe_buffer_libc_call, SourceLocation()) && S.getLangOpts().CPlusPlus /* only warn about libc calls in C++ */)) { -CallableVisitor(CallAnalyzers).TraverseTranslationUnitDecl(TU); +CallableVisitor(CallAnalyzers, TU->getOwningModuleID()).TraverseTranslationUnitDecl(TU); } } diff --git a/clang/test/Modules/safe_buffers_optout.cpp b/clang/test/Modules/safe_buffers_optout.cpp index 2129db65da752..8c3d6a235d399 100644 --- a/clang/test/Modules/safe_buffers_optout.cpp +++ b/clang/test/Modules/safe_buffers_optout.cpp @@ -95,18 +95,10 @@ int textual(int *p) { // `safe_buffers_test_optout`, which uses another top-level module // `safe_buffers_test_base`. (So the module dependencies form a DAG.) -// No expected warnings from base.h because base.h is a separate -// module and in a separate TU that is not textually included. The -// explicit command that builds base.h has no `-Wunsafe-buffer-usage`. - -// expected-warning@base.h:3{{unsafe buffer access}} -// expected-note@base.h:3{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} -// expected-warning@test_sub1.h:5{{unsafe buffer access}} -// expected-note@test_sub1.h:5{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} -// expected-warning@test_sub1.h:14{{unsafe buffer access}} -// expected-note@test_sub1.h:14{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} -// expected-warning@test_sub2.h:5{{unsafe buffer access}} -// expected-note@test_sub2.h:5{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} +// No expected warnings from base.h, test_sub1, or test_sub2 because they are +// in seperate modules, and the explicit commands that builds them have no +// `-Wunsafe-buffer-usage`. + int foo(int * p) { int x = p[5]; // expected-warning{{unsafe buffer access}} expected-note{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} #pragma clang unsafe_buffer_usage begin @@ -129,14 +121,10 @@ int foo(int * p) { // `safe_buffers_test_optout`, which uses another top-level module // `safe_buffers_test_base`. (So the module dependencies form a DAG.) -// expected-warning@base.h:3{{unsafe buffer access}} -// expected-note@base.h:3{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} -// expected-warning@test_sub1.h:5{{unsafe buffer access}} -// expected-note@test_sub1.h:5{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} -// expected-warning@test_sub1.h:14{{unsafe buffer access}} -// expected-note@test_sub1.h:14{{pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions}} -// expected-warning@test_sub2.h:5{{unsafe buffer access}} -// expected-note@test_sub2.h:5{{pass -f
[clang-tools-extra] [clangd] Enable parsing of forwarding functions in the preamble by default (PR #127359)
https://github.com/HighCommander4 updated https://github.com/llvm/llvm-project/pull/127359 >From fd189ad1b09c59040c3c2c16a7eccc0ce22c5b53 Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Sat, 15 Feb 2025 01:57:10 -0500 Subject: [PATCH] [clangd] Enable parsing of forwarding functions in the preamble by default Fixes https://github.com/clangd/clangd/issues/2324 --- clang-tools-extra/clangd/ClangdServer.h | 4 ++-- clang-tools-extra/clangd/Compiler.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clang-tools-extra/clangd/ClangdServer.h b/clang-tools-extra/clangd/ClangdServer.h index e030bf04122d5..1e612e2ba618e 100644 --- a/clang-tools-extra/clangd/ClangdServer.h +++ b/clang-tools-extra/clangd/ClangdServer.h @@ -184,7 +184,7 @@ class ClangdServer { bool UseDirtyHeaders = false; // If true, parse emplace-like functions in the preamble. -bool PreambleParseForwardingFunctions = false; +bool PreambleParseForwardingFunctions = true; /// Whether include fixer insertions for Objective-C code should use #import /// instead of #include. @@ -501,7 +501,7 @@ class ClangdServer { // Whether the client supports folding only complete lines. bool LineFoldingOnly = false; - bool PreambleParseForwardingFunctions = false; + bool PreambleParseForwardingFunctions = true; bool ImportInsertions = false; diff --git a/clang-tools-extra/clangd/Compiler.h b/clang-tools-extra/clangd/Compiler.h index 4e68da7610ca2..e513e4c40794a 100644 --- a/clang-tools-extra/clangd/Compiler.h +++ b/clang-tools-extra/clangd/Compiler.h @@ -40,7 +40,7 @@ class IgnoreDiagnostics : public DiagnosticConsumer { // Options to run clang e.g. when parsing AST. struct ParseOptions { - bool PreambleParseForwardingFunctions = false; + bool PreambleParseForwardingFunctions = true; bool ImportInsertions = false; }; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clangd] Enable parsing of forwarding functions in the preamble by default (PR #127359)
https://github.com/upsj approved this pull request. LGTM! https://github.com/llvm/llvm-project/pull/127359 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clangd] Enable parsing of forwarding functions in the preamble by default (PR #127359)
HighCommander4 wrote: > Maybe for consistency we should also change the other defaults that IIRC are > used to configure tests: > > https://github.com/llvm/llvm-project/blob/dbc98cfa46d52ede06e8be7fc5e855d807ba0fac/clang-tools-extra/clangd/ClangdServer.h#L187 > > https://github.com/llvm/llvm-project/blob/dbc98cfa46d52ede06e8be7fc5e855d807ba0fac/clang-tools-extra/clangd/ClangdServer.h#L504 Done https://github.com/llvm/llvm-project/pull/127359 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [libcxx] [llvm] [libc++][ranges] P2542R8: Implement `views::concat` (PR #120920)
https://github.com/changkhothuychung updated https://github.com/llvm/llvm-project/pull/120920 error: too big or took too long to generate ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [lld] [llvm] Integrated Distributed ThinLTO (DTLTO): Initial support (PR #126654)
bd1976bris wrote: @teresajohnson hopefully there has been enough time for design comments. I will start breaking this up into smaller commits as suggested. https://github.com/llvm/llvm-project/pull/126654 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Feat] Allow Finding across only parts of an AST. (PR #127423)
https://github.com/matts1 updated https://github.com/llvm/llvm-project/pull/127423 >From b3d8ac7a2e02a743a52370c5c86be5f8b00d5c8f Mon Sep 17 00:00:00 2001 From: Matt Stark Date: Mon, 17 Feb 2025 12:18:12 +1100 Subject: [PATCH] [Feat] Allow Finding across only parts of an AST. This is relevant for clang modules, as they are imported into the AST, but are actually part of a different TU. It can result in hundreds of milliseconds of additional time to also traverse the AST of these modules, and often for no benefit, as they are frequently already traversed in their own TU. --- .../clang/ASTMatchers/ASTMatchFinder.h| 7 ++ clang/lib/ASTMatchers/ASTMatchFinder.cpp | 3 ++- clang/unittests/ASTMatchers/ASTMatchersTest.h | 23 ++- .../ASTMatchers/ASTMatchersTraversalTest.cpp | 12 ++ 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/ASTMatchers/ASTMatchFinder.h b/clang/include/clang/ASTMatchers/ASTMatchFinder.h index a387d9037b7da..2b161a574d5b6 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchFinder.h +++ b/clang/include/clang/ASTMatchers/ASTMatchFinder.h @@ -139,6 +139,13 @@ class MatchFinder { /// /// It prints a report after match. std::optional CheckProfiling; + +/// Whether to traverse a Decl. This is relevant for clang modules, as they +/// are imported into the AST, but are actually part of a different TU. +/// It can result in hundreds of milliseconds of additional time to also +/// traverse the AST of these modules, and often for no benefit, as they +/// are frequently already traversed in their own TU. +std::optional> ShouldTraverseDecl; }; MatchFinder(MatchFinderOptions Options = MatchFinderOptions()); diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp index 3d01a70395a9b..5d2f2065ceba1 100644 --- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp @@ -1443,7 +1443,8 @@ bool MatchASTVisitor::objcClassIsDerivedFrom( } bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) { - if (!DeclNode) { + if (!DeclNode || (Options.ShouldTraverseDecl && +!(*Options.ShouldTraverseDecl)(*DeclNode))) { return true; } diff --git a/clang/unittests/ASTMatchers/ASTMatchersTest.h b/clang/unittests/ASTMatchers/ASTMatchersTest.h index ad2f5f355621c..02bdcc3a3ab1f 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTest.h +++ b/clang/unittests/ASTMatchers/ASTMatchersTest.h @@ -59,6 +59,11 @@ class VerifyMatch : public MatchFinder::MatchCallback { const std::unique_ptr FindResultReviewer; }; +inline ArrayRef langCxx11() { + static const TestLanguage Result[] = {Lang_CXX11}; + return ArrayRef(Result); +} + inline ArrayRef langCxx11OrLater() { static const TestLanguage Result[] = {Lang_CXX11, Lang_CXX14, Lang_CXX17, Lang_CXX20, Lang_CXX23}; @@ -91,9 +96,11 @@ testing::AssertionResult matchesConditionally( const Twine &Code, const T &AMatcher, bool ExpectMatch, ArrayRef CompileArgs, const FileContentMappings &VirtualMappedFiles = FileContentMappings(), -StringRef Filename = "input.cc") { +StringRef Filename = "input.cc", +MatchFinder::MatchFinderOptions Options = +MatchFinder::MatchFinderOptions()) { bool Found = false, DynamicFound = false; - MatchFinder Finder; + MatchFinder Finder(Options); VerifyMatch VerifyFound(nullptr, &Found); Finder.addMatcher(AMatcher, &VerifyFound); VerifyMatch VerifyDynamicFound(nullptr, &DynamicFound); @@ -147,11 +154,13 @@ testing::AssertionResult matchesConditionally( template testing::AssertionResult matchesConditionally(const Twine &Code, const T &AMatcher, bool ExpectMatch, - ArrayRef TestLanguages) { + ArrayRef TestLanguages, + MatchFinder::MatchFinderOptions Options = + MatchFinder::MatchFinderOptions()) { for (auto Lang : TestLanguages) { auto Result = matchesConditionally( Code, AMatcher, ExpectMatch, getCommandLineArgsForTesting(Lang), -FileContentMappings(), getFilenameForTesting(Lang)); +FileContentMappings(), getFilenameForTesting(Lang), Options); if (!Result) return Result; } @@ -162,8 +171,10 @@ matchesConditionally(const Twine &Code, const T &AMatcher, bool ExpectMatch, template testing::AssertionResult matches(const Twine &Code, const T &AMatcher, -ArrayRef TestLanguages = {Lang_CXX11}) { - return matchesConditionally(Code, AMatcher, true, TestLanguages); +ArrayRef TestLanguages = {Lang_CXX11}, +MatchFinder::MatchFinderOptions Options = +MatchFinder::MatchFinderOptions()) { + return matchesConditionally(Code, AMatcher, true, TestLanguages, Options); } template diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/AST
[clang-tools-extra] [clang-tidy] Add new check `readability-use-numeric-limits` (PR #127430)
llvmbot wrote: @llvm/pr-subscribers-clang-tools-extra @llvm/pr-subscribers-clang-tidy Author: Katherine Whitlock (stellar-aria) Changes The adds a check that replaces specific numeric literals like `32767` with the equivalent call to `std::numeric_limits` (such as `std::numeric_limits::max())`. Partially addresses #34434, but notably does not handle cases listed in the title post such as `~0` and `-1`. --- Full diff: https://github.com/llvm/llvm-project/pull/127430.diff 8 Files Affected: - (modified) clang-tools-extra/clang-tidy/readability/CMakeLists.txt (+1) - (modified) clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp (+3) - (added) clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp (+135) - (added) clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.h (+41) - (modified) clang-tools-extra/docs/ReleaseNotes.rst (+5) - (modified) clang-tools-extra/docs/clang-tidy/checks/list.rst (+1) - (added) clang-tools-extra/docs/clang-tidy/checks/readability/use-numeric-limits.rst (+22) - (added) clang-tools-extra/test/clang-tidy/checkers/readability/use-numeric-limits.cpp (+85) ``diff diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt index 8f303c51e1b0d..e06f68bdda73f 100644 --- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt @@ -57,6 +57,7 @@ add_clang_library(clangTidyReadabilityModule STATIC UniqueptrDeleteReleaseCheck.cpp UppercaseLiteralSuffixCheck.cpp UseAnyOfAllOfCheck.cpp + UseNumericLimitsCheck.cpp UseStdMinMaxCheck.cpp LINK_LIBS diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp index d61c0ba39658e..054083d25952a 100644 --- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp @@ -60,6 +60,7 @@ #include "UniqueptrDeleteReleaseCheck.h" #include "UppercaseLiteralSuffixCheck.h" #include "UseAnyOfAllOfCheck.h" +#include "UseNumericLimitsCheck.h" #include "UseStdMinMaxCheck.h" namespace clang::tidy { @@ -170,6 +171,8 @@ class ReadabilityModule : public ClangTidyModule { "readability-uppercase-literal-suffix"); CheckFactories.registerCheck( "readability-use-anyofallof"); +CheckFactories.registerCheck( +"readability-use-numeric-limits"); CheckFactories.registerCheck( "readability-use-std-min-max"); } diff --git a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp new file mode 100644 index 0..b26ae008cbdd5 --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp @@ -0,0 +1,135 @@ +//===--- UseNumericLimitsCheck.cpp - clang-tidy ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "UseNumericLimitsCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Preprocessor.h" +#include +#include + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +UseNumericLimitsCheck::UseNumericLimitsCheck(StringRef Name, + ClangTidyContext *Context) +: ClangTidyCheck(Name, Context), + SignedConstants{ + {std::numeric_limits::min(), + "std::numeric_limits::min()"}, + {std::numeric_limits::max(), + "std::numeric_limits::max()"}, + {std::numeric_limits::min(), + "std::numeric_limits::min()"}, + {std::numeric_limits::max(), + "std::numeric_limits::max()"}, + {std::numeric_limits::min(), + "std::numeric_limits::min()"}, + {std::numeric_limits::max(), + "std::numeric_limits::max()"}, + {std::numeric_limits::min(), + "std::numeric_limits::min()"}, + {std::numeric_limits::max(), + "std::numeric_limits::max()"}, + + }, + UnsignedConstants{ + {std::numeric_limits::max(), + "std::numeric_limits::max()"}, + {std::numeric_limits::max(), + "std::numeric_limits::max()"}, + {std::numeric_limits::max(), + "std::numeric_limits::max()"}, + {std::numeric_limits::max(), + "std::numeric_limits::max()"}, + }, + Inserter(Options.getLocalOrGlobal("IncludeStyle", +utils::IncludeSorter::IS_LLVM), + areDiagsSelfContained(
[clang-tools-extra] [clang-tidy] Add new check `readability-use-numeric-limits` (PR #127430)
dmdlott wrote: @PiotrZSL @5chmidti @HerrCai0907 https://github.com/llvm/llvm-project/pull/127430 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Feat] Allow Finding across only parts of an AST. (PR #127423)
https://github.com/matts1 edited https://github.com/llvm/llvm-project/pull/127423 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Feat] Allow Finding across only parts of an AST. (PR #127423)
https://github.com/matts1 edited https://github.com/llvm/llvm-project/pull/127423 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Feat] Allow Finding across only parts of an AST. (PR #127423)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Matt (matts1) Changes This is relevant for clang modules, as they are imported into the AST, but are actually part of a different TU. It can result in hundreds of milliseconds of additional time to also traverse the AST of these modules, and often for no benefit, as they are frequently already traversed in their own TU. Without this PR, our [raw pointer plugin](https://source.chromium.org/chromium/chromium/src/+/main:tools/clang/raw_ptr_plugin/FindBadRawPtrPatterns.cpp;l=372;drc=2ce79621853ae85219bc832f61d60d88c1760841) to detect unsafe uses of raw pointers can add up to 1 second of overhead to check a file that only contains the line `#include`. With this PR, we can use the same logic as in #127161 to reduce this overhead to <10ms, a 100x speedup. See https://issues.chromium.org/issues/351909443 for details and benchmarks. --- Full diff: https://github.com/llvm/llvm-project/pull/127423.diff 4 Files Affected: - (modified) clang/include/clang/ASTMatchers/ASTMatchFinder.h (+7) - (modified) clang/lib/ASTMatchers/ASTMatchFinder.cpp (+2-1) - (modified) clang/unittests/ASTMatchers/ASTMatchersTest.h (+17-6) - (modified) clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp (+12) ``diff diff --git a/clang/include/clang/ASTMatchers/ASTMatchFinder.h b/clang/include/clang/ASTMatchers/ASTMatchFinder.h index a387d9037b7da..2b161a574d5b6 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchFinder.h +++ b/clang/include/clang/ASTMatchers/ASTMatchFinder.h @@ -139,6 +139,13 @@ class MatchFinder { /// /// It prints a report after match. std::optional CheckProfiling; + +/// Whether to traverse a Decl. This is relevant for clang modules, as they +/// are imported into the AST, but are actually part of a different TU. +/// It can result in hundreds of milliseconds of additional time to also +/// traverse the AST of these modules, and often for no benefit, as they +/// are frequently already traversed in their own TU. +std::optional> ShouldTraverseDecl; }; MatchFinder(MatchFinderOptions Options = MatchFinderOptions()); diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp index 3d01a70395a9b..5d2f2065ceba1 100644 --- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp @@ -1443,7 +1443,8 @@ bool MatchASTVisitor::objcClassIsDerivedFrom( } bool MatchASTVisitor::TraverseDecl(Decl *DeclNode) { - if (!DeclNode) { + if (!DeclNode || (Options.ShouldTraverseDecl && +!(*Options.ShouldTraverseDecl)(*DeclNode))) { return true; } diff --git a/clang/unittests/ASTMatchers/ASTMatchersTest.h b/clang/unittests/ASTMatchers/ASTMatchersTest.h index ad2f5f355621c..02bdcc3a3ab1f 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTest.h +++ b/clang/unittests/ASTMatchers/ASTMatchersTest.h @@ -59,6 +59,11 @@ class VerifyMatch : public MatchFinder::MatchCallback { const std::unique_ptr FindResultReviewer; }; +inline ArrayRef langCxx11() { + static const TestLanguage Result[] = {Lang_CXX11}; + return ArrayRef(Result); +} + inline ArrayRef langCxx11OrLater() { static const TestLanguage Result[] = {Lang_CXX11, Lang_CXX14, Lang_CXX17, Lang_CXX20, Lang_CXX23}; @@ -91,9 +96,11 @@ testing::AssertionResult matchesConditionally( const Twine &Code, const T &AMatcher, bool ExpectMatch, ArrayRef CompileArgs, const FileContentMappings &VirtualMappedFiles = FileContentMappings(), -StringRef Filename = "input.cc") { +StringRef Filename = "input.cc", +MatchFinder::MatchFinderOptions Options = +MatchFinder::MatchFinderOptions()) { bool Found = false, DynamicFound = false; - MatchFinder Finder; + MatchFinder Finder(Options); VerifyMatch VerifyFound(nullptr, &Found); Finder.addMatcher(AMatcher, &VerifyFound); VerifyMatch VerifyDynamicFound(nullptr, &DynamicFound); @@ -147,11 +154,13 @@ testing::AssertionResult matchesConditionally( template testing::AssertionResult matchesConditionally(const Twine &Code, const T &AMatcher, bool ExpectMatch, - ArrayRef TestLanguages) { + ArrayRef TestLanguages, + MatchFinder::MatchFinderOptions Options = + MatchFinder::MatchFinderOptions()) { for (auto Lang : TestLanguages) { auto Result = matchesConditionally( Code, AMatcher, ExpectMatch, getCommandLineArgsForTesting(Lang), -FileContentMappings(), getFilenameForTesting(Lang)); +FileContentMappings(), getFilenameForTesting(Lang), Options); if (!Result) return Result; } @@ -162,8 +171,10 @@ matchesConditionally(const Twine &Code, const T &AMatcher, bool ExpectMatch, template testing::AssertionResult matches(const Twine &Code, const T &AMatcher, -ArrayRef TestLanguages = {Lang_CXX11})
[clang] [Feat] Allow Finding across only parts of an AST. (PR #127423)
https://github.com/matts1 ready_for_review https://github.com/llvm/llvm-project/pull/127423 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 5d62a79 - [Serialization] Remove getMacroID (#127413)
Author: Kazu Hirata Date: 2025-02-16T20:03:34-08:00 New Revision: 5d62a79bb79fee20f92f26dc55fd78440b9945ca URL: https://github.com/llvm/llvm-project/commit/5d62a79bb79fee20f92f26dc55fd78440b9945ca DIFF: https://github.com/llvm/llvm-project/commit/5d62a79bb79fee20f92f26dc55fd78440b9945ca.diff LOG: [Serialization] Remove getMacroID (#127413) The last use was removed in: commit ee977933f7df9cef13cc06ac7fa3e4a22b72e41f Author: Richard Smith Date: Fri May 1 21:22:17 2015 + Added: Modified: clang/include/clang/Serialization/ASTWriter.h clang/lib/Serialization/ASTWriter.cpp Removed: diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 079e39a9fb678..ad291d0948b57 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -751,9 +751,6 @@ class ASTWriter : public ASTDeserializationListener, /// Get the unique number used to refer to the given macro. serialization::MacroID getMacroRef(MacroInfo *MI, const IdentifierInfo *Name); - /// Determine the ID of an already-emitted macro. - serialization::MacroID getMacroID(MacroInfo *MI); - uint32_t getMacroDirectivesOffset(const IdentifierInfo *Name); /// Emit a reference to a type. diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 903a165ee75c6..64791300fe722 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -,14 +,6 @@ MacroID ASTWriter::getMacroRef(MacroInfo *MI, const IdentifierInfo *Name) { return ID; } -MacroID ASTWriter::getMacroID(MacroInfo *MI) { - if (!MI || MI->isBuiltinMacro()) -return 0; - - assert(MacroIDs.contains(MI) && "Macro not emitted!"); - return MacroIDs[MI]; -} - uint32_t ASTWriter::getMacroDirectivesOffset(const IdentifierInfo *Name) { return IdentMacroDirectivesOffsetMap.lookup(Name); } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [libcxx] [llvm] [libc++][ranges] P2542R8: Implement `views::concat` (PR #120920)
https://github.com/changkhothuychung updated https://github.com/llvm/llvm-project/pull/120920 error: too big or took too long to generate ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [libcxx] [llvm] [libc++][ranges] P2542R8: Implement `views::concat` (PR #120920)
https://github.com/changkhothuychung updated https://github.com/llvm/llvm-project/pull/120920 error: too big or took too long to generate ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [libcxx] [llvm] [libc++][ranges] P2542R8: Implement `views::concat` (PR #120920)
https://github.com/changkhothuychung updated https://github.com/llvm/llvm-project/pull/120920 error: too big or took too long to generate ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Index] Use HeuristicResolver in libIndex (PR #125153)
https://github.com/zyn0217 edited https://github.com/llvm/llvm-project/pull/125153 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][Index] Use HeuristicResolver in libIndex (PR #125153)
https://github.com/zyn0217 commented: Thanks, the improvement looks good https://github.com/llvm/llvm-project/pull/125153 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [lld] [llvm] Integrated Distributed ThinLTO (DTLTO): Initial support (PR #126654)
@@ -969,6 +969,10 @@ def Xlinker : Separate<["-"], "Xlinker">, Flags<[LinkerInput, RenderAsInput]>, Visibility<[ClangOption, CLOption, FlangOption]>, HelpText<"Pass to the linker">, MetaVarName<"">, Group; +def Xdist : Separate<["-"], "Xdist">, Flags<[LinkOption]>, bd1976bris wrote: I have updated to use `-Xthinlto-distributor`. It's longer than `-Xdist` so I have used `CommaJoined` which allows e.g. `-fthinlto-distributor=incredibuild.exe -Xthinlto-distributor=--verbose,--j10` https://github.com/llvm/llvm-project/pull/126654 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clang-tidy] Add new check `readability-use-numeric-limits` (PR #127430)
https://github.com/stellar-aria created https://github.com/llvm/llvm-project/pull/127430 The adds a check that replaces specific numeric literals like `32767` with the equivalent call to `std::numeric_limits` (such as `std::numeric_limits::max())`. Partially addresses #34434, but notably does not handle cases listed in the title post such as `~0` and `-1`. >From ba0eef9808b42b01e356cd5c87745f7477e07c68 Mon Sep 17 00:00:00 2001 From: Katherine Whitlock Date: Sun, 16 Feb 2025 22:45:06 -0500 Subject: [PATCH] [clang-tidy] Add new check `readability-use-numeric-limits` --- .../clang-tidy/readability/CMakeLists.txt | 1 + .../readability/ReadabilityTidyModule.cpp | 3 + .../readability/UseNumericLimitsCheck.cpp | 135 ++ .../readability/UseNumericLimitsCheck.h | 41 ++ clang-tools-extra/docs/ReleaseNotes.rst | 5 + .../docs/clang-tidy/checks/list.rst | 1 + .../checks/readability/use-numeric-limits.rst | 22 +++ .../readability/use-numeric-limits.cpp| 85 +++ 8 files changed, 293 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/readability/use-numeric-limits.rst create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/use-numeric-limits.cpp diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt index 8f303c51e1b0d..e06f68bdda73f 100644 --- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt @@ -57,6 +57,7 @@ add_clang_library(clangTidyReadabilityModule STATIC UniqueptrDeleteReleaseCheck.cpp UppercaseLiteralSuffixCheck.cpp UseAnyOfAllOfCheck.cpp + UseNumericLimitsCheck.cpp UseStdMinMaxCheck.cpp LINK_LIBS diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp index d61c0ba39658e..054083d25952a 100644 --- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp @@ -60,6 +60,7 @@ #include "UniqueptrDeleteReleaseCheck.h" #include "UppercaseLiteralSuffixCheck.h" #include "UseAnyOfAllOfCheck.h" +#include "UseNumericLimitsCheck.h" #include "UseStdMinMaxCheck.h" namespace clang::tidy { @@ -170,6 +171,8 @@ class ReadabilityModule : public ClangTidyModule { "readability-uppercase-literal-suffix"); CheckFactories.registerCheck( "readability-use-anyofallof"); +CheckFactories.registerCheck( +"readability-use-numeric-limits"); CheckFactories.registerCheck( "readability-use-std-min-max"); } diff --git a/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp new file mode 100644 index 0..b26ae008cbdd5 --- /dev/null +++ b/clang-tools-extra/clang-tidy/readability/UseNumericLimitsCheck.cpp @@ -0,0 +1,135 @@ +//===--- UseNumericLimitsCheck.cpp - clang-tidy ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===--===// + +#include "UseNumericLimitsCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Preprocessor.h" +#include +#include + +using namespace clang::ast_matchers; + +namespace clang::tidy::readability { + +UseNumericLimitsCheck::UseNumericLimitsCheck(StringRef Name, + ClangTidyContext *Context) +: ClangTidyCheck(Name, Context), + SignedConstants{ + {std::numeric_limits::min(), + "std::numeric_limits::min()"}, + {std::numeric_limits::max(), + "std::numeric_limits::max()"}, + {std::numeric_limits::min(), + "std::numeric_limits::min()"}, + {std::numeric_limits::max(), + "std::numeric_limits::max()"}, + {std::numeric_limits::min(), + "std::numeric_limits::min()"}, + {std::numeric_limits::max(), + "std::numeric_limits::max()"}, + {std::numeric_limits::min(), + "std::numeric_limits::min()"}, + {std::numeric_limits::max(), + "std::numeric_limits::max()"}, + + }, + UnsignedConstants{ + {std::numeric_limits::max(), + "std::numeric_limits::max()"}, + {std::numeric_limits::max(), + "std::numeric_limits::max()"}, + {std::numeric_limits::max(), + "std::numeric
[clang-tools-extra] [clang-tidy] Add new check `readability-use-numeric-limits` (PR #127430)
github-actions[bot] wrote: Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using `@` followed by their GitHub username. If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the [LLVM GitHub User Guide](https://llvm.org/docs/GitHub.html). You can also ask questions in a comment on this PR, on the [LLVM Discord](https://discord.com/invite/xS7Z362) or on the [forums](https://discourse.llvm.org/). https://github.com/llvm/llvm-project/pull/127430 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Serialization] Remove getMacroID (PR #127413)
https://github.com/kazutakahirata closed https://github.com/llvm/llvm-project/pull/127413 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits