[clang] Add flag to suppress overflow errors in C++ constant expressions. (PR #102390)

via cfe-commits cfe-commits at lists.llvm.org
Wed Aug 7 15:00:44 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Eli Friedman (efriedma-quic)

<details>
<summary>Changes</summary>

Recent Android NDK headers are broken on 32-bit because they contain an invalid shift, and older versions of clang didn't catch this. Demote the error to a default-error with a flag so it can be suppressed.  See discussion on #<!-- -->70307.

Not sure if this is really worth doing if it only affects the Android NDK; Android trunk has been fixed.  And presumably most people will use the compiler from the NDK itself, so they'll update their headers before they ever run into this.  But posting so we can discuss...

CC @<!-- -->glandium

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


5 Files Affected:

- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+8) 
- (modified) clang/include/clang/Sema/Sema.h (+1) 
- (modified) clang/lib/Sema/SemaExpr.cpp (+13-3) 
- (modified) clang/test/C/drs/dr2xx.c (+1-1) 
- (modified) clang/test/Sema/shift-count-overflow.c (+3) 


``````````diff
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 581434d33c5c9..e51f882856221 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -74,6 +74,14 @@ def err_expr_not_ice : Error<
 def ext_expr_not_ice : Extension<
   "expression is not an %select{integer|integral}0 constant expression; "
   "folding it to a constant is a GNU extension">, InGroup<GNUFoldingConstant>;
+def ext_expr_ice_overflow : Extension<
+  "expression is not an integer constant expression "
+  "because of arithmetic overflow; folding it to a constant is a GNU "
+  "extension">, InGroup<GNUFoldingConstant>;
+def ext_expr_ice_overflow_cxx : Extension<
+  "expression is not an integral constant expression "
+  "because of arithmetic overflow">,
+  InGroup<DiagGroup<"constant-overflow">>, DefaultError, SFINAEFailure;
 def err_typecheck_converted_constant_expression : Error<
   "value of type %0 is not implicitly convertible to %1">;
 def err_typecheck_converted_constant_expression_disallowed : Error<
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 2ec6367eccea0..96af6427b38ea 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -7242,6 +7242,7 @@ class Sema final : public SemaBase {
     virtual SemaDiagnosticBuilder diagnoseNotICE(Sema &S,
                                                  SourceLocation Loc) = 0;
     virtual SemaDiagnosticBuilder diagnoseFold(Sema &S, SourceLocation Loc);
+    virtual SemaDiagnosticBuilder diagnoseOverflow(Sema &S, SourceLocation Loc);
     virtual ~VerifyICEDiagnoser() {}
   };
 
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 74c0e01705905..84bc1e37215cd 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -16913,6 +16913,13 @@ Sema::VerifyICEDiagnoser::diagnoseFold(Sema &S, SourceLocation Loc) {
   return S.Diag(Loc, diag::ext_expr_not_ice) << S.LangOpts.CPlusPlus;
 }
 
+Sema::SemaDiagnosticBuilder
+Sema::VerifyICEDiagnoser::diagnoseOverflow(Sema &S, SourceLocation Loc) {
+  if (S.LangOpts.CPlusPlus)
+    return S.Diag(Loc, diag::ext_expr_ice_overflow_cxx);
+  return S.Diag(Loc, diag::ext_expr_ice_overflow);
+}
+
 ExprResult
 Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
                                       VerifyICEDiagnoser &Diagnoser,
@@ -17031,6 +17038,7 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
     }
 
     Diagnoser.diagnoseFold(*this, DiagLoc) << E->getSourceRange();
+
     for (const PartialDiagnosticAt &Note : Notes)
       Diag(Note.first, Note.second);
     
@@ -17045,8 +17053,7 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
   // not a constant expression as a side-effect.
   bool Folded =
       E->EvaluateAsRValue(EvalResult, Context, /*isConstantContext*/ true) &&
-      EvalResult.Val.isInt() && !EvalResult.HasSideEffects &&
-      (!getLangOpts().CPlusPlus || !EvalResult.HasUndefinedBehavior);
+      EvalResult.Val.isInt() && !EvalResult.HasSideEffects;
 
   if (!isa<ConstantExpr>(E))
     E = ConstantExpr::Create(Context, E, EvalResult.Val);
@@ -17079,7 +17086,10 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
     return ExprError();
   }
 
-  Diagnoser.diagnoseFold(*this, DiagLoc) << E->getSourceRange();
+  if (EvalResult.HasUndefinedBehavior)
+    Diagnoser.diagnoseOverflow(*this, DiagLoc) << E->getSourceRange();
+  else
+    Diagnoser.diagnoseFold(*this, DiagLoc) << E->getSourceRange();
   for (const PartialDiagnosticAt &Note : Notes)
     Diag(Note.first, Note.second);
 
diff --git a/clang/test/C/drs/dr2xx.c b/clang/test/C/drs/dr2xx.c
index ffdf5aac377d9..5df6f056e5c50 100644
--- a/clang/test/C/drs/dr2xx.c
+++ b/clang/test/C/drs/dr2xx.c
@@ -287,7 +287,7 @@ void dr261(void) {
    * but we fold it as a constant expression anyway as a GNU extension.
    */
   enum e2 {
-    ex2 = __INT_MAX__ + (0, 1) /* expected-warning {{expression is not an integer constant expression; folding it to a constant is a GNU extension}}
+    ex2 = __INT_MAX__ + (0, 1) /* expected-warning {{expression is not an integer constant expression because of arithmetic overflow; folding it to a constant is a GNU extension}}
                                   expected-note {{value 2147483648 is outside the range of representable values of type 'int'}}
                                   expected-warning {{left operand of comma operator has no effect}}
                                 */
diff --git a/clang/test/Sema/shift-count-overflow.c b/clang/test/Sema/shift-count-overflow.c
index b5186586c2272..69890d8d6cb28 100644
--- a/clang/test/Sema/shift-count-overflow.c
+++ b/clang/test/Sema/shift-count-overflow.c
@@ -1,6 +1,9 @@
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,c -pedantic %s
 // RUN: %clang_cc1 -x c++ -std=c++98 -fsyntax-only -verify=expected,cpp %s
 // RUN: %clang_cc1 -x c++ -std=c++11 -fsyntax-only -verify=expected,cpp %s
+// RUN: %clang_cc1 -x c++ -std=c++11 -fsyntax-only -Wno-constant-overflow -verify=suppress %s
+
+// suppress-no-diagnostics
 
 enum shiftof {
     X = (1<<32) // c-warning {{expression is not an integer constant expression; folding it to a constant is a GNU extension}}

``````````

</details>


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


More information about the cfe-commits mailing list