@@ -210,19 +210,9 @@ static bool isZeroSizedArray(QualType Ty) {
210
210
return false ;
211
211
}
212
212
213
- static Sema::DeviceDiagBuilder
214
- emitDeferredDiagnosticAndNote (Sema &S, SourceRange Loc, unsigned DiagID,
215
- SourceRange UsedAtLoc) {
216
- Sema::DeviceDiagBuilder builder =
217
- S.SYCLDiagIfDeviceCode (Loc.getBegin (), DiagID);
218
- if (UsedAtLoc.isValid ())
219
- S.SYCLDiagIfDeviceCode (UsedAtLoc.getBegin (), diag::note_sycl_used_here);
220
- return builder;
221
- }
222
-
223
- static void checkSYCLVarType (Sema &S, QualType Ty, SourceRange Loc,
224
- llvm::DenseSet<QualType> Visited,
225
- SourceRange UsedAtLoc = SourceRange()) {
213
+ static void checkSYCLType (Sema &S, QualType Ty, SourceRange Loc,
214
+ llvm::DenseSet<QualType> Visited,
215
+ SourceRange UsedAtLoc = SourceRange()) {
226
216
// Not all variable types are supported inside SYCL kernels,
227
217
// for example the quad type __float128 will cause errors in the
228
218
// SPIR-V translation phase.
@@ -233,16 +223,21 @@ static void checkSYCLVarType(Sema &S, QualType Ty, SourceRange Loc,
233
223
// different location than the variable declaration and we need to
234
224
// inform the user of both, e.g. struct member usage vs declaration.
235
225
226
+ bool Emitting = false ;
227
+
236
228
// --- check types ---
237
229
238
230
// zero length arrays
239
- if (isZeroSizedArray (Ty))
240
- emitDeferredDiagnosticAndNote (S, Loc, diag::err_typecheck_zero_array_size,
241
- UsedAtLoc);
231
+ if (isZeroSizedArray (Ty)) {
232
+ S.SYCLDiagIfDeviceCode (Loc.getBegin (), diag::err_typecheck_zero_array_size);
233
+ Emitting = true ;
234
+ }
242
235
243
236
// variable length arrays
244
- if (Ty->isVariableArrayType ())
245
- emitDeferredDiagnosticAndNote (S, Loc, diag::err_vla_unsupported, UsedAtLoc);
237
+ if (Ty->isVariableArrayType ()) {
238
+ S.SYCLDiagIfDeviceCode (Loc.getBegin (), diag::err_vla_unsupported);
239
+ Emitting = true ;
240
+ }
246
241
247
242
// Sub-reference array or pointer, then proceed with that type.
248
243
while (Ty->isAnyPointerType () || Ty->isArrayType ())
@@ -253,9 +248,14 @@ static void checkSYCLVarType(Sema &S, QualType Ty, SourceRange Loc,
253
248
Ty->isSpecificBuiltinType (BuiltinType::UInt128) ||
254
249
Ty->isSpecificBuiltinType (BuiltinType::LongDouble) ||
255
250
(Ty->isSpecificBuiltinType (BuiltinType::Float128) &&
256
- !S.Context .getTargetInfo ().hasFloat128Type ()))
257
- emitDeferredDiagnosticAndNote (S, Loc, diag::err_type_unsupported, UsedAtLoc )
251
+ !S.Context .getTargetInfo ().hasFloat128Type ())) {
252
+ S. SYCLDiagIfDeviceCode ( Loc. getBegin () , diag::err_type_unsupported)
258
253
<< Ty.getUnqualifiedType ().getCanonicalType ();
254
+ Emitting = true ;
255
+ }
256
+
257
+ if (Emitting && UsedAtLoc.isValid ())
258
+ S.SYCLDiagIfDeviceCode (UsedAtLoc.getBegin (), diag::note_used_here);
259
259
260
260
// --- now recurse ---
261
261
// Pointers complicate recursion. Add this type to Visited.
@@ -264,16 +264,15 @@ static void checkSYCLVarType(Sema &S, QualType Ty, SourceRange Loc,
264
264
return ;
265
265
266
266
if (const auto *ATy = dyn_cast<AttributedType>(Ty))
267
- return checkSYCLVarType (S, ATy->getModifiedType (), Loc, Visited);
267
+ return checkSYCLType (S, ATy->getModifiedType (), Loc, Visited);
268
268
269
269
if (const auto *RD = Ty->getAsRecordDecl ()) {
270
270
for (const auto &Field : RD->fields ())
271
- checkSYCLVarType (S, Field->getType (), Field->getSourceRange (), Visited,
272
- Loc);
271
+ checkSYCLType (S, Field->getType (), Field->getSourceRange (), Visited, Loc);
273
272
} else if (const auto *FPTy = dyn_cast<FunctionProtoType>(Ty)) {
274
273
for (const auto &ParamTy : FPTy->param_types ())
275
- checkSYCLVarType (S, ParamTy, Loc, Visited);
276
- checkSYCLVarType (S, FPTy->getReturnType (), Loc, Visited);
274
+ checkSYCLType (S, ParamTy, Loc, Visited);
275
+ checkSYCLType (S, FPTy->getReturnType (), Loc, Visited);
277
276
}
278
277
}
279
278
@@ -284,7 +283,7 @@ void Sema::checkSYCLDeviceVarDecl(VarDecl *Var) {
284
283
SourceRange Loc = Var->getLocation ();
285
284
llvm::DenseSet<QualType> Visited;
286
285
287
- checkSYCLVarType (*this , Ty, Loc, Visited);
286
+ checkSYCLType (*this , Ty, Loc, Visited);
288
287
}
289
288
290
289
class MarkDeviceFunction : public RecursiveASTVisitor <MarkDeviceFunction> {
@@ -805,6 +804,22 @@ class SyclKernelFieldChecker
805
804
bool IsInvalid = false ;
806
805
DiagnosticsEngine &Diag;
807
806
807
+ void checkAccessorType (QualType Ty, SourceRange Loc) {
808
+ assert (Util::isSyclAccessorType (Ty) &&
809
+ " Should only be called on SYCL accessor types." );
810
+
811
+ const RecordDecl *RecD = Ty->getAsRecordDecl ();
812
+ if (const ClassTemplateSpecializationDecl *CTSD =
813
+ dyn_cast<ClassTemplateSpecializationDecl>(RecD)) {
814
+ const TemplateArgumentList &TAL = CTSD->getTemplateArgs ();
815
+ TemplateArgument TA = TAL.get (0 );
816
+ const QualType TemplateArgTy = TA.getAsType ();
817
+
818
+ llvm::DenseSet<QualType> Visited;
819
+ checkSYCLType (SemaRef, TemplateArgTy, Loc, Visited);
820
+ }
821
+ }
822
+
808
823
public:
809
824
SyclKernelFieldChecker (Sema &S)
810
825
: SyclKernelFieldHandler(S), Diag(S.getASTContext().getDiagnostics()) {}
@@ -836,6 +851,15 @@ class SyclKernelFieldChecker
836
851
}
837
852
}
838
853
854
+ void handleSyclAccessorType (const CXXBaseSpecifier &BS,
855
+ QualType FieldTy) final {
856
+ checkAccessorType (FieldTy, BS.getBeginLoc ());
857
+ }
858
+
859
+ void handleSyclAccessorType (FieldDecl *FD, QualType FieldTy) final {
860
+ checkAccessorType (FieldTy, FD->getLocation ());
861
+ }
862
+
839
863
// We should be able to handle this, so we made it part of the visitor, but
840
864
// this is 'to be implemented'.
841
865
void handleArrayType (FieldDecl *FD, QualType FieldTy) final {
@@ -1543,7 +1567,9 @@ Sema::DeviceDiagBuilder Sema::SYCLDiagIfDeviceCode(SourceLocation Loc,
1543
1567
" Should only be called during SYCL compilation" );
1544
1568
FunctionDecl *FD = dyn_cast<FunctionDecl>(getCurLexicalContext ());
1545
1569
DeviceDiagBuilder::Kind DiagKind = [this , FD] {
1546
- if (ConstructingOpenCLKernel || !FD)
1570
+ if (ConstructingOpenCLKernel)
1571
+ return DeviceDiagBuilder::K_ImmediateWithCallStack;
1572
+ if (!FD)
1547
1573
return DeviceDiagBuilder::K_Nop;
1548
1574
if (getEmissionStatus (FD) == Sema::FunctionEmissionStatus::Emitted)
1549
1575
return DeviceDiagBuilder::K_ImmediateWithCallStack;
0 commit comments