clang 23.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 const auto *SEAttr = FD->getAttr<SYCLExternalAttr>();
283 assert(SEAttr && "Missing sycl_external attribute");
284 if (!FD->isInvalidDecl() && !FD->isTemplated()) {
285 if (!FD->isExternallyVisible())
288 Diag(SEAttr->getLocation(), diag::err_sycl_external_invalid_linkage)
289 << SEAttr;
290 }
291 if (FD->isDeletedAsWritten()) {
292 Diag(SEAttr->getLocation(),
293 diag::err_sycl_external_invalid_deleted_function)
294 << SEAttr;
295 }
296}
297
299 // Ensure that all attributes present on the declaration are consistent
300 // and warn about any redundant ones.
301 SYCLKernelEntryPointAttr *SKEPAttr = nullptr;
302 for (auto *SAI : FD->specific_attrs<SYCLKernelEntryPointAttr>()) {
303 if (!SKEPAttr) {
304 SKEPAttr = SAI;
305 continue;
306 }
307 if (!getASTContext().hasSameType(SAI->getKernelName(),
308 SKEPAttr->getKernelName())) {
309 Diag(SAI->getLocation(), diag::err_sycl_entry_point_invalid_redeclaration)
310 << SKEPAttr << SAI->getKernelName() << SKEPAttr->getKernelName();
311 Diag(SKEPAttr->getLocation(), diag::note_previous_attribute);
312 SAI->setInvalidAttr();
313 } else {
314 Diag(SAI->getLocation(),
315 diag::warn_sycl_entry_point_redundant_declaration)
316 << SAI;
317 Diag(SKEPAttr->getLocation(), diag::note_previous_attribute);
318 }
319 }
320 assert(SKEPAttr && "Missing sycl_kernel_entry_point attribute");
321
322 // Ensure the kernel name type is valid.
323 if (!SKEPAttr->getKernelName()->isDependentType() &&
324 CheckSYCLKernelName(SemaRef, SKEPAttr->getLocation(),
325 SKEPAttr->getKernelName()))
326 SKEPAttr->setInvalidAttr();
327
328 // Ensure that an attribute present on the previous declaration
329 // matches the one on this declaration.
330 FunctionDecl *PrevFD = FD->getPreviousDecl();
331 if (PrevFD && !PrevFD->isInvalidDecl()) {
332 const auto *PrevSKEPAttr = PrevFD->getAttr<SYCLKernelEntryPointAttr>();
333 if (PrevSKEPAttr && !PrevSKEPAttr->isInvalidAttr()) {
334 if (!getASTContext().hasSameType(SKEPAttr->getKernelName(),
335 PrevSKEPAttr->getKernelName())) {
336 Diag(SKEPAttr->getLocation(),
337 diag::err_sycl_entry_point_invalid_redeclaration)
338 << SKEPAttr << SKEPAttr->getKernelName()
339 << PrevSKEPAttr->getKernelName();
340 Diag(PrevSKEPAttr->getLocation(), diag::note_previous_decl) << PrevFD;
341 SKEPAttr->setInvalidAttr();
342 }
343 }
344 }
345
346 if (isa<CXXConstructorDecl>(FD)) {
347 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
348 << SKEPAttr << diag::InvalidSKEPReason::Constructor;
349 SKEPAttr->setInvalidAttr();
350 }
351 if (isa<CXXDestructorDecl>(FD)) {
352 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
353 << SKEPAttr << diag::InvalidSKEPReason::Destructor;
354 SKEPAttr->setInvalidAttr();
355 }
356 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
357 if (MD->isExplicitObjectMemberFunction()) {
358 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
359 << SKEPAttr << diag::InvalidSKEPReason::ExplicitObjectFn;
360 SKEPAttr->setInvalidAttr();
361 }
362 }
363
364 if (FD->isVariadic()) {
365 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
366 << SKEPAttr << diag::InvalidSKEPReason::VariadicFn;
367 SKEPAttr->setInvalidAttr();
368 }
369
370 if (FD->isDefaulted()) {
371 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
372 << SKEPAttr << diag::InvalidSKEPReason::DefaultedFn;
373 SKEPAttr->setInvalidAttr();
374 } else if (FD->isDeleted()) {
375 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
376 << SKEPAttr << diag::InvalidSKEPReason::DeletedFn;
377 SKEPAttr->setInvalidAttr();
378 }
379
380 if (FD->isConsteval()) {
381 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
382 << SKEPAttr << diag::InvalidSKEPReason::ConstevalFn;
383 SKEPAttr->setInvalidAttr();
384 } else if (FD->isConstexpr()) {
385 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
386 << SKEPAttr << diag::InvalidSKEPReason::ConstexprFn;
387 SKEPAttr->setInvalidAttr();
388 }
389
390 if (FD->isNoReturn()) {
391 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)
392 << SKEPAttr << diag::InvalidSKEPReason::NoreturnFn;
393 SKEPAttr->setInvalidAttr();
394 }
395
396 if (FD->getReturnType()->isUndeducedType()) {
397 Diag(SKEPAttr->getLocation(),
398 diag::err_sycl_entry_point_deduced_return_type)
399 << SKEPAttr;
400 SKEPAttr->setInvalidAttr();
401 } else if (!FD->getReturnType()->isDependentType() &&
402 !FD->getReturnType()->isVoidType()) {
403 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_return_type)
404 << SKEPAttr;
405 SKEPAttr->setInvalidAttr();
406 }
407
408 if (!FD->isInvalidDecl() && !FD->isTemplated() &&
409 !SKEPAttr->isInvalidAttr()) {
410 const SYCLKernelInfo *SKI =
411 getASTContext().findSYCLKernelInfo(SKEPAttr->getKernelName());
412 if (SKI) {
414 // FIXME: This diagnostic should include the origin of the kernel
415 // FIXME: names; not just the locations of the conflicting declarations.
416 Diag(FD->getLocation(), diag::err_sycl_kernel_name_conflict)
417 << SKEPAttr;
419 diag::note_previous_declaration);
420 SKEPAttr->setInvalidAttr();
421 }
422 } else {
424 }
425 }
426}
427
429 QualType KNT) {
430 // The current context must be the function definition context to ensure
431 // that name lookup is performed within the correct scope.
432 assert(SemaRef.CurContext == FD && "The current declaration context does not "
433 "match the requested function context");
434
435 // An appropriate source location is required to emit diagnostics if
436 // lookup fails to produce an overload set. The desired location is the
437 // start of the function body, but that is not yet available since the
438 // body of the function has not yet been set when this function is called.
439 // The general location of the function is used instead.
440 SourceLocation Loc = FD->getLocation();
441
442 ASTContext &Ctx = SemaRef.getASTContext();
443 IdentifierInfo &SYCLKernelLaunchID =
444 Ctx.Idents.get("sycl_kernel_launch", tok::TokenKind::identifier);
445
446 // Establish a code synthesis context for the implicit name lookup of
447 // a template named 'sycl_kernel_launch'. In the event of an error, this
448 // ensures an appropriate diagnostic note is issued to explain why the
449 // lookup was performed.
452 CSC.Entity = FD;
454
455 // Perform ordinary name lookup for a function or variable template that
456 // accepts a single type template argument.
457 LookupResult Result(SemaRef, &SYCLKernelLaunchID, Loc,
459 CXXScopeSpec EmptySS;
460 if (SemaRef.LookupTemplateName(Result, SemaRef.getCurScope(), EmptySS,
461 /*ObjectType*/ QualType(),
462 /*EnteringContext*/ false,
464 return ExprError();
465 if (Result.isAmbiguous())
466 return ExprError();
467
468 TemplateArgumentListInfo TALI{Loc, Loc};
471 SemaRef.getTrivialTemplateArgumentLoc(KNTA, QualType(), Loc);
472 TALI.addArgument(TAL);
473
474 ExprResult IdExpr;
475 if (SemaRef.isPotentialImplicitMemberAccess(EmptySS, Result,
476 /*IsAddressOfOperand*/ false)) {
477 // The lookup result allows for a possible implicit member access that
478 // would require an implicit or explicit 'this' argument.
479 IdExpr = SemaRef.BuildPossibleImplicitMemberExpr(
480 EmptySS, SourceLocation(), Result, &TALI, SemaRef.getCurScope());
481 } else {
482 IdExpr = SemaRef.BuildTemplateIdExpr(EmptySS, SourceLocation(), Result,
483 /*RequiresADL*/ true, &TALI);
484 }
485
486 // The resulting expression may be invalid if, for example, 'FD' is a
487 // non-static member function and sycl_kernel_launch lookup selects a
488 // member function (which would require a 'this' argument which is
489 // not available).
490 if (IdExpr.isInvalid())
491 return ExprError();
492
493 return IdExpr;
494}
495
496namespace {
497
498// Constructs the arguments to be passed for the SYCL kernel launch call.
499// The first argument is a string literal that contains the SYCL kernel
500// name. The remaining arguments are the parameters of 'FD' passed as
501// move-elligible xvalues. Returns true on error and false otherwise.
502bool BuildSYCLKernelLaunchCallArgs(Sema &SemaRef, FunctionDecl *FD,
503 const SYCLKernelInfo *SKI,
505 SourceLocation Loc) {
506 // The current context must be the function definition context to ensure
507 // that parameter references occur within the correct scope.
508 assert(SemaRef.CurContext == FD && "The current declaration context does not "
509 "match the requested function context");
510
511 // Prepare a string literal that contains the kernel name.
512 ASTContext &Ctx = SemaRef.getASTContext();
513 const std::string &KernelName = SKI->GetKernelName();
514 QualType KernelNameCharTy = Ctx.CharTy.withConst();
515 llvm::APInt KernelNameSize(Ctx.getTypeSize(Ctx.getSizeType()),
516 KernelName.size() + 1);
517 QualType KernelNameArrayTy = Ctx.getConstantArrayType(
518 KernelNameCharTy, KernelNameSize, nullptr, ArraySizeModifier::Normal, 0);
519 Expr *KernelNameExpr =
521 /*Pascal*/ false, KernelNameArrayTy, Loc);
522 Args.push_back(KernelNameExpr);
523
524 // Forward all parameters of 'FD' to the SYCL kernel launch function as if
525 // by std::move().
526 for (ParmVarDecl *PVD : FD->parameters()) {
527 QualType ParamType = PVD->getOriginalType().getNonReferenceType();
528 ExprResult E = SemaRef.BuildDeclRefExpr(PVD, ParamType, VK_LValue, Loc);
529 if (E.isInvalid())
530 return true;
531 if (!PVD->getType()->isLValueReferenceType())
532 E = ImplicitCastExpr::Create(SemaRef.Context, E.get()->getType(), CK_NoOp,
533 E.get(), nullptr, VK_XValue,
535 if (E.isInvalid())
536 return true;
537 Args.push_back(E.get());
538 }
539
540 return false;
541}
542
543// Constructs the SYCL kernel launch call.
544StmtResult BuildSYCLKernelLaunchCallStmt(Sema &SemaRef, FunctionDecl *FD,
545 const SYCLKernelInfo *SKI,
546 Expr *IdExpr, SourceLocation Loc) {
548 // IdExpr may be null if name lookup failed.
549 if (IdExpr) {
551
552 // Establish a code synthesis context for construction of the arguments
553 // for the implicit call to 'sycl_kernel_launch'.
554 {
557 CSC.Entity = FD;
558 Sema::ScopedCodeSynthesisContext ScopedCSC(SemaRef, CSC);
559
560 if (BuildSYCLKernelLaunchCallArgs(SemaRef, FD, SKI, Args, Loc))
561 return StmtError();
562 }
563
564 // Establish a code synthesis context for the implicit call to
565 // 'sycl_kernel_launch'.
566 {
569 CSC.Entity = FD;
570 CSC.CallArgs = Args.data();
571 CSC.NumCallArgs = Args.size();
572 Sema::ScopedCodeSynthesisContext ScopedCSC(SemaRef, CSC);
573
574 ExprResult LaunchResult =
575 SemaRef.BuildCallExpr(SemaRef.getCurScope(), IdExpr, Loc, Args, Loc);
576 if (LaunchResult.isInvalid())
577 return StmtError();
578
579 Stmts.push_back(SemaRef.MaybeCreateExprWithCleanups(LaunchResult).get());
580 }
581 }
582
583 return CompoundStmt::Create(SemaRef.getASTContext(), Stmts,
584 FPOptionsOverride(), Loc, Loc);
585}
586
587// The body of a function declared with the [[sycl_kernel_entry_point]]
588// attribute is cloned and transformed to substitute references to the original
589// function parameters with references to replacement variables that stand in
590// for SYCL kernel parameters or local variables that reconstitute a decomposed
591// SYCL kernel argument.
592class OutlinedFunctionDeclBodyInstantiator
593 : public TreeTransform<OutlinedFunctionDeclBodyInstantiator> {
594public:
595 using ParmDeclMap = llvm::DenseMap<ParmVarDecl *, VarDecl *>;
596
597 OutlinedFunctionDeclBodyInstantiator(Sema &S, ParmDeclMap &M,
598 FunctionDecl *FD)
599 : TreeTransform<OutlinedFunctionDeclBodyInstantiator>(S), SemaRef(S),
600 MapRef(M), FD(FD) {}
601
602 // A new set of AST nodes is always required.
603 bool AlwaysRebuild() { return true; }
604
605 // Transform ParmVarDecl references to the supplied replacement variables.
606 ExprResult TransformDeclRefExpr(DeclRefExpr *DRE) {
607 const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl());
608 if (PVD) {
609 ParmDeclMap::iterator I = MapRef.find(PVD);
610 if (I != MapRef.end()) {
611 VarDecl *VD = I->second;
612 assert(SemaRef.getASTContext().hasSameUnqualifiedType(
613 PVD->getType().getNonReferenceType(), VD->getType()));
614 assert(!VD->getType().isMoreQualifiedThan(
615 PVD->getType().getNonReferenceType(), SemaRef.getASTContext()));
616 VD->setIsUsed();
617 return DeclRefExpr::Create(
618 SemaRef.getASTContext(), DRE->getQualifierLoc(),
619 DRE->getTemplateKeywordLoc(), VD, false, DRE->getNameInfo(),
620 DRE->getType(), DRE->getValueKind());
621 }
622 }
623 return DRE;
624 }
625
626 // Diagnose CXXThisExpr in a potentially evaluated expression.
627 ExprResult TransformCXXThisExpr(CXXThisExpr *CTE) {
629 SemaRef.Diag(CTE->getExprLoc(), diag::err_sycl_entry_point_invalid_this)
630 << (CTE->isImplicitCXXThis() ? /* implicit */ 1 : /* empty */ 0)
631 << FD->getAttr<SYCLKernelEntryPointAttr>();
632 }
633 return CTE;
634 }
635
636private:
637 Sema &SemaRef;
638 ParmDeclMap &MapRef;
639 FunctionDecl *FD;
640};
641
642OutlinedFunctionDecl *BuildSYCLKernelEntryPointOutline(Sema &SemaRef,
643 FunctionDecl *FD,
644 CompoundStmt *Body) {
645 using ParmDeclMap = OutlinedFunctionDeclBodyInstantiator::ParmDeclMap;
646 ParmDeclMap ParmMap;
647
649 SemaRef.getASTContext(), FD, FD->getNumParams());
650 unsigned i = 0;
651 for (ParmVarDecl *PVD : FD->parameters()) {
653 SemaRef.getASTContext(), OFD, SourceLocation(), PVD->getIdentifier(),
655 OFD->setParam(i, IPD);
656 ParmMap[PVD] = IPD;
657 ++i;
658 }
659
660 OutlinedFunctionDeclBodyInstantiator OFDBodyInstantiator(SemaRef, ParmMap,
661 FD);
662 Stmt *OFDBody = OFDBodyInstantiator.TransformStmt(Body).get();
663 OFD->setBody(OFDBody);
664 OFD->setNothrow();
665
666 return OFD;
667}
668
669class KernelParamsChecker : public ConstSubobjectVisitor<KernelParamsChecker> {
670 SemaSYCL &SemaSYCLRef;
671 bool IsValid = true;
672 using ObjectAccess =
673 llvm::PointerUnion<const ParmVarDecl *, const CXXBaseSpecifier *,
674 const FieldDecl *>;
675 SmallVector<ObjectAccess, 4> ObjectAccessPath;
676
677 void emitObjectAccessPathNotes() {
678 for (auto Parent : llvm::reverse(ObjectAccessPath)) {
679 if (auto *FD = Parent.dyn_cast<const FieldDecl *>()) {
680 const CXXRecordDecl *ParentRD = cast<CXXRecordDecl>(FD->getParent());
681 if (ParentRD->isLambda()) {
682 SemaSYCLRef.Diag(ParentRD->getLocation(), diag::note_within_capture)
683 << ParentRD->getCapture(FD->getFieldIndex())->getCapturedVar();
684 } else {
685 SemaSYCLRef.Diag(ParentRD->getLocation(),
686 diag::note_within_field_of_type)
687 << ParentRD;
688 }
689 } else if (auto *BS = Parent.dyn_cast<const CXXBaseSpecifier *>()) {
690 CXXRecordDecl *RD = BS->getType()->getAsCXXRecordDecl();
691 assert(RD);
692 SemaSYCLRef.Diag(BS->getBeginLoc(), diag::note_within_base_of_type)
693 << RD;
694 } else {
695 auto *Param = cast<const ParmVarDecl *>(Parent);
696 SemaSYCLRef.Diag(Param->getBeginLoc(), diag::note_within_param_of_type)
697 << Param << Param->getType();
698 }
699 }
700 }
701
702public:
703 KernelParamsChecker(SemaSYCL &SR, SourceLocation Loc)
704 : ConstSubobjectVisitor<KernelParamsChecker>(SR.getASTContext()),
705 SemaSYCLRef(SR) {}
706
707 void checkParameter(const ParmVarDecl *PVD) {
708 ObjectAccessPath.push_back(PVD);
709 // Check the immediate type of the parameter.
710 if (checkType(PVD->getType())) {
711 // If type checking wasn't short circuited, visit subobjects to check
712 // them.
713 visit(PVD->getType());
714 }
715 ObjectAccessPath.pop_back();
716 assert(ObjectAccessPath.empty());
717 }
718
719 bool visitBaseSpecifierPre(const CXXBaseSpecifier *BS) {
720 ObjectAccessPath.push_back(BS);
721 return checkType(BS->getType());
722 }
723
724 bool visitFieldDeclPre(const FieldDecl *FD) {
725 ObjectAccessPath.push_back(FD);
726 return checkType(FD->getType());
727 }
728
729 // Returns true if subobjects should be visited and false otherwise.
730 bool checkType(QualType Ty) {
731 if (Ty->isReferenceType()) {
732 auto DirectParent = ObjectAccessPath.back();
733 // Reference cannot be a base, so just assume we came via a FieldDecl.
734 if (isa<const ParmVarDecl *>(DirectParent)) {
735 // If reference is a kernel parameter, there is nothing to do. We allow
736 // references in direct kernel parameters for better performance of the
737 // host code and we eliminate them when building actual kernel.
738 return true;
739 }
740
741 auto *DirectFieldParent = cast<const FieldDecl *>(DirectParent);
742 SemaSYCLRef.Diag(DirectFieldParent->getLocation(),
743 diag::err_bad_kernel_param_type)
744 << DirectFieldParent->getType();
745 emitObjectAccessPathNotes();
746
747 // Don't visit the type of the reference since any further invalid
748 // kernel parameter types contained within the referenced type
749 // might not be relevant once the programmer addresses the
750 // invalid use of a reference.
751 IsValid = false;
752 return false;
753 }
754 return true;
755 }
756
757 void visitFieldDeclPost(const FieldDecl *FD) { ObjectAccessPath.pop_back(); }
758 void visitBaseSpecifierPost(const CXXBaseSpecifier *BS) {
759 ObjectAccessPath.pop_back();
760 }
761
762 bool isInvalid() { return !IsValid; }
763};
764
765bool verifyKernelParams(FunctionDecl *FD, SemaSYCL &SemaSYCLRef) {
766 KernelParamsChecker KAC(SemaSYCLRef, FD->getLocation());
767 for (auto Param : FD->parameters())
768 KAC.checkParameter(Param);
769 return KAC.isInvalid();
770}
771
772} // unnamed namespace
773
775 CompoundStmt *Body,
776 Expr *LaunchIdExpr) {
777 assert(!FD->isInvalidDecl());
778 assert(!FD->isTemplated());
779 assert(FD->hasPrototype());
780 // The current context must be the function definition context to ensure
781 // that name lookup and parameter and local variable creation are performed
782 // within the correct scope.
783 assert(SemaRef.CurContext == FD && "The current declaration context does not "
784 "match the requested function context");
785
786 const auto *SKEPAttr = FD->getAttr<SYCLKernelEntryPointAttr>();
787 assert(SKEPAttr && "Missing sycl_kernel_entry_point attribute");
788 assert(!SKEPAttr->isInvalidAttr() &&
789 "sycl_kernel_entry_point attribute is invalid");
790
791 // Ensure that the kernel name was previously registered and that the
792 // stored declaration matches.
793 const SYCLKernelInfo &SKI =
794 getASTContext().getSYCLKernelInfo(SKEPAttr->getKernelName());
796 "SYCL kernel name conflict");
797 if (verifyKernelParams(FD, *this))
798 return StmtError();
799
800 // Build the outline of the synthesized device entry point function.
802 BuildSYCLKernelEntryPointOutline(SemaRef, FD, Body);
803 assert(OFD);
804
805 // Build the host kernel launch statement. An appropriate source location
806 // is required to emit diagnostics.
807 SourceLocation Loc = Body->getLBracLoc();
808 StmtResult LaunchResult =
809 BuildSYCLKernelLaunchCallStmt(SemaRef, FD, &SKI, LaunchIdExpr, Loc);
810 if (LaunchResult.isInvalid())
811 return StmtError();
812
813 Stmt *NewBody =
814 new (getASTContext()) SYCLKernelCallStmt(Body, LaunchResult.get(), OFD);
815
816 return NewBody;
817}
818
820 Expr *LaunchIdExpr) {
821 return UnresolvedSYCLKernelCallStmt::Create(SemaRef.getASTContext(), Body,
822 LaunchIdExpr);
823}
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:378
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:223
const ConstantArrayType * getAsConstantArrayType(QualType T) const
IdentifierTable & Idents
Definition ASTContext.h:805
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
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:1023
const LambdaCapture * getCapture(unsigned I) const
Definition DeclCXX.h:1119
Represents a C++ nested-name-specifier or a global scope specifier.
Definition DeclSpec.h:76
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:1750
SourceLocation getLBracLoc() const
Definition Stmt.h:1867
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:2126
DeclarationNameInfo getNameInfo() const
Definition Expr.h:1348
SourceLocation getTemplateKeywordLoc() const
Retrieve the location of the template keyword preceding this name, if any.
Definition Expr.h:1403
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:494
NestedNameSpecifierLoc getQualifierLoc() const
If the name was qualified, retrieves the nested-name-specifier that precedes the name,...
Definition Expr.h:1369
ValueDecl * getDecl()
Definition Expr.h:1344
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:581
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:596
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition DeclBase.h:567
SourceLocation getLocation() const
Definition DeclBase.h:447
void setIsUsed()
Set whether the declaration is used, in the sense of odr-use.
Definition DeclBase.h:616
This represents one expression.
Definition Expr.h:112
bool isImplicitCXXThis() const
Whether this expression is an implicit reference to 'this' in C++.
Definition Expr.cpp:3304
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition Expr.h:447
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:144
Represents difference between two FPOptions values.
Represents a function declaration or definition.
Definition Decl.h:2027
bool isFunctionTemplateSpecialization() const
Determine whether this function is a function template specialization.
Definition Decl.cpp:4182
bool isNoReturn() const
Determines whether this function is known to be 'noreturn', through an attribute on its declaration o...
Definition Decl.cpp:3628
QualType getReturnType() const
Definition Decl.h:2876
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2805
bool hasPrototype() const
Whether this function has a prototype, either because one was explicitly written or because it was "i...
Definition Decl.h:2470
FunctionTemplateSpecializationInfo * getTemplateSpecializationInfo() const
If this function is actually a function template specialization, retrieve information about this func...
Definition Decl.cpp:4300
bool isVariadic() const
Whether this function is variadic.
Definition Decl.cpp:3110
bool isDeleted() const
Whether this function has been deleted.
Definition Decl.h:2567
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition Decl.h:2497
bool isDeletedAsWritten() const
Definition Decl.h:2571
bool isDefaulted() const
Whether this function is defaulted.
Definition Decl.h:2412
bool isConsteval() const
Definition Decl.h:2509
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3803
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:2079
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
Definition Decl.cpp:5599
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:274
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:295
bool isExternallyVisible() const
Definition Decl.h:433
Represents a partial function definition.
Definition Decl.h:4914
static OutlinedFunctionDecl * Create(ASTContext &C, DeclContext *DC, unsigned NumParams)
Definition Decl.cpp:5660
void setNothrow(bool Nothrow=true)
Definition Decl.cpp:5680
void setParam(unsigned i, ImplicitParamDecl *P)
Definition Decl.h:4950
Represents a parameter to a function.
Definition Decl.h:1817
ParsedAttr - Represents a syntactic attribute.
Definition ParsedAttr.h:119
const ParsedType & getTypeArg() const
Definition ParsedAttr.h:459
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
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:8632
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:8601
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:579
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:819
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:774
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:281
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 handleKernelAttr(Decl *D, const ParsedAttr &AL)
Definition SemaSYCL.cpp:177
SemaSYCL(Sema &S)
Definition SemaSYCL.cpp:29
void CheckSYCLEntryPointFunctionDecl(FunctionDecl *FD)
Definition SemaSYCL.cpp:298
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:428
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:13676
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:869
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition Sema.h:1142
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition Sema.h:9415
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
Definition Sema.h:4802
const ExpressionEvaluationContextRecord & currentEvaluationContext() const
Definition Sema.h:7017
ASTContext & Context
Definition Sema.h:1309
ASTContext & getASTContext() const
Definition Sema.h:940
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:1447
Expr * MaybeCreateExprWithCleanups(Expr *SubExpr)
MaybeCreateExprWithCleanups - If the current full-expression requires any cleanups,...
@ TemplateNameIsRequired
Definition Sema.h:11486
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:86
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:1194
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:8418
The base class of the type hierarchy.
Definition TypeBase.h:1875
bool isVoidType() const
Definition TypeBase.h:9050
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool isArrayType() const
Definition TypeBase.h:8783
bool isReferenceType() const
Definition TypeBase.h:8708
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:508
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition TypeBase.h:2846
bool isUndeducedType() const
Determine whether this type is an undeduced type, meaning that it somehow involves a C++11 'auto' typ...
Definition TypeBase.h:9193
bool isStructureOrClassType() const
Definition Type.cpp:743
bool isAnyPointerType() const
Definition TypeBase.h:8692
const Type * getUnqualifiedDesugaredType() const
Return the specified type with any "sugar" removed from the type, removing any typedefs,...
Definition Type.cpp:690
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:712
QualType getType() const
Definition Decl.h:723
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
QualType getFunctionOrMethodResultType(const Decl *D)
Definition Attr.h:98
StmtResult StmtError()
Definition Ownership.h:266
@ Result
The result type of a method or function.
Definition TypeBase.h:905
ExprResult ExprError()
Definition Ownership.h:265
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:175
@ VK_XValue
An x-value expression is a reference to an object with independent storage but which can be "moved",...
Definition Specifiers.h:145
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition Specifiers.h:140
unsigned getFunctionOrMethodNumParams(const Decl *D)
getFunctionOrMethodNumParams - Return number of function or method parameters.
Definition Attr.h:64
bool declaresSameEntity(const Decl *D1, const Decl *D2)
Determine whether two declarations declare the same entity.
Definition DeclBase.h:1305
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:1772
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:13206
enum clang::Sema::CodeSynthesisContext::SynthesisKind Kind
unsigned NumCallArgs
The number of expressions in CallArgs.
Definition Sema.h:13360
const Expr *const * CallArgs
The list of argument expressions in a synthesized call.
Definition Sema.h:13350
@ SYCLKernelLaunchOverloadResolution
We are performing overload resolution for a call to a function template or variable template named 's...
Definition Sema.h:13324
@ SYCLKernelLaunchLookup
We are performing name lookup for a function template or variable template named 'sycl_kernel_launch'...
Definition Sema.h:13320
Decl * Entity
The entity that is being synthesized.
Definition Sema.h:13337