summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2014-12-29 04:09:59 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2014-12-29 04:09:59 +0000
commit90dbab3d83bbfed9108e6f072d9251f8e28825f2 (patch)
tree7a158021fede4f39334459ff4bd33feed2c0a8e1
parentc1ae02375d3c7cb04ad4e603d7f4afadff4abfbc (diff)
Sema: Forbid inconsistent constraint alternatives
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
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--lib/Sema/SemaStmtAsm.cpp20
-rw-r--r--test/Sema/asm.c7
3 files changed, 29 insertions, 0 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 1e951c8058..69f86b9692 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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">;
diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp
index e0f3dfe6e0..b31bb250dd 100644
--- a/lib/Sema/SemaStmtAsm.cpp
+++ b/lib/Sema/SemaStmtAsm.cpp
@@ -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
diff --git a/test/Sema/asm.c b/test/Sema/asm.c
index 13ae25f265..e49888ff3e 100644
--- a/test/Sema/asm.c
+++ b/test/Sema/asm.c
@@ -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}}
+}