diff options
Diffstat (limited to 'clang/lib/Sema/SemaCast.cpp')
-rw-r--r-- | clang/lib/Sema/SemaCast.cpp | 86 |
1 files changed, 66 insertions, 20 deletions
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 7b5bc7ca80b1..9fd9369c9641 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -451,6 +451,7 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT, case InitializationSequence::FK_ConstructorOverloadFailed: case InitializationSequence::FK_UserConversionOverloadFailed: + case InitializationSequence::FK_ParenthesizedListInitFailed: break; } @@ -1059,11 +1060,19 @@ static bool argTypeIsABIEquivalent(QualType SrcType, QualType DestType, return Context.hasSameUnqualifiedType(SrcType, DestType); } -static bool checkCastFunctionType(Sema &Self, const ExprResult &SrcExpr, - QualType DestType) { - if (Self.Diags.isIgnored(diag::warn_cast_function_type, - SrcExpr.get()->getExprLoc())) - return true; +static unsigned int checkCastFunctionType(Sema &Self, const ExprResult &SrcExpr, + QualType DestType) { + unsigned int DiagID = 0; + const unsigned int DiagList[] = {diag::warn_cast_function_type_strict, + diag::warn_cast_function_type}; + for (auto ID : DiagList) { + if (!Self.Diags.isIgnored(ID, SrcExpr.get()->getExprLoc())) { + DiagID = ID; + break; + } + } + if (!DiagID) + return 0; QualType SrcType = SrcExpr.get()->getType(); const FunctionType *SrcFTy = nullptr; @@ -1078,10 +1087,17 @@ static bool checkCastFunctionType(Sema &Self, const ExprResult &SrcExpr, SrcFTy = SrcType->castAs<FunctionType>(); DstFTy = DestType.getNonReferenceType()->castAs<FunctionType>(); } else { - return true; + return 0; } assert(SrcFTy && DstFTy); + if (Self.Context.hasSameType(SrcFTy, DstFTy)) + return 0; + + // For strict checks, ensure we have an exact match. + if (DiagID == diag::warn_cast_function_type_strict) + return DiagID; + auto IsVoidVoid = [](const FunctionType *T) { if (!T->getReturnType()->isVoidType()) return false; @@ -1092,16 +1108,16 @@ static bool checkCastFunctionType(Sema &Self, const ExprResult &SrcExpr, // Skip if either function type is void(*)(void) if (IsVoidVoid(SrcFTy) || IsVoidVoid(DstFTy)) - return true; + return 0; // Check return type. if (!argTypeIsABIEquivalent(SrcFTy->getReturnType(), DstFTy->getReturnType(), Self.Context)) - return false; + return DiagID; // Check if either has unspecified number of parameters if (SrcFTy->isFunctionNoProtoType() || DstFTy->isFunctionNoProtoType()) - return true; + return 0; // Check parameter types. @@ -1114,19 +1130,19 @@ static bool checkCastFunctionType(Sema &Self, const ExprResult &SrcExpr, unsigned DstNumParams = DstFPTy->getNumParams(); if (NumParams > DstNumParams) { if (!DstFPTy->isVariadic()) - return false; + return DiagID; NumParams = DstNumParams; } else if (NumParams < DstNumParams) { if (!SrcFPTy->isVariadic()) - return false; + return DiagID; } for (unsigned i = 0; i < NumParams; ++i) if (!argTypeIsABIEquivalent(SrcFPTy->getParamType(i), DstFPTy->getParamType(i), Self.Context)) - return false; + return DiagID; - return true; + return 0; } /// CheckReinterpretCast - Check that a reinterpret_cast\<DestType\>(SrcExpr) is @@ -1167,8 +1183,8 @@ void CastOperation::CheckReinterpretCast() { checkObjCConversion(Sema::CCK_OtherCast); DiagnoseReinterpretUpDownCast(Self, SrcExpr.get(), DestType, OpRange); - if (!checkCastFunctionType(Self, SrcExpr, DestType)) - Self.Diag(OpRange.getBegin(), diag::warn_cast_function_type) + if (unsigned DiagID = checkCastFunctionType(Self, SrcExpr, DestType)) + Self.Diag(OpRange.getBegin(), DiagID) << SrcExpr.get()->getType() << DestType << OpRange; } else { SrcExpr = ExprError(); @@ -2797,8 +2813,8 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle, if (Kind == CK_BitCast) checkCastAlign(); - if (!checkCastFunctionType(Self, SrcExpr, DestType)) - Self.Diag(OpRange.getBegin(), diag::warn_cast_function_type) + if (unsigned DiagID = checkCastFunctionType(Self, SrcExpr, DestType)) + Self.Diag(OpRange.getBegin(), DiagID) << SrcExpr.get()->getType() << DestType << OpRange; } else { @@ -2985,6 +3001,37 @@ void CastOperation::CheckCStyleCast() { return; } + // C2x 6.5.4p4: + // The type nullptr_t shall not be converted to any type other than void, + // bool, or a pointer type. No type other than nullptr_t shall be converted + // to nullptr_t. + if (SrcType->isNullPtrType()) { + // FIXME: 6.3.2.4p2 says that nullptr_t can be converted to itself, but + // 6.5.4p4 is a constraint check and nullptr_t is not void, bool, or a + // pointer type. We're not going to diagnose that as a constraint violation. + if (!DestType->isVoidType() && !DestType->isBooleanType() && + !DestType->isPointerType() && !DestType->isNullPtrType()) { + Self.Diag(SrcExpr.get()->getExprLoc(), diag::err_nullptr_cast) + << /*nullptr to type*/ 0 << DestType; + SrcExpr = ExprError(); + return; + } + if (!DestType->isNullPtrType()) { + // Implicitly cast from the null pointer type to the type of the + // destination. + CastKind CK = DestType->isPointerType() ? CK_NullToPointer : CK_BitCast; + SrcExpr = ImplicitCastExpr::Create(Self.Context, DestType, CK, + SrcExpr.get(), nullptr, VK_PRValue, + Self.CurFPFeatureOverrides()); + } + } + if (DestType->isNullPtrType() && !SrcType->isNullPtrType()) { + Self.Diag(SrcExpr.get()->getExprLoc(), diag::err_nullptr_cast) + << /*type to nullptr*/ 1 << SrcType; + SrcExpr = ExprError(); + return; + } + if (DestType->isExtVectorType()) { SrcExpr = Self.CheckExtVectorCast(OpRange, DestType, SrcExpr.get(), Kind); return; @@ -3125,9 +3172,8 @@ void CastOperation::CheckCStyleCast() { } } - if (!checkCastFunctionType(Self, SrcExpr, DestType)) - Self.Diag(OpRange.getBegin(), diag::warn_cast_function_type) - << SrcType << DestType << OpRange; + if (unsigned DiagID = checkCastFunctionType(Self, SrcExpr, DestType)) + Self.Diag(OpRange.getBegin(), DiagID) << SrcType << DestType << OpRange; if (isa<PointerType>(SrcType) && isa<PointerType>(DestType)) { QualType SrcTy = cast<PointerType>(SrcType)->getPointeeType(); |