diff mbox

C PATCH to warn when accessing members of atomic structures (PR c/69002)

Message ID 20151222151001.GQ3296@redhat.com
State New
Headers show

Commit Message

Marek Polacek Dec. 22, 2015, 3:10 p.m. UTC
This patch adds a warning (enabled by default) to warn about accessing elements
of atomic structures or unions, which is undefined behavior according to the C
standard.  I didn't make this a translation-time error because it's unclear if
it should be so.

Bootstrapped/regtested on x86_64-linux and powerpc64le-linux, ok for trunk?

2015-12-22  Marek Polacek  <polacek@redhat.com>

	PR c/69002
	* c-typeck.c (build_component_ref): Warn when acessing elements of
	atomic structures or unions.

	* gcc.dg/c11-atomic-1.c: Add dg-warnings.
	* gcc.dg/c11-atomic-4.c: New test.


	Marek

Comments

Joseph Myers Dec. 22, 2015, 3:13 p.m. UTC | #1
On Tue, 22 Dec 2015, Marek Polacek wrote:

> This patch adds a warning (enabled by default) to warn about accessing elements
> of atomic structures or unions, which is undefined behavior according to the C
> standard.  I didn't make this a translation-time error because it's unclear if
> it should be so.
> 
> Bootstrapped/regtested on x86_64-linux and powerpc64le-linux, ok for trunk?

OK.
diff mbox

Patch

diff --git gcc/c/c-typeck.c gcc/c/c-typeck.c
index a97774f..928fcd5 100644
--- gcc/c/c-typeck.c
+++ gcc/c/c-typeck.c
@@ -2349,6 +2349,18 @@  build_component_ref (location_t loc, tree datum, tree component)
 	  return error_mark_node;
 	}
 
+      /* Accessing elements of atomic structures or unions is undefined
+	 behavior (C11 6.5.2.3#5).  */
+      if (TYPE_ATOMIC (type) && c_inhibit_evaluation_warnings == 0)
+	{
+	  if (code == RECORD_TYPE)
+	    warning_at (loc, 0, "accessing a member %qE of an atomic "
+			"structure %qE", component, datum);
+	  else
+	    warning_at (loc, 0, "accessing a member %qE of an atomic "
+			"union %qE", component, datum);
+	}
+
       /* Chain the COMPONENT_REFs if necessary down to the FIELD.
 	 This might be better solved in future the way the C++ front
 	 end does it - by giving the anonymous entities each a
diff --git gcc/testsuite/gcc.dg/c11-atomic-1.c gcc/testsuite/gcc.dg/c11-atomic-1.c
index c7f9a1e..9702a10 100644
--- gcc/testsuite/gcc.dg/c11-atomic-1.c
+++ gcc/testsuite/gcc.dg/c11-atomic-1.c
@@ -61,15 +61,15 @@  func (_Atomic volatile long al1)
      accessing elements of atomic structures and unions is at
      translation or execution time; presume here that it's at
      execution time.  */
-  t1.i = at1.i;
-  at1.i = t1.i;
-  atp1->i = t1.i;
+  t1.i = at1.i; /* { dg-warning "accessing a member .i. of an atomic structure" } */
+  at1.i = t1.i; /* { dg-warning "accessing a member .i. of an atomic structure" } */
+  atp1->i = t1.i; /* { dg-warning "accessing a member .i. of an atomic structure" } */
   au1 = u1;
   u1 = au1;
   av1 = v1;
   v1 = av1;
-  v1.i = av1.i;
-  av1.i = v1.i;
+  v1.i = av1.i; /* { dg-warning "accessing a member .i. of an atomic union" } */
+  av1.i = v1.i; /* { dg-warning "accessing a member .i. of an atomic union" } */
   /* _Atomic is valid on register variables, even if not particularly
      useful.  */
   register _Atomic volatile int ra1 = 1, ra2 = 2;
diff --git gcc/testsuite/gcc.dg/c11-atomic-4.c gcc/testsuite/gcc.dg/c11-atomic-4.c
index e69de29..81003aa 100644
--- gcc/testsuite/gcc.dg/c11-atomic-4.c
+++ gcc/testsuite/gcc.dg/c11-atomic-4.c
@@ -0,0 +1,92 @@ 
+/* PR c/69002 */
+/* Test we diagnose accessing elements of atomic structures or unions,
+   which is undefined behavior (C11 6.5.2.3#5).  */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+struct S { int x; };
+union U { int x; };
+
+int
+fn1 (_Atomic struct S p)
+{
+  int e = 0 && p.x;
+  return p.x + e; /* { dg-warning "accessing a member .x. of an atomic structure" } */
+}
+
+int
+fn2 (_Atomic struct S *p)
+{
+  int e = 1 || p->x;
+  return p->x + e; /* { dg-warning "accessing a member .x. of an atomic structure" } */
+}
+
+void
+fn3 (_Atomic struct S p, int x)
+{
+  p.x = x; /* { dg-warning "accessing a member .x. of an atomic structure" } */
+}
+
+void
+fn4 (_Atomic struct S *p, int x)
+{
+  p->x = x; /* { dg-warning "accessing a member .x. of an atomic structure" } */
+}
+
+int
+fn5 (_Atomic struct S p)
+{
+  /* This is OK: Members can be safely accessed using a non-atomic
+     object which is assigned to or from the atomic object.  */
+  struct S s = p;
+  return s.x;
+}
+
+int
+fn6 (_Atomic struct S *p)
+{
+  struct S s = *p;
+  return s.x;
+}
+
+int
+fn7 (_Atomic union U p)
+{
+  int e = 0 && p.x;
+  return p.x + e; /* { dg-warning "accessing a member .x. of an atomic union" } */
+}
+
+int
+fn8 (_Atomic union U *p)
+{
+  int e = 1 || p->x;
+  return p->x + e; /* { dg-warning "accessing a member .x. of an atomic union" } */
+}
+
+void
+fn9 (_Atomic union U p, int x)
+{
+  p.x = x; /* { dg-warning "accessing a member .x. of an atomic union" } */
+}
+
+void
+fn10 (_Atomic union U *p, int x)
+{
+  p->x = x; /* { dg-warning "accessing a member .x. of an atomic union" } */
+}
+
+int
+fn11 (_Atomic union U p)
+{
+  /* This is OK: Members can be safely accessed using a non-atomic
+     object which is assigned to or from the atomic object.  */
+  union U s = p;
+  return s.x;
+}
+
+int
+fn12 (_Atomic union U *p)
+{
+  union U s = *p;
+  return s.x;
+}