aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2007-11-23 19:43:50 +0000
committerAnders Carlsson <andersca@mac.com>2007-11-23 19:43:50 +0000
commit04728b7ea928b029f165fc67d32ced40e6868b31 (patch)
tree9c9cda2c89a56e0afffa9124f5ece1f29c7d570e
parent0c3eb29e79e439a0d73e81e57cc130ddb45d50ea (diff)
Check asm input and output expressions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44289 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--Sema/SemaStmt.cpp34
-rw-r--r--include/clang/Basic/DiagnosticKinds.def4
-rw-r--r--test/Sema/asm.c14
3 files changed, 51 insertions, 1 deletions
diff --git a/Sema/SemaStmt.cpp b/Sema/SemaStmt.cpp
index f7aa6a9e27..00685c2824 100644
--- a/Sema/SemaStmt.cpp
+++ b/Sema/SemaStmt.cpp
@@ -655,8 +655,40 @@ Sema::StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
ExprTy **Clobbers,
SourceLocation RParenLoc) {
Expr *E = (Expr *)AsmString;
+
+ // Check that the output exprs are valid lvalues.
+ for (unsigned i = 0; i < NumOutputs; i++) {
+ Expr *OutputExpr = (Expr *)Exprs[i];
+ Expr::isLvalueResult Result = OutputExpr->isLvalue();
- // FIXME: Make sure that the expressions are valid.
+ if (Result != Expr::LV_Valid) {
+ ParenExpr *PE = cast<ParenExpr>(OutputExpr);
+
+ Diag(PE->getSubExpr()->getLocStart(),
+ diag::err_invalid_lvalue_in_asm_output,
+ PE->getSubExpr()->getSourceRange());
+
+ // FIXME: We currently leak memory here.
+ return true;
+ }
+ }
+
+ // Check that the input exprs aren't of type void.
+ for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
+ Expr *InputExpr = (Expr *)Exprs[i];
+
+ if (InputExpr->getType()->isVoidType()) {
+ ParenExpr *PE = cast<ParenExpr>(InputExpr);
+
+ Diag(PE->getSubExpr()->getLocStart(),
+ diag::err_invalid_type_in_asm_input,
+ PE->getType().getAsString(),
+ PE->getSubExpr()->getSourceRange());
+
+ // FIXME: We currently leak memory here.
+ return true;
+ }
+ }
return new AsmStmt(AsmLoc,
NumOutputs,
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def
index a6e90b3025..31fdd27b67 100644
--- a/include/clang/Basic/DiagnosticKinds.def
+++ b/include/clang/Basic/DiagnosticKinds.def
@@ -789,6 +789,10 @@ DIAG(warn_unused_expr, WARNING,
"expression result unused")
DIAG(err_pascal_string_too_long, ERROR,
"Pascal string is too long")
+DIAG(err_invalid_lvalue_in_asm_output, ERROR,
+ "invalid lvalue in asm output")
+DIAG(err_invalid_type_in_asm_input, ERROR,
+ "invalid type '%0' in asm input")
// CHECK: printf format string errors
DIAG(warn_printf_not_string_constant, WARNING,
diff --git a/test/Sema/asm.c b/test/Sema/asm.c
new file mode 100644
index 0000000000..e01a0f2dc0
--- /dev/null
+++ b/test/Sema/asm.c
@@ -0,0 +1,14 @@
+// RUN: clang %s -verify -fsyntax-only
+
+void
+f()
+{
+ int i;
+
+ asm ("foo\n" : : "a" (i + 2));
+ asm ("foo\n" : : "a" (f())); // expected-error {{invalid type 'void' in asm input}}
+
+ asm ("foo\n" : "=a" (f())); // expected-error {{invalid lvalue in asm output}}
+ asm ("foo\n" : "=a" (i + 2)); // expected-error {{invalid lvalue in asm output}}
+
+}