diff --git a/src/interpret.c b/src/interpret.c index d8b2ab9c5a..4a0f0508c5 100644 --- a/src/interpret.c +++ b/src/interpret.c @@ -25681,59 +25681,16 @@ compound statement of that handler. goto continue_mem_inits; } /* if */ - /* Retrieve the routine scope, or issue an error. */ if (callee == NULL) { info_with_pos(ec_constexpr_expression_cannot_be_interpreted, pos, ips); do_constexpr_fail(result); goto done; - } else if (!callee->is_constexpr) { - info_with_pos_sym(ec_constexpr_call_to_nonconstexpr_function, - pos, symbol_for(callee), ips); - do_constexpr_fail(result); - goto done; - } /* if */ - if (!callee->defined) { - if (has_routine_definition_from_module(callee)) { - /* The definition was stored in a module file. */ - if (!load_routine_definition_from_module(callee)) { - ips->input_error = TRUE; - do_constexpr_fail(result); - } /* if */ - } else if ((callee->is_inheriting_ctor || callee->compiler_generated) && - !callee->is_deleted) { - force_definition_of_compiler_generated_routine(callee); - } else { - set_instance_required(symbol_for(callee), TRUE, SIR_CONSTANT_CONTEXT); - } /* if */ - } /* if */ - if (callee->function_def_number == NULL_function_def_number) { - info_with_pos_sym(ec_constexpr_function_undefined, pos, - symbol_for(callee), ips); - do_constexpr_fail(result); - if (callee->is_deleted && ips->is_constant_evaluated) { - /* An error has presumably been issued earlier (use of a deleted - function). Treat this as an input error to avoid extraneous - diagnostics. */ - expect_error(); - ips->input_error = TRUE; - } /* if */ - goto done; - } else if (callee->is_prototype_instantiation) { - info_with_pos_sym(ec_constexpr_call_not_interpretable, pos, - symbol_for(callee), ips); - do_constexpr_fail(result); - goto done; - } else if (cost_exceeded(ips)) { - report_excessive_cost(ips); - do_constexpr_fail(result); - goto done; } else { a_byte *result_storage = cap.address; a_byte *complete_object = cap.complete_object; - a_scope_ptr callee_scope = scope_for_routine(callee); + a_scope_ptr callee_scope; an_expr_node_ptr args = dip->variant.constructor.args, arg; - a_variable_ptr params = callee_scope->variant.routine.parameters, - param, this_var; + a_variable_ptr params, param, this_var; a_base_class_ptr bcp; a_byte_count n_args = 1, n_params = 1; a_byte_count *arg_size; @@ -25741,23 +25698,6 @@ compound statement of that handler. an_alloc_seq_number alloc_seq_number; a_type_ptr class_type = parent_class_of(callee); unsigned long up_front_cost; - /* Don't attempt to interpret a non-constexpr function. The flag - scope->is_constexpr_routine is set at the end of a constexpr function - definition, so this also prevents the interpretation of a function that - is not fully parsed (e.g., requested due to a recursive call in a - constexpr function). */ - if (!callee_scope->is_constexpr_routine) { - do_constexpr_fail(result); - info_with_pos_sym(ec_constexpr_call_not_interpretable, pos, - symbol_for(callee), ips); - goto done; - } /* if */ - if (class_type->variant.class_struct_union.any_virtual_base_classes) { - do_constexpr_fail(result); - info_with_pos_type(ec_constexpr_object_with_virtual_base, pos, - class_type, ips); - goto done; - } /* if */ /* Set up arguments, starting with "this" if applicable. */ /* This process must happen in two phases. First, the arguments must be allocated and evaluated. Only then can we map parameter variables onto @@ -25775,17 +25715,9 @@ compound statement of that handler. result = FALSE; goto done; } /* if */ - /* Count the parameters (including "this") to make sure there are enough - arguments for the parameters. */ - for (param = params; param != NULL; param = param->next) { - n_params += 1; - } /* if */ - if (n_args < n_params) { - info_with_pos(ec_too_few_arguments, pos, ips); - do_constexpr_fail(result); - goto done; - } /* if */ - /* Phase 1: Allocate and evaluate the arguments. */ + /* Phase 1: Allocate and evaluate the arguments. That precedes the checks + of the constructor below: If the evaluation of an argument exits by + throwing an exception, the constructor is not invoked. */ /* The "+1" below is to account for the "this" pointer (handled later). */ p_arg_ptr = (a_byte**)arg_ptrs+1; arg_size = (a_byte_count*)arg_sizes; @@ -25794,13 +25726,16 @@ compound statement of that handler. /* The first non-this argument is implicit (i.e., not represented in the IL). Since it always corresponds to the reference parameter of a copy/move constructor, we know it is a constexpr address. */ + a_type_ptr routine_type = skip_typerefs(callee->type); + a_type_ptr param_type = routine_type->variant.routine.extra_info-> + param_type_list->type; a_byte_count n_bytes = sizeof(a_constexpr_address); a_byte *arg_bytes; do_host_alignment(&n_bytes); *arg_size = n_bytes; arg_size += 1; n_bytes += sizeof(a_var_postfix); - if (!alloc_complete_object(ips, n_bytes, params->type, arg_bytes)) { + if (!alloc_complete_object(ips, n_bytes, param_type, arg_bytes)) { goto done; } /* if */ *(a_constexpr_address*)arg_bytes = *implied_src; @@ -25863,6 +25798,79 @@ compound statement of that handler. goto done; } /* if */ } /* for */ + /* Check that the constructor can be interpreted, and retrieve its routine + scope. */ + if (!callee->is_constexpr) { + info_with_pos_sym(ec_constexpr_call_to_nonconstexpr_function, + pos, symbol_for(callee), ips); + do_constexpr_fail(result); + goto done; + } /* if */ + if (!callee->defined) { + if (has_routine_definition_from_module(callee)) { + /* The definition was stored in a module file. */ + if (!load_routine_definition_from_module(callee)) { + ips->input_error = TRUE; + do_constexpr_fail(result); + } /* if */ + } else if ((callee->is_inheriting_ctor || callee->compiler_generated) && + !callee->is_deleted) { + force_definition_of_compiler_generated_routine(callee); + } else { + set_instance_required(symbol_for(callee), TRUE, SIR_CONSTANT_CONTEXT); + } /* if */ + } /* if */ + if (callee->function_def_number == NULL_function_def_number) { + info_with_pos_sym(ec_constexpr_function_undefined, pos, + symbol_for(callee), ips); + do_constexpr_fail(result); + if (callee->is_deleted && ips->is_constant_evaluated) { + /* An error has presumably been issued earlier (use of a deleted + function). Treat this as an input error to avoid extraneous + diagnostics. */ + expect_error(); + ips->input_error = TRUE; + } /* if */ + goto done; + } else if (callee->is_prototype_instantiation) { + info_with_pos_sym(ec_constexpr_call_not_interpretable, pos, + symbol_for(callee), ips); + do_constexpr_fail(result); + goto done; + } else if (cost_exceeded(ips)) { + report_excessive_cost(ips); + do_constexpr_fail(result); + goto done; + } /* if */ + callee_scope = scope_for_routine(callee); + params = callee_scope->variant.routine.parameters; + /* Don't attempt to interpret a non-constexpr function. The flag + scope->is_constexpr_routine is set at the end of a constexpr function + definition, so this also prevents the interpretation of a function that + is not fully parsed (e.g., requested due to a recursive call in a + constexpr function). */ + if (!callee_scope->is_constexpr_routine) { + do_constexpr_fail(result); + info_with_pos_sym(ec_constexpr_call_not_interpretable, pos, + symbol_for(callee), ips); + goto done; + } /* if */ + if (class_type->variant.class_struct_union.any_virtual_base_classes) { + do_constexpr_fail(result); + info_with_pos_type(ec_constexpr_object_with_virtual_base, pos, + class_type, ips); + goto done; + } /* if */ + /* Count the parameters (including "this") to make sure there are enough + arguments for the parameters. */ + for (param = params; param != NULL; param = param->next) { + n_params += 1; + } /* if */ + if (n_args < n_params) { + info_with_pos(ec_too_few_arguments, pos, ips); + do_constexpr_fail(result); + goto done; + } /* if */ /* Phase 2: Map the parameters to the arguments. */ /* Associate with the parameter variables a new allocation number. For ordinary calls, we just use the allocation number about to be created diff --git a/tests/tests/imported/clang/cpp/SemaCXX/.cxx0x-initializer-stdinitializerlist.rto/default.1.1.txt b/tests/tests/imported/clang/cpp/SemaCXX/.cxx0x-initializer-stdinitializerlist.rto/default.1.1.txt index cfb2316e3a..f0ba66c15f 100644 --- a/tests/tests/imported/clang/cpp/SemaCXX/.cxx0x-initializer-stdinitializerlist.rto/default.1.1.txt +++ b/tests/tests/imported/clang/cpp/SemaCXX/.cxx0x-initializer-stdinitializerlist.rto/default.1.1.txt @@ -112,7 +112,7 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers "Test_name.c", line 314: error: expression must have a constant value constexpr int k = f( // expected-error {{must be initialized by a constant expression}} ^ -"Test_name.c", line 317: note: cannot call non-constexpr function "TemporaryInitListSourceRange_PR22367::A::A(std::initializer_list)" (declared at line 311) +"Test_name.c", line 317: note: cannot call non-constexpr function "std::initializer_list<_E>::initializer_list(const _E *, std::size_t) [with _E=int]" (declared at line 34) std::initializer_list // expected-note {{constructor}} ^ diff --git a/tests/tests/imported/clang/cpp/SemaCXX/.cxx0x-initializer-stdinitializerlist.rto/default.2.1.txt b/tests/tests/imported/clang/cpp/SemaCXX/.cxx0x-initializer-stdinitializerlist.rto/default.2.1.txt index 148b135dfd..e6fb5fcde4 100644 --- a/tests/tests/imported/clang/cpp/SemaCXX/.cxx0x-initializer-stdinitializerlist.rto/default.2.1.txt +++ b/tests/tests/imported/clang/cpp/SemaCXX/.cxx0x-initializer-stdinitializerlist.rto/default.2.1.txt @@ -112,7 +112,7 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers "Test_name.c", line 314: error: expression must have a constant value constexpr int k = f( // expected-error {{must be initialized by a constant expression}} ^ -"Test_name.c", line 317: note: cannot call non-constexpr function "TemporaryInitListSourceRange_PR22367::A::A(std::initializer_list)" (declared at line 311) +"Test_name.c", line 317: note: cannot call non-constexpr function "std::initializer_list<_E>::initializer_list(const _E *, std::size_t) [with _E=int]" (declared at line 34) std::initializer_list // expected-note {{constructor}} ^ diff --git a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/default.1.1.txt b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/default.1.1.txt index ebac2ca80a..4694e27eb7 100644 --- a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/default.1.1.txt +++ b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/default.1.1.txt @@ -85,9 +85,9 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers "Test_name.c", line 514: error: call to consteval function "GH112677::ConstEval::ConstEval(int)" did not produce a valid constant expression TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} ^ -"Test_name.c", line 514: note: constexpr function "GH112677::ConstEval::ConstEval(int)" (declared at line 508) is not defined +"Test_name.c", line 514: note: the value of parameter "arg" (declared at line 514) cannot be used as a constant TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} - ^ + ^ detected during implicit generation of "GH112677::C::C(int) [with Anything=int]" at line 520 "Test_name.c", line 520: error: call to consteval function "GH112677::C::C(int) [with Anything=int]" did not produce a valid constant expression diff --git a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/default.2.1.txt b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/default.2.1.txt index c034173f30..05d600843c 100644 --- a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/default.2.1.txt +++ b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/default.2.1.txt @@ -85,9 +85,9 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers "Test_name.c", line 514: error: call to consteval function "GH112677::ConstEval::ConstEval(int)" did not produce a valid constant expression TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} ^ -"Test_name.c", line 514: note: constexpr function "GH112677::ConstEval::ConstEval(int)" (declared at line 508) is not defined +"Test_name.c", line 514: note: the value of parameter "arg" (declared at line 514) cannot be used as a constant TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} - ^ + ^ detected during implicit generation of "GH112677::C::C(int) [with Anything=int]" at line 520 "Test_name.c", line 520: error: call to consteval function "GH112677::C::C(int) [with Anything=int]" did not produce a valid constant expression diff --git a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/default.3.1.txt b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/default.3.1.txt index dfcc73830d..50b187955a 100644 --- a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/default.3.1.txt +++ b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/default.3.1.txt @@ -120,9 +120,9 @@ fe_only -DTEST_NUMBER=3 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers "Test_name.c", line 514: error: call to consteval function "GH112677::ConstEval::ConstEval(int)" did not produce a valid constant expression TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} ^ -"Test_name.c", line 514: note: constexpr function "GH112677::ConstEval::ConstEval(int)" (declared at line 508) is not defined +"Test_name.c", line 514: note: the value of parameter "arg" (declared at line 514) cannot be used as a constant TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} - ^ + ^ detected during implicit generation of "GH112677::C::C(int) [with Anything=int]" at line 520 "Test_name.c", line 520: error: call to consteval function "GH112677::C::C(int) [with Anything=int]" did not produce a valid constant expression diff --git a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/default.4.1.txt b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/default.4.1.txt index 5e47f9ca5e..e00b7c7bb0 100644 --- a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/default.4.1.txt +++ b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/default.4.1.txt @@ -120,9 +120,9 @@ fe_only -DTEST_NUMBER=4 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers "Test_name.c", line 514: error: call to consteval function "GH112677::ConstEval::ConstEval(int)" did not produce a valid constant expression TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} ^ -"Test_name.c", line 514: note: constexpr function "GH112677::ConstEval::ConstEval(int)" (declared at line 508) is not defined +"Test_name.c", line 514: note: the value of parameter "arg" (declared at line 514) cannot be used as a constant TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} - ^ + ^ detected during implicit generation of "GH112677::C::C(int) [with Anything=int]" at line 520 "Test_name.c", line 520: error: call to consteval function "GH112677::C::C(int) [with Anything=int]" did not produce a valid constant expression diff --git a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_32_cp.1.1.txt b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_32_cp.1.1.txt index dd60ea3752..40683f13d3 100644 --- a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_32_cp.1.1.txt +++ b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_32_cp.1.1.txt @@ -85,9 +85,9 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers "Test_name.c", line 514: error: call to consteval function "GH112677::ConstEval::ConstEval(int)" did not produce a valid constant expression TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} ^ -"Test_name.c", line 514: note: constexpr function "GH112677::ConstEval::ConstEval(int)" (declared at line 508) is not defined +"Test_name.c", line 514: note: the value of parameter "arg" (declared at line 514) cannot be used as a constant TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} - ^ + ^ "Test_name.c", line 520: error: call to consteval function "GH112677::C::C(int) [with Anything=int]" did not produce a valid constant expression C c(0); // expected-note{{in implicit initialization for inherited constructor of 'C'}} diff --git a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_32_cp.2.1.txt b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_32_cp.2.1.txt index eb7c4f0b20..eb32420db3 100644 --- a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_32_cp.2.1.txt +++ b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_32_cp.2.1.txt @@ -85,9 +85,9 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers "Test_name.c", line 514: error: call to consteval function "GH112677::ConstEval::ConstEval(int)" did not produce a valid constant expression TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} ^ -"Test_name.c", line 514: note: constexpr function "GH112677::ConstEval::ConstEval(int)" (declared at line 508) is not defined +"Test_name.c", line 514: note: the value of parameter "arg" (declared at line 514) cannot be used as a constant TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} - ^ + ^ "Test_name.c", line 520: error: call to consteval function "GH112677::C::C(int) [with Anything=int]" did not produce a valid constant expression C c(0); // expected-note{{in implicit initialization for inherited constructor of 'C'}} diff --git a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_32_cp.3.1.txt b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_32_cp.3.1.txt index 9bf0d323c4..5e8685b120 100644 --- a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_32_cp.3.1.txt +++ b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_32_cp.3.1.txt @@ -120,9 +120,9 @@ fe_only -DTEST_NUMBER=3 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers "Test_name.c", line 514: error: call to consteval function "GH112677::ConstEval::ConstEval(int)" did not produce a valid constant expression TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} ^ -"Test_name.c", line 514: note: constexpr function "GH112677::ConstEval::ConstEval(int)" (declared at line 508) is not defined +"Test_name.c", line 514: note: the value of parameter "arg" (declared at line 514) cannot be used as a constant TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} - ^ + ^ "Test_name.c", line 520: error: call to consteval function "GH112677::C::C(int) [with Anything=int]" did not produce a valid constant expression C c(0); // expected-note{{in implicit initialization for inherited constructor of 'C'}} diff --git a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_32_cp.4.1.txt b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_32_cp.4.1.txt index d1c5aa924c..255a4f710d 100644 --- a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_32_cp.4.1.txt +++ b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_32_cp.4.1.txt @@ -120,9 +120,9 @@ fe_only -DTEST_NUMBER=4 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers "Test_name.c", line 514: error: call to consteval function "GH112677::ConstEval::ConstEval(int)" did not produce a valid constant expression TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} ^ -"Test_name.c", line 514: note: constexpr function "GH112677::ConstEval::ConstEval(int)" (declared at line 508) is not defined +"Test_name.c", line 514: note: the value of parameter "arg" (declared at line 514) cannot be used as a constant TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} - ^ + ^ "Test_name.c", line 520: error: call to consteval function "GH112677::C::C(int) [with Anything=int]" did not produce a valid constant expression C c(0); // expected-note{{in implicit initialization for inherited constructor of 'C'}} diff --git a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_64_cp.1.1.txt b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_64_cp.1.1.txt index dd60ea3752..40683f13d3 100644 --- a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_64_cp.1.1.txt +++ b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_64_cp.1.1.txt @@ -85,9 +85,9 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers "Test_name.c", line 514: error: call to consteval function "GH112677::ConstEval::ConstEval(int)" did not produce a valid constant expression TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} ^ -"Test_name.c", line 514: note: constexpr function "GH112677::ConstEval::ConstEval(int)" (declared at line 508) is not defined +"Test_name.c", line 514: note: the value of parameter "arg" (declared at line 514) cannot be used as a constant TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} - ^ + ^ "Test_name.c", line 520: error: call to consteval function "GH112677::C::C(int) [with Anything=int]" did not produce a valid constant expression C c(0); // expected-note{{in implicit initialization for inherited constructor of 'C'}} diff --git a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_64_cp.2.1.txt b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_64_cp.2.1.txt index eb7c4f0b20..eb32420db3 100644 --- a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_64_cp.2.1.txt +++ b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_64_cp.2.1.txt @@ -85,9 +85,9 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers "Test_name.c", line 514: error: call to consteval function "GH112677::ConstEval::ConstEval(int)" did not produce a valid constant expression TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} ^ -"Test_name.c", line 514: note: constexpr function "GH112677::ConstEval::ConstEval(int)" (declared at line 508) is not defined +"Test_name.c", line 514: note: the value of parameter "arg" (declared at line 514) cannot be used as a constant TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} - ^ + ^ "Test_name.c", line 520: error: call to consteval function "GH112677::C::C(int) [with Anything=int]" did not produce a valid constant expression C c(0); // expected-note{{in implicit initialization for inherited constructor of 'C'}} diff --git a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_64_cp.3.1.txt b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_64_cp.3.1.txt index 9bf0d323c4..5e8685b120 100644 --- a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_64_cp.3.1.txt +++ b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_64_cp.3.1.txt @@ -120,9 +120,9 @@ fe_only -DTEST_NUMBER=3 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers "Test_name.c", line 514: error: call to consteval function "GH112677::ConstEval::ConstEval(int)" did not produce a valid constant expression TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} ^ -"Test_name.c", line 514: note: constexpr function "GH112677::ConstEval::ConstEval(int)" (declared at line 508) is not defined +"Test_name.c", line 514: note: the value of parameter "arg" (declared at line 514) cannot be used as a constant TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} - ^ + ^ "Test_name.c", line 520: error: call to consteval function "GH112677::C::C(int) [with Anything=int]" did not produce a valid constant expression C c(0); // expected-note{{in implicit initialization for inherited constructor of 'C'}} diff --git a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_64_cp.4.1.txt b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_64_cp.4.1.txt index d1c5aa924c..255a4f710d 100644 --- a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_64_cp.4.1.txt +++ b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2b-consteval-propagate.rto/edg_x86_64_cp.4.1.txt @@ -120,9 +120,9 @@ fe_only -DTEST_NUMBER=4 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers "Test_name.c", line 514: error: call to consteval function "GH112677::ConstEval::ConstEval(int)" did not produce a valid constant expression TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} ^ -"Test_name.c", line 514: note: constexpr function "GH112677::ConstEval::ConstEval(int)" (declared at line 508) is not defined +"Test_name.c", line 514: note: the value of parameter "arg" (declared at line 514) cannot be used as a constant TemplateCtor(int arg) : val(arg) {} // expected-note {{undefined constructor 'ConstEval'}} - ^ + ^ "Test_name.c", line 520: error: call to consteval function "GH112677::C::C(int) [with Anything=int]" did not produce a valid constant expression C c(0); // expected-note{{in implicit initialization for inherited constructor of 'C'}} diff --git a/tests/tests/regressions/.gh-527-neg.rto/default.1.1.txt b/tests/tests/regressions/.gh-527-neg.rto/default.1.1.txt new file mode 100644 index 0000000000..3aafb33de8 --- /dev/null +++ b/tests/tests/regressions/.gh-527-neg.rto/default.1.1.txt @@ -0,0 +1,16 @@ +fe_only -DTEST_NUMBER=1 --c++26 Test_name.c +"Test_name.c", line 17: error: expression must have a constant value + static_assert(f(1) == 0); // Error: S::S(int) is not constexpr. + ^ +"Test_name.c", line 13: note: cannot call non-constexpr function "S::S(int)" (declared at line 8) + try { S(h(n)); } catch (int i) { return i; } + ^ + +"Test_name.c", line 25: error: expression must have a constant value + static_assert(g() == 0); // Error: *p is not a constant. + ^ +"Test_name.c", line 22: note: attempt to access run-time storage + S(h(*p)); + ^ + +2 errors detected in the compilation of "Test_name.c". diff --git a/tests/tests/regressions/.gh-527.rto/default.1.1.txt b/tests/tests/regressions/.gh-527.rto/default.1.1.txt new file mode 100644 index 0000000000..6d7fd63c87 --- /dev/null +++ b/tests/tests/regressions/.gh-527.rto/default.1.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=1 --c++26 Test_name.c diff --git a/tests/tests/regressions/gh-527-neg.sft.cpp b/tests/tests/regressions/gh-527-neg.sft.cpp new file mode 100644 index 0000000000..a41c5ed41e --- /dev/null +++ b/tests/tests/regressions/gh-527-neg.sft.cpp @@ -0,0 +1,25 @@ +//type:fn +//options_all:--c++26 +//remark:Non-constexpr constructor call with a non-throwing argument + +constexpr int h(int n) { if (n < 0) throw n; return n; } + +struct S { + S(int) {} + constexpr S(double) {} +}; + +constexpr int f(int n) { + try { S(h(n)); } catch (int i) { return i; } + return 0; +} +static_assert(f(-1) == -1); +static_assert(f(1) == 0); // Error: S::S(int) is not constexpr. + +// An argument that is not a constant is diagnosed first. +constexpr int g() { + int* p = nullptr; + S(h(*p)); + return 0; +} +static_assert(g() == 0); // Error: *p is not a constant. diff --git a/tests/tests/regressions/gh-527.sft.cpp b/tests/tests/regressions/gh-527.sft.cpp new file mode 100644 index 0000000000..1374912432 --- /dev/null +++ b/tests/tests/regressions/gh-527.sft.cpp @@ -0,0 +1,67 @@ +//type:fp +//options_all:--c++26 +//remark:Non-constexpr constructor call whose argument throws in constexpr + +// The arguments of a constructor call are evaluated before the constructor is +// invoked: If an argument exits by throwing an exception, the constructor is +// not invoked, so it doesn't matter that it isn't constexpr. +constexpr int h(int n) { throw n; } + +struct S { + S(int) {} + constexpr S(double) {} +}; + +constexpr int temporary() { + try { S(h(1)); } catch (int i) { return i; } + return 0; +} +static_assert(temporary() == 1); + +constexpr int variable() { + try { S s(h(2)); } catch (int i) { return i; } + return 0; +} +static_assert(variable() == 2); + +constexpr int new_expression() { + try { delete new S(h(3)); } catch (int i) { return i; } + return 0; +} +static_assert(new_expression() == 3); + +struct M { + S s; + constexpr M() : s(h(4)) {} +}; +constexpr int member() { + try { M m; } catch (int i) { return i; } + return 0; +} +static_assert(member() == 4); + +struct D : S { + constexpr D() : S(h(5)) {} +}; +constexpr int base() { + try { D d; } catch (int i) { return i; } + return 0; +} +static_assert(base() == 5); + +// The arguments evaluated before the one that throws are destroyed. +struct L { + int* p; + constexpr L(int* p) : p(p) {} + constexpr ~L() { ++*p; } +}; +struct T { + T(const L&, int) {} + constexpr T(double) {} +}; +constexpr int destroyed() { + int n = 0; + try { T(L(&n), h(6)); } catch (int i) { return n * 10 + i; } + return 0; +} +static_assert(destroyed() == 16);