summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaCast.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaCast.cpp')
-rw-r--r--lib/Sema/SemaCast.cpp93
1 files changed, 68 insertions, 25 deletions
diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp
index 0b4645e11c..21a4d107ba 100644
--- a/lib/Sema/SemaCast.cpp
+++ b/lib/Sema/SemaCast.cpp
@@ -1,9 +1,8 @@
//===--- SemaCast.cpp - Semantic Analysis for Casts -----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -400,11 +399,11 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT,
break;
}
- S.Diag(range.getBegin(), msg)
- << CT << srcType << destType
- << range << src->getSourceRange();
-
- candidates.NoteCandidates(S, howManyCandidates, src);
+ candidates.NoteCandidates(
+ PartialDiagnosticAt(range.getBegin(),
+ S.PDiag(msg) << CT << srcType << destType << range
+ << src->getSourceRange()),
+ S, howManyCandidates, src);
return true;
}
@@ -2213,7 +2212,15 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
/*CheckObjCLifetime=*/CStyle))
SuccessResult = getCastAwayConstnessCastKind(CACK, msg);
- if (IsLValueCast) {
+ if (IsAddressSpaceConversion(SrcType, DestType)) {
+ Kind = CK_AddressSpaceConversion;
+ assert(SrcType->isPointerType() && DestType->isPointerType());
+ if (!CStyle &&
+ !DestType->getPointeeType().getQualifiers().isAddressSpaceSupersetOf(
+ SrcType->getPointeeType().getQualifiers())) {
+ SuccessResult = TC_Failed;
+ }
+ } else if (IsLValueCast) {
Kind = CK_LValueBitCast;
} else if (DestType->isObjCObjectPointerType()) {
Kind = Self.PrepareCastToObjCObjectPointer(SrcExpr);
@@ -2223,8 +2230,6 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
} else {
Kind = CK_BitCast;
}
- } else if (IsAddressSpaceConversion(SrcType, DestType)) {
- Kind = CK_AddressSpaceConversion;
} else {
Kind = CK_BitCast;
}
@@ -2279,6 +2284,41 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
return SuccessResult;
}
+static TryCastResult TryAddressSpaceCast(Sema &Self, ExprResult &SrcExpr,
+ QualType DestType, bool CStyle,
+ unsigned &msg) {
+ if (!Self.getLangOpts().OpenCL)
+ // FIXME: As compiler doesn't have any information about overlapping addr
+ // spaces at the moment we have to be permissive here.
+ return TC_NotApplicable;
+ // Even though the logic below is general enough and can be applied to
+ // non-OpenCL mode too, we fast-path above because no other languages
+ // define overlapping address spaces currently.
+ auto SrcType = SrcExpr.get()->getType();
+ auto SrcPtrType = SrcType->getAs<PointerType>();
+ if (!SrcPtrType)
+ return TC_NotApplicable;
+ auto DestPtrType = DestType->getAs<PointerType>();
+ if (!DestPtrType)
+ return TC_NotApplicable;
+ auto SrcPointeeType = SrcPtrType->getPointeeType();
+ auto DestPointeeType = DestPtrType->getPointeeType();
+ if (SrcPointeeType.getAddressSpace() == DestPointeeType.getAddressSpace())
+ return TC_NotApplicable;
+ if (!DestPtrType->isAddressSpaceOverlapping(*SrcPtrType)) {
+ msg = diag::err_bad_cxx_cast_addr_space_mismatch;
+ return TC_Failed;
+ }
+ auto SrcPointeeTypeWithoutAS =
+ Self.Context.removeAddrSpaceQualType(SrcPointeeType.getCanonicalType());
+ auto DestPointeeTypeWithoutAS =
+ Self.Context.removeAddrSpaceQualType(DestPointeeType.getCanonicalType());
+ return Self.Context.hasSameType(SrcPointeeTypeWithoutAS,
+ DestPointeeTypeWithoutAS)
+ ? TC_Success
+ : TC_NotApplicable;
+}
+
void CastOperation::checkAddressSpaceCast(QualType SrcType, QualType DestType) {
// In OpenCL only conversions between pointers to objects in overlapping
// addr spaces are allowed. v2.0 s6.5.5 - Generic addr space overlaps
@@ -2373,30 +2413,35 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
// listed above, the interpretation that appears first in the list is used,
// even if a cast resulting from that interpretation is ill-formed.
// In plain language, this means trying a const_cast ...
+ // Note that for address space we check compatibility after const_cast.
unsigned msg = diag::err_bad_cxx_cast_generic;
TryCastResult tcr = TryConstCast(Self, SrcExpr, DestType,
- /*CStyle*/true, msg);
+ /*CStyle*/ true, msg);
if (SrcExpr.isInvalid())
return;
if (isValidCast(tcr))
Kind = CK_NoOp;
- Sema::CheckedConversionKind CCK
- = FunctionalStyle? Sema::CCK_FunctionalCast
- : Sema::CCK_CStyleCast;
+ Sema::CheckedConversionKind CCK =
+ FunctionalStyle ? Sema::CCK_FunctionalCast : Sema::CCK_CStyleCast;
if (tcr == TC_NotApplicable) {
- // ... or if that is not possible, a static_cast, ignoring const, ...
- tcr = TryStaticCast(Self, SrcExpr, DestType, CCK, OpRange,
- msg, Kind, BasePath, ListInitialization);
+ tcr = TryAddressSpaceCast(Self, SrcExpr, DestType, /*CStyle*/ true, msg);
if (SrcExpr.isInvalid())
return;
-
if (tcr == TC_NotApplicable) {
- // ... and finally a reinterpret_cast, ignoring const.
- tcr = TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/true,
- OpRange, msg, Kind);
+ // ... or if that is not possible, a static_cast, ignoring const, ...
+ tcr = TryStaticCast(Self, SrcExpr, DestType, CCK, OpRange, msg, Kind,
+ BasePath, ListInitialization);
if (SrcExpr.isInvalid())
return;
+
+ if (tcr == TC_NotApplicable) {
+ // ... and finally a reinterpret_cast, ignoring const.
+ tcr = TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/ true,
+ OpRange, msg, Kind);
+ if (SrcExpr.isInvalid())
+ return;
+ }
}
}
@@ -2427,8 +2472,6 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
}
}
- checkAddressSpaceCast(SrcExpr.get()->getType(), DestType);
-
if (isValidCast(tcr)) {
if (Kind == CK_BitCast)
checkCastAlign();