diff options
author | Jason Merrill <jason@redhat.com> | 2020-11-13 16:33:50 -0500 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2020-11-15 12:07:13 -0500 |
commit | baf38d2e363971ed8baa5f82b2eaf21cd8e74aae (patch) | |
tree | f5888a935e669ab96ba8aef052e2f514213f9d80 /gcc/cp/typeck2.c | |
parent | 82b6d25d289195d41e53fc91f63325864e3e28d0 (diff) | |
download | gcc-baf38d2e363971ed8baa5f82b2eaf21cd8e74aae.zip gcc-baf38d2e363971ed8baa5f82b2eaf21cd8e74aae.tar.gz gcc-baf38d2e363971ed8baa5f82b2eaf21cd8e74aae.tar.bz2 |
c++: Check abstract type only on object creation. [PR86252]
Abstract checking has been problematic for a while; when I implemented an
earlier issue resolution to do more checking it led to undesirable
instantiations, and so backed some of it out. During the C++20 process we
decided with P0929R2 that we should go the other way, and only check
abstractness when we're actually creating an object, not when merely forming
an array or function type. This means that we can remove the machinery for
checking whether a newly complete class makes some earlier declaration
ill-formed. This change was moved as a DR, so I'm applying it to all
standard levels. This could be reconsidered if it causes problems, but I
don't expect it to.
The change to the libstdc++ result_of test brings the expected behavior in
line with that for incomplete types, but as in PR97841 I think the libstdc++
handling of incomplete types in this and other type_traits is itself wrong,
so I expect these lines and others to change again before long.
gcc/cp/ChangeLog:
* decl.c (cp_finish_decl): Only check abstractness on definition.
(require_complete_types_for_parms): Check abstractness here.
(create_array_type_for_decl): Not here.
(grokdeclarator, grokparms, complete_vars): Not here.
* pt.c (tsubst, tsubst_arg_types, tsubst_function_type): Not here.
* typeck2.c (struct pending_abstract_type): Remove.
(struct abstract_type_hasher): Remove.
(abstract_pending_vars, complete_type_check_abstract): Remove.
(abstract_virtuals_error_sfinae): Handle arrays.
* call.c (conv_is_prvalue): Split out from...
(conv_binds_ref_to_prvalue): ...here.
(implicit_conversion_1): Rename from implicit_conversion.
(implicit_conversion): An abstract prvalue is bad.
(convert_like_internal): Don't complain if expr is already
error_mark_node.
gcc/testsuite/ChangeLog:
* g++.dg/other/abstract1.C: Adjust.
* g++.dg/other/abstract2.C: Adjust.
* g++.dg/other/abstract4.C: Adjust.
* g++.dg/other/abstract5.C: Adjust.
* g++.dg/other/abstract8.C: New test.
* g++.dg/template/sfinae-dr657.C: Adjust.
* g++.old-deja/g++.other/decl3.C: Adjust.
libstdc++-v3/ChangeLog:
* testsuite/20_util/result_of/sfinae_friendly_1.cc: Adjust.
Diffstat (limited to 'gcc/cp/typeck2.c')
-rw-r--r-- | gcc/cp/typeck2.c | 159 |
1 files changed, 7 insertions, 152 deletions
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 445e2a2..4128699 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -123,123 +123,6 @@ cxx_readonly_error (location_t loc, tree arg, enum lvalue_use errstring) readonly_error (loc, arg, errstring); } -/* Structure that holds information about declarations whose type was - incomplete and we could not check whether it was abstract or not. */ - -struct GTY((chain_next ("%h.next"), for_user)) pending_abstract_type { - /* Declaration which we are checking for abstractness. It is either - a DECL node, or an IDENTIFIER_NODE if we do not have a full - declaration available. */ - tree decl; - - /* Type which will be checked for abstractness. */ - tree type; - - /* Kind of use in an unnamed declarator. */ - enum abstract_class_use use; - - /* Position of the declaration. This is only needed for IDENTIFIER_NODEs, - because DECLs already carry locus information. */ - location_t locus; - - /* Link to the next element in list. */ - struct pending_abstract_type* next; -}; - -struct abstract_type_hasher : ggc_ptr_hash<pending_abstract_type> -{ - typedef tree compare_type; - static hashval_t hash (pending_abstract_type *); - static bool equal (pending_abstract_type *, tree); -}; - -/* Compute the hash value of the node VAL. This function is used by the - hash table abstract_pending_vars. */ - -hashval_t -abstract_type_hasher::hash (pending_abstract_type *pat) -{ - return (hashval_t) TYPE_UID (pat->type); -} - - -/* Compare node VAL1 with the type VAL2. This function is used by the - hash table abstract_pending_vars. */ - -bool -abstract_type_hasher::equal (pending_abstract_type *pat1, tree type2) -{ - return (pat1->type == type2); -} - -/* Hash table that maintains pending_abstract_type nodes, for which we still - need to check for type abstractness. The key of the table is the type - of the declaration. */ -static GTY (()) hash_table<abstract_type_hasher> *abstract_pending_vars = NULL; - -static int abstract_virtuals_error_sfinae (tree, tree, abstract_class_use, tsubst_flags_t); - -/* This function is called after TYPE is completed, and will check if there - are pending declarations for which we still need to verify the abstractness - of TYPE, and emit a diagnostic (through abstract_virtuals_error) if TYPE - turned out to be incomplete. */ - -void -complete_type_check_abstract (tree type) -{ - struct pending_abstract_type *pat; - location_t cur_loc = input_location; - - gcc_assert (COMPLETE_TYPE_P (type)); - - if (!abstract_pending_vars) - return; - - /* Retrieve the list of pending declarations for this type. */ - pending_abstract_type **slot - = abstract_pending_vars->find_slot_with_hash (type, TYPE_UID (type), - NO_INSERT); - if (!slot) - return; - pat = *slot; - gcc_assert (pat); - - /* If the type is not abstract, do not do anything. */ - if (CLASSTYPE_PURE_VIRTUALS (type)) - { - struct pending_abstract_type *prev = 0, *next; - - /* Reverse the list to emit the errors in top-down order. */ - for (; pat; pat = next) - { - next = pat->next; - pat->next = prev; - prev = pat; - } - pat = prev; - - /* Go through the list, and call abstract_virtuals_error for each - element: it will issue a diagnostic if the type is abstract. */ - while (pat) - { - gcc_assert (type == pat->type); - - /* Tweak input_location so that the diagnostic appears at the correct - location. Notice that this is only needed if the decl is an - IDENTIFIER_NODE. */ - input_location = pat->locus; - abstract_virtuals_error_sfinae (pat->decl, pat->type, pat->use, - tf_warning_or_error); - pat = pat->next; - } - } - - abstract_pending_vars->clear_slot (slot); - - input_location = cur_loc; -} - - /* If TYPE has abstract virtual functions, issue an error about trying to create an object of that type. DECL is the object declared, or NULL_TREE if the declaration is unavailable, in which case USE specifies @@ -252,6 +135,13 @@ abstract_virtuals_error_sfinae (tree decl, tree type, abstract_class_use use, { vec<tree, va_gc> *pure; + if (TREE_CODE (type) == ARRAY_TYPE) + { + decl = NULL_TREE; + use = ACU_ARRAY; + type = strip_array_types (type); + } + /* This function applies only to classes. Any other entity can never be abstract. */ if (!CLASS_TYPE_P (type)) @@ -266,38 +156,6 @@ abstract_virtuals_error_sfinae (tree decl, tree type, abstract_class_use use, complete_type (type); #endif - /* If the type is incomplete, we register it within a hash table, - so that we can check again once it is completed. This makes sense - only for objects for which we have a declaration or at least a - name. */ - if (!COMPLETE_TYPE_P (type) && (complain & tf_error)) - { - struct pending_abstract_type *pat; - - gcc_assert (!decl || DECL_P (decl) || identifier_p (decl)); - - if (!abstract_pending_vars) - abstract_pending_vars - = hash_table<abstract_type_hasher>::create_ggc (31); - - pending_abstract_type **slot - = abstract_pending_vars->find_slot_with_hash (type, TYPE_UID (type), - INSERT); - - pat = ggc_alloc<pending_abstract_type> (); - pat->type = type; - pat->decl = decl; - pat->use = use; - pat->locus = ((decl && DECL_P (decl)) - ? DECL_SOURCE_LOCATION (decl) - : input_location); - - pat->next = *slot; - *slot = pat; - - return 0; - } - if (!TYPE_SIZE (type)) /* TYPE is being defined, and during that time CLASSTYPE_PURE_VIRTUALS holds the inline friends. */ @@ -2594,6 +2452,3 @@ require_complete_eh_spec_types (tree fntype, tree decl) } } } - - -#include "gt-cp-typeck2.h" |