[PATCH] D42745: [analyzer] Add support for __builtin_constant_p to BuiltinFunctionChecker
This revision was automatically updated to reflect the committed changes. Closed by commit rL324789: [analyzer] Add support for __builtin_constant_p. (authored by dergachev, committed by ). Herald added a subscriber: llvm-commits. Changed prior to commit: https://reviews.llvm.org/D42745?vs=133447=133720#toc Repository: rL LLVM https://reviews.llvm.org/D42745 Files: cfe/trunk/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp cfe/trunk/test/Analysis/builtin-functions.cpp Index: cfe/trunk/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp === --- cfe/trunk/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp @@ -96,7 +96,8 @@ return true; } - case Builtin::BI__builtin_object_size: { + case Builtin::BI__builtin_object_size: + case Builtin::BI__builtin_constant_p: { // This must be resolvable at compile time, so we defer to the constant // evaluator for a value. SVal V = UnknownVal(); Index: cfe/trunk/test/Analysis/builtin-functions.cpp === --- cfe/trunk/test/Analysis/builtin-functions.cpp +++ cfe/trunk/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: cfe/trunk/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp === --- cfe/trunk/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp @@ -96,7 +96,8 @@ return true; } - case Builtin::BI__builtin_object_size: { + case Builtin::BI__builtin_object_size: + case Builtin::BI__builtin_constant_p: { // This must be resolvable at compile time, so we defer to the constant // evaluator for a value. SVal V = UnknownVal(); Index: cfe/trunk/test/Analysis/builtin-functions.cpp === --- cfe/trunk/test/Analysis/builtin-functions.cpp +++ cfe/trunk/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}} +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D42745: [analyzer] Add support for __builtin_constant_p to BuiltinFunctionChecker
This revision was automatically updated to reflect the committed changes. Closed by commit rC324789: [analyzer] Add support for __builtin_constant_p. (authored by dergachev, committed by ). Repository: rC Clang 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 @@ -96,7 +96,8 @@ return true; } - case Builtin::BI__builtin_object_size: { + case Builtin::BI__builtin_object_size: + case Builtin::BI__builtin_constant_p: { // This must be resolvable at compile time, so we defer to the constant // evaluator for a value. SVal V = UnknownVal(); 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 @@ -96,7 +96,8 @@ return true; } - case Builtin::BI__builtin_object_size: { + case Builtin::BI__builtin_object_size: + case Builtin::BI__builtin_constant_p: { // This must be resolvable at compile time, so we defer to the constant // evaluator for a value. SVal V = UnknownVal(); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D42745: [analyzer] Add support for __builtin_constant_p to BuiltinFunctionChecker
sp4r74n-117 added a comment. I do not have commit access so it would be great if you could do it for me. Thanks. https://reviews.llvm.org/D42745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D42745: [analyzer] Add support for __builtin_constant_p to BuiltinFunctionChecker
NoQ added a comment. Do you have commit access, or do you want me to commit this for you? https://reviews.llvm.org/D42745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D42745: [analyzer] Add support for __builtin_constant_p to BuiltinFunctionChecker
NoQ accepted this revision. NoQ added a comment. This revision is now accepted and ready to land. Tests look good. You can't test deadcode :) https://reviews.llvm.org/D42745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D42745: [analyzer] Add support for __builtin_constant_p to BuiltinFunctionChecker
sp4r74n-117 updated this revision to Diff 133447. sp4r74n-117 added a comment. Thanks for the explanation, seems like I was on the wrong track. I now do realize that my initial approach was in fact duplicating the logic of 'BI__builtin_object_size'. I've removed most of the changes applied to the checker and extended the 'case' instead. What remains is the regression test tho. 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 @@ -97,7 +97,8 @@ return true; } - case Builtin::BI__builtin_object_size: { + case Builtin::BI__builtin_object_size: + case Builtin::BI__builtin_constant_p: { // This must be resolvable at compile time, so we defer to the constant // evaluator for a value. SVal V = UnknownVal(); 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 @@ -97,7 +97,8 @@ return true; } - case Builtin::BI__builtin_object_size: { + case Builtin::BI__builtin_object_size: + case Builtin::BI__builtin_constant_p: { // This must be resolvable at compile time, so we defer to the constant // evaluator for a value. SVal V = UnknownVal(); ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D42745: [analyzer] Add support for __builtin_constant_p to BuiltinFunctionChecker
NoQ added a comment. Oh, i see what you did here. I thought you're evaluating the argument, but you're evaluating the whole builtin function call. In this case you don't need the else-branch: `EvaluateAsInt` will always succeed. Moreover, you can merge your code with the `BI__builtin_object_size` case, which is also fully evaluated at compile-time. Actually, maybe we should use that approach to evaluate more builtin functions, and all C++ //constexpr// function calls as well, in the engine or in a checker. It would be a nice thing to tackle eventually. https://reviews.llvm.org/D42745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D42745: [analyzer] Add support for __builtin_constant_p to BuiltinFunctionChecker
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 =
[PATCH] D42745: [analyzer] Add support for __builtin_constant_p to BuiltinFunctionChecker
NoQ added a comment. Nice, thanks! Comment at: lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp:126 + SVB.getBasicValueFactory().getAPSIntType(CE->getType()).apply(Result); + V = SVB.makeIntVal(Result); +} https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index-_005f_005fbuiltin_005fconstant_005fp > The function returns the integer 1 if the argument is known to be a > compile-time constant I don't think it returns the constant value to which the expression has evaluated. Could you add a test in which the expression evaluates to a constant and this constant is 0? Repository: rC Clang https://reviews.llvm.org/D42745 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D42745: [analyzer] Add support for __builtin_constant_p to BuiltinFunctionChecker
sp4r74n-117 created this revision. sp4r74n-117 added reviewers: george.karpenkov, dcoughlin, dergachev.a. sp4r74n-117 created this object with visibility "All Users". Herald added subscribers: cfe-commits, a.sidorin, szepet, xazax.hun. Added evaluation of __builtin_constant_p to the dedicated StaticAnalyzer checker along with a test case. Tested via: make clang-test Repository: rC Clang 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,18 @@ // 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)); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(i)); // expected-warning {{FALSE}} + clang_analyzer_eval(__builtin_constant_p(j)); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(k)); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(i + 42)); // expected-warning {{FALSE}} + clang_analyzer_eval(__builtin_constant_p(j + 42)); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(k + 42)); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(" ")); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(test_constant_p)); // expected-warning {{FALSE}} +} 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,18 @@ // 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)); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(i)); // expected-warning {{FALSE}} + clang_analyzer_eval(__builtin_constant_p(j)); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(k)); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(i + 42)); // expected-warning {{FALSE}} + clang_analyzer_eval(__builtin_constant_p(j + 42)); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(k + 42)); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(" ")); // expected-warning {{TRUE}} + clang_analyzer_eval(__builtin_constant_p(test_constant_p)); // expected-warning {{FALSE}} +} 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