From a0fb00f9837bd0d2e5948f16f6a6b82a7a628f51 Mon Sep 17 00:00:00 2001
From: dim <dim@FreeBSD.org>
Date: Sat, 26 Feb 2011 22:09:03 +0000
Subject: Vendor import of clang trunk r126547:
 http://llvm.org/svn/llvm-project/cfe/trunk@126547

---
 lib/Sema/SemaStmt.cpp | 104 ++++++++++++++++++++++++++++++--------------------
 1 file changed, 62 insertions(+), 42 deletions(-)

(limited to 'lib/Sema/SemaStmt.cpp')

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 &&
-- 
cgit v1.1