Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mimic GCC/Clang simplification behaviour when type checking ?: #7959

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 0 additions & 28 deletions regression/ansi-c/gcc_builtin_constant_p1/main.c

This file was deleted.

23 changes: 23 additions & 0 deletions regression/ansi-c/sizeof6/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
int main()
{
long long i;
#ifndef _MSC_VER
_Static_assert(sizeof(int) == sizeof(*(1 ? ((void *)(0ll)) : (int *)1)), "");
// We are able to simplify all of the expressions involving i below to 0, but
// GCC and Clang don't do so. Hence, the static asserts pass for those
// compilers.
_Static_assert(
sizeof(int) != sizeof(*(1 ? ((void *)(i * 0)) : (int *)1)), "");
_Static_assert(
sizeof(int) != sizeof(*(1 ? ((void *)(i - i)) : (int *)1)), "");
_Static_assert(
sizeof(int) != sizeof(*(1 ? ((void *)(i ? 0ll : 0ll)) : (int *)1)), "");
_Static_assert(
sizeof(int) != sizeof(*(1 ? ((void *)(0 ? i : 0ll)) : (int *)1)), "");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These appear to assert that some part of the subexpression is a compile time constant. May I suggest to use __builtin_constant_p for that. The sizeof assertion is a distraction.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This, I'm afraid, just uncovered another challenge: the above "true" cases aren't deemed null-pointer constants by the compilers (and, therefore, the type of the ?: is void* rather than int*). __builtin_constant_p, however, does return 1 for the very same expressions!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added a commit that better exercises (and extends) an existing test to also document (and test) these differences.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uhhh, sad

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth filing a bug report with those compilers.

#else
static_assert(sizeof(int) == sizeof(*(1 ? ((void *)(0)) : (int *)1)), "");
// Visual Studio rejects this as "illegal indirection"
// static_assert(
// sizeof(int) == sizeof(*(1 ? ((void *)(i * 0)) : (int *)1)), "");
#endif
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CORE gcc-only broken-test-c++-front-end
CORE
main.c

^EXIT=0$
Expand Down
47 changes: 47 additions & 0 deletions regression/cbmc/gcc_builtin_constant_p1/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include <assert.h>

#ifdef __GNUC__
enum
{
E1 = 1
} var;

struct whatnot
{
} whatnot_var;
#endif

int main()
{
// this is gcc only

#ifdef __GNUC__
assert(__builtin_constant_p("some string"));
assert(__builtin_constant_p(1.0f));
assert(__builtin_constant_p(E1));
assert(!__builtin_constant_p(var));
assert(!__builtin_constant_p(main));
assert(!__builtin_constant_p(whatnot_var));
assert(!__builtin_constant_p(&var));
assert(__builtin_constant_p(__builtin_constant_p(var)));

// The following are not constant expressions in the sense of the C standard
// and GCC wouldn't deem them constant expressions either, but they are
// subject to GCC's constant folding. See also regression test ansi-c/sizeof6.
// Clang's behaviour, however, is somewhat different. See
// https://github.com/llvm/llvm-project/issues/55946 for further examples of
// where they differ.
int j;
# ifndef __clang__
assert(__builtin_constant_p(j * 0));
assert(__builtin_constant_p(j - j));
assert(__builtin_constant_p(j ? 0ll : 0ll));
# endif
assert(__builtin_constant_p(0 ? j : 0ll));

// side-effects are _not_ evaluated
int i = 0;
assert(!__builtin_constant_p(i++));
assert(i == 0);
#endif
}
9 changes: 9 additions & 0 deletions regression/cbmc/gcc_builtin_constant_p1/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
CORE
main.c

^VERIFICATION SUCCESSFUL$
^EXIT=0$
^SIGNAL=0$
--
^warning: ignoring
^CONVERSION ERROR$
Loading