]> granicus.if.org Git - clang/commitdiff
implement PR4077: [Linux kernel] inscrutable error on inline asm input/output constra...
authorChris Lattner <sabre@nondot.org>
Sun, 26 Apr 2009 18:22:24 +0000 (18:22 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 26 Apr 2009 18:22:24 +0000 (18:22 +0000)
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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaStmt.cpp
test/Sema/asm.c

index 61d8e3b254a79dacea965057abc57e5085253740..bc46bdf994a4b7cff60b0de22cd8aab9baece8d7 100644 (file)
@@ -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: "
index ad33ad3b209490e2562b886d374a8b099157f8c6..93e30ec65f62898232e7d4b0113bc3c7b431bf26 100644 (file)
@@ -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.
index 4072a5cc76203b5ace37564eee73f7771d78874e..602b77388a69210b81024714d4b6f720498cb58e 100644 (file)
@@ -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;
+}