clang 24.0.0git
SemaSYCL.cpp
Go to the documentation of this file.
1//===- SemaSYCL.cpp - Semantic Analysis for SYCL constructs ---------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8// This implements Semantic Analysis for SYCL constructs.
9//===----------------------------------------------------------------------===//
10
11#include "clang/Sema/SemaSYCL.h"
12#include "TreeTransform.h"
13#include "clang/AST/Mangle.h"
15#include "clang/AST/StmtSYCL.h"
19#include "clang/Sema/Attr.h"
21#include "clang/Sema/Sema.h"
22
23using namespace clang;
24
25// -----------------------------------------------------------------------------
26// SYCL device specific diagnostics implementation
27// -----------------------------------------------------------------------------
28
30
32 unsigned DiagID) {
33 assert(getLangOpts().SYCLIsDevice &&
34 "Device diagnostics Should only be issued during device compilation");
35 SemaDiagnosticBuilder::Kind DiagKind = SemaDiagnosticBuilder::K_Nop;
36 FunctionDecl *FD = SemaRef.getCurFunctionDecl(/*AllowLambda=*/true);
37 if (FD) {
38 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(FD);
39 switch (FES) {
41 DiagKind = SemaDiagnosticBuilder::K_ImmediateWithCallStack;
42 break;
45 DiagKind = SemaDiagnosticBuilder::K_Deferred;
46 break;
48 llvm_unreachable("OMPDiscarded unexpected in SYCL device compilation");
50 llvm_unreachable("CUDADiscarded unexpected in SYCL device compilation");
51 }
52 }
53 return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, FD, SemaRef);
54}
55
56static bool isZeroSizedArray(SemaSYCL &S, QualType Ty) {
57 if (const auto *CAT = S.getASTContext().getAsConstantArrayType(Ty))
58 return CAT->isZeroSize();
59 return false;
60}
61
63 llvm::DenseSet<QualType> Visited,
64 ValueDecl *DeclToCheck) {
65 assert(getLangOpts().SYCLIsDevice &&
66 "Should only be called during SYCL compilation");
67 // Emit notes only for the first discovered declaration of unsupported type
68 // to avoid mess of notes. This flag is to track that error already happened.
69 bool NeedToEmitNotes = true;
70
71 auto Check = [&](QualType TypeToCheck, const ValueDecl *D) {
72 bool ErrorFound = false;
73 if (isZeroSizedArray(*this, TypeToCheck)) {
74 DiagIfDeviceCode(UsedAt, diag::err_typecheck_zero_array_size) << 1;
75 ErrorFound = true;
76 }
77 // Checks for other types can also be done here.
78 if (ErrorFound) {
79 if (NeedToEmitNotes) {
80 if (auto *FD = dyn_cast<FieldDecl>(D))
81 DiagIfDeviceCode(FD->getLocation(),
82 diag::note_illegal_field_declared_here)
83 << FD->getType()->isPointerType() << FD->getType();
84 else
85 DiagIfDeviceCode(D->getLocation(), diag::note_declared_at);
86 }
87 }
88
89 return ErrorFound;
90 };
91
92 // In case we have a Record used do the DFS for a bad field.
93 SmallVector<const ValueDecl *, 4> StackForRecursion;
94 StackForRecursion.push_back(DeclToCheck);
95
96 // While doing DFS save how we get there to emit a nice set of notes.
98 History.push_back(nullptr);
99
100 do {
101 const ValueDecl *Next = StackForRecursion.pop_back_val();
102 if (!Next) {
103 assert(!History.empty());
104 // Found a marker, we have gone up a level.
105 History.pop_back();
106 continue;
107 }
108 QualType NextTy = Next->getType();
109
110 if (!Visited.insert(NextTy).second)
111 continue;
112
113 auto EmitHistory = [&]() {
114 // The first element is always nullptr.
115 for (uint64_t Index = 1; Index < History.size(); ++Index) {
116 DiagIfDeviceCode(History[Index]->getLocation(),
117 diag::note_within_field_of_type)
118 << History[Index]->getType();
119 }
120 };
121
122 if (Check(NextTy, Next)) {
123 if (NeedToEmitNotes)
124 EmitHistory();
125 NeedToEmitNotes = false;
126 }
127
128 // In case pointer/array/reference type is met get pointee type, then
129 // proceed with that type.
130 while (NextTy->isAnyPointerType() || NextTy->isArrayType() ||
131 NextTy->isReferenceType()) {
132 if (NextTy->isArrayType())
133 NextTy = QualType{NextTy->getArrayElementTypeNoTypeQual(), 0};
134 else
135 NextTy = NextTy->getPointeeType();
136 if (Check(NextTy, Next)) {
137 if (NeedToEmitNotes)
138 EmitHistory();
139 NeedToEmitNotes = false;
140 }
141 }
142
143 if (const auto *RecDecl = NextTy->getAsRecordDecl()) {
144 if (auto *NextFD = dyn_cast<FieldDecl>(Next))
145 History.push_back(NextFD);
146 // When nullptr is discovered, this means we've gone back up a level, so
147 // the history should be cleaned.
148 StackForRecursion.push_back(nullptr);
149 llvm::append_range(StackForRecursion, RecDecl->fields());
150 }
151 } while (!StackForRecursion.empty());
152}
153
155 SourceLocation LParen,
156 SourceLocation RParen,
157 TypeSourceInfo *TSI) {
158 return SYCLUniqueStableNameExpr::Create(getASTContext(), OpLoc, LParen,
159 RParen, TSI);
160}
161
163 SourceLocation LParen,
164 SourceLocation RParen,
165 ParsedType ParsedTy) {
166 TypeSourceInfo *TSI = nullptr;
167 QualType Ty = SemaRef.GetTypeFromParser(ParsedTy, &TSI);
168
169 if (Ty.isNull())
170 return ExprError();
171 if (!TSI)
172 TSI = getASTContext().getTrivialTypeSourceInfo(Ty, LParen);
173
174 return BuildUniqueStableNameExpr(OpLoc, LParen, RParen, TSI);
175}
176
178 // The 'sycl_kernel' attribute applies only to function templates.
179 const auto *FD = cast<FunctionDecl>(D);
180 const FunctionTemplateDecl *FT = FD->getDescribedFunctionTemplate();
181 assert(FT && "Function template is expected");
182
183 // Function template must have at least two template parameters.
185 if (TL->size() < 2) {
186 Diag(FT->getLocation(), diag::warn_sycl_kernel_num_of_template_params);
187 return;
188 }
189
190 // Template parameters must be typenames.
191 for (unsigned I = 0; I < 2; ++I) {
192 const NamedDecl *TParam = TL->getParam(I);
193 if (isa<NonTypeTemplateParmDecl>(TParam)) {
194 Diag(FT->getLocation(),
195 diag::warn_sycl_kernel_invalid_template_param_type);
196 return;
197 }
198 }
199
200 // Function must have at least one argument.
201 if (getFunctionOrMethodNumParams(D) != 1) {
202 Diag(FT->getLocation(), diag::warn_sycl_kernel_num_of_function_params);
203 return;
204 }
205
206 // Function must return void.
208 if (!RetTy->isVoidType()) {
209 Diag(FT->getLocation(), diag::warn_sycl_kernel_return_type);
210 return;
211 }
212
214}
215
217 ParsedType PT = AL.getTypeArg();
218 TypeSourceInfo *TSI = nullptr;
219 (void)SemaRef.GetTypeFromParser(PT, &TSI);
220 assert(TSI && "no type source info for attribute argument");
221 D->addAttr(::new (SemaRef.Context)
222 SYCLKernelEntryPointAttr(SemaRef.Context, AL, TSI));
223}
224
226 assert(getLangOpts().SYCLIsDevice &&
227 "Should only be called during SYCL device compilation");
228
229 // Function declarations with the sycl_kernel_entry_point attribute cannot
230 // be ODR-used in a potentially evaluated context.
231 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
232 if (const auto *SKEPAttr = FD->getAttr<SYCLKernelEntryPointAttr>()) {
233 if (SemaRef.currentEvaluationContext().isPotentiallyEvaluated()) {
234 DiagIfDeviceCode(Loc, diag::err_sycl_entry_point_device_use)
235 << FD << SKEPAttr;
236 DiagIfDeviceCode(SKEPAttr->getLocation(), diag::note_attribute) << FD;
237 }
238 }
239 }
240}
241
242// Given a potentially qualified type, SourceLocationForUserDeclaredType()
243// returns the source location of the canonical declaration of the unqualified
244// desugared user declared type, if any. For non-user declared types, an
245// invalid source location is returned. The intended usage of this function
246// is to identify an appropriate source location, if any, for a
247// "entity declared here" diagnostic note.
249 SourceLocation Loc;
250 const Type *T = QT->getUnqualifiedDesugaredType();
251 if (const TagType *TT = dyn_cast<TagType>(T))
252 Loc = TT->getDecl()->getLocation();
253 else if (const auto *ObjCIT = dyn_cast<ObjCInterfaceType>(T))
254 Loc = ObjCIT->getDecl()->getLocation();
255 return Loc;
256}
257
259 QualType KernelName) {
260 assert(!KernelName->isDependentType());
261
262 if (!KernelName->isStructureOrClassType()) {
263 // SYCL 2020 section 5.2, "Naming of kernels", only requires that the
264 // kernel name be a C++ typename. However, the definition of "kernel name"
265 // in the glossary states that a kernel name is a class type. Neither
266 // section explicitly states whether the kernel name type can be
267 // cv-qualified. For now, kernel name types are required to be class types
268 // and that they may be cv-qualified. The following issue requests
269 // clarification from the SYCL WG.
270 // https://github.com/KhronosGroup/SYCL-Docs/issues/568
271 S.Diag(Loc, diag::warn_sycl_kernel_name_not_a_class_type) << KernelName;
272 SourceLocation DeclTypeLoc = SourceLocationForUserDeclaredType(KernelName);
273 if (DeclTypeLoc.isValid())
274 S.Diag(DeclTypeLoc, diag::note_entity_declared_at) << KernelName;
275 return true;
276 }
277
278 return false;
279}
280
282 // SYCL 2020 section 5.4 prohibits calling a variadic function from device
283 // code, so the attribute cannot be honored; declaring one is not prohibited,
284 // so ignore the attribute rather than reject the declaration.
285 if (cast<FunctionDecl>(D)->isVariadic()) {
286 Diag(AL.getLoc(), diag::warn_sycl_external_ignored_variadic_function) << AL;
287 return;
288 }
289
291}
292
294 const auto *SEAttr = FD->getAttr<SYCLExternalAttr>();
295 assert(SEAttr && "Missing sycl_external attribute");
296 if (!FD->isInvalidDecl() && !FD->isTemplated()) {
297 if (!FD->isExternallyVisible())
300 Diag(SEAttr->getLocation(), diag::err_sycl_external_invalid_linkage)
301 << SEAttr;
302 }
303 if (FD->isDeletedAsWritten()) {
304 Diag(SEAttr->getLocation(),
305 diag::err_sycl_external_invalid_deleted_function)
306 << SEAttr;
307 }
308}
309
311 // Ensure that all attributes present on the declaration are consistent
312 // and warn about any redundant ones.
313 SYCLKernelEntryPointAttr *SKEPAttr = nullptr;
314 for (auto *SAI : FD->specific_attrs<SYCLKernelEntryPointAttr>()) {
315 if (!SKEPAttr) {
316 SKEPAttr = SAI;
317 continue;
318 }
319 if (!getASTContext().hasSameType(SAI->getKernelName(),
320 SKEPAttr->getKernelName())) {
321 Diag(SAI->getLocation(), diag::err_sycl_entry_point_invalid_redeclaration)
322 << SKEPAttr << SAI->getKernelName() << SKEPAttr->getKernelName();
323 Diag(SKEPAttr->getLocation(), diag::note_previous_attribute);
324 SAI->setInvalidAttr();
325 } else {
326 Diag(SAI->getLocation(),
327 diag::warn_sycl_entry_point_redundant_declaration)
328 << SAI;
329 Diag(SKEPAttr->getLocation(), diag::note_previous_attribute);
330 }
331 }
332 assert(SKEPAttr && "Missing sycl_kernel_entry_point attribute");
333
334 // Ensure the kernel name type is valid.
335 if (!SKEPAttr->getKernelName()->isDependentType() &&
336 CheckSYCLKernelName(SemaRef, SKEPAttr->getLocation(),
337 SKEPAttr->getKernelName()))
338 SKEPAttr->setInvalidAttr();
339
340 // Ensure that an attribute present on the previous declaration
341 // matches the one on this declaration.
342 FunctionDecl *PrevFD = FD->getPreviousDecl();
343 if (PrevFD && !PrevFD->isInvalidDecl()) {
344 const auto *PrevSKEPAttr = PrevFD->getAttr<SYCLKernelEntryPointAttr>();
345 if (PrevSKEPAttr && !PrevSKEPAttr->isInvalidAttr()) {
346 if (!getASTContext().hasSameType(SKEPAttr->getKernelName(),
347 PrevSKEPAttr->getKernelName())) {
348 Diag(SKEPAttr->getLocation(),
349 diag::err_sycl_entry_point_invalid_redeclaration)
350 << SKEPAttr << SKEPAttr->getKernelName()
351 << PrevSKEPAttr->getKernelName();
352 Diag(PrevSKEPAttr->getLocation(), diag::note_previous_decl) << PrevFD;
353 SKEPAttr->setInvalidAttr();
354 }
355 }
356 }
357
358 if (isa<CXXConstructorDecl>(FD)) {
359 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
360 << SKEPAttr << diag::InvalidSKEPReason::Constructor;
361 SKEPAttr->setInvalidAttr();
362 }
363 if (isa<CXXDestructorDecl>(FD)) {
364 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
365 << SKEPAttr << diag::InvalidSKEPReason::Destructor;
366 SKEPAttr->setInvalidAttr();
367 }
368 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
369 if (MD->isExplicitObjectMemberFunction()) {
370 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
371 << SKEPAttr << diag::InvalidSKEPReason::ExplicitObjectFn;
372 SKEPAttr->setInvalidAttr();
373 }
374 }
375
376 if (FD->isVariadic()) {
377 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
378 << SKEPAttr << diag::InvalidSKEPReason::VariadicFn;
379 SKEPAttr->setInvalidAttr();
380 }
381
382 if (FD->isDefaulted()) {
383 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
384 << SKEPAttr << diag::InvalidSKEPReason::DefaultedFn;
385 SKEPAttr->setInvalidAttr();
386 } else if (FD->isDeleted()) {
387 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
388 << SKEPAttr << diag::InvalidSKEPReason::DeletedFn;
389 SKEPAttr->setInvalidAttr();
390 }
391
392 if (FD->isConsteval()) {
393 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
394 << SKEPAttr << diag::InvalidSKEPReason::ConstevalFn;
395 SKEPAttr->setInvalidAttr();
396 } else if (FD->isConstexpr()) {
397 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
398 << SKEPAttr << diag::InvalidSKEPReason::ConstexprFn;
399 SKEPAttr->setInvalidAttr();
400 }
401
402 if (FD->isNoReturn()) {
403 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
404 << SKEPAttr << diag::InvalidSKEPReason::NoreturnFn;
405 SKEPAttr->setInvalidAttr();
406 }
407
408 if (FD->getReturnType()->isUndeducedType()) {
409 Diag(SKEPAttr->getLocation(),
410 diag::err_sycl_entry_point_deduced_return_type)
411 << SKEPAttr;
412 SKEPAttr->setInvalidAttr();
413 } else if (!FD->getReturnType()->isDependentType() &&
414 !FD->getReturnType()->isVoidType()) {
415 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_return_type)
416 << SKEPAttr;
417 SKEPAttr->setInvalidAttr();
418 }
419
420 if (!FD->isInvalidDecl() && !FD->isTemplated() &&
421 !SKEPAttr->isInvalidAttr()) {
422 const SYCLKernelInfo *SKI =
423 getASTContext().findSYCLKernelInfo(SKEPAttr->getKernelName());
424 if (SKI) {
426 // FIXME: This diagnostic should include the origin of the kernel
427 // FIXME: names; not just the locations of the conflicting declarations.
428 Diag(FD->getLocation(), diag::err_sycl_kernel_name_conflict)
429 << SKEPAttr;
431 diag::note_previous_declaration);
432 SKEPAttr->setInvalidAttr();
433 }
434 } else {
436 }
437 }
438}
439
441 QualType KNT) {
442 // The current context must be the function definition context to ensure
443 // that name lookup is performed within the correct scope.
444 assert(SemaRef.CurContext == FD && "The current declaration context does not "
445 "match the requested function context");
446
447 // An appropriate source location is required to emit diagnostics if
448 // lookup fails to produce an overload set. The desired location is the
449 // start of the function body, but that is not yet available since the
450 // body of the function has not yet been set when this function is called.
451 // The general location of the function is used instead.
452 SourceLocation Loc = FD->getLocation();
453
454 ASTContext &Ctx = SemaRef.getASTContext();
455 IdentifierInfo &SYCLKernelLaunchID =
456 Ctx.Idents.get("sycl_kernel_launch", tok::TokenKind::identifier);
457
458 // Establish a code synthesis context for the implicit name lookup of
459 // a template named 'sycl_kernel_launch'. In the event of an error, this
460 // ensures an appropriate diagnostic note is issued to explain why the
461 // lookup was performed.
464 CSC.Entity = FD;
466
467 // Perform ordinary name lookup for a function or variable template that
468 // accepts a single type template argument.
469 LookupResult Result(SemaRef, &SYCLKernelLaunchID, Loc,
471 CXXScopeSpec EmptySS;
472 if (SemaRef.LookupTemplateName(Result, SemaRef.getCurScope(), EmptySS,
473 /*ObjectType*/ QualType(),
474 /*EnteringContext*/ false,
476 return ExprError();
477 if (Result.isAmbiguous())
478 return ExprError();
479
480 TemplateArgumentListInfo TALI{Loc, Loc};
483 SemaRef.getTrivialTemplateArgumentLoc(KNTA, QualType(), Loc);
484 TALI.addArgument(TAL);
485
486 ExprResult IdExpr;
487 if (SemaRef.isPotentialImplicitMemberAccess(EmptySS, Result,
488 /*IsAddressOfOperand*/ false)) {
489 // The lookup result allows for a possible implicit member access that
490 // would require an implicit or explicit 'this' argument.
491 IdExpr = SemaRef.BuildPossibleImplicitMemberExpr(
492 EmptySS, SourceLocation(), Result, &TALI, SemaRef.getCurScope());
493 } else {
494 IdExpr = SemaRef.BuildTemplateIdExpr(EmptySS, SourceLocation(), Result,
495 /*RequiresADL*/ true, &TALI);
496 }
497
498 // The resulting expression may be invalid if, for example, 'FD' is a
499 // non-static member function and sycl_kernel_launch lookup selects a
500 // member function (which would require a 'this' argument which is
501 // not available).
502 if (IdExpr.isInvalid())
503 return ExprError();
504
505 return IdExpr;
506}
507
508namespace {
509
510// Constructs the arguments to be passed for the SYCL kernel launch call.
511// The first argument is a string literal that contains the SYCL kernel
512// name. The remaining arguments are the parameters of 'FD' passed as
513// move-elligible xvalues. Returns true on error and false otherwise.
514bool BuildSYCLKernelLaunchCallArgs(Sema &SemaRef, FunctionDecl *FD,
515 const SYCLKernelInfo *SKI,
517 SourceLocation Loc) {
518 // The current context must be the function definition context to ensure
519 // that parameter references occur within the correct scope.
520 assert(SemaRef.CurContext == FD && "The current declaration context does not "
521 "match the requested function context");
522
523 // Prepare a string literal that contains the kernel name.
524 ASTContext &Ctx = SemaRef.getASTContext();
525 const std::string &KernelName = SKI->GetKernelName();
526 QualType KernelNameCharTy = Ctx.CharTy.withConst();
527 llvm::APInt KernelNameSize(Ctx.getTypeSize(Ctx.getSizeType()),
528 KernelName.size() + 1);
529 QualType KernelNameArrayTy = Ctx.getConstantArrayType(
530 KernelNameCharTy, KernelNameSize, nullptr, ArraySizeModifier::Normal, 0);
531 Expr *KernelNameExpr =
533 /*Pascal*/ false, KernelNameArrayTy, Loc);
534 Args.push_back(KernelNameExpr);
535
536 // Forward all parameters of 'FD' to the SYCL kernel launch function as if
537 // by std::move().
538 for (ParmVarDecl *PVD : FD->parameters()) {
539 QualType ParamType = PVD->getOriginalType().getNonReferenceType();
540 ExprResult E = SemaRef.BuildDeclRefExpr(PVD, ParamType, VK_LValue, Loc);
541 if (E.isInvalid())
542 return true;
543 if (!PVD->getType()->isLValueReferenceType())
544 E = ImplicitCastExpr::Create(SemaRef.Context, E.get()->getType(), CK_NoOp,
545 E.get(), nullptr, VK_XValue,
547 if (E.isInvalid())
548 return true;
549 Args.push_back(E.get());
550 }
551
552 return false;
553}
554
555// Constructs the SYCL kernel launch call.
556StmtResult BuildSYCLKernelLaunchCallStmt(Sema &SemaRef, FunctionDecl *FD,
557 const SYCLKernelInfo *SKI,
558 Expr *IdExpr, SourceLocation Loc) {
560 // IdExpr may be null if name lookup failed.
561 if (IdExpr) {
563
564 // Establish a code synthesis context for construction of the arguments
565 // for the implicit call to 'sycl_kernel_launch'.
566 {
569 CSC.Entity = FD;
570 Sema::ScopedCodeSynthesisContext ScopedCSC(SemaRef, CSC);
571
572 if (BuildSYCLKernelLaunchCallArgs(SemaRef, FD, SKI, Args, Loc))
573 return StmtError();
574 }
575
576 // Establish a code synthesis context for the implicit call to
577 // 'sycl_kernel_launch'.
578 {
581 CSC.Entity = FD;
582 CSC.CallArgs = Args.data();
583 CSC.NumCallArgs = Args.size();
584 Sema::ScopedCodeSynthesisContext ScopedCSC(SemaRef, CSC);
585
586 ExprResult LaunchResult =
587 SemaRef.BuildCallExpr(SemaRef.getCurScope(), IdExpr, Loc, Args, Loc);
588 if (LaunchResult.isInvalid())
589 return StmtError();
590
591 Stmts.push_back(SemaRef.MaybeCreateExprWithCleanups(LaunchResult).get());
592 }
593 }
594
595 return CompoundStmt::Create(SemaRef.getASTContext(), Stmts,
596 FPOptionsOverride(), Loc, Loc);
597}
598
599// The body of a function declared with the [[sycl_kernel_entry_point]]
600// attribute is cloned and transformed to substitute references to the original
601// function parameters with references to replacement variables that stand in
602// for SYCL kernel parameters or local variables that reconstitute a decomposed
603// SYCL kernel argument.
604class OutlinedFunctionDeclBodyInstantiator
605 : public TreeTransform<OutlinedFunctionDeclBodyInstantiator> {
606public:
607 using ParmDeclMap = llvm::DenseMap<ParmVarDecl *, VarDecl *>;
608
609 OutlinedFunctionDeclBodyInstantiator(Sema &S, ParmDeclMap &M,
610 FunctionDecl *FD)
611 : TreeTransform<OutlinedFunctionDeclBodyInstantiator>(S), SemaRef(S),
612 MapRef(M), FD(FD) {}
613
614 // A new set of AST nodes is always required.
615 bool AlwaysRebuild() { return true; }
616
617 // Transform ParmVarDecl references to the supplied replacement variables.
618 ExprResult TransformDeclRefExpr(DeclRefExpr *DRE) {
619 const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl());
620 if (PVD) {
621 ParmDeclMap::iterator I = MapRef.find(PVD);
622 if (I != MapRef.end()) {
623 VarDecl *VD = I->second;
624 assert(SemaRef.getASTContext().hasSameUnqualifiedType(
625 PVD->getType().getNonReferenceType(), VD->getType()));
626 assert(!VD->getType().isMoreQualifiedThan(
627 PVD->getType().getNonReferenceType(), SemaRef.getASTContext()));
628 VD->setIsUsed();
629 return DeclRefExpr::Create(
630 SemaRef.getASTContext(), DRE->getQualifierLoc(),
631 DRE->getTemplateKeywordLoc(), VD, false, DRE->getNameInfo(),
632 DRE->getType(), DRE->getValueKind());
633 }
634 }
635 return DRE;
636 }
637
638 // Diagnose CXXThisExpr in a potentially evaluated expression.
639 ExprResult TransformCXXThisExpr(CXXThisExpr *CTE) {
641 SemaRef.Diag(CTE->getExprLoc(), diag::err_sycl_entry_point_invalid_this)
642 << (CTE->isImplicitCXXThis() ? /* implicit */ 1 : /* empty */ 0)
643 << FD->getAttr<SYCLKernelEntryPointAttr>();
644 }
645 return CTE;
646 }
647
648private:
649 Sema &SemaRef;
650 ParmDeclMap &MapRef;
651 FunctionDecl *FD;
652};
653
654OutlinedFunctionDecl *BuildSYCLKernelEntryPointOutline(Sema &SemaRef,
655 FunctionDecl *FD,
656 CompoundStmt *Body) {
657 using ParmDeclMap = OutlinedFunctionDeclBodyInstantiator::ParmDeclMap;
658 ParmDeclMap ParmMap;
659
661 SemaRef.getASTContext(), FD, FD->getNumParams());
662 unsigned i = 0;
663 for (ParmVarDecl *PVD : FD->parameters()) {
665 SemaRef.getASTContext(), OFD, SourceLocation(), PVD->getIdentifier(),
667 OFD->setParam(i, IPD);
668 ParmMap[PVD] = IPD;
669 ++i;
670 }
671
672 OutlinedFunctionDeclBodyInstantiator OFDBodyInstantiator(SemaRef, ParmMap,
673 FD);
674 Stmt *OFDBody = OFDBodyInstantiator.TransformStmt(Body).get();
675 OFD->setBody(OFDBody);
676 OFD->setNothrow();
677
678 return OFD;
679}
680
681class KernelParamsChecker : public ConstSubobjectVisitor<KernelParamsChecker> {
682 SemaSYCL &SemaSYCLRef;
683 bool IsValid = true;
684 using ObjectAccess =
685 llvm::PointerUnion<const ParmVarDecl *, const CXXBaseSpecifier *,
686 const FieldDecl *>;
687 SmallVector<ObjectAccess, 4> ObjectAccessPath;
688
689 void emitObjectAccessPathNotes() {
690 for (auto Parent : llvm::reverse(ObjectAccessPath)) {
691 if (auto *FD = dyn_cast<const FieldDecl *>(Parent)) {
692 const CXXRecordDecl *ParentRD = cast<CXXRecordDecl>(FD->getParent());
693 if (ParentRD->isLambda()) {
694 SemaSYCLRef.Diag(ParentRD->getLocation(), diag::note_within_capture)
695 << ParentRD->getCapture(FD->getFieldIndex())->getCapturedVar();
696 } else {
697 SemaSYCLRef.Diag(ParentRD->getLocation(),
698 diag::note_within_field_of_type)
699 << ParentRD;
700 }
701 } else if (auto *BS = dyn_cast<const CXXBaseSpecifier *>(Parent)) {
702 CXXRecordDecl *RD = BS->getType()->getAsCXXRecordDecl();
703 assert(RD);
704 SemaSYCLRef.Diag(BS->getBeginLoc(), diag::note_within_base_of_type)
705 << RD;
706 } else {
707 auto *Param = cast<const ParmVarDecl *>(Parent);
708 SemaSYCLRef.Diag(Param->getBeginLoc(), diag::note_within_param_of_type)
709 << Param << Param->getType();
710 }
711 }
712 }
713
714public:
715 KernelParamsChecker(SemaSYCL &SR, SourceLocation Loc)
716 : ConstSubobjectVisitor<KernelParamsChecker>(SR.getASTContext()),
717 SemaSYCLRef(SR) {}
718
719 void checkParameter(const ParmVarDecl *PVD) {
720 ObjectAccessPath.push_back(PVD);
721 // Check the immediate type of the parameter.
722 if (checkType(PVD->getType())) {
723 // If type checking wasn't short circuited, visit subobjects to check
724 // them.
725 visit(PVD->getType());
726 }
727 ObjectAccessPath.pop_back();
728 assert(ObjectAccessPath.empty());
729 }
730
731 bool visitBaseSpecifierPre(const CXXBaseSpecifier *BS) {
732 ObjectAccessPath.push_back(BS);
733 return checkType(BS->getType());
734 }
735
736 bool visitFieldDeclPre(const FieldDecl *FD) {
737 ObjectAccessPath.push_back(FD);
738 return checkType(FD->getType());
739 }
740
741 // Returns true if subobjects should be visited and false otherwise.
742 bool checkType(QualType Ty) {
743 if (Ty->isReferenceType()) {
744 auto DirectParent = ObjectAccessPath.back();
745 // Reference cannot be a base, so just assume we came via a FieldDecl.
746 if (isa<const ParmVarDecl *>(DirectParent)) {
747 // If reference is a kernel parameter, there is nothing to do. We allow
748 // references in direct kernel parameters for better performance of the
749 // host code and we eliminate them when building actual kernel.
750 return true;
751 }
752
753 auto *DirectFieldParent = cast<const FieldDecl *>(DirectParent);
754 SemaSYCLRef.Diag(DirectFieldParent->getLocation(),
755 diag::err_bad_kernel_param_type)
756 << DirectFieldParent->getType();
757 emitObjectAccessPathNotes();
758
759 // Don't visit the type of the reference since any further invalid
760 // kernel parameter types contained within the referenced type
761 // might not be relevant once the programmer addresses the
762 // invalid use of a reference.
763 IsValid = false;
764 return false;
765 }
766 return true;
767 }
768
769 void visitFieldDeclPost(const FieldDecl *FD) { ObjectAccessPath.pop_back(); }
770 void visitBaseSpecifierPost(const CXXBaseSpecifier *BS) {
771 ObjectAccessPath.pop_back();
772 }
773
774 bool isInvalid() { return !IsValid; }
775};
776
777bool verifyKernelParams(FunctionDecl *FD, SemaSYCL &SemaSYCLRef) {
778 KernelParamsChecker KAC(SemaSYCLRef, FD->getLocation());
779 for (auto Param : FD->parameters())
780 KAC.checkParameter(Param);
781 return KAC.isInvalid();
782}
783
784} // unnamed namespace
785
787 CompoundStmt *Body,
788 Expr *LaunchIdExpr) {
789 assert(!FD->isInvalidDecl());
790 assert(!FD->isTemplated());
791 assert(FD->hasPrototype());
792 // The current context must be the function definition context to ensure
793 // that name lookup and parameter and local variable creation are performed
794 // within the correct scope.
795 assert(SemaRef.CurContext == FD && "The current declaration context does not "
796 "match the requested function context");
797
798 const auto *SKEPAttr = FD->getAttr<SYCLKernelEntryPointAttr>();
799 assert(SKEPAttr && "Missing sycl_kernel_entry_point attribute");
800 assert(!SKEPAttr->isInvalidAttr() &&
801 "sycl_kernel_entry_point attribute is invalid");
802
803 // Ensure that the kernel name was previously registered and that the
804 // stored declaration matches.
805 const SYCLKernelInfo &SKI =
806 getASTContext().getSYCLKernelInfo(SKEPAttr->getKernelName());
808 "SYCL kernel name conflict");
809 if (verifyKernelParams(FD, *this))
810 return StmtError();
811
812 // Build the outline of the synthesized device entry point function.
814 BuildSYCLKernelEntryPointOutline(SemaRef, FD, Body);
815 assert(OFD);
816
817 // Build the host kernel launch statement. An appropriate source location
818 // is required to emit diagnostics.
819 SourceLocation Loc = Body->getLBracLoc();
820 StmtResult LaunchResult =
821 BuildSYCLKernelLaunchCallStmt(SemaRef, FD, &SKI, LaunchIdExpr, Loc);
822 if (LaunchResult.isInvalid())
823 return StmtError();
824
825 Stmt *NewBody =
826 new (getASTContext()) SYCLKernelCallStmt(Body, LaunchResult.get(), OFD);
827
828 return NewBody;
829}
830
832 Expr *LaunchIdExpr) {
833 return UnresolvedSYCLKernelCallStmt::Create(SemaRef.getASTContext(), Body,
834 LaunchIdExpr);
835}
Defines the Diagnostic-related interfaces.
FormatToken * Next
The next token in the unwrapped line.
This file declares types used to describe SYCL kernels.
static bool isZeroSizedArray(const ConstantArrayType *CAT)
Definition SemaHLSL.cpp:392
static SourceLocation SourceLocationForUserDeclaredType(QualType QT)
Definition SemaSYCL.cpp:248
static bool CheckSYCLKernelName(Sema &S, SourceLocation Loc, QualType KernelName)
Definition SemaSYCL.cpp:258
This file declares semantic analysis for SYCL constructs.
static bool isInvalid(LocType Loc, bool *Invalid)
This file defines SYCL AST classes used to represent calls to SYCL kernels.
Allows QualTypes to be sorted and hence used in maps and sets.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
const ConstantArrayType * getAsConstantArrayType(QualType T) const
IdentifierTable & Idents
Definition ASTContext.h:852
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
CanQualType CharTy
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
void registerSYCLEntryPointFunction(FunctionDecl *FD)
Generates and stores SYCL kernel metadata for the provided SYCL kernel entry point function.
const SYCLKernelInfo & getSYCLKernelInfo(QualType T) const
Given a type used as a SYCL kernel name, returns a reference to the metadata generated from the corre...
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
const SYCLKernelInfo * findSYCLKernelInfo(QualType T) const
Returns a pointer to the metadata generated from the corresponding SYCLkernel entry point if the prov...
PtrTy get() const
Definition Ownership.h:171
bool isInvalid() const
Definition Ownership.h:167
SourceLocation getLoc() const
QualType getType() const
Retrieves the type of the base class.
Definition DeclCXX.h:249
bool isLambda() const
Determine whether this class describes a lambda function object.
Definition DeclCXX.h:1028
const LambdaCapture * getCapture(unsigned I) const
Definition DeclCXX.h:1124
Represents a C++ nested-name-specifier or a global scope specifier.
Definition DeclSpec.h:77
QualType withConst() const
Retrieves a version of this type with const applied.
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition Stmt.h:1751
SourceLocation getLBracLoc() const
Definition Stmt.h:1868
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
Definition Stmt.cpp:399
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2121
DeclarationNameInfo getNameInfo() const
Definition Expr.h:1387
SourceLocation getTemplateKeywordLoc() const
Retrieve the location of the template keyword preceding this name, if any.
Definition Expr.h:1442
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Definition Expr.cpp:498
NestedNameSpecifierLoc getQualifierLoc() const
If the name was qualified, retrieves the nested-name-specifier that precedes the name,...
Definition Expr.h:1408
ValueDecl * getDecl()
Definition Expr.h:1383
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:582
void addAttr(Attr *A)
bool isTemplated() const
Determine whether this declaration is a templated entity (whether it is.
Definition DeclBase.cpp:308
bool isInvalidDecl() const
Definition DeclBase.h:597
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition DeclBase.h:568
SourceLocation getLocation() const
Definition DeclBase.h:448
void setIsUsed()
Set whether the declaration is used, in the sense of odr-use.
Definition DeclBase.h:617
This represents one expression.
Definition Expr.h:114
bool isImplicitCXXThis() const
Whether this expression is an implicit reference to 'this' in C++.
Definition Expr.cpp:3334
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition Expr.h:449
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:146
Represents difference between two FPOptions values.
Represents a function declaration or definition.
Definition Decl.h:2071
bool isFunctionTemplateSpecialization() const
Determine whether this function is a function template specialization.
Definition Decl.cpp:4269
bool isNoReturn() const
Determines whether this function is known to be 'noreturn', through an attribute on its declaration o...
Definition Decl.cpp:3713
QualType getReturnType() const
Definition Decl.h:2992
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2917
bool hasPrototype() const
Whether this function has a prototype, either because one was explicitly written or because it was "i...
Definition Decl.h:2582
FunctionTemplateSpecializationInfo * getTemplateSpecializationInfo() const
If this function is actually a function template specialization, retrieve information about this func...
Definition Decl.cpp:4387
bool isVariadic() const
Whether this function is variadic.
Definition Decl.cpp:3139
bool isDeleted() const
Whether this function has been deleted.
Definition Decl.h:2679
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition Decl.h:2609
bool isDeletedAsWritten() const
Definition Decl.h:2683
bool isDefaulted() const
Whether this function is defaulted.
Definition Decl.h:2524
bool isConsteval() const
Definition Decl.h:2621
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3888
FunctionDecl * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
Declaration of a template function.
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition Expr.cpp:2109
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
Definition Decl.cpp:5699
ValueDecl * getCapturedVar() const
Retrieve the declaration of the local variable being captured.
Represents the results of name lookup.
Definition Lookup.h:147
This represents a decl that may have a name.
Definition Decl.h:276
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:297
bool isExternallyVisible() const
Definition Decl.h:435
Represents a partial function definition.
Definition Decl.h:5033
static OutlinedFunctionDecl * Create(ASTContext &C, DeclContext *DC, unsigned NumParams)
Definition Decl.cpp:5760
void setNothrow(bool Nothrow=true)
Definition Decl.cpp:5780
void setParam(unsigned i, ImplicitParamDecl *P)
Definition Decl.h:5069
Represents a parameter to a function.
Definition Decl.h:1832
ParsedAttr - Represents a syntactic attribute.
Definition ParsedAttr.h:119
const ParsedType & getTypeArg() const
Definition ParsedAttr.h:459
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1005
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition TypeBase.h:8763
bool isMoreQualifiedThan(QualType Other, const ASTContext &Ctx) const
Determine whether this type is more qualified than the other given type, requiring exact equality for...
Definition TypeBase.h:8732
SYCLKernelCallStmt represents the transformation that is applied to the body of a function declared w...
Definition StmtSYCL.h:36
const std::string & GetKernelName() const
const FunctionDecl * getKernelEntryPointDecl() const
static SYCLUniqueStableNameExpr * Create(const ASTContext &Ctx, SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, TypeSourceInfo *TSI)
Definition Expr.cpp:583
A generic diagnostic builder for errors which may or may not be deferred.
Definition SemaBase.h:111
SemaBase(Sema &S)
Definition SemaBase.cpp:7
ASTContext & getASTContext() const
Definition SemaBase.cpp:9
Sema & SemaRef
Definition SemaBase.h:40
const LangOptions & getLangOpts() const
Definition SemaBase.cpp:11
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Definition SemaBase.cpp:61
StmtResult BuildUnresolvedSYCLKernelCallStmt(CompoundStmt *Body, Expr *LaunchIdExpr)
Builds an UnresolvedSYCLKernelCallStmt to wrap 'Body'.
Definition SemaSYCL.cpp:831
StmtResult BuildSYCLKernelCallStmt(FunctionDecl *FD, CompoundStmt *Body, Expr *LaunchIdExpr)
Builds a SYCLKernelCallStmt to wrap 'Body' and to be used as the body of 'FD'.
Definition SemaSYCL.cpp:786
SemaDiagnosticBuilder DiagIfDeviceCode(SourceLocation Loc, unsigned DiagID)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as device c...
Definition SemaSYCL.cpp:31
void CheckSYCLExternalFunctionDecl(FunctionDecl *FD)
Definition SemaSYCL.cpp:293
ExprResult BuildUniqueStableNameExpr(SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, TypeSourceInfo *TSI)
Definition SemaSYCL.cpp:154
void handleKernelEntryPointAttr(Decl *D, const ParsedAttr &AL)
Definition SemaSYCL.cpp:216
void deepTypeCheckForDevice(SourceLocation UsedAt, llvm::DenseSet< QualType > Visited, ValueDecl *DeclToCheck)
Definition SemaSYCL.cpp:62
void handleSYCLExternalAttr(Decl *D, const ParsedAttr &AL)
Definition SemaSYCL.cpp:281
void handleKernelAttr(Decl *D, const ParsedAttr &AL)
Definition SemaSYCL.cpp:177
SemaSYCL(Sema &S)
Definition SemaSYCL.cpp:29
void CheckSYCLEntryPointFunctionDecl(FunctionDecl *FD)
Definition SemaSYCL.cpp:310
void CheckDeviceUseOfDecl(NamedDecl *ND, SourceLocation Loc)
Issues a deferred diagnostic if use of the declaration designated by 'ND' is invalid in a device cont...
Definition SemaSYCL.cpp:225
ExprResult BuildSYCLKernelLaunchIdExpr(FunctionDecl *FD, QualType KernelName)
Builds an expression for the lookup of a 'sycl_kernel_launch' template with 'KernelName' as an explic...
Definition SemaSYCL.cpp:440
ExprResult ActOnUniqueStableNameExpr(SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, ParsedType ParsedTy)
Definition SemaSYCL.cpp:162
RAII object to ensure that a code synthesis context is popped on scope exit.
Definition Sema.h:13824
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:862
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition Sema.h:1164
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition Sema.h:9501
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
Definition Sema.h:4927
const ExpressionEvaluationContextRecord & currentEvaluationContext() const
Definition Sema.h:7076
ASTContext & Context
Definition Sema.h:1331
ASTContext & getASTContext() const
Definition Sema.h:934
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
ExprResult BuildCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr, bool IsExecConfig=false, bool AllowRecovery=false)
BuildCallExpr - Handle a call to Fn with the specified array of arguments.
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition Sema.h:1471
Expr * MaybeCreateExprWithCleanups(Expr *SubExpr)
MaybeCreateExprWithCleanups - If the current full-expression requires any cleanups,...
@ TemplateNameIsRequired
Definition Sema.h:11620
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
Stmt - This represents one statement.
Definition Stmt.h:85
static StringLiteral * Create(const ASTContext &Ctx, StringRef Str, StringLiteralKind Kind, bool Pascal, QualType Ty, ArrayRef< SourceLocation > Locs)
This is the "fully general" constructor that allows representation of strings formed from one or more...
Definition Expr.cpp:1198
A convenient class for passing around template argument information.
void addArgument(const TemplateArgumentLoc &Loc)
Location wrapper for a TemplateArgument.
Represents a template argument.
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Stores a list of template parameters for a TemplateDecl and its derived classes.
NamedDecl * getParam(unsigned Idx)
A semantic tree transformation that allows one to transform one abstract syntax tree into another.
A container of type source information.
Definition TypeBase.h:8549
The base class of the type hierarchy.
Definition TypeBase.h:1879
bool isVoidType() const
Definition TypeBase.h:9200
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool isArrayType() const
Definition TypeBase.h:8914
bool isReferenceType() const
Definition TypeBase.h:8839
const Type * getArrayElementTypeNoTypeQual() const
If this is an array type, return the element type of the array, potentially with type qualifiers miss...
Definition Type.cpp:595
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:885
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition TypeBase.h:2863
bool isUndeducedType() const
Determine whether this type is an undeduced type, meaning that it somehow involves a C++11 'auto' typ...
Definition TypeBase.h:9347
bool isStructureOrClassType() const
Definition Type.cpp:839
bool isAnyPointerType() const
Definition TypeBase.h:8823
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
Definition Type.cpp:786
static UnresolvedSYCLKernelCallStmt * Create(const ASTContext &C, CompoundStmt *CS, Expr *IdExpr)
Definition StmtSYCL.h:120
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:714
QualType getType() const
Definition Decl.h:725
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
QualType getFunctionOrMethodResultType(const Decl *D)
Definition Attr.h:136
StmtResult StmtError()
Definition Ownership.h:266
@ Result
The result type of a method or function.
Definition TypeBase.h:906
const FunctionProtoType * T
ExprResult ExprError()
Definition Ownership.h:265
unsigned getFunctionOrMethodNumParams(const Decl *D, bool IncludeThis=false)
getFunctionOrMethodNumParams - Return number of function or method parameters, optionally including t...
Definition Attr.h:66
void handleSimpleAttribute(SemaBase &S, Decl *D, const AttributeCommonInfo &CI)
Applies the given attribute to the Decl without performing any additional semantic checking.
Definition Attr.h:213
@ VK_XValue
An x-value expression is a reference to an object with independent storage but which can be "moved",...
Definition Specifiers.h:148
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition Specifiers.h:143
bool declaresSameEntity(const Decl *D1, const Decl *D2)
Determine whether two declarations declare the same entity.
Definition DeclBase.h:1306
U cast(CodeGen::Address addr)
Definition Address.h:327
OpaquePtr< QualType > ParsedType
An opaque type for threading parsed type information through the parser.
Definition Ownership.h:230
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
@ Other
Other implicit parameter.
Definition Decl.h:1787
ActionResult< Stmt * > StmtResult
Definition Ownership.h:250
A context in which code is being synthesized (where a source location alone is not sufficient to iden...
Definition Sema.h:13345
enum clang::Sema::CodeSynthesisContext::SynthesisKind Kind
unsigned NumCallArgs
The number of expressions in CallArgs.
Definition Sema.h:13502
const Expr *const * CallArgs
The list of argument expressions in a synthesized call.
Definition Sema.h:13492
@ SYCLKernelLaunchOverloadResolution
We are performing overload resolution for a call to a function template or variable template named 's...
Definition Sema.h:13463
@ SYCLKernelLaunchLookup
We are performing name lookup for a function template or variable template named 'sycl_kernel_launch'...
Definition Sema.h:13459
Decl * Entity
The entity that is being synthesized.
Definition Sema.h:13479