[PATCH] D42745: [analyzer] Add support for __builtin_constant_p to BuiltinFunctionChecker

2018-02-09 Thread Phabricator via Phabricator via cfe-commits
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

2018-02-09 Thread Phabricator via Phabricator via cfe-commits
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

2018-02-09 Thread Felix Kostenzer via Phabricator via cfe-commits
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

2018-02-08 Thread Artem Dergachev via Phabricator via cfe-commits
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

2018-02-08 Thread Artem Dergachev via Phabricator via cfe-commits
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

2018-02-08 Thread Felix Kostenzer via Phabricator via cfe-commits
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

2018-02-05 Thread Artem Dergachev via Phabricator via cfe-commits
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

2018-02-03 Thread Felix Kostenzer via Phabricator via cfe-commits
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

2018-01-31 Thread Artem Dergachev via Phabricator via cfe-commits
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

2018-01-31 Thread Felix Kostenzer via Phabricator via cfe-commits
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