PR middle-end/97879 - ICE on invalid mode in attribute access
authorMartin Sebor <msebor@redhat.com>
Fri, 20 Nov 2020 20:44:57 +0000 (13:44 -0700)
committerMartin Sebor <msebor@redhat.com>
Fri, 20 Nov 2020 20:46:42 +0000 (13:46 -0700)
gcc/c-family/ChangeLog:

PR middle-end/97879
* c-attribs.c (handle_access_attribute): Handle ATTR_FLAG_INTERNAL.
Error out on invalid modes.

gcc/c/ChangeLog:
PR middle-end/97879
* c-decl.c (start_function): Set ATTR_FLAG_INTERNAL in flags.

gcc/ChangeLog:

PR middle-end/97879
* tree-core.h (enum attribute_flags): Add ATTR_FLAG_INTERNAL.

gcc/testsuite/ChangeLog:

PR middle-end/97879
* gcc.dg/attr-access-3.c: New test.

gcc/c-family/c-attribs.c
gcc/c/c-decl.c
gcc/testsuite/gcc.dg/attr-access-3.c [new file with mode: 0644]
gcc/tree-core.h

index b979fbcc0c6c571e33b3524c48cb0f79a81be4ea..1d2ab7c81eda254086fbb4e69cc699fe754c6270 100644 (file)
@@ -2810,9 +2810,11 @@ handle_copy_attribute (tree *node, tree name, tree args,
   tree attrs = TYPE_ATTRIBUTES (reftype);
 
   /* Copy type attributes from REF to DECL.  Pass in REF if it's a DECL
-     or a type but not if it's an expression.  */
+     or a type but not if it's an expression.  Set ATTR_FLAG_INTERNAL
+     since the attributes' arguments may be in their internal form.  */
   for (tree at = attrs; at; at = TREE_CHAIN (at))
-    decl_attributes (node, at, flags, EXPR_P (ref) ? NULL_TREE : ref);
+    decl_attributes (node, at, flags | ATTR_FLAG_INTERNAL,
+                    EXPR_P (ref) ? NULL_TREE : ref);
 
   return NULL_TREE;
 }
@@ -4289,8 +4291,8 @@ append_access_attr (tree node[3], tree attrs, const char *attrstr,
    the attribute and its arguments into a string.  */
 
 static tree
-handle_access_attribute (tree node[3], tree name, tree args,
-                        int ARG_UNUSED (flags), bool *no_add_attrs)
+handle_access_attribute (tree node[3], tree name, tree args, int flags,
+                        bool *no_add_attrs)
 {
   tree attrs = TYPE_ATTRIBUTES (*node);
   tree type = *node;
@@ -4336,15 +4338,19 @@ handle_access_attribute (tree node[3], tree name, tree args,
 
          /* Recursively call self to "replace" the documented/external
             form of the attribute with the condensend internal form.  */
-         decl_attributes (node, axsat, flags);
+         decl_attributes (node, axsat, flags | ATTR_FLAG_INTERNAL);
          return NULL_TREE;
        }
 
-      /* This is a recursive call to handle the condensed internal form
-        of the attribute (see below).  Since all validation has been
-        done simply return here, accepting the attribute as is.  */
-      *no_add_attrs = false;
-      return NULL_TREE;
+      if (flags & ATTR_FLAG_INTERNAL)
+       {
+         /* This is a recursive call to handle the condensed internal
+            form of the attribute (see below).  Since all validation
+            has been done simply return here, accepting the attribute
+            as is.  */
+         *no_add_attrs = false;
+         return NULL_TREE;
+       }
     }
 
   /* Set to true when the access mode has the form of a function call
@@ -4363,6 +4369,13 @@ handle_access_attribute (tree node[3], tree name, tree args,
       access_mode = DECL_NAME (access_mode);
       funcall = true;
     }
+  else if (TREE_CODE (access_mode) != IDENTIFIER_NODE)
+    {
+      error ("attribute %qE mode %qE is not an identifier; expected one of "
+            "%qs, %qs, %qs, or %qs", name, access_mode,
+            "read_only", "read_write", "write_only", "none");
+      return NULL_TREE;
+    }
 
   const char* const access_str = IDENTIFIER_POINTER (access_mode);
   const char *ps = access_str;
@@ -4573,7 +4586,7 @@ handle_access_attribute (tree node[3], tree name, tree args,
 
   /* Recursively call self to "replace" the documented/external form
      of the attribute with the condensed internal form.  */
-  decl_attributes (node, new_attrs, flags);
+  decl_attributes (node, new_attrs, flags | ATTR_FLAG_INTERNAL);
   return NULL_TREE;
 }
 
index 1b02240114b8a2aed9453ee30f3437fe20957b9b..27f77224ea47f21e6a3ceb2a71e1d7afd84345b1 100644 (file)
@@ -9598,7 +9598,8 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
   current_function_decl = pushdecl (decl1);
 
   if (tree access = build_attr_access_from_parms (parms, false))
-    decl_attributes (&current_function_decl, access, 0, old_decl);
+    decl_attributes (&current_function_decl, access, ATTR_FLAG_INTERNAL,
+                    old_decl);
 
   push_scope ();
   declare_parm_level ();
diff --git a/gcc/testsuite/gcc.dg/attr-access-3.c b/gcc/testsuite/gcc.dg/attr-access-3.c
new file mode 100644 (file)
index 0000000..45dd1aa
--- /dev/null
@@ -0,0 +1,21 @@
+/* PR middle-end/97879 - ICE on invalid mode in attribute access
+   { dg-do compile }
+   { dg-options "-Wall" } */
+
+#define A(...) __attribute__ ((access (__VA_ARGS__)))
+
+A (" ", 1) void f1 (int *);       // { dg-error "attribute 'access' mode '\" \"' is not an identifier; expected one of 'read_only', 'read_write', 'write_only', or 'none'" }
+           void f1 (int *);
+
+
+A ("none", 1) void f2 (char *);   // { dg-error "not an identifier" }
+              void f2 (char *);
+
+A (1) void f3 ();                 // { dg-error "not an identifier" }
+
+A (1, 2) void f4 ();              // { dg-error "not an identifier" }
+A (2., 3.) void f5 ();            // { dg-error "not an identifier" }
+
+// Verify that copying a valid access attribute doesn't cause errors.
+A (read_only, 1, 2)         void f6 (void*, int);
+__attribute__ ((copy (f6))) void f7 (void*, int);
index c9280a8d3b115921d3df704a58e6e83f334a8bf3..313a6af2253454491f1f0d743ef496e4590a11cb 100644 (file)
@@ -859,7 +859,10 @@ enum attribute_flags {
      are not in fact compatible with the function type.  */
   ATTR_FLAG_BUILT_IN = 16,
   /* A given attribute has been parsed as a C++-11 attribute.  */
-  ATTR_FLAG_CXX11 = 32
+  ATTR_FLAG_CXX11 = 32,
+  /* The attribute handler is being invoked with an internal argument
+     that may not otherwise be valid when specified in source code.  */
+  ATTR_FLAG_INTERNAL = 64
 };
 
 /* Types used to represent sizes.  */