diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaCast.cpp | 46 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 25 |
2 files changed, 55 insertions, 16 deletions
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 21a4d107ba2..0958943f9ef 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -2323,19 +2323,41 @@ 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 // with any named one, except for constant. + + // Converting the top level pointee addrspace is permitted for compatible + // addrspaces (such as 'generic int *' to 'local int *' or vice versa), but + // if any of the nested pointee addrspaces differ, we emit a warning + // regardless of addrspace compatibility. This makes + // local int ** p; + // return (generic int **) p; + // warn even though local -> generic is permitted. if (Self.getLangOpts().OpenCL) { - auto SrcPtrType = SrcType->getAs<PointerType>(); - if (!SrcPtrType) - return; - auto DestPtrType = DestType->getAs<PointerType>(); - if (!DestPtrType) - return; - if (!DestPtrType->isAddressSpaceOverlapping(*SrcPtrType)) { - Self.Diag(OpRange.getBegin(), - diag::err_typecheck_incompatible_address_space) - << SrcType << DestType << Sema::AA_Casting - << SrcExpr.get()->getSourceRange(); - SrcExpr = ExprError(); + const Type *DestPtr, *SrcPtr; + bool Nested = false; + unsigned DiagID = diag::err_typecheck_incompatible_address_space; + DestPtr = Self.getASTContext().getCanonicalType(DestType.getTypePtr()), + SrcPtr = Self.getASTContext().getCanonicalType(SrcType.getTypePtr()); + + while (isa<PointerType>(DestPtr) && isa<PointerType>(SrcPtr)) { + const PointerType *DestPPtr = cast<PointerType>(DestPtr); + const PointerType *SrcPPtr = cast<PointerType>(SrcPtr); + QualType DestPPointee = DestPPtr->getPointeeType(); + QualType SrcPPointee = SrcPPtr->getPointeeType(); + if (Nested ? DestPPointee.getAddressSpace() != + SrcPPointee.getAddressSpace() + : !DestPPtr->isAddressSpaceOverlapping(*SrcPPtr)) { + Self.Diag(OpRange.getBegin(), DiagID) + << SrcType << DestType << Sema::AA_Casting + << SrcExpr.get()->getSourceRange(); + if (!Nested) + SrcExpr = ExprError(); + return; + } + + DestPtr = DestPPtr->getPointeeType().getTypePtr(); + SrcPtr = SrcPPtr->getPointeeType().getTypePtr(); + Nested = true; + DiagID = diag::ext_nested_pointer_qualifier_mismatch; } } } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index d8c08961471..8bb306e66d6 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7724,9 +7724,9 @@ checkPointerTypesForAssignment(Sema &S, QualType LHSType, QualType RHSType) { } if (!lhq.compatiblyIncludes(rhq)) { - // Treat address-space mismatches as fatal. TODO: address subspaces + // Treat address-space mismatches as fatal. if (!lhq.isAddressSpaceSupersetOf(rhq)) - ConvTy = Sema::IncompatiblePointerDiscardsQualifiers; + return Sema::IncompatiblePointerDiscardsQualifiers; // It's okay to add or remove GC or lifetime qualifiers when converting to // and from void*. @@ -7799,8 +7799,22 @@ checkPointerTypesForAssignment(Sema &S, QualType LHSType, QualType RHSType) { // level of indirection, this must be the issue. if (isa<PointerType>(lhptee) && isa<PointerType>(rhptee)) { do { - lhptee = cast<PointerType>(lhptee)->getPointeeType().getTypePtr(); - rhptee = cast<PointerType>(rhptee)->getPointeeType().getTypePtr(); + std::tie(lhptee, lhq) = + cast<PointerType>(lhptee)->getPointeeType().split().asPair(); + std::tie(rhptee, rhq) = + cast<PointerType>(rhptee)->getPointeeType().split().asPair(); + + // Inconsistent address spaces at this point is invalid, even if the + // address spaces would be compatible. + // FIXME: This doesn't catch address space mismatches for pointers of + // different nesting levels, like: + // __local int *** a; + // int ** b = a; + // It's not clear how to actually determine when such pointers are + // invalidly incompatible. + if (lhq.getAddressSpace() != rhq.getAddressSpace()) + return Sema::IncompatibleNestedPointerAddressSpaceMismatch; + } while (isa<PointerType>(lhptee) && isa<PointerType>(rhptee)); if (lhptee == rhptee) @@ -14213,6 +14227,9 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, case IncompatibleNestedPointerQualifiers: DiagKind = diag::ext_nested_pointer_qualifier_mismatch; break; + case IncompatibleNestedPointerAddressSpaceMismatch: + DiagKind = diag::err_typecheck_incompatible_nested_address_space; + break; case IntToBlockPointer: DiagKind = diag::err_int_to_block_pointer; break; |