aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--lib/Sema/SemaStmt.cpp18
-rw-r--r--test/Sema/asm.c7
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;
+}