* C++ PATCH for c++/81359, Unparsed NSDMI error in SFINAE context
@ 2017-08-09 18:49 Jason Merrill
2017-08-10 7:35 ` Markus Trippelsdorf
0 siblings, 1 reply; 3+ messages in thread
From: Jason Merrill @ 2017-08-09 18:49 UTC (permalink / raw)
To: gcc-patches List
[-- Attachment #1: Type: text/plain, Size: 354 bytes --]
The issue here is that we try to determine the EH specification of
B::C::C() from within SFINAE context, and we can't determine it yet
because the NSDMI for B::C::i hasn't been parsed yet. This patch
allows that determination to fail quietly in SFINAE context; we'll try
again the next time it is needed.
Tested x86_64-pc-linux-gnu, applying to trunk.
[-- Attachment #2: 81359.diff --]
[-- Type: text/plain, Size: 18534 bytes --]
commit 616193fb149d17e8a671a46c03dca98aecbcc752
Author: Jason Merrill <jason@redhat.com>
Date: Tue Aug 8 12:49:42 2017 -0400
PR c++/81359 - Unparsed NSDMI error from SFINAE context.
* init.c (get_nsdmi): Add complain parm.
* typeck2.c (digest_nsdmi_init): Add complain parm.
(process_init_constructor_record): Pass complain to get_nsdmi.
* pt.c (maybe_instantiate_noexcept): Add complain parm, return bool.
* method.c (get_defaulted_eh_spec): Add complain parm. Pass it into
synthesized_method_walk.
(synthesized_method_walk): Adjust.
(walk_field_subobs): Pass complain to get_nsdmi.
(defaulted_late_check): Skip other checks if deleted.
* decl2.c (mark_used): Pass complain to maybe_instantiate_noexcept.
* call.c (build_aggr_conv): Pass complain to get_nsdmi.
* parser.c (defarg_location): New.
* error.c (location_of): Use it.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index fdd3731..4903119 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -916,7 +916,7 @@ build_aggr_conv (tree type, tree ctor, int flags, tsubst_flags_t complain)
if (i < CONSTRUCTOR_NELTS (ctor))
val = CONSTRUCTOR_ELT (ctor, i)->value;
else if (DECL_INITIAL (field))
- val = get_nsdmi (field, /*ctor*/false);
+ val = get_nsdmi (field, /*ctor*/false, complain);
else if (TREE_CODE (ftype) == REFERENCE_TYPE)
/* Value-initialization of reference is ill-formed. */
return NULL;
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 508570b..94738bd 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -8093,8 +8093,9 @@ resolve_address_of_overloaded_function (tree target_type,
continue;
/* In C++17 we need the noexcept-qualifier to compare types. */
- if (flag_noexcept_type)
- maybe_instantiate_noexcept (fn);
+ if (flag_noexcept_type
+ && !maybe_instantiate_noexcept (fn, complain))
+ continue;
/* See if there's a match. */
tree fntype = static_fn_type (fn);
@@ -8176,7 +8177,7 @@ resolve_address_of_overloaded_function (tree target_type,
/* In C++17 we need the noexcept-qualifier to compare types. */
if (flag_noexcept_type)
- maybe_instantiate_noexcept (instantiation);
+ maybe_instantiate_noexcept (instantiation, complain);
/* See if there's a match. */
tree fntype = static_fn_type (instantiation);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 115cdaf..3a0bd16 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6297,7 +6297,7 @@ extern tree get_type_value (tree);
extern tree build_zero_init (tree, tree, bool);
extern tree build_value_init (tree, tsubst_flags_t);
extern tree build_value_init_noctor (tree, tsubst_flags_t);
-extern tree get_nsdmi (tree, bool);
+extern tree get_nsdmi (tree, bool, tsubst_flags_t);
extern tree build_offset_ref (tree, tree, bool,
tsubst_flags_t);
extern tree throw_bad_array_new_length (void);
@@ -6355,7 +6355,7 @@ extern bool trivial_fn_p (tree);
extern tree forward_parm (tree);
extern bool is_trivially_xible (enum tree_code, tree, tree);
extern bool is_xible (enum tree_code, tree, tree);
-extern tree get_defaulted_eh_spec (tree);
+extern tree get_defaulted_eh_spec (tree, tsubst_flags_t = tf_warning_or_error);
extern void after_nsdmi_defaulted_late_checks (tree);
extern bool maybe_explain_implicit_delete (tree);
extern void explain_implicit_non_constexpr (tree);
@@ -6385,6 +6385,7 @@ extern tree cp_convert_range_for (tree, tree, tree, tree, unsigned int, bool);
extern bool parsing_nsdmi (void);
extern bool parsing_default_capturing_generic_lambda_in_template (void);
extern void inject_this_parameter (tree, cp_cv_quals);
+extern location_t defarg_location (tree);
/* in pt.c */
extern bool check_template_shadow (tree);
@@ -6448,7 +6449,7 @@ extern int more_specialized_fn (tree, tree, int);
extern void do_decl_instantiation (tree, tree);
extern void do_type_instantiation (tree, tree, tsubst_flags_t);
extern bool always_instantiate_p (tree);
-extern void maybe_instantiate_noexcept (tree);
+extern bool maybe_instantiate_noexcept (tree, tsubst_flags_t = tf_warning_or_error);
extern tree instantiate_decl (tree, bool, bool);
extern int comp_template_parms (const_tree, const_tree);
extern bool builtin_pack_fn_p (tree);
@@ -7166,7 +7167,7 @@ extern tree split_nonconstant_init (tree, tree);
extern bool check_narrowing (tree, tree, tsubst_flags_t);
extern tree digest_init (tree, tree, tsubst_flags_t);
extern tree digest_init_flags (tree, tree, int, tsubst_flags_t);
-extern tree digest_nsdmi_init (tree, tree);
+extern tree digest_nsdmi_init (tree, tree, tsubst_flags_t);
extern tree build_scoped_ref (tree, tree, tree *);
extern tree build_x_arrow (location_t, tree,
tsubst_flags_t);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 2a52f8c..8187ab9 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4988,8 +4988,9 @@ mark_used (tree decl, tsubst_flags_t complain)
if (TREE_CODE (decl) == CONST_DECL)
used_types_insert (DECL_CONTEXT (decl));
- if (TREE_CODE (decl) == FUNCTION_DECL)
- maybe_instantiate_noexcept (decl);
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && !maybe_instantiate_noexcept (decl, complain))
+ return false;
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DELETED_FN (decl))
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 2497c7f..31ca8fe 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -3046,6 +3046,8 @@ location_of (tree t)
if (DECL_P (t))
return DECL_SOURCE_LOCATION (t);
+ if (TREE_CODE (t) == DEFAULT_ARG)
+ return defarg_location (t);
return EXPR_LOC_OR_LOC (t, input_location);
}
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 81804112..83e685c 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -536,7 +536,7 @@ perform_target_ctor (tree init)
/* Return the non-static data initializer for FIELD_DECL MEMBER. */
tree
-get_nsdmi (tree member, bool in_ctor)
+get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
{
tree init;
tree save_ccp = current_class_ptr;
@@ -554,50 +554,54 @@ get_nsdmi (tree member, bool in_ctor)
{
init = DECL_INITIAL (DECL_TI_TEMPLATE (member));
if (TREE_CODE (init) == DEFAULT_ARG)
- goto unparsed;
-
+ /* Unparsed. */;
/* Check recursive instantiation. */
- if (DECL_INSTANTIATING_NSDMI_P (member))
+ else if (DECL_INSTANTIATING_NSDMI_P (member))
{
- error ("recursive instantiation of non-static data member "
- "initializer for %qD", member);
+ if (complain & tf_error)
+ error ("recursive instantiation of default member "
+ "initializer for %qD", member);
init = error_mark_node;
}
else
{
DECL_INSTANTIATING_NSDMI_P (member) = 1;
-
+
/* Do deferred instantiation of the NSDMI. */
init = (tsubst_copy_and_build
(init, DECL_TI_ARGS (member),
- tf_warning_or_error, member, /*function_p=*/false,
+ complain, member, /*function_p=*/false,
/*integral_constant_expression_p=*/false));
- init = digest_nsdmi_init (member, init);
+ init = digest_nsdmi_init (member, init, complain);
DECL_INSTANTIATING_NSDMI_P (member) = 0;
}
}
else
+ init = DECL_INITIAL (member);
+
+ if (init && TREE_CODE (init) == DEFAULT_ARG)
{
- init = DECL_INITIAL (member);
- if (init && TREE_CODE (init) == DEFAULT_ARG)
+ if (complain & tf_error)
{
- unparsed:
- error ("constructor required before non-static data member "
- "for %qD has been parsed", member);
+ error ("default member initializer for %qD required before the end "
+ "of its enclosing class", member);
+ inform (location_of (init), "defined here");
DECL_INITIAL (member) = error_mark_node;
- init = error_mark_node;
}
- /* Strip redundant TARGET_EXPR so we don't need to remap it, and
- so the aggregate init code below will see a CONSTRUCTOR. */
- bool simple_target = (init && SIMPLE_TARGET_EXPR_P (init));
- if (simple_target)
- init = TARGET_EXPR_INITIAL (init);
- init = break_out_target_exprs (init);
- if (simple_target && TREE_CODE (init) != CONSTRUCTOR)
- /* Now put it back so C++17 copy elision works. */
- init = get_target_expr (init);
+ init = error_mark_node;
}
+
+ /* Strip redundant TARGET_EXPR so we don't need to remap it, and
+ so the aggregate init code below will see a CONSTRUCTOR. */
+ bool simple_target = (init && SIMPLE_TARGET_EXPR_P (init));
+ if (simple_target)
+ init = TARGET_EXPR_INITIAL (init);
+ init = break_out_target_exprs (init);
+ if (simple_target && TREE_CODE (init) != CONSTRUCTOR)
+ /* Now put it back so C++17 copy elision works. */
+ init = get_target_expr (init);
+
current_class_ptr = save_ccp;
current_class_ref = save_ccr;
return init;
@@ -644,7 +648,7 @@ perform_member_init (tree member, tree init)
/* Use the non-static data member initializer if there was no
mem-initializer for this field. */
if (init == NULL_TREE)
- init = get_nsdmi (member, /*ctor*/true);
+ init = get_nsdmi (member, /*ctor*/true, tf_warning_or_error);
if (init == error_mark_node)
return;
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 8b07f52..bff9605 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1357,7 +1357,7 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
default constructor is noexcept(false). */
if (spec_p)
{
- tree nsdmi = get_nsdmi (field, /*ctor*/false);
+ tree nsdmi = get_nsdmi (field, /*ctor*/false, complain);
if (!expr_noexcept_p (nsdmi, complain))
*spec_p = noexcept_false_spec;
}
@@ -1660,6 +1660,10 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
flags |= LOOKUP_DEFAULTED;
tsubst_flags_t complain = diag ? tf_warning_or_error : tf_none;
+ if (diag && spec_p)
+ /* We're in get_defaulted_eh_spec; we don't actually want any walking
+ diagnostics, we just want complain set. */
+ diag = false;
int quals = const_p ? TYPE_QUAL_CONST : TYPE_UNQUALIFIED;
for (binfo = TYPE_BINFO (ctype), i = 0;
@@ -1749,7 +1753,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
needed. Return what it should be. */
tree
-get_defaulted_eh_spec (tree decl)
+get_defaulted_eh_spec (tree decl, tsubst_flags_t complain)
{
if (DECL_CLONED_FUNCTION_P (decl))
decl = DECL_CLONED_FUNCTION (decl);
@@ -1759,8 +1763,9 @@ get_defaulted_eh_spec (tree decl)
tree parm_type = TREE_VALUE (parms);
bool const_p = CP_TYPE_CONST_P (non_reference (parm_type));
tree spec = empty_except_spec;
+ bool diag = !DECL_DELETED_FN (decl) && (complain & tf_error);
synthesized_method_walk (ctype, sfk, const_p, &spec, NULL, NULL,
- NULL, false, DECL_INHERITED_CTOR (decl),
+ NULL, diag, DECL_INHERITED_CTOR (decl),
parms);
return spec;
}
@@ -2173,6 +2178,12 @@ defaulted_late_check (tree fn)
"does not match expected signature %qD", implicit_fn);
}
+ if (DECL_DELETED_FN (implicit_fn))
+ {
+ DECL_DELETED_FN (fn) = 1;
+ return;
+ }
+
/* 8.4.2/2: An explicitly-defaulted function (...) may have an explicit
exception-specification only if it is compatible (15.4) with the
exception-specification on the implicit declaration. If a function
@@ -2231,9 +2242,6 @@ defaulted_late_check (tree fn)
}
DECL_DECLARED_CONSTEXPR_P (fn) = false;
}
-
- if (DECL_DELETED_FN (implicit_fn))
- DECL_DELETED_FN (fn) = 1;
}
/* OK, we've parsed the NSDMI for class T, now we can check any explicit
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 23bd278..9458f2f 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -27431,7 +27431,7 @@ cp_parser_late_parse_one_default_arg (cp_parser *parser, tree decl,
else if (maybe_reject_flexarray_init (decl, parsed_arg))
parsed_arg = error_mark_node;
else
- parsed_arg = digest_nsdmi_init (decl, parsed_arg);
+ parsed_arg = digest_nsdmi_init (decl, parsed_arg, tf_warning_or_error);
}
/* If the token stream has not been completely used up, then
@@ -28681,6 +28681,17 @@ cp_parser_cache_defarg (cp_parser *parser, bool nsdmi)
return default_argument;
}
+/* A location to use for diagnostics about an unparsed DEFAULT_ARG. */
+
+location_t
+defarg_location (tree default_argument)
+{
+ cp_token_cache *tokens = DEFARG_TOKENS (default_argument);
+ location_t start = tokens->first->location;
+ location_t end = tokens->last->location;
+ return make_location (start, start, end);
+}
+
/* Begin parsing tentatively. We always save tokens while parsing
tentatively so that if the tentative parsing fails we can restore the
tokens. */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index bd61438..3d6f4b5 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -22493,16 +22493,17 @@ always_instantiate_p (tree decl)
}
/* If FN has a noexcept-specifier that hasn't been instantiated yet,
- instantiate it now, modifying TREE_TYPE (fn). */
+ instantiate it now, modifying TREE_TYPE (fn). Returns false on
+ error, true otherwise. */
-void
-maybe_instantiate_noexcept (tree fn)
+bool
+maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
{
tree fntype, spec, noex, clone;
/* Don't instantiate a noexcept-specification from template context. */
if (processing_template_decl)
- return;
+ return true;
if (DECL_CLONED_FUNCTION_P (fn))
fn = DECL_CLONED_FUNCTION (fn);
@@ -22510,7 +22511,7 @@ maybe_instantiate_noexcept (tree fn)
spec = TYPE_RAISES_EXCEPTIONS (fntype);
if (!spec || !TREE_PURPOSE (spec))
- return;
+ return true;
noex = TREE_PURPOSE (spec);
@@ -22519,7 +22520,7 @@ maybe_instantiate_noexcept (tree fn)
static hash_set<tree>* fns = new hash_set<tree>;
bool added = false;
if (DEFERRED_NOEXCEPT_PATTERN (noex) == NULL_TREE)
- spec = get_defaulted_eh_spec (fn);
+ spec = get_defaulted_eh_spec (fn, complain);
else if (!(added = !fns->add (fn)))
{
/* If hash_set::add returns true, the element was already there. */
@@ -22553,6 +22554,9 @@ maybe_instantiate_noexcept (tree fn)
if (added)
fns->remove (fn);
+ if (spec == error_mark_node)
+ return false;
+
TREE_TYPE (fn) = build_exception_variant (fntype, spec);
}
@@ -22563,6 +22567,8 @@ maybe_instantiate_noexcept (tree fn)
else
TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone), spec);
}
+
+ return true;
}
/* Produce the definition of D, a _DECL generated from a template. If
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 430ba30..06c079e 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1182,7 +1182,7 @@ digest_init_flags (tree type, tree init, int flags, tsubst_flags_t complain)
/* Process the initializer INIT for an NSDMI DECL (a FIELD_DECL). */
tree
-digest_nsdmi_init (tree decl, tree init)
+digest_nsdmi_init (tree decl, tree init, tsubst_flags_t complain)
{
gcc_assert (TREE_CODE (decl) == FIELD_DECL);
@@ -1192,8 +1192,8 @@ digest_nsdmi_init (tree decl, tree init)
flags = LOOKUP_NORMAL;
if (BRACE_ENCLOSED_INITIALIZER_P (init)
&& CP_AGGREGATE_TYPE_P (type))
- init = reshape_init (type, init, tf_warning_or_error);
- init = digest_init_flags (type, init, flags, tf_warning_or_error);
+ init = reshape_init (type, init, complain);
+ init = digest_init_flags (type, init, flags, complain);
if (TREE_CODE (init) == TARGET_EXPR)
/* This represents the whole initialization. */
TARGET_EXPR_DIRECT_INIT_P (init) = true;
@@ -1427,7 +1427,7 @@ process_init_constructor_record (tree type, tree init,
goto restart;
}
/* C++14 aggregate NSDMI. */
- next = get_nsdmi (field, /*ctor*/false);
+ next = get_nsdmi (field, /*ctor*/false, complain);
}
else if (type_build_ctor_call (TREE_TYPE (field)))
{
@@ -1525,7 +1525,8 @@ process_init_constructor_union (tree type, tree init,
{
CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (init),
field,
- get_nsdmi (field, /*in_ctor=*/false));
+ get_nsdmi (field, /*in_ctor=*/false,
+ complain));
break;
}
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer6.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer6.C
index 0f06343..056d16d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer6.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer6.C
@@ -2,7 +2,7 @@
struct A
{
- int i = (A(), 42); // { dg-error "constructor required" }
+ int i = (A(), 42); // { dg-error "" }
};
A a;
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template14.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template14.C
index 1a00ec0..a885a24 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template14.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template14.C
@@ -3,14 +3,14 @@
template<int> struct A
{
- int i = (A<0>(), 0); // { dg-error "recursive instantiation of non-static data" }
+ int i = (A<0>(), 0); // { dg-error "recursive instantiation of default" }
};
A<0> a;
template<int N> struct B
{
- B* p = new B<N>; // { dg-error "recursive instantiation of non-static data" }
+ B* p = new B<N>; // { dg-error "recursive instantiation of default" }
};
B<1> x;
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi10.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi10.C
index 56f9ff0..d8588b7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nsdmi10.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi10.C
@@ -6,7 +6,7 @@ struct A1 {
int y1 = 1;
};
- A1(const B1& opts = B1()) {} // { dg-error "constructor" }
+ A1(const B1& opts = B1()) {} // { dg-error "default member initializer" }
};
struct A2 {
@@ -14,5 +14,5 @@ struct A2 {
int x2, y2 = 1;
};
- A2(const B2& opts = B2()) {} // { dg-error "constructor" }
+ A2(const B2& opts = B2()) {} // { dg-error "default member initializer" }
};
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae59.C b/gcc/testsuite/g++.dg/cpp0x/sfinae59.C
new file mode 100644
index 0000000..d1c730b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae59.C
@@ -0,0 +1,19 @@
+// PR c++/81359
+// { dg-do compile { target c++11 } }
+
+template<typename _Tp, typename = decltype(_Tp())>
+static int test(int);
+
+template<typename>
+static void test(...);
+
+template <class T, class = decltype(test<T>(0))>
+struct A { };
+
+struct B
+{
+ struct C {
+ int i = 0;
+ };
+ A<C> a;
+};
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: C++ PATCH for c++/81359, Unparsed NSDMI error in SFINAE context
2017-08-09 18:49 C++ PATCH for c++/81359, Unparsed NSDMI error in SFINAE context Jason Merrill
@ 2017-08-10 7:35 ` Markus Trippelsdorf
2017-08-10 20:26 ` Jason Merrill
0 siblings, 1 reply; 3+ messages in thread
From: Markus Trippelsdorf @ 2017-08-10 7:35 UTC (permalink / raw)
To: Jason Merrill; +Cc: gcc-patches List
On 2017.08.09 at 14:30 -0400, Jason Merrill wrote:
> The issue here is that we try to determine the EH specification of
> B::C::C() from within SFINAE context, and we can't determine it yet
> because the NSDMI for B::C::i hasn't been parsed yet. This patch
> allows that determination to fail quietly in SFINAE context; we'll try
> again the next time it is needed.
Thanks.
Unfortunately it breaks the following testcase:
~ % cat asm-js.ii
struct A {
void operator delete(void *, unsigned long);
};
struct B : A {
virtual ~B();
};
struct C : B {};
~ % g++ -c asm-js.ii
asm-js.ii:7:8: error: no matching function for call to âC::operator delete(void*)â
struct C : B {};
^
asm-js.ii:2:8: note: candidate: âstatic void A::operator delete(void*, long unsigned int)â
void operator delete(void *, unsigned long);
^~~~~~~~
asm-js.ii:2:8: note: candidate expects 2 arguments, 1 provided
--
Markus
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: C++ PATCH for c++/81359, Unparsed NSDMI error in SFINAE context
2017-08-10 7:35 ` Markus Trippelsdorf
@ 2017-08-10 20:26 ` Jason Merrill
0 siblings, 0 replies; 3+ messages in thread
From: Jason Merrill @ 2017-08-10 20:26 UTC (permalink / raw)
To: Markus Trippelsdorf; +Cc: gcc-patches List
[-- Attachment #1: Type: text/plain, Size: 537 bytes --]
On Thu, Aug 10, 2017 at 12:13 AM, Markus Trippelsdorf
<markus@trippelsdorf.de> wrote:
> On 2017.08.09 at 14:30 -0400, Jason Merrill wrote:
>> The issue here is that we try to determine the EH specification of
>> B::C::C() from within SFINAE context, and we can't determine it yet
>> because the NSDMI for B::C::i hasn't been parsed yet. This patch
>> allows that determination to fail quietly in SFINAE context; we'll try
>> again the next time it is needed.
>
> Thanks.
>
> Unfortunately it breaks the following testcase:
Fixed thus:
[-- Attachment #2: vdelete.diff --]
[-- Type: text/plain, Size: 1587 bytes --]
commit 98a57ff77c97446c0477bea2aed831b62a0726a6
Author: Jason Merrill <jason@redhat.com>
Date: Thu Aug 10 12:23:12 2017 -0700
Fix regression from 81359 patch.
* method.c (synthesized_method_walk): Don't diagnose lack of
operator delete.
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index bff9605..809ebc8 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1693,12 +1693,18 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
if (check_vdtor && type_has_virtual_destructor (BINFO_TYPE (base_binfo)))
{
- fn = locate_fn_flags (ctype, cp_operator_id (DELETE_EXPR),
- ptr_type_node, flags, complain);
/* Unlike for base ctor/op=/dtor, for operator delete it's fine
to have a null fn (no class-specific op delete). */
- if (fn && fn == error_mark_node && deleted_p)
- *deleted_p = true;
+ fn = locate_fn_flags (ctype, cp_operator_id (DELETE_EXPR),
+ ptr_type_node, flags, tf_none);
+ if (fn && fn == error_mark_node)
+ {
+ if (complain & tf_error)
+ locate_fn_flags (ctype, cp_operator_id (DELETE_EXPR),
+ ptr_type_node, flags, complain);
+ if (deleted_p)
+ *deleted_p = true;
+ }
check_vdtor = false;
}
}
diff --git a/gcc/testsuite/g++.dg/inherit/vdtor1.C b/gcc/testsuite/g++.dg/inherit/vdtor1.C
new file mode 100644
index 0000000..caba17f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/vdtor1.C
@@ -0,0 +1,7 @@
+struct A {
+ void operator delete(void *, unsigned long);
+};
+struct B : A {
+ virtual ~B();
+};
+struct C : B {};
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2017-08-10 19:56 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-09 18:49 C++ PATCH for c++/81359, Unparsed NSDMI error in SFINAE context Jason Merrill
2017-08-10 7:35 ` Markus Trippelsdorf
2017-08-10 20:26 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).