]> granicus.if.org Git - clang/commitdiff
Sema: Forbid inconsistent constraint alternatives
authorDavid Majnemer <david.majnemer@gmail.com>
Mon, 29 Dec 2014 04:09:59 +0000 (04:09 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Mon, 29 Dec 2014 04:09:59 +0000 (04:09 +0000)
Verify that asm constraints have the same number of alternatives

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@224911 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 1e951c8058eabedf168f0f869c6dcf2da9c8e444..69f86b9692d48ab2272a97faa4e5d8d9ece8fb15 100644 (file)
@@ -6166,6 +6166,8 @@ let CategoryName = "Inline Assembly Issue" in {
   def err_asm_tying_incompatible_types : Error<
     "unsupported inline asm: input with type "
     "%diff{$ matching output with type $|}0,1">;
+  def err_asm_unexpected_constraint_alternatives : Error<
+    "asm constraint has an unexpected number of alternatives: %0 vs %1">;
   def err_asm_incomplete_type : Error<"asm operand has incomplete type %0">;
   def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">;
   def err_asm_bad_register_type : Error<"bad type for named register variable">;
index e0f3dfe6e00de9128085d15c47127b644de3e4fe..b31bb250dd8dce669cc9d6fd85de9e0783db6daf 100644 (file)
@@ -317,8 +317,28 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
   }
 
   // Validate tied input operands for type mismatches.
+  unsigned NumAlternatives = ~0U;
+  for (unsigned i = 0, e = OutputConstraintInfos.size(); i != e; ++i) {
+    TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i];
+    StringRef ConstraintStr = Info.getConstraintStr();
+    unsigned AltCount = ConstraintStr.count(',') + 1;
+    if (NumAlternatives == ~0U)
+      NumAlternatives = AltCount;
+    else if (NumAlternatives != AltCount)
+      return StmtError(Diag(NS->getOutputExpr(i)->getLocStart(),
+                            diag::err_asm_unexpected_constraint_alternatives)
+                       << NumAlternatives << AltCount);
+  }
   for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
     TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
+    StringRef ConstraintStr = Info.getConstraintStr();
+    unsigned AltCount = ConstraintStr.count(',') + 1;
+    if (NumAlternatives == ~0U)
+      NumAlternatives = AltCount;
+    else if (NumAlternatives != AltCount)
+      return StmtError(Diag(NS->getInputExpr(i)->getLocStart(),
+                            diag::err_asm_unexpected_constraint_alternatives)
+                       << NumAlternatives << AltCount);
 
     // 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
index 13ae25f265c3247ce49adbadb66eeb44366b7702..e49888ff3eb6997ed880e3dba2ce1d6b7c8b6933 100644 (file)
@@ -164,3 +164,10 @@ double f_output_constraint(void) {
   __asm("foo1": "=f" (result)); // expected-error {{invalid output constraint '=f' in asm}}
   return result;
 }
+
+void fn1() {
+  int l;
+  __asm__(""
+          : [l] "=r"(l)
+          : "[l],m"(l)); // expected-error {{asm constraint has an unexpected number of alternatives: 1 vs 2}}
+}