mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-22 03:46:53 -05:00
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: r118901
This commit is contained in:
committed by
Eric Botcazou
parent
aea945928a
commit
a18bfd8307
@@ -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 Andrew Pinski <andrew_pinski@playstation.sony.com>
|
||||
|
||||
PR tree-opt/29788
|
||||
|
||||
@@ -10361,11 +10361,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
|
||||
@@ -10375,55 +10374,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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -5858,7 +5858,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,
|
||||
@@ -5867,16 +5868,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
|
||||
@@ -5891,7 +5893,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
2006-11-16 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* gnat.dg/volatile_aggregate.adb: New test.
|
||||
|
||||
2006-11-16 Andrew Pinski <andrew_pinski@playstation.sony.com>
|
||||
|
||||
PR tree-opt/29788
|
||||
|
||||
33
gcc/testsuite/gnat.dg/volatile_aggregate.adb
Normal file
33
gcc/testsuite/gnat.dg/volatile_aggregate.adb
Normal file
@@ -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;
|
||||
Reference in New Issue
Block a user