From: Anna Zaks Date: Thu, 19 Nov 2015 01:25:28 +0000 (+0000) Subject: [analyzer] Improve modeling of static initializers. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6975f3c2b434551813ddd749f6cae5bc29555de4;p=clang [analyzer] Improve modeling of static initializers. Conversions between unrelated pointer types (e.g. char * and void *) involve bitcasts which were not properly modeled in case of static initializers. The patch fixes this problem. The problem was originally spotted by Artem Dergachev. Patched by Yuri Gribov! Differential Revision: http://reviews.llvm.org/D14652 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@253532 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp index 4f8ccd0329..98fac33c22 100644 --- a/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -275,11 +275,17 @@ Optional SValBuilder::getConstantVal(const Expr *E) { case Stmt::ImplicitCastExprClass: { const CastExpr *CE = cast(E); - if (CE->getCastKind() == CK_ArrayToPointerDecay) { - Optional ArrayVal = getConstantVal(CE->getSubExpr()); - if (!ArrayVal) + switch (CE->getCastKind()) { + default: + break; + case CK_ArrayToPointerDecay: + case CK_BitCast: { + const Expr *SE = CE->getSubExpr(); + Optional Val = getConstantVal(SE); + if (!Val) return None; - return evalCast(*ArrayVal, CE->getType(), CE->getSubExpr()->getType()); + return evalCast(*Val, CE->getType(), SE->getType()); + } } // FALLTHROUGH } diff --git a/test/Analysis/inline.cpp b/test/Analysis/inline.cpp index 183df16e12..b7962b53a8 100644 --- a/test/Analysis/inline.cpp +++ b/test/Analysis/inline.cpp @@ -275,7 +275,7 @@ namespace DefaultArgs { clang_analyzer_eval(defaultReferenceZero(1) == -1); // expected-warning{{TRUE}} clang_analyzer_eval(defaultReferenceZero() == 0); // expected-warning{{TRUE}} -} + } double defaultFloatReference(const double &i = 42) { return -i; @@ -300,6 +300,13 @@ namespace DefaultArgs { clang_analyzer_eval(defaultString("xyz") == 'y'); // expected-warning{{TRUE}} clang_analyzer_eval(defaultString() == 'b'); // expected-warning{{TRUE}} } + + const void * const void_string = "abc"; + + void testBitcastedString() { + clang_analyzer_eval(0 != void_string); // expected-warning{{TRUE}} + clang_analyzer_eval('b' == ((char *)void_string)[1]); // expected-warning{{TRUE}} + } } namespace OperatorNew {