forked from OSchip/llvm-project
[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
This commit is contained in:
parent
0ef8ee19f8
commit
81a25e352f
|
@ -8066,15 +8066,6 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
|
||||||
Qualifiers LQuals = LHSCan.getLocalQualifiers();
|
Qualifiers LQuals = LHSCan.getLocalQualifiers();
|
||||||
Qualifiers RQuals = RHSCan.getLocalQualifiers();
|
Qualifiers RQuals = RHSCan.getLocalQualifiers();
|
||||||
if (LQuals != RQuals) {
|
if (LQuals != RQuals) {
|
||||||
if (getLangOpts().OpenCL) {
|
|
||||||
if (LHSCan.getUnqualifiedType() != RHSCan.getUnqualifiedType() ||
|
|
||||||
LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers())
|
|
||||||
return QualType();
|
|
||||||
if (LQuals.isAddressSpaceSupersetOf(RQuals))
|
|
||||||
return LHS;
|
|
||||||
if (RQuals.isAddressSpaceSupersetOf(LQuals))
|
|
||||||
return RHS;
|
|
||||||
}
|
|
||||||
// If any of these qualifiers are different, we have a type
|
// If any of these qualifiers are different, we have a type
|
||||||
// mismatch.
|
// mismatch.
|
||||||
if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() ||
|
if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() ||
|
||||||
|
@ -8200,6 +8191,20 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
|
||||||
LHSPointee = LHSPointee.getUnqualifiedType();
|
LHSPointee = LHSPointee.getUnqualifiedType();
|
||||||
RHSPointee = RHSPointee.getUnqualifiedType();
|
RHSPointee = RHSPointee.getUnqualifiedType();
|
||||||
}
|
}
|
||||||
|
if (getLangOpts().OpenCL) {
|
||||||
|
Qualifiers LHSPteeQual = LHSPointee.getQualifiers();
|
||||||
|
Qualifiers RHSPteeQual = RHSPointee.getQualifiers();
|
||||||
|
// Blocks can't be an expression in a ternary operator (OpenCL v2.0
|
||||||
|
// 6.12.5) thus the following check is asymmetric.
|
||||||
|
if (!LHSPteeQual.isAddressSpaceSupersetOf(RHSPteeQual))
|
||||||
|
return QualType();
|
||||||
|
LHSPteeQual.removeAddressSpace();
|
||||||
|
RHSPteeQual.removeAddressSpace();
|
||||||
|
LHSPointee =
|
||||||
|
QualType(LHSPointee.getTypePtr(), LHSPteeQual.getAsOpaqueValue());
|
||||||
|
RHSPointee =
|
||||||
|
QualType(RHSPointee.getTypePtr(), RHSPteeQual.getAsOpaqueValue());
|
||||||
|
}
|
||||||
QualType ResultType = mergeTypes(LHSPointee, RHSPointee, OfBlockPointer,
|
QualType ResultType = mergeTypes(LHSPointee, RHSPointee, OfBlockPointer,
|
||||||
Unqualified);
|
Unqualified);
|
||||||
if (ResultType.isNull()) return QualType();
|
if (ResultType.isNull()) return QualType();
|
||||||
|
|
|
@ -2159,10 +2159,12 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals) {
|
||||||
} else {
|
} else {
|
||||||
switch (AS) {
|
switch (AS) {
|
||||||
default: llvm_unreachable("Not a language specific address space");
|
default: llvm_unreachable("Not a language specific address space");
|
||||||
// <OpenCL-addrspace> ::= "CL" [ "global" | "local" | "constant" ]
|
// <OpenCL-addrspace> ::= "CL" [ "global" | "local" | "constant |
|
||||||
|
// "generic" ]
|
||||||
case LangAS::opencl_global: ASString = "CLglobal"; break;
|
case LangAS::opencl_global: ASString = "CLglobal"; break;
|
||||||
case LangAS::opencl_local: ASString = "CLlocal"; break;
|
case LangAS::opencl_local: ASString = "CLlocal"; break;
|
||||||
case LangAS::opencl_constant: ASString = "CLconstant"; break;
|
case LangAS::opencl_constant: ASString = "CLconstant"; break;
|
||||||
|
case LangAS::opencl_generic: ASString = "CLgeneric"; break;
|
||||||
// <CUDA-addrspace> ::= "CU" [ "device" | "constant" | "shared" ]
|
// <CUDA-addrspace> ::= "CU" [ "device" | "constant" | "shared" ]
|
||||||
case LangAS::cuda_device: ASString = "CUdevice"; break;
|
case LangAS::cuda_device: ASString = "CUdevice"; break;
|
||||||
case LangAS::cuda_constant: ASString = "CUconstant"; break;
|
case LangAS::cuda_constant: ASString = "CUconstant"; break;
|
||||||
|
|
|
@ -6335,92 +6335,98 @@ static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
|
||||||
Qualifiers lhQual = lhptee.getQualifiers();
|
Qualifiers lhQual = lhptee.getQualifiers();
|
||||||
Qualifiers rhQual = rhptee.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();
|
unsigned MergedCVRQual = lhQual.getCVRQualifiers() | rhQual.getCVRQualifiers();
|
||||||
|
auto LHSCastKind = CK_BitCast, RHSCastKind = CK_BitCast;
|
||||||
lhQual.removeCVRQualifiers();
|
lhQual.removeCVRQualifiers();
|
||||||
rhQual.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);
|
lhptee = S.Context.getQualifiedType(lhptee.getUnqualifiedType(), lhQual);
|
||||||
rhptee = S.Context.getQualifiedType(rhptee.getUnqualifiedType(), rhQual);
|
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);
|
QualType CompositeTy = S.Context.mergeTypes(lhptee, rhptee);
|
||||||
|
|
||||||
// OpenCL cases 1c, 2a, 2b, and 2c.
|
|
||||||
if (CompositeTy.isNull()) {
|
if (CompositeTy.isNull()) {
|
||||||
// In this situation, we assume void* type. No especially good
|
// In this situation, we assume void* type. No especially good
|
||||||
// reason, but this is what gcc does, and we do have to pick
|
// reason, but this is what gcc does, and we do have to pick
|
||||||
// to get a consistent AST.
|
// to get a consistent AST.
|
||||||
QualType incompatTy;
|
QualType incompatTy;
|
||||||
if (S.getLangOpts().OpenCL) {
|
incompatTy = S.Context.getPointerType(
|
||||||
// OpenCL v1.1 s6.5 - Conversion between pointers to distinct address
|
S.Context.getAddrSpaceQualType(S.Context.VoidTy, ResultAddrSpace));
|
||||||
// spaces is disallowed.
|
LHS = S.ImpCastExprToType(LHS.get(), incompatTy, LHSCastKind);
|
||||||
unsigned ResultAddrSpace;
|
RHS = S.ImpCastExprToType(RHS.get(), incompatTy, RHSCastKind);
|
||||||
if (lhQual.isAddressSpaceSupersetOf(rhQual)) {
|
// FIXME: For OpenCL the warning emission and cast to void* leaves a room
|
||||||
// Cases 2a and 2b.
|
// for casts between types with incompatible address space qualifiers.
|
||||||
ResultAddrSpace = lhQual.getAddressSpace();
|
// For the following code the compiler produces casts between global and
|
||||||
} else if (rhQual.isAddressSpaceSupersetOf(lhQual)) {
|
// local address spaces of the corresponded innermost pointees:
|
||||||
// Cases 2a and 2b.
|
// local int *global *a;
|
||||||
ResultAddrSpace = rhQual.getAddressSpace();
|
// global int *global *b;
|
||||||
} else {
|
// a = (0 ? a : b); // see C99 6.5.16.1.p1.
|
||||||
// Cases 1c and 2c.
|
S.Diag(Loc, diag::ext_typecheck_cond_incompatible_pointers)
|
||||||
S.Diag(Loc,
|
<< LHSTy << RHSTy << LHS.get()->getSourceRange()
|
||||||
diag::err_typecheck_op_on_nonoverlapping_address_space_pointers)
|
<< RHS.get()->getSourceRange();
|
||||||
<< 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;
|
return incompatTy;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The pointer types are compatible.
|
// The pointer types are compatible.
|
||||||
QualType ResultTy = CompositeTy.withCVRQualifiers(MergedCVRQual);
|
// In case of OpenCL ResultTy should have the address space qualifier
|
||||||
auto LHSCastKind = CK_BitCast, RHSCastKind = CK_BitCast;
|
// 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)
|
if (IsBlockPointer)
|
||||||
ResultTy = S.Context.getBlockPointerType(ResultTy);
|
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);
|
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);
|
LHS = S.ImpCastExprToType(LHS.get(), ResultTy, LHSCastKind);
|
||||||
RHS = S.ImpCastExprToType(RHS.get(), ResultTy, RHSCastKind);
|
RHS = S.ImpCastExprToType(RHS.get(), ResultTy, RHSCastKind);
|
||||||
return ResultTy;
|
return ResultTy;
|
||||||
|
@ -7399,7 +7405,22 @@ checkBlockPointerTypesForAssignment(Sema &S, QualType LHSType,
|
||||||
if (LQuals != RQuals)
|
if (LQuals != RQuals)
|
||||||
ConvTy = Sema::CompatiblePointerDiscardsQualifiers;
|
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 Sema::IncompatibleBlockPointer;
|
||||||
|
|
||||||
return ConvTy;
|
return ConvTy;
|
||||||
|
|
|
@ -18,14 +18,20 @@
|
||||||
|
|
||||||
#ifdef GENERIC
|
#ifdef GENERIC
|
||||||
#define AS generic
|
#define AS generic
|
||||||
|
#define AS_COMP local
|
||||||
|
#define AS_INCOMP constant
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef GLOBAL
|
#ifdef GLOBAL
|
||||||
#define AS global
|
#define AS global
|
||||||
|
#define AS_COMP global
|
||||||
|
#define AS_INCOMP local
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONSTANT
|
#ifdef CONSTANT
|
||||||
#define AS constant
|
#define AS constant
|
||||||
|
#define AS_COMP constant
|
||||||
|
#define AS_INCOMP global
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void f_glob(global int *arg_glob) {}
|
void f_glob(global int *arg_glob) {}
|
||||||
|
@ -263,12 +269,16 @@ void test_ternary() {
|
||||||
var_void_gen = 0 ? var_cond : var_glob_ch;
|
var_void_gen = 0 ? var_cond : var_glob_ch;
|
||||||
#ifdef CONSTANT
|
#ifdef CONSTANT
|
||||||
// expected-error@-2{{conditional operator with the second and third operands of type ('__constant int *' and '__global char *') which are pointers to non-overlapping address spaces}}
|
// expected-error@-2{{conditional operator with the second and third operands of type ('__constant int *' and '__global char *') which are pointers to non-overlapping address spaces}}
|
||||||
|
#else
|
||||||
|
// expected-warning-re@-4{{pointer type mismatch ('__{{global|generic}} int *' and '__global char *')}}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
local char *var_loc_ch;
|
local char *var_loc_ch;
|
||||||
var_void_gen = 0 ? var_cond : var_loc_ch;
|
var_void_gen = 0 ? var_cond : var_loc_ch;
|
||||||
#ifndef GENERIC
|
#ifndef GENERIC
|
||||||
// expected-error-re@-2{{conditional operator with the second and third operands of type ('__{{global|constant}} int *' and '__local char *') which are pointers to non-overlapping address spaces}}
|
// expected-error-re@-2{{conditional operator with the second and third operands of type ('__{{global|constant}} int *' and '__local char *') which are pointers to non-overlapping address spaces}}
|
||||||
|
#else
|
||||||
|
// expected-warning@-4{{pointer type mismatch ('__generic int *' and '__local char *')}}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
constant void *var_void_const;
|
constant void *var_void_const;
|
||||||
|
@ -276,18 +286,45 @@ void test_ternary() {
|
||||||
var_void_const = 0 ? var_cond : var_const_ch;
|
var_void_const = 0 ? var_cond : var_const_ch;
|
||||||
#ifndef CONSTANT
|
#ifndef CONSTANT
|
||||||
// expected-error-re@-2{{conditional operator with the second and third operands of type ('__{{global|generic}} int *' and '__constant char *') which are pointers to non-overlapping address spaces}}
|
// expected-error-re@-2{{conditional operator with the second and third operands of type ('__{{global|generic}} int *' and '__constant char *') which are pointers to non-overlapping address spaces}}
|
||||||
|
#else
|
||||||
|
// expected-warning@-4{{pointer type mismatch ('__constant int *' and '__constant char *')}}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private char *var_priv_ch;
|
private char *var_priv_ch;
|
||||||
var_void_gen = 0 ? var_cond : var_priv_ch;
|
var_void_gen = 0 ? var_cond : var_priv_ch;
|
||||||
#ifndef GENERIC
|
#ifndef GENERIC
|
||||||
// expected-error-re@-2{{conditional operator with the second and third operands of type ('__{{global|constant}} int *' and 'char *') which are pointers to non-overlapping address spaces}}
|
// expected-error-re@-2{{conditional operator with the second and third operands of type ('__{{global|constant}} int *' and 'char *') which are pointers to non-overlapping address spaces}}
|
||||||
|
#else
|
||||||
|
// expected-warning@-4{{pointer type mismatch ('__generic int *' and 'char *')}}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
generic char *var_gen_ch;
|
generic char *var_gen_ch;
|
||||||
var_void_gen = 0 ? var_cond : var_gen_ch;
|
var_void_gen = 0 ? var_cond : var_gen_ch;
|
||||||
#ifdef CONSTANT
|
#ifdef CONSTANT
|
||||||
// expected-error@-2{{conditional operator with the second and third operands of type ('__constant int *' and '__generic char *') which are pointers to non-overlapping address spaces}}
|
// expected-error@-2{{conditional operator with the second and third operands of type ('__constant int *' and '__generic char *') which are pointers to non-overlapping address spaces}}
|
||||||
|
#else
|
||||||
|
// expected-warning-re@-4{{pointer type mismatch ('__{{global|generic}} int *' and '__generic char *')}}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_pointer_chains() {
|
||||||
|
AS int *AS *var_as_as_int;
|
||||||
|
AS int *AS_COMP *var_asc_as_int;
|
||||||
|
AS_INCOMP int *AS_COMP *var_asc_asn_int;
|
||||||
|
AS_COMP int *AS_COMP *var_asc_asc_int;
|
||||||
|
|
||||||
|
// Case 1:
|
||||||
|
// * address spaces of corresponded most outer pointees overlaps, their canonical types are equal
|
||||||
|
// * CVR, address spaces and canonical types of the rest of pointees are equivalent.
|
||||||
|
var_as_as_int = 0 ? var_as_as_int : var_asc_as_int;
|
||||||
|
|
||||||
|
// Case 2: Corresponded inner pointees has non-overlapping address spaces.
|
||||||
|
var_as_as_int = 0 ? var_as_as_int : var_asc_asn_int;
|
||||||
|
// expected-warning-re@-1{{pointer type mismatch ('__{{(generic|global|constant)}} int *__{{(generic|global|constant)}} *' and '__{{(local|global|constant)}} int *__{{(constant|local|global)}} *')}}
|
||||||
|
|
||||||
|
// Case 3: Corresponded inner pointees has overlapping but not equivalent address spaces.
|
||||||
|
#ifdef GENERIC
|
||||||
|
var_as_as_int = 0 ? var_as_as_int : var_asc_asc_int;
|
||||||
|
// expected-warning-re@-1{{pointer type mismatch ('__{{(generic|global|constant)}} int *__{{(generic|global|constant)}} *' and '__{{(local|global|constant)}} int *__{{(local|global|constant)}} *')}}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
// RUN: %clang_cc1 -cl-std=CL2.0 -emit-llvm -o - %s | FileCheck %s
|
||||||
|
|
||||||
|
void __attribute__((overloadable)) foo(global int *a, global int *b);
|
||||||
|
void __attribute__((overloadable)) foo(generic int *a, generic int *b);
|
||||||
|
void __attribute__((overloadable)) bar(generic int *global *a, generic int *global *b);
|
||||||
|
void __attribute__((overloadable)) bar(generic int *generic *a, generic int *generic *b);
|
||||||
|
|
||||||
|
void kernel ker() {
|
||||||
|
global int *a;
|
||||||
|
global int *b;
|
||||||
|
generic int *c;
|
||||||
|
local int *d;
|
||||||
|
generic int *generic *gengen;
|
||||||
|
generic int *local *genloc;
|
||||||
|
generic int *global *genglob;
|
||||||
|
// CHECK: call void @_Z3fooPU8CLglobaliS0_(i32* undef, i32* undef)
|
||||||
|
foo(a, b);
|
||||||
|
// CHECK: call void @_Z3fooPU9CLgenericiS0_(i32* undef, i32* undef)
|
||||||
|
foo(b, c);
|
||||||
|
// CHECK: call void @_Z3fooPU9CLgenericiS0_(i32* undef, i32* undef)
|
||||||
|
foo(a, d);
|
||||||
|
|
||||||
|
// CHECK: call void @_Z3barPU9CLgenericPU9CLgenericiS2_(i32** undef, i32** undef)
|
||||||
|
bar(gengen, genloc);
|
||||||
|
// CHECK: call void @_Z3barPU9CLgenericPU9CLgenericiS2_(i32** undef, i32** undef)
|
||||||
|
bar(gengen, genglob);
|
||||||
|
// CHECK: call void @_Z3barPU8CLglobalPU9CLgenericiS2_(i32** undef, i32** undef)
|
||||||
|
bar(genglob, genglob);
|
||||||
|
}
|
Loading…
Reference in New Issue