clang 19.0.0git
SemaOpenCL.cpp
Go to the documentation of this file.
1//===--- SemaOpenCL.cpp --- Semantic Analysis for OpenCL 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/// \file
9/// This file implements semantic analysis for OpenCL.
10///
11//===----------------------------------------------------------------------===//
12
14#include "clang/AST/Attr.h"
15#include "clang/AST/DeclBase.h"
18#include "clang/Sema/Sema.h"
19
20namespace clang {
22
24 if (getLangOpts().getOpenCLCompatibleVersion() < 200)
25 Diag(AL.getLoc(), diag::err_attribute_requires_opencl_version)
26 << AL << "2.0" << 1;
27 else
28 Diag(AL.getLoc(), diag::warn_opencl_attr_deprecated_ignored)
30}
31
33 if (D->isInvalidDecl())
34 return;
35
36 // Check if there is only one access qualifier.
37 if (D->hasAttr<OpenCLAccessAttr>()) {
38 if (D->getAttr<OpenCLAccessAttr>()->getSemanticSpelling() ==
40 Diag(AL.getLoc(), diag::warn_duplicate_declspec)
41 << AL.getAttrName()->getName() << AL.getRange();
42 } else {
43 Diag(AL.getLoc(), diag::err_opencl_multiple_access_qualifiers)
44 << D->getSourceRange();
45 D->setInvalidDecl(true);
46 return;
47 }
48 }
49
50 // OpenCL v2.0 s6.6 - read_write can be used for image types to specify that
51 // an image object can be read and written. OpenCL v2.0 s6.13.6 - A kernel
52 // cannot read from and write to the same pipe object. Using the read_write
53 // (or __read_write) qualifier with the pipe qualifier is a compilation error.
54 // OpenCL v3.0 s6.8 - For OpenCL C 2.0, or with the
55 // __opencl_c_read_write_images feature, image objects specified as arguments
56 // to a kernel can additionally be declared to be read-write.
57 // C++ for OpenCL 1.0 inherits rule from OpenCL C v2.0.
58 // C++ for OpenCL 2021 inherits rule from OpenCL C v3.0.
59 if (const auto *PDecl = dyn_cast<ParmVarDecl>(D)) {
60 const Type *DeclTy = PDecl->getType().getCanonicalType().getTypePtr();
61 if (AL.getAttrName()->getName().contains("read_write")) {
62 bool ReadWriteImagesUnsupported =
66 "__opencl_c_read_write_images", getLangOpts()));
67 if (ReadWriteImagesUnsupported || DeclTy->isPipeType()) {
68 Diag(AL.getLoc(), diag::err_opencl_invalid_read_write)
69 << AL << PDecl->getType() << DeclTy->isImageType();
70 D->setInvalidDecl(true);
71 return;
72 }
73 }
74 }
75
76 D->addAttr(::new (getASTContext()) OpenCLAccessAttr(getASTContext(), AL));
77}
78
80 uint32_t SGSize;
81 const Expr *E = AL.getArgAsExpr(0);
82 if (!SemaRef.checkUInt32Argument(AL, E, SGSize))
83 return;
84 if (SGSize == 0) {
85 Diag(AL.getLoc(), diag::err_attribute_argument_is_zero)
86 << AL << E->getSourceRange();
87 return;
88 }
89
90 OpenCLIntelReqdSubGroupSizeAttr *Existing =
91 D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>();
92 if (Existing && Existing->getSubGroupSize() != SGSize)
93 Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
94
95 D->addAttr(::new (getASTContext())
96 OpenCLIntelReqdSubGroupSizeAttr(getASTContext(), AL, SGSize));
97}
98
99static inline bool isBlockPointer(Expr *Arg) {
100 return Arg->getType()->isBlockPointerType();
101}
102
103/// OpenCL C v2.0, s6.13.17.2 - Checks that the block parameters are all local
104/// void*, which is a requirement of device side enqueue.
105static bool checkBlockArgs(Sema &S, Expr *BlockArg) {
106 const BlockPointerType *BPT =
107 cast<BlockPointerType>(BlockArg->getType().getCanonicalType());
108 ArrayRef<QualType> Params =
109 BPT->getPointeeType()->castAs<FunctionProtoType>()->getParamTypes();
110 unsigned ArgCounter = 0;
111 bool IllegalParams = false;
112 // Iterate through the block parameters until either one is found that is not
113 // a local void*, or the block is valid.
114 for (ArrayRef<QualType>::iterator I = Params.begin(), E = Params.end();
115 I != E; ++I, ++ArgCounter) {
116 if (!(*I)->isPointerType() || !(*I)->getPointeeType()->isVoidType() ||
117 (*I)->getPointeeType().getQualifiers().getAddressSpace() !=
119 // Get the location of the error. If a block literal has been passed
120 // (BlockExpr) then we can point straight to the offending argument,
121 // else we just point to the variable reference.
122 SourceLocation ErrorLoc;
123 if (isa<BlockExpr>(BlockArg)) {
124 BlockDecl *BD = cast<BlockExpr>(BlockArg)->getBlockDecl();
125 ErrorLoc = BD->getParamDecl(ArgCounter)->getBeginLoc();
126 } else if (isa<DeclRefExpr>(BlockArg)) {
127 ErrorLoc = cast<DeclRefExpr>(BlockArg)->getBeginLoc();
128 }
129 S.Diag(ErrorLoc,
130 diag::err_opencl_enqueue_kernel_blocks_non_local_void_args);
131 IllegalParams = true;
132 }
133 }
134
135 return IllegalParams;
136}
137
139 // OpenCL device can support extension but not the feature as extension
140 // requires subgroup independent forward progress, but subgroup independent
141 // forward progress is optional in OpenCL C 3.0 __opencl_c_subgroups feature.
142 if (!SemaRef.getOpenCLOptions().isSupported("cl_khr_subgroups",
143 getLangOpts()) &&
144 !SemaRef.getOpenCLOptions().isSupported("__opencl_c_subgroups",
145 getLangOpts())) {
146 Diag(Call->getBeginLoc(), diag::err_opencl_requires_extension)
147 << 1 << Call->getDirectCallee()
148 << "cl_khr_subgroups or __opencl_c_subgroups";
149 return true;
150 }
151 return false;
152}
153
155 if (SemaRef.checkArgCount(TheCall, 2))
156 return true;
157
158 if (checkSubgroupExt(TheCall))
159 return true;
160
161 // First argument is an ndrange_t type.
162 Expr *NDRangeArg = TheCall->getArg(0);
163 if (NDRangeArg->getType().getUnqualifiedType().getAsString() != "ndrange_t") {
164 Diag(NDRangeArg->getBeginLoc(), diag::err_opencl_builtin_expected_type)
165 << TheCall->getDirectCallee() << "'ndrange_t'";
166 return true;
167 }
168
169 Expr *BlockArg = TheCall->getArg(1);
170 if (!isBlockPointer(BlockArg)) {
171 Diag(BlockArg->getBeginLoc(), diag::err_opencl_builtin_expected_type)
172 << TheCall->getDirectCallee() << "block";
173 return true;
174 }
175 return checkBlockArgs(SemaRef, BlockArg);
176}
177
179 if (SemaRef.checkArgCount(TheCall, 1))
180 return true;
181
182 Expr *BlockArg = TheCall->getArg(0);
183 if (!isBlockPointer(BlockArg)) {
184 Diag(BlockArg->getBeginLoc(), diag::err_opencl_builtin_expected_type)
185 << TheCall->getDirectCallee() << "block";
186 return true;
187 }
188 return checkBlockArgs(SemaRef, BlockArg);
189}
190
191/// Diagnose integer type and any valid implicit conversion to it.
192static bool checkOpenCLEnqueueIntType(Sema &S, Expr *E, const QualType &IntT) {
193 // Taking into account implicit conversions,
194 // allow any integer.
195 if (!E->getType()->isIntegerType()) {
196 S.Diag(E->getBeginLoc(),
197 diag::err_opencl_enqueue_kernel_invalid_local_size_type);
198 return true;
199 }
200 // Potentially emit standard warnings for implicit conversions if enabled
201 // using -Wconversion.
203 return false;
204}
205
207 unsigned Start, unsigned End) {
208 bool IllegalParams = false;
209 for (unsigned I = Start; I <= End; ++I)
210 IllegalParams |= checkOpenCLEnqueueIntType(S, TheCall->getArg(I),
211 S.Context.getSizeType());
212 return IllegalParams;
213}
214
215/// OpenCL v2.0, s6.13.17.1 - Check that sizes are provided for all
216/// 'local void*' parameter of passed block.
218 Expr *BlockArg,
219 unsigned NumNonVarArgs) {
220 const BlockPointerType *BPT =
221 cast<BlockPointerType>(BlockArg->getType().getCanonicalType());
222 unsigned NumBlockParams =
223 BPT->getPointeeType()->castAs<FunctionProtoType>()->getNumParams();
224 unsigned TotalNumArgs = TheCall->getNumArgs();
225
226 // For each argument passed to the block, a corresponding uint needs to
227 // be passed to describe the size of the local memory.
228 if (TotalNumArgs != NumBlockParams + NumNonVarArgs) {
229 S.Diag(TheCall->getBeginLoc(),
230 diag::err_opencl_enqueue_kernel_local_size_args);
231 return true;
232 }
233
234 // Check that the sizes of the local memory are specified by integers.
235 return checkOpenCLEnqueueLocalSizeArgs(S, TheCall, NumNonVarArgs,
236 TotalNumArgs - 1);
237}
238
240 ASTContext &Context = getASTContext();
241 unsigned NumArgs = TheCall->getNumArgs();
242
243 if (NumArgs < 4) {
244 Diag(TheCall->getBeginLoc(), diag::err_typecheck_call_too_few_args_at_least)
245 << 0 << 4 << NumArgs << /*is non object*/ 0;
246 return true;
247 }
248
249 Expr *Arg0 = TheCall->getArg(0);
250 Expr *Arg1 = TheCall->getArg(1);
251 Expr *Arg2 = TheCall->getArg(2);
252 Expr *Arg3 = TheCall->getArg(3);
253
254 // First argument always needs to be a queue_t type.
255 if (!Arg0->getType()->isQueueT()) {
256 Diag(TheCall->getArg(0)->getBeginLoc(),
257 diag::err_opencl_builtin_expected_type)
258 << TheCall->getDirectCallee() << getASTContext().OCLQueueTy;
259 return true;
260 }
261
262 // Second argument always needs to be a kernel_enqueue_flags_t enum value.
263 if (!Arg1->getType()->isIntegerType()) {
264 Diag(TheCall->getArg(1)->getBeginLoc(),
265 diag::err_opencl_builtin_expected_type)
266 << TheCall->getDirectCallee() << "'kernel_enqueue_flags_t' (i.e. uint)";
267 return true;
268 }
269
270 // Third argument is always an ndrange_t type.
271 if (Arg2->getType().getUnqualifiedType().getAsString() != "ndrange_t") {
272 Diag(TheCall->getArg(2)->getBeginLoc(),
273 diag::err_opencl_builtin_expected_type)
274 << TheCall->getDirectCallee() << "'ndrange_t'";
275 return true;
276 }
277
278 // With four arguments, there is only one form that the function could be
279 // called in: no events and no variable arguments.
280 if (NumArgs == 4) {
281 // check that the last argument is the right block type.
282 if (!isBlockPointer(Arg3)) {
283 Diag(Arg3->getBeginLoc(), diag::err_opencl_builtin_expected_type)
284 << TheCall->getDirectCallee() << "block";
285 return true;
286 }
287 // we have a block type, check the prototype
288 const BlockPointerType *BPT =
289 cast<BlockPointerType>(Arg3->getType().getCanonicalType());
291 0) {
292 Diag(Arg3->getBeginLoc(), diag::err_opencl_enqueue_kernel_blocks_no_args);
293 return true;
294 }
295 return false;
296 }
297 // we can have block + varargs.
298 if (isBlockPointer(Arg3))
299 return (checkBlockArgs(SemaRef, Arg3) ||
300 checkOpenCLEnqueueVariadicArgs(SemaRef, TheCall, Arg3, 4));
301 // last two cases with either exactly 7 args or 7 args and varargs.
302 if (NumArgs >= 7) {
303 // check common block argument.
304 Expr *Arg6 = TheCall->getArg(6);
305 if (!isBlockPointer(Arg6)) {
306 Diag(Arg6->getBeginLoc(), diag::err_opencl_builtin_expected_type)
307 << TheCall->getDirectCallee() << "block";
308 return true;
309 }
310 if (checkBlockArgs(SemaRef, Arg6))
311 return true;
312
313 // Forth argument has to be any integer type.
314 if (!Arg3->getType()->isIntegerType()) {
315 Diag(TheCall->getArg(3)->getBeginLoc(),
316 diag::err_opencl_builtin_expected_type)
317 << TheCall->getDirectCallee() << "integer";
318 return true;
319 }
320 // check remaining common arguments.
321 Expr *Arg4 = TheCall->getArg(4);
322 Expr *Arg5 = TheCall->getArg(5);
323
324 // Fifth argument is always passed as a pointer to clk_event_t.
325 if (!Arg4->isNullPointerConstant(Context,
328 Diag(TheCall->getArg(4)->getBeginLoc(),
329 diag::err_opencl_builtin_expected_type)
330 << TheCall->getDirectCallee()
331 << Context.getPointerType(Context.OCLClkEventTy);
332 return true;
333 }
334
335 // Sixth argument is always passed as a pointer to clk_event_t.
336 if (!Arg5->isNullPointerConstant(Context,
338 !(Arg5->getType()->isPointerType() &&
339 Arg5->getType()->getPointeeType()->isClkEventT())) {
340 Diag(TheCall->getArg(5)->getBeginLoc(),
341 diag::err_opencl_builtin_expected_type)
342 << TheCall->getDirectCallee()
343 << Context.getPointerType(Context.OCLClkEventTy);
344 return true;
345 }
346
347 if (NumArgs == 7)
348 return false;
349
350 return checkOpenCLEnqueueVariadicArgs(SemaRef, TheCall, Arg6, 7);
351 }
352
353 // None of the specific case has been detected, give generic error
354 Diag(TheCall->getBeginLoc(), diag::err_opencl_enqueue_kernel_incorrect_args);
355 return true;
356}
357
358/// Returns OpenCL access qual.
359static OpenCLAccessAttr *getOpenCLArgAccess(const Decl *D) {
360 return D->getAttr<OpenCLAccessAttr>();
361}
362
363/// Returns true if pipe element type is different from the pointer.
364static bool checkPipeArg(Sema &S, CallExpr *Call) {
365 const Expr *Arg0 = Call->getArg(0);
366 // First argument type should always be pipe.
367 if (!Arg0->getType()->isPipeType()) {
368 S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_first_arg)
369 << Call->getDirectCallee() << Arg0->getSourceRange();
370 return true;
371 }
372 OpenCLAccessAttr *AccessQual =
373 getOpenCLArgAccess(cast<DeclRefExpr>(Arg0)->getDecl());
374 // Validates the access qualifier is compatible with the call.
375 // OpenCL v2.0 s6.13.16 - The access qualifiers for pipe should only be
376 // read_only and write_only, and assumed to be read_only if no qualifier is
377 // specified.
378 switch (Call->getDirectCallee()->getBuiltinID()) {
379 case Builtin::BIread_pipe:
380 case Builtin::BIreserve_read_pipe:
381 case Builtin::BIcommit_read_pipe:
382 case Builtin::BIwork_group_reserve_read_pipe:
383 case Builtin::BIsub_group_reserve_read_pipe:
384 case Builtin::BIwork_group_commit_read_pipe:
385 case Builtin::BIsub_group_commit_read_pipe:
386 if (!(!AccessQual || AccessQual->isReadOnly())) {
387 S.Diag(Arg0->getBeginLoc(),
388 diag::err_opencl_builtin_pipe_invalid_access_modifier)
389 << "read_only" << Arg0->getSourceRange();
390 return true;
391 }
392 break;
393 case Builtin::BIwrite_pipe:
394 case Builtin::BIreserve_write_pipe:
395 case Builtin::BIcommit_write_pipe:
396 case Builtin::BIwork_group_reserve_write_pipe:
397 case Builtin::BIsub_group_reserve_write_pipe:
398 case Builtin::BIwork_group_commit_write_pipe:
399 case Builtin::BIsub_group_commit_write_pipe:
400 if (!(AccessQual && AccessQual->isWriteOnly())) {
401 S.Diag(Arg0->getBeginLoc(),
402 diag::err_opencl_builtin_pipe_invalid_access_modifier)
403 << "write_only" << Arg0->getSourceRange();
404 return true;
405 }
406 break;
407 default:
408 break;
409 }
410 return false;
411}
412
413/// Returns true if pipe element type is different from the pointer.
414static bool checkPipePacketType(Sema &S, CallExpr *Call, unsigned Idx) {
415 const Expr *Arg0 = Call->getArg(0);
416 const Expr *ArgIdx = Call->getArg(Idx);
417 const PipeType *PipeTy = cast<PipeType>(Arg0->getType());
418 const QualType EltTy = PipeTy->getElementType();
419 const PointerType *ArgTy = ArgIdx->getType()->getAs<PointerType>();
420 // The Idx argument should be a pointer and the type of the pointer and
421 // the type of pipe element should also be the same.
422 if (!ArgTy ||
424 EltTy, ArgTy->getPointeeType()->getCanonicalTypeInternal())) {
425 S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
426 << Call->getDirectCallee() << S.Context.getPointerType(EltTy)
427 << ArgIdx->getType() << ArgIdx->getSourceRange();
428 return true;
429 }
430 return false;
431}
432
434 // OpenCL v2.0 s6.13.16.2 - The built-in read/write
435 // functions have two forms.
436 switch (Call->getNumArgs()) {
437 case 2:
439 return true;
440 // The call with 2 arguments should be
441 // read/write_pipe(pipe T, T*).
442 // Check packet type T.
444 return true;
445 break;
446
447 case 4: {
449 return true;
450 // The call with 4 arguments should be
451 // read/write_pipe(pipe T, reserve_id_t, uint, T*).
452 // Check reserve_id_t.
453 if (!Call->getArg(1)->getType()->isReserveIDT()) {
454 Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
455 << Call->getDirectCallee() << getASTContext().OCLReserveIDTy
456 << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange();
457 return true;
458 }
459
460 // Check the index.
461 const Expr *Arg2 = Call->getArg(2);
462 if (!Arg2->getType()->isIntegerType() &&
463 !Arg2->getType()->isUnsignedIntegerType()) {
464 Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
465 << Call->getDirectCallee() << getASTContext().UnsignedIntTy
466 << Arg2->getType() << Arg2->getSourceRange();
467 return true;
468 }
469
470 // Check packet type T.
472 return true;
473 } break;
474 default:
475 Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_arg_num)
476 << Call->getDirectCallee() << Call->getSourceRange();
477 return true;
478 }
479
480 return false;
481}
482
484 if (SemaRef.checkArgCount(Call, 2))
485 return true;
486
488 return true;
489
490 // Check the reserve size.
491 if (!Call->getArg(1)->getType()->isIntegerType() &&
492 !Call->getArg(1)->getType()->isUnsignedIntegerType()) {
493 Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
494 << Call->getDirectCallee() << getASTContext().UnsignedIntTy
495 << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange();
496 return true;
497 }
498
499 // Since return type of reserve_read/write_pipe built-in function is
500 // reserve_id_t, which is not defined in the builtin def file , we used int
501 // as return type and need to override the return type of these functions.
502 Call->setType(getASTContext().OCLReserveIDTy);
503
504 return false;
505}
506
508 if (SemaRef.checkArgCount(Call, 2))
509 return true;
510
512 return true;
513
514 // Check reserve_id_t.
515 if (!Call->getArg(1)->getType()->isReserveIDT()) {
516 Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
517 << Call->getDirectCallee() << getASTContext().OCLReserveIDTy
518 << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange();
519 return true;
520 }
521
522 return false;
523}
524
526 if (SemaRef.checkArgCount(Call, 1))
527 return true;
528
529 if (!Call->getArg(0)->getType()->isPipeType()) {
530 Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_first_arg)
531 << Call->getDirectCallee() << Call->getArg(0)->getSourceRange();
532 return true;
533 }
534
535 return false;
536}
537
538bool SemaOpenCL::checkBuiltinToAddr(unsigned BuiltinID, CallExpr *Call) {
539 if (SemaRef.checkArgCount(Call, 1))
540 return true;
541
542 auto RT = Call->getArg(0)->getType();
543 if (!RT->isPointerType() ||
544 RT->getPointeeType().getAddressSpace() == LangAS::opencl_constant) {
545 Diag(Call->getBeginLoc(), diag::err_opencl_builtin_to_addr_invalid_arg)
546 << Call->getArg(0) << Call->getDirectCallee() << Call->getSourceRange();
547 return true;
548 }
549
550 if (RT->getPointeeType().getAddressSpace() != LangAS::opencl_generic) {
551 Diag(Call->getArg(0)->getBeginLoc(),
552 diag::warn_opencl_generic_address_space_arg)
553 << Call->getDirectCallee()->getNameInfo().getAsString()
554 << Call->getArg(0)->getSourceRange();
555 }
556
557 RT = RT->getPointeeType();
558 auto Qual = RT.getQualifiers();
559 switch (BuiltinID) {
560 case Builtin::BIto_global:
561 Qual.setAddressSpace(LangAS::opencl_global);
562 break;
563 case Builtin::BIto_local:
564 Qual.setAddressSpace(LangAS::opencl_local);
565 break;
566 case Builtin::BIto_private:
567 Qual.setAddressSpace(LangAS::opencl_private);
568 break;
569 default:
570 llvm_unreachable("Invalid builtin function");
571 }
572 Call->setType(getASTContext().getPointerType(
573 getASTContext().getQualifiedType(RT.getUnqualifiedType(), Qual)));
574
575 return false;
576}
577
578} // namespace clang
const Decl * D
Expr * E
This file declares semantic analysis routines for OpenCL.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:186
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:2632
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
CanQualType UnsignedIntTy
Definition: ASTContext.h:1119
CanQualType OCLReserveIDTy
Definition: ASTContext.h:1147
CanQualType OCLQueueTy
Definition: ASTContext.h:1147
SourceLocation getLoc() const
const IdentifierInfo * getAttrName() const
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Definition: Decl.h:4467
const ParmVarDecl * getParamDecl(unsigned i) const
Definition: Decl.h:4573
Pointer to a block type.
Definition: Type.h:3368
QualType getPointeeType() const
Definition: Type.h:3380
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2825
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: Expr.h:3016
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.cpp:1638
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition: Expr.h:2995
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition: Expr.h:3003
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
T * getAttr() const
Definition: DeclBase.h:579
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Decl.h:783
This represents one expression.
Definition: Expr.h:110
@ NPC_ValueDependentIsNotNull
Specifies that a value-dependent expression should be considered to never be a null pointer constant.
Definition: Expr.h:830
NullPointerConstantKind isNullPointerConstant(ASTContext &Ctx, NullPointerConstantValueDependence NPC) const
isNullPointerConstant - C99 6.3.2.3p3 - Test if this reduces down to a Null pointer constant.
Definition: Expr.cpp:3941
QualType getType() const
Definition: Expr.h:142
Represents a prototype with parameter type info, e.g.
Definition: Type.h:4971
unsigned getNumParams() const
Definition: Type.h:5220
StringRef getName() const
Return the actual identifier string.
std::string getOpenCLVersionString() const
Return the OpenCL C or C++ for OpenCL language name and version as a string.
Definition: LangOptions.cpp:79
unsigned getOpenCLCompatibleVersion() const
Return the OpenCL version that kernel language is compatible with.
Definition: LangOptions.cpp:63
bool isSupported(llvm::StringRef Ext, const LangOptions &LO) const
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:129
unsigned getSemanticSpelling() const
If the parsed attribute has a semantic equivalent, and it would have a semantic Spelling enumeration ...
Definition: ParsedAttr.cpp:262
Expr * getArgAsExpr(unsigned Arg) const
Definition: ParsedAttr.h:398
PipeType - OpenCL20.
Definition: Type.h:7593
QualType getElementType() const
Definition: Type.h:7604
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:3158
QualType getPointeeType() const
Definition: Type.h:3168
A (possibly-)qualified type.
Definition: Type.h:942
QualType getCanonicalType() const
Definition: Type.h:7796
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:7838
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition: Type.h:1340
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:60
ASTContext & getASTContext() const
Definition: SemaBase.cpp:9
Sema & SemaRef
Definition: SemaBase.h:40
const LangOptions & getLangOpts() const
Definition: SemaBase.cpp:11
bool checkBuiltinNDRangeAndBlock(CallExpr *TheCall)
Definition: SemaOpenCL.cpp:154
bool checkBuiltinKernelWorkGroupSize(CallExpr *TheCall)
OpenCL C v2.0, s6.13.17.6 - Check the argument to the get_kernel_work_group_size and get_kernel_prefe...
Definition: SemaOpenCL.cpp:178
bool checkBuiltinEnqueueKernel(CallExpr *TheCall)
OpenCL C v2.0, s6.13.17 - Enqueue kernel function contains four different overload formats specified ...
Definition: SemaOpenCL.cpp:239
bool checkBuiltinCommitRWPipe(CallExpr *Call)
Definition: SemaOpenCL.cpp:507
void handleSubGroupSize(Decl *D, const ParsedAttr &AL)
Definition: SemaOpenCL.cpp:79
bool checkBuiltinPipePackets(CallExpr *Call)
Definition: SemaOpenCL.cpp:525
void handleNoSVMAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaOpenCL.cpp:23
bool checkSubgroupExt(CallExpr *Call)
Definition: SemaOpenCL.cpp:138
void handleAccessAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaOpenCL.cpp:32
bool checkBuiltinToAddr(unsigned BuiltinID, CallExpr *Call)
Definition: SemaOpenCL.cpp:538
bool checkBuiltinRWPipe(CallExpr *Call)
Definition: SemaOpenCL.cpp:433
bool checkBuiltinReserveRWPipe(CallExpr *Call)
Definition: SemaOpenCL.cpp:483
SemaOpenCL(Sema &S)
Definition: SemaOpenCL.cpp:21
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:535
ASTContext & Context
Definition: Sema.h:1002
void CheckImplicitConversion(Expr *E, QualType T, SourceLocation CC, bool *ICContext=nullptr, bool IsListInit=false)
bool checkUInt32Argument(const AttrInfo &AI, const Expr *Expr, uint32_t &Val, unsigned Idx=UINT_MAX, bool StrictlyUnsigned=false)
If Expr is a valid integer constant, get the value of the integer expression and return success or fa...
Definition: Sema.h:4418
bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount)
Checks that a call expression's argument count is the desired number.
OpenCLOptions & getOpenCLOptions()
Definition: Sema.h:594
Encodes a location in the source.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:326
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:338
The base class of the type hierarchy.
Definition: Type.h:1826
bool isBlockPointerType() const
Definition: Type.h:8007
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
Definition: Type.h:8474
bool isPointerType() const
Definition: Type.h:7997
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: Type.h:8336
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:8584
bool isClkEventT() const
Definition: Type.h:8208
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:705
bool isPipeType() const
Definition: Type.h:8227
QualType getCanonicalTypeInternal() const
Definition: Type.h:2952
bool isQueueT() const
Definition: Type.h:8212
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
Definition: Type.cpp:2195
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8517
The JSON file list parser is used to communicate input to InstallAPI.
static bool checkBlockArgs(Sema &S, Expr *BlockArg)
OpenCL C v2.0, s6.13.17.2 - Checks that the block parameters are all local void*, which is a requirem...
Definition: SemaOpenCL.cpp:105
static bool checkOpenCLEnqueueIntType(Sema &S, Expr *E, const QualType &IntT)
Diagnose integer type and any valid implicit conversion to it.
Definition: SemaOpenCL.cpp:192
static bool checkPipeArg(Sema &S, CallExpr *Call)
Returns true if pipe element type is different from the pointer.
Definition: SemaOpenCL.cpp:364
static bool isBlockPointer(Expr *Arg)
Definition: SemaOpenCL.cpp:99
static bool checkOpenCLEnqueueVariadicArgs(Sema &S, CallExpr *TheCall, Expr *BlockArg, unsigned NumNonVarArgs)
OpenCL v2.0, s6.13.17.1 - Check that sizes are provided for all 'local void*' parameter of passed blo...
Definition: SemaOpenCL.cpp:217
static bool checkOpenCLEnqueueLocalSizeArgs(Sema &S, CallExpr *TheCall, unsigned Start, unsigned End)
Definition: SemaOpenCL.cpp:206
static OpenCLAccessAttr * getOpenCLArgAccess(const Decl *D)
Returns OpenCL access qual.
Definition: SemaOpenCL.cpp:359
static bool checkPipePacketType(Sema &S, CallExpr *Call, unsigned Idx)
Returns true if pipe element type is different from the pointer.
Definition: SemaOpenCL.cpp:414