[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-03-20 Thread JJ Marr via cfe-commits

jj-marr wrote:

I'm still working on this. It seems like I broke the assertion tests. I'm 
unsure why, but it should be fixed if I figure out a better way of evaluating 
the macro.

https://github.com/llvm/llvm-project/pull/130458
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-04-17 Thread JJ Marr via cfe-commits

https://github.com/jj-marr converted_to_draft 
https://github.com/llvm/llvm-project/pull/130458
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-04-29 Thread JJ Marr via cfe-commits

https://github.com/jj-marr updated 
https://github.com/llvm/llvm-project/pull/130458

>From d06c5ab5c30e535893335af798df339b0e9c6878 Mon Sep 17 00:00:00 2001
From: JJ Marr 
Date: Sat, 8 Mar 2025 22:00:45 -0500
Subject: [PATCH] Explain which assertion failed during consteval

---
 .../clang/Basic/DiagnosticSemaKinds.td|  2 ++
 clang/lib/AST/ExprConstant.cpp| 11 ++
 clang/test/SemaCXX/consteval-assert.cpp   | 20 +++
 3 files changed, 33 insertions(+)
 create mode 100644 clang/test/SemaCXX/consteval-assert.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 4c96142e28134..58f32066f5da5 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -162,6 +162,8 @@ def err_ice_too_large : Error<
   "integer constant expression evaluates to value %0 that cannot be "
   "represented in a %1-bit %select{signed|unsigned}2 integer type">;
 def err_expr_not_string_literal : Error<"expression is not a string literal">;
+def note_constexpr_assert_failed : Note<
+  "assertion failed in constant evaluation: '%0'">;
 
 // Semantic analysis of constant literals.
 def ext_predef_outside_function : Warning<
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f2e49b9ea669e..3467a4d71acd5 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -8409,6 +8409,17 @@ class ExprEvaluatorBase
 return false;
 }
 
+// If an assertion fails during constant evaluation, give a specific note 
explaining that
+if (FD->getName() == "__assert_fail") {
+  const Expr *AssertionExpr = E->getArg(0);
+  const StringLiteral *AssertionText = 
dyn_cast(AssertionExpr->IgnoreParens()->IgnoreParenImpCasts());
+
+  Info.FFDiag(E->getBeginLoc(), diag::note_constexpr_assert_failed)
+  << (AssertionText ? AssertionText->getString() : "");
+
+  return false;
+}
+
 SmallVector CovariantAdjustmentPath;
 if (This) {
   auto *NamedMember = dyn_cast(FD);
diff --git a/clang/test/SemaCXX/consteval-assert.cpp 
b/clang/test/SemaCXX/consteval-assert.cpp
new file mode 100644
index 0..d253db2a3ddde
--- /dev/null
+++ b/clang/test/SemaCXX/consteval-assert.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -std=c++23 -verify=expected,cxx20_plus %s
+
+#ifdef __ASSERT_FUNCTION
+#undef __ASSERT_FUNCTION
+#endif
+extern "C" void __assert_fail(const char*, const char*, unsigned, const char*);
+
+#define assert(cond) \
+  ((cond) ? (void)0 : __assert_fail(#cond, __FILE__, __LINE__, __func__))
+
+consteval int square(int x) {
+  int result = x * x;
+  assert(result == 42); // expected-note {{assertion failed in constant 
evaluation: 'result == 42'}}
+  return result;
+}
+
+void test() {
+  auto val = square(2); // expected-note {{in call to 'square(2)'}} \
+  // expected-error {{call to consteval function 'square' is not a constant 
expression}}
+}

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-03-08 Thread JJ Marr via cfe-commits

https://github.com/jj-marr created 
https://github.com/llvm/llvm-project/pull/130458

Take this piece of code:
```cpp
#include 

consteval int square(int x) {
  int result = x * x;
  assert(result == 42);
  return result;
}

void test() {
  auto val = square(2);
}
```
The assertion will fail, and `clang++` will output 
(https://godbolt.org/z/hjz3KbTTv):
```cpp
:10:14: error: call to consteval function 'square' is not a constant 
expression
   10 |   auto val = square(2);
  |  ^
:5:3: note: non-constexpr function '__assert_fail' cannot be used in a 
constant expression
5 |   assert(result == 42);
  |   ^
/usr/include/assert.h:95:9: note: expanded from macro 'assert'
   95 |   : __assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION))
  | ^
:10:14: note: in call to 'square(2)'
   10 |   auto val = square(2);
  |  ^
/usr/include/assert.h:69:13: note: declared here
   69 | extern void __assert_fail (const char *__assertion, const char *__file,
  | ^
1 error generated.
Compiler returned: 1
```
This is confusing because it implies that the issue was using an assertion in a 
constant-evaluted context, and not that the assertion failed (`assert()` is OK 
in constant evaluation). This PR changes the error message to:
```cpp
test.cpp:10:14: error: call to consteval function 'square' is not a constant 
expression
   10 |   auto val = square(2);
  |  ^
test.cpp:5:3: note: assertion failed in consteval context: 'result == 42'
5 |   assert(result == 42);
  |   ^
/nix/store/lw21wr626v5sdcaxxkv2k4zf1121hfc9-glibc-2.40-36-dev/include/assert.h:102:9:
 note: expanded from macro 'assert'
  102 |   : __assert_fail (#expr, __ASSERT_FILE, __ASSERT_LINE, 
\
  | ^
test.cpp:10:14: note: in call to 'square(2)'
   10 |   auto val = square(2);
  |  ^
1 error generated.```

>From 8a09c78d3fdb151c86785822da6cb451025b4654 Mon Sep 17 00:00:00 2001
From: JJ Marr 
Date: Sat, 8 Mar 2025 22:00:45 -0500
Subject: [PATCH 1/2] Explain which assertion failed during consteval

---
 clang/include/clang/Basic/DiagnosticSemaKinds.td |  2 ++
 clang/lib/AST/ExprConstant.cpp   | 11 +++
 2 files changed, 13 insertions(+)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 21be7c358a61d..ff5f88d6ac572 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -107,6 +107,8 @@ def err_ice_too_large : Error<
   "integer constant expression evaluates to value %0 that cannot be "
   "represented in a %1-bit %select{signed|unsigned}2 integer type">;
 def err_expr_not_string_literal : Error<"expression is not a string literal">;
+def note_constexpr_assert_failed : Note<
+  "assertion failed in consteval context: '%0'">;
 
 // Semantic analysis of constant literals.
 def ext_predef_outside_function : Warning<
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index d9a1e5bb42343..7013f0b143a0a 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -8361,6 +8361,17 @@ class ExprEvaluatorBase
 return false;
 }
 
+// If an assertion fails during constant evaluation, give a specific note 
explaining that
+if (FD->getName() == "__assert_fail") {
+  const Expr *AssertionExpr = E->getArg(0);
+  const StringLiteral *AssertionText = 
dyn_cast(AssertionExpr->IgnoreParens()->IgnoreParenImpCasts());
+
+  Info.FFDiag(E->getBeginLoc(), diag::note_constexpr_assert_failed)
+  << (AssertionText ? AssertionText->getString() : "");
+
+  return false;
+}
+
 SmallVector CovariantAdjustmentPath;
 if (This) {
   auto *NamedMember = dyn_cast(FD);

>From c8fe23e62a6a0090ef050a3ca3ac9abe549b0aa6 Mon Sep 17 00:00:00 2001
From: JJ Marr 
Date: Sat, 8 Mar 2025 22:36:26 -0500
Subject: [PATCH 2/2] Add unit test

---
 clang/test/SemaCXX/consteval_assert.cpp | 20 
 1 file changed, 20 insertions(+)
 create mode 100644 clang/test/SemaCXX/consteval_assert.cpp

diff --git a/clang/test/SemaCXX/consteval_assert.cpp 
b/clang/test/SemaCXX/consteval_assert.cpp
new file mode 100644
index 0..94ca9ffd4888d
--- /dev/null
+++ b/clang/test/SemaCXX/consteval_assert.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -std=c++23 -verify=expected,cxx20_plus %s
+
+#ifdef __ASSERT_FUNCTION
+#undef __ASSERT_FUNCTION
+#endif
+extern "C" void __assert_fail(const char*, const char*, unsigned, const char*);
+
+#define assert(cond) \
+  ((cond) ? (void)0 : __assert_fail(#cond, __FILE__, __LINE__, __func__))
+
+consteval int square(int x) {
+  int result = x * x;
+  assert(result == 42); // expected-note {{assertion failed in consteval 
context: 'result == 42'}}
+  return result;
+}
+
+void test() {
+  auto val = square(2); // expected-note {{in call to 'square(2)'}} \
+  // expec

[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-03-08 Thread JJ Marr via cfe-commits

https://github.com/jj-marr updated 
https://github.com/llvm/llvm-project/pull/130458

>From d61892d8546944000118ad0312886da75cd6509b Mon Sep 17 00:00:00 2001
From: JJ Marr 
Date: Sat, 8 Mar 2025 22:00:45 -0500
Subject: [PATCH] Explain which assertion failed during consteval

---
 .../clang/Basic/DiagnosticSemaKinds.td|  2 ++
 clang/lib/AST/ExprConstant.cpp| 11 ++
 clang/test/SemaCXX/consteval_assert.cpp   | 20 +++
 3 files changed, 33 insertions(+)
 create mode 100644 clang/test/SemaCXX/consteval_assert.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 21be7c358a61d..ff5f88d6ac572 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -107,6 +107,8 @@ def err_ice_too_large : Error<
   "integer constant expression evaluates to value %0 that cannot be "
   "represented in a %1-bit %select{signed|unsigned}2 integer type">;
 def err_expr_not_string_literal : Error<"expression is not a string literal">;
+def note_constexpr_assert_failed : Note<
+  "assertion failed in consteval context: '%0'">;
 
 // Semantic analysis of constant literals.
 def ext_predef_outside_function : Warning<
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index d9a1e5bb42343..7013f0b143a0a 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -8361,6 +8361,17 @@ class ExprEvaluatorBase
 return false;
 }
 
+// If an assertion fails during constant evaluation, give a specific note 
explaining that
+if (FD->getName() == "__assert_fail") {
+  const Expr *AssertionExpr = E->getArg(0);
+  const StringLiteral *AssertionText = 
dyn_cast(AssertionExpr->IgnoreParens()->IgnoreParenImpCasts());
+
+  Info.FFDiag(E->getBeginLoc(), diag::note_constexpr_assert_failed)
+  << (AssertionText ? AssertionText->getString() : "");
+
+  return false;
+}
+
 SmallVector CovariantAdjustmentPath;
 if (This) {
   auto *NamedMember = dyn_cast(FD);
diff --git a/clang/test/SemaCXX/consteval_assert.cpp 
b/clang/test/SemaCXX/consteval_assert.cpp
new file mode 100644
index 0..94ca9ffd4888d
--- /dev/null
+++ b/clang/test/SemaCXX/consteval_assert.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -std=c++23 -verify=expected,cxx20_plus %s
+
+#ifdef __ASSERT_FUNCTION
+#undef __ASSERT_FUNCTION
+#endif
+extern "C" void __assert_fail(const char*, const char*, unsigned, const char*);
+
+#define assert(cond) \
+  ((cond) ? (void)0 : __assert_fail(#cond, __FILE__, __LINE__, __func__))
+
+consteval int square(int x) {
+  int result = x * x;
+  assert(result == 42); // expected-note {{assertion failed in consteval 
context: 'result == 42'}}
+  return result;
+}
+
+void test() {
+  auto val = square(2); // expected-note {{in call to 'square(2)'}} \
+  // expected-error {{call to consteval function 'square' is not a constant 
expression}}
+}

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-03-10 Thread JJ Marr via cfe-commits


@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -std=c++23 -verify=expected,cxx20_plus %s
+
+#ifdef __ASSERT_FUNCTION
+#undef __ASSERT_FUNCTION
+#endif
+extern "C" void __assert_fail(const char*, const char*, unsigned, const char*);
+
+#define assert(cond) \
+  ((cond) ? (void)0 : __assert_fail(#cond, __FILE__, __LINE__, __func__))
+
+consteval int square(int x) {
+  int result = x * x;
+  assert(result == 42); // expected-note {{assertion failed in consteval 
context: 'result == 42'}}

jj-marr wrote:

Perhaps it should say "during constant evaluation". Both `constexpr` and 
`consteval` functions can be constant evaluated (i.e. evaluated at 
compile-time), but it's also possible for a `constexpr` function to be used at 
runtime, in which case the assertion would _not_ be triggered.

https://github.com/llvm/llvm-project/pull/130458
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-04-04 Thread JJ Marr via cfe-commits

https://github.com/jj-marr updated 
https://github.com/llvm/llvm-project/pull/130458

>From 0cba377eb8693657b7688cd1feb1cc9c5734f307 Mon Sep 17 00:00:00 2001
From: JJ Marr 
Date: Sat, 8 Mar 2025 22:00:45 -0500
Subject: [PATCH] Explain which assertion failed during consteval

---
 .../clang/Basic/DiagnosticSemaKinds.td|  2 ++
 clang/lib/AST/ExprConstant.cpp| 11 ++
 clang/test/SemaCXX/consteval_assert.cpp   | 20 +++
 3 files changed, 33 insertions(+)
 create mode 100644 clang/test/SemaCXX/consteval_assert.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 21be7c358a61d..0c8ee08117058 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -107,6 +107,8 @@ def err_ice_too_large : Error<
   "integer constant expression evaluates to value %0 that cannot be "
   "represented in a %1-bit %select{signed|unsigned}2 integer type">;
 def err_expr_not_string_literal : Error<"expression is not a string literal">;
+def note_constexpr_assert_failed : Note<
+  "assertion failed in constant evaluation: '%0'">;
 
 // Semantic analysis of constant literals.
 def ext_predef_outside_function : Warning<
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index d9a1e5bb42343..7013f0b143a0a 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -8361,6 +8361,17 @@ class ExprEvaluatorBase
 return false;
 }
 
+// If an assertion fails during constant evaluation, give a specific note 
explaining that
+if (FD->getName() == "__assert_fail") {
+  const Expr *AssertionExpr = E->getArg(0);
+  const StringLiteral *AssertionText = 
dyn_cast(AssertionExpr->IgnoreParens()->IgnoreParenImpCasts());
+
+  Info.FFDiag(E->getBeginLoc(), diag::note_constexpr_assert_failed)
+  << (AssertionText ? AssertionText->getString() : "");
+
+  return false;
+}
+
 SmallVector CovariantAdjustmentPath;
 if (This) {
   auto *NamedMember = dyn_cast(FD);
diff --git a/clang/test/SemaCXX/consteval_assert.cpp 
b/clang/test/SemaCXX/consteval_assert.cpp
new file mode 100644
index 0..d253db2a3ddde
--- /dev/null
+++ b/clang/test/SemaCXX/consteval_assert.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -std=c++23 -verify=expected,cxx20_plus %s
+
+#ifdef __ASSERT_FUNCTION
+#undef __ASSERT_FUNCTION
+#endif
+extern "C" void __assert_fail(const char*, const char*, unsigned, const char*);
+
+#define assert(cond) \
+  ((cond) ? (void)0 : __assert_fail(#cond, __FILE__, __LINE__, __func__))
+
+consteval int square(int x) {
+  int result = x * x;
+  assert(result == 42); // expected-note {{assertion failed in constant 
evaluation: 'result == 42'}}
+  return result;
+}
+
+void test() {
+  auto val = square(2); // expected-note {{in call to 'square(2)'}} \
+  // expected-error {{call to consteval function 'square' is not a constant 
expression}}
+}

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-05-09 Thread JJ Marr via cfe-commits

https://github.com/jj-marr ready_for_review 
https://github.com/llvm/llvm-project/pull/130458
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-05-09 Thread JJ Marr via cfe-commits

https://github.com/jj-marr updated 
https://github.com/llvm/llvm-project/pull/130458



  



Rate limit · GitHub


  body {
background-color: #f6f8fa;
color: #24292e;
font-family: -apple-system,BlinkMacSystemFont,Segoe 
UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;
font-size: 14px;
line-height: 1.5;
margin: 0;
  }

  .container { margin: 50px auto; max-width: 600px; text-align: center; 
padding: 0 24px; }

  a { color: #0366d6; text-decoration: none; }
  a:hover { text-decoration: underline; }

  h1 { line-height: 60px; font-size: 48px; font-weight: 300; margin: 0px; 
text-shadow: 0 1px 0 #fff; }
  p { color: rgba(0, 0, 0, 0.5); margin: 20px 0 40px; }

  ul { list-style: none; margin: 25px 0; padding: 0; }
  li { display: table-cell; font-weight: bold; width: 1%; }

  .logo { display: inline-block; margin-top: 35px; }
  .logo-img-2x { display: none; }
  @media
  only screen and (-webkit-min-device-pixel-ratio: 2),
  only screen and (   min--moz-device-pixel-ratio: 2),
  only screen and ( -o-min-device-pixel-ratio: 2/1),
  only screen and (min-device-pixel-ratio: 2),
  only screen and (min-resolution: 192dpi),
  only screen and (min-resolution: 2dppx) {
.logo-img-1x { display: none; }
.logo-img-2x { display: inline-block; }
  }

  #suggestions {
margin-top: 35px;
color: #ccc;
  }
  #suggestions a {
color: #66;
font-weight: 200;
font-size: 14px;
margin: 0 10px;
  }


  
  



  Whoa there!
  You have exceeded a secondary rate limit.
Please wait a few minutes before you try again;
in some cases this may take up to an hour.
  
  
https://support.github.com/contact";>Contact Support —
https://githubstatus.com";>GitHub Status —
https://twitter.com/githubstatus";>@githubstatus
  

  

  

  

  

  


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-05-09 Thread JJ Marr via cfe-commits

https://github.com/jj-marr updated 
https://github.com/llvm/llvm-project/pull/130458

>From 3b6d28e4f74c1fda73abe3b5972d5ac2a43576de Mon Sep 17 00:00:00 2001
From: JJ Marr 
Date: Sat, 8 Mar 2025 22:00:45 -0500
Subject: [PATCH] Explain which assertion failed during consteval

---
 clang/docs/ReleaseNotes.rst   |  4 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  2 ++
 clang/lib/AST/ExprConstant.cpp| 10 --
 clang/test/SemaCXX/consteval-assert.cpp   | 34 +++
 4 files changed, 48 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/SemaCXX/consteval-assert.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index eb2e8f2b8a6c0..4c719ebc19221 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -419,6 +419,10 @@ Improvements to Clang's diagnostics
 - ``-Winitializer-overrides`` and ``-Wreorder-init-list`` are now grouped under
   the ``-Wc99-designator`` diagnostic group, as they also are about the
   behavior of the C99 feature as it was introduced into C++20. Fixes #GH47037
+  
+- Explanatory note is printed when ``assert`` fails during evaluation of a
+  constant expression. Prior to this, the error inaccurately implied that 
assert
+  could not be used at all in a constant expression (#GH130458)
 
 Improvements to Clang's time-trace
 --
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 4c96142e28134..87e982e9c491c 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -162,6 +162,8 @@ def err_ice_too_large : Error<
   "integer constant expression evaluates to value %0 that cannot be "
   "represented in a %1-bit %select{signed|unsigned}2 integer type">;
 def err_expr_not_string_literal : Error<"expression is not a string literal">;
+def note_constexpr_assert_failed : Note<
+  "assertion failed during evaluation of constant expression">;
 
 // Semantic analysis of constant literals.
 def ext_predef_outside_function : Warning<
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f2e49b9ea669e..3ee355d6570ed 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -5975,9 +5975,15 @@ static bool CheckConstexprFunction(EvalInfo &Info, 
SourceLocation CallLoc,
 
Definition->hasAttr(
 return true;
 
-  if (Info.getLangOpts().CPlusPlus11) {
-const FunctionDecl *DiagDecl = Definition ? Definition : Declaration;
+  const FunctionDecl *DiagDecl = Definition ? Definition : Declaration;  
+  if (CallLoc.isMacroID() && (DiagDecl->getName() == "__assert_rtn" ||
+  DiagDecl->getName() == "__assert_fail" ||
+  DiagDecl->getName() == "_wassert")) {
+Info.FFDiag(CallLoc, diag::note_constexpr_assert_failed);
+return false;
+  }
 
+  if (Info.getLangOpts().CPlusPlus11) {
 // If this function is not constexpr because it is an inherited
 // non-constexpr constructor, diagnose that directly.
 auto *CD = dyn_cast(DiagDecl);
diff --git a/clang/test/SemaCXX/consteval-assert.cpp 
b/clang/test/SemaCXX/consteval-assert.cpp
new file mode 100644
index 0..b54a38ff26105
--- /dev/null
+++ b/clang/test/SemaCXX/consteval-assert.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++23 -verify=expected,cxx20_plus -DTEST_LINUX %s
+// RUN: %clang_cc1 -std=c++23 -verify=expected,cxx20_plus -DTEST_WINDOWS %s
+// RUN: %clang_cc1 -std=c++23 -verify=expected,cxx20_plus -DTEST_DARWIN %s
+
+#ifdef __ASSERT_FUNCTION
+#undef __ASSERT_FUNCTION
+#endif
+
+#if defined(TEST_LINUX)
+  extern "C" void __assert_fail(const char*, const char*, unsigned, const 
char*);
+  #define assert(cond) \
+((cond) ? (void)0 : __assert_fail(#cond, __FILE__, __LINE__, __func__))
+#elif defined(TEST_DARWIN)
+  void __assert_rtn(const char *, const char *, int, const char *);
+  #define assert(cond) \
+  (__builtin_expect(!(cond), 0) ? __assert_rtn(__func__, __FILE__, __LINE__, 
#cond) : (void)0)
+#elif defined(TEST_WINDOWS)
+  void /*__cdecl*/ _wassert(const wchar_t*, const wchar_t*, unsigned);
+  #define _CRT_WIDE_(s) L ## s
+  #define _CRT_WIDE(s) _CRT_WIDE_(s)
+  #define assert(cond) \
+(void)((!!(cond)) || (_wassert(_CRT_WIDE(#cond), _CRT_WIDE(__FILE__), 
(unsigned)(__LINE__)), 0))
+#endif
+
+consteval int square(int x) {
+  int result = x * x;
+  assert(result == 42); // expected-note {{assertion failed during evaluation 
of constant expression}}
+  return result;
+}
+
+void test() {
+  auto val = square(2); // expected-note {{in call to 'square(2)'}} \
+  // expected-error {{call to consteval function 'square' is not a constant 
expression}}
+}

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-

[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-05-09 Thread JJ Marr via cfe-commits

https://github.com/jj-marr updated 
https://github.com/llvm/llvm-project/pull/130458



  



Rate limit · GitHub


  body {
background-color: #f6f8fa;
color: #24292e;
font-family: -apple-system,BlinkMacSystemFont,Segoe 
UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;
font-size: 14px;
line-height: 1.5;
margin: 0;
  }

  .container { margin: 50px auto; max-width: 600px; text-align: center; 
padding: 0 24px; }

  a { color: #0366d6; text-decoration: none; }
  a:hover { text-decoration: underline; }

  h1 { line-height: 60px; font-size: 48px; font-weight: 300; margin: 0px; 
text-shadow: 0 1px 0 #fff; }
  p { color: rgba(0, 0, 0, 0.5); margin: 20px 0 40px; }

  ul { list-style: none; margin: 25px 0; padding: 0; }
  li { display: table-cell; font-weight: bold; width: 1%; }

  .logo { display: inline-block; margin-top: 35px; }
  .logo-img-2x { display: none; }
  @media
  only screen and (-webkit-min-device-pixel-ratio: 2),
  only screen and (   min--moz-device-pixel-ratio: 2),
  only screen and ( -o-min-device-pixel-ratio: 2/1),
  only screen and (min-device-pixel-ratio: 2),
  only screen and (min-resolution: 192dpi),
  only screen and (min-resolution: 2dppx) {
.logo-img-1x { display: none; }
.logo-img-2x { display: inline-block; }
  }

  #suggestions {
margin-top: 35px;
color: #ccc;
  }
  #suggestions a {
color: #66;
font-weight: 200;
font-size: 14px;
margin: 0 10px;
  }


  
  



  Whoa there!
  You have exceeded a secondary rate limit.
Please wait a few minutes before you try again;
in some cases this may take up to an hour.
  
  
https://support.github.com/contact";>Contact Support —
https://githubstatus.com";>GitHub Status —
https://twitter.com/githubstatus";>@githubstatus
  

  

  

  

  

  


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-05-10 Thread JJ Marr via cfe-commits

https://github.com/jj-marr updated 
https://github.com/llvm/llvm-project/pull/130458



  



Rate limit · GitHub


  body {
background-color: #f6f8fa;
color: #24292e;
font-family: -apple-system,BlinkMacSystemFont,Segoe 
UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;
font-size: 14px;
line-height: 1.5;
margin: 0;
  }

  .container { margin: 50px auto; max-width: 600px; text-align: center; 
padding: 0 24px; }

  a { color: #0366d6; text-decoration: none; }
  a:hover { text-decoration: underline; }

  h1 { line-height: 60px; font-size: 48px; font-weight: 300; margin: 0px; 
text-shadow: 0 1px 0 #fff; }
  p { color: rgba(0, 0, 0, 0.5); margin: 20px 0 40px; }

  ul { list-style: none; margin: 25px 0; padding: 0; }
  li { display: table-cell; font-weight: bold; width: 1%; }

  .logo { display: inline-block; margin-top: 35px; }
  .logo-img-2x { display: none; }
  @media
  only screen and (-webkit-min-device-pixel-ratio: 2),
  only screen and (   min--moz-device-pixel-ratio: 2),
  only screen and ( -o-min-device-pixel-ratio: 2/1),
  only screen and (min-device-pixel-ratio: 2),
  only screen and (min-resolution: 192dpi),
  only screen and (min-resolution: 2dppx) {
.logo-img-1x { display: none; }
.logo-img-2x { display: inline-block; }
  }

  #suggestions {
margin-top: 35px;
color: #ccc;
  }
  #suggestions a {
color: #66;
font-weight: 200;
font-size: 14px;
margin: 0 10px;
  }


  
  



  Whoa there!
  You have exceeded a secondary rate limit.
Please wait a few minutes before you try again;
in some cases this may take up to an hour.
  
  
https://support.github.com/contact";>Contact Support —
https://githubstatus.com";>GitHub Status —
https://twitter.com/githubstatus";>@githubstatus
  

  

  

  

  

  


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-05-10 Thread JJ Marr via cfe-commits


@@ -5975,9 +5975,15 @@ static bool CheckConstexprFunction(EvalInfo &Info, 
SourceLocation CallLoc,
 
Definition->hasAttr(
 return true;
 
-  if (Info.getLangOpts().CPlusPlus11) {
-const FunctionDecl *DiagDecl = Definition ? Definition : Declaration;
+  const FunctionDecl *DiagDecl = Definition ? Definition : Declaration;  
+  if (CallLoc.isMacroID() && (DiagDecl->getName() == "__assert_rtn" ||

jj-marr wrote:

Done for both.

https://github.com/llvm/llvm-project/pull/130458
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-05-09 Thread JJ Marr via cfe-commits

jj-marr wrote:

> LGTM modulo nit.
> 
> Are you happy with the current state? @cor3ntin @Sirraide

Shouldn't CI be passing? I can't figure out why there are failures.

https://github.com/llvm/llvm-project/pull/130458
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-05-09 Thread JJ Marr via cfe-commits


@@ -5975,9 +5975,15 @@ static bool CheckConstexprFunction(EvalInfo &Info, 
SourceLocation CallLoc,
 
Definition->hasAttr(
 return true;
 
-  if (Info.getLangOpts().CPlusPlus11) {
-const FunctionDecl *DiagDecl = Definition ? Definition : Declaration;
+  const FunctionDecl *DiagDecl = Definition ? Definition : Declaration;  
+  if (CallLoc.isMacroID() && (DiagDecl->getName() == "__assert_rtn" ||

jj-marr wrote:

I have no idea how to improve this, otherwise I'd do it. How would I get access 
to the preprocessor from here?

https://github.com/llvm/llvm-project/pull/130458
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-05-11 Thread JJ Marr via cfe-commits


@@ -5975,9 +5975,22 @@ static bool CheckConstexprFunction(EvalInfo &Info, 
SourceLocation CallLoc,
 
Definition->hasAttr(
 return true;
 
-  if (Info.getLangOpts().CPlusPlus11) {
-const FunctionDecl *DiagDecl = Definition ? Definition : Declaration;
+  const FunctionDecl *DiagDecl = Definition ? Definition : Declaration;
+  // Special note for the assert() macro, as the normal error message falsely
+  // implies we cannot use an assertion during constant evaluation.
+  if (CallLoc.isMacroID() && DiagDecl->getIdentifier()) {
+// FIXME: Instead of checking for an implementation-defined function,
+// check and evaluate the assert() macro.

jj-marr wrote:

I have no idea how to access the preprocessor from this method and I am too 
inexperienced to know where to start. 
If you can give me a hint on where to look I would appreciate that. Do I just 
do a big refactor and pass it in as a parameter to the function? Or is there 
some method on an object I already have? 

https://github.com/llvm/llvm-project/pull/130458
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-05-12 Thread JJ Marr via cfe-commits

https://github.com/jj-marr updated 
https://github.com/llvm/llvm-project/pull/130458



  



Rate limit · GitHub


  body {
background-color: #f6f8fa;
color: #24292e;
font-family: -apple-system,BlinkMacSystemFont,Segoe 
UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;
font-size: 14px;
line-height: 1.5;
margin: 0;
  }

  .container { margin: 50px auto; max-width: 600px; text-align: center; 
padding: 0 24px; }

  a { color: #0366d6; text-decoration: none; }
  a:hover { text-decoration: underline; }

  h1 { line-height: 60px; font-size: 48px; font-weight: 300; margin: 0px; 
text-shadow: 0 1px 0 #fff; }
  p { color: rgba(0, 0, 0, 0.5); margin: 20px 0 40px; }

  ul { list-style: none; margin: 25px 0; padding: 0; }
  li { display: table-cell; font-weight: bold; width: 1%; }

  .logo { display: inline-block; margin-top: 35px; }
  .logo-img-2x { display: none; }
  @media
  only screen and (-webkit-min-device-pixel-ratio: 2),
  only screen and (   min--moz-device-pixel-ratio: 2),
  only screen and ( -o-min-device-pixel-ratio: 2/1),
  only screen and (min-device-pixel-ratio: 2),
  only screen and (min-resolution: 192dpi),
  only screen and (min-resolution: 2dppx) {
.logo-img-1x { display: none; }
.logo-img-2x { display: inline-block; }
  }

  #suggestions {
margin-top: 35px;
color: #ccc;
  }
  #suggestions a {
color: #66;
font-weight: 200;
font-size: 14px;
margin: 0 10px;
  }


  
  



  Whoa there!
  You have exceeded a secondary rate limit.
Please wait a few minutes before you try again;
in some cases this may take up to an hour.
  
  
https://support.github.com/contact";>Contact Support —
https://githubstatus.com";>GitHub Status —
https://twitter.com/githubstatus";>@githubstatus
  

  

  

  

  

  


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-05-13 Thread JJ Marr via cfe-commits

https://github.com/jj-marr updated 
https://github.com/llvm/llvm-project/pull/130458

>From 64eb62576dc1ecf0e696f2448e410c2fd77575de Mon Sep 17 00:00:00 2001
From: JJ Marr 
Date: Sat, 8 Mar 2025 22:00:45 -0500
Subject: [PATCH] Explain which assertion failed during consteval

---
 clang/docs/ReleaseNotes.rst   |  4 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  2 ++
 clang/lib/AST/ExprConstant.cpp| 17 --
 clang/test/SemaCXX/consteval-assert.cpp   | 34 +++
 4 files changed, 55 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/SemaCXX/consteval-assert.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2c3c75b88a9fe..01a4f96404681 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -523,6 +523,10 @@ Improvements to Clang's diagnostics
 
 - An error is now emitted when OpenMP ``collapse`` and ``ordered`` clauses 
have an
   argument larger than what can fit within a 64-bit integer.
+  
+- Explanatory note is printed when ``assert`` fails during evaluation of a
+  constant expression. Prior to this, the error inaccurately implied that 
assert
+  could not be used at all in a constant expression (#GH130458)
 
 Improvements to Clang's time-trace
 --
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 3efe9593b8633..a84f84b4653de 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -164,6 +164,8 @@ def err_ice_too_large : Error<
   "integer constant expression evaluates to value %0 that cannot be "
   "represented in a %1-bit %select{signed|unsigned}2 integer type">;
 def err_expr_not_string_literal : Error<"expression is not a string literal">;
+def note_constexpr_assert_failed : Note<
+  "assertion failed during evaluation of constant expression">;
 
 // Semantic analysis of constant literals.
 def ext_predef_outside_function : Warning<
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 500d43accb082..c09afef9c4bf9 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -5975,9 +5975,22 @@ static bool CheckConstexprFunction(EvalInfo &Info, 
SourceLocation CallLoc,
 
Definition->hasAttr(
 return true;
 
-  if (Info.getLangOpts().CPlusPlus11) {
-const FunctionDecl *DiagDecl = Definition ? Definition : Declaration;
+  const FunctionDecl *DiagDecl = Definition ? Definition : Declaration;
+  // Special note for the assert() macro, as the normal error message falsely
+  // implies we cannot use an assertion during constant evaluation.
+  if (CallLoc.isMacroID() && DiagDecl->getIdentifier()) {
+// FIXME: Instead of checking for an implementation-defined function,
+// check and evaluate the assert() macro.
+StringRef Name = DiagDecl->getName();
+bool AssertFailed =
+Name == "__assert_rtn" || Name == "__assert_fail" || Name == 
"_wassert";
+if (AssertFailed) {
+  Info.FFDiag(CallLoc, diag::note_constexpr_assert_failed);
+  return false;
+}
+  }
 
+  if (Info.getLangOpts().CPlusPlus11) {
 // If this function is not constexpr because it is an inherited
 // non-constexpr constructor, diagnose that directly.
 auto *CD = dyn_cast(DiagDecl);
diff --git a/clang/test/SemaCXX/consteval-assert.cpp 
b/clang/test/SemaCXX/consteval-assert.cpp
new file mode 100644
index 0..b54a38ff26105
--- /dev/null
+++ b/clang/test/SemaCXX/consteval-assert.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++23 -verify=expected,cxx20_plus -DTEST_LINUX %s
+// RUN: %clang_cc1 -std=c++23 -verify=expected,cxx20_plus -DTEST_WINDOWS %s
+// RUN: %clang_cc1 -std=c++23 -verify=expected,cxx20_plus -DTEST_DARWIN %s
+
+#ifdef __ASSERT_FUNCTION
+#undef __ASSERT_FUNCTION
+#endif
+
+#if defined(TEST_LINUX)
+  extern "C" void __assert_fail(const char*, const char*, unsigned, const 
char*);
+  #define assert(cond) \
+((cond) ? (void)0 : __assert_fail(#cond, __FILE__, __LINE__, __func__))
+#elif defined(TEST_DARWIN)
+  void __assert_rtn(const char *, const char *, int, const char *);
+  #define assert(cond) \
+  (__builtin_expect(!(cond), 0) ? __assert_rtn(__func__, __FILE__, __LINE__, 
#cond) : (void)0)
+#elif defined(TEST_WINDOWS)
+  void /*__cdecl*/ _wassert(const wchar_t*, const wchar_t*, unsigned);
+  #define _CRT_WIDE_(s) L ## s
+  #define _CRT_WIDE(s) _CRT_WIDE_(s)
+  #define assert(cond) \
+(void)((!!(cond)) || (_wassert(_CRT_WIDE(#cond), _CRT_WIDE(__FILE__), 
(unsigned)(__LINE__)), 0))
+#endif
+
+consteval int square(int x) {
+  int result = x * x;
+  assert(result == 42); // expected-note {{assertion failed during evaluation 
of constant expression}}
+  return result;
+}
+
+void test() {
+  auto val = square(2); // expected-note {{in call to 'square(2)'}} \
+  // expected-error {{call

[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-05-13 Thread JJ Marr via cfe-commits

https://github.com/jj-marr updated 
https://github.com/llvm/llvm-project/pull/130458

>From 67984fbf0374fa40fd7b73431b17baddc301290f Mon Sep 17 00:00:00 2001
From: JJ Marr 
Date: Sat, 8 Mar 2025 22:00:45 -0500
Subject: [PATCH] Explain which assertion failed during consteval

---
 clang/docs/ReleaseNotes.rst   |  4 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  2 ++
 clang/lib/AST/ExprConstant.cpp| 17 --
 clang/test/SemaCXX/consteval-assert.cpp   | 34 +++
 4 files changed, 55 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/SemaCXX/consteval-assert.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index bc13d02e2d20b..6ff370004d6ab 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -523,6 +523,10 @@ Improvements to Clang's diagnostics
 
 - An error is now emitted when OpenMP ``collapse`` and ``ordered`` clauses 
have an
   argument larger than what can fit within a 64-bit integer.
+  
+- Explanatory note is printed when ``assert`` fails during evaluation of a
+  constant expression. Prior to this, the error inaccurately implied that 
assert
+  could not be used at all in a constant expression (#GH130458)
 
 Improvements to Clang's time-trace
 --
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 3efe9593b8633..a84f84b4653de 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -164,6 +164,8 @@ def err_ice_too_large : Error<
   "integer constant expression evaluates to value %0 that cannot be "
   "represented in a %1-bit %select{signed|unsigned}2 integer type">;
 def err_expr_not_string_literal : Error<"expression is not a string literal">;
+def note_constexpr_assert_failed : Note<
+  "assertion failed during evaluation of constant expression">;
 
 // Semantic analysis of constant literals.
 def ext_predef_outside_function : Warning<
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 500d43accb082..c09afef9c4bf9 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -5975,9 +5975,22 @@ static bool CheckConstexprFunction(EvalInfo &Info, 
SourceLocation CallLoc,
 
Definition->hasAttr(
 return true;
 
-  if (Info.getLangOpts().CPlusPlus11) {
-const FunctionDecl *DiagDecl = Definition ? Definition : Declaration;
+  const FunctionDecl *DiagDecl = Definition ? Definition : Declaration;
+  // Special note for the assert() macro, as the normal error message falsely
+  // implies we cannot use an assertion during constant evaluation.
+  if (CallLoc.isMacroID() && DiagDecl->getIdentifier()) {
+// FIXME: Instead of checking for an implementation-defined function,
+// check and evaluate the assert() macro.
+StringRef Name = DiagDecl->getName();
+bool AssertFailed =
+Name == "__assert_rtn" || Name == "__assert_fail" || Name == 
"_wassert";
+if (AssertFailed) {
+  Info.FFDiag(CallLoc, diag::note_constexpr_assert_failed);
+  return false;
+}
+  }
 
+  if (Info.getLangOpts().CPlusPlus11) {
 // If this function is not constexpr because it is an inherited
 // non-constexpr constructor, diagnose that directly.
 auto *CD = dyn_cast(DiagDecl);
diff --git a/clang/test/SemaCXX/consteval-assert.cpp 
b/clang/test/SemaCXX/consteval-assert.cpp
new file mode 100644
index 0..b54a38ff26105
--- /dev/null
+++ b/clang/test/SemaCXX/consteval-assert.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++23 -verify=expected,cxx20_plus -DTEST_LINUX %s
+// RUN: %clang_cc1 -std=c++23 -verify=expected,cxx20_plus -DTEST_WINDOWS %s
+// RUN: %clang_cc1 -std=c++23 -verify=expected,cxx20_plus -DTEST_DARWIN %s
+
+#ifdef __ASSERT_FUNCTION
+#undef __ASSERT_FUNCTION
+#endif
+
+#if defined(TEST_LINUX)
+  extern "C" void __assert_fail(const char*, const char*, unsigned, const 
char*);
+  #define assert(cond) \
+((cond) ? (void)0 : __assert_fail(#cond, __FILE__, __LINE__, __func__))
+#elif defined(TEST_DARWIN)
+  void __assert_rtn(const char *, const char *, int, const char *);
+  #define assert(cond) \
+  (__builtin_expect(!(cond), 0) ? __assert_rtn(__func__, __FILE__, __LINE__, 
#cond) : (void)0)
+#elif defined(TEST_WINDOWS)
+  void /*__cdecl*/ _wassert(const wchar_t*, const wchar_t*, unsigned);
+  #define _CRT_WIDE_(s) L ## s
+  #define _CRT_WIDE(s) _CRT_WIDE_(s)
+  #define assert(cond) \
+(void)((!!(cond)) || (_wassert(_CRT_WIDE(#cond), _CRT_WIDE(__FILE__), 
(unsigned)(__LINE__)), 0))
+#endif
+
+consteval int square(int x) {
+  int result = x * x;
+  assert(result == 42); // expected-note {{assertion failed during evaluation 
of constant expression}}
+  return result;
+}
+
+void test() {
+  auto val = square(2); // expected-note {{in call to 'square(2)'}} \
+  // expected-error {{call

[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-05-13 Thread JJ Marr via cfe-commits

https://github.com/jj-marr updated 
https://github.com/llvm/llvm-project/pull/130458



  



Rate limit · GitHub


  body {
background-color: #f6f8fa;
color: #24292e;
font-family: -apple-system,BlinkMacSystemFont,Segoe 
UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;
font-size: 14px;
line-height: 1.5;
margin: 0;
  }

  .container { margin: 50px auto; max-width: 600px; text-align: center; 
padding: 0 24px; }

  a { color: #0366d6; text-decoration: none; }
  a:hover { text-decoration: underline; }

  h1 { line-height: 60px; font-size: 48px; font-weight: 300; margin: 0px; 
text-shadow: 0 1px 0 #fff; }
  p { color: rgba(0, 0, 0, 0.5); margin: 20px 0 40px; }

  ul { list-style: none; margin: 25px 0; padding: 0; }
  li { display: table-cell; font-weight: bold; width: 1%; }

  .logo { display: inline-block; margin-top: 35px; }
  .logo-img-2x { display: none; }
  @media
  only screen and (-webkit-min-device-pixel-ratio: 2),
  only screen and (   min--moz-device-pixel-ratio: 2),
  only screen and ( -o-min-device-pixel-ratio: 2/1),
  only screen and (min-device-pixel-ratio: 2),
  only screen and (min-resolution: 192dpi),
  only screen and (min-resolution: 2dppx) {
.logo-img-1x { display: none; }
.logo-img-2x { display: inline-block; }
  }

  #suggestions {
margin-top: 35px;
color: #ccc;
  }
  #suggestions a {
color: #66;
font-weight: 200;
font-size: 14px;
margin: 0 10px;
  }


  
  



  Whoa there!
  You have exceeded a secondary rate limit.
Please wait a few minutes before you try again;
in some cases this may take up to an hour.
  
  
https://support.github.com/contact";>Contact Support —
https://githubstatus.com";>GitHub Status —
https://twitter.com/githubstatus";>@githubstatus
  

  

  

  

  

  


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-05-13 Thread JJ Marr via cfe-commits

jj-marr wrote:

> @jj-marr Thanks. Do you want us to merge that for you?

Is it something I can actually do myself?

https://github.com/llvm/llvm-project/pull/130458
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Better diagnostics when assertion fails in `consteval` (PR #130458)

2025-05-13 Thread JJ Marr via cfe-commits

jj-marr wrote:

OK, merge whenever. 

https://github.com/llvm/llvm-project/pull/130458
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Add modernize-use-span linter check (PR #140001)

2025-05-20 Thread JJ Marr via cfe-commits

jj-marr wrote:

Thinking more, this is not a good check at this time.

https://github.com/llvm/llvm-project/pull/140001
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Add modernize-use-span linter check (PR #140001)

2025-05-20 Thread JJ Marr via cfe-commits

https://github.com/jj-marr closed 
https://github.com/llvm/llvm-project/pull/140001
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Add modernize-use-span linter check (PR #140001)

2025-05-19 Thread JJ Marr via cfe-commits

jj-marr wrote:

`std::span` has a capability gap with a const reference to a `std::vector` 
until C++26 as `std::span` cannot be constructed from an initializer list. 
Should this be a C++26 check? 

https://github.com/llvm/llvm-project/pull/140001
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][bytecode] Diagnose failed constexpr assertions differently (PR #140000)

2025-05-15 Thread JJ Marr via cfe-commits


@@ -851,6 +851,19 @@ bool CheckCallable(InterpState &S, CodePtr OpPC, const 
Function *F) {
   if (F->isLambdaStaticInvoker())
 return true;
 
+  // Diagnose failed assertions specially.
+  if (S.Current->getLocation(OpPC).isMacroID() &&
+  F->getDecl()->getIdentifier()) {
+StringRef Name = F->getDecl()->getName();
+bool AssertFailed =
+Name == "__assert_rtn" || Name == "__assert_fail" || Name == 
"_wassert";

jj-marr wrote:

I actually want to fix it at some point since I wrote the original code. My 
skillset is bad though which is why I couldn't figure it out. I'll make the 
GitHub issue and assign it to myself. 

https://github.com/llvm/llvm-project/pull/14
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][bytecode] Diagnose failed constexpr assertions differently (PR #140000)

2025-05-15 Thread JJ Marr via cfe-commits

https://github.com/jj-marr edited 
https://github.com/llvm/llvm-project/pull/14
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-03 Thread JJ Marr via cfe-commits

jj-marr wrote:

@vbvictor It makes sense to provide an autofix for `float`/`double`, since I 
have never heard of them being anything other than IEEE754 32-bit binary floats 
or IEEE754 64-bit binary floats respectively.

`char8_t` will always be `unsigned char` so a fix from `unsigned char` to 
`char8_t` could make sense as well.

Is an autofix from `char` or `signed char` to `char8_t` is a good idea?

https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-03 Thread JJ Marr via cfe-commits

https://github.com/jj-marr updated 
https://github.com/llvm/llvm-project/pull/146970

>From 3ef4feb748551806c863529306fefb2bd914e5be Mon Sep 17 00:00:00 2001
From: JJ Marr 
Date: Thu, 3 Jul 2025 17:17:06 -0400
Subject: [PATCH 1/6] AvoidFundamentalIntegerTypesCheck

---
 .../AvoidFundamentalIntegerTypesCheck.cpp | 183 ++
 .../AvoidFundamentalIntegerTypesCheck.h   |  46 +
 .../clang-tidy/modernize/CMakeLists.txt   |   1 +
 .../modernize/ModernizeTidyModule.cpp |   3 +
 .../avoid-fundamental-integer-types.cpp   | 108 +++
 5 files changed, 341 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.h
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-fundamental-integer-types.cpp

diff --git 
a/clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp
new file mode 100644
index 0..8a393bc894cfe
--- /dev/null
+++ 
b/clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp
@@ -0,0 +1,183 @@
+//===--- AvoidFundamentalIntegerTypesCheck.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 "AvoidFundamentalIntegerTypesCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+namespace {
+
+AST_MATCHER(clang::TypeLoc, hasValidBeginLoc) {
+  return Node.getBeginLoc().isValid();
+}
+
+AST_MATCHER_P(clang::TypeLoc, hasType,
+  clang::ast_matchers::internal::Matcher,
+  InnerMatcher) {
+  const clang::Type *TypeNode = Node.getTypePtr();
+  return TypeNode != nullptr &&
+ InnerMatcher.matches(*TypeNode, Finder, Builder);
+}
+
+} // namespace
+
+AvoidFundamentalIntegerTypesCheck::AvoidFundamentalIntegerTypesCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  IgnoreTypedefs(Options.get("IgnoreTypedefs", false)) {}
+
+void AvoidFundamentalIntegerTypesCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IgnoreTypedefs", IgnoreTypedefs);
+}
+
+bool AvoidFundamentalIntegerTypesCheck::isFundamentalIntegerType(
+const Type *T) const {
+  if (!T->isBuiltinType())
+return false;
+
+  const auto *BT = T->getAs();
+  if (!BT)
+return false;
+
+  switch (BT->getKind()) {
+  case BuiltinType::Int:
+  case BuiltinType::UInt:
+  case BuiltinType::Short:
+  case BuiltinType::UShort:
+  case BuiltinType::Long:
+  case BuiltinType::ULong:
+  case BuiltinType::LongLong:
+  case BuiltinType::ULongLong:
+return true;
+  default:
+return false;
+  }
+}
+
+bool AvoidFundamentalIntegerTypesCheck::isSemanticType(const Type *T) const {
+  if (!T->isBuiltinType())
+return false;
+
+  const auto *BT = T->getAs();
+  if (!BT)
+return false;
+
+  switch (BT->getKind()) {
+  case BuiltinType::Bool:
+  case BuiltinType::Char_S:
+  case BuiltinType::Char_U:
+  case BuiltinType::SChar:
+  case BuiltinType::UChar:
+  case BuiltinType::WChar_S:
+  case BuiltinType::WChar_U:
+  case BuiltinType::Char8:
+  case BuiltinType::Char16:
+  case BuiltinType::Char32:
+return true;
+  default:
+return false;
+  }
+}
+
+void AvoidFundamentalIntegerTypesCheck::registerMatchers(MatchFinder *Finder) {
+  // Match variable declarations with fundamental integer types
+  Finder->addMatcher(
+  varDecl().bind("var_decl"),
+  this);
+
+  // Match function declarations with fundamental integer return types
+  Finder->addMatcher(
+  functionDecl().bind("func_decl"),
+  this);
+
+  // Match function parameters with fundamental integer types
+  Finder->addMatcher(
+  parmVarDecl().bind("param_decl"),
+  this);
+
+  // Match field declarations with fundamental integer types
+  Finder->addMatcher(
+  fieldDecl().bind("field_decl"),
+  this);
+
+  // Match typedef declarations if not ignoring them
+  if (!IgnoreTypedefs) {
+Finder->addMatcher(
+typedefDecl().bind("typedef_decl"),
+this);
+
+Finder->addMatcher(
+typeAliasDecl().bind("alias_decl"),
+this);
+  }
+}
+
+void AvoidFundamentalIntegerTypesCheck::check(
+const MatchFinder::MatchResult &Result) {
+  SourceLocation Loc;
+  QualType QT;
+  std::string DeclType;
+
+  if (const auto *VD = Result.Nodes.getNodeAs("var_decl")) {
+Loc = VD->getLocation();
+QT = VD->getType();
+DeclType = "variable";
+  

[clang-tools-extra] [clang-tidy] Add portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-03 Thread JJ Marr via cfe-commits

https://github.com/jj-marr edited 
https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-03 Thread JJ Marr via cfe-commits

https://github.com/jj-marr updated 
https://github.com/llvm/llvm-project/pull/146970

>From 3ef4feb748551806c863529306fefb2bd914e5be Mon Sep 17 00:00:00 2001
From: JJ Marr 
Date: Thu, 3 Jul 2025 17:17:06 -0400
Subject: [PATCH 1/8] AvoidFundamentalIntegerTypesCheck

---
 .../AvoidFundamentalIntegerTypesCheck.cpp | 183 ++
 .../AvoidFundamentalIntegerTypesCheck.h   |  46 +
 .../clang-tidy/modernize/CMakeLists.txt   |   1 +
 .../modernize/ModernizeTidyModule.cpp |   3 +
 .../avoid-fundamental-integer-types.cpp   | 108 +++
 5 files changed, 341 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.h
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-fundamental-integer-types.cpp

diff --git 
a/clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp
new file mode 100644
index 0..8a393bc894cfe
--- /dev/null
+++ 
b/clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp
@@ -0,0 +1,183 @@
+//===--- AvoidFundamentalIntegerTypesCheck.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 "AvoidFundamentalIntegerTypesCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+namespace {
+
+AST_MATCHER(clang::TypeLoc, hasValidBeginLoc) {
+  return Node.getBeginLoc().isValid();
+}
+
+AST_MATCHER_P(clang::TypeLoc, hasType,
+  clang::ast_matchers::internal::Matcher,
+  InnerMatcher) {
+  const clang::Type *TypeNode = Node.getTypePtr();
+  return TypeNode != nullptr &&
+ InnerMatcher.matches(*TypeNode, Finder, Builder);
+}
+
+} // namespace
+
+AvoidFundamentalIntegerTypesCheck::AvoidFundamentalIntegerTypesCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  IgnoreTypedefs(Options.get("IgnoreTypedefs", false)) {}
+
+void AvoidFundamentalIntegerTypesCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IgnoreTypedefs", IgnoreTypedefs);
+}
+
+bool AvoidFundamentalIntegerTypesCheck::isFundamentalIntegerType(
+const Type *T) const {
+  if (!T->isBuiltinType())
+return false;
+
+  const auto *BT = T->getAs();
+  if (!BT)
+return false;
+
+  switch (BT->getKind()) {
+  case BuiltinType::Int:
+  case BuiltinType::UInt:
+  case BuiltinType::Short:
+  case BuiltinType::UShort:
+  case BuiltinType::Long:
+  case BuiltinType::ULong:
+  case BuiltinType::LongLong:
+  case BuiltinType::ULongLong:
+return true;
+  default:
+return false;
+  }
+}
+
+bool AvoidFundamentalIntegerTypesCheck::isSemanticType(const Type *T) const {
+  if (!T->isBuiltinType())
+return false;
+
+  const auto *BT = T->getAs();
+  if (!BT)
+return false;
+
+  switch (BT->getKind()) {
+  case BuiltinType::Bool:
+  case BuiltinType::Char_S:
+  case BuiltinType::Char_U:
+  case BuiltinType::SChar:
+  case BuiltinType::UChar:
+  case BuiltinType::WChar_S:
+  case BuiltinType::WChar_U:
+  case BuiltinType::Char8:
+  case BuiltinType::Char16:
+  case BuiltinType::Char32:
+return true;
+  default:
+return false;
+  }
+}
+
+void AvoidFundamentalIntegerTypesCheck::registerMatchers(MatchFinder *Finder) {
+  // Match variable declarations with fundamental integer types
+  Finder->addMatcher(
+  varDecl().bind("var_decl"),
+  this);
+
+  // Match function declarations with fundamental integer return types
+  Finder->addMatcher(
+  functionDecl().bind("func_decl"),
+  this);
+
+  // Match function parameters with fundamental integer types
+  Finder->addMatcher(
+  parmVarDecl().bind("param_decl"),
+  this);
+
+  // Match field declarations with fundamental integer types
+  Finder->addMatcher(
+  fieldDecl().bind("field_decl"),
+  this);
+
+  // Match typedef declarations if not ignoring them
+  if (!IgnoreTypedefs) {
+Finder->addMatcher(
+typedefDecl().bind("typedef_decl"),
+this);
+
+Finder->addMatcher(
+typeAliasDecl().bind("alias_decl"),
+this);
+  }
+}
+
+void AvoidFundamentalIntegerTypesCheck::check(
+const MatchFinder::MatchResult &Result) {
+  SourceLocation Loc;
+  QualType QT;
+  std::string DeclType;
+
+  if (const auto *VD = Result.Nodes.getNodeAs("var_decl")) {
+Loc = VD->getLocation();
+QT = VD->getType();
+DeclType = "variable";
+  

[clang-tools-extra] [clang-tidy] Add portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-03 Thread JJ Marr via cfe-commits


@@ -0,0 +1,181 @@
+//===--- AvoidFundamentalIntegerTypesCheck.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 "AvoidFundamentalIntegerTypesCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+namespace {
+
+AST_MATCHER(clang::TypeLoc, hasValidBeginLoc) {
+  return Node.getBeginLoc().isValid();
+}
+
+AST_MATCHER_P(clang::TypeLoc, hasType,
+  clang::ast_matchers::internal::Matcher,
+  InnerMatcher) {
+  const clang::Type *TypeNode = Node.getTypePtr();
+  return TypeNode != nullptr &&
+ InnerMatcher.matches(*TypeNode, Finder, Builder);
+}
+
+} // namespace
+
+AvoidFundamentalIntegerTypesCheck::AvoidFundamentalIntegerTypesCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context) {}
+
+bool AvoidFundamentalIntegerTypesCheck::isFundamentalIntegerType(
+const Type *T) const {
+  if (!T->isBuiltinType())
+return false;
+
+  const auto *BT = T->getAs();
+  if (!BT)
+return false;
+
+  switch (BT->getKind()) {
+  case BuiltinType::Int:
+  case BuiltinType::UInt:
+  case BuiltinType::Short:
+  case BuiltinType::UShort:
+  case BuiltinType::Long:
+  case BuiltinType::ULong:
+  case BuiltinType::LongLong:
+  case BuiltinType::ULongLong:
+return true;
+  default:
+return false;
+  }
+}
+
+bool AvoidFundamentalIntegerTypesCheck::isSemanticType(const Type *T) const {
+  if (!T->isBuiltinType())
+return false;
+
+  const auto *BT = T->getAs();
+  if (!BT)
+return false;
+
+  switch (BT->getKind()) {
+  case BuiltinType::Bool:
+  case BuiltinType::Char_S:
+  case BuiltinType::Char_U:
+  case BuiltinType::SChar:
+  case BuiltinType::UChar:
+  case BuiltinType::WChar_S:
+  case BuiltinType::WChar_U:
+  case BuiltinType::Char8:
+  case BuiltinType::Char16:
+  case BuiltinType::Char32:
+return true;
+  default:
+return false;
+  }
+}
+
+void AvoidFundamentalIntegerTypesCheck::registerMatchers(MatchFinder *Finder) {
+  // Match variable declarations with fundamental integer types
+  Finder->addMatcher(
+  varDecl().bind("var_decl"),
+  this);

jj-marr wrote:

Done.

https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-03 Thread JJ Marr via cfe-commits

https://github.com/jj-marr updated 
https://github.com/llvm/llvm-project/pull/146970

>From 3ef4feb748551806c863529306fefb2bd914e5be Mon Sep 17 00:00:00 2001
From: JJ Marr 
Date: Thu, 3 Jul 2025 17:17:06 -0400
Subject: [PATCH 1/9] AvoidFundamentalIntegerTypesCheck

---
 .../AvoidFundamentalIntegerTypesCheck.cpp | 183 ++
 .../AvoidFundamentalIntegerTypesCheck.h   |  46 +
 .../clang-tidy/modernize/CMakeLists.txt   |   1 +
 .../modernize/ModernizeTidyModule.cpp |   3 +
 .../avoid-fundamental-integer-types.cpp   | 108 +++
 5 files changed, 341 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.h
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-fundamental-integer-types.cpp

diff --git 
a/clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp
new file mode 100644
index 0..8a393bc894cfe
--- /dev/null
+++ 
b/clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp
@@ -0,0 +1,183 @@
+//===--- AvoidFundamentalIntegerTypesCheck.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 "AvoidFundamentalIntegerTypesCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+namespace {
+
+AST_MATCHER(clang::TypeLoc, hasValidBeginLoc) {
+  return Node.getBeginLoc().isValid();
+}
+
+AST_MATCHER_P(clang::TypeLoc, hasType,
+  clang::ast_matchers::internal::Matcher,
+  InnerMatcher) {
+  const clang::Type *TypeNode = Node.getTypePtr();
+  return TypeNode != nullptr &&
+ InnerMatcher.matches(*TypeNode, Finder, Builder);
+}
+
+} // namespace
+
+AvoidFundamentalIntegerTypesCheck::AvoidFundamentalIntegerTypesCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  IgnoreTypedefs(Options.get("IgnoreTypedefs", false)) {}
+
+void AvoidFundamentalIntegerTypesCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IgnoreTypedefs", IgnoreTypedefs);
+}
+
+bool AvoidFundamentalIntegerTypesCheck::isFundamentalIntegerType(
+const Type *T) const {
+  if (!T->isBuiltinType())
+return false;
+
+  const auto *BT = T->getAs();
+  if (!BT)
+return false;
+
+  switch (BT->getKind()) {
+  case BuiltinType::Int:
+  case BuiltinType::UInt:
+  case BuiltinType::Short:
+  case BuiltinType::UShort:
+  case BuiltinType::Long:
+  case BuiltinType::ULong:
+  case BuiltinType::LongLong:
+  case BuiltinType::ULongLong:
+return true;
+  default:
+return false;
+  }
+}
+
+bool AvoidFundamentalIntegerTypesCheck::isSemanticType(const Type *T) const {
+  if (!T->isBuiltinType())
+return false;
+
+  const auto *BT = T->getAs();
+  if (!BT)
+return false;
+
+  switch (BT->getKind()) {
+  case BuiltinType::Bool:
+  case BuiltinType::Char_S:
+  case BuiltinType::Char_U:
+  case BuiltinType::SChar:
+  case BuiltinType::UChar:
+  case BuiltinType::WChar_S:
+  case BuiltinType::WChar_U:
+  case BuiltinType::Char8:
+  case BuiltinType::Char16:
+  case BuiltinType::Char32:
+return true;
+  default:
+return false;
+  }
+}
+
+void AvoidFundamentalIntegerTypesCheck::registerMatchers(MatchFinder *Finder) {
+  // Match variable declarations with fundamental integer types
+  Finder->addMatcher(
+  varDecl().bind("var_decl"),
+  this);
+
+  // Match function declarations with fundamental integer return types
+  Finder->addMatcher(
+  functionDecl().bind("func_decl"),
+  this);
+
+  // Match function parameters with fundamental integer types
+  Finder->addMatcher(
+  parmVarDecl().bind("param_decl"),
+  this);
+
+  // Match field declarations with fundamental integer types
+  Finder->addMatcher(
+  fieldDecl().bind("field_decl"),
+  this);
+
+  // Match typedef declarations if not ignoring them
+  if (!IgnoreTypedefs) {
+Finder->addMatcher(
+typedefDecl().bind("typedef_decl"),
+this);
+
+Finder->addMatcher(
+typeAliasDecl().bind("alias_decl"),
+this);
+  }
+}
+
+void AvoidFundamentalIntegerTypesCheck::check(
+const MatchFinder::MatchResult &Result) {
+  SourceLocation Loc;
+  QualType QT;
+  std::string DeclType;
+
+  if (const auto *VD = Result.Nodes.getNodeAs("var_decl")) {
+Loc = VD->getLocation();
+QT = VD->getType();
+DeclType = "variable";
+  

[clang-tools-extra] [clang-tidy] Add portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-03 Thread JJ Marr via cfe-commits

jj-marr wrote:

I will add the `float` component of the check tomorrow.

https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-05 Thread JJ Marr via cfe-commits

https://github.com/jj-marr updated 
https://github.com/llvm/llvm-project/pull/146970

>From 3ef4feb748551806c863529306fefb2bd914e5be Mon Sep 17 00:00:00 2001
From: JJ Marr 
Date: Thu, 3 Jul 2025 17:17:06 -0400
Subject: [PATCH 01/10] AvoidFundamentalIntegerTypesCheck

---
 .../AvoidFundamentalIntegerTypesCheck.cpp | 183 ++
 .../AvoidFundamentalIntegerTypesCheck.h   |  46 +
 .../clang-tidy/modernize/CMakeLists.txt   |   1 +
 .../modernize/ModernizeTidyModule.cpp |   3 +
 .../avoid-fundamental-integer-types.cpp   | 108 +++
 5 files changed, 341 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.h
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-fundamental-integer-types.cpp

diff --git 
a/clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp
new file mode 100644
index 0..8a393bc894cfe
--- /dev/null
+++ 
b/clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp
@@ -0,0 +1,183 @@
+//===--- AvoidFundamentalIntegerTypesCheck.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 "AvoidFundamentalIntegerTypesCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+namespace {
+
+AST_MATCHER(clang::TypeLoc, hasValidBeginLoc) {
+  return Node.getBeginLoc().isValid();
+}
+
+AST_MATCHER_P(clang::TypeLoc, hasType,
+  clang::ast_matchers::internal::Matcher,
+  InnerMatcher) {
+  const clang::Type *TypeNode = Node.getTypePtr();
+  return TypeNode != nullptr &&
+ InnerMatcher.matches(*TypeNode, Finder, Builder);
+}
+
+} // namespace
+
+AvoidFundamentalIntegerTypesCheck::AvoidFundamentalIntegerTypesCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  IgnoreTypedefs(Options.get("IgnoreTypedefs", false)) {}
+
+void AvoidFundamentalIntegerTypesCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IgnoreTypedefs", IgnoreTypedefs);
+}
+
+bool AvoidFundamentalIntegerTypesCheck::isFundamentalIntegerType(
+const Type *T) const {
+  if (!T->isBuiltinType())
+return false;
+
+  const auto *BT = T->getAs();
+  if (!BT)
+return false;
+
+  switch (BT->getKind()) {
+  case BuiltinType::Int:
+  case BuiltinType::UInt:
+  case BuiltinType::Short:
+  case BuiltinType::UShort:
+  case BuiltinType::Long:
+  case BuiltinType::ULong:
+  case BuiltinType::LongLong:
+  case BuiltinType::ULongLong:
+return true;
+  default:
+return false;
+  }
+}
+
+bool AvoidFundamentalIntegerTypesCheck::isSemanticType(const Type *T) const {
+  if (!T->isBuiltinType())
+return false;
+
+  const auto *BT = T->getAs();
+  if (!BT)
+return false;
+
+  switch (BT->getKind()) {
+  case BuiltinType::Bool:
+  case BuiltinType::Char_S:
+  case BuiltinType::Char_U:
+  case BuiltinType::SChar:
+  case BuiltinType::UChar:
+  case BuiltinType::WChar_S:
+  case BuiltinType::WChar_U:
+  case BuiltinType::Char8:
+  case BuiltinType::Char16:
+  case BuiltinType::Char32:
+return true;
+  default:
+return false;
+  }
+}
+
+void AvoidFundamentalIntegerTypesCheck::registerMatchers(MatchFinder *Finder) {
+  // Match variable declarations with fundamental integer types
+  Finder->addMatcher(
+  varDecl().bind("var_decl"),
+  this);
+
+  // Match function declarations with fundamental integer return types
+  Finder->addMatcher(
+  functionDecl().bind("func_decl"),
+  this);
+
+  // Match function parameters with fundamental integer types
+  Finder->addMatcher(
+  parmVarDecl().bind("param_decl"),
+  this);
+
+  // Match field declarations with fundamental integer types
+  Finder->addMatcher(
+  fieldDecl().bind("field_decl"),
+  this);
+
+  // Match typedef declarations if not ignoring them
+  if (!IgnoreTypedefs) {
+Finder->addMatcher(
+typedefDecl().bind("typedef_decl"),
+this);
+
+Finder->addMatcher(
+typeAliasDecl().bind("alias_decl"),
+this);
+  }
+}
+
+void AvoidFundamentalIntegerTypesCheck::check(
+const MatchFinder::MatchResult &Result) {
+  SourceLocation Loc;
+  QualType QT;
+  std::string DeclType;
+
+  if (const auto *VD = Result.Nodes.getNodeAs("var_decl")) {
+Loc = VD->getLocation();
+QT = VD->getType();
+DeclType = "variable";
+

[clang-tools-extra] [clang-tidy] Add portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-05 Thread JJ Marr via cfe-commits

https://github.com/jj-marr updated 
https://github.com/llvm/llvm-project/pull/146970

>From 3ef4feb748551806c863529306fefb2bd914e5be Mon Sep 17 00:00:00 2001
From: JJ Marr 
Date: Thu, 3 Jul 2025 17:17:06 -0400
Subject: [PATCH 01/14] AvoidFundamentalIntegerTypesCheck

---
 .../AvoidFundamentalIntegerTypesCheck.cpp | 183 ++
 .../AvoidFundamentalIntegerTypesCheck.h   |  46 +
 .../clang-tidy/modernize/CMakeLists.txt   |   1 +
 .../modernize/ModernizeTidyModule.cpp |   3 +
 .../avoid-fundamental-integer-types.cpp   | 108 +++
 5 files changed, 341 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.h
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-fundamental-integer-types.cpp

diff --git 
a/clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp
new file mode 100644
index 0..8a393bc894cfe
--- /dev/null
+++ 
b/clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp
@@ -0,0 +1,183 @@
+//===--- AvoidFundamentalIntegerTypesCheck.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 "AvoidFundamentalIntegerTypesCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+namespace {
+
+AST_MATCHER(clang::TypeLoc, hasValidBeginLoc) {
+  return Node.getBeginLoc().isValid();
+}
+
+AST_MATCHER_P(clang::TypeLoc, hasType,
+  clang::ast_matchers::internal::Matcher,
+  InnerMatcher) {
+  const clang::Type *TypeNode = Node.getTypePtr();
+  return TypeNode != nullptr &&
+ InnerMatcher.matches(*TypeNode, Finder, Builder);
+}
+
+} // namespace
+
+AvoidFundamentalIntegerTypesCheck::AvoidFundamentalIntegerTypesCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  IgnoreTypedefs(Options.get("IgnoreTypedefs", false)) {}
+
+void AvoidFundamentalIntegerTypesCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IgnoreTypedefs", IgnoreTypedefs);
+}
+
+bool AvoidFundamentalIntegerTypesCheck::isFundamentalIntegerType(
+const Type *T) const {
+  if (!T->isBuiltinType())
+return false;
+
+  const auto *BT = T->getAs();
+  if (!BT)
+return false;
+
+  switch (BT->getKind()) {
+  case BuiltinType::Int:
+  case BuiltinType::UInt:
+  case BuiltinType::Short:
+  case BuiltinType::UShort:
+  case BuiltinType::Long:
+  case BuiltinType::ULong:
+  case BuiltinType::LongLong:
+  case BuiltinType::ULongLong:
+return true;
+  default:
+return false;
+  }
+}
+
+bool AvoidFundamentalIntegerTypesCheck::isSemanticType(const Type *T) const {
+  if (!T->isBuiltinType())
+return false;
+
+  const auto *BT = T->getAs();
+  if (!BT)
+return false;
+
+  switch (BT->getKind()) {
+  case BuiltinType::Bool:
+  case BuiltinType::Char_S:
+  case BuiltinType::Char_U:
+  case BuiltinType::SChar:
+  case BuiltinType::UChar:
+  case BuiltinType::WChar_S:
+  case BuiltinType::WChar_U:
+  case BuiltinType::Char8:
+  case BuiltinType::Char16:
+  case BuiltinType::Char32:
+return true;
+  default:
+return false;
+  }
+}
+
+void AvoidFundamentalIntegerTypesCheck::registerMatchers(MatchFinder *Finder) {
+  // Match variable declarations with fundamental integer types
+  Finder->addMatcher(
+  varDecl().bind("var_decl"),
+  this);
+
+  // Match function declarations with fundamental integer return types
+  Finder->addMatcher(
+  functionDecl().bind("func_decl"),
+  this);
+
+  // Match function parameters with fundamental integer types
+  Finder->addMatcher(
+  parmVarDecl().bind("param_decl"),
+  this);
+
+  // Match field declarations with fundamental integer types
+  Finder->addMatcher(
+  fieldDecl().bind("field_decl"),
+  this);
+
+  // Match typedef declarations if not ignoring them
+  if (!IgnoreTypedefs) {
+Finder->addMatcher(
+typedefDecl().bind("typedef_decl"),
+this);
+
+Finder->addMatcher(
+typeAliasDecl().bind("alias_decl"),
+this);
+  }
+}
+
+void AvoidFundamentalIntegerTypesCheck::check(
+const MatchFinder::MatchResult &Result) {
+  SourceLocation Loc;
+  QualType QT;
+  std::string DeclType;
+
+  if (const auto *VD = Result.Nodes.getNodeAs("var_decl")) {
+Loc = VD->getLocation();
+QT = VD->getType();
+DeclType = "variable";
+

[clang-tools-extra] [clang-tidy] Add portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-05 Thread JJ Marr via cfe-commits


@@ -0,0 +1,43 @@
+//===--- AvoidPlatformSpecificFundamentalTypesCheck.h - clang-tidy ---*- 
C++
+//-*-===//

jj-marr wrote:

Done.

https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-05 Thread JJ Marr via cfe-commits


@@ -0,0 +1,111 @@
+.. title:: clang-tidy - portability-avoid-platform-specific-fundamental-types
+
+portability-avoid-platform-specific-fundamental-types
+=
+
+Finds fundamental types and recommends using typedefs or fixed-width types 
instead.
+
+This check detects fundamental integer types (``int``, ``short``, ``long``, 
``long long``, and their
+``unsigned`` variants) and warns against their use due to non-standard 
platform-dependent behavior.
+For example, ``long`` is 64 bits on Linux but 32 bits on Windows. There is no 
standard rationale or
+intent for the sizes of these types.
+
+Instead of fundamental types, use fixed-width types such as ``int32_t`` or 
implementation-defined
+types with standard semantics, e.g. ``int_fast32_t`` for the fastest integer 
type greater than or

jj-marr wrote:

Done locally.

https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-05 Thread JJ Marr via cfe-commits

https://github.com/jj-marr edited 
https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-05 Thread JJ Marr via cfe-commits

https://github.com/jj-marr edited 
https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-05 Thread JJ Marr via cfe-commits

https://github.com/jj-marr edited 
https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-04 Thread JJ Marr via cfe-commits

jj-marr wrote:

> Have you looked at google-runtime-int? It should be doing the same thing 
> (maybe small differences)

I haven't before now. I still think a new check is necessary. 

`google-runtime-int` isn't as strict because it is coupled to the Google coding 
guidelines. That means it doesn't flag `int`, `float`, `double`, etc. That 
behaviour shouldn't change as Google's coding guidelines explicitly recommend 
using `int` for loop counters as well as `float`, `double` for IEEE754 floats. 

This check will encompass usage of almost all fundamental types that are 
implementation-defined, including `float`, `double`, `int`, and (potentially) 
`char`. The main exception is `bool` because it doesn't suffer from the same 
overflow issues as other types. This is a significant change and goes against 
Google's coding guidelines. 

https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-05 Thread JJ Marr via cfe-commits


@@ -0,0 +1,43 @@
+//===--- AvoidPlatformSpecificFundamentalTypesCheck.h - clang-tidy ---*- 
C++
+//-*-===//

jj-marr wrote:

This requires turning off `clang-format` since line 1 is too long.

https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-05 Thread JJ Marr via cfe-commits

https://github.com/jj-marr edited 
https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-05 Thread JJ Marr via cfe-commits

jj-marr wrote:

 > You could make a universal option to configure autofixes. Make 
 > semicolon-separated list of key-value pairs, e.g. 
 > `int=int32_t;float=float32_t;char=char8_t`. User could specify any type he 
 > wants, and remove/add fixes for `int`, `char` and so on.
> 
> By default, we could even put fixes for all common types and let the user 
> delete/modify what doesn't like.

This is a good idea but even the basic configuration I wanted to do adds a lot 
of scope to the PR.

Autofix for `float` is implemented because it's easy to figure out w/o much 
ambiguity. Float/double/etc means "I want IEEE754" most of the time, with the 
only exception being `bfloat16`.

https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-05 Thread JJ Marr via cfe-commits


@@ -0,0 +1,246 @@
+//===--- AvoidPlatformSpecificFundamentalTypesCheck.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 "AvoidPlatformSpecificFundamentalTypesCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/TargetInfo.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::portability {
+
+AvoidPlatformSpecificFundamentalTypesCheck::
+AvoidPlatformSpecificFundamentalTypesCheck(StringRef Name,
+   ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  WarnOnFloats(Options.get("WarnOnFloats", false)),
+  IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",
+   utils::IncludeSorter::IS_LLVM),
+  areDiagsSelfContained()) {}
+
+void AvoidPlatformSpecificFundamentalTypesCheck::registerPPCallbacks(
+const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) 
{
+  IncludeInserter.registerPreprocessor(PP);
+}
+
+void AvoidPlatformSpecificFundamentalTypesCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "WarnOnFloats", WarnOnFloats);
+  Options.store(Opts, "IncludeStyle", IncludeInserter.getStyle());
+}
+
+std::string AvoidPlatformSpecificFundamentalTypesCheck::getFloatReplacement(
+const BuiltinType *BT, ASTContext &Context) const {
+  const TargetInfo &Target = Context.getTargetInfo();
+
+  auto GetReplacementType = [](unsigned Width) {
+switch (Width) {
+// This is ambiguous by default since it could be bfloat16 or float16
+case 16U:
+  return "";
+case 32U:
+  return "float32_t";
+case 64U:
+  return "float64_t";
+case 128U:
+  return "float128_t";
+default:
+  return "";
+}
+  };
+
+  switch (BT->getKind()) {
+  // Not an ambiguous type
+  case BuiltinType::BFloat16:
+return "bfloat16_t";
+  case BuiltinType::Half:
+return GetReplacementType(Target.getHalfWidth());
+  case BuiltinType::Float:
+return GetReplacementType(Target.getFloatWidth());
+  case BuiltinType::Double:
+return GetReplacementType(Target.getDoubleWidth());
+  default:
+return "";
+  }
+}
+
+void AvoidPlatformSpecificFundamentalTypesCheck::registerMatchers(
+MatchFinder *Finder) {
+  // Build the list of type strings to match
+  std::vector TypeStrings = {"short",
+  "short int",
+  "signed short",
+  "signed short int",
+  "unsigned short",
+  "unsigned short int",
+  "int",
+  "signed",
+  "signed int",
+  "unsigned",
+  "unsigned int",
+  "long",
+  "long int",
+  "signed long",
+  "signed long int",
+  "unsigned long",
+  "unsigned long int",
+  "long long",
+  "long long int",
+  "signed long long",
+  "signed long long int",
+  "unsigned long long",
+  "unsigned long long int"};
+
+  // Add float types if the option is enabled
+  if (WarnOnFloats) {
+TypeStrings.push_back("half");
+TypeStrings.push_back("__bf16");
+TypeStrings.push_back("float");
+TypeStrings.push_back("double");
+TypeStrings.push_back("long double");
+  }
+
+  // Create the matcher dynamically
+  auto TypeMatcher = asString(TypeStrings[0]);
+  for (size_t i = 1; i < TypeStrings.size(); ++i) {
+TypeMatcher = anyOf(TypeMatcher, asString(TypeStrings[i]));
+  }
+
+  auto PlatformSpecificFundamentalType = qualType(allOf(
+  // Must be a builtin type directly (not through typedef)
+  builtinType(),
+  // Match the specific fundamental types we care about
+  TypeMatcher));
+
+  // Match variable declarations with platform-specific fundamental types
+  Finder->addMatcher(
+  varDecl(hasType(PlatformSpecificFundamentalType)).bind("var_decl"), 
this);
+
+  // Match function declarations 

[clang-tools-extra] [clang-tidy] Add portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-05 Thread JJ Marr via cfe-commits

https://github.com/jj-marr commented:

comments for myself

https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-05 Thread JJ Marr via cfe-commits

https://github.com/jj-marr edited 
https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-05 Thread JJ Marr via cfe-commits


@@ -0,0 +1,246 @@
+//===--- AvoidPlatformSpecificFundamentalTypesCheck.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 "AvoidPlatformSpecificFundamentalTypesCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/TargetInfo.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::portability {
+
+AvoidPlatformSpecificFundamentalTypesCheck::
+AvoidPlatformSpecificFundamentalTypesCheck(StringRef Name,
+   ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  WarnOnFloats(Options.get("WarnOnFloats", false)),
+  IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",
+   utils::IncludeSorter::IS_LLVM),
+  areDiagsSelfContained()) {}
+
+void AvoidPlatformSpecificFundamentalTypesCheck::registerPPCallbacks(
+const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) 
{
+  IncludeInserter.registerPreprocessor(PP);
+}
+
+void AvoidPlatformSpecificFundamentalTypesCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "WarnOnFloats", WarnOnFloats);
+  Options.store(Opts, "IncludeStyle", IncludeInserter.getStyle());
+}
+
+std::string AvoidPlatformSpecificFundamentalTypesCheck::getFloatReplacement(
+const BuiltinType *BT, ASTContext &Context) const {
+  const TargetInfo &Target = Context.getTargetInfo();
+
+  auto GetReplacementType = [](unsigned Width) {
+switch (Width) {
+// This is ambiguous by default since it could be bfloat16 or float16
+case 16U:
+  return "";
+case 32U:
+  return "float32_t";
+case 64U:
+  return "float64_t";
+case 128U:
+  return "float128_t";
+default:
+  return "";
+}
+  };
+
+  switch (BT->getKind()) {
+  // Not an ambiguous type
+  case BuiltinType::BFloat16:
+return "bfloat16_t";
+  case BuiltinType::Half:
+return GetReplacementType(Target.getHalfWidth());
+  case BuiltinType::Float:
+return GetReplacementType(Target.getFloatWidth());
+  case BuiltinType::Double:
+return GetReplacementType(Target.getDoubleWidth());
+  default:
+return "";
+  }
+}
+
+void AvoidPlatformSpecificFundamentalTypesCheck::registerMatchers(
+MatchFinder *Finder) {
+  // Build the list of type strings to match
+  std::vector TypeStrings = {"short",

jj-marr wrote:

warn on int should also be a config option.

https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-06 Thread JJ Marr via cfe-commits


@@ -0,0 +1,260 @@
+//===--- AvoidPlatformSpecificFundamentalTypesCheck.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 "AvoidPlatformSpecificFundamentalTypesCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/TargetInfo.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::portability {
+
+AvoidPlatformSpecificFundamentalTypesCheck::
+AvoidPlatformSpecificFundamentalTypesCheck(StringRef Name,
+   ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  WarnOnFloats(Options.get("WarnOnFloats", true)),
+  WarnOnInts(Options.get("WarnOnInts", true)),
+  WarnOnChars(Options.get("WarnOnChars", true)),
+  IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",
+   utils::IncludeSorter::IS_LLVM),
+  areDiagsSelfContained()) {}
+
+void AvoidPlatformSpecificFundamentalTypesCheck::registerPPCallbacks(
+const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) 
{
+  IncludeInserter.registerPreprocessor(PP);
+}
+
+void AvoidPlatformSpecificFundamentalTypesCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "WarnOnFloats", WarnOnFloats);
+  Options.store(Opts, "WarnOnInts", WarnOnInts);
+  Options.store(Opts, "WarnOnChars", WarnOnChars);
+  Options.store(Opts, "IncludeStyle", IncludeInserter.getStyle());
+}
+
+std::string AvoidPlatformSpecificFundamentalTypesCheck::getFloatReplacement(
+const BuiltinType *BT, ASTContext &Context) const {
+  const TargetInfo &Target = Context.getTargetInfo();
+
+  auto GetReplacementType = [](unsigned Width) {
+switch (Width) {
+// This is ambiguous by default since it could be bfloat16 or float16
+case 16U:
+  return "";
+case 32U:
+  return "float32_t";
+case 64U:
+  return "float64_t";
+case 128U:
+  return "float128_t";
+default:
+  return "";
+}
+  };
+
+  switch (BT->getKind()) {
+  // Not an ambiguous type
+  case BuiltinType::BFloat16:
+return "bfloat16_t";
+  case BuiltinType::Half:
+return GetReplacementType(Target.getHalfWidth());
+  case BuiltinType::Float:
+return GetReplacementType(Target.getFloatWidth());
+  case BuiltinType::Double:
+return GetReplacementType(Target.getDoubleWidth());
+  default:
+return "";
+  }
+}
+
+void AvoidPlatformSpecificFundamentalTypesCheck::registerMatchers(
+MatchFinder *Finder) {
+  // Build the list of type strings to match
+  std::vector TypeStrings;
+
+  // Add integer types if the option is enabled
+  if (WarnOnInts) {
+TypeStrings.insert(TypeStrings.end(), {"short",

jj-marr wrote:

This makes more sense. I was thinking I couldn't check the type itself because 
`typedef`s don't create a new type, but if it works for the Google check I 
suppose it'll work for this one.

https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-06 Thread JJ Marr via cfe-commits

jj-marr wrote:

> Please remove unnecessary comments that tell the same as code itself, 
> speaking mostly about comments in `registerMatchers`. They mostly don't give 
> any more information that matchers themselves.

To be honest, this is because I coded 98% of this with AI (except for the 
`.rst` documentation text which I mostly wrote myself). I am still getting used 
to stripping out useless comments and also how `llvm`/compilers in general work.

https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-06 Thread JJ Marr via cfe-commits


@@ -0,0 +1,52 @@
+//==-- AvoidPlatformSpecificFundamentalTypesCheck.h - clang-tidy -*- 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 
LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PORTABILITY_AVOIDPLATFORMSPECIFICFUNDAMENTALTYPESCHECK_H
+#define 
LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PORTABILITY_AVOIDPLATFORMSPECIFICFUNDAMENTALTYPESCHECK_H
+
+#include "../ClangTidyCheck.h"
+#include "../utils/IncludeInserter.h"
+
+namespace clang::tidy::portability {
+
+/// Find fundamental platform-dependent types and recommend using typedefs or
+/// fixed-width types.
+///
+/// Detects fundamental types (int, short, long, long long, char, float, etc)
+/// and warns against their use due to platform-dependent behavior.
+///
+/// For the user-facing documentation see:
+/// 
http://clang.llvm.org/extra/clang-tidy/checks/portability/avoid-platform-specific-fundamental-types.html
+class AvoidPlatformSpecificFundamentalTypesCheck : public ClangTidyCheck {
+public:
+  AvoidPlatformSpecificFundamentalTypesCheck(StringRef Name,
+ ClangTidyContext *Context);
+  void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+   Preprocessor *ModuleExpanderPP) override;
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+  bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+return LangOpts.CPlusPlus11;
+  }
+  std::optional getCheckTraversalKind() const override {
+return TK_IgnoreUnlessSpelledInSource;
+  }
+
+private:
+  const bool WarnOnFloats;
+  const bool WarnOnInts;
+  const bool WarnOnChars;
+  utils::IncludeInserter IncludeInserter;
+  std::string getFloatReplacement(const BuiltinType *BT,
+  ASTContext &Context) const;

jj-marr wrote:

I'm used to having linters flag this (along with missed `const` declarations).

https://github.com/llvm/llvm-project/pull/146970
___
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 modernize-avoid-fundamental-integer-types (PR #146970)

2025-07-03 Thread JJ Marr via cfe-commits

https://github.com/jj-marr created 
https://github.com/llvm/llvm-project/pull/146970

The fundamental types are widely recognized to be flawed because they're of 
implementation-defined sizes without a common purpose.

For example, `long int` is a footgun since its 32 bits on Windows and 64 bits 
on most 64-bit Unixes. On Windows, backwards compatibility has it frozen at 32 
bits while on Unix, it is implementation-defined to be the processor's word 
size.

To address this, C/C++ introduced the `stdint.h`/`cstdint` headers that provide 
standard types of a specific number of bits. The language also introduced 
implementation-defined types such as `size_t` or `int_fast32_t`, which unlike 
`int`, have a clear specification of intent in the standard and can change size 
based on standardized aspects of the implementation (maximum size of objects, 
"fastest" type). 

TODO:

- [ ] Decide whether to provide an autofix. I have chosen not to, because it 
will depend on the context one is using a type in.
- [ ] Decide whether `char` should be linted. I have chosen not to lint `char` 
by default because it can be used to convey "1 byte" regardless of the size of 
the byte. However, I might add this as an option defaulted to "Yes", because on 
virtually every platform people actually use C++20/C23 on, `char` can be safely 
replaced with `char8_t` as 1 byte is 8 bits.
-- If 
[P3477](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3477r5.html) 
is adopted, `CHAR_BIT=8` on all conforming C++ implementations.
- [ ] Decide whether `float` and `double` should be linted in favour of 
[stdfloat types](https://en.cppreference.com/w/cpp/types/floating-point.html) 
or whether this should be a separate check.

>From 3ef4feb748551806c863529306fefb2bd914e5be Mon Sep 17 00:00:00 2001
From: JJ Marr 
Date: Thu, 3 Jul 2025 17:17:06 -0400
Subject: [PATCH 1/3] AvoidFundamentalIntegerTypesCheck

---
 .../AvoidFundamentalIntegerTypesCheck.cpp | 183 ++
 .../AvoidFundamentalIntegerTypesCheck.h   |  46 +
 .../clang-tidy/modernize/CMakeLists.txt   |   1 +
 .../modernize/ModernizeTidyModule.cpp |   3 +
 .../avoid-fundamental-integer-types.cpp   | 108 +++
 5 files changed, 341 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.h
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-fundamental-integer-types.cpp

diff --git 
a/clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp
new file mode 100644
index 0..8a393bc894cfe
--- /dev/null
+++ 
b/clang-tools-extra/clang-tidy/modernize/AvoidFundamentalIntegerTypesCheck.cpp
@@ -0,0 +1,183 @@
+//===--- AvoidFundamentalIntegerTypesCheck.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 "AvoidFundamentalIntegerTypesCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+namespace {
+
+AST_MATCHER(clang::TypeLoc, hasValidBeginLoc) {
+  return Node.getBeginLoc().isValid();
+}
+
+AST_MATCHER_P(clang::TypeLoc, hasType,
+  clang::ast_matchers::internal::Matcher,
+  InnerMatcher) {
+  const clang::Type *TypeNode = Node.getTypePtr();
+  return TypeNode != nullptr &&
+ InnerMatcher.matches(*TypeNode, Finder, Builder);
+}
+
+} // namespace
+
+AvoidFundamentalIntegerTypesCheck::AvoidFundamentalIntegerTypesCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  IgnoreTypedefs(Options.get("IgnoreTypedefs", false)) {}
+
+void AvoidFundamentalIntegerTypesCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IgnoreTypedefs", IgnoreTypedefs);
+}
+
+bool AvoidFundamentalIntegerTypesCheck::isFundamentalIntegerType(
+const Type *T) const {
+  if (!T->isBuiltinType())
+return false;
+
+  const auto *BT = T->getAs();
+  if (!BT)
+return false;
+
+  switch (BT->getKind()) {
+  case BuiltinType::Int:
+  case BuiltinType::UInt:
+  case BuiltinType::Short:
+  case BuiltinType::UShort:
+  case BuiltinType::Long:
+  case BuiltinType::ULong:
+  case BuiltinType::LongLong:
+  case BuiltinType::ULongLong:
+return true;
+  default:
+return false;
+  }
+}
+
+bool AvoidFundamentalIntegerTypesCheck::isSemanticType(const Type *T) const {
+  if (!T->isBuiltinType())
+return false;
+
+  const auto *BT = T->get

[clang-tools-extra] [clang-tidy] Add portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-06 Thread JJ Marr via cfe-commits


@@ -0,0 +1,100 @@
+// RUN: %check_clang_tidy %s 
portability-avoid-platform-specific-fundamental-types %t -- 
-config="{CheckOptions: [{key: 
portability-avoid-platform-specific-fundamental-types.WarnOnFloats, value: 
true}]}" -header-filter=.* -- -std=c++23
+
+// Mock fixed-width float types
+// In reality, these types are aliases to "extended floating point types", and
+// are not typedefs. However, there isn't a good way to mock extended floats as
+// they are not fundamental types.
+// NOLINTBEGIN(portability-avoid-platform-specific-fundamental-types)
+typedef float float32_t;
+typedef double float64_t;
+// NOLINTEND(portability-avoid-platform-specific-fundamental-types)
+
+// Test floating point types that should trigger warnings when WarnOnFloats is 
enabled
+float global_float = 3.14f;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: avoid using platform-dependent 
floating point type 'float'; consider using 'float32_t' instead 
[portability-avoid-platform-specific-fundamental-types]
+// CHECK-FIXES: float32_t global_float = 3.14f;

jj-marr wrote:

Not done. I want to make this another check, maybe 
"`readability-inconsistent-literal-suffix`".

https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-06 Thread JJ Marr via cfe-commits


@@ -0,0 +1,190 @@
+.. title:: clang-tidy - portability-avoid-platform-specific-fundamental-types
+
+portability-avoid-platform-specific-fundamental-types
+=
+
+Finds fundamental types (e.g. `int`, `float`) and recommends using typedefs 
+or fixed-width types instead to improve portability across different platforms.
+
+This check detects fundamental types (``int``, ``short``, ``long``, ``float``, 
+``char`` and their ``unsigned`` or ``signed`` variants) and warns against 
their 
+use due to non-standard platform-dependent behavior. For example, ``long`` is 
+64 bits on Linux but 32 bits on Windows. There is no standard rationale or 
+intent for the sizes of these types.
+
+Instead of fundamental types, use fixed-width types such as ``int32_t`` or 
+implementation-defined types with standard semantics, e.g. ``int_fast32_t`` 
for 
+the fastest integer type greater than or equal to 32 bits.
+
+Examples
+
+
+.. code-block:: c++
+
+  // Bad: platform-dependent fundamental types
+  int global_int = 42;
+  short global_short = 10;
+  long global_long = 100L;
+  unsigned long global_unsigned_long = 100UL;
+  
+  void function_with_int_param(int param) {
+// ...
+  }
+  
+  int function_returning_int() {
+return 42;
+  }
+  
+  struct MyStruct {
+int member_int;
+long member_long;
+  };
+
+.. code-block:: c++
+
+  // Good: use fixed-width types or typedefs
+  #include 
+  
+  int32_t global_int32 = 42;
+  int16_t global_int16 = 10;
+  int64_t global_int64 = 100L;
+  uint64_t global_uint64 = 100UL;
+  
+  void function_with_int32_param(int32_t param) {
+// ...
+  }
+  
+  int32_t function_returning_int32() {
+return 42;
+  }
+  
+  struct MyStruct {
+int32_t member_int32;
+int64_t member_int64;
+  };
+
+The check will also warn about typedef declarations that use fundamental types
+as their underlying type:
+
+.. code-block:: c++
+
+  // Bad: typedef using fundamental type
+  typedef long long MyLongType;
+  using MyIntType = int;
+
+.. code-block:: c++
+
+  // Good: use descriptive names or fixed-width types
+  typedef int64_t TimestampType;
+  using CounterType = uint32_t;
+
+Rationale
+-
+
+Fundamental types have platform-dependent sizes and behavior:
+
+- ``int`` is typically 32 bits on modern platforms but is only guaranteed to be
+  16 bits by the spec
+- ``long int`` is 32 bits on Windows but 64 bits on most Unix systems
+- ``double`` is typically 64-bit IEEE754, but on some microcontrollers without
+  a 64-bit FPU (e.g. certain Arduinos) it can be 32 bits
+- ``char`` is signed on ARM and unsigned on x86
+
+The C++ specification does not define these types beyond their minimum sizes. 
+That means they can communicate intent in non-standard ways and are often 
+needlessly incompatible. For example, ``int``was traditionally the word size of
+a given processor in 16-bit and 32-bit computing and was a reasonable default 
+for performance. This is no longer true on modern 64-bit computers, but the 
+size of ``int`` remains fixed at 32 bits for backwards compatibility with code 
+that relied on a 32-bit implementation of ``int``.
+
+If code is explicitly relying on the size of an ``int`` being 32 bits, it is 
+better to say so in the typename with ``int32_t``. Otherwise, use an 
+appropriate implementation-defined type such as ``fast_int32_t`` or 
+``least_int32_t`` that communicates the appropriate time/space tradeoff.
+
+Likewise, ``float`` and ``double`` should be replaced by ``float32_t`` and
+``float64_t`` which are guaranteed to be standard IEEE754 floats for a given
+size.
+
+``char`` should be replaced by ``char8_t`` when used in the representation of
+Unicode text. When used to represent a byte on a given platform, ``std::byte``
+is an appropriate replacement.
+
+Types Not Flagged
+-
+
+The following types are intentionally not flagged:
+
+- ``bool`` (boolean type)
+- Standard library typedefs like ``size_t``, ``ptrdiff_t``, or ``uint32_t``.
+- Already typedef'd types, though the check will flag the typedef itself
+
+``bool`` is excluded because it can only be true or false, and is not 
vulnerable to overflow or
+narrowing issues that occur as a result of using implementation-defined types.
+
+Options
+---
+
+.. option:: WarnOnFloats
+
+   When `true`, the check will warn about floating point types (``float`` and 
``double``).
+   When `false` (default), floating point types are not flagged.
+
+   Floating point types can have platform-dependent behavior:
+   
+   - ``float`` is typically 32-bit IEEE754, but can vary on some platforms
+   - ``double`` is typically 64-bit IEEE754, but on some microcontrollers 
without
+ a 64-bit FPU it can be 32 bits
+   
+   When this option is enabled, the check will suggest using ``float32_t`` and 
``float64_t``
+   instead of ``float`` and ``double`` respectively, when the target platform 
supports
+   standard IEEE754 sizes.
+
+ 

[clang-tools-extra] [clang-tidy] Add portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-06 Thread JJ Marr via cfe-commits


@@ -0,0 +1,190 @@
+.. title:: clang-tidy - portability-avoid-platform-specific-fundamental-types
+
+portability-avoid-platform-specific-fundamental-types
+=
+
+Finds fundamental types (e.g. `int`, `float`) and recommends using typedefs 
+or fixed-width types instead to improve portability across different platforms.
+
+This check detects fundamental types (``int``, ``short``, ``long``, ``float``, 
+``char`` and their ``unsigned`` or ``signed`` variants) and warns against 
their 
+use due to non-standard platform-dependent behavior. For example, ``long`` is 
+64 bits on Linux but 32 bits on Windows. There is no standard rationale or 
+intent for the sizes of these types.
+
+Instead of fundamental types, use fixed-width types such as ``int32_t`` or 
+implementation-defined types with standard semantics, e.g. ``int_fast32_t`` 
for 
+the fastest integer type greater than or equal to 32 bits.
+
+Examples
+
+
+.. code-block:: c++
+
+  // Bad: platform-dependent fundamental types
+  int global_int = 42;
+  short global_short = 10;
+  long global_long = 100L;
+  unsigned long global_unsigned_long = 100UL;
+  
+  void function_with_int_param(int param) {
+// ...
+  }
+  
+  int function_returning_int() {
+return 42;
+  }
+  
+  struct MyStruct {
+int member_int;
+long member_long;
+  };
+
+.. code-block:: c++
+
+  // Good: use fixed-width types or typedefs
+  #include 
+  
+  int32_t global_int32 = 42;
+  int16_t global_int16 = 10;
+  int64_t global_int64 = 100L;
+  uint64_t global_uint64 = 100UL;
+  
+  void function_with_int32_param(int32_t param) {
+// ...
+  }
+  
+  int32_t function_returning_int32() {
+return 42;
+  }
+  
+  struct MyStruct {
+int32_t member_int32;
+int64_t member_int64;
+  };
+
+The check will also warn about typedef declarations that use fundamental types
+as their underlying type:
+
+.. code-block:: c++
+
+  // Bad: typedef using fundamental type
+  typedef long long MyLongType;
+  using MyIntType = int;
+
+.. code-block:: c++
+
+  // Good: use descriptive names or fixed-width types
+  typedef int64_t TimestampType;
+  using CounterType = uint32_t;
+
+Rationale
+-
+
+Fundamental types have platform-dependent sizes and behavior:
+
+- ``int`` is typically 32 bits on modern platforms but is only guaranteed to be
+  16 bits by the spec
+- ``long int`` is 32 bits on Windows but 64 bits on most Unix systems
+- ``double`` is typically 64-bit IEEE754, but on some microcontrollers without
+  a 64-bit FPU (e.g. certain Arduinos) it can be 32 bits
+- ``char`` is signed on ARM and unsigned on x86
+
+The C++ specification does not define these types beyond their minimum sizes. 
+That means they can communicate intent in non-standard ways and are often 
+needlessly incompatible. For example, ``int``was traditionally the word size of
+a given processor in 16-bit and 32-bit computing and was a reasonable default 
+for performance. This is no longer true on modern 64-bit computers, but the 
+size of ``int`` remains fixed at 32 bits for backwards compatibility with code 
+that relied on a 32-bit implementation of ``int``.
+
+If code is explicitly relying on the size of an ``int`` being 32 bits, it is 
+better to say so in the typename with ``int32_t``. Otherwise, use an 
+appropriate implementation-defined type such as ``fast_int32_t`` or 
+``least_int32_t`` that communicates the appropriate time/space tradeoff.
+
+Likewise, ``float`` and ``double`` should be replaced by ``float32_t`` and
+``float64_t`` which are guaranteed to be standard IEEE754 floats for a given
+size.
+
+``char`` should be replaced by ``char8_t`` when used in the representation of
+Unicode text. When used to represent a byte on a given platform, ``std::byte``
+is an appropriate replacement.
+
+Types Not Flagged
+-
+
+The following types are intentionally not flagged:
+
+- ``bool`` (boolean type)
+- Standard library typedefs like ``size_t``, ``ptrdiff_t``, or ``uint32_t``.
+- Already typedef'd types, though the check will flag the typedef itself
+
+``bool`` is excluded because it can only be true or false, and is not 
vulnerable to overflow or
+narrowing issues that occur as a result of using implementation-defined types.
+
+Options

jj-marr wrote:

no WarnOnInt option documentation

https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-06 Thread JJ Marr via cfe-commits


@@ -0,0 +1,190 @@
+.. title:: clang-tidy - portability-avoid-platform-specific-fundamental-types
+
+portability-avoid-platform-specific-fundamental-types
+=
+
+Finds fundamental types (e.g. `int`, `float`) and recommends using typedefs 
+or fixed-width types instead to improve portability across different platforms.
+
+This check detects fundamental types (``int``, ``short``, ``long``, ``float``, 
+``char`` and their ``unsigned`` or ``signed`` variants) and warns against 
their 
+use due to non-standard platform-dependent behavior. For example, ``long`` is 
+64 bits on Linux but 32 bits on Windows. There is no standard rationale or 
+intent for the sizes of these types.
+
+Instead of fundamental types, use fixed-width types such as ``int32_t`` or 
+implementation-defined types with standard semantics, e.g. ``int_fast32_t`` 
for 
+the fastest integer type greater than or equal to 32 bits.
+
+Examples
+
+
+.. code-block:: c++
+
+  // Bad: platform-dependent fundamental types
+  int global_int = 42;
+  short global_short = 10;
+  long global_long = 100L;
+  unsigned long global_unsigned_long = 100UL;
+  
+  void function_with_int_param(int param) {
+// ...
+  }
+  
+  int function_returning_int() {
+return 42;
+  }
+  
+  struct MyStruct {
+int member_int;
+long member_long;
+  };
+
+.. code-block:: c++
+
+  // Good: use fixed-width types or typedefs
+  #include 
+  
+  int32_t global_int32 = 42;
+  int16_t global_int16 = 10;
+  int64_t global_int64 = 100L;
+  uint64_t global_uint64 = 100UL;
+  
+  void function_with_int32_param(int32_t param) {
+// ...
+  }
+  
+  int32_t function_returning_int32() {
+return 42;
+  }
+  
+  struct MyStruct {
+int32_t member_int32;
+int64_t member_int64;
+  };
+
+The check will also warn about typedef declarations that use fundamental types
+as their underlying type:
+
+.. code-block:: c++
+
+  // Bad: typedef using fundamental type
+  typedef long long MyLongType;
+  using MyIntType = int;
+
+.. code-block:: c++
+
+  // Good: use descriptive names or fixed-width types
+  typedef int64_t TimestampType;
+  using CounterType = uint32_t;
+
+Rationale
+-
+
+Fundamental types have platform-dependent sizes and behavior:
+
+- ``int`` is typically 32 bits on modern platforms but is only guaranteed to be
+  16 bits by the spec
+- ``long int`` is 32 bits on Windows but 64 bits on most Unix systems
+- ``double`` is typically 64-bit IEEE754, but on some microcontrollers without
+  a 64-bit FPU (e.g. certain Arduinos) it can be 32 bits
+- ``char`` is signed on ARM and unsigned on x86
+
+The C++ specification does not define these types beyond their minimum sizes. 
+That means they can communicate intent in non-standard ways and are often 
+needlessly incompatible. For example, ``int``was traditionally the word size of
+a given processor in 16-bit and 32-bit computing and was a reasonable default 
+for performance. This is no longer true on modern 64-bit computers, but the 
+size of ``int`` remains fixed at 32 bits for backwards compatibility with code 
+that relied on a 32-bit implementation of ``int``.
+
+If code is explicitly relying on the size of an ``int`` being 32 bits, it is 
+better to say so in the typename with ``int32_t``. Otherwise, use an 
+appropriate implementation-defined type such as ``fast_int32_t`` or 
+``least_int32_t`` that communicates the appropriate time/space tradeoff.
+
+Likewise, ``float`` and ``double`` should be replaced by ``float32_t`` and
+``float64_t`` which are guaranteed to be standard IEEE754 floats for a given
+size.
+
+``char`` should be replaced by ``char8_t`` when used in the representation of
+Unicode text. When used to represent a byte on a given platform, ``std::byte``
+is an appropriate replacement.
+
+Types Not Flagged
+-
+
+The following types are intentionally not flagged:
+
+- ``bool`` (boolean type)
+- Standard library typedefs like ``size_t``, ``ptrdiff_t``, or ``uint32_t``.
+- Already typedef'd types, though the check will flag the typedef itself
+
+``bool`` is excluded because it can only be true or false, and is not 
vulnerable to overflow or
+narrowing issues that occur as a result of using implementation-defined types.
+
+Options
+---
+
+.. option:: WarnOnFloats
+
+   When `true`, the check will warn about floating point types (``float`` and 
``double``).

jj-marr wrote:

should be true by default. Maybe only on C++23 and above?

https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-06 Thread JJ Marr via cfe-commits


@@ -0,0 +1,63 @@
+// RUN: %check_clang_tidy %s 
portability-avoid-platform-specific-fundamental-types %t -- 
-config="{CheckOptions: [{key: 
portability-avoid-platform-specific-fundamental-types.WarnOnChars, value: 
true}]}" -header-filter=.* -- -std=c++11

jj-marr wrote:

should also ensure that ints aren't linted when WarnOnChars on its own is 
enabled and the other two are disabled

https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-06 Thread JJ Marr via cfe-commits


@@ -0,0 +1,100 @@
+// RUN: %check_clang_tidy %s 
portability-avoid-platform-specific-fundamental-types %t -- 
-config="{CheckOptions: [{key: 
portability-avoid-platform-specific-fundamental-types.WarnOnFloats, value: 
true}]}" -header-filter=.* -- -std=c++23
+
+// Mock fixed-width float types
+// In reality, these types are aliases to "extended floating point types", and
+// are not typedefs. However, there isn't a good way to mock extended floats as
+// they are not fundamental types.
+// NOLINTBEGIN(portability-avoid-platform-specific-fundamental-types)
+typedef float float32_t;
+typedef double float64_t;
+// NOLINTEND(portability-avoid-platform-specific-fundamental-types)
+
+// Test floating point types that should trigger warnings when WarnOnFloats is 
enabled
+float global_float = 3.14f;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: avoid using platform-dependent 
floating point type 'float'; consider using 'float32_t' instead 
[portability-avoid-platform-specific-fundamental-types]
+// CHECK-FIXES: float32_t global_float = 3.14f;

jj-marr wrote:

this should change the suffixes too if they exist

https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-06 Thread JJ Marr via cfe-commits


@@ -0,0 +1,190 @@
+.. title:: clang-tidy - portability-avoid-platform-specific-fundamental-types
+
+portability-avoid-platform-specific-fundamental-types
+=
+
+Finds fundamental types (e.g. `int`, `float`) and recommends using typedefs 
+or fixed-width types instead to improve portability across different platforms.
+
+This check detects fundamental types (``int``, ``short``, ``long``, ``float``, 
+``char`` and their ``unsigned`` or ``signed`` variants) and warns against 
their 
+use due to non-standard platform-dependent behavior. For example, ``long`` is 
+64 bits on Linux but 32 bits on Windows. There is no standard rationale or 
+intent for the sizes of these types.
+
+Instead of fundamental types, use fixed-width types such as ``int32_t`` or 
+implementation-defined types with standard semantics, e.g. ``int_fast32_t`` 
for 
+the fastest integer type greater than or equal to 32 bits.
+
+Examples
+
+
+.. code-block:: c++
+
+  // Bad: platform-dependent fundamental types
+  int global_int = 42;
+  short global_short = 10;
+  long global_long = 100L;
+  unsigned long global_unsigned_long = 100UL;
+  
+  void function_with_int_param(int param) {
+// ...
+  }
+  
+  int function_returning_int() {
+return 42;
+  }
+  
+  struct MyStruct {
+int member_int;
+long member_long;
+  };
+
+.. code-block:: c++
+
+  // Good: use fixed-width types or typedefs
+  #include 
+  
+  int32_t global_int32 = 42;
+  int16_t global_int16 = 10;
+  int64_t global_int64 = 100L;
+  uint64_t global_uint64 = 100UL;
+  
+  void function_with_int32_param(int32_t param) {
+// ...
+  }
+  
+  int32_t function_returning_int32() {
+return 42;
+  }
+  
+  struct MyStruct {
+int32_t member_int32;
+int64_t member_int64;
+  };
+
+The check will also warn about typedef declarations that use fundamental types
+as their underlying type:
+
+.. code-block:: c++
+
+  // Bad: typedef using fundamental type
+  typedef long long MyLongType;
+  using MyIntType = int;
+
+.. code-block:: c++
+
+  // Good: use descriptive names or fixed-width types
+  typedef int64_t TimestampType;
+  using CounterType = uint32_t;
+
+Rationale
+-
+
+Fundamental types have platform-dependent sizes and behavior:
+
+- ``int`` is typically 32 bits on modern platforms but is only guaranteed to be
+  16 bits by the spec
+- ``long int`` is 32 bits on Windows but 64 bits on most Unix systems
+- ``double`` is typically 64-bit IEEE754, but on some microcontrollers without
+  a 64-bit FPU (e.g. certain Arduinos) it can be 32 bits
+- ``char`` is signed on ARM and unsigned on x86
+
+The C++ specification does not define these types beyond their minimum sizes. 
+That means they can communicate intent in non-standard ways and are often 
+needlessly incompatible. For example, ``int``was traditionally the word size of

jj-marr wrote:

Done.

https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-06 Thread JJ Marr via cfe-commits


@@ -0,0 +1,260 @@
+//===--- AvoidPlatformSpecificFundamentalTypesCheck.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 "AvoidPlatformSpecificFundamentalTypesCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/TargetInfo.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::portability {
+
+AvoidPlatformSpecificFundamentalTypesCheck::
+AvoidPlatformSpecificFundamentalTypesCheck(StringRef Name,
+   ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  WarnOnFloats(Options.get("WarnOnFloats", false)),
+  WarnOnInts(Options.get("WarnOnInts", true)),
+  WarnOnChars(Options.get("WarnOnChars", false)),
+  IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",
+   utils::IncludeSorter::IS_LLVM),
+  areDiagsSelfContained()) {}
+
+void AvoidPlatformSpecificFundamentalTypesCheck::registerPPCallbacks(
+const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) 
{
+  IncludeInserter.registerPreprocessor(PP);
+}
+
+void AvoidPlatformSpecificFundamentalTypesCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "WarnOnFloats", WarnOnFloats);
+  Options.store(Opts, "WarnOnInts", WarnOnInts);
+  Options.store(Opts, "WarnOnChars", WarnOnChars);
+  Options.store(Opts, "IncludeStyle", IncludeInserter.getStyle());
+}
+
+std::string AvoidPlatformSpecificFundamentalTypesCheck::getFloatReplacement(
+const BuiltinType *BT, ASTContext &Context) const {
+  const TargetInfo &Target = Context.getTargetInfo();
+
+  auto GetReplacementType = [](unsigned Width) {
+switch (Width) {
+// This is ambiguous by default since it could be bfloat16 or float16
+case 16U:
+  return "";
+case 32U:
+  return "float32_t";
+case 64U:
+  return "float64_t";
+case 128U:
+  return "float128_t";
+default:
+  return "";
+}
+  };
+
+  switch (BT->getKind()) {
+  // Not an ambiguous type
+  case BuiltinType::BFloat16:
+return "bfloat16_t";
+  case BuiltinType::Half:
+return GetReplacementType(Target.getHalfWidth());
+  case BuiltinType::Float:
+return GetReplacementType(Target.getFloatWidth());
+  case BuiltinType::Double:
+return GetReplacementType(Target.getDoubleWidth());
+  default:
+return "";
+  }
+}
+
+void AvoidPlatformSpecificFundamentalTypesCheck::registerMatchers(
+MatchFinder *Finder) {
+  // Build the list of type strings to match
+  std::vector TypeStrings;
+
+  // Add integer types if the option is enabled
+  if (WarnOnInts) {
+TypeStrings.insert(TypeStrings.end(), {"short",
+   "short int",
+   "signed short",
+   "signed short int",
+   "unsigned short",
+   "unsigned short int",
+   "int",
+   "signed",
+   "signed int",
+   "unsigned",
+   "unsigned int",
+   "long",
+   "long int",
+   "signed long",
+   "signed long int",
+   "unsigned long",
+   "unsigned long int",
+   "long long",
+   "long long int",
+   "signed long long",
+   "signed long long int",
+   "unsigned long long",
+   "unsigned long long int"});
+  }
+
+  // Add float types if the option is enabled
+  if (WarnOnFloats) {
+TypeStrings.insert(TypeStrings.end(),
+   {"half", "__bf16", "float", "double", "long double"});
+  }
+
+  // Add char types if the option is enabled
+  if (WarnOnChars) {
+TypeStrings.insert(TypeStrings.end(),
+   {"char", "signed char", "unsigned char"});
+  }
+
+  // If no types are enabled, return early
+  if (TypeStrings.empty()) {
+return;
+  }
+
+  // Create the matcher dynamically
+  auto TypeMatcher = asString(TypeStrings.front());
+  for

[clang-tools-extra] [clang-tidy] Add portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-06 Thread JJ Marr via cfe-commits


@@ -0,0 +1,54 @@
+// clang-format off
+//===--- AvoidPlatformSpecificFundamentalTypesCheck.h - clang-tidy -*- 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
+//
+//===-===//
+// clang-format on

jj-marr wrote:

Done.

https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-06 Thread JJ Marr via cfe-commits


@@ -0,0 +1,54 @@
+// clang-format off
+//===--- AvoidPlatformSpecificFundamentalTypesCheck.h - clang-tidy -*- C++ 
-*-===//

jj-marr wrote:

Done.

https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-04 Thread JJ Marr via cfe-commits

jj-marr wrote:

> Check makes sense to me! As a first iteration it's fine without autofix but I 
> can imagine it will be hard for a codebase to enable this check given the 
> large amount of things to fix. Maybe users can specify a mapping of wanted 
> types via an option?

I'm planning for an autofix of `float` and `double` since it's unambiguous what 
those types should be.

For `int` types, maybe I'll give 3 options for an autofix:

* Fixed (`int32_t`) 
* Fast (`int_fast32_t`) 
* Least (`int_least32_t`) 

Based on sizeof the type when running `clang-tidy`. This represents 
compatibility/time/space tradeoffs.

Not sure about `char`. If you're actually representing UTF-8 text, it's a good 
idea to replace with `char8_t`. If you're using `char` because it's 1 byte and 
you want to do wacky things with memory, `std::byte` is the way to go. I'm not 
sure how relatively common each is since I work with low-level hardware at my 
day job and I'm biased towards assuming weird byte level stuff is more common 
than it really is. 

It's also not a "safe" replacement to get rid of `char` in all cases, since 
`char8_t` and `std::byte` are always unsigned. If the memory representation of 
`char` is identical to `unsigned char` it's probably safe enough?

https://github.com/llvm/llvm-project/pull/146970
___
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 portability-avoid-platform-specific-fundamental-types (PR #146970)

2025-07-10 Thread JJ Marr via cfe-commits


@@ -0,0 +1,260 @@
+//===--- AvoidPlatformSpecificFundamentalTypesCheck.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 "AvoidPlatformSpecificFundamentalTypesCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/TargetInfo.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::portability {
+
+AvoidPlatformSpecificFundamentalTypesCheck::
+AvoidPlatformSpecificFundamentalTypesCheck(StringRef Name,
+   ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  WarnOnFloats(Options.get("WarnOnFloats", true)),
+  WarnOnInts(Options.get("WarnOnInts", true)),
+  WarnOnChars(Options.get("WarnOnChars", true)),
+  IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",
+   utils::IncludeSorter::IS_LLVM),
+  areDiagsSelfContained()) {}
+
+void AvoidPlatformSpecificFundamentalTypesCheck::registerPPCallbacks(
+const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) 
{
+  IncludeInserter.registerPreprocessor(PP);
+}
+
+void AvoidPlatformSpecificFundamentalTypesCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "WarnOnFloats", WarnOnFloats);
+  Options.store(Opts, "WarnOnInts", WarnOnInts);
+  Options.store(Opts, "WarnOnChars", WarnOnChars);
+  Options.store(Opts, "IncludeStyle", IncludeInserter.getStyle());
+}
+
+std::string AvoidPlatformSpecificFundamentalTypesCheck::getFloatReplacement(
+const BuiltinType *BT, ASTContext &Context) const {
+  const TargetInfo &Target = Context.getTargetInfo();
+
+  auto GetReplacementType = [](unsigned Width) {
+switch (Width) {
+// This is ambiguous by default since it could be bfloat16 or float16
+case 16U:
+  return "";
+case 32U:
+  return "float32_t";
+case 64U:
+  return "float64_t";
+case 128U:
+  return "float128_t";
+default:
+  return "";
+}
+  };
+
+  switch (BT->getKind()) {
+  // Not an ambiguous type
+  case BuiltinType::BFloat16:
+return "bfloat16_t";
+  case BuiltinType::Half:
+return GetReplacementType(Target.getHalfWidth());
+  case BuiltinType::Float:
+return GetReplacementType(Target.getFloatWidth());
+  case BuiltinType::Double:
+return GetReplacementType(Target.getDoubleWidth());
+  default:
+return "";
+  }
+}
+
+void AvoidPlatformSpecificFundamentalTypesCheck::registerMatchers(
+MatchFinder *Finder) {
+  // Build the list of type strings to match
+  std::vector TypeStrings;
+
+  // Add integer types if the option is enabled
+  if (WarnOnInts) {
+TypeStrings.insert(TypeStrings.end(), {"short",

jj-marr wrote:

> You don't need to worry about `unit32_t` because clang-tidy usually suppress 
> warning from system headers unless you explicitly use `--header-filter=*`. 
> Usually people don't care what warnings system headers have.

If the warning triggers on `MyLong global_long = 100L; // Warning`, then it 
would also trigger when I use `uint32_t global_long = 100U`, no? Assuming it's 
triggered on use.

I also don't see the purpose of having this case because there will already be 
a warning on `using MyLong = long;` If I want to silence the warning, I'd 
rather `NOLINT` it when I define the typedef rather than everywhere I use it.

https://github.com/llvm/llvm-project/pull/146970
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits