]> granicus.if.org Git - clang/commitdiff
[Diagnostics] Check for integer overflow in array size expressions
authorDavid Bolvansky <david.bolvansky@gmail.com>
Thu, 18 Oct 2018 20:49:06 +0000 (20:49 +0000)
committerDavid Bolvansky <david.bolvansky@gmail.com>
Thu, 18 Oct 2018 20:49:06 +0000 (20:49 +0000)
Summary: Fixes PR27439

Reviewers: rsmith, Rakete1111

Reviewed By: rsmith

Subscribers: Rakete1111, cfe-commits

Differential Revision: https://reviews.llvm.org/D52750

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@344759 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Expr.h
lib/AST/ExprConstant.cpp
lib/Sema/SemaExpr.cpp
test/Sema/integer-overflow.c

index 8bc14e12df3b10b3b524c231fa133e4ae3c0df5e..8817aa4d6af0662c85ab62a901cc7df86188820e 100644 (file)
@@ -631,8 +631,13 @@ public:
   /// EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded
   /// integer. This must be called on an expression that constant folds to an
   /// integer.
-  llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx,
-                    SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr) const;
+  llvm::APSInt EvaluateKnownConstInt(
+      const ASTContext &Ctx,
+      SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr) const;
+
+  llvm::APSInt EvaluateKnownConstIntCheckOverflow(
+      const ASTContext &Ctx,
+      SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr) const;
 
   void EvaluateForOverflow(const ASTContext &Ctx) const;
 
index de0de5d13cdb4ff30c4011e95a0a2691e5a9ecc1..c4d1245071daa890c5a313fc821f310dc8c7bf27 100644 (file)
@@ -10851,6 +10851,19 @@ APSInt Expr::EvaluateKnownConstInt(const ASTContext &Ctx,
   return EvalResult.Val.getInt();
 }
 
+APSInt Expr::EvaluateKnownConstIntCheckOverflow(
+    const ASTContext &Ctx, SmallVectorImpl<PartialDiagnosticAt> *Diag) const {
+  EvalResult EvalResult;
+  EvalResult.Diag = Diag;
+  EvalInfo Info(Ctx, EvalResult, EvalInfo::EM_EvaluateForOverflow);
+  bool Result = ::EvaluateAsRValue(Info, this, EvalResult.Val);
+  (void)Result;
+  assert(Result && "Could not evaluate expression");
+  assert(EvalResult.Val.isInt() && "Expression did not evaluate to integer");
+
+  return EvalResult.Val.getInt();
+}
+
 void Expr::EvaluateForOverflow(const ASTContext &Ctx) const {
   bool IsConst;
   EvalResult EvalResult;
index 72499b0e9057ba9e511501f7acd484cdf18588d7..597f220bc4c01e69e72b32f68ccc4330f6da8a63 100644 (file)
@@ -14105,7 +14105,7 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
   // in the non-ICE case.
   if (!getLangOpts().CPlusPlus11 && E->isIntegerConstantExpr(Context)) {
     if (Result)
-      *Result = E->EvaluateKnownConstInt(Context);
+      *Result = E->EvaluateKnownConstIntCheckOverflow(Context);
     return E;
   }
 
index d66ce7ff16472ac2d43f23622e023c2f220e8b7a..39395d9bc1fd4766a5c9a86c685efb2dcd94e1e5 100644 (file)
@@ -172,6 +172,9 @@ void check_integer_overflows_in_function_calls() {
 // expected-warning@+1 {{overflow in expression; result is 536870912 with type 'int'}}
   (void)f2(0, f0(4608 * 1024 * 1024));
 }
+void check_integer_overflows_in_array_size() {
+  int arr[4608 * 1024 * 1024]; // expected-warning {{overflow in expression; result is 536870912 with type 'int'}}
+}
 
 struct s {
   unsigned x;