sp4r74n-117 updated this revision to Diff 132738. sp4r74n-117 added a comment.
Thanks for the feedback. I've added two additional tests to 'test_constant_p' for the case where an expression evaluating to a constant 0 is passed to the builtin. The existing tests have been refactored to check explicitly for 0 or 1 instead of relying on the implicit boolean conversion. https://reviews.llvm.org/D42745 Files: lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp test/Analysis/builtin-functions.cpp Index: test/Analysis/builtin-functions.cpp =================================================================== --- test/Analysis/builtin-functions.cpp +++ test/Analysis/builtin-functions.cpp @@ -64,3 +64,20 @@ // We give up the analysis on this path. } } + +void test_constant_p() { + int i = 1; + const int j = 2; + constexpr int k = 3; + clang_analyzer_eval(__builtin_constant_p(42) == 1); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(i) == 0); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(j) == 1); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(k) == 1); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(i + 42) == 0); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(j + 42) == 1); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(k + 42) == 1); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(" ") == 1); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(test_constant_p) == 0); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(k - 3) == 0); // expected-warning {{FALSE}} + clang_analyzer_eval(__builtin_constant_p(k - 3) == 1); // expected-warning {{TRUE}} +} Index: lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp +++ lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp @@ -113,6 +113,24 @@ C.addTransition(state->BindExpr(CE, LCtx, V)); return true; } + + case Builtin::BI__builtin_constant_p: { + SVal V; + SValBuilder& SVB = C.getSValBuilder(); + + llvm::APSInt Result; + // Model semantics as 'A return of 0 does not indicate that the value is + // not a constant, but merely that GCC cannot prove it is a constant [...]' + if (CE->EvaluateAsInt(Result, C.getASTContext(), Expr::SE_NoSideEffects)) { + SVB.getBasicValueFactory().getAPSIntType(CE->getType()).apply(Result); + V = SVB.makeIntVal(Result); + } + else + V = SVB.makeZeroVal(CE->getType()); + + C.addTransition(state->BindExpr(CE, LCtx, V)); + return true; + } } }
Index: test/Analysis/builtin-functions.cpp =================================================================== --- test/Analysis/builtin-functions.cpp +++ test/Analysis/builtin-functions.cpp @@ -64,3 +64,20 @@ // We give up the analysis on this path. } } + +void test_constant_p() { + int i = 1; + const int j = 2; + constexpr int k = 3; + clang_analyzer_eval(__builtin_constant_p(42) == 1); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(i) == 0); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(j) == 1); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(k) == 1); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(i + 42) == 0); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(j + 42) == 1); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(k + 42) == 1); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(" ") == 1); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(test_constant_p) == 0); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(k - 3) == 0); // expected-warning {{FALSE}} + clang_analyzer_eval(__builtin_constant_p(k - 3) == 1); // expected-warning {{TRUE}} +} Index: lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp +++ lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp @@ -113,6 +113,24 @@ C.addTransition(state->BindExpr(CE, LCtx, V)); return true; } + + case Builtin::BI__builtin_constant_p: { + SVal V; + SValBuilder& SVB = C.getSValBuilder(); + + llvm::APSInt Result; + // Model semantics as 'A return of 0 does not indicate that the value is + // not a constant, but merely that GCC cannot prove it is a constant [...]' + if (CE->EvaluateAsInt(Result, C.getASTContext(), Expr::SE_NoSideEffects)) { + SVB.getBasicValueFactory().getAPSIntType(CE->getType()).apply(Result); + V = SVB.makeIntVal(Result); + } + else + V = SVB.makeZeroVal(CE->getType()); + + C.addTransition(state->BindExpr(CE, LCtx, V)); + return true; + } } }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits