OSDN Git Service

/cp
authorpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 5 Sep 2012 10:14:37 +0000 (10:14 +0000)
committerpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 5 Sep 2012 10:14:37 +0000 (10:14 +0000)
2012-09-05  Paolo Carlini  <paolo.carlini@oracle.com>

PR c++/54191
* search.c (lookup_base): Add tsubst_flags_t parameter.
(adjust_result_of_qualified_name_lookup, check_final_overrider):
Adjust.
* name-lookup.c (do_class_using_decl): Adjust.
* typeck2.c (binfo_or_else, build_scoped_ref, build_m_component_ref):
Likewise.
* cvt.c (cp_convert_to_pointer, convert_to_pointer_force,
build_up_reference): Likewise.
* rtti.c (build_dynamic_cast_1): Likewise.
* tree.c (maybe_dummy_object): Likewise.
* call.c (build_conditional_expr_1, build_over_call): Likewise.
* cp-tree.h (UNIQUELY_DERIVED_FROM_P, PUBLICLY_UNIQUELY_DERIVED_P):
Remove.
(enum base_access_flags, ba_quiet): Remove.
(uniquely_derived_from_p, publicly_uniquely_derived_p): Declare.
* except.c (can_convert_eh): Adjust.
* decl.c (grokdeclarator): Likewise.
* typeck.c (comp_except_types, build_class_member_access_expr,
finish_class_member_access_expr, get_member_function_from_ptrfunc,
build_static_cast_1, get_delta_difference_1): Likewise.
* class.c (build_base_path, convert_to_base, build_vtbl_ref_1,
warn_about_ambiguous_bases): Likewise.
(uniquely_derived_from_p, publicly_uniquely_derived_p): Define.

/testsuite
2012-09-05  Paolo Carlini  <paolo.carlini@oracle.com>

PR c++/54191
* g++.dg/cpp0x/sfinae39.C: New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@190969 138bc75d-0d04-0410-961f-82ee72b054a4

15 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/except.c
gcc/cp/name-lookup.c
gcc/cp/rtti.c
gcc/cp/search.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/sfinae39.C [new file with mode: 0644]

index 629ab57..41c0160 100644 (file)
@@ -1,3 +1,30 @@
+2012-09-05  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/54191
+       * search.c (lookup_base): Add tsubst_flags_t parameter.
+       (adjust_result_of_qualified_name_lookup, check_final_overrider):
+       Adjust.
+       * name-lookup.c (do_class_using_decl): Adjust.
+       * typeck2.c (binfo_or_else, build_scoped_ref, build_m_component_ref):
+       Likewise.
+       * cvt.c (cp_convert_to_pointer, convert_to_pointer_force,
+       build_up_reference): Likewise.
+       * rtti.c (build_dynamic_cast_1): Likewise.
+       * tree.c (maybe_dummy_object): Likewise.
+       * call.c (build_conditional_expr_1, build_over_call): Likewise.
+       * cp-tree.h (UNIQUELY_DERIVED_FROM_P, PUBLICLY_UNIQUELY_DERIVED_P):
+       Remove.
+       (enum base_access_flags, ba_quiet): Remove.
+       (uniquely_derived_from_p, publicly_uniquely_derived_p): Declare.
+       * except.c (can_convert_eh): Adjust.
+       * decl.c (grokdeclarator): Likewise.
+       * typeck.c (comp_except_types, build_class_member_access_expr,
+       finish_class_member_access_expr, get_member_function_from_ptrfunc,
+       build_static_cast_1, get_delta_difference_1): Likewise.
+       * class.c (build_base_path, convert_to_base, build_vtbl_ref_1,
+       warn_about_ambiguous_bases): Likewise.
+       (uniquely_derived_from_p, publicly_uniquely_derived_p): Define.
+
 2012-09-04  Jason Merrill  <jason@redhat.com>
 
        PR c++/54441
index 4d65b3e..159be6b 100644 (file)
@@ -4758,6 +4758,9 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3,
       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 flags, tsubst_flags_t complain)
         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 flags, tsubst_flags_t complain)
       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 3b1906a..13d9c76 100644 (file)
@@ -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 check_access, bool nonnull,
 {
   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 check_access, bool nonnull,
   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_data* vid)
   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 fa3d7b0..3e0fc3f 100644 (file)
@@ -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
@@ -5003,6 +4995,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,
@@ -5438,8 +5432,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 9550f15..86f01ab 100644 (file)
@@ -149,11 +149,13 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain)
          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, tsubst_flags_t complain)
          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, tree decl,
       && 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 b665fe8..f86c54f 100644 (file)
@@ -8524,7 +8524,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 2339b9c..ff967de 100644 (file)
@@ -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 0211d4f..9392c01 100644 (file)
@@ -3264,7 +3264,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)
index 51cb5ee..e619180 100644 (file)
@@ -615,7 +615,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
     tree binfo;
 
     binfo = lookup_base (TREE_TYPE (exprtype), TREE_TYPE (type),
-                        ba_check, NULL);
+                        ba_check, NULL, complain);
 
     if (binfo)
       {
index dc802e4..7d358ef 100644 (file)
@@ -179,13 +179,13 @@ accessible_base_p (tree t, tree base, bool consider_local_p)
    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 @@ lookup_base (tree t, tree base, base_access access, base_kind *kind_ptr)
        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 @@ lookup_base (tree t, tree base, base_access access, base_kind *kind_ptr)
            && 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 7cc2457..ce1af73 100644 (file)
@@ -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 25f37e8..f625321 100644 (file)
@@ -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 member,
          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 name, bool template_p,
            }
 
          /* 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_ptrptr, tree function,
          (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_cast_p,
         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_cast_p,
        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_cast_p,
 {
   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 2180535..6faebb5 100644 (file)
@@ -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* binfo_p)
   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, tsubst_flags_t complain)
     }
   else
     {
-      binfo = lookup_base (objtype, ctype, ba_check, NULL);
+      binfo = lookup_base (objtype, ctype, ba_check, NULL, complain);
 
       if (!binfo)
        {
index 62dfe13..26a82db 100644 (file)
@@ -1,3 +1,8 @@
+2012-09-05  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/54191
+       * g++.dg/cpp0x/sfinae39.C: New.
+
 2012-09-04  Jason Merrill  <jason@redhat.com>
 
        PR c++/54441
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae39.C b/gcc/testsuite/g++.dg/cpp0x/sfinae39.C
new file mode 100644 (file)
index 0000000..8183bda
--- /dev/null
@@ -0,0 +1,146 @@
+// PR c++/54191
+// { dg-do compile { target c++11 } }
+
+struct B
+{};
+
+struct D
+  : private B
+{};
+
+template<typename T>
+T &&declval();
+
+
+template<typename From, typename = decltype(B{declval<From>()})>
+constexpr bool test_braced_cast_to_base(int)
+{ return true; }
+
+template<typename>
+constexpr bool test_braced_cast_to_base(bool)
+{ return false; }
+
+static_assert(!test_braced_cast_to_base<D>(0), "");
+
+
+template<typename From, typename = decltype(D{declval<From>()})>
+constexpr bool test_braced_cast_to_derived(int)
+{ return true; }
+
+template<typename>
+constexpr bool test_braced_cast_to_derived(bool)
+{ return false; }
+
+static_assert(!test_braced_cast_to_derived<B>(0), "");
+
+
+typedef B *PB;
+
+template<typename From, typename = decltype(PB{declval<From>()})>
+constexpr bool test_braced_cast_to_ptr_to_base(int)
+{ return true; }
+
+template<typename>
+constexpr bool test_braced_cast_to_ptr_to_base(bool)
+{ return false; }
+
+static_assert(!test_braced_cast_to_ptr_to_base<D *>(0), "");
+
+
+typedef D *PD;
+
+template<typename From, typename = decltype(PD{declval<From>()})>
+constexpr bool test_braced_cast_to_ptr_to_derived(int)
+{ return true; }
+
+template<typename>
+constexpr bool test_braced_cast_to_ptr_to_derived(bool)
+{ return false; }
+
+static_assert(!test_braced_cast_to_ptr_to_derived<B *>(0), "");
+
+
+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), "");