[clang] [clang][ExprConst] Add diagnostics for invalid binary arithmetic (PR #118475)

via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 3 03:54:11 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

<details>
<summary>Changes</summary>

... between unrelated declarations or literals.

Leaving this small (I haven't run the whole test suite locally) to get some feedback on the wording and implementation first.

The output of the sample in https://github.com/llvm/llvm-project/issues/117409 is now:
```console
./array.cpp:57:6: warning: expression result unused [-Wunused-value]
   57 |   am - aj.af();
      |   ~~ ^ ~~~~~~~
./array.cpp:70:8: error: call to consteval function 'L::L<bx>' is not a constant expression
   70 |   q(0, [] {
      |        ^
./array.cpp:57:6: note: arithmetic on addresses of literals has unspecified value
   57 |   am - aj.af();
      |      ^
./array.cpp:62:5: note: in call to 'al(&""[0], {&""[0]})'
   62 |     al(bp.af(), k);
      |     ^~~~~~~~~~~~~~
./array.cpp:70:8: note: in call to 'L<bx>({})'
   70 |   q(0, [] {
      |        ^~~~
   71 |     struct bx {
      |     ~~~~~~~~~~~
   72 |       constexpr operator ab<g<l<decltype(""[0])>::e>::e>() { return t(""); }
      |       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   73 |     };
      |     ~~
   74 |     return bx();
      |     ~~~~~~~~~~~~
   75 |   }());
      |   ~~~
```

The output for 
```c++
int a, b;
constexpr int n = &b - &a
```

is now:
```console
./array.cpp:80:15: error: constexpr variable 'n' must be initialized by a constant expression
   80 | constexpr int n = &b - &a;
      |               ^   ~~~~~~~
./array.cpp:80:22: note: arithmetic involving '&b' and '&a' has unspecified value
   80 | constexpr int n = &b - &a;
      |                      ^
1 error generated.

```

---
Full diff: https://github.com/llvm/llvm-project/pull/118475.diff


2 Files Affected:

- (modified) clang/include/clang/Basic/DiagnosticASTKinds.td (+4) 
- (modified) clang/lib/AST/ExprConstant.cpp (+15-2) 


``````````diff
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td
index f630698757c5fb..4d078fc9ca6bb7 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -91,11 +91,15 @@ def note_constexpr_pointer_subtraction_zero_size : Note<
   "subtraction of pointers to type %0 of zero size">;
 def note_constexpr_pointer_comparison_unspecified : Note<
   "comparison between '%0' and '%1' has unspecified value">;
+def note_constexpr_pointer_arith_unspecified : Note<
+  "arithmetic involving '%0' and '%1' has unspecified value">;
 def note_constexpr_pointer_constant_comparison : Note<
   "comparison of numeric address '%0' with pointer '%1' can only be performed "
   "at runtime">;
 def note_constexpr_literal_comparison : Note<
   "comparison of addresses of literals has unspecified value">;
+def note_constexpr_literal_arith : Note<
+  "arithmetic on addresses of literals has unspecified value">;
 def note_constexpr_opaque_call_comparison : Note<
   "comparison against opaque constant address '%0' can only be performed at "
   "runtime">;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 6b5b95aee35522..2aefcd870ebaf8 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -14548,8 +14548,21 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
         return Error(E);
       const Expr *LHSExpr = LHSValue.Base.dyn_cast<const Expr *>();
       const Expr *RHSExpr = RHSValue.Base.dyn_cast<const Expr *>();
-      if (!LHSExpr || !RHSExpr)
-        return Error(E);
+      if (!LHSExpr || !RHSExpr) {
+        std::string LHS = LHSValue.toString(Info.Ctx, E->getLHS()->getType());
+        std::string RHS = RHSValue.toString(Info.Ctx, E->getRHS()->getType());
+        Info.FFDiag(E, diag::note_constexpr_pointer_arith_unspecified)
+            << LHS << RHS;
+        return false;
+      }
+
+      if (ArePotentiallyOverlappingStringLiterals(Info, LHSValue, RHSValue)) {
+        std::string LHS = LHSValue.toString(Info.Ctx, E->getLHS()->getType());
+        std::string RHS = RHSValue.toString(Info.Ctx, E->getRHS()->getType());
+        Info.FFDiag(E, diag::note_constexpr_literal_arith) << LHS << RHS;
+        return false;
+      }
+
       const AddrLabelExpr *LHSAddrExpr = dyn_cast<AddrLabelExpr>(LHSExpr);
       const AddrLabelExpr *RHSAddrExpr = dyn_cast<AddrLabelExpr>(RHSExpr);
       if (!LHSAddrExpr || !RHSAddrExpr)

``````````

</details>


https://github.com/llvm/llvm-project/pull/118475


More information about the cfe-commits mailing list