aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaCast.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaCast.cpp')
-rw-r--r--clang/lib/Sema/SemaCast.cpp86
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();