Commit a9e64c63 by Eric Botcazou Committed by Eric Botcazou

re PR middle-end/26306 (ICE on volatile array with non-constant bounds)

	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.

From-SVN: r118900
parent c8cf9f0f
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> 2006-11-16 Joseph Myers <joseph@codesourcery.com>
* config/rs6000/spe.md (frob_di_df_2): Handle non-offsettable * config/rs6000/spe.md (frob_di_df_2): Handle non-offsettable
......
...@@ -10441,11 +10441,10 @@ Predefined Macros,cpp,The GNU C Preprocessor}). ...@@ -10441,11 +10441,10 @@ Predefined Macros,cpp,The GNU C Preprocessor}).
Both the C and C++ standard have the concept of volatile objects. These Both the C and C++ standard have the concept of volatile objects. These
are normally accessed by pointers and used for accessing hardware. The are normally accessed by pointers and used for accessing hardware. The
standards encourage compilers to refrain from optimizations standards encourage compilers to refrain from optimizations concerning
concerning accesses to volatile objects that it might perform on accesses to volatile objects. The C standard leaves it implementation
non-volatile objects. The C standard leaves it implementation defined defined as to what constitutes a volatile access. The C++ standard omits
as to what constitutes a volatile access. The C++ standard omits to to specify this, except to say that C++ should behave in a similar manner
specify this, except to say that C++ should behave in a similar manner
to C with respect to volatiles, where possible. The minimum either to C with respect to volatiles, where possible. The minimum either
standard specifies is that at a sequence point all previous accesses to standard specifies is that at a sequence point all previous accesses to
volatile objects have stabilized and no subsequent accesses have 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 ...@@ -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 allow you to violate the restriction on updating objects multiple times
within a sequence point. within a sequence point.
In most expressions, it is intuitively obvious what is a read and what is @xref{Qualifiers implementation, , Volatile qualifier and the C compiler}.
a write. For instance
@smallexample The behavior differs slightly between C and C++ in the non-obvious cases:
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,
@smallexample @smallexample
volatile int *src = @var{somevalue}; volatile int *src = @var{somevalue};
*src; *src;
@end smallexample @end smallexample
With C, such expressions are rvalues, and as rvalues cause a read of With C, such expressions are rvalues, and GCC interprets this either as a
the object, GCC interprets this as a read of the volatile being pointed read of the volatile object being pointed to or only as request to evaluate
to. The C++ standard specifies that such expressions do not undergo the side-effects. The C++ standard specifies that such expressions do not
lvalue to rvalue conversion, and that the type of the dereferenced undergo lvalue to rvalue conversion, and that the type of the dereferenced
object may be incomplete. The C++ standard does not specify explicitly 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, causing an access. However, there is reason to believe that it is,
because otherwise certain simple expressions become undefined. However, because otherwise certain simple expressions become undefined. However,
because it would surprise most programmers, G++ treats dereferencing a because it would surprise most programmers, G++ treats dereferencing a
pointer to volatile object of complete type in a void context as a read pointer to volatile object of complete type when the value is unused as
of the object. When the object has incomplete type, G++ issues a GCC would do for an equivalent type in C. When the object has incomplete
warning. 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.
@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)}.
When using a reference to volatile, G++ does not treat equivalent When using a reference to volatile, G++ does not treat equivalent
expressions as accesses to volatiles, but instead issues a warning that expressions as accesses to volatiles, but instead issues a warning that
......
...@@ -503,7 +503,42 @@ determined by the ABI@. ...@@ -503,7 +503,42 @@ determined by the ABI@.
@cite{What constitutes an access to an object that has volatile-qualified @cite{What constitutes an access to an object that has volatile-qualified
type (C90 6.5.3, C99 6.7.3).} 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 @end itemize
......
...@@ -5854,7 +5854,8 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, ...@@ -5854,7 +5854,8 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
gimple_test_f, fallback); gimple_test_f, fallback);
break; 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, gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
gimple_test_f, fallback); gimple_test_f, fallback);
gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p, post_p, 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, ...@@ -5863,16 +5864,17 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
default: default:
/* Anything else with side-effects must be converted to /* 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 (); gcc_unreachable ();
} }
*expr_p = NULL; *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 /* Historically, the compiler has treated a bare reference
reference to a volatile lvalue as forcing a load. */ to a non-BLKmode volatile lvalue as forcing a load. */
tree type = TYPE_MAIN_VARIANT (TREE_TYPE (*expr_p)); tree type = TYPE_MAIN_VARIANT (TREE_TYPE (*expr_p));
/* Normally, we do not want to create a temporary for a /* Normally, we do not want to create a temporary for a
TREE_ADDRESSABLE type because such a type should not be 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, ...@@ -5887,7 +5889,10 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
} }
else else
/* We can't do anything useful with a volatile reference to /* 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; *expr_p = NULL;
} }
......
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> 2006-11-16 Francois-Xavier Coudert <coudert@clipper.ens.fr>
PR fortran/29391 PR fortran/29391
-- { 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;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment