re PR c++/51047 ([C++0x] SFINAE does not handle errors of ambiguous base members)
authorPaolo Carlini <paolo.carlini@oracle.com>
Wed, 9 Nov 2011 17:19:12 +0000 (17:19 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Wed, 9 Nov 2011 17:19:12 +0000 (17:19 +0000)
/cp
2011-11-09  Paolo Carlini  <paolo.carlini@oracle.com>

PR c++/51047
* search.c (lookup_member): Change to take also a tsubst_flags_t
parameter.
(lookup_field, lookup_fnfields): Adjust calls.
* typeck.c (lookup_destructor, finish_class_member_access_expr,
build_ptrmemfunc_access_expr): Likewise.
* class.c (handle_using_decl, maybe_note_name_used_in_class):
Likewise.
* pt.c (resolve_typename_type): Likewise.
* semantics.c (lambda_function): Likewise.
* parser.c (cp_parser_perform_range_for_lookup,
cp_parser_lookup_name): Likewise.
* friend.c (make_friend_class): Likewise.
* name-lookup.c (pushdecl_maybe_friend_1, get_class_binding,
do_class_using_decl, lookup_qualified_name): Likewise.
* cp-tree.h (lookup_member): Adjust declaration.

/testsuite
2011-11-09  Paolo Carlini  <paolo.carlini@oracle.com>

PR c++/51047
* g++.dg/cpp0x/sfinae29.C: New.

From-SVN: r181213

gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/friend.c
gcc/cp/name-lookup.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/search.c
gcc/cp/semantics.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/sfinae29.C [new file with mode: 0644]

index be632be..f10a749 100644 (file)
@@ -1167,7 +1167,8 @@ handle_using_decl (tree using_decl, tree t)
 
   gcc_assert (!processing_template_decl && decl);
 
-  old_value = lookup_member (t, name, /*protect=*/0, /*want_type=*/false);
+  old_value = lookup_member (t, name, /*protect=*/0, /*want_type=*/false,
+                            tf_warning_or_error);
   if (old_value)
     {
       if (is_overloaded_fn (old_value))
@@ -7290,7 +7291,7 @@ maybe_note_name_used_in_class (tree name, tree decl)
   /* If there's already a binding for this NAME, then we don't have
      anything to worry about.  */
   if (lookup_member (current_class_type, name,
-                    /*protect=*/0, /*want_type=*/false))
+                    /*protect=*/0, /*want_type=*/false, tf_warning_or_error))
     return;
 
   if (!current_class_stack[current_class_depth - 1].names_used)
index 32d08ca..5ba1885 100644 (file)
@@ -5367,7 +5367,8 @@ extern tree lookup_fnfields_slot          (tree, tree);
 extern tree lookup_fnfields_slot_nolazy                (tree, tree);
 extern int class_method_index_for_fn           (tree, tree);
 extern tree lookup_fnfields                    (tree, tree, int);
-extern tree lookup_member                      (tree, tree, int, bool);
+extern tree lookup_member                      (tree, tree, int, bool,
+                                                tsubst_flags_t);
 extern int look_for_overrides                  (tree, tree);
 extern void get_pure_virtuals                  (tree);
 extern void maybe_suppress_debug_info          (tree);
index b6bd387..e532a30 100644 (file)
@@ -314,7 +314,7 @@ make_friend_class (tree type, tree friend_type, bool complain)
            }
          else
            {
-             decl = lookup_member (ctype, name, 0, true);
+             decl = lookup_member (ctype, name, 0, true, tf_warning_or_error);
              if (!decl)
                {
                  error ("%qT is not a member of %qT", name, ctype);
index 7b61d68..044a97f 100644 (file)
@@ -1121,7 +1121,8 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
                member = lookup_member (current_class_type,
                                        name,
                                        /*protect=*/0,
-                                       /*want_type=*/false);
+                                       /*want_type=*/false,
+                                       tf_warning_or_error);
              else
                member = NULL_TREE;
 
@@ -2891,10 +2892,12 @@ get_class_binding (tree name, cp_binding_level *scope)
 
   /* Get the type binding.  */
   type_binding = lookup_member (class_type, name,
-                               /*protect=*/2, /*want_type=*/true);
+                               /*protect=*/2, /*want_type=*/true,
+                               tf_warning_or_error);
   /* Get the value binding.  */
   value_binding = lookup_member (class_type, name,
-                                /*protect=*/2, /*want_type=*/false);
+                                /*protect=*/2, /*want_type=*/false,
+                                tf_warning_or_error);
 
   if (value_binding
       && (TREE_CODE (value_binding) == TYPE_DECL
@@ -3193,7 +3196,7 @@ do_class_using_decl (tree scope, tree name)
        }
       else if (!name_dependent_p)
        {
-         decl = lookup_member (binfo, name, 0, false);
+         decl = lookup_member (binfo, name, 0, false, tf_warning_or_error);
          if (!decl)
            {
              error ("no members matching %<%T::%D%> in %q#T", scope, name,
@@ -4258,7 +4261,7 @@ lookup_qualified_name (tree scope, tree name, bool is_type_p, bool complain)
   else if (cxx_dialect != cxx98 && TREE_CODE (scope) == ENUMERAL_TYPE)
     t = lookup_enumerator (scope, name);
   else if (is_class_type (scope, complain))
-    t = lookup_member (scope, name, 2, is_type_p);
+    t = lookup_member (scope, name, 2, is_type_p, tf_warning_or_error);
 
   if (!t)
     return error_mark_node;
index 1376a3a..931c593 100644 (file)
@@ -9495,9 +9495,11 @@ cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end)
       id_begin = get_identifier ("begin");
       id_end = get_identifier ("end");
       member_begin = lookup_member (TREE_TYPE (range), id_begin,
-                                   /*protect=*/2, /*want_type=*/false);
+                                   /*protect=*/2, /*want_type=*/false,
+                                   tf_warning_or_error);
       member_end = lookup_member (TREE_TYPE (range), id_end,
-                                 /*protect=*/2, /*want_type=*/false);
+                                 /*protect=*/2, /*want_type=*/false,
+                                 tf_warning_or_error);
 
       if (member_begin != NULL_TREE || member_end != NULL_TREE)
        {
@@ -20398,7 +20400,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
        object_decl = lookup_member (object_type,
                                     name,
                                     /*protect=*/0,
-                                    tag_type != none_type);
+                                    tag_type != none_type,
+                                    tf_warning_or_error);
       /* Look it up in the enclosing context, too.  */
       decl = lookup_name_real (name, tag_type != none_type,
                               /*nonclass=*/0,
index 8c91a9e..e53e90f 100644 (file)
@@ -19861,7 +19861,8 @@ resolve_typename_type (tree type, bool only_current_p)
      longer be considered a dependent type.  */
   pushed_scope = push_scope (scope);
   /* Look up the declaration.  */
-  decl = lookup_member (scope, name, /*protect=*/0, /*want_type=*/true);
+  decl = lookup_member (scope, name, /*protect=*/0, /*want_type=*/true,
+                       tf_warning_or_error);
 
   result = NULL_TREE;
   
index 40af661..7d9551c 100644 (file)
@@ -1155,7 +1155,8 @@ build_baselink (tree binfo, tree access_binfo, tree functions, tree optype)
    If nothing can be found return NULL_TREE and do not issue an error.  */
 
 tree
-lookup_member (tree xbasetype, tree name, int protect, bool want_type)
+lookup_member (tree xbasetype, tree name, int protect, bool want_type,
+              tsubst_flags_t complain)
 {
   tree rval, rval_binfo = NULL_TREE;
   tree type = NULL_TREE, basetype_path = NULL_TREE;
@@ -1250,9 +1251,12 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type)
 
   if (errstr && protect)
     {
-      error (errstr, name, type);
-      if (lfi.ambiguous)
-       print_candidates (lfi.ambiguous);
+      if (complain & tf_error)
+       {
+         error (errstr, name, type);
+         if (lfi.ambiguous)
+           print_candidates (lfi.ambiguous);
+       }
       rval = error_mark_node;
     }
 
@@ -1269,7 +1273,8 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type)
 tree
 lookup_field (tree xbasetype, tree name, int protect, bool want_type)
 {
-  tree rval = lookup_member (xbasetype, name, protect, want_type);
+  tree rval = lookup_member (xbasetype, name, protect, want_type,
+                            tf_warning_or_error);
 
   /* Ignore functions, but propagate the ambiguity list.  */
   if (!error_operand_p (rval)
@@ -1285,7 +1290,8 @@ lookup_field (tree xbasetype, tree name, int protect, bool want_type)
 tree
 lookup_fnfields (tree xbasetype, tree name, int protect)
 {
-  tree rval = lookup_member (xbasetype, name, protect, /*want_type=*/false);
+  tree rval = lookup_member (xbasetype, name, protect, /*want_type=*/false,
+                            tf_warning_or_error);
 
   /* Ignore non-functions, but propagate the ambiguity list.  */
   if (!error_operand_p (rval)
index 508e252..e9da381 100644 (file)
@@ -8621,7 +8621,8 @@ lambda_function (tree lambda)
       && !COMPLETE_OR_OPEN_TYPE_P (type))
     return NULL_TREE;
   lambda = lookup_member (type, ansi_opname (CALL_EXPR),
-                         /*protect=*/0, /*want_type=*/false);
+                         /*protect=*/0, /*want_type=*/false,
+                         tf_warning_or_error);
   if (lambda)
     lambda = BASELINK_FUNCTIONS (lambda);
   return lambda;
index aed2891..2964952 100644 (file)
@@ -2397,7 +2397,8 @@ lookup_destructor (tree object, tree scope, tree dtor_name)
       return error_mark_node;
     }
   expr = lookup_member (dtor_type, complete_dtor_identifier,
-                       /*protect=*/1, /*want_type=*/false);
+                       /*protect=*/1, /*want_type=*/false,
+                       tf_warning_or_error);
   expr = (adjust_result_of_qualified_name_lookup
          (expr, dtor_type, object_type));
   return expr;
@@ -2607,7 +2608,7 @@ finish_class_member_access_expr (tree object, tree name, bool template_p,
        {
          /* Look up the member.  */
          member = lookup_member (access_path, name, /*protect=*/1,
-                                 /*want_type=*/false);
+                                 /*want_type=*/false, complain);
          if (member == NULL_TREE)
            {
              if (complain & tf_error)
@@ -2681,7 +2682,7 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
   ptrmem_type = TREE_TYPE (ptrmem);
   gcc_assert (TYPE_PTRMEMFUNC_P (ptrmem_type));
   member = lookup_member (ptrmem_type, member_name, /*protect=*/0,
-                         /*want_type=*/false);
+                         /*want_type=*/false, tf_warning_or_error);
   member_type = cp_build_qualified_type (TREE_TYPE (member),
                                         cp_type_quals (ptrmem_type));
   return fold_build3_loc (input_location,
index 83ef171..03691b5 100644 (file)
@@ -1,3 +1,8 @@
+2011-11-09  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/51047
+       * g++.dg/cpp0x/sfinae29.C: New.
+
 2011-11-09  Janus Weil  <janus@gcc.gnu.org>
 
        PR fortran/50960
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae29.C b/gcc/testsuite/g++.dg/cpp0x/sfinae29.C
new file mode 100644 (file)
index 0000000..a2e10b4
--- /dev/null
@@ -0,0 +1,17 @@
+// PR c++/51047
+// { dg-options -std=c++0x }
+
+template<typename T> T &&declval();
+template<class T> decltype(declval<T>().x) f(T *);
+template<class T> char f(T);
+struct B1{ int x; };
+struct B2{ int x; };
+struct D : public B1, B2{};
+struct S { int x; };
+int main()
+{
+  S *p = nullptr;
+  static_assert(sizeof(f(p)) == sizeof(int), "");
+  D *q = nullptr;
+  static_assert(sizeof(f(q)) == 1u, "");
+}