From: Chris Lattner Date: Sun, 26 Apr 2009 18:22:24 +0000 (+0000) Subject: implement PR4077: [Linux kernel] inscrutable error on inline asm input/output constra... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=49ac88166d36f8c436780694f2ce955acde87c6a;p=clang implement PR4077: [Linux kernel] inscrutable error on inline asm input/output constraint mismatch Before we emitted: $ clang t.c -S -m64 llvm: error: Unsupported asm: input constraint with a matching output constraint of incompatible type! Now we produce: $ clang t.c -S -m64 t.c:5:40: error: unsupported inline asm: input with type 'unsigned long' matching output with type 'int' asm volatile("foo " : "=a" (a) :"0" (b)); ~~~ ~^~ git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70142 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 61d8e3b254..bc46bdf994 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1326,6 +1326,8 @@ def err_asm_invalid_input_constraint : Error< "invalid input constraint '%0' in asm">; def err_asm_invalid_type_in_input : Error< "invalid type %0 in asm input for constraint '%1'">; +def err_asm_tying_incompatible_types : Error< + "unsupported inline asm: input with type %0 matching output with type %1">; def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">; def err_invalid_asm_cast_lvalue : Error< "invalid use of a cast in a inline asm context requiring an l-value: " diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index ad33ad3b20..93e30ec65f 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -978,6 +978,24 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, } DefaultFunctionArrayConversion(Exprs[i]); + + // If this is a tied constraint, verify that the output and input have + // either exactly the same type, or that they are int/ptr operands with the + // same size (int/long, int*/long, are ok etc). + if (Info.hasTiedOperand()) { + unsigned TiedTo = Info.getTiedOperand(); + QualType T1 = Exprs[TiedTo]->getType(), T2 = Exprs[i]->getType(); + if (!Context.hasSameType(T1, T2)) { + // Int/ptr operands are ok if they are the same size. + if (!(T1->isIntegerType() || T1->isPointerType()) || + !(T2->isIntegerType() || T2->isPointerType()) || + Context.getTypeSize(T1) != Context.getTypeSize(T2)) + return StmtError(Diag(InputExpr->getSubExpr()->getLocStart(), + diag::err_asm_tying_incompatible_types) + << T2 << T1 << Exprs[TiedTo]->getSourceRange() + << Exprs[i]->getSourceRange()); + } + } } // Check that the clobbers are valid. diff --git a/test/Sema/asm.c b/test/Sema/asm.c index 4072a5cc76..602b77388a 100644 --- a/test/Sema/asm.c +++ b/test/Sema/asm.c @@ -69,3 +69,10 @@ void asm_string_tests(int i) { asm("%9" :: "i"(4)); // expected-error {{invalid operand number in inline asm string}} asm("%1" : "+r"(i)); // ok, referring to input. } + +// PR4077 +int test7(unsigned long long b) { + int a; + asm volatile("foo " : "=a" (a) :"0" (b)); // expected-error {{input with type 'unsigned long long' matching output with type 'int'}} + return a; +}