aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2020-03-01 17:41:45 -0700
committerMartin Sebor <msebor@redhat.com>2020-03-01 17:41:45 -0700
commita499c2f899961f2c09db2dc33e60b66e8d770092 (patch)
treeb4e1280ce09a78f7b1a84f3e921d48f47aef1ef2
parent1e9369c5dcf301e090d3a83e2c210cd6b96ac08c (diff)
downloadgcc-a499c2f899961f2c09db2dc33e60b66e8d770092.zip
gcc-a499c2f899961f2c09db2dc33e60b66e8d770092.tar.gz
gcc-a499c2f899961f2c09db2dc33e60b66e8d770092.tar.bz2
PR c/93812 - ICE on redeclaration of an attribute format function without protoype
gcc/c/ChangeLog: PR c/93812 * c-typeck.c (build_functype_attribute_variant): New function. (composite_type): Call it. gcc/testsuite/ChangeLog: PR c/93812 * gcc.dg/format/proto.c: New test.
-rw-r--r--gcc/c/ChangeLog6
-rw-r--r--gcc/c/c-typeck.c27
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/format/proto.c89
4 files changed, 124 insertions, 3 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 83bf651..effb71b 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,9 @@
+2020-03-01 Martin Sebor <msebor@redhat.com>
+
+ PR c/93812
+ * c-typeck.c (build_functype_attribute_variant): New function.
+ (composite_type): Call it.
+
2020-02-25 Jakub Jelinek <jakub@redhat.com>
PR other/93912
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 8df0849..308fcff 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -353,7 +353,28 @@ c_vla_type_p (const_tree t)
return true;
return false;
}
-
+
+/* If NTYPE is a type of a non-variadic function with a prototype
+ and OTYPE is a type of a function without a prototype and ATTRS
+ contains attribute format, diagnosess and removes it from ATTRS.
+ Returns the result of build_type_attribute_variant of NTYPE and
+ the (possibly) modified ATTRS. */
+
+static tree
+build_functype_attribute_variant (tree ntype, tree otype, tree attrs)
+{
+ if (!prototype_p (otype)
+ && prototype_p (ntype)
+ && lookup_attribute ("format", attrs))
+ {
+ warning_at (input_location, OPT_Wattributes,
+ "%qs attribute cannot be applied to a function that "
+ "does not take variable arguments", "format");
+ attrs = remove_attribute ("format", attrs);
+ }
+ return build_type_attribute_variant (ntype, attrs);
+
+}
/* Return the composite type of two compatible types.
We assume that comptypes has already been done and returned
@@ -504,9 +525,9 @@ composite_type (tree t1, tree t2)
/* Save space: see if the result is identical to one of the args. */
if (valtype == TREE_TYPE (t1) && !TYPE_ARG_TYPES (t2))
- return build_type_attribute_variant (t1, attributes);
+ return build_functype_attribute_variant (t1, t2, attributes);
if (valtype == TREE_TYPE (t2) && !TYPE_ARG_TYPES (t1))
- return build_type_attribute_variant (t2, attributes);
+ return build_functype_attribute_variant (t2, t1, attributes);
/* Simple way if one arg fails to specify argument types. */
if (TYPE_ARG_TYPES (t1) == NULL_TREE)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7e73cc6..a6524be 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
2020-03-01 Martin Sebor <msebor@redhat.com>
+ PR c/93812
+ * gcc.dg/format/proto.c: New test.
+
+2020-03-01 Martin Sebor <msebor@redhat.com>
+
PR middle-end/93829
* gcc.dg/Wstringop-overflow-32.c: New test.
diff --git a/gcc/testsuite/gcc.dg/format/proto.c b/gcc/testsuite/gcc.dg/format/proto.c
new file mode 100644
index 0000000..b2050c9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/format/proto.c
@@ -0,0 +1,89 @@
+/* PR c/93812 - ICE on redeclaration of an attribute format function without
+ protoype
+ It's not clear that attribute format should be accepted on functions
+ without a prototype. If it's decided that it shouldn't be the tests
+ here will need to be adjusted.
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+#define FMT(n1, n2) __attribute__((__format__(__printf__, n1, n2)))
+
+// Exercise function declarations.
+FMT (1, 2) void print1 ();
+
+FMT (2, 3) void print2 ();
+ void print2 ();
+
+FMT (3, 4) void print3 ();
+FMT (3, 4) void print3 ();
+
+FMT (1, 2) void print4 ();
+ void print4 (void); // { dg-warning "'format' attribute cannot be applied to a function that does not take variable arguments" }
+
+ void print5 ();
+FMT (1, 2) void print5 (void); // { dg-warning "\\\[-Wattributes" }
+
+FMT (1, 2) void print6 ();
+ void print6 (const char*, ...); // { dg-error "conflicting types" }
+
+ void print7 (const char*, ...);
+FMT (1, 2) void print7 (); // { dg-error "conflicting types" }
+
+
+// Exercise function calls.
+void test_print (void)
+{
+ print1 ("%i %s", 123, "");
+ print1 ("%s %i", 123, 123); // { dg-warning "\\\[-Wformat" }
+
+ print2 (0, "%s %i", "", 123);
+ print2 (1, "%i %s", "", 123); // { dg-warning "\\\[-Wformat" }
+
+ print3 (0, 1, "%s %i", "", 123);
+ print3 (1, 2, "%i %s", "", 123); // { dg-warning "\\\[-Wformat" }
+
+ // Just verify there's no ICE.
+ print4 ();
+ print5 ();
+ print6 ("%i %s", 123, "");
+}
+
+
+// Exercise declarations of pointers to functions.
+FMT (1, 2) void (*pfprint1)();
+
+FMT (2, 3) void (*pfprint2)();
+ void (*pfprint2)();
+
+FMT (3, 4) void (*pfprint3)();
+FMT (3, 4) void (*pfprint3)();
+
+FMT (1, 2) void (*pfprint4)();
+ void (*pfprint4)(void); // { dg-warning "'format' attribute cannot be applied to a function that does not take variable arguments" }
+
+ void (*pfprint5)();
+FMT (1, 2) void (*pfprint5)(void); // { dg-warning "\\\[-Wattributes" }
+
+FMT (1, 2) void (*pfprint6)();
+ void (*pfprint6)(const char*, ...); // { dg-error "conflicting types" }
+
+ void (*pfprint7)(const char*, ...);
+FMT (1, 2) void (*pfprint7)(); // { dg-error "conflicting types" }
+
+// Exercise calls via function pointers.
+void test_pfprint (void)
+{
+ pfprint1 ("%i %s", 123, "");
+ pfprint1 ("%s %i", 123, 123); // { dg-warning "\\\[-Wformat" }
+
+ pfprint2 (0, "%s %i", "", 123);
+ pfprint2 (1, "%i %s", "", 123); // { dg-warning "\\\[-Wformat" }
+
+ pfprint3 (0, 1, "%s %i", "", 123);
+ pfprint3 (1, 2, "%i %s", "", 123); // { dg-warning "\\\[-Wformat" }
+
+ // Just verify there's no ICE.
+ pfprint4 ();
+ pfprint5 ();
+ pfprint6 ("%i %s", 123, "");
+}