C++ ObjC++ Joined RejectNegative UInteger Var(constexpr_cache_depth) Init(8)
-fconstexpr-cache-depth=<number> Specify maximum constexpr recursion cache depth.
+fconstexpr-fp-except
+C++ ObjC++ Var(flag_constexpr_fp_except) Init(0)
+Allow IEC559 floating point exceptions in constant expressions.
+
fconstexpr-loop-limit=
C++ ObjC++ Joined RejectNegative UInteger Var(constexpr_loop_limit) Init(262144)
-fconstexpr-loop-limit=<number> Specify maximum constexpr loop iteration count.
}
if (r == NULL_TREE)
- r = fold_binary_loc (loc, code, type, lhs, rhs);
+ {
+ if (ctx->manifestly_const_eval
+ && (flag_constexpr_fp_except
+ || TREE_CODE (type) != REAL_TYPE))
+ r = fold_binary_initializer_loc (loc, code, type, lhs, rhs);
+ else
+ r = fold_binary_loc (loc, code, type, lhs, rhs);
+ }
if (r == NULL_TREE
&& (code == LSHIFT_EXPR || code == RSHIFT_EXPR)
constexpr calculations you might want to experiment to find which
value works best for you.
+@item -fconstexpr-fp-except
+@opindex fconstexpr-fp-except
+Annex F of the C standard specifies that IEC559 floating point
+exceptions encountered at compile time should not stop compilation.
+C++ compilers have historically not followed this guidance, instead
+treating floating point division by zero as non-constant even though
+it has a well defined value. This flag tells the compiler to give
+Annex F priority over other rules saying that a particular operation
+is undefined.
+
+@smallexample
+constexpr float inf = 1./0.; // OK with -fconstexpr-fp-except
+@end smallexample
+
@item -fconstexpr-loop-limit=@var{n}
@opindex fconstexpr-loop-limit
Set the maximum number of iterations for a loop in C++14 constexpr functions
#include "asan.h"
#include "gimple-range.h"
-/* Nonzero if we are folding constants inside an initializer; zero
- otherwise. */
+/* Nonzero if we are folding constants inside an initializer or a C++
+ manifestly-constant-evaluated context; zero otherwise. */
int folding_initializer = 0;
/* The following constants represent a bit based encoding of GCC's
static int
maybe_nonzero_address (tree decl)
{
+ /* Normally, don't do anything for variables and functions before symtab is
+ built; it is quite possible that DECL will be declared weak later.
+ But if folding_initializer, we need a constant answer now, so create
+ the symtab entry and prevent later weak declaration. */
if (DECL_P (decl) && decl_in_symtab_p (decl))
- if (struct symtab_node *symbol = symtab_node::get_create (decl))
+ if (struct symtab_node *symbol
+ = (folding_initializer
+ ? symtab_node::get_create (decl)
+ : symtab_node::get (decl)))
return symbol->nonzero_address ();
/* Function local objects are never NULL. */
return result;
}
+tree
+fold_binary_initializer_loc (location_t loc, tree_code code, tree type,
+ tree lhs, tree rhs)
+{
+ tree result;
+ START_FOLD_INIT;
+
+ result = fold_binary_loc (loc, code, type, lhs, rhs);
+
+ END_FOLD_INIT;
+ return result;
+}
+
#undef START_FOLD_INIT
#undef END_FOLD_INIT
#define fold_build_call_array_initializer(T1,T2,N,T4)\
fold_build_call_array_initializer_loc (UNKNOWN_LOCATION, T1, T2, N, T4)
extern tree fold_build_call_array_initializer_loc (location_t, tree, tree, int, tree *);
+extern tree fold_binary_initializer_loc (location_t, tree_code, tree, tree, tree);
extern tree get_array_ctor_element_at_index (tree, offset_int,
unsigned * = NULL);
extern bool fold_convertible_p (const_tree, const_tree);
--- /dev/null
+// { dg-do compile { target c++11 } }
+// { dg-additional-options -fconstexpr-fp-except }
+
+constexpr double inf = 1./0.;
--- /dev/null
+// PR c++/103310
+// Test that only manifestly-constant-evaluated comparisons lock a symbol's
+// weakness.
+
+// { dg-do compile { target c++17 } }
+
+extern void weakfn1 (void);
+extern void weakfn2 (void);
+
+void call_weakfn (void)
+{
+ if (weakfn1)
+ weakfn1 ();
+ if constexpr (weakfn2)
+ weakfn2 ();
+}
+
+extern void weakfn1 (void) __attribute__((weak));
+extern void weakfn2 (void) __attribute__((weak)); // { dg-error "declared weak after being used" }
/* { dg-do compile } */
-/* { dg-options "-O2 -fdelete-null-pointer-checks" } */
+/* { dg-options "-O2 -fdelete-null-pointer-checks -fdump-tree-optimized" } */
/* { dg-require-weak "" } */
/* { dg-skip-if "" keeps_null_pointer_checks } */
-extern int a; /* { dg-error "declared weak after being used" } */
+extern int a;
int
t()
{
+ /* { dg-final { scan-tree-dump "&a != 0" "optimized" } } */
return &a!=0;
}
extern int a __attribute__ ((weak));
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdelete-null-pointer-checks -fdump-tree-optimized" } */
+
+/* { dg-skip-if "" keeps_null_pointer_checks } */
+extern int a;
+int
+t()
+{
+ /* { dg-final { scan-tree-dump-not "&a != 0" "optimized" } } */
+ return &a!=0;
+}
struct symtab_node *n = symtab_node::get (decl);
if (n && n->refuse_visibility_changes)
- error ("%+qD declared weak after being used", decl);
+ error ("%qD declared weak after being used", decl);
DECL_WEAK (decl) = 1;
if (DECL_RTL_SET_P (decl)