aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2021-08-29 18:17:22 -0400
committerJason Merrill <jason@redhat.com>2021-08-30 17:25:21 -0400
commit8960a29b18b830ff0490b7f52051903fba472e45 (patch)
tree35a7a49679fa0b3925eb27ea96f7eaf295f5e535 /gcc
parent729f6881cfcc6df3c15a1dd4ebd45bc46bb8f3e9 (diff)
downloadgcc-8960a29b18b830ff0490b7f52051903fba472e45.zip
gcc-8960a29b18b830ff0490b7f52051903fba472e45.tar.gz
gcc-8960a29b18b830ff0490b7f52051903fba472e45.tar.bz2
c++: limit instantiation with ill-formed class [PR96286]
I noticed that after the static_assert failures in lwg3466.cc, we got various follow-on errors because we went ahead and tried to instantiate the promise<T> member functions even after instantiating the class itself ran into problems. Interrupting instantiation of the class itself seems likely to cause error-recovery problems, but preventing instantiation of member functions seems strictly better for error-recovery. This doesn't fix any of the specific testcases in PR96286, but addresses part of that problem space. PR c++/96286 gcc/cp/ChangeLog: * cp-tree.h (struct lang_type): Add erroneous bit-field. (CLASSTYPE_ERRONEOUS): New. * pt.c (limit_bad_template_recursion): Check it. (instantiate_class_template_1): Set it. libstdc++-v3/ChangeLog: * testsuite/30_threads/promise/requirements/lwg3466.cc: Remove dg-prune-outputs. gcc/testsuite/ChangeLog: * g++.dg/template/access2.C: Split struct A.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/cp-tree.h7
-rw-r--r--gcc/cp/pt.c14
-rw-r--r--gcc/testsuite/g++.dg/template/access2.C6
3 files changed, 24 insertions, 3 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 6a17937..ce7ca53 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2336,6 +2336,7 @@ struct GTY(()) lang_type {
unsigned has_constexpr_ctor : 1;
unsigned unique_obj_representations : 1;
unsigned unique_obj_representations_set : 1;
+ bool erroneous : 1;
/* When adding a flag here, consider whether or not it ought to
apply to a template instance if it applies to the template. If
@@ -2344,7 +2345,7 @@ struct GTY(()) lang_type {
/* There are some bits left to fill out a 32-bit word. Keep track
of this by updating the size of this bitfield whenever you add or
remove a flag. */
- unsigned dummy : 5;
+ unsigned dummy : 4;
tree primary_base;
vec<tree_pair_s, va_gc> *vcall_indices;
@@ -2660,6 +2661,10 @@ struct GTY(()) lang_type {
/* Nonzero if a _DECL node requires us to output debug info for this class. */
#define CLASSTYPE_DEBUG_REQUESTED(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->debug_requested)
+
+/* True if we saw errors while instantiating this class. */
+#define CLASSTYPE_ERRONEOUS(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->erroneous)
/* Additional macros for inheritance information. */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index d7d0dce..fcf3ac3 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -10885,9 +10885,14 @@ limit_bad_template_recursion (tree decl)
{
struct tinst_level *lev = current_tinst_level;
int errs = errorcount + sorrycount;
- if (lev == NULL || errs == 0 || !neglectable_inst_p (decl))
+ if (errs == 0 || !neglectable_inst_p (decl))
return false;
+ /* Avoid instantiating members of an ill-formed class. */
+ if (DECL_CLASS_SCOPE_P (decl)
+ && CLASSTYPE_ERRONEOUS (DECL_CONTEXT (decl)))
+ return true;
+
for (; lev; lev = lev->next)
if (neglectable_inst_p (lev->maybe_get_node ()))
break;
@@ -12212,6 +12217,13 @@ instantiate_class_template_1 (tree type)
finish_struct_1 (type);
TYPE_BEING_DEFINED (type) = 0;
+ /* Remember if instantiating this class ran into errors, so we can avoid
+ instantiating member functions in limit_bad_template_recursion. We set
+ this flag even if the problem was in another instantiation triggered by
+ this one, as that will likely also cause trouble for member functions. */
+ if (errorcount + sorrycount > current_tinst_level->errors)
+ CLASSTYPE_ERRONEOUS (type) = true;
+
/* We don't instantiate default arguments for member functions. 14.7.1:
The implicit instantiation of a class template specialization causes
diff --git a/gcc/testsuite/g++.dg/template/access2.C b/gcc/testsuite/g++.dg/template/access2.C
index 0620c10..4a80bb4 100644
--- a/gcc/testsuite/g++.dg/template/access2.C
+++ b/gcc/testsuite/g++.dg/template/access2.C
@@ -5,6 +5,9 @@
template <class T> struct A {
typename T::X x; // { dg-error "this context" }
+};
+
+template <class T> struct A2 {
int f() { return T::i; } // { dg-error "this context" }
};
@@ -16,5 +19,6 @@ class B {
int main()
{
A<B> ab; // { dg-message "required" }
- ab.f(); // { dg-message "required" }
+ A2<B> a2b;
+ a2b.f(); // { dg-message "required" }
}