Re: C++ PATCH to implement C++20 P0892R2 - explicit(bool) [v4]

2018-10-30 Thread Jason Merrill

On 10/29/18 6:15 PM, Marek Polacek wrote:

On Wed, Oct 24, 2018 at 02:55:14PM -0400, Jason Merrill wrote:

On 10/12/18 12:32 PM, Marek Polacek wrote:

+   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)


Why not add the explicit-specifier to cp_decl_specifier_seq?  They don't
live very long, so making them bigger isn't a concern.  Then other of the
handling could move into grokdeclarator along with the other explicit
handling.


Great -- that simplifies things.


@@ -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);
+   }


This is setting DECL_NONCONVERTING_P on the template, rather than the
instantiation r, which hasn't been created yet at this point; this handling
needs to move further down in the function.


Hmm, interesting that that worked, too.  Anyway, fixed.  Thanks!


It worked for the testcase because that bit was then copied to the 
instantiation.  I'm surprised that converting b0 in explicit13.C worked, 
though.



+  /* 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 (r) = (spec == boolean_true_node);
+}


It still surprises me that you don't need to store the partially 
instantiated explicit-specifier, but explicit13.C does seem to cover the 
cases I would expect to break.



Bootstrapped/regtested on x86_64-linux, ok for trunk?


OK.

Jason


Re: C++ PATCH to implement C++20 P0892R2 - explicit(bool) [v4]

2018-10-29 Thread Marek Polacek
On Wed, Oct 24, 2018 at 02:55:14PM -0400, Jason Merrill wrote:
> On 10/12/18 12:32 PM, Marek Polacek wrote:
> > +   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)
> 
> Why not add the explicit-specifier to cp_decl_specifier_seq?  They don't
> live very long, so making them bigger isn't a concern.  Then other of the
> handling could move into grokdeclarator along with the other explicit
> handling.

Great -- that simplifies things.

> > @@ -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);
> > +   }
> 
> This is setting DECL_NONCONVERTING_P on the template, rather than the
> instantiation r, which hasn't been created yet at this point; this handling
> needs to move further down in the function.

Hmm, interesting that that worked, too.  Anyway, fixed.  Thanks!

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2018-10-29  Marek Polacek  

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.
(cp_decl_specifier_seq): Add explicit_specifier field.
(build_explicit_specifier, store_explicit_specifier): Declare.
* decl.c (grokdeclarator): Call store_explicit_specifier.
(build_explicit_specifier): New function.
* parser.c (cp_parser_function_specifier_opt) :
Parse C++20 explicit(bool).
* 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 cd0c0f60ced..e3453aca96e 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