diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index 6cd5d618a4aca..57a81e03bc484 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -717,8 +717,15 @@ bool TargetInfo::validateOutputConstraint(ConstraintInfo &Info) const { if (*Name != '=' && *Name != '+') return false; - if (*Name == '+') + if (*Name == '+') { Info.setIsReadWrite(); + // To align with GCC asm: "=f" is not allowed, the + // operand constraints must select a class with a single reg. + auto Flag = Name + 1; + if (Flag && *Flag == 'f') { + return false; + } + } Name++; while (*Name) { diff --git a/clang/test/Sema/asm.c b/clang/test/Sema/asm.c index 630a5e85dd913..a490e9fb5e932 100644 --- a/clang/test/Sema/asm.c +++ b/clang/test/Sema/asm.c @@ -359,3 +359,17 @@ void test19(long long x) // FIXME: This case should be supported by codegen, but it fails now. asm ("" : "=rm" (x): "0" (e)); // expected-error {{unsupported inline asm: input with type 'st_size128' (aka 'struct _st_size128') matching output with type 'long long'}} } + +void test20() +{ + double f00 = 0.0; + double f01 = 0.0; + double f10 = 0.0; + double f11 = 0.0; + int mem; + asm volatile ("" : "+f" (f00), "+f" (f01), "+f" (f10), "+f" (f11), "+m" (mem) :: "memory"); // expected-error {{invalid output constraint '+f' in asm}} + asm volatile ("" : "+r" (f00), "+f" (f01), "+f" (f10), "+f" (f11), "+m" (mem) :: "memory"); // expected-error {{invalid output constraint '+f' in asm}} + asm volatile ("" : "+r" (f00), "+r" (f01), "+f" (f10), "+f" (f11), "+m" (mem) :: "memory"); // expected-error {{invalid output constraint '+f' in asm}} + asm volatile ("" : "+r" (f00), "+r" (f01), "+r" (f10), "+f" (f11), "+m" (mem) :: "memory"); // expected-error {{invalid output constraint '+f' in asm}} + asm volatile ("" : "+r" (f00), "+r" (f01), "+r" (f10), "+r" (f11), "+m" (mem) :: "memory"); // no-error +} \ No newline at end of file