Skip to content

Commit a29aa47

Browse files
author
Anastasia Stulova
committed
[OpenCL] Move addr space deduction to Sema.
In order to simplify implementation we are moving add space deduction into Sema while constructing variable declaration and on template instantiation. Pointee are deduced to generic addr space during creation of types. This commit also - fixed addr space dedution for auto type; - factors out in a separate helper function OpenCL specific logic from type diagnostics in var decl. Tags: #clang Differential Revision: https://reviews.llvm.org/D65744
1 parent 3edf2eb commit a29aa47

File tree

15 files changed

+236
-257
lines changed

15 files changed

+236
-257
lines changed

clang/include/clang/AST/Type.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2069,6 +2069,8 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
20692069
bool isAlignValT() const; // C++17 std::align_val_t
20702070
bool isStdByteType() const; // C++17 std::byte
20712071
bool isAtomicType() const; // C11 _Atomic()
2072+
bool isUndeducedAutoType() const; // C++11 auto or
2073+
// C++14 decltype(auto)
20722074

20732075
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
20742076
bool is##Id##Type() const;
@@ -6509,6 +6511,10 @@ inline bool Type::isAtomicType() const {
65096511
return isa<AtomicType>(CanonicalType);
65106512
}
65116513

6514+
inline bool Type::isUndeducedAutoType() const {
6515+
return isa<AutoType>(CanonicalType);
6516+
}
6517+
65126518
inline bool Type::isObjCQualifiedIdType() const {
65136519
if (const auto *OPT = getAs<ObjCObjectPointerType>())
65146520
return OPT->isObjCQualifiedIdType();

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8760,6 +8760,8 @@ class Sema final {
87608760
bool CheckARCMethodDecl(ObjCMethodDecl *method);
87618761
bool inferObjCARCLifetime(ValueDecl *decl);
87628762

8763+
void deduceOpenCLAddressSpace(ValueDecl *decl);
8764+
87638765
ExprResult
87648766
HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
87658767
Expr *BaseExpr,

clang/lib/AST/Expr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1814,7 +1814,7 @@ bool CastExpr::CastConsistency() const {
18141814
auto Ty = getType();
18151815
auto SETy = getSubExpr()->getType();
18161816
assert(getValueKindForType(Ty) == Expr::getValueKindForType(SETy));
1817-
if (/*isRValue()*/ !Ty->getPointeeType().isNull()) {
1817+
if (isRValue()) {
18181818
Ty = Ty->getPointeeType();
18191819
SETy = SETy->getPointeeType();
18201820
}

clang/lib/Sema/SemaDecl.cpp

Lines changed: 129 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -6117,6 +6117,22 @@ bool Sema::inferObjCARCLifetime(ValueDecl *decl) {
61176117
return false;
61186118
}
61196119

6120+
void Sema::deduceOpenCLAddressSpace(ValueDecl *Decl) {
6121+
if (Decl->getType().getQualifiers().hasAddressSpace())
6122+
return;
6123+
if (VarDecl *Var = dyn_cast<VarDecl>(Decl)) {
6124+
QualType Type = Var->getType();
6125+
if (Type->isSamplerT() || Type->isVoidType())
6126+
return;
6127+
LangAS ImplAS = LangAS::opencl_private;
6128+
if ((getLangOpts().OpenCLCPlusPlus || getLangOpts().OpenCLVersion >= 200) &&
6129+
Var->hasGlobalStorage())
6130+
ImplAS = LangAS::opencl_global;
6131+
Type = Context.getAddrSpaceQualType(Type, ImplAS);
6132+
Decl->setType(Type);
6133+
}
6134+
}
6135+
61206136
static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
61216137
// Ensure that an auto decl is deduced otherwise the checks below might cache
61226138
// the wrong linkage.
@@ -6474,6 +6490,105 @@ static bool isDeclExternC(const Decl *D) {
64746490

64756491
llvm_unreachable("Unknown type of decl!");
64766492
}
6493+
/// Returns true if there hasn't been any invalid type diagnosed.
6494+
static bool diagnoseOpenCLTypes(Scope *S, Sema &Se, Declarator &D,
6495+
DeclContext *DC, QualType R) {
6496+
// OpenCL v2.0 s6.9.b - Image type can only be used as a function argument.
6497+
// OpenCL v2.0 s6.13.16.1 - Pipe type can only be used as a function
6498+
// argument.
6499+
if (R->isImageType() || R->isPipeType()) {
6500+
Se.Diag(D.getIdentifierLoc(),
6501+
diag::err_opencl_type_can_only_be_used_as_function_parameter)
6502+
<< R;
6503+
D.setInvalidType();
6504+
return false;
6505+
}
6506+
6507+
// OpenCL v1.2 s6.9.r:
6508+
// The event type cannot be used to declare a program scope variable.
6509+
// OpenCL v2.0 s6.9.q:
6510+
// The clk_event_t and reserve_id_t types cannot be declared in program
6511+
// scope.
6512+
if (NULL == S->getParent()) {
6513+
if (R->isReserveIDT() || R->isClkEventT() || R->isEventT()) {
6514+
Se.Diag(D.getIdentifierLoc(),
6515+
diag::err_invalid_type_for_program_scope_var)
6516+
<< R;
6517+
D.setInvalidType();
6518+
return false;
6519+
}
6520+
}
6521+
6522+
// OpenCL v1.0 s6.8.a.3: Pointers to functions are not allowed.
6523+
QualType NR = R;
6524+
while (NR->isPointerType()) {
6525+
if (NR->isFunctionPointerType()) {
6526+
Se.Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer);
6527+
D.setInvalidType();
6528+
return false;
6529+
}
6530+
NR = NR->getPointeeType();
6531+
}
6532+
6533+
if (!Se.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
6534+
// OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and
6535+
// half array type (unless the cl_khr_fp16 extension is enabled).
6536+
if (Se.Context.getBaseElementType(R)->isHalfType()) {
6537+
Se.Diag(D.getIdentifierLoc(), diag::err_opencl_half_declaration) << R;
6538+
D.setInvalidType();
6539+
return false;
6540+
}
6541+
}
6542+
6543+
// OpenCL v1.2 s6.9.r:
6544+
// The event type cannot be used with the __local, __constant and __global
6545+
// address space qualifiers.
6546+
if (R->isEventT()) {
6547+
if (R.getAddressSpace() != LangAS::opencl_private) {
6548+
Se.Diag(D.getBeginLoc(), diag::err_event_t_addr_space_qual);
6549+
D.setInvalidType();
6550+
return false;
6551+
}
6552+
}
6553+
6554+
// C++ for OpenCL does not allow the thread_local storage qualifier.
6555+
// OpenCL C does not support thread_local either, and
6556+
// also reject all other thread storage class specifiers.
6557+
DeclSpec::TSCS TSC = D.getDeclSpec().getThreadStorageClassSpec();
6558+
if (TSC != TSCS_unspecified) {
6559+
bool IsCXX = Se.getLangOpts().OpenCLCPlusPlus;
6560+
Se.Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
6561+
diag::err_opencl_unknown_type_specifier)
6562+
<< IsCXX << Se.getLangOpts().getOpenCLVersionTuple().getAsString()
6563+
<< DeclSpec::getSpecifierName(TSC) << 1;
6564+
D.setInvalidType();
6565+
return false;
6566+
}
6567+
6568+
if (R->isSamplerT()) {
6569+
// OpenCL v1.2 s6.9.b p4:
6570+
// The sampler type cannot be used with the __local and __global address
6571+
// space qualifiers.
6572+
if (R.getAddressSpace() == LangAS::opencl_local ||
6573+
R.getAddressSpace() == LangAS::opencl_global) {
6574+
Se.Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace);
6575+
D.setInvalidType();
6576+
}
6577+
6578+
// OpenCL v1.2 s6.12.14.1:
6579+
// A global sampler must be declared with either the constant address
6580+
// space qualifier or with the const qualifier.
6581+
if (DC->isTranslationUnit() &&
6582+
!(R.getAddressSpace() == LangAS::opencl_constant ||
6583+
R.isConstQualified())) {
6584+
Se.Diag(D.getIdentifierLoc(), diag::err_opencl_nonconst_global_sampler);
6585+
D.setInvalidType();
6586+
}
6587+
if (D.isInvalidType())
6588+
return false;
6589+
}
6590+
return true;
6591+
}
64776592

64786593
NamedDecl *Sema::ActOnVariableDeclarator(
64796594
Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo,
@@ -6497,95 +6612,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(
64976612
return nullptr;
64986613
}
64996614

6500-
if (getLangOpts().OpenCL) {
6501-
// OpenCL v2.0 s6.9.b - Image type can only be used as a function argument.
6502-
// OpenCL v2.0 s6.13.16.1 - Pipe type can only be used as a function
6503-
// argument.
6504-
if (R->isImageType() || R->isPipeType()) {
6505-
Diag(D.getIdentifierLoc(),
6506-
diag::err_opencl_type_can_only_be_used_as_function_parameter)
6507-
<< R;
6508-
D.setInvalidType();
6509-
return nullptr;
6510-
}
6511-
6512-
// OpenCL v1.2 s6.9.r:
6513-
// The event type cannot be used to declare a program scope variable.
6514-
// OpenCL v2.0 s6.9.q:
6515-
// The clk_event_t and reserve_id_t types cannot be declared in program scope.
6516-
if (NULL == S->getParent()) {
6517-
if (R->isReserveIDT() || R->isClkEventT() || R->isEventT()) {
6518-
Diag(D.getIdentifierLoc(),
6519-
diag::err_invalid_type_for_program_scope_var) << R;
6520-
D.setInvalidType();
6521-
return nullptr;
6522-
}
6523-
}
6524-
6525-
// OpenCL v1.0 s6.8.a.3: Pointers to functions are not allowed.
6526-
QualType NR = R;
6527-
while (NR->isPointerType()) {
6528-
if (NR->isFunctionPointerType()) {
6529-
Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer);
6530-
D.setInvalidType();
6531-
break;
6532-
}
6533-
NR = NR->getPointeeType();
6534-
}
6535-
6536-
if (!getOpenCLOptions().isEnabled("cl_khr_fp16")) {
6537-
// OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and
6538-
// half array type (unless the cl_khr_fp16 extension is enabled).
6539-
if (Context.getBaseElementType(R)->isHalfType()) {
6540-
Diag(D.getIdentifierLoc(), diag::err_opencl_half_declaration) << R;
6541-
D.setInvalidType();
6542-
}
6543-
}
6544-
6545-
if (R->isSamplerT()) {
6546-
// OpenCL v1.2 s6.9.b p4:
6547-
// The sampler type cannot be used with the __local and __global address
6548-
// space qualifiers.
6549-
if (R.getAddressSpace() == LangAS::opencl_local ||
6550-
R.getAddressSpace() == LangAS::opencl_global) {
6551-
Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace);
6552-
}
6553-
6554-
// OpenCL v1.2 s6.12.14.1:
6555-
// A global sampler must be declared with either the constant address
6556-
// space qualifier or with the const qualifier.
6557-
if (DC->isTranslationUnit() &&
6558-
!(R.getAddressSpace() == LangAS::opencl_constant ||
6559-
R.isConstQualified())) {
6560-
Diag(D.getIdentifierLoc(), diag::err_opencl_nonconst_global_sampler);
6561-
D.setInvalidType();
6562-
}
6563-
}
6564-
6565-
// OpenCL v1.2 s6.9.r:
6566-
// The event type cannot be used with the __local, __constant and __global
6567-
// address space qualifiers.
6568-
if (R->isEventT()) {
6569-
if (R.getAddressSpace() != LangAS::opencl_private) {
6570-
Diag(D.getBeginLoc(), diag::err_event_t_addr_space_qual);
6571-
D.setInvalidType();
6572-
}
6573-
}
6574-
6575-
// C++ for OpenCL does not allow the thread_local storage qualifier.
6576-
// OpenCL C does not support thread_local either, and
6577-
// also reject all other thread storage class specifiers.
6578-
DeclSpec::TSCS TSC = D.getDeclSpec().getThreadStorageClassSpec();
6579-
if (TSC != TSCS_unspecified) {
6580-
bool IsCXX = getLangOpts().OpenCLCPlusPlus;
6581-
Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
6582-
diag::err_opencl_unknown_type_specifier)
6583-
<< IsCXX << getLangOpts().getOpenCLVersionTuple().getAsString()
6584-
<< DeclSpec::getSpecifierName(TSC) << 1;
6585-
D.setInvalidType();
6586-
return nullptr;
6587-
}
6588-
}
65896615

65906616
DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec();
65916617
StorageClass SC = StorageClassSpecToVarDeclStorageClass(D.getDeclSpec());
@@ -6942,6 +6968,13 @@ NamedDecl *Sema::ActOnVariableDeclarator(
69426968
}
69436969
}
69446970

6971+
if (getLangOpts().OpenCL) {
6972+
6973+
deduceOpenCLAddressSpace(NewVD);
6974+
6975+
diagnoseOpenCLTypes(S, *this, D, DC, NewVD->getType());
6976+
}
6977+
69456978
// Handle attributes prior to checking for duplicates in MergeVarDecl
69466979
ProcessDeclAttributes(S, NewVD, D);
69476980

@@ -11285,6 +11318,9 @@ bool Sema::DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit,
1128511318
if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(VDecl))
1128611319
VDecl->setInvalidDecl();
1128711320

11321+
if (getLangOpts().OpenCL)
11322+
deduceOpenCLAddressSpace(VDecl);
11323+
1128811324
// If this is a redeclaration, check that the type we just deduced matches
1128911325
// the previously declared type.
1129011326
if (VarDecl *Old = VDecl->getPreviousDecl()) {
@@ -13107,6 +13143,10 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
1310713143
if (New->hasAttr<BlocksAttr>()) {
1310813144
Diag(New->getLocation(), diag::err_block_on_nonlocal);
1310913145
}
13146+
13147+
if (getLangOpts().OpenCL)
13148+
deduceOpenCLAddressSpace(New);
13149+
1311013150
return New;
1311113151
}
1311213152

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,8 +1514,12 @@ TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm,
15141514
int indexAdjustment,
15151515
Optional<unsigned> NumExpansions,
15161516
bool ExpectParameterPack) {
1517-
return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, indexAdjustment,
1518-
NumExpansions, ExpectParameterPack);
1517+
auto NewParm =
1518+
SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, indexAdjustment,
1519+
NumExpansions, ExpectParameterPack);
1520+
if (NewParm && SemaRef.getLangOpts().OpenCL)
1521+
SemaRef.deduceOpenCLAddressSpace(NewParm);
1522+
return NewParm;
15191523
}
15201524

15211525
QualType

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,9 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
930930
SemaRef.inferObjCARCLifetime(Var))
931931
Var->setInvalidDecl();
932932

933+
if (SemaRef.getLangOpts().OpenCL)
934+
SemaRef.deduceOpenCLAddressSpace(Var);
935+
933936
// Substitute the nested name specifier, if any.
934937
if (SubstQualifier(D, Var))
935938
return nullptr;

0 commit comments

Comments
 (0)