public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Motivation for diagnosing conversions that discard 'restrict' qualifier (as warning/error)
@ 2020-11-27 17:45 Bruno De Fraine
  0 siblings, 0 replies; only message in thread
From: Bruno De Fraine @ 2020-11-27 17:45 UTC (permalink / raw)
  To: gcc

Hello,

Gcc will diagnose C or C++ code that converts a pointer to a restrict qualified
type to a pointer to a type without restrict:

  int * __restrict p;
  int **pp = &p; // [C] warning: initialization discards 'restrict' qualifier
                 // [C++] error: invalid conversion from 'int* __restrict__*' to 'int**'

I wanted to raise the question why a diagnostic when discarding restrict is
necessary, both by the language specification, and to protect the programmer
from inadvertent mistakes.
A similar diagnostic when discarding const or volatile qualifiers has a clear
purpose: such a conversion must be diagnosed, because the conversion can allow
following valid code to inadvertently perform an invalid access on a const or
volatile qualified object. For example:

  const int c = 123;
  int *pc = &c; // invalid: loss of 'const'
  *pc = 456;    // valid

A similar example, also using the const qualifier, is given in the C99 standard
(section 6.5.16.1) and C++ standard (section [conv.qual]). Note that it is
undefined behavior to access a const or volatile object through an lvalue
without respectively the const or volatile qualifier.

The restrict qualifier works entirely different than const and volatile
qualifiers, however. Its implications are specified in C99, section 6.7.3.1,
and are defined in terms of aliasing between lvalues that have their address
"based on" a pointer object declared with restrict qualifier (versus those that
are not "based on"), within the scope of that declaration. For the definition
of "based on", it is irrelevant whether the restrict qualifier is retained in
the pointer expression or not, for example:

  int * __restrict p;
  int *q = p + j;
  int **qp = &q;
  *p, p[i], *q, **qp  // all lvalues based on 'p'

Consequently, there seems to be no value in diagnosing a loss of restrict
qualifier, or preventing that a restrict qualified pointer is inadvertently
accessed through an lvalue without this qualifier?

But is the compiler required by the language specification to diagnose this?
For C, it surely seems required: in the C99 specification, restrict is a type
qualifier, and section 6.5.16.1 lists as assignment constraint for pointers:
"both operands are pointers to qualified or unqualified versions of compatible
types, and the type pointed to by the left has all the qualifiers of the type
pointed to by the right". In the original example from this e-mail, the "has
all the qualifiers" part of the constraint is not satisfied, so compilers must
diagnose the violation.

The assignment constraint from the C specification is arguably too strict
though, because the following is also a violation:

  int* p;
  volatile int* const* pp = &p;
While this "has all the qualifiers", the pointers do not point to compatible
types ('int*' versus 'volatile int*'). The danger is that a pointer to a
volatile could be stored in 'p' by writing it through '*pp', but the const
qualifier prevents any stores through '*pp', so this is in fact safe. The C++
specification did address this overly strict constraint, and does allow the
above assignment when the const qualifier is present, as detailed for
qualification conversions in section [conv.qual].

Presumably, because the C constraint is known to be overly strict, gcc is only
diagnosing violations of the strict constraint in C with a warning, while it is
diagnosing violations of the relaxed constraint in C++ with an error?

While an error seems appropriate for the loss of a const or volatile qualifier
in C++, gcc now also gives an error for the loss of a restrict qualifier in
C++, where I've tried to make the point in this e-mail that the loss of
restrict seems harmless. Unfortunately, the C++ language specification does
not consider the restrict qualifier (although __restrict is a common C++
language extension), so there is no direct answer whether this should be
considered a violation that should be diagnosed.

Thanks for any feedback that motivates the gcc implementation on this point.
I'll note that it sometimes raises questions, for example [1].

Best regards,
Bruno De Fraine

[1] https://stackoverflow.com/questions/48926403/


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-11-27 17:45 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-27 17:45 Motivation for diagnosing conversions that discard 'restrict' qualifier (as warning/error) Bruno De Fraine

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).