]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: make finish_non_static_data_member SFINAE enabled [PR105351]
authorPatrick Palka <ppalka@redhat.com>
Tue, 3 May 2022 19:21:26 +0000 (15:21 -0400)
committerPatrick Palka <ppalka@redhat.com>
Tue, 3 May 2022 19:21:26 +0000 (15:21 -0400)
Here since finish_non_static_data_member isn't SFINAE enabled, we
incorrectly emit an error when considering the first overload rather
than silently discarding it:

sfinae33.C: In substitution of ‘template<class T> A<T::value> f() [with T = B]’:
sfinae33.C:11:7:   required from here
sfinae33.C:5:31: error: invalid use of non-static data member ‘B::value’
    5 | template<class T> A<T::value> f();
      |                               ^

This patch makes the function SFINAE enabled in the usual way: give it a
complain parameter, check it before emitting an error, and pass it through
appropriately.

PR c++/105351

gcc/cp/ChangeLog:

* cp-tree.h (finish_non_static_data_member): Add defaulted
complain parameter.
* pt.cc (tsubst_copy_and_build): Pass complain to
finish_non_static_data_member.
* semantics.cc (finish_non_static_data_member): Respect complain
parameter.
(finish_qualified_id_expr): Pass complain to
finish_non_static_data_member.

gcc/testsuite/ChangeLog:

* g++.dg/template/sfinae33.C: New test.

gcc/cp/cp-tree.h
gcc/cp/pt.cc
gcc/cp/semantics.cc
gcc/testsuite/g++.dg/template/sfinae33.C [new file with mode: 0644]

index 6de29c0571c5a1ec3bf5919ab29443e0d5e4e699..8d7cf240b6865a7cd4e474adc82a4693470d85e3 100644 (file)
@@ -7615,7 +7615,8 @@ inline tree force_paren_expr_uneval               (tree t)
 { return force_paren_expr (t, true); }
 extern tree maybe_undo_parenthesized_ref       (tree);
 extern tree maybe_strip_ref_conversion         (tree);
-extern tree finish_non_static_data_member       (tree, tree, tree);
+extern tree finish_non_static_data_member       (tree, tree, tree,
+                                                tsubst_flags_t = tf_warning_or_error);
 extern tree begin_stmt_expr                    (void);
 extern tree finish_stmt_expr_expr              (tree, tree);
 extern tree finish_stmt_expr                   (tree, bool);
index 3edee50924f6a71a5e8f14cc687f97e0bdb0ef08..ac002907a41a71479fe2d24e02cec05d3c08215b 100644 (file)
@@ -21054,7 +21054,8 @@ tsubst_copy_and_build (tree t,
          }
        else if (TREE_CODE (member) == FIELD_DECL)
          {
-           r = finish_non_static_data_member (member, object, NULL_TREE);
+           r = finish_non_static_data_member (member, object, NULL_TREE,
+                                              complain);
            if (TREE_CODE (r) == COMPONENT_REF)
              REF_PARENTHESIZED_P (r) = REF_PARENTHESIZED_P (t);
            RETURN (r);
index 377f61113c0d3d915c7db05d71376a63073a1a75..bfb737f665b0634b1e318f9b9857495f539dbc03 100644 (file)
@@ -2141,7 +2141,8 @@ finish_parenthesized_expr (cp_expr expr)
    preceded by `.' or `->'.  */
 
 tree
-finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
+finish_non_static_data_member (tree decl, tree object, tree qualifying_scope,
+                              tsubst_flags_t complain /* = tf_warning_or_error */)
 {
   gcc_assert (TREE_CODE (decl) == FIELD_DECL);
   bool try_omp_private = !object && omp_private_member_map;
@@ -2172,12 +2173,15 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
   if (is_dummy_object (object) && cp_unevaluated_operand == 0
       && (!processing_template_decl || !current_class_ref))
     {
-      if (current_function_decl
-         && DECL_STATIC_FUNCTION_P (current_function_decl))
-       error ("invalid use of member %qD in static member function", decl);
-      else
-       error ("invalid use of non-static data member %qD", decl);
-      inform (DECL_SOURCE_LOCATION (decl), "declared here");
+      if (complain & tf_error)
+       {
+         if (current_function_decl
+             && DECL_STATIC_FUNCTION_P (current_function_decl))
+           error ("invalid use of member %qD in static member function", decl);
+         else
+           error ("invalid use of non-static data member %qD", decl);
+         inform (DECL_SOURCE_LOCATION (decl), "declared here");
+       }
 
       return error_mark_node;
     }
@@ -2219,8 +2223,9 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
     {
       tree access_type = TREE_TYPE (object);
 
-      perform_or_defer_access_check (TYPE_BINFO (access_type), decl,
-                                    decl, tf_warning_or_error);
+      if (!perform_or_defer_access_check (TYPE_BINFO (access_type), decl,
+                                         decl, complain))
+       return error_mark_node;
 
       /* If the data member was named `C::M', convert `*this' to `C'
         first.  */
@@ -2234,7 +2239,7 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
       ret = build_class_member_access_expr (object, decl,
                                            /*access_path=*/NULL_TREE,
                                            /*preserve_reference=*/false,
-                                           tf_warning_or_error);
+                                           complain);
     }
   if (try_omp_private)
     {
@@ -2396,7 +2401,7 @@ finish_qualified_id_expr (tree qualifying_class,
     {
       push_deferring_access_checks (dk_no_check);
       expr = finish_non_static_data_member (expr, NULL_TREE,
-                                           qualifying_class);
+                                           qualifying_class, complain);
       pop_deferring_access_checks ();
     }
   else if (BASELINK_P (expr))
diff --git a/gcc/testsuite/g++.dg/template/sfinae33.C b/gcc/testsuite/g++.dg/template/sfinae33.C
new file mode 100644 (file)
index 0000000..ee384e8
--- /dev/null
@@ -0,0 +1,12 @@
+// PR c++/105351
+
+template<int> struct A { };
+
+template<class T> A<T::value> f();
+template<class T> void f();
+
+struct B { int value; };
+
+int main() {
+  f<B>();
+}