clang 23.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/Decl.h"
16#include "clang/AST/DeclBase.h"
17#include "clang/AST/Expr.h"
20#include "clang/Sema/Sema.h"
21
22namespace clang {
24
26 if (getLangOpts().getOpenCLCompatibleVersion() < 200)
27 Diag(AL.getLoc(), diag::err_attribute_requires_opencl_version)
28 << AL << "2.0" << 1;
29 else
30 Diag(AL.getLoc(), diag::warn_opencl_attr_deprecated_ignored)
32}
33
35 if (D->isInvalidDecl())
36 return;
37
38 // Check if there is only one access qualifier.
39 if (D->hasAttr<OpenCLAccessAttr>()) {
40 if (D->getAttr<OpenCLAccessAttr>()->getSemanticSpelling() ==
42 Diag(AL.getLoc(), diag::warn_duplicate_declspec)
43 << AL.getAttrName()->getName() << AL.getRange();
44 } else {
45 Diag(AL.getLoc(), diag::err_opencl_multiple_access_qualifiers)
46 << D->getSourceRange();
47 D->setInvalidDecl(true);
48 return;
49 }
50 }
51
52 // OpenCL v2.0 s6.6 - read_write can be used for image types to specify that
53 // an image object can be read and written. OpenCL v2.0 s6.13.6 - A kernel
54 // cannot read from and write to the same pipe object. Using the read_write
55 // (or __read_write) qualifier with the pipe qualifier is a compilation error.
56 // OpenCL v3.0 s6.8 - For OpenCL C 2.0, or with the
57 // __opencl_c_read_write_images feature, image objects specified as arguments
58 // to a kernel can additionally be declared to be read-write.
59 // C++ for OpenCL 1.0 inherits rule from OpenCL C v2.0.
60 // C++ for OpenCL 2021 inherits rule from OpenCL C v3.0.
61 if (const auto *PDecl = dyn_cast<ParmVarDecl>(D)) {
62 const Type *DeclTy = PDecl->getType().getCanonicalType().getTypePtr();
63 if (AL.getAttrName()->getName().contains("read_write")) {
64 bool ReadWriteImagesUnsupported =
66 (getLangOpts().getOpenCLCompatibleVersion() == 300 &&
67 !SemaRef.getOpenCLOptions().isSupported(
68 "__opencl_c_read_write_images", getLangOpts()));
69 if (ReadWriteImagesUnsupported || DeclTy->isPipeType()) {
70 Diag(AL.getLoc(), diag::err_opencl_invalid_read_write)
71 << AL << PDecl->getType() << DeclTy->isImageType();
72 D->setInvalidDecl(true);
73 return;
74 }
75 }
76 }
77
78 D->addAttr(::new (getASTContext()) OpenCLAccessAttr(getASTContext(), AL));
79}
80
82 uint32_t SGSize;
83 const Expr *E = AL.getArgAsExpr(0);
84 if (!SemaRef.checkUInt32Argument(AL, E, SGSize))
85 return;
86 if (SGSize == 0) {
87 Diag(AL.getLoc(), diag::err_attribute_argument_is_zero)
88 << AL << E->getSourceRange();
89 return;
90 }
91
92 OpenCLIntelReqdSubGroupSizeAttr *Existing =
93 D->getAttr<OpenCLIntelReqdSubGroupSizeAttr>();
94 if (Existing && Existing->getSubGroupSize() != SGSize)
95 Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;
96
97 D->addAttr(::new (getASTContext())
98 OpenCLIntelReqdSubGroupSizeAttr(getASTContext(), AL, SGSize));
99}
100
101static inline bool isBlockPointer(Expr *Arg) {
102 return Arg->getType()->isBlockPointerType();
103}
104
105/// OpenCL C v2.0, s6.13.17.2 - Checks that the block parameters are all local
106/// void*, which is a requirement of device side enqueue.
107static bool checkBlockArgs(Sema &S, Expr *BlockArg) {
108 const BlockPointerType *BPT =
110 ArrayRef<QualType> Params =
111 BPT->getPointeeType()->castAs<FunctionProtoType>()->getParamTypes();
112 unsigned ArgCounter = 0;
113 bool IllegalParams = false;
114 // Iterate through the block parameters until either one is found that is not
115 // a local void*, or the block is valid.
116 for (ArrayRef<QualType>::iterator I = Params.begin(), E = Params.end();
117 I != E; ++I, ++ArgCounter) {
118 if (!(*I)->isPointerType() || !(*I)->getPointeeType()->isVoidType() ||
119 (*I)->getPointeeType().getQualifiers().getAddressSpace() !=
121 // Get the location of the error. If a block literal has been passed
122 // (BlockExpr) then we can point straight to the offending argument,
123 // else we just point to the variable reference.
124 SourceLocation ErrorLoc;
125 if (isa<BlockExpr>(BlockArg)) {
126 BlockDecl *BD = cast<BlockExpr>(BlockArg)->getBlockDecl();
127 ErrorLoc = BD->getParamDecl(ArgCounter)->getBeginLoc();
128 } else if (isa<DeclRefExpr>(BlockArg)) {
129 ErrorLoc = cast<DeclRefExpr>(BlockArg)->getBeginLoc();
130 }
131 S.Diag(ErrorLoc,
132 diag::err_opencl_enqueue_kernel_blocks_non_local_void_args);
133 IllegalParams = true;
134 }
135 }
136
137 return IllegalParams;
138}
139
141 // OpenCL device can support extension but not the feature as extension
142 // requires subgroup independent forward progress, but subgroup independent
143 // forward progress is optional in OpenCL C 3.0 __opencl_c_subgroups feature.
144 if (!SemaRef.getOpenCLOptions().isSupported("cl_khr_subgroups",
145 getLangOpts()) &&
146 !SemaRef.getOpenCLOptions().isSupported("__opencl_c_subgroups",
147 getLangOpts())) {
148 Diag(Call->getBeginLoc(), diag::err_opencl_requires_extension)
149 << 1 << Call->getDirectCallee()
150 << "cl_khr_subgroups or __opencl_c_subgroups";
151 return true;
152 }
153 return false;
154}
155
157 if (SemaRef.checkArgCount(TheCall, 2))
158 return true;
159
160 if (checkSubgroupExt(TheCall))
161 return true;
162
163 // First argument is an ndrange_t type.
164 Expr *NDRangeArg = TheCall->getArg(0);
165 if (NDRangeArg->getType().getUnqualifiedType().getAsString() != "ndrange_t") {
166 Diag(NDRangeArg->getBeginLoc(), diag::err_opencl_builtin_expected_type)
167 << TheCall->getDirectCallee() << "'ndrange_t'";
168 return true;
169 }
170
171 Expr *BlockArg = TheCall->getArg(1);
172 if (!isBlockPointer(BlockArg)) {
173 Diag(BlockArg->getBeginLoc(), diag::err_opencl_builtin_expected_type)
174 << TheCall->getDirectCallee() << "block";
175 return true;
176 }
177 return checkBlockArgs(SemaRef, BlockArg);
178}
179
181 if (SemaRef.checkArgCount(TheCall, 1))
182 return true;
183
184 Expr *BlockArg = TheCall->getArg(0);
185 if (!isBlockPointer(BlockArg)) {
186 Diag(BlockArg->getBeginLoc(), diag::err_opencl_builtin_expected_type)
187 << TheCall->getDirectCallee() << "block";
188 return true;
189 }
190 return checkBlockArgs(SemaRef, BlockArg);
191}
192
193/// Diagnose integer type and any valid implicit conversion to it.
194static bool checkOpenCLEnqueueIntType(Sema &S, Expr *E, const QualType &IntT) {
195 // Taking into account implicit conversions,
196 // allow any integer.
197 if (!E->getType()->isIntegerType()) {
198 S.Diag(E->getBeginLoc(),
199 diag::err_opencl_enqueue_kernel_invalid_local_size_type);
200 return true;
201 }
202 // Potentially emit standard warnings for implicit conversions if enabled
203 // using -Wconversion.
204 S.CheckImplicitConversion(E, IntT, E->getBeginLoc());
205 return false;
206}
207
209 unsigned Start, unsigned End) {
210 bool IllegalParams = false;
211 for (unsigned I = Start; I <= End; ++I)
212 IllegalParams |= checkOpenCLEnqueueIntType(S, TheCall->getArg(I),
213 S.Context.getSizeType());
214 return IllegalParams;
215}
216
217/// OpenCL v2.0, s6.13.17.1 - Check that sizes are provided for all
218/// 'local void*' parameter of passed block.
220 Expr *BlockArg,
221 unsigned NumNonVarArgs) {
222 const BlockPointerType *BPT =
224 unsigned NumBlockParams =
225 BPT->getPointeeType()->castAs<FunctionProtoType>()->getNumParams();
226 unsigned TotalNumArgs = TheCall->getNumArgs();
227
228 // For each argument passed to the block, a corresponding uint needs to
229 // be passed to describe the size of the local memory.
230 if (TotalNumArgs != NumBlockParams + NumNonVarArgs) {
231 S.Diag(TheCall->getBeginLoc(),
232 diag::err_opencl_enqueue_kernel_local_size_args);
233 return true;
234 }
235
236 // Check that the sizes of the local memory are specified by integers.
237 return checkOpenCLEnqueueLocalSizeArgs(S, TheCall, NumNonVarArgs,
238 TotalNumArgs - 1);
239}
240
242 ASTContext &Context = getASTContext();
243 unsigned NumArgs = TheCall->getNumArgs();
244
245 if (NumArgs < 4) {
246 Diag(TheCall->getBeginLoc(), diag::err_typecheck_call_too_few_args_at_least)
247 << 0 << 4 << NumArgs << /*is non object*/ 0;
248 return true;
249 }
250
251 Expr *Arg0 = TheCall->getArg(0);
252 Expr *Arg1 = TheCall->getArg(1);
253 Expr *Arg2 = TheCall->getArg(2);
254 Expr *Arg3 = TheCall->getArg(3);
255
256 // First argument always needs to be a queue_t type.
257 if (!Arg0->getType()->isQueueT()) {
258 Diag(TheCall->getArg(0)->getBeginLoc(),
259 diag::err_opencl_builtin_expected_type)
260 << TheCall->getDirectCallee() << getASTContext().OCLQueueTy;
261 return true;
262 }
263
264 // Second argument always needs to be a kernel_enqueue_flags_t enum value.
265 if (!Arg1->getType()->isIntegerType()) {
266 Diag(TheCall->getArg(1)->getBeginLoc(),
267 diag::err_opencl_builtin_expected_type)
268 << TheCall->getDirectCallee() << "'kernel_enqueue_flags_t' (i.e. uint)";
269 return true;
270 }
271
272 // Third argument is always an ndrange_t type.
273 if (Arg2->getType().getUnqualifiedType().getAsString() != "ndrange_t") {
274 Diag(TheCall->getArg(2)->getBeginLoc(),
275 diag::err_opencl_builtin_expected_type)
276 << TheCall->getDirectCallee() << "'ndrange_t'";
277 return true;
278 }
279
280 // With four arguments, there is only one form that the function could be
281 // called in: no events and no variable arguments.
282 if (NumArgs == 4) {
283 // check that the last argument is the right block type.
284 if (!isBlockPointer(Arg3)) {
285 Diag(Arg3->getBeginLoc(), diag::err_opencl_builtin_expected_type)
286 << TheCall->getDirectCallee() << "block";
287 return true;
288 }
289 // we have a block type, check the prototype
290 const BlockPointerType *BPT =
293 0) {
294 Diag(Arg3->getBeginLoc(), diag::err_opencl_enqueue_kernel_blocks_no_args);
295 return true;
296 }
297 return false;
298 }
299 // we can have block + varargs.
300 if (isBlockPointer(Arg3))
301 return (checkBlockArgs(SemaRef, Arg3) ||
302 checkOpenCLEnqueueVariadicArgs(SemaRef, TheCall, Arg3, 4));
303 // last two cases with either exactly 7 args or 7 args and varargs.
304 if (NumArgs >= 7) {
305 // check common block argument.
306 Expr *Arg6 = TheCall->getArg(6);
307 if (!isBlockPointer(Arg6)) {
308 Diag(Arg6->getBeginLoc(), diag::err_opencl_builtin_expected_type)
309 << TheCall->getDirectCallee() << "block";
310 return true;
311 }
312 if (checkBlockArgs(SemaRef, Arg6))
313 return true;
314
315 // Forth argument has to be any integer type.
316 if (!Arg3->getType()->isIntegerType()) {
317 Diag(TheCall->getArg(3)->getBeginLoc(),
318 diag::err_opencl_builtin_expected_type)
319 << TheCall->getDirectCallee() << "integer";
320 return true;
321 }
322 // check remaining common arguments.
323 Expr *Arg4 = TheCall->getArg(4);
324 Expr *Arg5 = TheCall->getArg(5);
325
326 // Fifth argument is always passed as a pointer to clk_event_t.
327 if (!Arg4->isNullPointerConstant(Context,
330 Diag(TheCall->getArg(4)->getBeginLoc(),
331 diag::err_opencl_builtin_expected_type)
332 << TheCall->getDirectCallee()
333 << Context.getPointerType(Context.OCLClkEventTy);
334 return true;
335 }
336
337 // Sixth argument is always passed as a pointer to clk_event_t.
338 if (!Arg5->isNullPointerConstant(Context,
340 !(Arg5->getType()->isPointerType() &&
341 Arg5->getType()->getPointeeType()->isClkEventT())) {
342 Diag(TheCall->getArg(5)->getBeginLoc(),
343 diag::err_opencl_builtin_expected_type)
344 << TheCall->getDirectCallee()
345 << Context.getPointerType(Context.OCLClkEventTy);
346 return true;
347 }
348
349 if (NumArgs == 7)
350 return false;
351
352 return checkOpenCLEnqueueVariadicArgs(SemaRef, TheCall, Arg6, 7);
353 }
354
355 // None of the specific case has been detected, give generic error
356 Diag(TheCall->getBeginLoc(), diag::err_opencl_enqueue_kernel_incorrect_args);
357 return true;
358}
359
360/// Returns OpenCL access qual.
361static OpenCLAccessAttr *getOpenCLArgAccess(const Decl *D) {
362 return D->getAttr<OpenCLAccessAttr>();
363}
364
365/// Returns true if pipe element type is different from the pointer.
366static bool checkPipeArg(Sema &S, CallExpr *Call) {
367 const Expr *Arg0 = Call->getArg(0);
368 // First argument type should always be pipe.
369 if (!Arg0->getType()->isPipeType()) {
370 S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_first_arg)
371 << Call->getDirectCallee() << Arg0->getSourceRange();
372 return true;
373 }
374 OpenCLAccessAttr *AccessQual =
375 getOpenCLArgAccess(cast<DeclRefExpr>(Arg0)->getDecl());
376 // Validates the access qualifier is compatible with the call.
377 // OpenCL v2.0 s6.13.16 - The access qualifiers for pipe should only be
378 // read_only and write_only, and assumed to be read_only if no qualifier is
379 // specified.
380 switch (Call->getDirectCallee()->getBuiltinID()) {
381 case Builtin::BIread_pipe:
382 case Builtin::BIreserve_read_pipe:
383 case Builtin::BIcommit_read_pipe:
384 case Builtin::BIwork_group_reserve_read_pipe:
385 case Builtin::BIsub_group_reserve_read_pipe:
386 case Builtin::BIwork_group_commit_read_pipe:
387 case Builtin::BIsub_group_commit_read_pipe:
388 if (!(!AccessQual || AccessQual->isReadOnly())) {
389 S.Diag(Arg0->getBeginLoc(),
390 diag::err_opencl_builtin_pipe_invalid_access_modifier)
391 << "read_only" << Arg0->getSourceRange();
392 return true;
393 }
394 break;
395 case Builtin::BIwrite_pipe:
396 case Builtin::BIreserve_write_pipe:
397 case Builtin::BIcommit_write_pipe:
398 case Builtin::BIwork_group_reserve_write_pipe:
399 case Builtin::BIsub_group_reserve_write_pipe:
400 case Builtin::BIwork_group_commit_write_pipe:
401 case Builtin::BIsub_group_commit_write_pipe:
402 if (!(AccessQual && AccessQual->isWriteOnly())) {
403 S.Diag(Arg0->getBeginLoc(),
404 diag::err_opencl_builtin_pipe_invalid_access_modifier)
405 << "write_only" << Arg0->getSourceRange();
406 return true;
407 }
408 break;
409 default:
410 break;
411 }
412 return false;
413}
414
415/// Returns true if pipe element type is different from the pointer.
416static bool checkPipePacketType(Sema &S, CallExpr *Call, unsigned Idx) {
417 const Expr *Arg0 = Call->getArg(0);
418 const Expr *ArgIdx = Call->getArg(Idx);
419 const PipeType *PipeTy = cast<PipeType>(Arg0->getType());
420 const QualType EltTy = PipeTy->getElementType();
421 const PointerType *ArgTy = ArgIdx->getType()->getAs<PointerType>();
422 // The Idx argument should be a pointer and the type of the pointer and
423 // the type of pipe element should also be the same.
424 if (!ArgTy ||
426 EltTy, ArgTy->getPointeeType()->getCanonicalTypeInternal())) {
427 S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
428 << Call->getDirectCallee() << S.Context.getPointerType(EltTy)
429 << ArgIdx->getType() << ArgIdx->getSourceRange();
430 return true;
431 }
432 return false;
433}
434
436 // OpenCL v2.0 s6.13.16.2 - The built-in read/write
437 // functions have two forms.
438 switch (Call->getNumArgs()) {
439 case 2:
441 return true;
442 // The call with 2 arguments should be
443 // read/write_pipe(pipe T, T*).
444 // Check packet type T.
446 return true;
447 break;
448
449 case 4: {
451 return true;
452 // The call with 4 arguments should be
453 // read/write_pipe(pipe T, reserve_id_t, uint, T*).
454 // Check reserve_id_t.
455 if (!Call->getArg(1)->getType()->isReserveIDT()) {
456 Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
457 << Call->getDirectCallee() << getASTContext().OCLReserveIDTy
458 << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange();
459 return true;
460 }
461
462 // Check the index.
463 const Expr *Arg2 = Call->getArg(2);
464 if (!Arg2->getType()->isIntegerType() &&
465 !Arg2->getType()->isUnsignedIntegerType()) {
466 Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
467 << Call->getDirectCallee() << getASTContext().UnsignedIntTy
468 << Arg2->getType() << Arg2->getSourceRange();
469 return true;
470 }
471
472 // Check packet type T.
474 return true;
475 } break;
476 default:
477 Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_arg_num)
478 << Call->getDirectCallee() << Call->getSourceRange();
479 return true;
480 }
481
482 return false;
483}
484
486 if (SemaRef.checkArgCount(Call, 2))
487 return true;
488
490 return true;
491
492 // Check the reserve size.
493 if (!Call->getArg(1)->getType()->isIntegerType() &&
494 !Call->getArg(1)->getType()->isUnsignedIntegerType()) {
495 Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
496 << Call->getDirectCallee() << getASTContext().UnsignedIntTy
497 << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange();
498 return true;
499 }
500
501 // Since return type of reserve_read/write_pipe built-in function is
502 // reserve_id_t, which is not defined in the builtin def file , we used int
503 // as return type and need to override the return type of these functions.
504 Call->setType(getASTContext().OCLReserveIDTy);
505
506 return false;
507}
508
510 if (SemaRef.checkArgCount(Call, 2))
511 return true;
512
514 return true;
515
516 // Check reserve_id_t.
517 if (!Call->getArg(1)->getType()->isReserveIDT()) {
518 Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
519 << Call->getDirectCallee() << getASTContext().OCLReserveIDTy
520 << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange();
521 return true;
522 }
523
524 return false;
525}
526
528 if (SemaRef.checkArgCount(Call, 1))
529 return true;
530
531 if (!Call->getArg(0)->getType()->isPipeType()) {
532 Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_first_arg)
533 << Call->getDirectCallee() << Call->getArg(0)->getSourceRange();
534 return true;
535 }
536
537 return false;
538}
539
540bool SemaOpenCL::checkBuiltinToAddr(unsigned BuiltinID, CallExpr *Call) {
541 if (SemaRef.checkArgCount(Call, 1))
542 return true;
543
544 auto RT = Call->getArg(0)->getType();
545 if (!RT->isPointerType() ||
546 RT->getPointeeType().getAddressSpace() == LangAS::opencl_constant) {
547 Diag(Call->getArg(0)->getBeginLoc(),
548 diag::err_opencl_builtin_to_addr_invalid_arg)
549 << Call->getArg(0) << Call->getDirectCallee() << Call->getSourceRange();
550 return true;
551 }
552
553 if (RT->getPointeeType().getAddressSpace() != LangAS::opencl_generic) {
554 Diag(Call->getArg(0)->getBeginLoc(),
555 diag::warn_opencl_generic_address_space_arg)
556 << Call->getDirectCallee()->getNameInfo().getAsString()
557 << Call->getArg(0)->getSourceRange();
558 }
559
560 RT = RT->getPointeeType();
561 auto Qual = RT.getQualifiers();
562 switch (BuiltinID) {
563 case Builtin::BIto_global:
564 Qual.setAddressSpace(LangAS::opencl_global);
565 break;
566 case Builtin::BIto_local:
567 Qual.setAddressSpace(LangAS::opencl_local);
568 break;
569 case Builtin::BIto_private:
570 Qual.setAddressSpace(LangAS::opencl_private);
571 break;
572 default:
573 llvm_unreachable("Invalid builtin function");
574 }
575 Call->setType(getASTContext().getPointerType(
576 getASTContext().getQualifiedType(RT.getUnqualifiedType(), Qual)));
577
578 return false;
579}
580
582 IdentifierInfo *II = FDecl->getIdentifier();
583 if (!II)
584 return;
585 StringRef Name = II->getName();
586 if (Name != "read_imagei" && Name != "read_imageui")
587 return;
588
589 if (FDecl->getNumParams() < 2)
590 return;
591 QualType ParamTy = FDecl->getParamDecl(1)->getType().getCanonicalType();
592 if (!ParamTy->isSamplerT())
593 return;
594 Expr *SamplerArg = Call->getArg(1);
595
596 Expr *IntExpr = nullptr;
597 Expr *Inner = SamplerArg->IgnoreParenCasts();
598
599 if (auto *DRE = dyn_cast<DeclRefExpr>(Inner)) {
600 if (auto *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
601 if (const Expr *Init = Var->getAnyInitializer()) {
602 Init = Init->IgnoreParenImpCasts();
603 if (Init->getType()->isIntegerType())
604 IntExpr = const_cast<Expr *>(Init);
605 }
606 }
607 } else if (Inner->getType()->isIntegerType()) {
608 IntExpr = Inner;
609 }
610
611 if (!IntExpr)
612 return;
613
614 Expr::EvalResult EVResult;
615 if (!IntExpr->EvaluateAsInt(EVResult, getASTContext()))
616 return;
617
618 uint64_t SamplerValue = EVResult.Val.getInt().getLimitedValue();
619 // Must stay in sync with CLK_FILTER_* defines in opencl-c-base.h.
620 constexpr unsigned FilterModeMask = 0x30u;
621 constexpr unsigned FilterModeLinear = 0x20u;
622 if ((SamplerValue & FilterModeMask) == FilterModeLinear)
623 Diag(SamplerArg->getExprLoc(), diag::warn_sampler_argument_invalid_filter)
624 << Name << SamplerArg->getSourceRange();
625}
626
627} // namespace clang
This file declares semantic analysis routines for OpenCL.
APSInt & getInt()
Definition APValue.h:508
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
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:4691
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:4797
Pointer to a block type.
Definition TypeBase.h:3606
QualType getPointeeType() const
Definition TypeBase.h:3618
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2949
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3153
SourceLocation getBeginLoc() const
Definition Expr.h:3283
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3132
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition Expr.h:3140
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:581
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:596
bool hasAttr() const
Definition DeclBase.h:585
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:435
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:831
This represents one expression.
Definition Expr.h:112
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition Expr.cpp:3104
@ NPC_ValueDependentIsNotNull
Specifies that a value-dependent expression should be considered to never be a null pointer constant.
Definition Expr.h:841
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:4077
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 a function declaration or definition.
Definition Decl.h:2027
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2802
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3804
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5371
unsigned getNumParams() const
Definition TypeBase.h:5649
One of these records is kept for each identifier that is lexed.
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.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:295
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:8265
QualType getElementType() const
Definition TypeBase.h:8276
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3392
QualType getPointeeType() const
Definition TypeBase.h:3402
A (possibly-)qualified type.
Definition TypeBase.h:937
QualType getCanonicalType() const
Definition TypeBase.h:8499
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8541
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition TypeBase.h:1347
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)
void checkBuiltinReadImage(FunctionDecl *FDecl, CallExpr *Call)
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:869
ASTContext & Context
Definition Sema.h:1309
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:343
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
The base class of the type hierarchy.
Definition TypeBase.h:1875
bool isBlockPointerType() const
Definition TypeBase.h:8704
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
Definition TypeBase.h:9237
bool isPointerType() const
Definition TypeBase.h:8684
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:9094
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9344
bool isClkEventT() const
Definition TypeBase.h:8936
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
bool isPipeType() const
Definition TypeBase.h:8955
QualType getCanonicalTypeInternal() const
Definition TypeBase.h:3183
bool isQueueT() const
Definition TypeBase.h:8940
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:2336
bool isSamplerT() const
Definition TypeBase.h:8928
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9277
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
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.
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:652
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:654