Ping.

On Fri, Oct 12, 2018 at 12:32:43PM -0400, Marek Polacek wrote:
> On Fri, Oct 12, 2018 at 02:26:45AM -0400, Jason Merrill wrote:
> > On Thu, Oct 11, 2018 at 8:25 PM Marek Polacek <pola...@redhat.com> wrote:
> > >
> > > On Thu, Oct 11, 2018 at 11:35:23AM -0400, Jason Merrill wrote:
> > > > > +       /* [dcl.fct.spec]
> > > > > +          "the constant-expression, if supplied, shall be a 
> > > > > contextually
> > > > > +          converted constant expression of type bool."  */
> > > > > +       expr = build_explicit_specifier (expr, tf_warning_or_error);
> > > > > +       /* We could evaluate it -- mark the decl as appropriate.  */
> > > > > +       if (expr == boolean_true_node)
> > > > > +         set_and_check_decl_spec_loc (decl_specs, ds_explicit, 
> > > > > token);
> > > > > +       else if (explicit_specifier)
> > > > > +         /* The expression was value-dependent.  Remember it so that 
> > > > > we can
> > > > > +            substitute it later.  */
> > > > > +         *explicit_specifier = expr;
> > > >
> > > > What if expr == boolean_false_node?
> > >
> > > Then we proceed like no explicit was present and the decl isn't marked as
> > > explicit/nonconverting.  Perhaps I could have made this clearer with
> > >
> > >   else if (expr == boolean_true_node)
> > >     /* Don't mark the decl as explicit.  */;
> > >
> > > or somesuch.
> > 
> > Yes, and also so that we don't store the false as a "dependent" specifier.
> 
> Oh, absolutely.  Fixed.
> 
> > > > > +      /* Handle explicit(dependent-expr).  */
> > > > > +      if (DECL_HAS_DEPENDENT_EXPLICIT_SPEC_P (t))
> > > > > +       {
> > > > > +         tree spec = lookup_explicit_specifier (t);
> > > > > +         spec = tsubst_copy_and_build (spec, args, complain, in_decl,
> > > > > +                                       /*function_p=*/false,
> > > > > +                                       /*i_c_e_p=*/true);
> > > > > +         spec = build_explicit_specifier (spec, complain);
> > > > > +         DECL_NONCONVERTING_P (t) = (spec == boolean_true_node);
> > > > > +       }
> > > >
> > > > What if spec is still dependent, e.g. after partial substitution of a
> > > > member template?
> > >
> > > Something like this?
> > >
> > > template<typename> struct A {
> > >   template<typename T, int N = 0>
> > >   explicit(N) operator T();
> > > };
> > >
> > > void
> > > bar ()
> > > {
> > >   A<int> a;
> > >   int i = a;
> > > }
> > >
> > > This also seemed to work: if spec is still dependent, the decl isn't 
> > > marked as
> > > DECL_NONCONVERTING_P, and we'll try again after deduction 
> > > (fn_type_unification
> > > in add_template_candidate).
> > 
> > Does it also work if N is true?  What if the specifier depends on
> > template parameters from both the enclosing class and the member
> > template?
> 
> All of that seems to work.  I've added explicit12.C and explicit13.C tests to
> cover that.  Please check if that's what you had in mind.  Thanks,
> 
> Bootstrapped/regtested on x86_64-linux, ok for trunk?
> 
> 2018-10-12  Marek Polacek  <pola...@redhat.com>
> 
>       Implement P0892R2, explicit(bool).
>       * c-cppbuiltin.c (c_cpp_builtins): Define __cpp_explicit_bool.
> 
>       * call.c (add_template_candidate_real): Return if the declaration is
>       explicit and we're only looking for non-converting constructor.
>       * cp-tree.h (lang_decl_fn): Add has_dependent_explicit_spec_p bit.
>       (DECL_HAS_DEPENDENT_EXPLICIT_SPEC_P): New macro.
>       (build_explicit_specifier, store_explicit_specifier): Declare.
>       * decl.c (build_explicit_specifier): New function.
>       * parser.c (cp_parser_decl_specifier_seq): Add explicit_specifier
>       parameter.  Pass it down to cp_parser_function_specifier_opt.
>       (cp_parser_function_specifier_opt): Add explicit_specifier parameter.
>       <case RID_EXPLICIT>: Parse C++20 explicit(bool).
>       (cp_parser_explicit_instantiation): Update call to
>       cp_parser_function_specifier_opt.
>       (cp_parser_member_declaration): Have cp_parser_decl_specifier_seq save
>       the explicit-specifier.  Save it using store_explicit_specifier.
>       (cp_parser_single_declaration): Likewise.
>       * pt.c (store_explicit_specifier, lookup_explicit_specifier): New.
>       (tsubst_function_decl): Handle explicit(dependent-expr).
> 
>       * g++.dg/cpp2a/explicit1.C: New test.
>       * g++.dg/cpp2a/explicit10.C: New test.
>       * g++.dg/cpp2a/explicit11.C: New test.
>       * g++.dg/cpp2a/explicit12.C: New test.
>       * g++.dg/cpp2a/explicit13.C: New test.
>       * g++.dg/cpp2a/explicit2.C: New test.
>       * g++.dg/cpp2a/explicit3.C: New test.
>       * g++.dg/cpp2a/explicit4.C: New test.
>       * g++.dg/cpp2a/explicit5.C: New test.
>       * g++.dg/cpp2a/explicit6.C: New test.
>       * g++.dg/cpp2a/explicit7.C: New test.
>       * g++.dg/cpp2a/explicit8.C: New test.
>       * g++.dg/cpp2a/explicit9.C: New test.
> 
>       * testsuite/20_util/any/cons/explicit.cc: Adjust dg-error.
>       * testsuite/20_util/pair/cons/explicit_construct.cc: Likewise.
>       * testsuite/20_util/tuple/cons/explicit_construct.cc: Likewise.
> 
> diff --git gcc/gcc/c-family/c-cppbuiltin.c gcc/gcc/c-family/c-cppbuiltin.c
> index 96a6b4dfd2b..b085cf9201f 100644
> --- gcc/gcc/c-family/c-cppbuiltin.c
> +++ gcc/gcc/c-family/c-cppbuiltin.c
> @@ -955,7 +955,7 @@ c_cpp_builtins (cpp_reader *pfile)
>       }
>        if (cxx_dialect > cxx14)
>       {
> -       /* Set feature test macros for C++1z.  */
> +       /* Set feature test macros for C++17.  */
>         cpp_define (pfile, "__cpp_unicode_characters=201411");
>         cpp_define (pfile, "__cpp_static_assert=201411");
>         cpp_define (pfile, "__cpp_namespace_attributes=201411");
> @@ -975,6 +975,11 @@ c_cpp_builtins (cpp_reader *pfile)
>         cpp_define (pfile, "__cpp_structured_bindings=201606");
>         cpp_define (pfile, "__cpp_variadic_using=201611");
>       }
> +      if (cxx_dialect > cxx17)
> +     {
> +       /* Set feature test macros for C++2a.  */
> +       cpp_define (pfile, "__cpp_explicit_bool=201806");
> +     }
>        if (flag_concepts)
>       cpp_define (pfile, "__cpp_concepts=201507");
>        if (flag_tm)
> diff --git gcc/gcc/cp/call.c gcc/gcc/cp/call.c
> index 0baf26e4346..1ae2f0d68a2 100644
> --- gcc/gcc/cp/call.c
> +++ gcc/gcc/cp/call.c
> @@ -3251,6 +3251,12 @@ add_template_candidate_real (struct z_candidate 
> **candidates, tree tmpl,
>        goto fail;
>      }
>  
> +  /* Now the explicit specifier might have been deduced; check if this
> +     declaration is explicit.  If it is and we're ignoring non-converting
> +     constructors, don't add this function to the set of candidates.  */
> +  if ((flags & LOOKUP_ONLYCONVERTING) && DECL_NONCONVERTING_P (fn))
> +    return NULL;
> +
>    if (DECL_CONSTRUCTOR_P (fn) && nargs == 2)
>      {
>        tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (fn);
> diff --git gcc/gcc/cp/cp-tree.h gcc/gcc/cp/cp-tree.h
> index 26ded3a9214..cf2d0554cb7 100644
> --- gcc/gcc/cp/cp-tree.h
> +++ gcc/gcc/cp/cp-tree.h
> @@ -2587,7 +2587,8 @@ struct GTY(()) lang_decl_fn {
>    unsigned this_thunk_p : 1;
>    unsigned hidden_friend_p : 1;
>    unsigned omp_declare_reduction_p : 1;
> -  unsigned spare : 13;
> +  unsigned has_dependent_explicit_spec_p : 1;
> +  unsigned spare : 12;
>  
>    /* 32-bits padding on 64-bit host.  */
>  
> @@ -3033,6 +3034,12 @@ struct GTY(()) lang_decl {
>  #define DECL_PURE_VIRTUAL_P(NODE) \
>    (LANG_DECL_FN_CHECK (NODE)->pure_virtual)
>  
> +/* Nonzero for FUNCTION_DECL means that this member function (either
> +   a constructor or a conversion function) has an explicit specifier
> +   with a value-dependent expression.  */
> +#define DECL_HAS_DEPENDENT_EXPLICIT_SPEC_P(NODE) \
> +  (LANG_DECL_FN_CHECK (NODE)->has_dependent_explicit_spec_p)
> +
>  /* True (in a FUNCTION_DECL) if NODE is a virtual function that is an
>     invalid overrider for a function from a base class.  Once we have
>     complained about an invalid overrider we avoid complaining about it
> @@ -6375,6 +6382,7 @@ extern tree cxx_maybe_build_cleanup             (tree, 
> tsubst_flags_t);
>  extern bool check_array_designated_initializer  (constructor_elt *,
>                                                unsigned HOST_WIDE_INT);
>  extern bool check_for_uninitialized_const_var   (tree, bool, tsubst_flags_t);
> +extern tree build_explicit_specifier         (tree, tsubst_flags_t);
>  
>  /* in decl2.c */
>  extern void record_mangling                  (tree, bool);
> @@ -6771,6 +6779,7 @@ extern bool dguide_name_p                       (tree);
>  extern bool deduction_guide_p                        (const_tree);
>  extern bool copy_guide_p                     (const_tree);
>  extern bool template_guide_p                 (const_tree);
> +extern void store_explicit_specifier         (tree, tree);
>  
>  /* in repo.c */
>  extern void init_repo                                (void);
> diff --git gcc/gcc/cp/decl.c gcc/gcc/cp/decl.c
> index 5ebfaaf85e6..f7a2e2a6789 100644
> --- gcc/gcc/cp/decl.c
> +++ gcc/gcc/cp/decl.c
> @@ -16560,4 +16560,20 @@ require_deduced_type (tree decl, tsubst_flags_t 
> complain)
>    return true;
>  }
>  
> +/* Create a representation of the explicit-specifier with
> +   constant-expression of EXPR.  COMPLAIN is as for tsubst.  */
> +
> +tree
> +build_explicit_specifier (tree expr, tsubst_flags_t complain)
> +{
> +  if (processing_template_decl && value_dependent_expression_p (expr))
> +    /* Wait for instantiation, tsubst_function_decl will handle it.  */
> +    return expr;
> +
> +  expr = build_converted_constant_expr (boolean_type_node, expr, complain);
> +  expr = instantiate_non_dependent_expr (expr);
> +  expr = cxx_constant_value (expr);
> +  return expr;
> +}
> +
>  #include "gt-cp-decl.h"
> diff --git gcc/gcc/cp/parser.c gcc/gcc/cp/parser.c
> index 76ff83616b0..29a63cd92f6 100644
> --- gcc/gcc/cp/parser.c
> +++ gcc/gcc/cp/parser.c
> @@ -2140,11 +2140,11 @@ static void cp_parser_block_declaration
>  static void cp_parser_simple_declaration
>    (cp_parser *, bool, tree *);
>  static void cp_parser_decl_specifier_seq
> -  (cp_parser *, cp_parser_flags, cp_decl_specifier_seq *, int *);
> +  (cp_parser *, cp_parser_flags, cp_decl_specifier_seq *, int *, tree * = 
> NULL);
>  static tree cp_parser_storage_class_specifier_opt
>    (cp_parser *);
>  static tree cp_parser_function_specifier_opt
> -  (cp_parser *, cp_decl_specifier_seq *);
> +  (cp_parser *, cp_decl_specifier_seq *, tree *);
>  static tree cp_parser_type_specifier
>    (cp_parser *, cp_parser_flags, cp_decl_specifier_seq *, bool,
>     int *, bool *);
> @@ -13513,13 +13513,15 @@ cp_parser_decomposition_declaration (cp_parser 
> *parser,
>       2: one of the decl-specifiers is an enum-specifier or a
>       class-specifier (i.e., a type definition)
>  
> -   */
> +   EXPLICIT_SPECIFIER is used in case the explicit-specifier, if any, has
> +   value-dependent expression.  */
>  
>  static void
>  cp_parser_decl_specifier_seq (cp_parser* parser,
>                             cp_parser_flags flags,
>                             cp_decl_specifier_seq *decl_specs,
> -                           int* declares_class_or_enum)
> +                           int* declares_class_or_enum,
> +                           tree* explicit_specifier)
>  {
>    bool constructor_possible_p = !parser->in_declarator_p;
>    bool found_decl_spec = false;
> @@ -13640,7 +13642,8 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
>       case RID_INLINE:
>       case RID_VIRTUAL:
>       case RID_EXPLICIT:
> -       cp_parser_function_specifier_opt (parser, decl_specs);
> +       cp_parser_function_specifier_opt (parser, decl_specs,
> +                                         explicit_specifier);
>         break;
>  
>         /* decl-specifier:
> @@ -13867,12 +13870,17 @@ cp_parser_storage_class_specifier_opt (cp_parser* 
> parser)
>       virtual
>       explicit
>  
> +   C++2A Extension:
> +     explicit(constant-expression)
> +
>     Returns an IDENTIFIER_NODE corresponding to the keyword used.
> -   Updates DECL_SPECS, if it is non-NULL.  */
> +   Updates DECL_SPECS, if it is non-NULL.  Updates EXPLICIT_SPECIFIER,
> +   in case an explicit-specifier is found.  */
>  
>  static tree
>  cp_parser_function_specifier_opt (cp_parser* parser,
> -                               cp_decl_specifier_seq *decl_specs)
> +                               cp_decl_specifier_seq *decl_specs,
> +                               tree *explicit_specifier)
>  {
>    cp_token *token = cp_lexer_peek_token (parser->lexer);
>    switch (token->keyword)
> @@ -13893,8 +13901,53 @@ cp_parser_function_specifier_opt (cp_parser* parser,
>        break;
>  
>      case RID_EXPLICIT:
> -      set_and_check_decl_spec_loc (decl_specs, ds_explicit, token);
> -      break;
> +      {
> +     tree id = cp_lexer_consume_token (parser->lexer)->u.value;
> +     /* If we see '(', it's C++20 explicit(bool).  */
> +     tree expr;
> +     if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
> +       {
> +         matching_parens parens;
> +         parens.consume_open (parser);
> +
> +         /* New types are not allowed in an explicit-specifier.  */
> +         const char *saved_message
> +           = parser->type_definition_forbidden_message;
> +         parser->type_definition_forbidden_message
> +           = G_("types may not be defined in explicit-specifier");
> +
> +         if (cxx_dialect < cxx2a)
> +           pedwarn (token->location, 0,
> +                    "%<explicit(bool)%> only available with -std=c++2a "
> +                    "or -std=gnu++2a");
> +
> +         /* Parse the constant-expression.  */
> +         expr = cp_parser_constant_expression (parser);
> +
> +         /* Restore the saved message.  */
> +         parser->type_definition_forbidden_message = saved_message;
> +         parens.require_close (parser);
> +       }
> +     else
> +       /* The explicit-specifier explicit without a constant-expression is
> +          equivalent to the explicit-specifier explicit(true).  */
> +       expr = boolean_true_node;
> +
> +     /* [dcl.fct.spec]
> +        "the constant-expression, if supplied, shall be a contextually
> +        converted constant expression of type bool."  */
> +     expr = build_explicit_specifier (expr, tf_warning_or_error);
> +     /* We could evaluate it -- mark the decl as appropriate.  */
> +     if (expr == boolean_true_node)
> +       set_and_check_decl_spec_loc (decl_specs, ds_explicit, token);
> +     else if (expr == boolean_false_node)
> +       /* Don't mark the decl as explicit.  */;
> +     else if (explicit_specifier)
> +       /* The expression was value-dependent.  Remember it so that we can
> +          substitute it later.  */
> +       *explicit_specifier = expr;
> +     return id;
> +      }
>  
>      default:
>        return NULL_TREE;
> @@ -16655,7 +16708,8 @@ cp_parser_explicit_instantiation (cp_parser* parser)
>        if (!extension_specifier)
>       extension_specifier
>         = cp_parser_function_specifier_opt (parser,
> -                                           /*decl_specs=*/NULL);
> +                                           /*decl_specs=*/NULL,
> +                                           /*explicit_specifier*/NULL);
>      }
>  
>    /* Look for the `template' keyword.  */
> @@ -23569,6 +23623,7 @@ cp_parser_member_declaration (cp_parser* parser)
>    cp_token *initializer_token_start = NULL;
>    int saved_pedantic;
>    bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
> +  tree explicit_specifier = NULL_TREE;
>  
>    /* Check for the `__extension__' keyword.  */
>    if (cp_parser_extension_opt (parser, &saved_pedantic))
> @@ -23665,7 +23720,8 @@ cp_parser_member_declaration (cp_parser* parser)
>    cp_parser_decl_specifier_seq (parser,
>                               CP_PARSER_FLAGS_OPTIONAL,
>                               &decl_specifiers,
> -                             &declares_class_or_enum);
> +                             &declares_class_or_enum,
> +                             &explicit_specifier);
>    /* Check for an invalid type-name.  */
>    if (!decl_specifiers.any_type_specifiers_p
>        && cp_parser_parse_and_diagnose_invalid_type_name (parser))
> @@ -24019,6 +24075,8 @@ cp_parser_member_declaration (cp_parser* parser)
>                 /* If the member was not a friend, declare it here.  */
>                 if (!friend_p)
>                   finish_member_declaration (decl);
> +               if (decl && explicit_specifier)
> +                 store_explicit_specifier (decl, explicit_specifier);
>                 /* Peek at the next token.  */
>                 token = cp_lexer_peek_token (parser->lexer);
>                 /* If the next token is a semicolon, consume it.  */
> @@ -24048,6 +24106,8 @@ cp_parser_member_declaration (cp_parser* parser)
>                 else
>                   decl = finish_fully_implicit_template (parser, decl);
>               }
> +           if (decl && explicit_specifier)
> +             store_explicit_specifier (decl, explicit_specifier);
>           }
>  
>         cp_finalize_omp_declare_simd (parser, decl);
> @@ -27327,6 +27387,7 @@ cp_parser_single_declaration (cp_parser* parser,
>    cp_decl_specifier_seq decl_specifiers;
>    bool function_definition_p = false;
>    cp_token *decl_spec_token_start;
> +  tree explicit_specifier = NULL_TREE;
>  
>    /* This function is only used when processing a template
>       declaration.  */
> @@ -27342,7 +27403,8 @@ cp_parser_single_declaration (cp_parser* parser,
>    cp_parser_decl_specifier_seq (parser,
>                               CP_PARSER_FLAGS_OPTIONAL,
>                               &decl_specifiers,
> -                             &declares_class_or_enum);
> +                             &declares_class_or_enum,
> +                             &explicit_specifier);
>    if (friend_p)
>      *friend_p = cp_parser_friend_p (&decl_specifiers);
>  
> @@ -27453,6 +27515,9 @@ cp_parser_single_declaration (cp_parser* parser,
>  
>      if (decl && VAR_P (decl))
>        check_template_variable (decl);
> +
> +    if (decl && explicit_specifier)
> +      store_explicit_specifier (decl, explicit_specifier);
>      }
>  
>    /* Look for a trailing `;' after the declaration.  */
> diff --git gcc/gcc/cp/pt.c gcc/gcc/cp/pt.c
> index f290cb32fc2..c9a3bb0235d 100644
> --- gcc/gcc/cp/pt.c
> +++ gcc/gcc/cp/pt.c
> @@ -12803,6 +12803,28 @@ tsubst_default_arguments (tree fn, tsubst_flags_t 
> complain)
>                                                   complain);
>  }
>  
> +/* Hash table mapping a FUNCTION_DECL to its dependent explicit-specifier.  
> */
> +static GTY((cache)) tree_cache_map *explicit_specifier_map;
> +
> +/* Store a pair to EXPLICIT_SPECIFIER_MAP.  */
> +
> +void
> +store_explicit_specifier (tree v, tree t)
> +{
> +  if (!explicit_specifier_map)
> +    explicit_specifier_map = tree_cache_map::create_ggc (37);
> +  DECL_HAS_DEPENDENT_EXPLICIT_SPEC_P (v) = true;
> +  explicit_specifier_map->put (v, t);
> +}
> +
> +/* Lookup an element in EXPLICIT_SPECIFIER_MAP.  */
> +
> +static tree
> +lookup_explicit_specifier (tree v)
> +{
> +  return *explicit_specifier_map->get (v);
> +}
> +
>  /* Subroutine of tsubst_decl for the case when T is a FUNCTION_DECL.  */
>  
>  static tree
> @@ -12822,6 +12844,17 @@ tsubst_function_decl (tree t, tree args, 
> tsubst_flags_t complain,
>        if (!uses_template_parms (DECL_TI_ARGS (t)))
>       return t;
>  
> +      /* Handle explicit(dependent-expr).  */
> +      if (DECL_HAS_DEPENDENT_EXPLICIT_SPEC_P (t))
> +     {
> +       tree spec = lookup_explicit_specifier (t);
> +       spec = tsubst_copy_and_build (spec, args, complain, in_decl,
> +                                     /*function_p=*/false,
> +                                     /*i_c_e_p=*/true);
> +       spec = build_explicit_specifier (spec, complain);
> +       DECL_NONCONVERTING_P (t) = (spec == boolean_true_node);
> +     }
> +
>        /* Calculate the most general template of which R is a
>        specialization.  */
>        gen_tmpl = most_general_template (DECL_TI_TEMPLATE (t));
> diff --git gcc/gcc/testsuite/g++.dg/cpp2a/explicit1.C 
> gcc/gcc/testsuite/g++.dg/cpp2a/explicit1.C
> index e69de29bb2d..b39f90f3397 100644
> --- gcc/gcc/testsuite/g++.dg/cpp2a/explicit1.C
> +++ gcc/gcc/testsuite/g++.dg/cpp2a/explicit1.C
> @@ -0,0 +1,63 @@
> +// P0892R2
> +// { dg-do compile }
> +// { dg-options "-std=c++2a" }
> +
> +constexpr int fn0 () { return 0; }
> +constexpr int fn1 () { return 1; }
> +
> +struct S {
> +  explicit(true) S(int);
> +  explicit(1 == 0) S(int, int);
> +  explicit(fn0()) S(int, int, int);
> +  explicit(fn1()) S(int, int, int, int);
> +};
> +
> +struct X {
> +  static const bool value = true;
> +  static constexpr bool foo () { return 1; }
> +};
> +
> +struct T {
> +  explicit(true ? 1 : throw 1) T(int);
> +  explicit(true || true ? 1 : throw 1) T(int, int);
> +  explicit(X::value) T(int, int, int);
> +  explicit(X::foo ()) T(int, int, int, int);
> +};
> +
> +struct W {
> +  constexpr operator bool() { return true; };
> +};
> +
> +struct W2 {
> +  constexpr operator bool() { return false; };
> +};
> +
> +struct U {
> +  explicit(W()) U(int);
> +  explicit(W2()) U(int, int);
> +};
> +
> +int
> +main ()
> +{
> +  S s1 = { 1 }; // { dg-error "converting" }
> +  S s1x{ 1 };
> +  S s2 = { 2, 3 };
> +  S s3 = { 4, 5, 6 };
> +  S s4 = { 7, 8, 9, 10 }; // { dg-error "converting" }
> +  S s4x{ 7, 8, 9, 10 };
> +
> +  T t1 = { 1 }; // { dg-error "converting" }
> +  T t2 = { 1, 2 }; // { dg-error "converting" }
> +  T t3 = { 1, 2, 3 }; // { dg-error "converting" }
> +  T t4 = { 1, 2, 3, 4 }; // { dg-error "converting" }
> +  T t5{ 1 };
> +  T t6{ 1, 2 };
> +  T t7{ 1, 2, 3 };
> +  T t8{ 1, 2, 3, 4 };
> +
> +  U u1 = { 1 }; // { dg-error "converting" }
> +  U u2{ 1 };
> +  U u3 = { 1, 2 };
> +  U u4 { 1, 2 };
> +}
> diff --git gcc/gcc/testsuite/g++.dg/cpp2a/explicit10.C 
> gcc/gcc/testsuite/g++.dg/cpp2a/explicit10.C
> index e69de29bb2d..c8701551c9a 100644
> --- gcc/gcc/testsuite/g++.dg/cpp2a/explicit10.C
> +++ gcc/gcc/testsuite/g++.dg/cpp2a/explicit10.C
> @@ -0,0 +1,32 @@
> +// P0892R2
> +// { dg-do compile }
> +// { dg-options "-std=c++2a" }
> +
> +#include <type_traits>
> +
> +class A {};
> +class B : public A {};
> +class C {};
> +class D { public: operator C() { return c; }  C c; };
> +
> +template <typename T1, typename T2>
> +struct S {
> +  explicit(!std::is_convertible_v<T1, T2>)
> +  S(T1, T2) { }
> +};
> +
> +void
> +foo ()
> +{
> +  A a;
> +  B b;
> +  C c;
> +  D d;
> +
> +  S<int, int> s{ 1, 2 };
> +  S<int, int> s2 = { 1, 2 };
> +  S<B*, A*> s3 = { &b, &a };
> +  S<A*, B*> s4 = { &a, &b }; // { dg-error "converting" }
> +  S<B*, C*> s5 = { &b, &c }; // { dg-error "converting" }
> +  S<D, C> s6 = { d, c };
> +}
> diff --git gcc/gcc/testsuite/g++.dg/cpp2a/explicit11.C 
> gcc/gcc/testsuite/g++.dg/cpp2a/explicit11.C
> index e69de29bb2d..ad1bed5b3f0 100644
> --- gcc/gcc/testsuite/g++.dg/cpp2a/explicit11.C
> +++ gcc/gcc/testsuite/g++.dg/cpp2a/explicit11.C
> @@ -0,0 +1,29 @@
> +// P0892R2
> +// { dg-do compile }
> +// { dg-options "-std=c++2a -pedantic" }
> +
> +template<typename T>
> +struct A {
> +  explicit A(const T&, ...) noexcept;
> +  A(T&&, ...);
> +};
> +
> +int i;
> +A a1 = { i, i }; // { dg-error "deduction|cannot" }
> +A a2{ i, i };
> +A a3{ 0, i };
> +A a4 = { 0, i };
> +
> +template<typename T> A(const T&, const T&) -> A<T&>;
> +template<typename T> explicit A(T&&, T&&) -> A<T>;
> +
> +A a5 = { 0, 1 }; // { dg-error "deduction|ambiguous" }
> +A a6{ 0, 1 };
> +
> +template<typename T>
> +struct B {
> +  template<typename U> using TA = T;
> +  template<typename U> B(U, TA<U>);
> +};
> +
> +B b{(int *)0, (char *)0};
> diff --git gcc/gcc/testsuite/g++.dg/cpp2a/explicit12.C 
> gcc/gcc/testsuite/g++.dg/cpp2a/explicit12.C
> index e69de29bb2d..6db3157580b 100644
> --- gcc/gcc/testsuite/g++.dg/cpp2a/explicit12.C
> +++ gcc/gcc/testsuite/g++.dg/cpp2a/explicit12.C
> @@ -0,0 +1,23 @@
> +// P0892R2
> +// { dg-do compile }
> +// { dg-options "-std=c++2a" }
> +
> +template<typename> struct A {
> +  template<typename T, int N = 0>
> +  explicit(N) operator T();
> +};
> +
> +template<typename> struct B {
> +  template<typename T, int N = 1>
> +  explicit(N) operator T();
> +};
> +
> +void
> +bar ()
> +{
> +  A<int> a;
> +  int i = a;
> +
> +  B<int> b;
> +  int j = b; // { dg-error "cannot convert" }
> +}
> diff --git gcc/gcc/testsuite/g++.dg/cpp2a/explicit13.C 
> gcc/gcc/testsuite/g++.dg/cpp2a/explicit13.C
> index e69de29bb2d..4747ebd3df4 100644
> --- gcc/gcc/testsuite/g++.dg/cpp2a/explicit13.C
> +++ gcc/gcc/testsuite/g++.dg/cpp2a/explicit13.C
> @@ -0,0 +1,35 @@
> +// P0892R2
> +// { dg-do compile }
> +// { dg-options "-std=c++2a" }
> +
> +template<int M = 0> struct A {
> +  template<typename T, int N = 0>
> +  explicit(N + M) operator T();
> +};
> +
> +template<int M = 1> struct B {
> +  template<typename T, int N = 1>
> +  explicit(N * M) operator T();
> +};
> +
> +void
> +bar ()
> +{
> +  A a;
> +  int i = a;
> +
> +  A<0> a0;
> +  int i0 = a0;
> +
> +  A<1> a1;
> +  int i1 = a1; // { dg-error "cannot convert" }
> +
> +  B b;
> +  int j = b; // { dg-error "cannot convert" }
> +
> +  B<0> b0;
> +  int j0 = b0;
> +
> +  B<1> b1;
> +  int j1 = b1; // { dg-error "cannot convert" }
> +}
> diff --git gcc/gcc/testsuite/g++.dg/cpp2a/explicit2.C 
> gcc/gcc/testsuite/g++.dg/cpp2a/explicit2.C
> index e69de29bb2d..7d1748c0f5e 100644
> --- gcc/gcc/testsuite/g++.dg/cpp2a/explicit2.C
> +++ gcc/gcc/testsuite/g++.dg/cpp2a/explicit2.C
> @@ -0,0 +1,25 @@
> +// P0892R2
> +// { dg-do compile }
> +// { dg-options "-std=c++2a" }
> +
> +int foo() { return 42; }
> +int g;
> +
> +struct S {
> +  explicit(foo()) S(int); // { dg-error "call to" }
> +  explicit(int) S(int, int); // { dg-error "expected" }
> +  explicit(false ? 1 : throw 1) S(int, int, int); // { dg-error "not a 
> constant" }
> +};
> +
> +struct S2 {
> +  explicit(true) S2();
> +  explicit(false) S2(); // { dg-error "cannot be overloaded" }
> +};
> +
> +int
> +main ()
> +{
> +  S s1 = { 1 };
> +  S s2 = { 1, 2 }; // { dg-error "could not convert" }
> +  S s3 = { 1, 2, 3 };
> +}
> diff --git gcc/gcc/testsuite/g++.dg/cpp2a/explicit3.C 
> gcc/gcc/testsuite/g++.dg/cpp2a/explicit3.C
> index e69de29bb2d..7c495a3640b 100644
> --- gcc/gcc/testsuite/g++.dg/cpp2a/explicit3.C
> +++ gcc/gcc/testsuite/g++.dg/cpp2a/explicit3.C
> @@ -0,0 +1,24 @@
> +// P0892R2
> +// { dg-do compile }
> +// { dg-options "-std=c++2a" }
> +
> +#include <type_traits>
> +
> +template <typename T1, typename T2>
> +struct pair {
> +    template <typename U1=T1, typename U2=T2,
> +        std::enable_if_t<
> +            std::is_constructible_v<T1, U1> &&
> +            std::is_constructible_v<T2, U2>
> +        , int> = 0>
> +    explicit(!std::is_convertible_v<U1, T1> ||
> +        !std::is_convertible_v<U2, T2>)
> +    constexpr pair(U1&&, U2&&) { }
> +};
> +
> +void
> +foo ()
> +{
> +  pair<int, int> p{1, 2};
> +  pair<int, int> p2 = {1, 2};
> +}
> diff --git gcc/gcc/testsuite/g++.dg/cpp2a/explicit4.C 
> gcc/gcc/testsuite/g++.dg/cpp2a/explicit4.C
> index e69de29bb2d..822a1f155b4 100644
> --- gcc/gcc/testsuite/g++.dg/cpp2a/explicit4.C
> +++ gcc/gcc/testsuite/g++.dg/cpp2a/explicit4.C
> @@ -0,0 +1,41 @@
> +// P0892R2
> +// { dg-do compile }
> +// { dg-options "-std=c++2a" }
> +
> +template<int T = 1>
> +struct S {
> +  explicit(T) S(int);
> +  explicit(!T) S(int, int);
> +};
> +
> +template<typename T, int N>
> +struct S2 {
> +  explicit(N) S2(T);
> +};
> +
> +template<typename T>
> +struct S3 {
> +  explicit((T) 1.0) S3(int);
> +};
> +
> +int
> +main ()
> +{
> +  S<> s1 = { 1 }; // { dg-error "converting" }
> +  S<true> s2 = { 1 }; // { dg-error "converting" }
> +  S<false> s3 = { 1 };
> +  S<> s4{ 1 };
> +  S<true> s5{ 1 };
> +  S<> s6 = { 1, 2 };
> +  S<true> s7 = { 1, 2 };
> +  S<false> s8 = { 1, 2 }; // { dg-error "converting" }
> +  S<false> s9{ 1, 2 };
> +
> +  const int x = 1;
> +  S<x> s10 = { 1 }; // { dg-error "converting" }
> +  S<x> s11{ 2 };
> +
> +  S2<int, true> s12 = { 1 }; // { dg-error "converting" }
> +
> +  S3<int> s13 = { 1 }; // { dg-error "converting" }
> +}
> diff --git gcc/gcc/testsuite/g++.dg/cpp2a/explicit5.C 
> gcc/gcc/testsuite/g++.dg/cpp2a/explicit5.C
> index e69de29bb2d..70a106f1fcb 100644
> --- gcc/gcc/testsuite/g++.dg/cpp2a/explicit5.C
> +++ gcc/gcc/testsuite/g++.dg/cpp2a/explicit5.C
> @@ -0,0 +1,71 @@
> +// P0892R2
> +// { dg-do compile }
> +// { dg-options "-std=c++2a" }
> +
> +constexpr int fn0 () { return 0; }
> +constexpr int fn1 () { return 1; }
> +
> +struct S0 {
> +  explicit(false) operator int();
> +  explicit(1 == 0) operator double();
> +  explicit(fn0()) operator char();
> +};
> +
> +struct S1 {
> +  explicit(true) operator int();
> +  explicit(1 == 1) operator double();
> +  explicit(fn1()) operator char();
> +};
> +
> +struct X {
> +  static const bool value = true;
> +  static constexpr bool foo () { return 1; }
> +};
> +
> +struct T {
> +  explicit(true ? 1 : throw 1) operator int();
> +  explicit(true || true ? 1 : throw 1) operator double();
> +  explicit(X::value) operator char();
> +  explicit(X::foo ()) operator long();
> +};
> +
> +struct W {
> +  constexpr operator bool() { return true; };
> +};
> +
> +struct W2 {
> +  constexpr operator bool() { return false; };
> +};
> +
> +struct U1 {
> +  explicit(W()) operator int();
> +};
> +
> +struct U2 {
> +  explicit(W2()) operator int();
> +};
> +
> +int
> +main ()
> +{
> +  S0 s0;
> +  S1 s1;
> +  int i0 = s0;
> +  int i1 = s1; // { dg-error "cannot convert" }
> +  double d0 = s0;
> +  double d1 = s1; // { dg-error "cannot convert" }
> +  char c0 = s0;
> +  char c1 = s1; // { dg-error "cannot convert" }
> +
> +  T t;
> +  int i2 = t; // { dg-error "cannot convert" }
> +  double d2 = t; // { dg-error "cannot convert" }
> +  char c2 = t; // { dg-error "cannot convert" }
> +  long l1 = t; // { dg-error "cannot convert" }
> +
> +  U1 u1;
> +  int i3 = u1; // { dg-error "cannot convert" }
> +
> +  U2 u2;
> +  int i4 = u2;
> +}
> diff --git gcc/gcc/testsuite/g++.dg/cpp2a/explicit6.C 
> gcc/gcc/testsuite/g++.dg/cpp2a/explicit6.C
> index e69de29bb2d..10134680ed3 100644
> --- gcc/gcc/testsuite/g++.dg/cpp2a/explicit6.C
> +++ gcc/gcc/testsuite/g++.dg/cpp2a/explicit6.C
> @@ -0,0 +1,41 @@
> +// P0892R2
> +// { dg-do compile }
> +// { dg-options "-std=c++2a" }
> +
> +template<int T = 1>
> +struct S {
> +  explicit(T) operator int();
> +};
> +
> +template<typename T, int N>
> +struct R {
> +  explicit(N) operator T();
> +};
> +
> +template<typename T>
> +struct U {
> +  explicit((T) 1.0) operator T();
> +};
> +
> +int
> +main ()
> +{
> +  S s;
> +  int i1 = s; // { dg-error "cannot convert" }
> +  S<true> s2;
> +  int i2 = s2; // { dg-error "cannot convert" }
> +  S<false> s3;
> +  int i3 = s3;
> +  int i4{s};
> +  int i5{s2};
> +  int i6{s3};
> +
> +  R<int, true> r;
> +  int i7 = r; // { dg-error "cannot convert" }
> +  R<int, false> r2;
> +  int i8 = r2;
> +
> +  U<int> u;
> +  int i9 = u; // { dg-error "cannot convert" }
> +  int i10{u};
> +}
> diff --git gcc/gcc/testsuite/g++.dg/cpp2a/explicit7.C 
> gcc/gcc/testsuite/g++.dg/cpp2a/explicit7.C
> index e69de29bb2d..dfa4e138d4c 100644
> --- gcc/gcc/testsuite/g++.dg/cpp2a/explicit7.C
> +++ gcc/gcc/testsuite/g++.dg/cpp2a/explicit7.C
> @@ -0,0 +1,22 @@
> +// P0892R2
> +// { dg-do compile }
> +// { dg-options "-std=c++2a" }
> +
> +template<typename T>
> +struct B {
> +  static const T value = true;
> +};
> +
> +struct X {
> +  template<typename T>
> +  explicit(B<T>::value) operator T();
> +};
> +
> +int
> +main ()
> +{
> +  X x;
> +  int i = x.operator int();
> +  int i3 = x; // { dg-error "cannot convert" }
> +  int i2{x};
> +}
> diff --git gcc/gcc/testsuite/g++.dg/cpp2a/explicit8.C 
> gcc/gcc/testsuite/g++.dg/cpp2a/explicit8.C
> index e69de29bb2d..bf2f9ed9917 100644
> --- gcc/gcc/testsuite/g++.dg/cpp2a/explicit8.C
> +++ gcc/gcc/testsuite/g++.dg/cpp2a/explicit8.C
> @@ -0,0 +1,24 @@
> +// P0892R2
> +// { dg-do compile }
> +// { dg-options "-std=c++2a" }
> +
> +struct X {
> +  template<typename T, int N = 1>
> +  explicit(N) operator T();
> +};
> +
> +int
> +main ()
> +{
> +  X x;
> +  int i = x; // { dg-error "cannot convert" }
> +  int i2{x};
> +  double d = x; // { dg-error "cannot convert" }
> +  double d2{x};
> +  char c = x; // { dg-error "cannot convert" }
> +  char c2{x};
> +  long l = x; // { dg-error "cannot convert" }
> +  long l2{x};
> +  int *p = x; // { dg-error "cannot convert" }
> +  int *p2{x};
> +}
> diff --git gcc/gcc/testsuite/g++.dg/cpp2a/explicit9.C 
> gcc/gcc/testsuite/g++.dg/cpp2a/explicit9.C
> index e69de29bb2d..6568e5c6661 100644
> --- gcc/gcc/testsuite/g++.dg/cpp2a/explicit9.C
> +++ gcc/gcc/testsuite/g++.dg/cpp2a/explicit9.C
> @@ -0,0 +1,22 @@
> +// P0892R2
> +// { dg-do compile }
> +// { dg-options "-std=c++2a -fconcepts" }
> +
> +#include <type_traits>
> +
> +template <typename T1, typename T2>
> +struct pair {
> +    template <typename U1=T1, typename U2=T2>
> +        requires std::is_constructible_v<T1, U1> &&
> +            std::is_constructible_v<T2, U2>
> +    explicit(!std::is_convertible_v<U1, T1> ||
> +        !std::is_convertible_v<U2, T2>)
> +    constexpr pair(U1&&, U2&&) { }
> +};
> +
> +void
> +foo ()
> +{
> +  pair<int, int> p{1, 2};
> +  pair<int, int> p2 = {1, 2};
> +}
> diff --git gcc/libstdc++-v3/testsuite/20_util/any/cons/explicit.cc 
> gcc/libstdc++-v3/testsuite/20_util/any/cons/explicit.cc
> index f5425e09fba..3c13a86a2c9 100644
> --- gcc/libstdc++-v3/testsuite/20_util/any/cons/explicit.cc
> +++ gcc/libstdc++-v3/testsuite/20_util/any/cons/explicit.cc
> @@ -24,7 +24,7 @@
>  
>  int main()
>  {
> -  std::any a = {std::in_place_type<int>, 42}; // { dg-error "converting" }
> +  std::any a = {std::in_place_type<int>, 42}; // { dg-error "convert" }
>    std::any a2 = {std::in_place_type<std::vector<int>>,
> -              {42, 666}}; // { dg-error "converting" }
> +              {42, 666}}; // { dg-error "convert" }
>  }
> diff --git gcc/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc 
> gcc/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
> index 67603fb706f..6185ed6cdbc 100644
> --- gcc/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
> +++ gcc/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
> @@ -37,7 +37,7 @@ struct ExplicitDefaultDefault
>  
>  std::pair<int, int> f1() {return {1,2};}
>  
> -std::pair<Explicit, Explicit> f2() {return {1,2};} // { dg-error "explicit" }
> +std::pair<Explicit, Explicit> f2() {return {1,2};} // { dg-error "could not 
> convert" }
>  
>  std::pair<long, long> f3() {return std::pair<int, int>{1,2};}
>  
> @@ -52,7 +52,7 @@ std::pair<int, int> v0{1,2};
>  
>  std::pair<Explicit, Explicit> v1{1,2};
>  
> -std::pair<Explicit, Explicit> v2 = {1,2}; // { dg-error "explicit" }
> +std::pair<Explicit, Explicit> v2 = {1,2}; // { dg-error "could not convert" }
>  
>  std::pair<Explicit, Explicit> v3{std::pair<int,int>{1,2}};
>  
> @@ -83,12 +83,12 @@ void f7(std::pair<long, long>) {}
>  
>  std::pair<ExplicitDefault, int> f8()
>  {
> -  return {}; // { dg-error "explicit" }
> +  return {}; // { dg-error "could not convert" }
>  }
>  
>  std::pair<ExplicitDefaultDefault, int> f9()
>  {
> -  return {}; // { dg-error "explicit" }
> +  return {}; // { dg-error "could not convert" }
>  }
>  
>  void f10(std::pair<ExplicitDefault, int>) {}
> @@ -99,7 +99,7 @@ void test_arg_passing()
>  {
>    f6(v0); // { dg-error "could not convert" }
>    f6(v1);
> -  f6({1,2}); // { dg-error "explicit" }
> +  f6({1,2}); // { dg-error "could not convert" }
>    f6(std::pair<Explicit, Explicit>{});
>    f6(std::pair<int, int>{}); // { dg-error "could not convert" }
>    f7(v0);
> @@ -107,8 +107,8 @@ void test_arg_passing()
>    f7({1,2});
>    f7(std::pair<int, int>{});
>    f7(std::pair<long, long>{});
> -  f10({}); // { dg-error "explicit" }
> -  f11({}); // { dg-error "explicit" }
> +  f10({}); // { dg-error "could not convert" }
> +  f11({}); // { dg-error "could not convert" }
>    f10(std::pair<ExplicitDefault, int>{});
>    f11(std::pair<ExplicitDefaultDefault, int>{});
>  }
> @@ -130,6 +130,6 @@ std::pair<int*, ExplicitMoveOnly> v14{0, MoveOnly{}};
>  std::pair<ExplicitMoveOnly, int*> v15{MoveOnly{}, 0};
>  
>  std::pair<int*, ExplicitMoveOnly> v16 =
> -  {0, MoveOnly{}}; // { dg-error "explicit" }
> +  {0, MoveOnly{}}; // { dg-error "could not convert" }
>  std::pair<ExplicitMoveOnly, int*> v17 =
> -  {MoveOnly{}, 0}; // { dg-error "explicit" }
> +  {MoveOnly{}, 0}; // { dg-error "could not convert" }
> diff --git 
> gcc/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc 
> gcc/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
> index 2b1de37bb62..6874be40f71 100644
> --- gcc/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
> +++ gcc/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
> @@ -43,11 +43,11 @@ std::tuple<int, int> f1b() {return {1,2};}
>  std::tuple<int, int, int> f1c() {return {1,2,3};}
>  
>  std::tuple<Explicit> f2_a()
> -{return {1};} // { dg-error "explicit" }
> +{return {1};} // { dg-error "could not convert" }
>  std::tuple<Explicit, Explicit> f2_b()
> -{return {1,2};} // { dg-error "explicit" }
> +{return {1,2};} // { dg-error "could not convert" }
>  std::tuple<Explicit, Explicit, Explicit> f2_c()
> -{return {1,2,3};} // { dg-error "explicit" }
> +{return {1,2,3};} // { dg-error "could not convert" }
>  
>  std::tuple<long> f3_a() {return std::tuple<int>{1};}
>  std::tuple<long, long> f3_b() {return std::tuple<int, int>{1,2};}
> @@ -71,22 +71,22 @@ std::tuple<long, long> f5_b() {return {1,2};}
>  std::tuple<long, long, long> f5_c() {return {1,2,3};}
>  
>  std::tuple<ExplicitDefault> f6_a()
> -{return {};} // { dg-error "explicit" }
> +{return {};} // { dg-error "could not convert" }
>  std::tuple<ExplicitDefault, ExplicitDefault> f6_b()
> -{return {};} // { dg-error "explicit" }
> +{return {};} // { dg-error "could not convert" }
>  std::tuple<ExplicitDefault, ExplicitDefault, ExplicitDefault> f6_c()
> -{return {};} // { dg-error "explicit" }
> +{return {};} // { dg-error "could not convert" }
>  std::tuple<ExplicitDefault, int> f6_d()
> -{return {};} // { dg-error "explicit" }
> +{return {};} // { dg-error "could not convert" }
>  
>  std::tuple<ExplicitDefaultDefault> f7_a()
> -{return {};} // { dg-error "explicit" }
> +{return {};} // { dg-error "could not convert" }
>  std::tuple<ExplicitDefaultDefault, ExplicitDefaultDefault> f7_b()
> -{return {};} // { dg-error "explicit" }
> +{return {};} // { dg-error "could not convert" }
>  std::tuple<ExplicitDefaultDefault,
>             ExplicitDefaultDefault,
>             ExplicitDefaultDefault> f7_c()
> -{return {};} // { dg-error "explicit" }
> +{return {};} // { dg-error "could not convert" }
>  
>  std::tuple<int, int> fp1() {return std::pair<int, int>{1,2}; }
>  std::tuple<long, long> fp2() {return std::pair<int, int>{1,2}; }
> @@ -101,9 +101,9 @@ std::tuple<Explicit> v1_a{1};
>  std::tuple<Explicit, Explicit> v1_b{1,2};
>  std::tuple<Explicit, Explicit, Explicit> v1_c{1,2,3};
>  
> -std::tuple<Explicit> v2_a = {1}; // { dg-error "explicit" }
> -std::tuple<Explicit, Explicit> v2_b = {1,2}; // { dg-error "explicit" }
> -std::tuple<Explicit, Explicit, Explicit> v2_c = {1,2,3}; // { dg-error 
> "explicit" }
> +std::tuple<Explicit> v2_a = {1}; // { dg-error "could not convert" }
> +std::tuple<Explicit, Explicit> v2_b = {1,2}; // { dg-error "could not 
> convert" }
> +std::tuple<Explicit, Explicit, Explicit> v2_c = {1,2,3}; // { dg-error 
> "could not convert" }
>  
>  std::tuple<Explicit> v3_a{std::tuple<int>{1}};
>  std::tuple<Explicit, Explicit> v3_b{std::tuple<int,int>{1,2}};
> @@ -194,11 +194,11 @@ std::tuple<long, long, long>
>    v31_c{std::allocator_arg, std::allocator<int>{}, 1,2,3};
>  
>  std::tuple<Explicit> v32_a
> -  = {std::allocator_arg, std::allocator<int>{ }, 1}; // { dg-error 
> "explicit" }
> +  = {std::allocator_arg, std::allocator<int>{ }, 1}; // { dg-error "could 
> not convert" }
>  std::tuple<Explicit, Explicit> v32_b
> -  = {std::allocator_arg, std::allocator<int>{}, 1, 2}; // { dg-error 
> "explicit" }
> +  = {std::allocator_arg, std::allocator<int>{}, 1, 2}; // { dg-error "could 
> not convert" }
>  std::tuple<Explicit, Explicit, Explicit> v32_c
> -  = {std::allocator_arg, std::allocator<int>{}, 1,2,3}; // { dg-error 
> "explicit" }
> +  = {std::allocator_arg, std::allocator<int>{}, 1,2,3}; // { dg-error "could 
> not convert" }
>  
>  std::tuple<int, int> v33{std::allocator_arg, std::allocator<int>{},
>    std::pair<int, int>{1, 2}};
> @@ -216,7 +216,7 @@ std::tuple<long, long> v37 = {std::allocator_arg, 
> std::allocator<int>{},
>    std::pair<int, int>{1, 2}};
>  
>  std::tuple<Explicit, Explicit> v38
> -= {std::allocator_arg, std::allocator<int>{}, std::pair<int, int>{1, 2}}; // 
> { dg-error "explicit" }
> += {std::allocator_arg, std::allocator<int>{}, std::pair<int, int>{1, 2}}; // 
> { dg-error "could not convert" }
>  
>  std::tuple<int, int> v39{std::allocator_arg, std::allocator<int>{}, v20};
>  
> @@ -230,18 +230,18 @@ std::tuple<int, int> v42 = {std::allocator_arg, 
> std::allocator<int>{}, v20};
>  std::tuple<long, long> v43 = {std::allocator_arg, std::allocator<int>{}, 
> v20};
>  
>  std::tuple<Explicit, Explicit> v44
> -= {std::allocator_arg, std::allocator<int>{ }, v20}; // { dg-error 
> "explicit" }
> += {std::allocator_arg, std::allocator<int>{ }, v20}; // { dg-error "could 
> not convert" }
>  std::tuple<ExplicitDefault> v45_a{};
>  std::tuple<ExplicitDefault, int> v45_b{};
>  
> -std::tuple<ExplicitDefault> v46_a = {}; // { dg-error "explicit" }
> -std::tuple<ExplicitDefault, int> v46_b = {}; // { dg-error "explicit" }
> +std::tuple<ExplicitDefault> v46_a = {}; // { dg-error "could not convert" }
> +std::tuple<ExplicitDefault, int> v46_b = {}; // { dg-error "could not 
> convert" }
>  
>  std::tuple<ExplicitDefaultDefault> v47_a{};
>  std::tuple<ExplicitDefaultDefault, int> v47_b{};
>  
> -std::tuple<ExplicitDefaultDefault> v48_a = {}; // { dg-error "explicit" }
> -std::tuple<ExplicitDefaultDefault, int> v48_b = { }; // { dg-error 
> "explicit" }
> +std::tuple<ExplicitDefaultDefault> v48_a = {}; // { dg-error "could not 
> convert" }
> +std::tuple<ExplicitDefaultDefault, int> v48_b = { }; // { dg-error "could 
> not convert" }
>  
>  
>  struct DeletedCopy
> @@ -293,9 +293,9 @@ void test_arg_passing()
>    f8_b(v1_b);
>    f8_c(v1_c);
>  
> -  f8_a({1}); // { dg-error "explicit" }
> -  f8_b({1,2}); // { dg-error "explicit" }
> -  f8_c({1,2,3}); // { dg-error "explicit" }
> +  f8_a({1}); // { dg-error "could not convert" }
> +  f8_b({1,2}); // { dg-error "could not convert" }
> +  f8_c({1,2,3}); // { dg-error "could not convert" }
>  
>    f8_a(std::tuple<Explicit>{});
>    f8_b(std::tuple<Explicit, Explicit>{});
> @@ -328,10 +328,10 @@ void test_arg_passing()
>    f9_b(std::tuple<long, long>{});
>    f9_c(std::tuple<long, long, long>{});
>  
> -  f10_a({}); // { dg-error "explicit" }
> -  f10_b({}); // { dg-error "explicit" }
> -  f11_a({}); // { dg-error "explicit" }
> -  f11_b({}); // { dg-error "explicit" }
> +  f10_a({}); // { dg-error "could not convert" }
> +  f10_b({}); // { dg-error "could not convert" }
> +  f11_a({}); // { dg-error "could not convert" }
> +  f11_b({}); // { dg-error "could not convert" }
>  
>    f10_a(std::tuple<ExplicitDefault>{});
>    f10_b(std::tuple<ExplicitDefault, int>{});

Marek

Reply via email to