clang 22.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 =
64 (getLangOpts().getOpenCLCompatibleVersion() == 300 &&
65 !SemaRef.getOpenCLOptions().isSupported(
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 =
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.
202 S.CheckImplicitConversion(E, IntT, E->getBeginLoc());
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 =
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 =
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->getArg(0)->getBeginLoc(),
546 diag::err_opencl_builtin_to_addr_invalid_arg)
547 << Call->getArg(0) << Call->getDirectCallee() << Call->getSourceRange();
548 return true;
549 }
550
551 if (RT->getPointeeType().getAddressSpace() != LangAS::opencl_generic) {
552 Diag(Call->getArg(0)->getBeginLoc(),
553 diag::warn_opencl_generic_address_space_arg)
554 << Call->getDirectCallee()->getNameInfo().getAsString()
555 << Call->getArg(0)->getSourceRange();
556 }
557
558 RT = RT->getPointeeType();
559 auto Qual = RT.getQualifiers();
560 switch (BuiltinID) {
561 case Builtin::BIto_global:
562 Qual.setAddressSpace(LangAS::opencl_global);
563 break;
564 case Builtin::BIto_local:
565 Qual.setAddressSpace(LangAS::opencl_local);
566 break;
567 case Builtin::BIto_private:
568 Qual.setAddressSpace(LangAS::opencl_private);
569 break;
570 default:
571 llvm_unreachable("Invalid builtin function");
572 }
573 Call->setType(getASTContext().getPointerType(
574 getASTContext().getQualifiedType(RT.getUnqualifiedType(), Qual)));
575
576 return false;
577}
578
579} // namespace clang
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:220
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType UnsignedIntTy
CanQualType OCLReserveIDTy
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
CanQualType OCLQueueTy
SourceLocation getLoc() const
const IdentifierInfo * getAttrName() const
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Definition Decl.h:4654
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:4760
Pointer to a block type.
Definition TypeBase.h:3542
QualType getPointeeType() const
Definition TypeBase.h:3554
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2877
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3081
SourceLocation getBeginLoc() const
Definition Expr.h:3211
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3060
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition Expr.h:3068
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:573
void addAttr(Attr *A)
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Definition DeclBase.cpp:178
bool isInvalidDecl() const
Definition DeclBase.h:588
bool hasAttr() const
Definition DeclBase.h:577
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:427
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:831
This represents one expression.
Definition Expr.h:112
@ NPC_ValueDependentIsNotNull
Specifies that a value-dependent expression should be considered to never be a null pointer constant.
Definition Expr.h:835
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:4042
QualType getType() const
Definition Expr.h:144
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5254
unsigned getNumParams() const
Definition TypeBase.h:5532
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.
unsigned getOpenCLCompatibleVersion() const
Return the OpenCL version that kernel language is compatible with.
ParsedAttr - Represents a syntactic attribute.
Definition ParsedAttr.h:119
unsigned getSemanticSpelling() const
If the parsed attribute has a semantic equivalent, and it would have a semantic Spelling enumeration ...
Expr * getArgAsExpr(unsigned Arg) const
Definition ParsedAttr.h:383
PipeType - OpenCL20.
Definition TypeBase.h:8096
QualType getElementType() const
Definition TypeBase.h:8107
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3328
QualType getPointeeType() const
Definition TypeBase.h:3338
A (possibly-)qualified type.
Definition TypeBase.h:937
QualType getCanonicalType() const
Definition TypeBase.h:8330
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8372
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition TypeBase.h:1332
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
bool checkBuiltinNDRangeAndBlock(CallExpr *TheCall)
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...
bool checkBuiltinEnqueueKernel(CallExpr *TheCall)
OpenCL C v2.0, s6.13.17 - Enqueue kernel function contains four different overload formats specified ...
bool checkBuiltinCommitRWPipe(CallExpr *Call)
void handleSubGroupSize(Decl *D, const ParsedAttr &AL)
bool checkBuiltinPipePackets(CallExpr *Call)
void handleNoSVMAttr(Decl *D, const ParsedAttr &AL)
bool checkSubgroupExt(CallExpr *Call)
void handleAccessAttr(Decl *D, const ParsedAttr &AL)
bool checkBuiltinToAddr(unsigned BuiltinID, CallExpr *Call)
bool checkBuiltinRWPipe(CallExpr *Call)
bool checkBuiltinReserveRWPipe(CallExpr *Call)
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:854
ASTContext & Context
Definition Sema.h:1283
void CheckImplicitConversion(Expr *E, QualType T, SourceLocation CC, bool *ICContext=nullptr, bool IsListInit=false)
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:338
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:350
The base class of the type hierarchy.
Definition TypeBase.h:1833
bool isBlockPointerType() const
Definition TypeBase.h:8535
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
Definition TypeBase.h:9051
bool isPointerType() const
Definition TypeBase.h:8515
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:8915
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9158
bool isClkEventT() const
Definition TypeBase.h:8757
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:752
bool isPipeType() const
Definition TypeBase.h:8776
QualType getCanonicalTypeInternal() const
Definition TypeBase.h:3119
bool isQueueT() const
Definition TypeBase.h:8761
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:2253
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9091
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
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...
static bool checkOpenCLEnqueueIntType(Sema &S, Expr *E, const QualType &IntT)
Diagnose integer type and any valid implicit conversion to it.
static bool checkPipeArg(Sema &S, CallExpr *Call)
Returns true if pipe element type is different from the pointer.
static bool isBlockPointer(Expr *Arg)
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...
static bool checkOpenCLEnqueueLocalSizeArgs(Sema &S, CallExpr *TheCall, unsigned Start, unsigned End)
static OpenCLAccessAttr * getOpenCLArgAccess(const Decl *D)
Returns OpenCL access qual.
U cast(CodeGen::Address addr)
Definition Address.h:327
static bool checkPipePacketType(Sema &S, CallExpr *Call, unsigned Idx)
Returns true if pipe element type is different from the pointer.