diff options
author | David Majnemer <david.majnemer@gmail.com> | 2014-12-29 04:09:59 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2014-12-29 04:09:59 +0000 |
commit | c63fa612e46ec56776474580c72c7fb761e8777d (patch) | |
tree | b7989c465e3b6c15531a0ee7677d276f914479f7 | |
parent | c52f300698e86195cff4b8e9eadbb184c42d29eb (diff) | |
download | bcm5719-llvm-c63fa612e46ec56776474580c72c7fb761e8777d.tar.gz bcm5719-llvm-c63fa612e46ec56776474580c72c7fb761e8777d.zip |
Sema: Forbid inconsistent constraint alternatives
Verify that asm constraints have the same number of alternatives
llvm-svn: 224911
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmtAsm.cpp | 20 | ||||
-rw-r--r-- | clang/test/Sema/asm.c | 7 |
3 files changed, 29 insertions, 0 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 1e951c8058e..69f86b9692d 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/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/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp index e0f3dfe6e00..b31bb250dd8 100644 --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/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/clang/test/Sema/asm.c b/clang/test/Sema/asm.c index 13ae25f265c..e49888ff3eb 100644 --- a/clang/test/Sema/asm.c +++ b/clang/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}} +} |