From 3d46479781659e5844a87d0c84952af392aada3a Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Wed, 10 Feb 2016 06:06:06 +0000 Subject: [PATCH] [Sema] Issue a warning for integer overflow in nested struct initializer 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 | 20 ++++++++++++++------ test/Sema/integer-overflow.c | 20 ++++++++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 9c3f721ca6..3b41a50609 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -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(E->IgnoreParenCasts())) - E->IgnoreParenCasts()->EvaluateForOverflow(Context); - else if (auto InitList = dyn_cast(E)) - for (Expr *E : InitList->inits()) - if (isa(E->IgnoreParenCasts())) - E->IgnoreParenCasts()->EvaluateForOverflow(Context); + // Use a work list to deal with nested struct initializers. + SmallVector Exprs(1, E); + + do { + Expr *E = Exprs.pop_back_val(); + + if (isa(E->IgnoreParenCasts())) { + E->IgnoreParenCasts()->EvaluateForOverflow(Context); + continue; + } + + if (auto InitList = dyn_cast(E)) + Exprs.append(InitList->inits().begin(), InitList->inits().end()); + } while (!Exprs.empty()); } namespace { diff --git a/test/Sema/integer-overflow.c b/test/Sema/integer-overflow.c index db5c1f4c71..02d99b3fc5 100644 --- a/test/Sema/integer-overflow.c +++ b/test/Sema/integer-overflow.c @@ -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'}} + } + } +}; -- 2.50.1