re PR c++/60765 (Function attributes ignored for pointer-to-member-function parameters)
authorPatrick Palka <patrick@parcs.ath.cx>
Wed, 16 Apr 2014 20:17:46 +0000 (03:17 +0700)
committerPaolo Carlini <paolo@gcc.gnu.org>
Wed, 16 Apr 2014 20:17:46 +0000 (20:17 +0000)
2014-04-16  Patrick Palka  <patrick@parcs.ath.cx>

PR c++/60765
* decl2.c (cplus_decl_attributes): Handle
pointer-to-member-function declarations.

2014-04-16  Patrick Palka  <patrick@parcs.ath.cx>

PR c++/60764
* call.c (build_user_type_coversion): Use build_dummy_object
to create the placeholder object for a constructor method call.
(build_special_member_call): Likewise.
(build_over_call): Check for the placeholder object with
is_dummy_object.
(build_new_method_call_1): Likewise.  Don't attempt to resolve
a dummy object for a constructor method call.

From-SVN: r209447

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/decl2.c
gcc/testsuite/g++.dg/cpp0x/gen-attrs-36-1.C
gcc/testsuite/g++.dg/ext/attrib49.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/nonnull2.C [new file with mode: 0644]

index f9206e8..28c6d96 100644 (file)
@@ -1,3 +1,20 @@
+2014-04-16  Patrick Palka  <patrick@parcs.ath.cx>
+
+       PR c++/60765
+       * decl2.c (cplus_decl_attributes): Handle
+       pointer-to-member-function declarations.
+
+2014-04-16  Patrick Palka  <patrick@parcs.ath.cx>
+
+       PR c++/60764
+       * call.c (build_user_type_coversion): Use build_dummy_object
+       to create the placeholder object for a constructor method call.
+       (build_special_member_call): Likewise.
+       (build_over_call): Check for the placeholder object with
+       is_dummy_object.
+       (build_new_method_call_1): Likewise.  Don't attempt to resolve
+       a dummy object for a constructor method call.
+
 2014-04-16  Paul Pluzhnikov  <ppluzhnikov@google.com>
 
        PR c++/59295
index 7c0dcc2..7dbe935 100644 (file)
@@ -3524,8 +3524,7 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags,
     {
       int ctorflags = flags;
 
-      first_arg = build_int_cst (build_pointer_type (totype), 0);
-      first_arg = build_fold_indirect_ref (first_arg);
+      first_arg = build_dummy_object (totype);
 
       /* We should never try to call the abstract or base constructor
         from here.  */
@@ -7101,7 +7100,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
         ctor is trivial, do a bitwise copy with a simple TARGET_EXPR for a
         temp or an INIT_EXPR otherwise.  */
       fa = argarray[0];
-      if (integer_zerop (fa))
+      if (is_dummy_object (fa))
        {
          if (TREE_CODE (arg) == TARGET_EXPR)
            return arg;
@@ -7443,10 +7442,7 @@ build_special_member_call (tree instance, tree name, vec<tree, va_gc> **args,
 
   /* Handle the special case where INSTANCE is NULL_TREE.  */
   if (name == complete_ctor_identifier && !instance)
-    {
-      instance = build_int_cst (build_pointer_type (class_type), 0);
-      instance = build1 (INDIRECT_REF, class_type, instance);
-    }
+    instance = build_dummy_object (class_type);
   else
     {
       if (name == complete_dtor_identifier
@@ -7756,8 +7752,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
 
       if (init)
        {
-         if (INDIRECT_REF_P (instance)
-             && integer_zerop (TREE_OPERAND (instance, 0)))
+         if (is_dummy_object (instance))
            return get_target_expr_sfinae (init, complain);
          init = build2 (INIT_EXPR, TREE_TYPE (instance), instance, init);
          TREE_SIDE_EFFECTS (init) = true;
@@ -7856,6 +7851,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
            }
 
          if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
+             && !DECL_CONSTRUCTOR_P (fn)
              && is_dummy_object (instance))
            {
              instance = maybe_resolve_dummy (instance);
index 6c52e53..8a7a836 100644 (file)
@@ -1427,7 +1427,15 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags)
   if (TREE_CODE (*decl) == TEMPLATE_DECL)
     decl = &DECL_TEMPLATE_RESULT (*decl);
 
-  decl_attributes (decl, attributes, flags);
+  if (TREE_TYPE (*decl) && TYPE_PTRMEMFUNC_P (TREE_TYPE (*decl)))
+    {
+      attributes
+       = decl_attributes (decl, attributes, flags | ATTR_FLAG_FUNCTION_NEXT);
+      decl_attributes (&TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (*decl)),
+                      attributes, flags);
+    }
+  else
+    decl_attributes (decl, attributes, flags);
 
   if (TREE_CODE (*decl) == TYPE_DECL)
     SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl));
index 2aae9ca..131af36 100644 (file)
@@ -6,6 +6,6 @@ typedef int (*F [[gnu::warn_unused_result]]) (int);
 
 typedef int (*F2 [[gnu::warn_unused_result]]) (int);
 
-typedef int (S::*F3 [[gnu::warn_unused_result]]) (int); // { dg-warning "only applies to function types" }
+typedef int (S::*F3 [[gnu::warn_unused_result]]) (int);
 
 typedef int [[gnu::warn_unused_result]] (*F5) (int); // { dg-warning "ignored" }
diff --git a/gcc/testsuite/g++.dg/ext/attrib49.C b/gcc/testsuite/g++.dg/ext/attrib49.C
new file mode 100644 (file)
index 0000000..99c6154
--- /dev/null
@@ -0,0 +1,20 @@
+// PR c++/60765
+// { dg-options "-Wall -Wunused-parameter" }
+
+struct foo
+{
+} x;
+
+void (foo::*g) (int *) __attribute__ ((nonnull (2)));
+
+void
+fun1 (void (foo::*f) (int *) __attribute__ ((nonnull (2))))
+{
+    (x.*f) ((int *) 0); // { dg-warning "null argument" }
+}
+
+void
+fun2 (void (foo::*f) () __attribute__ ((nonnull, unused))) // { dg-bogus "unused" }
+{
+    (x.*g) ((int *) 0); // { dg-warning "null argument" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/nonnull2.C b/gcc/testsuite/g++.dg/warn/nonnull2.C
new file mode 100644 (file)
index 0000000..10515a4
--- /dev/null
@@ -0,0 +1,10 @@
+// PR c++/60764
+// { dg-options "-Wall" }
+
+struct foo
+{
+  foo () __attribute__ ((nonnull (1)));
+};
+
+const foo &x = foo (); // { dg-bogus "null argument" }
+foo y = foo (); // { dg-bogus "null argument" }