Page MenuHomePhabricator

[analyzer] When failing to evaluate a __builtin_constant_p, presume it's false.

Authored by NoQ on Apr 1 2019, 7:45 PM.



__builtin_constant_p(x) is a compiler builtin that evaluates to 1 when its argument x is a compile-time constant and to 0 otherwise. In CodeGen it is simply lowered to the respective LLVM intrinsic. In the Analyzer we've been trying to delegate modeling to Expr::EvaluateAsInt, which can sometimes fail simply because the expression is too complicated.

When it fails, let's conservatively return false. The behavior of this builtin is so unpredictable (in fact, it even depends on optimization level) that any code that's using the builtin should expect anything except maybe a concrete integer to be described by it as "not a constant". Therefore, returning "false" when we're unsure is unlikely to trigger weird execution paths in the code, while returning "unknown (potentially true)" may do so. Which is something i've just seen on some real-world code within a weird macro expansion that tries to emulate compile-time assertions in C by declaring arrays of size -1 when it fails, which triggers the VLA checker to warn if "-1" wasn't in fact a constant. Something like this:

if (__builtin_constant_p((p == 0))) { // EvaluateAsInt returns Unknown here.
  char __compile_time_assert__[((p == 0)) ? 1 : -1]; // Warning: array of size -1.

Diff Detail


Event Timeline

NoQ created this revision.Apr 1 2019, 7:45 PM
Herald added a project: Restricted Project. · View Herald TranscriptApr 1 2019, 7:45 PM
Szelethus accepted this revision.Apr 2 2019, 4:40 AM


This revision is now accepted and ready to land.Apr 2 2019, 4:40 AM
This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptApr 2 2019, 6:54 PM