diff options
Diffstat (limited to 'lib/Sema/SemaStmt.cpp')
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 104 |
1 files changed, 62 insertions, 42 deletions
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index e995e8f..89957e6 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -25,6 +25,7 @@ #include "clang/AST/TypeLoc.h" #include "clang/Lex/Preprocessor.h" #include "clang/Basic/TargetInfo.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" using namespace clang; @@ -92,6 +93,8 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { unsigned DiagID = diag::warn_unused_expr; if (const ExprWithCleanups *Temps = dyn_cast<ExprWithCleanups>(E)) E = Temps->getSubExpr(); + if (const CXXBindTemporaryExpr *TempExpr = dyn_cast<CXXBindTemporaryExpr>(E)) + E = TempExpr->getSubExpr(); E = E->IgnoreParenImpCasts(); if (const CallExpr *CE = dyn_cast<CallExpr>(E)) { @@ -143,7 +146,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { } } - DiagRuntimeBehavior(Loc, PDiag(DiagID) << R1 << R2); + DiagRuntimeBehavior(Loc, 0, PDiag(DiagID) << R1 << R2); } StmtResult @@ -499,8 +502,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, bool HasDependentValue = CondExpr->isTypeDependent() || CondExpr->isValueDependent(); unsigned CondWidth - = HasDependentValue? 0 - : static_cast<unsigned>(Context.getTypeSize(CondTypeBeforePromotion)); + = HasDependentValue ? 0 : Context.getIntWidth(CondTypeBeforePromotion); bool CondIsSigned = CondTypeBeforePromotion->isSignedIntegerType(); // Accumulate all of the case values in a vector so that we can sort them @@ -1392,19 +1394,29 @@ static bool CheckAsmLValue(const Expr *E, Sema &S) { return true; } +/// isOperandMentioned - Return true if the specified operand # is mentioned +/// anywhere in the decomposed asm string. +static bool isOperandMentioned(unsigned OpNo, + llvm::ArrayRef<AsmStmt::AsmStringPiece> AsmStrPieces) { + for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) { + const AsmStmt::AsmStringPiece &Piece = AsmStrPieces[p]; + if (!Piece.isOperand()) continue; + + // If this is a reference to the input and if the input was the smaller + // one, then we have to reject this asm. + if (Piece.getOperandNo() == OpNo) + return true; + } + + return false; +} -StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, - bool IsSimple, - bool IsVolatile, - unsigned NumOutputs, - unsigned NumInputs, - IdentifierInfo **Names, - MultiExprArg constraints, - MultiExprArg exprs, - Expr *asmString, - MultiExprArg clobbers, - SourceLocation RParenLoc, - bool MSAsm) { +StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, + bool IsVolatile, unsigned NumOutputs, + unsigned NumInputs, IdentifierInfo **Names, + MultiExprArg constraints, MultiExprArg exprs, + Expr *asmString, MultiExprArg clobbers, + SourceLocation RParenLoc, bool MSAsm) { unsigned NumClobbers = clobbers.size(); StringLiteral **Constraints = reinterpret_cast<StringLiteral**>(constraints.get()); @@ -1529,8 +1541,9 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, 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)) @@ -1569,30 +1582,22 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, continue; // If the smaller input/output operand is not mentioned in the asm string, - // then we can promote it and the asm string won't notice. Check this - // case now. + // then we can promote the smaller one to a larger input and the asm string + // won't notice. bool SmallerValueMentioned = false; - for (unsigned p = 0, e = Pieces.size(); p != e; ++p) { - AsmStmt::AsmStringPiece &Piece = Pieces[p]; - if (!Piece.isOperand()) continue; - - // If this is a reference to the input and if the input was the smaller - // one, then we have to reject this asm. - if (Piece.getOperandNo() == i+NumOutputs) { - if (InSize < OutSize) { - SmallerValueMentioned = true; - break; - } - } - - // If this is a reference to the input and if the input was the smaller - // one, then we have to reject this asm. - if (Piece.getOperandNo() == TiedTo) { - if (InSize > OutSize) { - SmallerValueMentioned = true; - break; - } - } + + // 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(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". + SmallerValueMentioned |= InSize < OutSize; + } + if (isOperandMentioned(TiedTo, Pieces)) { + // If this is a reference to the output, and if the output is the larger + // value, then it's ok because we'll promote the input to the larger type. + SmallerValueMentioned |= OutSize < InSize; } // If the smaller value wasn't mentioned in the asm string, and if the @@ -1601,7 +1606,20 @@ StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, if (!SmallerValueMentioned && InputDomain != AD_Other && 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() @@ -1747,8 +1765,10 @@ public: StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, MultiStmtArg RawHandlers) { - if (!getLangOptions().Exceptions) - Diag(TryLoc, diag::err_exceptions_disabled) << "try"; + // Don't report an error if 'try' is used in system headers. + if (!getLangOptions().Exceptions && + !getSourceManager().isInSystemHeader(TryLoc)) + Diag(TryLoc, diag::err_exceptions_disabled) << "try"; unsigned NumHandlers = RawHandlers.size(); assert(NumHandlers > 0 && |