diff options
| author | Anastasia Stulova <anastasia.stulova@arm.com> | 2017-03-10 15:23:07 +0000 |
|---|---|---|
| committer | Anastasia Stulova <anastasia.stulova@arm.com> | 2017-03-10 15:23:07 +0000 |
| commit | 81a25e352f9e59ac9e5acb1185bd1bc68d6e783d (patch) | |
| tree | e334055423dfa329b1bc8c86622efcada6f1b194 /clang/lib/Sema | |
| parent | 0ef8ee19f8fe2bd295a0980e3265f032cfead5fd (diff) | |
| download | bcm5719-llvm-81a25e352f9e59ac9e5acb1185bd1bc68d6e783d.tar.gz bcm5719-llvm-81a25e352f9e59ac9e5acb1185bd1bc68d6e783d.zip | |
[OpenCL] Fix type compatibility check and generic AS mangling.
1. Reimplemented conditional operator so that it checks
compatibility of unqualified pointees of the 2nd and
the 3rd operands (C99, OpenCL v2.0 6.5.15).
Define QualTypes compatibility for OpenCL as following:
- corresponding types are compatible (C99 6.7.3)
- CVR-qualifiers are equal (C99 6.7.3)
- address spaces are equal (implementation defined)
2. Added generic address space to Itanium mangling.
Review: D30037
Patch by Dmitry Borisenkov!
llvm-svn: 297468
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 147 |
1 files changed, 84 insertions, 63 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index e422fe02263..88f32bb6b3b 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6335,92 +6335,98 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS, Qualifiers lhQual = lhptee.getQualifiers(); Qualifiers rhQual = rhptee.getQualifiers(); + unsigned ResultAddrSpace = 0; + unsigned LAddrSpace = lhQual.getAddressSpace(); + unsigned RAddrSpace = rhQual.getAddressSpace(); + if (S.getLangOpts().OpenCL) { + // OpenCL v1.1 s6.5 - Conversion between pointers to distinct address + // spaces is disallowed. + if (lhQual.isAddressSpaceSupersetOf(rhQual)) + ResultAddrSpace = LAddrSpace; + else if (rhQual.isAddressSpaceSupersetOf(lhQual)) + ResultAddrSpace = RAddrSpace; + else { + S.Diag(Loc, + diag::err_typecheck_op_on_nonoverlapping_address_space_pointers) + << LHSTy << RHSTy << 2 << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); + return QualType(); + } + } + unsigned MergedCVRQual = lhQual.getCVRQualifiers() | rhQual.getCVRQualifiers(); + auto LHSCastKind = CK_BitCast, RHSCastKind = CK_BitCast; lhQual.removeCVRQualifiers(); rhQual.removeCVRQualifiers(); + // OpenCL v2.0 specification doesn't extend compatibility of type qualifiers + // (C99 6.7.3) for address spaces. We assume that the check should behave in + // the same manner as it's defined for CVR qualifiers, so for OpenCL two + // qual types are compatible iff + // * corresponded types are compatible + // * CVR qualifiers are equal + // * address spaces are equal + // Thus for conditional operator we merge CVR and address space unqualified + // pointees and if there is a composite type we return a pointer to it with + // merged qualifiers. + if (S.getLangOpts().OpenCL) { + LHSCastKind = LAddrSpace == ResultAddrSpace + ? CK_BitCast + : CK_AddressSpaceConversion; + RHSCastKind = RAddrSpace == ResultAddrSpace + ? CK_BitCast + : CK_AddressSpaceConversion; + lhQual.removeAddressSpace(); + rhQual.removeAddressSpace(); + } + 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()) { // 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; - 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); - } + incompatTy = S.Context.getPointerType( + S.Context.getAddrSpaceQualType(S.Context.VoidTy, ResultAddrSpace)); + LHS = S.ImpCastExprToType(LHS.get(), incompatTy, LHSCastKind); + RHS = S.ImpCastExprToType(RHS.get(), incompatTy, RHSCastKind); + // FIXME: For OpenCL the warning emission and cast to void* leaves a room + // for casts between types with incompatible address space qualifiers. + // For the following code the compiler produces casts between global and + // local address spaces of the corresponded innermost pointees: + // local int *global *a; + // global int *global *b; + // a = (0 ? a : b); // see C99 6.5.16.1.p1. + S.Diag(Loc, diag::ext_typecheck_cond_incompatible_pointers) + << LHSTy << RHSTy << LHS.get()->getSourceRange() + << RHS.get()->getSourceRange(); return incompatTy; } // The pointer types are compatible. - QualType ResultTy = CompositeTy.withCVRQualifiers(MergedCVRQual); - auto LHSCastKind = CK_BitCast, RHSCastKind = CK_BitCast; + // In case of OpenCL ResultTy should have the address space qualifier + // which is a superset of address spaces of both the 2nd and the 3rd + // operands of the conditional operator. + QualType ResultTy = [&, ResultAddrSpace]() { + if (S.getLangOpts().OpenCL) { + Qualifiers CompositeQuals = CompositeTy.getQualifiers(); + CompositeQuals.setAddressSpace(ResultAddrSpace); + return S.Context + .getQualifiedType(CompositeTy.getUnqualifiedType(), CompositeQuals) + .withCVRQualifiers(MergedCVRQual); + } else + return CompositeTy.withCVRQualifiers(MergedCVRQual); + }(); if (IsBlockPointer) ResultTy = S.Context.getBlockPointerType(ResultTy); 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); } - // 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; @@ -7399,7 +7405,22 @@ checkBlockPointerTypesForAssignment(Sema &S, QualType LHSType, if (LQuals != RQuals) ConvTy = Sema::CompatiblePointerDiscardsQualifiers; - if (!S.Context.typesAreBlockPointerCompatible(LHSType, RHSType)) + // FIXME: OpenCL doesn't define the exact compile time semantics for a block + // assignment. + // The current behavior is similar to C++ lambdas. A block might be + // assigned to a variable iff its return type and parameters are compatible + // (C99 6.2.7) with the corresponding return type and parameters of the LHS of + // an assignment. Presumably it should behave in way that a function pointer + // assignment does in C, so for each parameter and return type: + // * CVR and address space of LHS should be a superset of CVR and address + // space of RHS. + // * unqualified types should be compatible. + if (S.getLangOpts().OpenCL) { + if (!S.Context.typesAreBlockPointerCompatible( + S.Context.getQualifiedType(LHSType.getUnqualifiedType(), LQuals), + S.Context.getQualifiedType(RHSType.getUnqualifiedType(), RQuals))) + return Sema::IncompatibleBlockPointer; + } else if (!S.Context.typesAreBlockPointerCompatible(LHSType, RHSType)) return Sema::IncompatibleBlockPointer; return ConvTy; |

