diff --git a/clang/Sema/SemaStmt.cpp b/clang/Sema/SemaStmt.cpp index f7aa6a9e272f..00685c282458 100644 --- a/clang/Sema/SemaStmt.cpp +++ b/clang/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(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(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/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index a6e90b30255b..31fdd27b670f 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/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/clang/test/Sema/asm.c b/clang/test/Sema/asm.c new file mode 100644 index 000000000000..e01a0f2dc0de --- /dev/null +++ b/clang/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}} + +}