aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2019-12-04 23:26:10 +0000
committerJoseph Myers <jsm28@gcc.gnu.org>2019-12-04 23:26:10 +0000
commit4691bf46e3572dec2040a4ac59b9e9e279b827d7 (patch)
tree0bc763be30e740b45f4af65fde1f52977102431c
parentf30025bb34ca110653f517efd6d6193cc8bac1aa (diff)
downloadgcc-4691bf46e3572dec2040a4ac59b9e9e279b827d7.zip
gcc-4691bf46e3572dec2040a4ac59b9e9e279b827d7.tar.gz
gcc-4691bf46e3572dec2040a4ac59b9e9e279b827d7.tar.bz2
Fix C handling of use of lvalues of incomplete types (PR c/36941, PR c/88827).
Bug 88827 points out that GCC should not be rejecting C code that dereferences a pointer to an incomplete type in the case that uses &* to take the address of the resulting lvalue, because no constraint is violated in that case (other than for C90 when the incomplete type is unqualified void, which we already handle correctly) and as the lvalue never gets converted to an rvalue there is no undefined behavior either. This means that the diagnostic for such a dereference is bogus and should be removed; if the lvalue gets converted to an rvalue, there should be an appropriate error later for the use of the incomplete type. In most cases, there is, but bug 36941 points out the lack of a diagnostic when the incomplete (non-void) type gets cast to void (where a diagnostic seems appropriate for this undefined behavior as a matter of quality of implementation). This patch removes the bogus diagnostic (and C_TYPE_ERROR_REPORTED which was only used in the code that is removed - only that one, bogus diagnostic had this duplicate suppression, not any of the other, more legitimate diagnostics for use of incomplete types) and makes convert_lvalue_to_rvalue call require_complete_type for arguments not of void types, so that all relevant code paths (possibly except some for ObjC) get incomplete types diagnosed. It's possible that this makes some other checks for incomplete types obsolete, but no attempt is made to remove any such checks. Bootstrapped with no regressions for x86_64-pc-linux-gnu. PR c/36941 PR c/88827 gcc/c: * c-typeck.c (convert_lvalue_to_rvalue): Call require_complete_type for arguments not of void types. (build_indirect_ref): Do not diagnose dereferencing pointers to incomplete types. * c-tree.h (C_TYPE_ERROR_REPORTED): Remove. gcc/testsuite: * gcc.dg/lvalue-9.c, gcc.dg/lvalue-10.c: New tests. * gcc.dg/array-8.c, gcc.dg/enum-incomplete-1.c, gcc.dg/enum-incomplete-3.c, gcc.dg/noncompile/incomplete-3.c, gcc.dg/pr48552-1.c, gcc.dg/pr48552-2.c, gcc.dg/pr63543.c, gcc.dg/pr69796.c: Update expected diagnostics. From-SVN: r278976
-rw-r--r--gcc/c/ChangeLog10
-rw-r--r--gcc/c/c-tree.h3
-rw-r--r--gcc/c/c-typeck.c12
-rw-r--r--gcc/testsuite/ChangeLog10
-rw-r--r--gcc/testsuite/gcc.dg/array-8.c1
-rw-r--r--gcc/testsuite/gcc.dg/enum-incomplete-1.c10
-rw-r--r--gcc/testsuite/gcc.dg/enum-incomplete-3.c10
-rw-r--r--gcc/testsuite/gcc.dg/lvalue-10.c22
-rw-r--r--gcc/testsuite/gcc.dg/lvalue-9.c77
-rw-r--r--gcc/testsuite/gcc.dg/noncompile/incomplete-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr48552-1.c5
-rw-r--r--gcc/testsuite/gcc.dg/pr48552-2.c5
-rw-r--r--gcc/testsuite/gcc.dg/pr63543.c12
-rw-r--r--gcc/testsuite/gcc.dg/pr69796.c2
14 files changed, 146 insertions, 35 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 3ea177f..f9c6293 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,13 @@
+2019-12-04 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/36941
+ PR c/88827
+ * c-typeck.c (convert_lvalue_to_rvalue): Call
+ require_complete_type for arguments not of void types.
+ (build_indirect_ref): Do not diagnose dereferencing pointers to
+ incomplete types.
+ * c-tree.h (C_TYPE_ERROR_REPORTED): Remove.
+
2019-12-03 Joseph Myers <joseph@codesourcery.com>
PR c/88704
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index cdfb908..ff2345d 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -55,9 +55,6 @@ along with GCC; see the file COPYING3. If not see
This is used for -Wc++-compat. */
#define C_TYPE_DEFINED_IN_STRUCT(TYPE) TYPE_LANG_FLAG_2 (TYPE)
-/* Record whether an "incomplete type" error was given for the type. */
-#define C_TYPE_ERROR_REPORTED(TYPE) TYPE_LANG_FLAG_3 (TYPE)
-
/* Record whether a typedef for type `int' was actually `signed int'. */
#define C_TYPEDEF_EXPLICITLY_SIGNED(EXP) DECL_LANG_FLAG_1 (EXP)
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index f9ab1e3..36aedc0 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -2054,6 +2054,8 @@ convert_lvalue_to_rvalue (location_t loc, struct c_expr exp,
mark_exp_read (exp.value);
if (convert_p)
exp = default_function_array_conversion (loc, exp);
+ if (!VOID_TYPE_P (TREE_TYPE (exp.value)))
+ exp.value = require_complete_type (loc, exp.value);
if (really_atomic_lvalue (exp.value))
{
vec<tree, va_gc> *params;
@@ -2550,16 +2552,6 @@ build_indirect_ref (location_t loc, tree ptr, ref_operator errstring)
ref = build1 (INDIRECT_REF, t, pointer);
- if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE)
- {
- if (!C_TYPE_ERROR_REPORTED (TREE_TYPE (ptr)))
- {
- error_at (loc, "dereferencing pointer to incomplete type "
- "%qT", t);
- C_TYPE_ERROR_REPORTED (TREE_TYPE (ptr)) = 1;
- }
- return error_mark_node;
- }
if (VOID_TYPE_P (t) && c_inhibit_evaluation_warnings == 0)
warning_at (loc, 0, "dereferencing %<void *%> pointer");
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7678625..48a6d45 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,13 @@
+2019-12-04 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/36941
+ PR c/88827
+ * gcc.dg/lvalue-9.c, gcc.dg/lvalue-10.c: New tests.
+ * gcc.dg/array-8.c, gcc.dg/enum-incomplete-1.c,
+ gcc.dg/enum-incomplete-3.c, gcc.dg/noncompile/incomplete-3.c,
+ gcc.dg/pr48552-1.c, gcc.dg/pr48552-2.c, gcc.dg/pr63543.c,
+ gcc.dg/pr69796.c: Update expected diagnostics.
+
2019-12-04 Richard Sandiford <richard.sandiford@arm.com>
* gcc.target/aarch64/sve/acle/general/whilelt_5.c: New test.
diff --git a/gcc/testsuite/gcc.dg/array-8.c b/gcc/testsuite/gcc.dg/array-8.c
index 644d84f..71c9803 100644
--- a/gcc/testsuite/gcc.dg/array-8.c
+++ b/gcc/testsuite/gcc.dg/array-8.c
@@ -43,6 +43,5 @@ g (void)
pv[0]; /* { dg-warning "dereferencing 'void \\*' pointer" } */
0[pv]; /* { dg-warning "dereferencing 'void \\*' pointer" } */
sip[0]; /* { dg-error "invalid use of undefined type 'struct si'" } */
- /* { dg-error "dereferencing pointer to incomplete type" "incomplete" { target *-*-* } .-1 } */
0[sip]; /* { dg-error "invalid use of undefined type 'struct si'" } */
}
diff --git a/gcc/testsuite/gcc.dg/enum-incomplete-1.c b/gcc/testsuite/gcc.dg/enum-incomplete-1.c
index 06c247c..2da3b58 100644
--- a/gcc/testsuite/gcc.dg/enum-incomplete-1.c
+++ b/gcc/testsuite/gcc.dg/enum-incomplete-1.c
@@ -13,14 +13,16 @@ f0 (int i)
{
ve; /* { dg-error "incomplete" } */
vs; /* { dg-error "incomplete" } */
- (void) ve;
- (void) vs;
+ (void) ve; /* { dg-error "incomplete" } */
+ (void) vs; /* { dg-error "incomplete" } */
(void) (i ? ve : ve); /* { dg-error "incomplete" } */
(void) (i ? vs : vs); /* { dg-error "incomplete" } */
(void) (ve = ve); /* { dg-error "incomplete" } */
(void) (vs = vs); /* { dg-error "incomplete" } */
- (void) ve, (void) ve;
- (void) vs, (void) vs;
+ (void) ve, /* { dg-error "incomplete" } */
+ (void) ve; /* { dg-error "incomplete" } */
+ (void) vs, /* { dg-error "incomplete" } */
+ (void) vs; /* { dg-error "incomplete" } */
p = &ve;
p = &vs;
(void) sizeof (ve); /* { dg-error "incomplete" } */
diff --git a/gcc/testsuite/gcc.dg/enum-incomplete-3.c b/gcc/testsuite/gcc.dg/enum-incomplete-3.c
index db1138b..12280db 100644
--- a/gcc/testsuite/gcc.dg/enum-incomplete-3.c
+++ b/gcc/testsuite/gcc.dg/enum-incomplete-3.c
@@ -4,17 +4,17 @@
enum E e; /* { dg-error "storage size" } */
-void bar (int [e]); /* { dg-error "size of unnamed array has incomplete type" } */
-void bar2 (int [][e]); /* { dg-error "size of unnamed array has incomplete type" } */
+void bar (int [e]); /* { dg-error "has an incomplete type" } */
+void bar2 (int [][e]); /* { dg-error "has an incomplete type" } */
void
foo (void)
{
- int a1[e]; /* { dg-error "size of array .a1. has incomplete type" } */
- int a2[e][3]; /* { dg-error "size of array .a2. has incomplete type" } */
+ int a1[e]; /* { dg-error "has an incomplete type" } */
+ int a2[e][3]; /* { dg-error "has an incomplete type" } */
struct S
{
- int a3[e]; /* { dg-error "size of array .a3. has incomplete type" } */
+ int a3[e]; /* { dg-error "has an incomplete type" } */
};
}
diff --git a/gcc/testsuite/gcc.dg/lvalue-10.c b/gcc/testsuite/gcc.dg/lvalue-10.c
new file mode 100644
index 0000000..cc5f37b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lvalue-10.c
@@ -0,0 +1,22 @@
+/* Test handling of lvalues of incomplete types. Bugs 36941, 88647
+ (invalid), 88827. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+struct S;
+
+extern struct S var;
+extern struct S *vp;
+
+void
+f8 (void)
+{
+ /* These are valid because there is no constraint violation and the
+ result of '*' is never converted from an lvalue to an rvalue
+ (which would yield undefined behavior). */
+ &var;
+ &*vp;
+ &(var);
+ &(*vp);
+ &*&*vp;
+}
diff --git a/gcc/testsuite/gcc.dg/lvalue-9.c b/gcc/testsuite/gcc.dg/lvalue-9.c
new file mode 100644
index 0000000..382b3ff
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lvalue-9.c
@@ -0,0 +1,77 @@
+/* Test handling of lvalues of incomplete types. Bugs 36941, 88647
+ (invalid), 88827. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+struct S;
+
+extern struct S var;
+extern struct S *vp;
+extern int i;
+
+void
+f1 (void)
+{
+ var; /* { dg-error "has an incomplete type" } */
+ var, (void) 0; /* { dg-error "has an incomplete type" } */
+ (i
+ ? var /* { dg-error "has an incomplete type" } */
+ : var); /* { dg-error "has an incomplete type" } */
+}
+
+void
+f2 (void)
+{
+ (void) var; /* { dg-error "has an incomplete type" } */
+ (void) (var, (void) 0); /* { dg-error "has an incomplete type" } */
+ (void) (i
+ ? var /* { dg-error "has an incomplete type" } */
+ : var); /* { dg-error "has an incomplete type" } */
+}
+
+void
+f3 (void)
+{
+ (const void) var; /* { dg-error "has an incomplete type" } */
+ (const void) (var, (void) 0); /* { dg-error "has an incomplete type" } */
+ (const void) (i
+ ? var /* { dg-error "has an incomplete type" } */
+ : var); /* { dg-error "has an incomplete type" } */
+}
+
+void
+f4 (void)
+{
+ *vp; /* { dg-error "invalid use of undefined type" } */
+ *vp, (void) 0; /* { dg-error "invalid use of undefined type" } */
+ (i
+ ? *vp /* { dg-error "invalid use of undefined type" } */
+ : *vp); /* { dg-error "invalid use of undefined type" } */
+}
+
+void
+f5 (void)
+{
+ (void) *vp; /* { dg-error "invalid use of undefined type" } */
+ (void) (*vp, (void) 0); /* { dg-error "invalid use of undefined type" } */
+ (void) (i
+ ? *vp /* { dg-error "invalid use of undefined type" } */
+ : *vp); /* { dg-error "invalid use of undefined type" } */
+}
+
+void
+f6 (void)
+{
+ (const void) *vp; /* { dg-error "invalid use of undefined type" } */
+ (const void) (*vp, (void) 0); /* { dg-error "invalid use of undefined type" } */
+ (const void) (i
+ ? *vp /* { dg-error "invalid use of undefined type" } */
+ : *vp); /* { dg-error "invalid use of undefined type" } */
+}
+
+void
+f7 (void)
+{
+ /* This is invalid because of the constraints on []. */
+ &vp[0]; /* { dg-error "invalid use of undefined type" } */
+}
diff --git a/gcc/testsuite/gcc.dg/noncompile/incomplete-3.c b/gcc/testsuite/gcc.dg/noncompile/incomplete-3.c
index 735ef46..0618b4d 100644
--- a/gcc/testsuite/gcc.dg/noncompile/incomplete-3.c
+++ b/gcc/testsuite/gcc.dg/noncompile/incomplete-3.c
@@ -5,5 +5,5 @@ int foo (void)
{
b_t d;
struct b_t *c = &d; /* { dg-warning "incompatible pointer type" } */
- c->a; /* { dg-error "incomplete type" } */
+ c->a; /* { dg-error "invalid use of undefined type" } */
}
diff --git a/gcc/testsuite/gcc.dg/pr48552-1.c b/gcc/testsuite/gcc.dg/pr48552-1.c
index 70d3483..11ee401 100644
--- a/gcc/testsuite/gcc.dg/pr48552-1.c
+++ b/gcc/testsuite/gcc.dg/pr48552-1.c
@@ -43,11 +43,12 @@ f6 (void *x)
void
f7 (struct S *x)
{
- __asm volatile ("" : : "r" (*x)); /* { dg-error "dereferencing pointer to incomplete type" } */
+ __asm volatile ("" : : "r" (*x)); /* { dg-error "invalid use of undefined type" } */
}
void
f8 (struct S *x)
{
- __asm volatile ("" : "=r" (*x)); /* { dg-error "invalid lvalue in 'asm' output 0" } */
+ __asm volatile ("" : "=r" (*x)); /* { dg-error "impossible constraint in 'asm'" } */
+ /* { dg-error "non-memory output 0 must stay in memory" "memory" { target *-*-* } .-1 } */
}
diff --git a/gcc/testsuite/gcc.dg/pr48552-2.c b/gcc/testsuite/gcc.dg/pr48552-2.c
index ce6bece..2d2a00c 100644
--- a/gcc/testsuite/gcc.dg/pr48552-2.c
+++ b/gcc/testsuite/gcc.dg/pr48552-2.c
@@ -43,11 +43,12 @@ f6 (void *x)
void
f7 (struct S *x)
{
- __asm ("" : : "r" (*x)); /* { dg-error "dereferencing pointer to incomplete type" } */
+ __asm ("" : : "r" (*x)); /* { dg-error "invalid use of undefined type" } */
}
void
f8 (struct S *x)
{
- __asm ("" : "=r" (*x)); /* { dg-error "invalid lvalue in 'asm' output 0" } */
+ __asm ("" : "=r" (*x)); /* { dg-error "impossible constraint in 'asm'" } */
+ /* { dg-error "non-memory output 0 must stay in memory" "memory" { target *-*-* } .-1 } */
}
diff --git a/gcc/testsuite/gcc.dg/pr63543.c b/gcc/testsuite/gcc.dg/pr63543.c
index 215b62e..d85e10d 100644
--- a/gcc/testsuite/gcc.dg/pr63543.c
+++ b/gcc/testsuite/gcc.dg/pr63543.c
@@ -7,15 +7,15 @@ union U;
int
f1 (struct S *s)
{
- return s->a /* { dg-error "dereferencing pointer to incomplete type .struct S." } */
- + s->b
- + s->c;
+ return s->a /* { dg-error "invalid use of undefined type .struct S." } */
+ + s->b /* { dg-error "invalid use of undefined type .struct S." } */
+ + s->c; /* { dg-error "invalid use of undefined type .struct S." } */
}
int
f2 (union U *u)
{
- return u->a /* { dg-error "dereferencing pointer to incomplete type .union U." } */
- + u->a
- + u->a;
+ return u->a /* { dg-error "invalid use of undefined type .union U." } */
+ + u->a /* { dg-error "invalid use of undefined type .union U." } */
+ + u->a; /* { dg-error "invalid use of undefined type .union U." } */
}
diff --git a/gcc/testsuite/gcc.dg/pr69796.c b/gcc/testsuite/gcc.dg/pr69796.c
index ebf34aa..4b725a5 100644
--- a/gcc/testsuite/gcc.dg/pr69796.c
+++ b/gcc/testsuite/gcc.dg/pr69796.c
@@ -6,5 +6,5 @@ struct S s; /* { dg-error "storage size of 's' isn't known" } */
void
foo ()
{
- s a; /* { dg-error "expression statement has incomplete type|expected" } */
+ s a; /* { dg-error "has an incomplete type|expected" } */
}