On Tue, Oct 12, 2021 at 09:21:21AM -0700, Fāng-ruì Sòng wrote:
> > > An output constraint takes a lvalue. While GCC happily strips the
> > > incorrect lvalue to rvalue conversion, Clang rejects the code by default:
> > >
> > >     error: invalid use of a cast in a inline asm context requiring an 
> > > lvalue: remove the cast or build with -fheinous-gnu-extensions
> > >
> > > The file appears to share the same origin with gmplib longlong.h but
> > > they differ much now (gmplib version is much longer).
> > >
> > > I don't have write access to the git repo.
> > > ---
> > >  include/longlong.h | 186 ++++++++++++++++++++++-----------------------
> > >  1 file changed, 93 insertions(+), 93 deletions(-)
> > >
> > > diff --git a/include/longlong.h b/include/longlong.h
> > > index c3e92e54ecc..0a21a441d2d 100644
> > > --- a/include/longlong.h
> > > +++ b/include/longlong.h
> > > @@ -194,8 +194,8 @@ extern UDItype __udiv_qrnnd (UDItype *, UDItype, 
> > > UDItype, UDItype);
> > >  #if defined (__arc__) && W_TYPE_SIZE == 32
> > >  #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
> > >    __asm__ ("add.f    %1, %4, %5\n\tadc       %0, %2, %3"             \
> > > -        : "=r" ((USItype) (sh)),                                     \
> > > -          "=&r" ((USItype) (sl))                                     \
> > > +        : "=r" (sh),                                                 \
> > > +          "=&r" (sl)                                                 \
> > >          : "%r" ((USItype) (ah)),                                     \
> > >            "rICal" ((USItype) (bh)),                                  \
> > >            "%r" ((USItype) (al)),                                     \
> >
> > This seems to alter the meanining of existing programs if sh and sl do
> > not have the expected type.
> >
> > I think you need to add a compound expression and temporaries of type
> > USItype if you want to avoid the cast.
> 
> Add folks who may comment on the output constraint behavior when a
> lvalue to rvalue conversion like (`(USItype)`) is added.

Allowing the casts in there is intentional, the comment about this
e.g. in GCC's C FE says:
Really, this should not be here.  Users should be using a
proper lvalue, dammit.  But there's a long history of using casts
in the output operands.  In cases like longlong.h, this becomes a
primitive form of typechecking -- if the cast can be removed, then
the output operand had a type of the proper width; otherwise we'll
get an error.

If you try e.g.:

void
foo (void)
{
  int i;
  long l;
  __asm ("" : "=r" ((unsigned) i));
  __asm ("" : "=r" ((long) l));
  __asm ("" : "=r" ((long long) l));
  __asm ("" : "=r" ((int) l));
  __asm ("" : "=r" ((long) i));
}

then on e.g. x86-64 the first 3 asms are accepted by GCC, the last two
rejected, because the modes are different there.

So the above change throws away important typechecking.  As it is
used in a macro, something different should verify that if the casts are
removed.

        Jakub

Reply via email to