[clang] [Serialization] Remove getMacroID (PR #127413)

2025-02-16 Thread Chuanqi Xu via cfe-commits

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)

2025-02-16 Thread Chuanqi Xu via cfe-commits


@@ -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)

2025-02-16 Thread Nhat Nguyen via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread A. Jiang via cfe-commits


@@ -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)

2025-02-16 Thread A. Jiang via cfe-commits

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)

2025-02-16 Thread A. Jiang via cfe-commits


@@ -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)

2025-02-16 Thread via cfe-commits


@@ -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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread Chuanqi Xu via cfe-commits


@@ -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)

2025-02-16 Thread Nathan Ridge via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread via cfe-commits


@@ -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)

2025-02-16 Thread Chuanqi Xu via cfe-commits

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)

2025-02-16 Thread Farzon Lotfi via cfe-commits


@@ -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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread Nathan Ridge via cfe-commits

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)

2025-02-16 Thread Nathan Ridge via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread Younan Zhang via cfe-commits


@@ -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)

2025-02-16 Thread LLVM Continuous Integration via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread Timm Baeder via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread Timm Baeder via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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.
```
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.

---
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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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.
```
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.

---
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)

2025-02-16 Thread A. Jiang via cfe-commits

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)

2025-02-16 Thread A. Jiang via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits

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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits

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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Mészáros Gergely via cfe-commits


@@ -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)

2025-02-16 Thread Marco Elver via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread Kazu Hirata via cfe-commits

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)

2025-02-16 Thread Kazu Hirata via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread Michael Kruse via cfe-commits

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)

2025-02-16 Thread Michael Kruse via cfe-commits

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)

2025-02-16 Thread Shafik Yaghmour via cfe-commits

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)

2025-02-16 Thread Björn Schäpers via cfe-commits

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)

2025-02-16 Thread via cfe-commits


@@ -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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread Nathan Ridge via cfe-commits

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)

2025-02-16 Thread Tobias Ribizel via cfe-commits

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)

2025-02-16 Thread Nathan Ridge via cfe-commits

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)

2025-02-16 Thread Nhat Nguyen via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread Nhat Nguyen via cfe-commits

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)

2025-02-16 Thread Nhat Nguyen via cfe-commits

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)

2025-02-16 Thread Nhat Nguyen via cfe-commits

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)

2025-02-16 Thread Younan Zhang via cfe-commits

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)

2025-02-16 Thread Younan Zhang via cfe-commits

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)

2025-02-16 Thread via cfe-commits


@@ -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)

2025-02-16 Thread Katherine Whitlock via cfe-commits

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)

2025-02-16 Thread via cfe-commits

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)

2025-02-16 Thread Kazu Hirata via cfe-commits

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


  1   2   3   >