ygribov created this revision. ygribov added reviewers: zaks.anna, dcoughlin, jordan_rose. ygribov added a subscriber: cfe-commits.
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. http://reviews.llvm.org/D14652 Files: lib/StaticAnalyzer/Core/SValBuilder.cpp test/Analysis/inline.cpp Index: test/Analysis/inline.cpp =================================================================== --- test/Analysis/inline.cpp +++ test/Analysis/inline.cpp @@ -275,7 +275,7 @@ 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 @@ 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(0 != ((char *)void_string)[1]); // expected-warning{{TRUE}} + } } namespace OperatorNew { Index: lib/StaticAnalyzer/Core/SValBuilder.cpp =================================================================== --- lib/StaticAnalyzer/Core/SValBuilder.cpp +++ lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -275,11 +275,17 @@ case Stmt::ImplicitCastExprClass: { const CastExpr *CE = cast<CastExpr>(E); - if (CE->getCastKind() == CK_ArrayToPointerDecay) { - Optional<SVal> ArrayVal = getConstantVal(CE->getSubExpr()); - if (!ArrayVal) + switch (CE->getCastKind()) { + default: + break; + case CK_ArrayToPointerDecay: + case CK_BitCast: { + const Expr *SE = CE->getSubExpr(); + Optional<SVal> Val = getConstantVal(SE); + if (!Val) return None; - return evalCast(*ArrayVal, CE->getType(), CE->getSubExpr()->getType()); + return evalCast(*Val, CE->getType(), SE->getType()); + } } // FALLTHROUGH }
Index: test/Analysis/inline.cpp =================================================================== --- test/Analysis/inline.cpp +++ test/Analysis/inline.cpp @@ -275,7 +275,7 @@ 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 @@ 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(0 != ((char *)void_string)[1]); // expected-warning{{TRUE}} + } } namespace OperatorNew { Index: lib/StaticAnalyzer/Core/SValBuilder.cpp =================================================================== --- lib/StaticAnalyzer/Core/SValBuilder.cpp +++ lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -275,11 +275,17 @@ case Stmt::ImplicitCastExprClass: { const CastExpr *CE = cast<CastExpr>(E); - if (CE->getCastKind() == CK_ArrayToPointerDecay) { - Optional<SVal> ArrayVal = getConstantVal(CE->getSubExpr()); - if (!ArrayVal) + switch (CE->getCastKind()) { + default: + break; + case CK_ArrayToPointerDecay: + case CK_BitCast: { + const Expr *SE = CE->getSubExpr(); + Optional<SVal> Val = getConstantVal(SE); + if (!Val) return None; - return evalCast(*ArrayVal, CE->getType(), CE->getSubExpr()->getType()); + return evalCast(*Val, CE->getType(), SE->getType()); + } } // FALLTHROUGH }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits