On 10/14/2011 08:30 PM, Paolo Carlini wrote:
On 10/14/2011 08:23 PM, Paolo Carlini wrote:
Hi,
submitter complains that, at variance with C++11, __is_base_of
doesn't handle an incomplete base type (the first parameter). The
reason seems simple: in finish_trait_expr we try to complete *both*
types instead of doing it where/when necessary.
Hmm, maybe we should be even more careful and call complete (type2)
only when
NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2) &&
!same_type_ignoring_top_level_qualifiers_p (type1, type2)
is true?
Like this?
Paolo.
///////////////////
Index: testsuite/g++.dg/ext/is_base_of_incomplete.C
===================================================================
--- testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0)
+++ testsuite/g++.dg/ext/is_base_of_incomplete.C (revision 0)
@@ -0,0 +1,7 @@
+template <typename T>
+struct non_instantiable
+{
+ typedef typename T::THIS_TYPE_CANNOT_BE_INSTANTIATED type;
+};
+
+int check[__is_base_of(non_instantiable<int>, void) ? -1 : 1];
Index: cp/semantics.c
===================================================================
--- cp/semantics.c (revision 179997)
+++ cp/semantics.c (working copy)
@@ -5276,10 +5276,6 @@ finish_trait_expr (cp_trait_kind kind, tree type1,
return trait_expr;
}
- complete_type (type1);
- if (type2)
- complete_type (type2);
-
switch (kind)
{
case CPTK_HAS_NOTHROW_ASSIGN:
@@ -5297,6 +5293,7 @@ finish_trait_expr (cp_trait_kind kind, tree type1,
case CPTK_IS_POLYMORPHIC:
case CPTK_IS_STD_LAYOUT:
case CPTK_IS_TRIVIAL:
+ complete_type (type1);
if (!check_trait_type (type1))
{
error ("incomplete type %qT not allowed", type1);
@@ -5306,11 +5303,14 @@ finish_trait_expr (cp_trait_kind kind, tree type1,
case CPTK_IS_BASE_OF:
if (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2)
- && !same_type_ignoring_top_level_qualifiers_p (type1, type2)
- && !COMPLETE_TYPE_P (type2))
+ && !same_type_ignoring_top_level_qualifiers_p (type1, type2))
{
- error ("incomplete type %qT not allowed", type2);
- return error_mark_node;
+ complete_type (type2);
+ if (!COMPLETE_TYPE_P (type2))
+ {
+ error ("incomplete type %qT not allowed", type2);
+ return error_mark_node;
+ }
}
break;