diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 18 | ||||
-rw-r--r-- | test/Sema/asm.c | 7 |
3 files changed, 27 insertions, 0 deletions
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; +} |