[Bug c/103310] null comparison with a weak symbol eliminated

2021-12-01 Thread cvs-commit at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103310

--- Comment #3 from CVS Commits  ---
The master branch has been updated by Jason Merrill :

https://gcc.gnu.org/g:53caa4723d8de73fe21e63ba264082f3071b2887

commit r12-5696-g53caa4723d8de73fe21e63ba264082f3071b2887
Author: Jason Merrill 
Date:   Wed Nov 24 05:45:02 2021 -0500

c++: constexpr, fold, weak redecl, fp/0 [PR103310]

For PR61825, honza changed tree_single_nonzero_warnv_p to prevent a later
declaration from marking a function as weak after we've determined that it
wasn't weak before.  But we shouldn't do that for speculative folding; we
should only do it when we actually need a constant value.  In C++, such a
context is called "manifestly constant-evaluated".  In fold, this seems to
correspond to the folding_initializer flag, since in C this situation only
occurs in static initializers.

This change makes nonzero-1.c well-formed; I've added a nonzero-1a.c to
verify that we delete the null check eventually if there is no weak
redeclaration.

The varasm.c change is so that if we do get the weak redeclaration error,
we
get it at the position of the weak declaration rather than the previous
declaration.

Using the FOLD_INIT paths also affects floating point arithmetic: notably,
this makes floating point division by zero in a manifestly
constant-evaluated context constant, as in a C static initializer.  I've
had
some success convincing CWG that this is the right direction; C++ should
follow C's floating point semantics more than we have been doing, and
Joseph
says that the C policy is that Annex F overrides other parts of the
standard
that say that some operations are undefined.  But since we're in stage 3,
I'm only making this change with the new flag -fconstexpr-fp-except.  It
may
turn on by default in a future release.

I think this distinction is only relevant for binary operations; arithmetic
for the floating point case, comparison for possibly non-zero addresses.

PR c++/103310

gcc/ChangeLog:

* fold-const.c (maybe_nonzero_address): Use get_create or get
depending on folding_initializer.
(fold_binary_initializer_loc): New.
* fold-const.h (fold_binary_initializer_loc): Declare.
* varasm.c (mark_weak): Don't use the decl location.
* doc/invoke.texi: Document -fconstexpr-fp-except.

gcc/c-family/ChangeLog:

* c.opt: Add -fconstexpr-fp-except.

gcc/cp/ChangeLog:

* constexpr.c (cxx_eval_binary_expression): Use
fold_binary_initializer_loc if manifestly cxeval.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-fp-except1.C: New test.
* g++.dg/cpp1z/constexpr-if36.C: New test.
* gcc.dg/tree-ssa/nonzero-1.c: Now well-formed.
* gcc.dg/tree-ssa/nonzero-1a.c: New test.

[Bug c/103310] null comparison with a weak symbol eliminated

2021-11-18 Thread jason at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103310

Jason Merrill  changed:

   What|Removed |Added

 Status|UNCONFIRMED |NEW
 Ever confirmed|0   |1
 CC||jason at gcc dot gnu.org
   Last reconfirmed||2021-11-18

--- Comment #2 from Jason Merrill  ---
The C++ front end rejects the testcase with "declared weak after used".  We set
refuse_visibility_changes under fold's tree_single_nonzero_warnv_p. 

Changing get_create to get in maybe_nonzero_address makes the C++ compiler
accept the testcase, and properly test whether alias is null.

This issue seems to go back to Honza's r5-3627, which changed symtab_node::get
to symtab_node::get_create in the code that became maybe_nonzero_address, so
that we decide early whether a particular function is weak or not.

This was done so that constant-evaluation could properly decide that the
address of a function is non-null.  But it's harmful when we do that for
speculative folding; we should only return a definitive answer, and set
refuse_visibility_changes, when a constant result is required.

It seems we need a way to tell fold that we really want a constant value, have
the C++ front end set that for manifestly-constant-evaluated expressions, and
only use get_create in that case.

But I also guess the issue that the C front end is both optimizing away the
test and not setting refuse_visibility_changes is a C front end issue, that
it's doing the optimization without involving fold.

[Bug c/103310] null comparison with a weak symbol eliminated

2021-11-17 Thread msebor at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103310

Martin Sebor  changed:

   What|Removed |Added

  Component|middle-end  |c

--- Comment #1 from Martin Sebor  ---
The test case below shows that storing the address of the alias in a local
pointer avoids the problem.  The dumps show that the problem is in the front
end which folds the test of the address of the weak symbol to true.

$ cat pr103310.c && gcc -Wall -O2 -S -fdump-tree-original=/dev/stdout
-fdump-tree-optimized=/dev/stdout pr103310.c
extern void alias (void);

void call_alias (void)
{
  __builtin_printf ("in %s: alias = %p\n", __func__, alias);

  if (alias)
alias ();
}

void call_ptr_alias (void)
{
  void (*p)(void) = alias;

  __builtin_printf ("in %s: alias = %p\n", __func__, p);

  if (p)
p ();
}

extern void alias (void)  __attribute__((weak));
pr103310.c: In function ‘call_alias’:
pr103310.c:7:7: warning: the address of ‘alias’ will always evaluate as ‘true’
[-Waddress]
7 |   if (alias)
  |   ^

;; Function call_alias (null)
;; enabled by -tree-original


{
  static const char __func__[11] = "call_alias";

static const char __func__[11] = "call_alias";
  __builtin_printf ((const char *) "in %s: alias = %p\n", (const char *)
&__func__, alias);
  if (1)
{
  alias ();
}
}


;; Function call_ptr_alias (null)
;; enabled by -tree-original


{
  void (*) (void) p = alias;
  static const char __func__[15] = "call_ptr_alias";

static const char __func__[15] = "call_ptr_alias";
void (*) (void) p = alias;
  __builtin_printf ((const char *) "in %s: alias = %p\n", (const char *)
&__func__, p);
  if (p != 0B)
{
  p ();
}
}


;; Function call_alias (call_alias, funcdef_no=0, decl_uid=1945, cgraph_uid=1,
symbol_order=0)

void call_alias ()
{
  static const char __func__[11] = "call_alias";

   [local count: 1073741824]:
  __builtin_printf ("in %s: alias = %p\n", &__func__, alias);
  alias (); [tail call]
  return;

}



;; Function call_ptr_alias (call_ptr_alias, funcdef_no=1, decl_uid=1949,
cgraph_uid=2, symbol_order=1)

Removing basic block 5
void call_ptr_alias ()
{
  static const char __func__[15] = "call_ptr_alias";

   [local count: 1073741824]:
  __builtin_printf ("in %s: alias = %p\n", &__func__, alias);
  if (alias != 0B)
goto ; [53.47%]
  else
goto ; [46.53%]

   [local count: 574129753]:
  alias (); [tail call]

   [local count: 1073741824]:
  return;

}