diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 75 |
1 files changed, 66 insertions, 9 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 32e189a843e..561e4777e6a 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6193,30 +6193,87 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS, lhptee = S.Context.getQualifiedType(lhptee.getUnqualifiedType(), lhQual); rhptee = S.Context.getQualifiedType(rhptee.getUnqualifiedType(), rhQual); + // For OpenCL: + // 1. If LHS and RHS types match exactly and: + // (a) AS match => use standard C rules, no bitcast or addrspacecast + // (b) AS overlap => generate addrspacecast + // (c) AS don't overlap => give an error + // 2. if LHS and RHS types don't match: + // (a) AS match => use standard C rules, generate bitcast + // (b) AS overlap => generate addrspacecast instead of bitcast + // (c) AS don't overlap => give an error + + // For OpenCL, non-null composite type is returned only for cases 1a and 1b. QualType CompositeTy = S.Context.mergeTypes(lhptee, rhptee); + // OpenCL cases 1c, 2a, 2b, and 2c. if (CompositeTy.isNull()) { - S.Diag(Loc, diag::ext_typecheck_cond_incompatible_pointers) - << LHSTy << RHSTy << LHS.get()->getSourceRange() - << RHS.get()->getSourceRange(); // In this situation, we assume void* type. No especially good // reason, but this is what gcc does, and we do have to pick // to get a consistent AST. - QualType incompatTy = S.Context.getPointerType(S.Context.VoidTy); - LHS = S.ImpCastExprToType(LHS.get(), incompatTy, CK_BitCast); - RHS = S.ImpCastExprToType(RHS.get(), incompatTy, CK_BitCast); + QualType incompatTy; + if (S.getLangOpts().OpenCL) { + // OpenCL v1.1 s6.5 - Conversion between pointers to distinct address + // spaces is disallowed. + unsigned ResultAddrSpace; + if (lhQual.isAddressSpaceSupersetOf(rhQual)) { + // Cases 2a and 2b. + ResultAddrSpace = lhQual.getAddressSpace(); + } else if (rhQual.isAddressSpaceSupersetOf(lhQual)) { + // Cases 2a and 2b. + ResultAddrSpace = rhQual.getAddressSpace(); + } else { + // Cases 1c and 2c. + S.Diag(Loc, + diag::err_typecheck_op_on_nonoverlapping_address_space_pointers) + << LHSTy << RHSTy << 2 << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + return QualType(); + } + + // Continue handling cases 2a and 2b. + incompatTy = S.Context.getPointerType( + S.Context.getAddrSpaceQualType(S.Context.VoidTy, ResultAddrSpace)); + LHS = S.ImpCastExprToType(LHS.get(), incompatTy, + (lhQual.getAddressSpace() != ResultAddrSpace) + ? CK_AddressSpaceConversion /* 2b */ + : CK_BitCast /* 2a */); + RHS = S.ImpCastExprToType(RHS.get(), incompatTy, + (rhQual.getAddressSpace() != ResultAddrSpace) + ? CK_AddressSpaceConversion /* 2b */ + : CK_BitCast /* 2a */); + } else { + S.Diag(Loc, diag::ext_typecheck_cond_incompatible_pointers) + << LHSTy << RHSTy << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + incompatTy = S.Context.getPointerType(S.Context.VoidTy); + LHS = S.ImpCastExprToType(LHS.get(), incompatTy, CK_BitCast); + RHS = S.ImpCastExprToType(RHS.get(), incompatTy, CK_BitCast); + } return incompatTy; } // The pointer types are compatible. QualType ResultTy = CompositeTy.withCVRQualifiers(MergedCVRQual); + auto LHSCastKind = CK_BitCast, RHSCastKind = CK_BitCast; if (IsBlockPointer) ResultTy = S.Context.getBlockPointerType(ResultTy); - else + else { + // Cases 1a and 1b for OpenCL. + auto ResultAddrSpace = ResultTy.getQualifiers().getAddressSpace(); + LHSCastKind = lhQual.getAddressSpace() == ResultAddrSpace + ? CK_BitCast /* 1a */ + : CK_AddressSpaceConversion /* 1b */; + RHSCastKind = rhQual.getAddressSpace() == ResultAddrSpace + ? CK_BitCast /* 1a */ + : CK_AddressSpaceConversion /* 1b */; ResultTy = S.Context.getPointerType(ResultTy); + } - LHS = S.ImpCastExprToType(LHS.get(), ResultTy, CK_BitCast); - RHS = S.ImpCastExprToType(RHS.get(), ResultTy, CK_BitCast); + // For case 1a of OpenCL, S.ImpCastExprToType will not insert bitcast + // if the target type does not change. + LHS = S.ImpCastExprToType(LHS.get(), ResultTy, LHSCastKind); + RHS = S.ImpCastExprToType(RHS.get(), ResultTy, RHSCastKind); return ResultTy; } |