From: Anders Carlsson Date: Fri, 23 Nov 2007 19:43:50 +0000 (+0000) Subject: Check asm input and output expressions. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=04728b7ea928b029f165fc67d32ced40e6868b31;p=clang Check asm input and output expressions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44289 91177308-0d34-0410-b5e6-96231b3b80d8 --- 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(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/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}} + +}