PR middle-end/26306
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 16 Nov 2006 21:25:16 +0000 (21:25 +0000)
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 16 Nov 2006 21:25:16 +0000 (21:25 +0000)
* gimplify.c (gimplify_expr): Only force a load for references to
non-BLKmode volatile values.
* doc/implement-c.texi (Qualifiers implementation): Document the
interpretation of what a volatile access is.
* doc/extend.texi (C++ Extensions): Rework same documentation.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@118900 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/doc/extend.texi
gcc/doc/implement-c.texi
gcc/gimplify.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/volatile_aggregate.adb [new file with mode: 0644]

index fed1fb5..c0cb879 100644 (file)
@@ -1,3 +1,12 @@
+2006-11-16  Eric Botcazou  <ebotcazou@adacore.com>
+
+       PR middle-end/26306
+       * gimplify.c (gimplify_expr): Only force a load for references to
+       non-BLKmode volatile values.
+       * doc/implement-c.texi (Qualifiers implementation): Document the
+       interpretation of what a volatile access is.
+       * doc/extend.texi (C++ Extensions): Rework same documentation.
+
 2006-11-16  Joseph Myers  <joseph@codesourcery.com>
 
        * config/rs6000/spe.md (frob_di_df_2): Handle non-offsettable
index 079bc37..3576b71 100644 (file)
@@ -10441,11 +10441,10 @@ Predefined Macros,cpp,The GNU C Preprocessor}).
 
 Both the C and C++ standard have the concept of volatile objects.  These
 are normally accessed by pointers and used for accessing hardware.  The
-standards encourage compilers to refrain from optimizations
-concerning accesses to volatile objects that it might perform on
-non-volatile objects.  The C standard leaves it implementation defined
-as to what constitutes a volatile access.  The C++ standard omits to
-specify this, except to say that C++ should behave in a similar manner
+standards encourage compilers to refrain from optimizations concerning
+accesses to volatile objects.  The C standard leaves it implementation
+defined  as to what constitutes a volatile access.  The C++ standard omits
+to specify this, except to say that C++ should behave in a similar manner
 to C with respect to volatiles, where possible.  The minimum either
 standard specifies is that at a sequence point all previous accesses to
 volatile objects have stabilized and no subsequent accesses have
@@ -10455,55 +10454,28 @@ for accesses across a sequence point.  The use of volatiles does not
 allow you to violate the restriction on updating objects multiple times
 within a sequence point.
 
-In most expressions, it is intuitively obvious what is a read and what is
-a write.  For instance
+@xref{Qualifiers implementation, , Volatile qualifier and the C compiler}.
 
-@smallexample
-volatile int *dst = @var{somevalue};
-volatile int *src = @var{someothervalue};
-*dst = *src;
-@end smallexample
-
-@noindent
-will cause a read of the volatile object pointed to by @var{src} and stores the
-value into the volatile object pointed to by @var{dst}.  There is no
-guarantee that these reads and writes are atomic, especially for objects
-larger than @code{int}.
-
-Less obvious expressions are where something which looks like an access
-is used in a void context.  An example would be,
+The behavior differs slightly between C and C++ in the non-obvious cases:
 
 @smallexample
 volatile int *src = @var{somevalue};
 *src;
 @end smallexample
 
-With C, such expressions are rvalues, and as rvalues cause a read of
-the object, GCC interprets this as a read of the volatile being pointed
-to.  The C++ standard specifies that such expressions do not undergo
-lvalue to rvalue conversion, and that the type of the dereferenced
+With C, such expressions are rvalues, and GCC interprets this either as a
+read of the volatile object being pointed to or only as request to evaluate
+the side-effects.  The C++ standard specifies that such expressions do not
+undergo lvalue to rvalue conversion, and that the type of the dereferenced
 object may be incomplete.  The C++ standard does not specify explicitly
-that it is this lvalue to rvalue conversion which is responsible for
+that it is this lvalue to rvalue conversion which may be responsible for
 causing an access.  However, there is reason to believe that it is,
 because otherwise certain simple expressions become undefined.  However,
 because it would surprise most programmers, G++ treats dereferencing a
-pointer to volatile object of complete type in a void context as a read
-of the object.  When the object has incomplete type, G++ issues a
-warning.
-
-@smallexample
-struct S;
-struct T @{int m;@};
-volatile S *ptr1 = @var{somevalue};
-volatile T *ptr2 = @var{somevalue};
-*ptr1;
-*ptr2;
-@end smallexample
-
-In this example, a warning is issued for @code{*ptr1}, and @code{*ptr2}
-causes a read of the object pointed to.  If you wish to force an error on
-the first case, you must force a conversion to rvalue with, for instance
-a static cast, @code{static_cast<S>(*ptr1)}.
+pointer to volatile object of complete type when the value is unused as
+GCC would do for an equivalent type in C.  When the object has incomplete
+type, G++ issues a warning; if you wish to force an error, you must
+force a conversion to rvalue with, for instance, a static cast.
 
 When using a reference to volatile, G++ does not treat equivalent
 expressions as accesses to volatiles, but instead issues a warning that
index 9631233..dc99610 100644 (file)
@@ -503,7 +503,42 @@ determined by the ABI@.
 @cite{What constitutes an access to an object that has volatile-qualified
 type (C90 6.5.3, C99 6.7.3).}
 
-@xref{Volatiles, , When is a Volatile Object Accessed?}.
+Such an object is normally accessed by pointers and used for accessing
+hardware.  In most expressions, it is intuitively obvious what is a read
+and what is a write.  For example
+
+@smallexample
+volatile int *dst = @var{somevalue};
+volatile int *src = @var{someothervalue};
+*dst = *src;
+@end smallexample
+
+@noindent
+will cause a read of the volatile object pointed to by @var{src} and store the
+value into the volatile object pointed to by @var{dst}.  There is no
+guarantee that these reads and writes are atomic, especially for objects
+larger than @code{int}.
+
+However, if the volatile storage is not being modified, and the value of
+the volatile storage is not used, then the situation is less obvious.
+For example
+
+@smallexample
+volatile int *src = @var{somevalue};
+*src;
+@end smallexample
+
+According to the C standard, such an expression is an rvalue whose type
+is the unqualified version of its original type, i.e. @code{int}.  Whether
+GCC interprets this as a read of the volatile object being pointed to or
+only as a request to evaluate the expression for its side-effects depends
+on this type.
+
+If it is a scalar type, or on most targets an aggregate type whose only
+member object is of a scalar type, or a union type whose member objects
+are of scalar types, the expression is interpreted by GCC as a read of
+the volatile object; in the other cases, the expression is only evaluated
+for its side-effects.
 
 @end itemize
 
index ab2efac..81a18a0 100644 (file)
@@ -5854,7 +5854,8 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
                             gimple_test_f, fallback);
              break;
 
-           case ARRAY_REF: case ARRAY_RANGE_REF:
+           case ARRAY_REF:
+           case ARRAY_RANGE_REF:
              gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
                             gimple_test_f, fallback);
              gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p,
@@ -5863,16 +5864,17 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
 
            default:
               /* Anything else with side-effects must be converted to
-                 a valid statement before we get here.  */
+                 a valid statement before we get here.  */
              gcc_unreachable ();
            }
 
          *expr_p = NULL;
        }
-      else if (COMPLETE_TYPE_P (TREE_TYPE (*expr_p)))
+      else if (COMPLETE_TYPE_P (TREE_TYPE (*expr_p))
+              && TYPE_MODE (TREE_TYPE (*expr_p)) != BLKmode)
        {
-         /* Historically, the compiler has treated a bare
-            reference to a volatile lvalue as forcing a load.  */
+         /* Historically, the compiler has treated a bare reference
+            to a non-BLKmode volatile lvalue as forcing a load.  */
          tree type = TYPE_MAIN_VARIANT (TREE_TYPE (*expr_p));
          /* Normally, we do not want to create a temporary for a
             TREE_ADDRESSABLE type because such a type should not be
@@ -5887,7 +5889,10 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
        }
       else
        /* We can't do anything useful with a volatile reference to
-          incomplete type, so just throw it away.  */
+          an incomplete type, so just throw it away.  Likewise for
+          a BLKmode type, since any implicit inner load should
+          already have been turned into an explicit one by the
+          gimplification process.  */
        *expr_p = NULL;
     }
 
index efbbfe4..28da16b 100644 (file)
@@ -1,3 +1,7 @@
+2006-11-16  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/volatile_aggregate.adb: New test.
+
 2006-11-16  Francois-Xavier Coudert  <coudert@clipper.ens.fr>
 
        PR fortran/29391
diff --git a/gcc/testsuite/gnat.dg/volatile_aggregate.adb b/gcc/testsuite/gnat.dg/volatile_aggregate.adb
new file mode 100644 (file)
index 0000000..e30e28b
--- /dev/null
@@ -0,0 +1,33 @@
+-- { dg-do compile }
+
+with System;
+
+procedure Volatile_Aggregate is 
+
+  function GetArrayUpperBound return Integer is 
+  begin
+    return 2;
+  end GetArrayUpperBound; 
+
+  some_value : Integer := GetArrayUpperBound;
+
+  type Gp_Element_Type is record
+    Element : Integer;
+  end record;
+
+  type some_type is array (1 .. some_value) of Gp_Element_Type;
+
+  type Aligned_Some_Type is record
+    Value : aliased some_type;
+  end record;          
+
+  for Aligned_Some_Type'Alignment use 8;          
+
+  an_aligned_type : aligned_Some_Type;   
+  my_address : system.address; 
+
+  pragma Volatile (an_aligned_type);
+
+begin
+  my_address := an_aligned_type.value(1)'address; 
+end;