FNDECL_MANIFESTLY_CONST_EVALUATED (in FUNCTION_DECL)
TARGET_EXPR_INTERNAL_P (in TARGET_EXPR)
CONTRACT_CONST (in ASSERTION_, PRECONDITION_, POSTCONDITION_STMT)
+ DECL_HAS_DEFAULT_ARGUMENT_P (in PARM_DECL)
5: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
FUNCTION_RVALUE_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE)
CALL_EXPR_REVERSE_ARGS (in CALL_EXPR, AGGR_INIT_EXPR)
#define MULTIPLE_NAMES_PARM_P(NODE) \
TREE_LANG_FLAG_2 (PARM_DECL_CHECK (NODE))
+/* Nonzero for PARM_DECL node means that at least one block scope extern
+ for the corresponding FUNCTION_DECL provided default argument for this
+ parameter. */
+#define DECL_HAS_DEFAULT_ARGUMENT_P(NODE) \
+ TREE_LANG_FLAG_4 (PARM_DECL_CHECK (NODE))
+
/* Nonzero for a FIELD_DECL who's NSMDI is currently being
instantiated. */
#define DECL_INSTANTIATING_NSDMI_P(NODE) \
merge_decl_arguments (tree newdecl, tree olddecl, bool new_defines_function,
bool types_match, bool extern_alias)
{
- tree oldarg, newarg;
+ tree oldarg, newarg, type = NULL_TREE;
+ tree first_user_parm = NULL_TREE;
+ if (extern_alias)
+ first_user_parm = FUNCTION_FIRST_USER_PARM (newdecl);
for (oldarg = DECL_ARGUMENTS (olddecl), newarg = DECL_ARGUMENTS (newdecl);
oldarg && newarg;
oldarg = DECL_CHAIN (oldarg), newarg = DECL_CHAIN (newarg))
we should do that for the function itself, not just parameters. */
if (!extern_alias || flag_reflection)
DECL_ATTRIBUTES (oldarg) = DECL_ATTRIBUTES (newarg);
+ if (!flag_reflection)
+ continue;
+ /* For extern_alias set DECL_HAS_DEFAULT_ARGUMENT_P on oldarg
+ if the local extern has a default argument for that parameter. */
+ if (extern_alias)
+ {
+ if (newarg == first_user_parm)
+ type = FUNCTION_FIRST_USER_PARMTYPE (newdecl);
+ else if (type)
+ type = TREE_CHAIN (type);
+ if (type && TREE_PURPOSE (type))
+ DECL_HAS_DEFAULT_ARGUMENT_P (oldarg) = 1;
+ }
+ else
+ {
+ /* Otherwise propagate the flag. */
+ if (DECL_HAS_DEFAULT_ARGUMENT_P (oldarg))
+ DECL_HAS_DEFAULT_ARGUMENT_P (newarg) = 1;
+ if (DECL_HAS_DEFAULT_ARGUMENT_P (newarg))
+ DECL_HAS_DEFAULT_ARGUMENT_P (oldarg) = 1;
+ }
/* Merge names for std::meta::has_identifier and
std::meta::{,u8}identifier_of purposes. If they are different and
both oldarg and newarg are named, add flag to force that
unnamed, if neither is a olddecl nor newdecl is definition, propagate
DECL_NAME to both. Otherwise stash the old name into "old parm name"
artificial attribute. */
- if (flag_reflection && DECL_NAME (oldarg) != DECL_NAME (newarg))
+ if (DECL_NAME (oldarg) != DECL_NAME (newarg))
{
if (DECL_NAME (oldarg) && DECL_NAME (newarg))
{
t = dtor;
}
+ /* Look through block scope externs. */
+ if (VAR_OR_FUNCTION_DECL_P (t) && DECL_LOCAL_DECL_P (t))
+ t = DECL_LOCAL_DECL_ALIAS (t);
+
if (t == error_mark_node)
return error_mark_node;
if (eval_is_function_parameter (r, kind) == boolean_false_node)
return boolean_false_node;
r = maybe_update_function_parm (r);
+ if (DECL_HAS_DEFAULT_ARGUMENT_P (r))
+ return boolean_true_node;
tree fn = DECL_CONTEXT (r);
tree args = FUNCTION_FIRST_USER_PARM (fn);
tree types = FUNCTION_FIRST_USER_PARMTYPE (fn);
--- /dev/null
+// PR c++/123612
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+#include <meta>
+
+int a;
+extern int b;
+int foo (int x, int y, int z = 42);
+
+consteval auto
+bar ()
+{
+ extern int a;
+ return ^^a;
+}
+
+consteval auto
+baz ()
+{
+ extern int b;
+ return ^^b;
+}
+
+consteval auto
+qux ()
+{
+ static_assert (!has_default_argument (parameters_of (^^foo)[0]));
+ static_assert (!has_default_argument (parameters_of (^^foo)[1]));
+ static_assert (has_default_argument (parameters_of (^^foo)[2]));
+ {
+ extern int foo (int x, int y = 5, int z = 16);
+ static_assert (!has_default_argument (parameters_of (^^foo)[0]));
+ static_assert (has_default_argument (parameters_of (^^foo)[1]));
+ static_assert (has_default_argument (parameters_of (^^foo)[2]));
+ return ^^foo;
+ }
+}
+
+static_assert (^^a == bar ());
+static_assert (^^b == baz ());
+static_assert (^^foo == qux ());
+static_assert (!has_default_argument (parameters_of (^^foo)[0]));
+static_assert (has_default_argument (parameters_of (^^foo)[1]));
+static_assert (has_default_argument (parameters_of (^^foo)[2]));