diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Stmt.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 18 |
2 files changed, 20 insertions, 2 deletions
diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 7e73f02e67e..8a80275aa16 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -218,6 +218,10 @@ unsigned AsmStmt::getNumPlusOperands() const { Expr *AsmStmt::getInputExpr(unsigned i) { return cast<Expr>(Exprs[i + NumOutputs]); } +void AsmStmt::setInputExpr(unsigned i, Expr *E) { + Exprs[i + NumOutputs] = E; +} + /// getInputConstraint - Return the specified input constraint. Unlike output /// constraints, these can be empty. diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 6801dd4c2eb..3815deae58f 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -1542,8 +1542,9 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, if (!Info.hasTiedOperand()) continue; unsigned TiedTo = Info.getTiedOperand(); + unsigned InputOpNo = i+NumOutputs; Expr *OutputExpr = Exprs[TiedTo]; - Expr *InputExpr = Exprs[i+NumOutputs]; + Expr *InputExpr = Exprs[InputOpNo]; QualType InTy = InputExpr->getType(); QualType OutTy = OutputExpr->getType(); if (Context.hasSameType(InTy, OutTy)) @@ -1588,7 +1589,7 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, // If this is a reference to the input and if the input was the smaller // one, then we have to reject this asm. - if (isOperandMentioned(i+NumOutputs, Pieces)) { + if (isOperandMentioned(InputOpNo, Pieces)) { // This is a use in the asm string of the smaller operand. Since we // codegen this by promoting to a wider value, the asm will get printed // "wrong". @@ -1607,6 +1608,19 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, OutputConstraintInfos[TiedTo].allowsRegister()) continue; + // Either both of the operands were mentioned or the smaller one was + // mentioned. One more special case that we'll allow: if the tied input is + // integer, unmentioned, and is a constant, then we'll allow truncating it + // down to the size of the destination. + if (InputDomain == AD_Int && OutputDomain == AD_Int && + !isOperandMentioned(InputOpNo, Pieces) && + InputExpr->isEvaluatable(Context)) { + ImpCastExprToType(InputExpr, OutTy, CK_IntegralCast); + Exprs[InputOpNo] = InputExpr; + NS->setInputExpr(i, InputExpr); + continue; + } + Diag(InputExpr->getLocStart(), diag::err_asm_tying_incompatible_types) << InTy << OutTy << OutputExpr->getSourceRange() |