On 08/27/2012 08:04 PM, Jason Merrill wrote:
On 08/27/2012 01:36 PM, Paolo Carlini wrote:
Thanks for the feedback. Indeed, as I tried to explain in an older
message, that was also my understanding. The practical difficulty with
the mapping (which you can also guess from the current structure of
get_delta_difference_1, the if (kind == bk_inaccessible || kind ==
bk_ambig) check) is that ba_quiet, as used by lookup_base, doesn't just
control the error calls - like normally tf_error does - it *also*
changes the return value, error_mark_node or NULL_TREE. I'm still not
sure about the correct (and concise! see get_delta_difference_1, again)
way to handle this...
I think the right way is to adjust the callers to handle
error_mark_node return properly. Macros may need to become functions.
Ah, ok. I guess the prospect of touching those macros was somehow
psychologically "blocking" me., eh ;) But actually, all in all, the code
doesn't become more complex, because only the cases where we are now
passing tf_none require checking for error_mark_node too where we were
simply checking != NULL_TREE as return value of lookup_base and most of
the calls are otherwise already Ok, or even become simpler, where we
were, on a case by case basis, tweaking to | ba_quiet basing on complain
(note: I left DERIVED_FROM_P alone, because we weren't passing ba_quiet
to it)
The below passes testing on x86_64-linux.
Thanks!
Paolo.
//////////////////////////
Index: testsuite/g++.dg/cpp0x/sfinae39.C
===================================================================
--- testsuite/g++.dg/cpp0x/sfinae39.C (revision 0)
+++ testsuite/g++.dg/cpp0x/sfinae39.C (revision 0)
@@ -0,0 +1,98 @@
+// PR c++/54191
+// { dg-do compile { target c++11 } }
+
+struct B
+{};
+
+struct D
+ : private B
+{};
+
+template<typename T>
+T &&declval();
+
+
+template<typename From, typename To,
+ typename = decltype(static_cast<To>(declval<From>()))>
+constexpr bool test_static_cast(int)
+{ return true; }
+
+template<typename, typename>
+constexpr bool test_static_cast(bool)
+{ return false; }
+
+static_assert(!test_static_cast<B &, D &>(0), "");
+static_assert(!test_static_cast<B *, D *>(0), "");
+
+
+template<typename From, typename To,
+ typename = decltype(dynamic_cast<To>(declval<From>()))>
+constexpr bool test_dynamic_cast(int)
+{ return true; }
+
+template<typename, typename>
+constexpr bool test_dynamic_cast(bool)
+{ return false; }
+
+static_assert(!test_dynamic_cast<D &, B &>(0), "");
+static_assert(!test_dynamic_cast<D *, B *>(0), "");
+
+
+int B::*pm = 0;
+
+template<typename T, typename = decltype(declval<T>().*pm)>
+constexpr bool test_member_ptr_dot(int)
+{ return true; }
+
+template<typename>
+constexpr bool test_member_ptr_dot(bool)
+{ return false; }
+
+static_assert(!test_member_ptr_dot<D>(0), "");
+
+
+template<typename T, typename = decltype(declval<T>()->*pm)>
+constexpr bool test_member_ptr_arrow(int)
+{ return true; }
+
+template<typename>
+constexpr bool test_member_ptr_arrow(bool)
+{ return false; }
+
+static_assert(!test_member_ptr_arrow<D *>(0), "");
+
+
+template<typename T, typename U,
+ typename = decltype(declval<T>() < declval<U>())>
+constexpr bool test_rel_op(int)
+{ return true; }
+
+template<typename, typename>
+constexpr bool test_rel_op(bool)
+{ return false; }
+
+static_assert(!test_rel_op<D *, B *>(0), "");
+
+
+template<typename T, typename U,
+ typename = decltype(declval<T>() == declval<U>())>
+constexpr bool test_eq(int)
+{ return true; }
+
+template<typename, typename>
+constexpr bool test_eq(bool)
+{ return false; }
+
+static_assert(!test_eq<D *, B *>(0), "");
+
+
+template<typename T, typename U,
+ typename = decltype(false ? declval<T>() : declval<U>())>
+constexpr bool test_cond_op(int)
+{ return true; }
+
+template<typename, typename>
+constexpr bool test_cond_op(bool)
+{ return false; }
+
+static_assert(!test_cond_op<B *, D *>(0), "");
Index: cp/typeck.c
===================================================================
--- cp/typeck.c (revision 190730)
+++ cp/typeck.c (working copy)
@@ -975,7 +975,7 @@ comp_except_types (tree a, tree b, bool exact)
|| TREE_CODE (b) != RECORD_TYPE)
return false;
- if (PUBLICLY_UNIQUELY_DERIVED_P (a, b))
+ if (publicly_uniquely_derived_p (a, b))
return true;
}
return false;
@@ -2247,7 +2247,7 @@ build_class_member_access_expr (tree object, tree
base_kind kind;
binfo = lookup_base (access_path ? access_path : object_type,
- member_scope, ba_unique, &kind);
+ member_scope, ba_unique, &kind, complain);
if (binfo == error_mark_node)
return error_mark_node;
@@ -2630,7 +2630,8 @@ finish_class_member_access_expr (tree object, tree
}
/* Find the base of OBJECT_TYPE corresponding to SCOPE. */
- access_path = lookup_base (object_type, scope, ba_check, NULL);
+ access_path = lookup_base (object_type, scope, ba_check,
+ NULL, complain);
if (access_path == error_mark_node)
return error_mark_node;
if (!access_path)
@@ -3151,7 +3152,7 @@ get_member_function_from_ptrfunc (tree *instance_p
(basetype, TREE_TYPE (TREE_TYPE (instance_ptr))))
{
basetype = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)),
- basetype, ba_check, NULL);
+ basetype, ba_check, NULL, complain);
instance_ptr = build_base_path (PLUS_EXPR, instance_ptr, basetype,
1, complain);
if (instance_ptr == error_mark_node)
@@ -5997,7 +5998,7 @@ build_static_cast_1 (tree type, tree expr, bool c_
not considered. */
base = lookup_base (TREE_TYPE (type), intype,
c_cast_p ? ba_unique : ba_check,
- NULL);
+ NULL, complain);
/* Convert from "B*" to "D*". This function will check that "B"
is not a virtual base of "D". */
@@ -6121,7 +6122,7 @@ build_static_cast_1 (tree type, tree expr, bool c_
return error_mark_node;
base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
c_cast_p ? ba_unique : ba_check,
- NULL);
+ NULL, complain);
expr = build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false,
complain);
return cp_fold_convert(type, expr);
@@ -7181,16 +7182,11 @@ get_delta_difference_1 (tree from, tree to, bool c
{
tree binfo;
base_kind kind;
- base_access access = c_cast_p ? ba_unique : ba_check;
- /* Note: ba_quiet does not distinguish between access control and
- ambiguity. */
- if (!(complain & tf_error))
- access |= ba_quiet;
+ binfo = lookup_base (to, from, c_cast_p ? ba_unique : ba_check,
+ &kind, complain);
- binfo = lookup_base (to, from, access, &kind);
-
- if (kind == bk_inaccessible || kind == bk_ambig)
+ if (binfo == error_mark_node)
{
if (!(complain & tf_error))
return error_mark_node;
Index: cp/class.c
===================================================================
--- cp/class.c (revision 190730)
+++ cp/class.c (working copy)
@@ -275,7 +275,7 @@ build_base_path (enum tree_code code,
if (complain & tf_error)
{
tree base = lookup_base (probe, BINFO_TYPE (d_binfo),
- ba_unique, NULL);
+ ba_unique, NULL, complain);
gcc_assert (base == error_mark_node);
}
return error_mark_node;
@@ -544,7 +544,6 @@ convert_to_base (tree object, tree type, bool chec
{
tree binfo;
tree object_type;
- base_access access;
if (TYPE_PTR_P (TREE_TYPE (object)))
{
@@ -554,12 +553,8 @@ convert_to_base (tree object, tree type, bool chec
else
object_type = TREE_TYPE (object);
- access = check_access ? ba_check : ba_unique;
- if (!(complain & tf_error))
- access |= ba_quiet;
- binfo = lookup_base (object_type, type,
- access,
- NULL);
+ binfo = lookup_base (object_type, type, check_access ? ba_check : ba_unique,
+ NULL, complain);
if (!binfo || binfo == error_mark_node)
return error_mark_node;
@@ -652,8 +647,8 @@ build_vtbl_ref_1 (tree instance, tree idx)
if (fixed_type && !cdtorp)
{
tree binfo = lookup_base (fixed_type, basetype,
- ba_unique | ba_quiet, NULL);
- if (binfo)
+ ba_unique, NULL, tf_none);
+ if (binfo && binfo != error_mark_node)
vtbl = unshare_expr (BINFO_VTABLE (binfo));
}
@@ -5483,7 +5478,7 @@ warn_about_ambiguous_bases (tree t)
{
basetype = BINFO_TYPE (base_binfo);
- if (!lookup_base (t, basetype, ba_unique | ba_quiet, NULL))
+ if (!uniquely_derived_from_p (basetype, t))
warning (0, "direct base %qT inaccessible in %qT due to ambiguity",
basetype, t);
}
@@ -5495,9 +5490,9 @@ warn_about_ambiguous_bases (tree t)
{
basetype = BINFO_TYPE (binfo);
- if (!lookup_base (t, basetype, ba_unique | ba_quiet, NULL))
- warning (OPT_Wextra, "virtual base %qT inaccessible in %qT due to
ambiguity",
- basetype, t);
+ if (!uniquely_derived_from_p (basetype, t))
+ warning (OPT_Wextra, "virtual base %qT inaccessible in %qT due "
+ "to ambiguity", basetype, t);
}
}
@@ -8933,4 +8928,24 @@ build_rtti_vtbl_entries (tree binfo, vtbl_init_dat
CONSTRUCTOR_APPEND_ELT (vid->inits, NULL_TREE, init);
}
+/* TRUE iff TYPE is uniquely derived from PARENT. Ignores
+ accessibility. */
+
+bool
+uniquely_derived_from_p (tree parent, tree type)
+{
+ tree base = lookup_base (type, parent, ba_unique, NULL, tf_none);
+ return base && base != error_mark_node;
+}
+
+/* TRUE iff TYPE is publicly & uniquely derived from PARENT. */
+
+bool
+publicly_uniquely_derived_p (tree parent, tree type)
+{
+ tree base = lookup_base (type, parent, ba_ignore_scope | ba_check,
+ NULL, tf_none);
+ return base && base != error_mark_node;
+}
+
#include "gt-cp-class.h"
Index: cp/decl.c
===================================================================
--- cp/decl.c (revision 190730)
+++ cp/decl.c (working copy)
@@ -8512,7 +8512,7 @@ grokdeclarator (const cp_declarator *declarator,
}
else if (innermost_code != cdk_function
&& current_class_type
- && !UNIQUELY_DERIVED_FROM_P (ctype,
+ && !uniquely_derived_from_p (ctype,
current_class_type))
{
error ("type %qT is not derived from type %qT",
Index: cp/rtti.c
===================================================================
--- cp/rtti.c (revision 190730)
+++ cp/rtti.c (working copy)
@@ -615,7 +615,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst
tree binfo;
binfo = lookup_base (TREE_TYPE (exprtype), TREE_TYPE (type),
- ba_check, NULL);
+ ba_check, NULL, complain);
if (binfo)
{
Index: cp/except.c
===================================================================
--- cp/except.c (revision 190730)
+++ cp/except.c (working copy)
@@ -1052,7 +1052,7 @@ can_convert_eh (tree to, tree from)
}
if (CLASS_TYPE_P (to) && CLASS_TYPE_P (from)
- && PUBLICLY_UNIQUELY_DERIVED_P (to, from))
+ && publicly_uniquely_derived_p (to, from))
return 1;
return 0;
Index: cp/tree.c
===================================================================
--- cp/tree.c (revision 190730)
+++ cp/tree.c (working copy)
@@ -2772,7 +2772,8 @@ maybe_dummy_object (tree type, tree* binfop)
tree current = current_nonlambda_class_type ();
if (current
- && (binfo = lookup_base (current, type, ba_any, NULL)))
+ && (binfo = lookup_base (current, type, ba_any, NULL,
+ tf_warning_or_error)))
context = current;
else
{
Index: cp/typeck2.c
===================================================================
--- cp/typeck2.c (revision 190730)
+++ cp/typeck2.c (working copy)
@@ -57,7 +57,8 @@ error_not_base_type (tree basetype, tree type)
tree
binfo_or_else (tree base, tree type)
{
- tree binfo = lookup_base (type, base, ba_unique, NULL);
+ tree binfo = lookup_base (type, base, ba_unique,
+ NULL, tf_warning_or_error);
if (binfo == error_mark_node)
return NULL_TREE;
@@ -1447,7 +1448,8 @@ build_scoped_ref (tree datum, tree basetype, tree*
if (*binfo_p)
binfo = *binfo_p;
else
- binfo = lookup_base (TREE_TYPE (datum), basetype, ba_check, NULL);
+ binfo = lookup_base (TREE_TYPE (datum), basetype, ba_check,
+ NULL, tf_warning_or_error);
if (!binfo || binfo == error_mark_node)
{
@@ -1600,7 +1602,7 @@ build_m_component_ref (tree datum, tree component,
}
else
{
- binfo = lookup_base (objtype, ctype, ba_check, NULL);
+ binfo = lookup_base (objtype, ctype, ba_check, NULL, complain);
if (!binfo)
{
Index: cp/call.c
===================================================================
--- cp/call.c (revision 190730)
+++ cp/call.c (working copy)
@@ -4758,6 +4758,9 @@ build_conditional_expr_1 (tree arg1, tree arg2, tr
return error_mark_node;
}
+ if (arg2 == error_mark_node || arg3 == error_mark_node)
+ return error_mark_node;
+
valid_operands:
result = build3 (COND_EXPR, result_type, arg1, arg2, arg3);
if (!cp_unevaluated_operand)
@@ -6608,7 +6611,8 @@ build_over_call (struct z_candidate *cand, int fla
will be to the derived class, not the base declaring fn. We
must convert from derived to base. */
base_binfo = lookup_base (TREE_TYPE (TREE_TYPE (converted_arg)),
- TREE_TYPE (parmtype), ba_unique, NULL);
+ TREE_TYPE (parmtype), ba_unique,
+ NULL, complain);
converted_arg = build_base_path (PLUS_EXPR, converted_arg,
base_binfo, 1, complain);
@@ -6852,7 +6856,7 @@ build_over_call (struct z_candidate *cand, int fla
tree t;
tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (argarray[0])),
DECL_CONTEXT (fn),
- ba_any, NULL);
+ ba_any, NULL, complain);
gcc_assert (binfo && binfo != error_mark_node);
/* Warn about deprecated virtual functions now, since we're about
Index: cp/cvt.c
===================================================================
--- cp/cvt.c (revision 190730)
+++ cp/cvt.c (working copy)
@@ -149,11 +149,13 @@ cp_convert_to_pointer (tree type, tree expr, tsubs
binfo = NULL_TREE;
/* Try derived to base conversion. */
if (!same_p)
- binfo = lookup_base (intype_class, type_class, ba_check, NULL);
+ binfo = lookup_base (intype_class, type_class, ba_check,
+ NULL, complain);
if (!same_p && !binfo)
{
/* Try base to derived conversion. */
- binfo = lookup_base (type_class, intype_class, ba_check, NULL);
+ binfo = lookup_base (type_class, intype_class, ba_check,
+ NULL, complain);
code = MINUS_EXPR;
}
if (binfo == error_mark_node)
@@ -279,11 +281,11 @@ convert_to_pointer_force (tree type, tree expr, ts
tree binfo;
binfo = lookup_base (TREE_TYPE (intype), TREE_TYPE (type),
- ba_unique, NULL);
+ ba_unique, NULL, complain);
if (!binfo)
{
binfo = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
- ba_unique, NULL);
+ ba_unique, NULL, complain);
code = MINUS_EXPR;
}
if (binfo == error_mark_node)
@@ -352,7 +354,8 @@ build_up_reference (tree type, tree arg, int flags
&& MAYBE_CLASS_TYPE_P (target_type))
{
/* We go through lookup_base for the access control. */
- tree binfo = lookup_base (argtype, target_type, ba_check, NULL);
+ tree binfo = lookup_base (argtype, target_type, ba_check,
+ NULL, complain);
if (binfo == error_mark_node)
return error_mark_node;
if (binfo == NULL_TREE)
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h (revision 190730)
+++ cp/cp-tree.h (working copy)
@@ -1278,15 +1278,8 @@ enum languages { lang_c, lang_cplusplus, lang_java
/* Nonzero iff TYPE is derived from PARENT. Ignores accessibility and
ambiguity issues. */
#define DERIVED_FROM_P(PARENT, TYPE) \
- (lookup_base ((TYPE), (PARENT), ba_any, NULL) != NULL_TREE)
-/* Nonzero iff TYPE is uniquely derived from PARENT. Ignores
- accessibility. */
-#define UNIQUELY_DERIVED_FROM_P(PARENT, TYPE) \
- (lookup_base ((TYPE), (PARENT), ba_unique | ba_quiet, NULL) != NULL_TREE)
-/* Nonzero iff TYPE is publicly & uniquely derived from PARENT. */
-#define PUBLICLY_UNIQUELY_DERIVED_P(PARENT, TYPE) \
- (lookup_base ((TYPE), (PARENT), ba_ignore_scope | ba_check | ba_quiet, \
- NULL) != NULL_TREE)
+ (lookup_base ((TYPE), (PARENT), ba_any, NULL, tf_warning_or_error)\
+ != NULL_TREE)
/* Gives the visibility specification for a class type. */
#define CLASSTYPE_VISIBILITY(TYPE) \
@@ -4187,8 +4180,7 @@ enum base_access_flags {
ba_unique = 1 << 0, /* Must be a unique base. */
ba_check_bit = 1 << 1, /* Check access. */
ba_check = ba_unique | ba_check_bit,
- ba_ignore_scope = 1 << 2, /* Ignore access allowed by local scope. */
- ba_quiet = 1 << 3 /* Do not issue error messages. */
+ ba_ignore_scope = 1 << 2 /* Ignore access allowed by local scope. */
};
/* This type is used for parameters and variables which hold
@@ -5007,6 +4999,8 @@ extern void clone_function_decl (tree,
int);
extern void adjust_clone_args (tree);
extern void deduce_noexcept_on_destructor (tree);
extern void insert_late_enum_def_into_classtype_sorted_fields (tree, tree);
+extern bool uniquely_derived_from_p (tree, tree);
+extern bool publicly_uniquely_derived_p (tree, tree);
/* in cvt.c */
extern tree convert_to_reference (tree, tree, int, int, tree,
@@ -5439,8 +5433,8 @@ extern bool emit_tinfo_decl (tree);
/* in search.c */
extern bool accessible_base_p (tree, tree, bool);
-extern tree lookup_base (tree, tree,
base_access,
- base_kind *);
+extern tree lookup_base (tree, tree, base_access,
+ base_kind *, tsubst_flags_t);
extern tree dcast_base_hint (tree, tree);
extern int accessible_p (tree, tree, bool);
extern tree lookup_field_1 (tree, tree, bool);
Index: cp/search.c
===================================================================
--- cp/search.c (revision 190730)
+++ cp/search.c (working copy)
@@ -179,13 +179,13 @@ accessible_base_p (tree t, tree base, bool conside
non-NULL, fill with information about what kind of base we
discovered.
- If the base is inaccessible, or ambiguous, and the ba_quiet bit is
- not set in ACCESS, then an error is issued and error_mark_node is
- returned. If the ba_quiet bit is set, then no error is issued and
- NULL_TREE is returned. */
+ If the base is inaccessible, or ambiguous, then error_mark_node is
+ returned. If the tf_error bit of COMPLAIN is not set, no error
+ is issued. */
tree
-lookup_base (tree t, tree base, base_access access, base_kind *kind_ptr)
+lookup_base (tree t, tree base, base_access access,
+ base_kind *kind_ptr, tsubst_flags_t complain)
{
tree binfo;
tree t_binfo;
@@ -251,11 +251,9 @@ tree
break;
case bk_ambig:
- if (!(access & ba_quiet))
- {
- error ("%qT is an ambiguous base of %qT", base, t);
- binfo = error_mark_node;
- }
+ if (complain & tf_error)
+ error ("%qT is an ambiguous base of %qT", base, t);
+ binfo = error_mark_node;
break;
default:
@@ -269,13 +267,9 @@ tree
&& COMPLETE_TYPE_P (base)
&& !accessible_base_p (t, base, !(access & ba_ignore_scope)))
{
- if (!(access & ba_quiet))
- {
- error ("%qT is an inaccessible base of %qT", base, t);
- binfo = error_mark_node;
- }
- else
- binfo = NULL_TREE;
+ if (complain & tf_error)
+ error ("%qT is an inaccessible base of %qT", base, t);
+ binfo = error_mark_node;
bk = bk_inaccessible;
}
break;
@@ -1537,14 +1531,13 @@ adjust_result_of_qualified_name_lookup (tree decl,
or ambiguity -- in either case, the choice of a static member
function might make the usage valid. */
base = lookup_base (context_class, qualifying_scope,
- ba_unique | ba_quiet, NULL);
- if (base)
+ ba_unique, NULL, tf_none);
+ if (base && base != error_mark_node)
{
BASELINK_ACCESS_BINFO (decl) = base;
BASELINK_BINFO (decl)
= lookup_base (base, BINFO_TYPE (BASELINK_BINFO (decl)),
- ba_unique | ba_quiet,
- NULL);
+ ba_unique, NULL, tf_none);
}
}
@@ -1875,12 +1868,13 @@ check_final_overrider (tree overrider, tree basefn
/* Strictly speaking, the standard requires the return type to be
complete even if it only differs in cv-quals, but that seems
like a bug in the wording. */
- if (!same_type_ignoring_top_level_qualifiers_p (base_return,
over_return))
+ if (!same_type_ignoring_top_level_qualifiers_p (base_return,
+ over_return))
{
tree binfo = lookup_base (over_return, base_return,
- ba_check | ba_quiet, NULL);
+ ba_check, NULL, tf_none);
- if (!binfo)
+ if (!binfo || binfo == error_mark_node)
fail = 1;
}
}
Index: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c (revision 190730)
+++ cp/name-lookup.c (working copy)
@@ -3265,7 +3265,8 @@ do_class_using_decl (tree scope, tree name)
if (!scope_dependent_p)
{
base_kind b_kind;
- binfo = lookup_base (current_class_type, scope, ba_any, &b_kind);
+ binfo = lookup_base (current_class_type, scope, ba_any, &b_kind,
+ tf_warning_or_error);
if (b_kind < bk_proper_base)
{
if (!bases_dependent_p)