diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaCXXCast.cpp | 24 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 267 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 87 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaObjCProperty.cpp | 13 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 38 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 5 |
9 files changed, 291 insertions, 150 deletions
diff --git a/clang/lib/Sema/SemaCXXCast.cpp b/clang/lib/Sema/SemaCXXCast.cpp index baeebe1e409..e8e9deddc21 100644 --- a/clang/lib/Sema/SemaCXXCast.cpp +++ b/clang/lib/Sema/SemaCXXCast.cpp @@ -157,7 +157,7 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, << 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 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, 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 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, 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 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, 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 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, 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 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, // 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 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr, } // 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 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr, } // 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); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 56a0c076ad3..e11d68ca19d 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -547,7 +547,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { // 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(); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 8b7863107b4..e07b1ac4716 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1375,7 +1375,8 @@ static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) { // 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; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 687b92e21bb..ae38a597e8f 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4252,33 +4252,6 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist, 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 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) { 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 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, ParsedType Ty, 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 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, 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 @@ Sema::CheckObjCPointerTypesForAssignment(QualType lhsType, QualType rhsType) { /// 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 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { // 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 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { // 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 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { 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 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { } 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 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { 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 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) { } } - 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 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { lhsType->isBlockPointerType()) && rExpr->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { - ImpCastExprToType(rExpr, lhsType, CK_Unknown); + ImpCastExprToType(rExpr, lhsType, CK_NullToPointer); return Compatible; } @@ -5515,8 +5559,9 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { 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 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { // 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 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { 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 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, } } 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, diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index b6a02518a7d..70e9a97fc67 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -604,7 +604,7 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, // 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 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, 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 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, 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 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, << 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 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, } 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 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, 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 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, 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: diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 7025369b851..77b620b9e9f 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3745,7 +3745,7 @@ InitializationSequence::Perform(Sema &S, 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; diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index e1c0f4af99e..4c439f90e89 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -424,8 +424,11 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, 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 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, 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() diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 7c51548b2bb..0c8d78025b4 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1064,17 +1064,26 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // 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 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, 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 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, 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 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, 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 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, } } 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 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, // 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; } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 3243903863d..3f4a1af7727 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -3087,7 +3087,10 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, 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. |