Index: include/clang/Basic/TargetInfo.h =================================================================== --- include/clang/Basic/TargetInfo.h +++ include/clang/Basic/TargetInfo.h @@ -629,6 +629,12 @@ StringRef getNormalizedGCCRegisterName(StringRef Name, bool ReturnCanonical = false) const; + /// \brief Extracts a register from the passed constraint (if it is a + /// single-register constraint) and the asm label expression related to a + /// variable in the input or output list of an inline asm statement. + /// + /// This function is used by Sema in order to diagnose conflicts between + /// the clobber list and the input/output lists. virtual StringRef getConstraintRegister(StringRef Constraint, StringRef Expression) const { return ""; Index: lib/Basic/Targets/AArch64.h =================================================================== --- lib/Basic/Targets/AArch64.h +++ lib/Basic/Targets/AArch64.h @@ -82,6 +82,11 @@ std::string &SuggestedModifier) const override; const char *getClobbers() const override; + StringRef getConstraintRegister(StringRef Constraint, + StringRef Expression) const override { + return Expression; + } + int getEHDataRegisterNumber(unsigned RegNo) const override; }; Index: lib/Basic/Targets/ARM.h =================================================================== --- lib/Basic/Targets/ARM.h +++ lib/Basic/Targets/ARM.h @@ -156,6 +156,11 @@ std::string &SuggestedModifier) const override; const char *getClobbers() const override; + StringRef getConstraintRegister(StringRef Constraint, + StringRef Expression) const override { + return Expression; + } + CallingConvCheckResult checkCallingConvention(CallingConv CC) const override; int getEHDataRegisterNumber(unsigned RegNo) const override; Index: test/Sema/arm-asm.c =================================================================== --- test/Sema/arm-asm.c +++ test/Sema/arm-asm.c @@ -10,3 +10,10 @@ long long foo = 0, bar = 0; asm volatile("INST %0, %1" : "=r"(foo) : "r"(bar)); } + +void test_clobber_conflict(void) { + register int x asm("r1"); + asm volatile("nop" :: "r"(x) : "%r1"); // expected-error {{conflicts with asm clobber list}} + asm volatile("nop" :: "l"(x) : "%r1"); // expected-error {{conflicts with asm clobber list}} + asm volatile("nop" : "=r"(x) :: "%r1"); // expected-error {{conflicts with asm clobber list}} +} Index: test/Sema/arm64-inline-asm.c =================================================================== --- test/Sema/arm64-inline-asm.c +++ test/Sema/arm64-inline-asm.c @@ -7,3 +7,9 @@ asm volatile("USE(%0)" :: "z"(0)); // expected-warning {{value size does not match register size specified by the constraint and modifier}} expected-note {{use constraint modifier "w"}} } + +void test_clobber_conflict(void) { + register long x asm("x1"); + asm volatile("nop" :: "r"(x) : "%x1"); // expected-error {{conflicts with asm clobber list}} + asm volatile("nop" : "=r"(x) :: "%x1"); // expected-error {{conflicts with asm clobber list}} +}