diff mbox series

c++: Fix access checking for __is_assignable and __is_constructible (c++/94197)

Message ID CAFk2RUbzGttMNp8br5nk3vox4F7=UpkUpnsL_rPQrYb3M9JXzA@mail.gmail.com
State New
Headers show
Series c++: Fix access checking for __is_assignable and __is_constructible (c++/94197) | expand

Commit Message

Li, Pan2 via Gcc-patches March 16, 2020, 9:25 p.m. UTC
Tested on Linux-PPC64.

This ain't no regression. But it seems to hamper attempts to fix library
regressions (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94033).

2020-03-16  Ville Voutilainen  <ville.voutilainen@gmail.com>

    gcc/

    PR c++/94197
    * cp/method.c (assignable_expr, constructible_expr): Push
    a deferred access check for the stub object.

    testsuite/

    PR c++/94197
    * g++.dg/ext/pr94197.C: New.

Comments

Li, Pan2 via Gcc-patches March 16, 2020, 10:13 p.m. UTC | #1
On Mon, 16 Mar 2020 at 23:25, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
>
> Tested on Linux-PPC64.
>
> This ain't no regression. But it seems to hamper attempts to fix library
> regressions (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94033).

It occurred to me that this can be done in one place.

2020-03-17  Ville Voutilainen  <ville.voutilainen@gmail.com>

    gcc/

    PR c++/94197
    * cp/method.c (assignable_expr): Use cp_unevaluated.
    (is_xible_helper): Push a non-deferred access check for
    the stub objects created by assignable_expr and constructible_expr.

    testsuite/

    PR c++/94197
    * g++.dg/ext/pr94197.C: New.
Li, Pan2 via Gcc-patches March 16, 2020, 10:58 p.m. UTC | #2
On 3/16/20 6:13 PM, Ville Voutilainen wrote:
> On Mon, 16 Mar 2020 at 23:25, Ville Voutilainen
> <ville.voutilainen@gmail.com> wrote:
>>
>> Tested on Linux-PPC64.
>>
>> This ain't no regression. But it seems to hamper attempts to fix library
>> regressions (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94033).
> 
> It occurred to me that this can be done in one place.
> 
> 2020-03-17  Ville Voutilainen  <ville.voutilainen@gmail.com>
> 
>      gcc/
> 
>      PR c++/94197
>      * cp/method.c (assignable_expr): Use cp_unevaluated.
>      (is_xible_helper): Push a non-deferred access check for
>      the stub objects created by assignable_expr and constructible_expr.

It occurs to me that we don't need to defer access control in 
instantiate_template_1 if we're instantiating an alias template, but 
this patch is OK as is.

Jason
Li, Pan2 via Gcc-patches March 17, 2020, 1:02 p.m. UTC | #3
Shouldn't the test use { dg-do compile { target c++11 } } instead of:

+// { dg-do compile }
+// { dg-options "-std=c++11" }

?
Li, Pan2 via Gcc-patches March 17, 2020, 1:04 p.m. UTC | #4
On 17/03/20 13:02 +0000, Jonathan Wakely wrote:
>Shouldn't the test use { dg-do compile { target c++11 } } instead of:
>
>+// { dg-do compile }
>+// { dg-options "-std=c++11" }
>
>?
>

With that change I see:

UNSUPPORTED: g++.dg/ext/pr94197.C  -std=c++98
PASS: g++.dg/ext/pr94197.C  -std=c++14 (test for excess errors)
PASS: g++.dg/ext/pr94197.C  -std=c++17 (test for excess errors)
PASS: g++.dg/ext/pr94197.C  -std=c++2a (test for excess errors)

rather than:

PASS: g++.dg/ext/pr94197.C   (test for excess errors)
Li, Pan2 via Gcc-patches March 17, 2020, 2:42 p.m. UTC | #5
On 3/17/20 9:04 AM, Jonathan Wakely wrote:
> On 17/03/20 13:02 +0000, Jonathan Wakely wrote:
>> Shouldn't the test use { dg-do compile { target c++11 } } instead of:
>>
>> +// { dg-do compile }
>> +// { dg-options "-std=c++11" }
>>
>> ?
>>
> 
> With that change I see:
> 
> UNSUPPORTED: g++.dg/ext/pr94197.C  -std=c++98
> PASS: g++.dg/ext/pr94197.C  -std=c++14 (test for excess errors)
> PASS: g++.dg/ext/pr94197.C  -std=c++17 (test for excess errors)
> PASS: g++.dg/ext/pr94197.C  -std=c++2a (test for excess errors)
> 
> rather than:
> 
> PASS: g++.dg/ext/pr94197.C   (test for excess errors)

Yes, good point.

Jason
Li, Pan2 via Gcc-patches March 17, 2020, 2:52 p.m. UTC | #6
On Tue, 17 Mar 2020 at 16:42, Jason Merrill <jason@redhat.com> wrote:
>
> On 3/17/20 9:04 AM, Jonathan Wakely wrote:
> > On 17/03/20 13:02 +0000, Jonathan Wakely wrote:
> >> Shouldn't the test use { dg-do compile { target c++11 } } instead of:
> >>
> >> +// { dg-do compile }
> >> +// { dg-options "-std=c++11" }
>
> Yes, good point.

Ack, changing to { dg-do compile { target c++11 } } and committing
with the (correct :P) expectation that
the change is still ok with that change.
Li, Pan2 via Gcc-patches March 17, 2020, 3:25 p.m. UTC | #7
On Tue, 17 Mar 2020 at 16:52, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
>
> On Tue, 17 Mar 2020 at 16:42, Jason Merrill <jason@redhat.com> wrote:
> >
> > On 3/17/20 9:04 AM, Jonathan Wakely wrote:
> > > On 17/03/20 13:02 +0000, Jonathan Wakely wrote:
> > >> Shouldn't the test use { dg-do compile { target c++11 } } instead of:
> > >>
> > >> +// { dg-do compile }
> > >> +// { dg-options "-std=c++11" }
> >
> > Yes, good point.
>
> Ack, changing to { dg-do compile { target c++11 } } and committing
> with the (correct :P) expectation that
> the change is still ok with that change.

Jason, are backports ok too?
Li, Pan2 via Gcc-patches March 17, 2020, 7:48 p.m. UTC | #8
On 3/17/20 11:25 AM, Ville Voutilainen wrote:
> On Tue, 17 Mar 2020 at 16:52, Ville Voutilainen
> <ville.voutilainen@gmail.com> wrote:
>>
>> On Tue, 17 Mar 2020 at 16:42, Jason Merrill <jason@redhat.com> wrote:
>>>
>>> On 3/17/20 9:04 AM, Jonathan Wakely wrote:
>>>> On 17/03/20 13:02 +0000, Jonathan Wakely wrote:
>>>>> Shouldn't the test use { dg-do compile { target c++11 } } instead of:
>>>>>
>>>>> +// { dg-do compile }
>>>>> +// { dg-options "-std=c++11" }
>>>
>>> Yes, good point.
>>
>> Ack, changing to { dg-do compile { target c++11 } } and committing
>> with the (correct :P) expectation that
>> the change is still ok with that change.
> 
> Jason, are backports ok too?

Yes.

Jason
diff mbox series

Patch

diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 790d5704092..b429ea48049 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1739,11 +1739,11 @@  check_nontriv (tree *tp, int *, void *)
 static tree
 assignable_expr (tree to, tree from)
 {
-  ++cp_unevaluated_operand;
+  cp_unevaluated cp_uneval_guard;
+  deferring_access_check_sentinel acs (dk_no_deferred);
   to = build_stub_object (to);
   from = build_stub_object (from);
   tree r = cp_build_modify_expr (input_location, to, NOP_EXPR, from, tf_none);
-  --cp_unevaluated_operand;
   return r;
 }
 
@@ -1759,6 +1759,7 @@  constructible_expr (tree to, tree from)
 {
   tree expr;
   cp_unevaluated cp_uneval_guard;
+  deferring_access_check_sentinel acs (dk_no_deferred);
   if (CLASS_TYPE_P (to))
     {
       tree ctype = to;
diff --git a/gcc/testsuite/g++.dg/ext/pr94197.C b/gcc/testsuite/g++.dg/ext/pr94197.C
new file mode 100644
index 00000000000..768bfbac0a6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/pr94197.C
@@ -0,0 +1,75 @@ 
+// { dg-do compile }
+// { dg-options "-std=c++11" }
+
+template<typename T>
+  T&& declval() noexcept;
+
+template<bool B>
+struct bool_constant
+{
+  static constexpr bool value = B;
+  using type = bool_constant;
+};
+
+using true_type = bool_constant<true>;
+using false_type = bool_constant<false>;
+
+template<bool, typename T, typename Arg>
+  struct __is_nt_constructible_impl
+  : public false_type
+  { };
+
+template<typename T, typename Arg>
+  struct __is_nt_constructible_impl<true, T, Arg>
+  : public bool_constant<noexcept(static_cast<T>(declval<Arg>()))>
+  { };
+
+template<typename T, typename Arg>
+  using __is_nothrow_constructible_impl
+    = __is_nt_constructible_impl<__is_constructible(T, Arg), T, Arg>;
+
+template<typename T>
+  struct __is_nothrow_copy_constructible_impl
+  : public __is_nothrow_constructible_impl<T, const T&>
+  { };
+
+template<typename T>
+  struct is_nothrow_copy_constructible
+  : public __is_nothrow_copy_constructible_impl<T>::type
+  { };
+
+template<bool, typename T, typename Arg>
+  struct __is_nt_assignable_impl
+  : public false_type
+  { };
+
+template<typename T, typename Arg>
+  struct __is_nt_assignable_impl<true, T, Arg>
+  : public bool_constant<noexcept(declval<T&>() = declval<Arg>())>
+  { };
+
+template<typename T, typename Arg>
+  using __is_nothrow_assignable_impl
+    = __is_nt_assignable_impl<__is_assignable(T, Arg), T, Arg>;
+
+template<typename T>
+  struct __is_nothrow_copy_assignable_impl
+  : public __is_nothrow_assignable_impl<T, const T&>
+  { };
+
+template<typename T>
+  struct is_nothrow_copy_assignable
+  : public __is_nothrow_copy_assignable_impl<T>::type
+  { };
+
+struct NType
+{
+  NType();
+private:
+  NType(const NType&);
+  NType& operator=(const NType&);
+};
+
+
+static_assert( !is_nothrow_copy_constructible<NType>::value, "" );
+static_assert( !is_nothrow_copy_assignable<NType>::value, "" );