]> granicus.if.org Git - clang/commitdiff
[Sema] Issue a warning for integer overflow in nested struct initializer
authorAkira Hatanaka <ahatanaka@apple.com>
Wed, 10 Feb 2016 06:06:06 +0000 (06:06 +0000)
committerAkira Hatanaka <ahatanaka@apple.com>
Wed, 10 Feb 2016 06:06:06 +0000 (06:06 +0000)
r257357 fixed clang to warn on integer overflow in struct initializers.
However, it didn't warn when a struct had a nested initializer. This
commit makes changes in Sema::CheckForIntOverflow to handle nested
initializers.

For example:

struct s {
  struct t {
    unsigned x;
  } t;
} s = {
  {
    .x = 4 * 1024 * 1024 * 1024
  }
};

rdar://problem/23526454

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

lib/Sema/SemaChecking.cpp
test/Sema/integer-overflow.c

index 9c3f721ca63fc1a4bc6dba403e00796615b5dcd5..3b41a50609d35b2e175e901507d2ad4dfb77e1ea 100644 (file)
@@ -8123,12 +8123,20 @@ void Sema::CheckBoolLikeConversion(Expr *E, SourceLocation CC) {
 /// Diagnose when expression is an integer constant expression and its evaluation
 /// results in integer overflow
 void Sema::CheckForIntOverflow (Expr *E) {
-  if (isa<BinaryOperator>(E->IgnoreParenCasts()))
-    E->IgnoreParenCasts()->EvaluateForOverflow(Context);
-  else if (auto InitList = dyn_cast<InitListExpr>(E))
-    for (Expr *E : InitList->inits())
-      if (isa<BinaryOperator>(E->IgnoreParenCasts()))
-        E->IgnoreParenCasts()->EvaluateForOverflow(Context);
+  // Use a work list to deal with nested struct initializers.
+  SmallVector<Expr *, 2> Exprs(1, E);
+
+  do {
+    Expr *E = Exprs.pop_back_val();
+
+    if (isa<BinaryOperator>(E->IgnoreParenCasts())) {
+      E->IgnoreParenCasts()->EvaluateForOverflow(Context);
+      continue;
+    }
+
+    if (auto InitList = dyn_cast<InitListExpr>(E))
+      Exprs.append(InitList->inits().begin(), InitList->inits().end());
+  } while (!Exprs.empty());
 }
 
 namespace {
index db5c1f4c7118db3478a328a031a28406183c68af..02d99b3fc5caa2000f230da712ea51fd6b46c257 100644 (file)
@@ -153,3 +153,23 @@ struct s {
   .y = 5,
   .x = 4 * 1024 * 1024 * 1024  // expected-warning {{overflow in expression; result is 0 with type 'int'}}
 };
+
+struct s2 {
+  unsigned a0;
+
+  struct s3 {
+    unsigned a2;
+
+    struct s4 {
+      unsigned a4;
+    } a3;
+  } a1;
+} s2 = {
+  .a0 = 4 * 1024 * 1024 * 1024, // expected-warning {{overflow in expression; result is 0 with type 'int'}}
+  {
+    .a2 = 4 * 1024 * 1024 * 1024, // expected-warning {{overflow in expression; result is 0 with type 'int'}}
+    {
+      .a4 = 4 * 1024 * 1024 * 1024 // expected-warning {{overflow in expression; result is 0 with type 'int'}}
+    }
+  }
+};