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