From c91b27155288e9869fc8345c689f7f6b90b0ee7e Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Thu, 28 Mar 2019 18:23:18 +0000 Subject: [PATCH] PR c++/89836 - bool constant expression and explicit conversions. * call.c (build_converted_constant_expr_internal): New function, renamed from... (build_converted_constant_expr): ...this. New. (build_converted_constant_bool_expr): New. * cp-tree.h (build_converted_constant_bool_expr): Declare. * decl.c (build_explicit_specifier): Call build_converted_constant_bool_expr. * g++.dg/cpp2a/explicit15.C: New test. From-SVN: r270002 --- gcc/cp/ChangeLog | 11 ++++++ gcc/cp/call.c | 50 ++++++++++++++++++------- gcc/cp/cp-tree.h | 1 + gcc/cp/decl.c | 2 +- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/g++.dg/cpp2a/explicit15.C | 10 +++++ 6 files changed, 65 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/explicit15.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b7c6c35a160..075e977b70b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2019-03-28 Marek Polacek + + PR c++/89836 - bool constant expression and explicit conversions. + * call.c (build_converted_constant_expr_internal): New function, + renamed from... + (build_converted_constant_expr): ...this. New. + (build_converted_constant_bool_expr): New. + * cp-tree.h (build_converted_constant_bool_expr): Declare. + * decl.c (build_explicit_specifier): Call + build_converted_constant_bool_expr. + 2019-03-28 Jakub Jelinek PR c++/89785 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 9efca735b16..bc5179416a5 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4175,18 +4175,11 @@ build_user_type_conversion (tree totype, tree expr, int flags, return ret; } -/* Subroutine of convert_nontype_argument. +/* Worker for build_converted_constant_expr. */ - EXPR is an expression used in a context that requires a converted - constant-expression, such as a template non-type parameter. Do any - necessary conversions (that are permitted for converted - constant-expressions) to convert it to the desired type. - - If conversion is successful, returns the converted expression; - otherwise, returns error_mark_node. */ - -tree -build_converted_constant_expr (tree type, tree expr, tsubst_flags_t complain) +static tree +build_converted_constant_expr_internal (tree type, tree expr, + int flags, tsubst_flags_t complain) { conversion *conv; void *p; @@ -4200,8 +4193,7 @@ build_converted_constant_expr (tree type, tree expr, tsubst_flags_t complain) p = conversion_obstack_alloc (0); conv = implicit_conversion (type, TREE_TYPE (expr), expr, - /*c_cast_p=*/false, - LOOKUP_IMPLICIT, complain); + /*c_cast_p=*/false, flags, complain); /* A converted constant expression of type T is an expression, implicitly converted to type T, where the converted expression is a constant @@ -4304,6 +4296,38 @@ build_converted_constant_expr (tree type, tree expr, tsubst_flags_t complain) return expr; } +/* Subroutine of convert_nontype_argument. + + EXPR is an expression used in a context that requires a converted + constant-expression, such as a template non-type parameter. Do any + necessary conversions (that are permitted for converted + constant-expressions) to convert it to the desired type. + + This function doesn't consider explicit conversion functions. If + you mean to use "a contextually converted constant expression of type + bool", use build_converted_constant_bool_expr. + + If conversion is successful, returns the converted expression; + otherwise, returns error_mark_node. */ + +tree +build_converted_constant_expr (tree type, tree expr, tsubst_flags_t complain) +{ + return build_converted_constant_expr_internal (type, expr, LOOKUP_IMPLICIT, + complain); +} + +/* Used to create "a contextually converted constant expression of type + bool". This differs from build_converted_constant_expr in that it + also considers explicit conversion functions. */ + +tree +build_converted_constant_bool_expr (tree expr, tsubst_flags_t complain) +{ + return build_converted_constant_expr_internal (boolean_type_node, expr, + LOOKUP_NORMAL, complain); +} + /* Do any initial processing on the arguments to a function call. */ static vec * diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 3fe91ad2160..fd612b0dbb1 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6233,6 +6233,7 @@ extern int remaining_arguments (tree); extern tree perform_implicit_conversion (tree, tree, tsubst_flags_t); extern tree perform_implicit_conversion_flags (tree, tree, tsubst_flags_t, int); extern tree build_converted_constant_expr (tree, tree, tsubst_flags_t); +extern tree build_converted_constant_bool_expr (tree, tsubst_flags_t); extern tree perform_direct_initialization_if_possible (tree, tree, bool, tsubst_flags_t); extern tree in_charge_arg_for_name (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index c8435e29491..c46a39665bd 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -16700,7 +16700,7 @@ build_explicit_specifier (tree expr, tsubst_flags_t complain) expr = instantiate_non_dependent_expr_sfinae (expr, complain); /* Don't let convert_like_real create more template codes. */ processing_template_decl_sentinel s; - expr = build_converted_constant_expr (boolean_type_node, expr, complain); + expr = build_converted_constant_bool_expr (expr, complain); expr = cxx_constant_value (expr); return expr; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9c98973f764..0210cd72935 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-03-28 Marek Polacek + + PR c++/89836 - bool constant expression and explicit conversions. + * g++.dg/cpp2a/explicit15.C: New test. + 2019-03-28 Jakub Jelinek PR c/89812 diff --git a/gcc/testsuite/g++.dg/cpp2a/explicit15.C b/gcc/testsuite/g++.dg/cpp2a/explicit15.C new file mode 100644 index 00000000000..e0058f6dc87 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/explicit15.C @@ -0,0 +1,10 @@ +// PR c++/89836 +// { dg-do compile { target c++2a } } + +struct W { + constexpr explicit operator bool() { return true; }; +}; + +struct U { + explicit(W()) U(int); +};