[cfe-commits] r119138 - in /cfe/trunk: include/clang/AST/Expr.h include/clang/AST/OperationKinds.h include/clang/AST/Type.h include/clang/Sema/Sema.h lib/AST/Expr.cpp lib/AST/Type.cpp lib/Checker/GRExprEngine.cpp lib/CodeGen/CGExpr.cpp lib/CodeGen/CGExprScalar.cpp lib/Sema/SemaCXXCast.cpp lib/Sema/SemaChecking.cpp lib/Sema/SemaDeclAttr.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaInit.cpp lib/Sema/SemaObjCProperty.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplate.cpp

John McCall rjmccall at apple.com
Mon Nov 15 01:13:47 PST 2010


Author: rjmccall
Date: Mon Nov 15 03:13:47 2010
New Revision: 119138

URL: http://llvm.org/viewvc/llvm-project?rev=119138&view=rev
Log:
Assorted work leading towards the elimination of CK_Unknown.


Modified:
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/include/clang/AST/OperationKinds.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/Checker/GRExprEngine.cpp
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/Sema/SemaCXXCast.cpp
    cfe/trunk/lib/Sema/SemaChecking.cpp
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/lib/Sema/SemaObjCProperty.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Mon Nov 15 03:13:47 2010
@@ -1961,7 +1961,7 @@
 private:
   Stmt *Op;
 
-  void CheckBasePath() const {
+  void CheckCastConsistency() const {
 #ifndef NDEBUG
     switch (getCastKind()) {
     case CK_DerivedToBase:
@@ -1973,17 +1973,14 @@
       break;
 
     // These should not have an inheritance path.
-    case CK_Unknown:
     case CK_BitCast:
     case CK_LValueBitCast:
-    case CK_NoOp:
     case CK_Dynamic:
     case CK_ToUnion:
     case CK_ArrayToPointerDecay:
     case CK_FunctionToPointerDecay:
     case CK_NullToMemberPointer:
     case CK_NullToPointer:
-    case CK_UserDefinedConversion:
     case CK_ConstructorConversion:
     case CK_IntegralToPointer:
     case CK_PointerToIntegral:
@@ -1993,20 +1990,30 @@
     case CK_IntegralToFloating:
     case CK_FloatingToIntegral:
     case CK_FloatingCast:
-    case CK_MemberPointerToBoolean:
     case CK_AnyPointerToObjCPointerCast:
     case CK_AnyPointerToBlockPointerCast:
     case CK_ObjCObjectLValueCast:
     case CK_FloatingRealToComplex:
     case CK_FloatingComplexToReal:
-    case CK_FloatingComplexToBoolean:
     case CK_FloatingComplexCast:
     case CK_FloatingComplexToIntegralComplex:
     case CK_IntegralRealToComplex:
     case CK_IntegralComplexToReal:
-    case CK_IntegralComplexToBoolean:
     case CK_IntegralComplexCast:
     case CK_IntegralComplexToFloatingComplex:
+      assert(!getType()->isBooleanType() && "unheralded conversion to bool");
+      // fallthrough to check for null base path
+
+    case CK_Dependent:
+    case CK_Unknown:
+    case CK_NoOp:
+    case CK_UserDefinedConversion:
+    case CK_PointerToBoolean:
+    case CK_IntegralToBoolean:
+    case CK_FloatingToBoolean:
+    case CK_MemberPointerToBoolean:
+    case CK_FloatingComplexToBoolean:
+    case CK_IntegralComplexToBoolean:
       assert(path_empty() && "Cast kind should not have a base path!");
       break;
     }
@@ -2029,9 +2036,10 @@
          // dependent or if the subexpression is value-dependent.
          ty->isDependentType() || (op && op->isValueDependent())),
     Op(op) {
+    assert(kind != CK_Invalid && "creating cast with invalid cast kind");
     CastExprBits.Kind = kind;
     CastExprBits.BasePathSize = BasePathSize;
-    CheckBasePath();
+    CheckCastConsistency();
   }
 
   /// \brief Construct an empty cast.

Modified: cfe/trunk/include/clang/AST/OperationKinds.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/OperationKinds.h?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/OperationKinds.h (original)
+++ cfe/trunk/include/clang/AST/OperationKinds.h Mon Nov 15 03:13:47 2010
@@ -25,6 +25,10 @@
   /// going on.
   CK_Unknown,
 
+  /// CK_Dependent - This explicit cast cannot yet be analyzed because
+  /// the type or expression is dependent.
+  CK_Dependent,
+
   /// CK_BitCast - Used for reinterpret_cast.
   CK_BitCast,
 
@@ -83,6 +87,9 @@
     
   /// CK_PointerToIntegral - Pointer to integral
   CK_PointerToIntegral,
+
+  /// CK_PointerToBoolean - Pointer to boolean (i.e. is not null)
+  CK_PointerToBoolean,
     
   /// CK_ToVoid - Cast to void.
   CK_ToVoid,
@@ -92,14 +99,21 @@
   /// src expression into the destination expression.
   CK_VectorSplat,
     
-  /// CK_IntegralCast - Casting between integral types of different size.
+  /// CK_IntegralCast - A truncating or extending cast between integral
+  /// types of different size.
   CK_IntegralCast,
 
+  /// CK_IntegralToBoolean - Integral to boolean.
+  CK_IntegralToBoolean,
+
   /// CK_IntegralToFloating - Integral to floating point.
   CK_IntegralToFloating,
     
   /// CK_FloatingToIntegral - Floating point to integral.
   CK_FloatingToIntegral,
+
+  /// CK_FloatingToBoolean - Floating point to boolean.
+  CK_FloatingToBoolean,
     
   /// CK_FloatingCast - Casting between floating types of different size.
   CK_FloatingCast,
@@ -151,6 +165,7 @@
   CK_IntegralComplexToFloatingComplex
 };
 
+#define CK_Invalid ((CastKind) -1)
 
 enum BinaryOperatorKind {
   // Operators listed in order of precedence.

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Mon Nov 15 03:13:47 2010
@@ -1123,6 +1123,18 @@
   bool isTemplateTypeParmType() const;          // C++ template type parameter
   bool isNullPtrType() const;                   // C++0x nullptr_t
 
+  enum ScalarTypeKind {
+    STK_Pointer,
+    STK_MemberPointer,
+    STK_Bool,
+    STK_Integral,
+    STK_Floating,
+    STK_IntegralComplex,
+    STK_FloatingComplex
+  };
+  /// getScalarTypeKind - Given that this is a scalar type, classify it.
+  ScalarTypeKind getScalarTypeKind() const;
+
   /// isDependentType - Whether this type is a dependent type, meaning
   /// that its definition somehow depends on a template parameter
   /// (C++ [temp.dep.type]).

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Nov 15 03:13:47 2010
@@ -4109,7 +4109,8 @@
   /// CheckAssignmentConstraints - Perform type checking for assignment,
   /// argument passing, variable initialization, and function return values.
   /// This routine is only used by the following two methods. C99 6.5.16.
-  AssignConvertType CheckAssignmentConstraints(QualType lhs, QualType rhs);
+  AssignConvertType CheckAssignmentConstraints(QualType lhs, QualType rhs,
+                                               CastKind &Kind);
 
   // CheckSingleAssignmentConstraints - Currently used by
   // CheckAssignmentOperands, and ActOnReturnStmt. Prior to type checking,

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Mon Nov 15 03:13:47 2010
@@ -742,6 +742,8 @@
   switch (getCastKind()) {
   case CK_Unknown:
     return "Unknown";
+  case CK_Dependent:
+    return "Dependent";
   case CK_BitCast:
     return "BitCast";
   case CK_LValueBitCast:
@@ -778,18 +780,24 @@
     return "IntegralToPointer";
   case CK_PointerToIntegral:
     return "PointerToIntegral";
+  case CK_PointerToBoolean:
+    return "PointerToBoolean";
   case CK_ToVoid:
     return "ToVoid";
   case CK_VectorSplat:
     return "VectorSplat";
   case CK_IntegralCast:
     return "IntegralCast";
+  case CK_IntegralToBoolean:
+    return "IntegralToBoolean";
   case CK_IntegralToFloating:
     return "IntegralToFloating";
   case CK_FloatingToIntegral:
     return "FloatingToIntegral";
   case CK_FloatingCast:
     return "FloatingCast";
+  case CK_FloatingToBoolean:
+    return "FloatingToBoolean";
   case CK_MemberPointerToBoolean:
     return "MemberPointerToBoolean";
   case CK_AnyPointerToObjCPointerCast:

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Mon Nov 15 03:13:47 2010
@@ -572,7 +572,8 @@
 
 bool Type::isScalarType() const {
   if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
-    return BT->getKind() != BuiltinType::Void && !BT->isPlaceholderType();
+    return BT->getKind() > BuiltinType::Void &&
+           BT->getKind() <= BuiltinType::NullPtr;
   if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
     // Enums are scalar types, but only if they are defined.  Incomplete enums
     // are not treated as scalar types.
@@ -584,6 +585,35 @@
          isa<ObjCObjectPointerType>(CanonicalType);
 }
 
+Type::ScalarTypeKind Type::getScalarTypeKind() const {
+  assert(isScalarType());
+
+  const Type *T = CanonicalType.getTypePtr();
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(T)) {
+    if (BT->getKind() == BuiltinType::Bool) return STK_Bool;
+    if (BT->getKind() == BuiltinType::NullPtr) return STK_Pointer;
+    if (BT->isInteger()) return STK_Integral;
+    if (BT->isFloatingPoint()) return STK_Floating;
+    llvm_unreachable("unknown scalar builtin type");
+  } else if (isa<PointerType>(T) ||
+             isa<BlockPointerType>(T) ||
+             isa<ObjCObjectPointerType>(T)) {
+    return STK_Pointer;
+  } else if (isa<MemberPointerType>(T)) {
+    return STK_MemberPointer;
+  } else if (isa<EnumType>(T)) {
+    assert(cast<EnumType>(T)->getDecl()->isComplete());
+    return STK_Integral;
+  } else if (const ComplexType *CT = dyn_cast<ComplexType>(T)) {
+    if (CT->getElementType()->isRealFloatingType())
+      return STK_FloatingComplex;
+    return STK_IntegralComplex;
+  }
+
+  llvm_unreachable("unknown scalar type");
+  return STK_Pointer;
+}
+
 /// \brief Determines whether the type is a C++ aggregate type or C
 /// aggregate or union type.
 ///

Modified: cfe/trunk/lib/Checker/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/GRExprEngine.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Checker/GRExprEngine.cpp Mon Nov 15 03:13:47 2010
@@ -2541,6 +2541,7 @@
     return;
 
   case CK_Unknown:
+  case CK_Dependent:
   case CK_ArrayToPointerDecay:
   case CK_BitCast:
   case CK_LValueBitCast:
@@ -2548,8 +2549,11 @@
   case CK_NullToPointer:
   case CK_IntegralToPointer:
   case CK_PointerToIntegral:
+  case CK_PointerToBoolean:
+  case CK_IntegralToBoolean:
   case CK_IntegralToFloating:
   case CK_FloatingToIntegral:
+  case CK_FloatingToBoolean:
   case CK_FloatingCast:
   case CK_FloatingRealToComplex:
   case CK_FloatingComplexToReal:

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Mon Nov 15 03:13:47 2010
@@ -1783,7 +1783,10 @@
   switch (E->getCastKind()) {
   case CK_ToVoid:
     return EmitUnsupportedLValue(E, "unexpected cast lvalue");
-   
+
+  case CK_Dependent:
+    llvm_unreachable("dependent cast kind in IR gen!");
+
   case CK_NoOp:
     if (E->getSubExpr()->Classify(getContext()).getKind() 
                                           != Expr::Classification::CL_PRValue) {
@@ -1800,7 +1803,7 @@
       return LV;
     }
     // Fall through to synthesize a temporary.
-      
+
   case CK_Unknown:
   case CK_BitCast:
   case CK_ArrayToPointerDecay:
@@ -1809,10 +1812,13 @@
   case CK_NullToPointer:
   case CK_IntegralToPointer:
   case CK_PointerToIntegral:
+  case CK_PointerToBoolean:
   case CK_VectorSplat:
   case CK_IntegralCast:
+  case CK_IntegralToBoolean:
   case CK_IntegralToFloating:
   case CK_FloatingToIntegral:
+  case CK_FloatingToBoolean:
   case CK_FloatingCast:
   case CK_FloatingRealToComplex:
   case CK_FloatingComplexToReal:

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Mon Nov 15 03:13:47 2010
@@ -110,6 +110,41 @@
   /// EmitNullValue - Emit a value that corresponds to null for the given type.
   Value *EmitNullValue(QualType Ty);
 
+  /// EmitFloatToBoolConversion - Perform an FP to boolean conversion.
+  Value *EmitFloatToBoolConversion(Value *V) {
+    // Compare against 0.0 for fp scalars.
+    llvm::Value *Zero = llvm::Constant::getNullValue(V->getType());
+    return Builder.CreateFCmpUNE(V, Zero, "tobool");
+  }
+
+  /// EmitPointerToBoolConversion - Perform a pointer to boolean conversion.
+  Value *EmitPointerToBoolConversion(Value *V) {
+    Value *Zero = llvm::ConstantPointerNull::get(
+                                      cast<llvm::PointerType>(V->getType()));
+    return Builder.CreateICmpNE(V, Zero, "tobool");
+  }
+
+  Value *EmitIntToBoolConversion(Value *V) {
+    // Because of the type rules of C, we often end up computing a
+    // logical value, then zero extending it to int, then wanting it
+    // as a logical value again.  Optimize this common case.
+    if (llvm::ZExtInst *ZI = dyn_cast<llvm::ZExtInst>(V)) {
+      if (ZI->getOperand(0)->getType() == Builder.getInt1Ty()) {
+        Value *Result = ZI->getOperand(0);
+        // If there aren't any more uses, zap the instruction to save space.
+        // Note that there can be more uses, for example if this
+        // is the result of an assignment.
+        if (ZI->use_empty())
+          ZI->eraseFromParent();
+        return Result;
+      }
+    }
+
+    const llvm::IntegerType *Ty = cast<llvm::IntegerType>(V->getType());
+    Value *Zero = llvm::ConstantInt::get(Ty, 0);
+    return Builder.CreateICmpNE(V, Zero, "tobool");
+  }
+
   //===--------------------------------------------------------------------===//
   //                            Visitor Methods
   //===--------------------------------------------------------------------===//
@@ -461,11 +496,8 @@
 Value *ScalarExprEmitter::EmitConversionToBool(Value *Src, QualType SrcType) {
   assert(SrcType.isCanonical() && "EmitScalarConversion strips typedefs");
 
-  if (SrcType->isRealFloatingType()) {
-    // Compare against 0.0 for fp scalars.
-    llvm::Value *Zero = llvm::Constant::getNullValue(Src->getType());
-    return Builder.CreateFCmpUNE(Src, Zero, "tobool");
-  }
+  if (SrcType->isRealFloatingType())
+    return EmitFloatToBoolConversion(Src);
 
   if (const MemberPointerType *MPT = dyn_cast<MemberPointerType>(SrcType))
     return CGF.CGM.getCXXABI().EmitMemberPointerIsNotNull(CGF, Src, MPT);
@@ -473,25 +505,11 @@
   assert((SrcType->isIntegerType() || isa<llvm::PointerType>(Src->getType())) &&
          "Unknown scalar type to convert");
 
-  // Because of the type rules of C, we often end up computing a logical value,
-  // then zero extending it to int, then wanting it as a logical value again.
-  // Optimize this common case.
-  if (llvm::ZExtInst *ZI = dyn_cast<llvm::ZExtInst>(Src)) {
-    if (ZI->getOperand(0)->getType() ==
-        llvm::Type::getInt1Ty(CGF.getLLVMContext())) {
-      Value *Result = ZI->getOperand(0);
-      // If there aren't any more uses, zap the instruction to save space.
-      // Note that there can be more uses, for example if this
-      // is the result of an assignment.
-      if (ZI->use_empty())
-        ZI->eraseFromParent();
-      return Result;
-    }
-  }
+  if (isa<llvm::IntegerType>(Src->getType()))
+    return EmitIntToBoolConversion(Src);
 
-  // Compare against an integer or pointer null.
-  llvm::Value *Zero = llvm::Constant::getNullValue(Src->getType());
-  return Builder.CreateICmpNE(Src, Zero, "tobool");
+  assert(isa<llvm::PointerType>(Src->getType()));
+  return EmitPointerToBoolConversion(Src);
 }
 
 /// EmitScalarConversion - Emit a conversion from the specified type to the
@@ -979,6 +997,8 @@
   // a default case, so the compiler will warn on a missing case.  The cases
   // are in the same order as in the CastKind enum.
   switch (Kind) {
+  case CK_Dependent: llvm_unreachable("dependent cast kind in IR gen!");
+      
   case CK_Unknown:
     // FIXME: All casts should have a known kind!
     //assert(0 && "Unknown cast kind!");
@@ -1134,19 +1154,27 @@
     // Splat the element across to all elements
     llvm::SmallVector<llvm::Constant*, 16> Args;
     unsigned NumElements = cast<llvm::VectorType>(DstTy)->getNumElements();
+    llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Int32Ty, 0);
     for (unsigned i = 0; i < NumElements; i++)
-      Args.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 0));
+      Args.push_back(Zero);
 
     llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], NumElements);
     llvm::Value *Yay = Builder.CreateShuffleVector(UnV, UnV, Mask, "splat");
     return Yay;
   }
+
   case CK_IntegralCast:
   case CK_IntegralToFloating:
   case CK_FloatingToIntegral:
   case CK_FloatingCast:
     return EmitScalarConversion(Visit(E), E->getType(), DestTy);
 
+  case CK_IntegralToBoolean:
+    return EmitIntToBoolConversion(Visit(E));
+  case CK_PointerToBoolean:
+    return EmitPointerToBoolConversion(Visit(E));
+  case CK_FloatingToBoolean:
+    return EmitFloatToBoolConversion(Visit(E));
   case CK_MemberPointerToBoolean: {
     llvm::Value *MemPtr = Visit(E);
     const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>();

Modified: cfe/trunk/lib/Sema/SemaCXXCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXCast.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXCast.cpp Mon Nov 15 03:13:47 2010
@@ -157,7 +157,7 @@
       << Ex->getSourceRange();
 
   switch (Kind) {
-  default: assert(0 && "Unknown C++ cast!");
+  default: llvm_unreachable("Unknown C++ cast!");
 
   case tok::kw_const_cast:
     if (!TypeDependent)
@@ -167,7 +167,7 @@
                                           Ex, DestTInfo, OpLoc));
 
   case tok::kw_dynamic_cast: {
-    CastKind Kind = CK_Unknown;
+    CastKind Kind = CK_Dependent;
     CXXCastPath BasePath;
     if (!TypeDependent)
       CheckDynamicCast(*this, Ex, DestType, OpRange, DestRange, Kind, BasePath);
@@ -177,7 +177,7 @@
                                             OpLoc));
   }
   case tok::kw_reinterpret_cast: {
-    CastKind Kind = CK_Unknown;
+    CastKind Kind = CK_Dependent;
     if (!TypeDependent)
       CheckReinterpretCast(*this, Ex, DestType, OpRange, DestRange, Kind);
     return Owned(CXXReinterpretCastExpr::Create(Context,
@@ -186,7 +186,7 @@
                                   DestTInfo, OpLoc));
   }
   case tok::kw_static_cast: {
-    CastKind Kind = CK_Unknown;
+    CastKind Kind = CK_Dependent;
     CXXCastPath BasePath;
     if (!TypeDependent)
       CheckStaticCast(*this, Ex, DestType, OpRange, Kind, BasePath);
@@ -515,7 +515,7 @@
   if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg,
                     Kind, BasePath) != TC_Success && msg != 0)
   {
-    if ( SrcExpr->getType() == Self.Context.OverloadTy )
+    if (SrcExpr->getType() == Self.Context.OverloadTy)
     {
       OverloadExpr* oe = OverloadExpr::find(SrcExpr).Expression;
       Self.Diag(OpRange.getBegin(), diag::err_bad_static_cast_overload)
@@ -593,7 +593,11 @@
   // C++0x 5.2.9p9: A value of a scoped enumeration type can be explicitly
   // converted to an integral type.
   if (Self.getLangOptions().CPlusPlus0x && SrcType->isEnumeralType()) {
-    if (DestType->isIntegralType(Self.Context)) {
+    assert(SrcType->getAs<EnumType>()->getDecl()->isScoped());
+    if (DestType->isBooleanType()) {
+      Kind = CK_IntegralToBoolean;
+      return TC_Success;
+    } else if (DestType->isIntegralType(Self.Context)) {
       Kind = CK_IntegralCast;
       return TC_Success;
     }
@@ -665,8 +669,10 @@
   }
   // Allow arbitray objective-c pointer conversion with static casts.
   if (SrcType->isObjCObjectPointerType() &&
-      DestType->isObjCObjectPointerType())
+      DestType->isObjCObjectPointerType()) {
+    Kind = CK_BitCast;
     return TC_Success;
+  }
   
   // We tried everything. Everything! Nothing works! :-(
   return TC_NotApplicable;
@@ -1357,8 +1363,10 @@
   }
 
   // If the type is dependent, we won't do any other semantic analysis now.
-  if (CastTy->isDependentType() || CastExpr->isTypeDependent())
+  if (CastTy->isDependentType() || CastExpr->isTypeDependent()) {
+    Kind = CK_Dependent;
     return false;
+  }
 
   if (!CastTy->isLValueReferenceType() && !CastTy->isRecordType())
     DefaultFunctionArrayLvalueConversion(CastExpr);

Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Mon Nov 15 03:13:47 2010
@@ -547,7 +547,7 @@
 
     // GCC does an implicit conversion to the pointer or integer ValType.  This
     // can fail in some cases (1i -> int**), check for this error case now.
-    CastKind Kind = CK_Unknown;
+    CastKind Kind = CK_Invalid;
     CXXCastPath BasePath;
     if (CheckCastTypes(Arg->getSourceRange(), ValType, Arg, Kind, BasePath))
       return ExprError();

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Mon Nov 15 03:13:47 2010
@@ -1375,7 +1375,8 @@
   // If this ever proves to be a problem it should be easy to fix.
   QualType Ty = S.Context.getPointerType(VD->getType());
   QualType ParamTy = FD->getParamDecl(0)->getType();
-  if (S.CheckAssignmentConstraints(ParamTy, Ty) != Sema::Compatible) {
+  CastKind K;
+  if (S.CheckAssignmentConstraints(ParamTy, Ty, K) != Sema::Compatible) {
     S.Diag(Attr.getLoc(),
            diag::err_attribute_cleanup_func_arg_incompatible_type) <<
       Attr.getParameterName() << ParamTy << Ty;

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Nov 15 03:13:47 2010
@@ -4252,33 +4252,6 @@
   return Owned(E);
 }
 
-enum ScalarKind {
-  SK_Pointer,
-  SK_Bool,
-  SK_Integral,
-  SK_Floating,
-  SK_IntegralComplex,
-  SK_FloatingComplex
-};
-static ScalarKind ClassifyScalarType(QualType QT) {
-  assert(QT->isScalarType());
-
-  const Type *T = QT->getCanonicalTypeUnqualified().getTypePtr();
-  if (T->hasPointerRepresentation())
-    return SK_Pointer;
-  if (T->isBooleanType())
-    return SK_Bool;
-  if (T->isRealFloatingType())
-    return SK_Floating;
-  if (const ComplexType *CT = dyn_cast<ComplexType>(T)) {
-    if (CT->getElementType()->isRealFloatingType())
-      return SK_FloatingComplex;
-    return SK_IntegralComplex;
-  }
-  assert(T->isIntegerType());
-  return SK_Integral;
-}
-
 /// Prepares for a scalar cast, performing all the necessary stages
 /// except the final cast and returning the kind required.
 static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) {
@@ -4290,87 +4263,112 @@
   if (S.Context.hasSameUnqualifiedType(SrcTy, DestTy))
     return CK_NoOp;
 
-  switch (ClassifyScalarType(SrcTy)) {
-  case SK_Pointer:
-    if (DestTy->isIntegerType())
-      return CK_PointerToIntegral;
-    assert(DestTy->hasPointerRepresentation());
-    return DestTy->isObjCObjectPointerType() ?
+  switch (SrcTy->getScalarTypeKind()) {
+  case Type::STK_MemberPointer:
+    llvm_unreachable("member pointer type in C");
+    
+  case Type::STK_Pointer:
+    switch (DestTy->getScalarTypeKind()) {
+    case Type::STK_Pointer:
+      return DestTy->isObjCObjectPointerType() ?
                 CK_AnyPointerToObjCPointerCast :
                 CK_BitCast;
+    case Type::STK_Bool:
+      return CK_PointerToBoolean;
+    case Type::STK_Integral:
+      return CK_PointerToIntegral;
+    case Type::STK_Floating:
+    case Type::STK_FloatingComplex:
+    case Type::STK_IntegralComplex:
+    case Type::STK_MemberPointer:
+      llvm_unreachable("illegal cast from pointer");
+    }
+    break;
 
-  case SK_Bool: // casting from bool is like casting from an integer
-  case SK_Integral:
-    switch (ClassifyScalarType(DestTy)) {
-    case SK_Pointer:
+  case Type::STK_Bool: // casting from bool is like casting from an integer
+  case Type::STK_Integral:
+    switch (DestTy->getScalarTypeKind()) {
+    case Type::STK_Pointer:
       if (Src->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNull))
         return CK_NullToPointer;
       return CK_IntegralToPointer;
-
-    case SK_Bool: // TODO: there should be an int->bool cast kind
-    case SK_Integral:
+    case Type::STK_Bool:
+      return CK_IntegralToBoolean;
+    case Type::STK_Integral:
       return CK_IntegralCast;
-    case SK_Floating:
+    case Type::STK_Floating:
       return CK_IntegralToFloating;
-    case SK_IntegralComplex:
+    case Type::STK_IntegralComplex:
       return CK_IntegralRealToComplex;
-    case SK_FloatingComplex:
+    case Type::STK_FloatingComplex:
       S.ImpCastExprToType(Src, cast<ComplexType>(DestTy)->getElementType(),
                           CK_IntegralToFloating);
       return CK_FloatingRealToComplex;
+    case Type::STK_MemberPointer:
+      llvm_unreachable("member pointer type in C");
     }
     break;
 
-  case SK_Floating:
-    switch (ClassifyScalarType(DestTy)) {
-    case SK_Floating:
+  case Type::STK_Floating:
+    switch (DestTy->getScalarTypeKind()) {
+    case Type::STK_Floating:
       return CK_FloatingCast;
-    case SK_Bool: // TODO: there should be a float->bool cast kind
-    case SK_Integral:
+    case Type::STK_Bool:
+      return CK_FloatingToBoolean;
+    case Type::STK_Integral:
       return CK_FloatingToIntegral;
-    case SK_FloatingComplex:
+    case Type::STK_FloatingComplex:
       return CK_FloatingRealToComplex;
-    case SK_IntegralComplex:
+    case Type::STK_IntegralComplex:
       S.ImpCastExprToType(Src, cast<ComplexType>(DestTy)->getElementType(),
                           CK_FloatingToIntegral);
       return CK_IntegralRealToComplex;
-    case SK_Pointer: llvm_unreachable("valid float->pointer cast?");
+    case Type::STK_Pointer:
+      llvm_unreachable("valid float->pointer cast?");
+    case Type::STK_MemberPointer:
+      llvm_unreachable("member pointer type in C");
     }
     break;
 
-  case SK_FloatingComplex:
-    switch (ClassifyScalarType(DestTy)) {
-    case SK_FloatingComplex:
+  case Type::STK_FloatingComplex:
+    switch (DestTy->getScalarTypeKind()) {
+    case Type::STK_FloatingComplex:
       return CK_FloatingComplexCast;
-    case SK_IntegralComplex:
+    case Type::STK_IntegralComplex:
       return CK_FloatingComplexToIntegralComplex;
-    case SK_Floating:
+    case Type::STK_Floating:
       return CK_FloatingComplexToReal;
-    case SK_Bool:
+    case Type::STK_Bool:
       return CK_FloatingComplexToBoolean;
-    case SK_Integral:
+    case Type::STK_Integral:
       S.ImpCastExprToType(Src, cast<ComplexType>(SrcTy)->getElementType(),
                           CK_FloatingComplexToReal);
       return CK_FloatingToIntegral;
-    case SK_Pointer: llvm_unreachable("valid complex float->pointer cast?");
+    case Type::STK_Pointer:
+      llvm_unreachable("valid complex float->pointer cast?");
+    case Type::STK_MemberPointer:
+      llvm_unreachable("member pointer type in C");
     }
     break;
 
-  case SK_IntegralComplex:
-    switch (ClassifyScalarType(DestTy)) {
-    case SK_FloatingComplex:
+  case Type::STK_IntegralComplex:
+    switch (DestTy->getScalarTypeKind()) {
+    case Type::STK_FloatingComplex:
       return CK_IntegralComplexToFloatingComplex;
-    case SK_IntegralComplex:
+    case Type::STK_IntegralComplex:
       return CK_IntegralComplexCast;
-    case SK_Integral:
+    case Type::STK_Integral:
       return CK_IntegralComplexToReal;
-    case SK_Bool:
+    case Type::STK_Bool:
       return CK_IntegralComplexToBoolean;
-    case SK_Floating:
+    case Type::STK_Floating:
       S.ImpCastExprToType(Src, cast<ComplexType>(SrcTy)->getElementType(),
                           CK_IntegralComplexToReal);
       return CK_IntegralToFloating;
-    case SK_Pointer: llvm_unreachable("valid complex int->pointer cast?");
+    case Type::STK_Pointer:
+      llvm_unreachable("valid complex int->pointer cast?");
+    case Type::STK_MemberPointer:
+      llvm_unreachable("member pointer type in C");
     }
     break;
   }
@@ -4565,7 +4563,7 @@
 ExprResult
 Sema::BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty,
                           SourceLocation RParenLoc, Expr *castExpr) {
-  CastKind Kind = CK_Unknown;
+  CastKind Kind = CK_Invalid;
   CXXCastPath BasePath;
   if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), Ty->getType(), castExpr,
                      Kind, BasePath))
@@ -4772,12 +4770,12 @@
   if ((LHSTy->isAnyPointerType() || LHSTy->isBlockPointerType()) &&
       RHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
     // promote the null to a pointer.
-    ImpCastExprToType(RHS, LHSTy, CK_Unknown);
+    ImpCastExprToType(RHS, LHSTy, CK_NullToPointer);
     return LHSTy;
   }
   if ((RHSTy->isAnyPointerType() || RHSTy->isBlockPointerType()) &&
       LHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
-    ImpCastExprToType(LHS, RHSTy, CK_Unknown);
+    ImpCastExprToType(LHS, RHSTy, CK_NullToPointer);
     return RHSTy;
   }
 
@@ -5242,21 +5240,26 @@
 /// As a result, the code for dealing with pointers is more complex than the
 /// C99 spec dictates.
 ///
+/// Sets 'Kind' for any result kind except Incompatible.
 Sema::AssignConvertType
-Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
+Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType,
+                                 CastKind &Kind) {
   // Get canonical types.  We're not formatting these types, just comparing
   // them.
   lhsType = Context.getCanonicalType(lhsType).getUnqualifiedType();
   rhsType = Context.getCanonicalType(rhsType).getUnqualifiedType();
 
-  if (lhsType == rhsType)
+  if (lhsType == rhsType) {
+    Kind = CK_NoOp;
     return Compatible; // Common case: fast path an exact match.
+  }
 
   if ((lhsType->isObjCClassType() &&
        (rhsType.getDesugaredType() == Context.ObjCClassRedefinitionType)) ||
      (rhsType->isObjCClassType() &&
        (lhsType.getDesugaredType() == Context.ObjCClassRedefinitionType))) {
-      return Compatible;
+    Kind = CK_BitCast;
+    return Compatible;
   }
 
   // If the left-hand side is a reference type, then we are in a
@@ -5267,17 +5270,21 @@
   // lhsType so that the resulting expression does not have reference
   // type.
   if (const ReferenceType *lhsTypeRef = lhsType->getAs<ReferenceType>()) {
-    if (Context.typesAreCompatible(lhsTypeRef->getPointeeType(), rhsType))
+    if (Context.typesAreCompatible(lhsTypeRef->getPointeeType(), rhsType)) {
+      Kind = CK_LValueBitCast;
       return Compatible;
+    }
     return Incompatible;
   }
   // Allow scalar to ExtVector assignments, and assignments of an ExtVector type
   // to the same ExtVector type.
   if (lhsType->isExtVectorType()) {
     if (rhsType->isExtVectorType())
-      return lhsType == rhsType ? Compatible : Incompatible;
-    if (rhsType->isArithmeticType())
+      return Incompatible;
+    if (rhsType->isArithmeticType()) {
+      Kind = CK_Unknown; // FIXME: vector splat, requires two casts
       return Compatible;
+    }
   }
 
   if (lhsType->isVectorType() || rhsType->isVectorType()) {
@@ -5286,48 +5293,67 @@
       // vectors, the total size only needs to be the same. This is a bitcast;
       // no bits are changed but the result type is different.
       if (getLangOptions().LaxVectorConversions &&
-         (Context.getTypeSize(lhsType) == Context.getTypeSize(rhsType)))
+          (Context.getTypeSize(lhsType) == Context.getTypeSize(rhsType))) {
+        Kind = CK_Unknown; // FIXME: vector reinterpret is... bitcast?
         return IncompatibleVectors;
+      }
 
       // Allow assignments of an AltiVec vector type to an equivalent GCC
       // vector type and vice versa
-      if (Context.areCompatibleVectorTypes(lhsType, rhsType))
+      if (Context.areCompatibleVectorTypes(lhsType, rhsType)) {
+        Kind = CK_Unknown; // FIXME: vector conversion
         return Compatible;
+      }
     }
     return Incompatible;
   }
 
   if (lhsType->isArithmeticType() && rhsType->isArithmeticType() &&
-      !(getLangOptions().CPlusPlus && lhsType->isEnumeralType()))
+      !(getLangOptions().CPlusPlus && lhsType->isEnumeralType())) {
+    Kind = CK_Unknown; // FIXME: reuse the cast logic if possible
     return Compatible;
+  }
 
   if (isa<PointerType>(lhsType)) {
-    if (rhsType->isIntegerType())
+    if (rhsType->isIntegerType()) {
+      Kind = CK_IntegralToPointer; // FIXME: null?
       return IntToPointer;
+    }
 
-    if (isa<PointerType>(rhsType))
+    if (isa<PointerType>(rhsType)) {
+      Kind = CK_BitCast;
       return CheckPointerTypesForAssignment(lhsType, rhsType);
+    }
 
     // In general, C pointers are not compatible with ObjC object pointers.
     if (isa<ObjCObjectPointerType>(rhsType)) {
+      Kind = CK_AnyPointerToObjCPointerCast;
       if (lhsType->isVoidPointerType()) // an exception to the rule.
         return Compatible;
       return IncompatiblePointer;
     }
     if (rhsType->getAs<BlockPointerType>()) {
-      if (lhsType->getAs<PointerType>()->getPointeeType()->isVoidType())
+      if (lhsType->getAs<PointerType>()->getPointeeType()->isVoidType()) {
+        Kind = CK_BitCast;
         return Compatible;
+      }
 
       // Treat block pointers as objects.
-      if (getLangOptions().ObjC1 && lhsType->isObjCIdType())
+      if (getLangOptions().ObjC1 && lhsType->isObjCIdType()) {
+        Kind = CK_AnyPointerToObjCPointerCast;
         return Compatible;
+      }
     }
     return Incompatible;
   }
 
   if (isa<BlockPointerType>(lhsType)) {
-    if (rhsType->isIntegerType())
+    if (rhsType->isIntegerType()) {
+      Kind = CK_IntegralToPointer; // FIXME: null
       return IntToBlockPointer;
+    }
+
+    Kind = CK_AnyPointerToObjCPointerCast;
 
     // Treat block pointers as objects.
     if (getLangOptions().ObjC1 && rhsType->isObjCIdType())
@@ -5336,16 +5362,20 @@
     if (rhsType->isBlockPointerType())
       return CheckBlockPointerTypesForAssignment(lhsType, rhsType);
 
-    if (const PointerType *RHSPT = rhsType->getAs<PointerType>()) {
+    if (const PointerType *RHSPT = rhsType->getAs<PointerType>())
       if (RHSPT->getPointeeType()->isVoidType())
         return Compatible;
-    }
+
     return Incompatible;
   }
 
   if (isa<ObjCObjectPointerType>(lhsType)) {
-    if (rhsType->isIntegerType())
+    if (rhsType->isIntegerType()) {
+      Kind = CK_IntegralToPointer; // FIXME: null
       return IntToPointer;
+    }
+
+    Kind = CK_BitCast;
 
     // In general, C pointers are not compatible with ObjC object pointers.
     if (isa<PointerType>(rhsType)) {
@@ -5367,27 +5397,36 @@
   }
   if (isa<PointerType>(rhsType)) {
     // C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer.
-    if (lhsType == Context.BoolTy)
+    if (lhsType == Context.BoolTy) {
+      Kind = CK_PointerToBoolean;
       return Compatible;
+    }
 
-    if (lhsType->isIntegerType())
+    if (lhsType->isIntegerType()) {
+      Kind = CK_PointerToIntegral;
       return PointerToInt;
-
-    if (isa<PointerType>(lhsType))
-      return CheckPointerTypesForAssignment(lhsType, rhsType);
+    }
 
     if (isa<BlockPointerType>(lhsType) &&
-        rhsType->getAs<PointerType>()->getPointeeType()->isVoidType())
+        rhsType->getAs<PointerType>()->getPointeeType()->isVoidType()) {
+      Kind = CK_AnyPointerToBlockPointerCast;
       return Compatible;
+    }
     return Incompatible;
   }
   if (isa<ObjCObjectPointerType>(rhsType)) {
     // C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer.
-    if (lhsType == Context.BoolTy)
+    if (lhsType == Context.BoolTy) {
+      Kind = CK_PointerToBoolean;
       return Compatible;
+    }
 
-    if (lhsType->isIntegerType())
+    if (lhsType->isIntegerType()) {
+      Kind = CK_PointerToIntegral;
       return PointerToInt;
+    }
+
+    Kind = CK_BitCast;
 
     // In general, C pointers are not compatible with ObjC object pointers.
     if (isa<PointerType>(lhsType)) {
@@ -5396,14 +5435,18 @@
       return IncompatiblePointer;
     }
     if (isa<BlockPointerType>(lhsType) &&
-        rhsType->getAs<PointerType>()->getPointeeType()->isVoidType())
+        rhsType->getAs<PointerType>()->getPointeeType()->isVoidType()) {
+      Kind = CK_AnyPointerToBlockPointerCast;
       return Compatible;
+    }
     return Incompatible;
   }
 
   if (isa<TagType>(lhsType) && isa<TagType>(rhsType)) {
-    if (Context.typesAreCompatible(lhsType, rhsType))
+    if (Context.typesAreCompatible(lhsType, rhsType)) {
+      Kind = CK_NoOp;
       return Compatible;
+    }
   }
   return Incompatible;
 }
@@ -5463,9 +5506,10 @@
       }
     }
 
-    if (CheckAssignmentConstraints(it->getType(), rExpr->getType())
+    CastKind Kind = CK_Invalid;
+    if (CheckAssignmentConstraints(it->getType(), rExpr->getType(), Kind)
           == Compatible) {
-      ImpCastExprToType(rExpr, it->getType(), CK_Unknown);
+      ImpCastExprToType(rExpr, it->getType(), Kind);
       InitField = *it;
       break;
     }
@@ -5502,7 +5546,7 @@
        lhsType->isBlockPointerType())
       && rExpr->isNullPointerConstant(Context,
                                       Expr::NPC_ValueDependentIsNull)) {
-    ImpCastExprToType(rExpr, lhsType, CK_Unknown);
+    ImpCastExprToType(rExpr, lhsType, CK_NullToPointer);
     return Compatible;
   }
 
@@ -5515,8 +5559,9 @@
   if (!lhsType->isReferenceType())
     DefaultFunctionArrayLvalueConversion(rExpr);
 
+  CastKind Kind = CK_Invalid;
   Sema::AssignConvertType result =
-    CheckAssignmentConstraints(lhsType, rExpr->getType());
+    CheckAssignmentConstraints(lhsType, rExpr->getType(), Kind);
 
   // C99 6.5.16.1p2: The value of the right operand is converted to the
   // type of the assignment expression.
@@ -5525,8 +5570,7 @@
   // The getNonReferenceType() call makes sure that the resulting expression
   // does not have reference type.
   if (result != Incompatible && rExpr->getType() != lhsType)
-    ImpCastExprToType(rExpr, lhsType.getNonLValueExprType(Context),
-                      CK_Unknown);
+    ImpCastExprToType(rExpr, lhsType.getNonLValueExprType(Context), Kind);
   return result;
 }
 
@@ -5594,16 +5638,22 @@
   if (const ExtVectorType *LV = lhsType->getAs<ExtVectorType>()) {
     QualType EltTy = LV->getElementType();
     if (EltTy->isIntegralType(Context) && rhsType->isIntegralType(Context)) {
-      if (Context.getIntegerTypeOrder(EltTy, rhsType) >= 0) {
-        ImpCastExprToType(rex, lhsType, CK_IntegralCast);
+      int order = Context.getIntegerTypeOrder(EltTy, rhsType);
+      if (order > 0)
+        ImpCastExprToType(rex, EltTy, CK_IntegralCast);
+      if (order >= 0) {
+        ImpCastExprToType(rex, lhsType, CK_VectorSplat);
         if (swapped) std::swap(rex, lex);
         return lhsType;
       }
     }
     if (EltTy->isRealFloatingType() && rhsType->isScalarType() &&
         rhsType->isRealFloatingType()) {
-      if (Context.getFloatingTypeOrder(EltTy, rhsType) >= 0) {
-        ImpCastExprToType(rex, lhsType, CK_FloatingCast);
+      int order = Context.getFloatingTypeOrder(EltTy, rhsType);
+      if (order > 0)
+        ImpCastExprToType(rex, EltTy, CK_FloatingCast);
+      if (order >= 0) {
+        ImpCastExprToType(rex, lhsType, CK_VectorSplat);
         if (swapped) std::swap(rex, lex);
         return lhsType;
       }
@@ -6583,7 +6633,8 @@
     }
   } else {
     // Compound assignment "x += y"
-    ConvTy = CheckAssignmentConstraints(LHSType, RHSType);
+    CastKind Kind = CK_Invalid; // forgotten?
+    ConvTy = CheckAssignmentConstraints(LHSType, RHSType, Kind);
   }
 
   if (DiagnoseAssignmentResult(ConvTy, Loc, LHSType, RHSType,

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Nov 15 03:13:47 2010
@@ -604,7 +604,7 @@
   // corresponding cast expression.
   //
   if (NumExprs == 1) {
-    CastKind Kind = CK_Unknown;
+    CastKind Kind = CK_Invalid;
     CXXCastPath BasePath;
     if (CheckCastTypes(TInfo->getTypeLoc().getSourceRange(), Ty, Exprs[0], 
                        Kind, BasePath,
@@ -1708,7 +1708,7 @@
   case ImplicitConversionSequence::UserDefinedConversion: {
     
       FunctionDecl *FD = ICS.UserDefined.ConversionFunction;
-      CastKind CastKind = CK_Unknown;
+      CastKind CastKind;
       QualType BeforeToType;
       if (const CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(FD)) {
         CastKind = CK_UserDefinedConversion;
@@ -1893,9 +1893,23 @@
     break;
 
   case ICK_Complex_Promotion:
-  case ICK_Complex_Conversion:
-    ImpCastExprToType(From, ToType, CK_Unknown);
+  case ICK_Complex_Conversion: {
+    QualType FromEl = From->getType()->getAs<ComplexType>()->getElementType();
+    QualType ToEl = ToType->getAs<ComplexType>()->getElementType();
+    CastKind CK;
+    if (FromEl->isRealFloatingType()) {
+      if (ToEl->isRealFloatingType())
+        CK = CK_FloatingComplexCast;
+      else
+        CK = CK_FloatingComplexToIntegralComplex;
+    } else if (ToEl->isRealFloatingType()) {
+      CK = CK_IntegralComplexToFloatingComplex;
+    } else {
+      CK = CK_IntegralComplexCast;
+    }
+    ImpCastExprToType(From, ToType, CK);
     break;
+  }
 
   case ICK_Floating_Integral:
     if (ToType->isRealFloatingType())
@@ -1916,9 +1930,8 @@
         << From->getType() << ToType << Action
         << From->getSourceRange();
     }
-
     
-    CastKind Kind = CK_Unknown;
+    CastKind Kind = CK_Invalid;
     CXXCastPath BasePath;
     if (CheckPointerConversion(From, ToType, Kind, BasePath, IgnoreBaseAccess))
       return true;
@@ -1927,7 +1940,7 @@
   }
   
   case ICK_Pointer_Member: {
-    CastKind Kind = CK_Unknown;
+    CastKind Kind = CK_Invalid;
     CXXCastPath BasePath;
     if (CheckMemberPointerConversion(From, ToType, Kind, BasePath,
                                      IgnoreBaseAccess))
@@ -1938,9 +1951,16 @@
     break;
   }
   case ICK_Boolean_Conversion: {
-    CastKind Kind = CK_Unknown;
-    if (FromType->isMemberPointerType())
-      Kind = CK_MemberPointerToBoolean;
+    CastKind Kind = CK_Invalid;
+    switch (FromType->getScalarTypeKind()) {
+    case Type::STK_Pointer: Kind = CK_PointerToBoolean; break;
+    case Type::STK_MemberPointer: Kind = CK_MemberPointerToBoolean; break;
+    case Type::STK_Bool: llvm_unreachable("bool -> bool conversion?");
+    case Type::STK_Integral: Kind = CK_IntegralToBoolean; break;
+    case Type::STK_Floating: Kind = CK_FloatingToBoolean; break;
+    case Type::STK_IntegralComplex: Kind = CK_IntegralComplexToBoolean; break;
+    case Type::STK_FloatingComplex: Kind = CK_FloatingComplexToBoolean; break;
+    }
     
     ImpCastExprToType(From, Context.BoolTy, Kind);
     break;
@@ -1971,7 +1991,52 @@
     break;
       
   case ICK_Complex_Real:
-    ImpCastExprToType(From, ToType, CK_Unknown);
+    // Case 1.  x -> _Complex y
+    if (const ComplexType *ToComplex = ToType->getAs<ComplexType>()) {
+      QualType ElType = ToComplex->getElementType();
+      bool isFloatingComplex = ElType->isRealFloatingType();
+
+      // x -> y
+      if (Context.hasSameUnqualifiedType(ElType, From->getType())) {
+        // do nothing
+      } else if (From->getType()->isRealFloatingType()) {
+        ImpCastExprToType(From, ElType,
+                isFloatingComplex ? CK_FloatingCast : CK_FloatingToIntegral);
+      } else {
+        assert(From->getType()->isIntegerType());
+        ImpCastExprToType(From, ElType,
+                isFloatingComplex ? CK_IntegralToFloating : CK_IntegralCast);
+      }
+      // y -> _Complex y
+      ImpCastExprToType(From, ToType,
+                   isFloatingComplex ? CK_FloatingRealToComplex
+                                     : CK_IntegralRealToComplex);
+
+    // Case 2.  _Complex x -> y
+    } else {
+      const ComplexType *FromComplex = From->getType()->getAs<ComplexType>();
+      assert(FromComplex);
+
+      QualType ElType = FromComplex->getElementType();
+      bool isFloatingComplex = ElType->isRealFloatingType();
+
+      // _Complex x -> x
+      ImpCastExprToType(From, ElType,
+                   isFloatingComplex ? CK_FloatingComplexToReal
+                                     : CK_IntegralComplexToReal);
+
+      // x -> y
+      if (Context.hasSameUnqualifiedType(ElType, ToType)) {
+        // do nothing
+      } else if (ToType->isRealFloatingType()) {
+        ImpCastExprToType(From, ToType,
+                isFloatingComplex ? CK_FloatingCast : CK_IntegralToFloating);
+      } else {
+        assert(ToType->isIntegerType());
+        ImpCastExprToType(From, ToType,
+                isFloatingComplex ? CK_FloatingToIntegral : CK_IntegralCast);
+      }
+    }
     break;
       
   case ICK_Lvalue_To_Rvalue:

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Mon Nov 15 03:13:47 2010
@@ -3745,7 +3745,7 @@
     case SK_UserConversion: {
       // We have a user-defined conversion that invokes either a constructor
       // or a conversion function.
-      CastKind CastKind = CK_Unknown;
+      CastKind CastKind;
       bool IsCopy = false;
       FunctionDecl *Fn = Step->Function.Function;
       DeclAccessPair FoundFn = Step->Function.FoundDecl;

Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)
+++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Mon Nov 15 03:13:47 2010
@@ -424,8 +424,11 @@
           Context.canAssignObjCInterfaces(
                                   PropType->getAs<ObjCObjectPointerType>(),
                                   IvarType->getAs<ObjCObjectPointerType>());
-      else 
-        compat = (CheckAssignmentConstraints(PropType, IvarType) == Compatible);
+      else  {
+        CastKind K = CK_Invalid;
+        compat = (CheckAssignmentConstraints(PropType, IvarType, K)
+                    == Compatible);
+      }
       if (!compat) {
         Diag(PropertyLoc, diag::error_property_ivar_type)
           << property->getDeclName() << PropType
@@ -644,9 +647,11 @@
   if (GetterMethod &&
       GetterMethod->getResultType() != property->getType()) {
     AssignConvertType result = Incompatible;
-    if (property->getType()->isObjCObjectPointerType())
+    if (property->getType()->isObjCObjectPointerType()) {
+      CastKind Kind = CK_Invalid;
       result = CheckAssignmentConstraints(GetterMethod->getResultType(),
-                                          property->getType());
+                                          property->getType(), Kind);
+    }
     if (result != Compatible) {
       Diag(Loc, diag::warn_accessor_property_type_mismatch)
       << property->getDeclName()

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Nov 15 03:13:47 2010
@@ -1064,17 +1064,26 @@
     // Complex promotion (Clang extension)
     SCS.Second = ICK_Complex_Promotion;
     FromType = ToType.getUnqualifiedType();
+  } else if (ToType->isBooleanType() &&
+             (FromType->isArithmeticType() ||
+              FromType->isAnyPointerType() ||
+              FromType->isBlockPointerType() ||
+              FromType->isMemberPointerType() ||
+              FromType->isNullPtrType())) {
+    // Boolean conversions (C++ 4.12).
+    SCS.Second = ICK_Boolean_Conversion;
+    FromType = S.Context.BoolTy;
   } else if (FromType->isIntegralOrUnscopedEnumerationType() &&
              ToType->isIntegralType(S.Context)) {
     // Integral conversions (C++ 4.7).
     SCS.Second = ICK_Integral_Conversion;
     FromType = ToType.getUnqualifiedType();
-  } else if (FromType->isComplexType() && ToType->isComplexType()) {
+  } else if (FromType->isAnyComplexType() && ToType->isComplexType()) {
     // Complex conversions (C99 6.3.1.6)
     SCS.Second = ICK_Complex_Conversion;
     FromType = ToType.getUnqualifiedType();
-  } else if ((FromType->isComplexType() && ToType->isArithmeticType()) ||
-             (ToType->isComplexType() && FromType->isArithmeticType())) {
+  } else if ((FromType->isAnyComplexType() && ToType->isArithmeticType()) ||
+             (ToType->isAnyComplexType() && FromType->isArithmeticType())) {
     // Complex-real conversions (C99 6.3.1.7)
     SCS.Second = ICK_Complex_Real;
     FromType = ToType.getUnqualifiedType();
@@ -1083,7 +1092,7 @@
     SCS.Second = ICK_Floating_Conversion;
     FromType = ToType.getUnqualifiedType();
   } else if ((FromType->isRealFloatingType() && 
-              ToType->isIntegralType(S.Context) && !ToType->isBooleanType()) ||
+              ToType->isIntegralType(S.Context)) ||
              (FromType->isIntegralOrUnscopedEnumerationType() &&
               ToType->isRealFloatingType())) {
     // Floating-integral conversions (C++ 4.9).
@@ -1098,15 +1107,6 @@
                                          InOverloadResolution, FromType)) {
     // Pointer to member conversions (4.11).
     SCS.Second = ICK_Pointer_Member;
-  } else if (ToType->isBooleanType() &&
-             (FromType->isArithmeticType() ||
-              FromType->isAnyPointerType() ||
-              FromType->isBlockPointerType() ||
-              FromType->isMemberPointerType() ||
-              FromType->isNullPtrType())) {
-    // Boolean conversions (C++ 4.12).
-    SCS.Second = ICK_Boolean_Conversion;
-    FromType = S.Context.BoolTy;
   } else if (IsVectorConversion(S.Context, FromType, ToType, SecondICK)) {
     SCS.Second = SecondICK;
     FromType = ToType.getUnqualifiedType();
@@ -1755,6 +1755,8 @@
   QualType FromType = From->getType();
   bool IsCStyleOrFunctionalCast = IgnoreBaseAccess;
 
+  Kind = CK_BitCast;
+
   if (CXXBoolLiteralExpr* LitBool
                           = dyn_cast<CXXBoolLiteralExpr>(From->IgnoreParens()))
     if (!IsCStyleOrFunctionalCast && LitBool->getValue() == false)
@@ -1781,7 +1783,7 @@
       }
     }
   if (const ObjCObjectPointerType *FromPtrType =
-        FromType->getAs<ObjCObjectPointerType>())
+        FromType->getAs<ObjCObjectPointerType>()) {
     if (const ObjCObjectPointerType *ToPtrType =
           ToType->getAs<ObjCObjectPointerType>()) {
       // Objective-C++ conversions are always okay.
@@ -1789,8 +1791,14 @@
       // Objective-C++ implicit conversions.
       if (FromPtrType->isObjCBuiltinType() || ToPtrType->isObjCBuiltinType())
         return false;
-
+    }
   }
+
+  // We shouldn't fall into this case unless it's valid for other
+  // reasons.
+  if (From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull))
+    Kind = CK_NullToPointer;
+
   return false;
 }
 

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Nov 15 03:13:47 2010
@@ -3087,7 +3087,10 @@
       Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch)
         << ArgType << ParamType;
       Diag(Param->getLocation(), diag::note_template_param_here);
-      return true;      
+      return true;
+    } else if (ParamType->isBooleanType()) {
+      // This is an integral-to-boolean conversion.
+      ImpCastExprToType(Arg, ParamType, CK_IntegralToBoolean);
     } else if (IsIntegralPromotion(Arg, ArgType, ParamType) ||
                !ParamType->isEnumeralType()) {
       // This is an integral promotion or conversion.





More information about the cfe-commits mailing list