clang  20.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 
13 #include "clang/Sema/SemaOpenCL.h"
14 #include "clang/AST/Attr.h"
15 #include "clang/AST/DeclBase.h"
17 #include "clang/Sema/ParsedAttr.h"
18 #include "clang/Sema/Sema.h"
19 
20 namespace 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() ==
39  AL.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 
79 static inline bool isBlockPointer(Expr *Arg) {
80  return Arg->getType()->isBlockPointerType();
81 }
82 
83 /// OpenCL C v2.0, s6.13.17.2 - Checks that the block parameters are all local
84 /// void*, which is a requirement of device side enqueue.
85 static bool checkBlockArgs(Sema &S, Expr *BlockArg) {
86  const BlockPointerType *BPT =
87  cast<BlockPointerType>(BlockArg->getType().getCanonicalType());
88  ArrayRef<QualType> Params =
89  BPT->getPointeeType()->castAs<FunctionProtoType>()->getParamTypes();
90  unsigned ArgCounter = 0;
91  bool IllegalParams = false;
92  // Iterate through the block parameters until either one is found that is not
93  // a local void*, or the block is valid.
94  for (ArrayRef<QualType>::iterator I = Params.begin(), E = Params.end();
95  I != E; ++I, ++ArgCounter) {
96  if (!(*I)->isPointerType() || !(*I)->getPointeeType()->isVoidType() ||
97  (*I)->getPointeeType().getQualifiers().getAddressSpace() !=
99  // Get the location of the error. If a block literal has been passed
100  // (BlockExpr) then we can point straight to the offending argument,
101  // else we just point to the variable reference.
102  SourceLocation ErrorLoc;
103  if (isa<BlockExpr>(BlockArg)) {
104  BlockDecl *BD = cast<BlockExpr>(BlockArg)->getBlockDecl();
105  ErrorLoc = BD->getParamDecl(ArgCounter)->getBeginLoc();
106  } else if (isa<DeclRefExpr>(BlockArg)) {
107  ErrorLoc = cast<DeclRefExpr>(BlockArg)->getBeginLoc();
108  }
109  S.Diag(ErrorLoc,
110  diag::err_opencl_enqueue_kernel_blocks_non_local_void_args);
111  IllegalParams = true;
112  }
113  }
114 
115  return IllegalParams;
116 }
117 
119  // OpenCL device can support extension but not the feature as extension
120  // requires subgroup independent forward progress, but subgroup independent
121  // forward progress is optional in OpenCL C 3.0 __opencl_c_subgroups feature.
122  if (!SemaRef.getOpenCLOptions().isSupported("cl_khr_subgroups",
123  getLangOpts()) &&
124  !SemaRef.getOpenCLOptions().isSupported("__opencl_c_subgroups",
125  getLangOpts())) {
126  Diag(Call->getBeginLoc(), diag::err_opencl_requires_extension)
127  << 1 << Call->getDirectCallee()
128  << "cl_khr_subgroups or __opencl_c_subgroups";
129  return true;
130  }
131  return false;
132 }
133 
135  if (SemaRef.checkArgCount(TheCall, 2))
136  return true;
137 
138  if (checkSubgroupExt(TheCall))
139  return true;
140 
141  // First argument is an ndrange_t type.
142  Expr *NDRangeArg = TheCall->getArg(0);
143  if (NDRangeArg->getType().getUnqualifiedType().getAsString() != "ndrange_t") {
144  Diag(NDRangeArg->getBeginLoc(), diag::err_opencl_builtin_expected_type)
145  << TheCall->getDirectCallee() << "'ndrange_t'";
146  return true;
147  }
148 
149  Expr *BlockArg = TheCall->getArg(1);
150  if (!isBlockPointer(BlockArg)) {
151  Diag(BlockArg->getBeginLoc(), diag::err_opencl_builtin_expected_type)
152  << TheCall->getDirectCallee() << "block";
153  return true;
154  }
155  return checkBlockArgs(SemaRef, BlockArg);
156 }
157 
159  if (SemaRef.checkArgCount(TheCall, 1))
160  return true;
161 
162  Expr *BlockArg = TheCall->getArg(0);
163  if (!isBlockPointer(BlockArg)) {
164  Diag(BlockArg->getBeginLoc(), diag::err_opencl_builtin_expected_type)
165  << TheCall->getDirectCallee() << "block";
166  return true;
167  }
168  return checkBlockArgs(SemaRef, BlockArg);
169 }
170 
171 /// Diagnose integer type and any valid implicit conversion to it.
172 static bool checkOpenCLEnqueueIntType(Sema &S, Expr *E, const QualType &IntT) {
173  // Taking into account implicit conversions,
174  // allow any integer.
175  if (!E->getType()->isIntegerType()) {
176  S.Diag(E->getBeginLoc(),
177  diag::err_opencl_enqueue_kernel_invalid_local_size_type);
178  return true;
179  }
180  // Potentially emit standard warnings for implicit conversions if enabled
181  // using -Wconversion.
182  S.CheckImplicitConversion(E, IntT, E->getBeginLoc());
183  return false;
184 }
185 
187  unsigned Start, unsigned End) {
188  bool IllegalParams = false;
189  for (unsigned I = Start; I <= End; ++I)
190  IllegalParams |= checkOpenCLEnqueueIntType(S, TheCall->getArg(I),
191  S.Context.getSizeType());
192  return IllegalParams;
193 }
194 
195 /// OpenCL v2.0, s6.13.17.1 - Check that sizes are provided for all
196 /// 'local void*' parameter of passed block.
198  Expr *BlockArg,
199  unsigned NumNonVarArgs) {
200  const BlockPointerType *BPT =
201  cast<BlockPointerType>(BlockArg->getType().getCanonicalType());
202  unsigned NumBlockParams =
203  BPT->getPointeeType()->castAs<FunctionProtoType>()->getNumParams();
204  unsigned TotalNumArgs = TheCall->getNumArgs();
205 
206  // For each argument passed to the block, a corresponding uint needs to
207  // be passed to describe the size of the local memory.
208  if (TotalNumArgs != NumBlockParams + NumNonVarArgs) {
209  S.Diag(TheCall->getBeginLoc(),
210  diag::err_opencl_enqueue_kernel_local_size_args);
211  return true;
212  }
213 
214  // Check that the sizes of the local memory are specified by integers.
215  return checkOpenCLEnqueueLocalSizeArgs(S, TheCall, NumNonVarArgs,
216  TotalNumArgs - 1);
217 }
218 
220  ASTContext &Context = getASTContext();
221  unsigned NumArgs = TheCall->getNumArgs();
222 
223  if (NumArgs < 4) {
224  Diag(TheCall->getBeginLoc(), diag::err_typecheck_call_too_few_args_at_least)
225  << 0 << 4 << NumArgs << /*is non object*/ 0;
226  return true;
227  }
228 
229  Expr *Arg0 = TheCall->getArg(0);
230  Expr *Arg1 = TheCall->getArg(1);
231  Expr *Arg2 = TheCall->getArg(2);
232  Expr *Arg3 = TheCall->getArg(3);
233 
234  // First argument always needs to be a queue_t type.
235  if (!Arg0->getType()->isQueueT()) {
236  Diag(TheCall->getArg(0)->getBeginLoc(),
237  diag::err_opencl_builtin_expected_type)
238  << TheCall->getDirectCallee() << getASTContext().OCLQueueTy;
239  return true;
240  }
241 
242  // Second argument always needs to be a kernel_enqueue_flags_t enum value.
243  if (!Arg1->getType()->isIntegerType()) {
244  Diag(TheCall->getArg(1)->getBeginLoc(),
245  diag::err_opencl_builtin_expected_type)
246  << TheCall->getDirectCallee() << "'kernel_enqueue_flags_t' (i.e. uint)";
247  return true;
248  }
249 
250  // Third argument is always an ndrange_t type.
251  if (Arg2->getType().getUnqualifiedType().getAsString() != "ndrange_t") {
252  Diag(TheCall->getArg(2)->getBeginLoc(),
253  diag::err_opencl_builtin_expected_type)
254  << TheCall->getDirectCallee() << "'ndrange_t'";
255  return true;
256  }
257 
258  // With four arguments, there is only one form that the function could be
259  // called in: no events and no variable arguments.
260  if (NumArgs == 4) {
261  // check that the last argument is the right block type.
262  if (!isBlockPointer(Arg3)) {
263  Diag(Arg3->getBeginLoc(), diag::err_opencl_builtin_expected_type)
264  << TheCall->getDirectCallee() << "block";
265  return true;
266  }
267  // we have a block type, check the prototype
268  const BlockPointerType *BPT =
269  cast<BlockPointerType>(Arg3->getType().getCanonicalType());
271  0) {
272  Diag(Arg3->getBeginLoc(), diag::err_opencl_enqueue_kernel_blocks_no_args);
273  return true;
274  }
275  return false;
276  }
277  // we can have block + varargs.
278  if (isBlockPointer(Arg3))
279  return (checkBlockArgs(SemaRef, Arg3) ||
280  checkOpenCLEnqueueVariadicArgs(SemaRef, TheCall, Arg3, 4));
281  // last two cases with either exactly 7 args or 7 args and varargs.
282  if (NumArgs >= 7) {
283  // check common block argument.
284  Expr *Arg6 = TheCall->getArg(6);
285  if (!isBlockPointer(Arg6)) {
286  Diag(Arg6->getBeginLoc(), diag::err_opencl_builtin_expected_type)
287  << TheCall->getDirectCallee() << "block";
288  return true;
289  }
290  if (checkBlockArgs(SemaRef, Arg6))
291  return true;
292 
293  // Forth argument has to be any integer type.
294  if (!Arg3->getType()->isIntegerType()) {
295  Diag(TheCall->getArg(3)->getBeginLoc(),
296  diag::err_opencl_builtin_expected_type)
297  << TheCall->getDirectCallee() << "integer";
298  return true;
299  }
300  // check remaining common arguments.
301  Expr *Arg4 = TheCall->getArg(4);
302  Expr *Arg5 = TheCall->getArg(5);
303 
304  // Fifth argument is always passed as a pointer to clk_event_t.
305  if (!Arg4->isNullPointerConstant(Context,
308  Diag(TheCall->getArg(4)->getBeginLoc(),
309  diag::err_opencl_builtin_expected_type)
310  << TheCall->getDirectCallee()
311  << Context.getPointerType(Context.OCLClkEventTy);
312  return true;
313  }
314 
315  // Sixth argument is always passed as a pointer to clk_event_t.
316  if (!Arg5->isNullPointerConstant(Context,
318  !(Arg5->getType()->isPointerType() &&
319  Arg5->getType()->getPointeeType()->isClkEventT())) {
320  Diag(TheCall->getArg(5)->getBeginLoc(),
321  diag::err_opencl_builtin_expected_type)
322  << TheCall->getDirectCallee()
323  << Context.getPointerType(Context.OCLClkEventTy);
324  return true;
325  }
326 
327  if (NumArgs == 7)
328  return false;
329 
330  return checkOpenCLEnqueueVariadicArgs(SemaRef, TheCall, Arg6, 7);
331  }
332 
333  // None of the specific case has been detected, give generic error
334  Diag(TheCall->getBeginLoc(), diag::err_opencl_enqueue_kernel_incorrect_args);
335  return true;
336 }
337 
338 /// Returns OpenCL access qual.
339 static OpenCLAccessAttr *getOpenCLArgAccess(const Decl *D) {
340  return D->getAttr<OpenCLAccessAttr>();
341 }
342 
343 /// Returns true if pipe element type is different from the pointer.
344 static bool checkPipeArg(Sema &S, CallExpr *Call) {
345  const Expr *Arg0 = Call->getArg(0);
346  // First argument type should always be pipe.
347  if (!Arg0->getType()->isPipeType()) {
348  S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_first_arg)
349  << Call->getDirectCallee() << Arg0->getSourceRange();
350  return true;
351  }
352  OpenCLAccessAttr *AccessQual =
353  getOpenCLArgAccess(cast<DeclRefExpr>(Arg0)->getDecl());
354  // Validates the access qualifier is compatible with the call.
355  // OpenCL v2.0 s6.13.16 - The access qualifiers for pipe should only be
356  // read_only and write_only, and assumed to be read_only if no qualifier is
357  // specified.
358  switch (Call->getDirectCallee()->getBuiltinID()) {
359  case Builtin::BIread_pipe:
360  case Builtin::BIreserve_read_pipe:
361  case Builtin::BIcommit_read_pipe:
362  case Builtin::BIwork_group_reserve_read_pipe:
363  case Builtin::BIsub_group_reserve_read_pipe:
364  case Builtin::BIwork_group_commit_read_pipe:
365  case Builtin::BIsub_group_commit_read_pipe:
366  if (!(!AccessQual || AccessQual->isReadOnly())) {
367  S.Diag(Arg0->getBeginLoc(),
368  diag::err_opencl_builtin_pipe_invalid_access_modifier)
369  << "read_only" << Arg0->getSourceRange();
370  return true;
371  }
372  break;
373  case Builtin::BIwrite_pipe:
374  case Builtin::BIreserve_write_pipe:
375  case Builtin::BIcommit_write_pipe:
376  case Builtin::BIwork_group_reserve_write_pipe:
377  case Builtin::BIsub_group_reserve_write_pipe:
378  case Builtin::BIwork_group_commit_write_pipe:
379  case Builtin::BIsub_group_commit_write_pipe:
380  if (!(AccessQual && AccessQual->isWriteOnly())) {
381  S.Diag(Arg0->getBeginLoc(),
382  diag::err_opencl_builtin_pipe_invalid_access_modifier)
383  << "write_only" << Arg0->getSourceRange();
384  return true;
385  }
386  break;
387  default:
388  break;
389  }
390  return false;
391 }
392 
393 /// Returns true if pipe element type is different from the pointer.
394 static bool checkPipePacketType(Sema &S, CallExpr *Call, unsigned Idx) {
395  const Expr *Arg0 = Call->getArg(0);
396  const Expr *ArgIdx = Call->getArg(Idx);
397  const PipeType *PipeTy = cast<PipeType>(Arg0->getType());
398  const QualType EltTy = PipeTy->getElementType();
399  const PointerType *ArgTy = ArgIdx->getType()->getAs<PointerType>();
400  // The Idx argument should be a pointer and the type of the pointer and
401  // the type of pipe element should also be the same.
402  if (!ArgTy ||
403  !S.Context.hasSameType(
404  EltTy, ArgTy->getPointeeType()->getCanonicalTypeInternal())) {
405  S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
406  << Call->getDirectCallee() << S.Context.getPointerType(EltTy)
407  << ArgIdx->getType() << ArgIdx->getSourceRange();
408  return true;
409  }
410  return false;
411 }
412 
414  // OpenCL v2.0 s6.13.16.2 - The built-in read/write
415  // functions have two forms.
416  switch (Call->getNumArgs()) {
417  case 2:
418  if (checkPipeArg(SemaRef, Call))
419  return true;
420  // The call with 2 arguments should be
421  // read/write_pipe(pipe T, T*).
422  // Check packet type T.
423  if (checkPipePacketType(SemaRef, Call, 1))
424  return true;
425  break;
426 
427  case 4: {
428  if (checkPipeArg(SemaRef, Call))
429  return true;
430  // The call with 4 arguments should be
431  // read/write_pipe(pipe T, reserve_id_t, uint, T*).
432  // Check reserve_id_t.
433  if (!Call->getArg(1)->getType()->isReserveIDT()) {
434  Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
435  << Call->getDirectCallee() << getASTContext().OCLReserveIDTy
436  << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange();
437  return true;
438  }
439 
440  // Check the index.
441  const Expr *Arg2 = Call->getArg(2);
442  if (!Arg2->getType()->isIntegerType() &&
443  !Arg2->getType()->isUnsignedIntegerType()) {
444  Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
445  << Call->getDirectCallee() << getASTContext().UnsignedIntTy
446  << Arg2->getType() << Arg2->getSourceRange();
447  return true;
448  }
449 
450  // Check packet type T.
451  if (checkPipePacketType(SemaRef, Call, 3))
452  return true;
453  } break;
454  default:
455  Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_arg_num)
456  << Call->getDirectCallee() << Call->getSourceRange();
457  return true;
458  }
459 
460  return false;
461 }
462 
464  if (SemaRef.checkArgCount(Call, 2))
465  return true;
466 
467  if (checkPipeArg(SemaRef, Call))
468  return true;
469 
470  // Check the reserve size.
471  if (!Call->getArg(1)->getType()->isIntegerType() &&
472  !Call->getArg(1)->getType()->isUnsignedIntegerType()) {
473  Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
474  << Call->getDirectCallee() << getASTContext().UnsignedIntTy
475  << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange();
476  return true;
477  }
478 
479  // Since return type of reserve_read/write_pipe built-in function is
480  // reserve_id_t, which is not defined in the builtin def file , we used int
481  // as return type and need to override the return type of these functions.
482  Call->setType(getASTContext().OCLReserveIDTy);
483 
484  return false;
485 }
486 
488  if (SemaRef.checkArgCount(Call, 2))
489  return true;
490 
491  if (checkPipeArg(SemaRef, Call))
492  return true;
493 
494  // Check reserve_id_t.
495  if (!Call->getArg(1)->getType()->isReserveIDT()) {
496  Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)
497  << Call->getDirectCallee() << getASTContext().OCLReserveIDTy
498  << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange();
499  return true;
500  }
501 
502  return false;
503 }
504 
506  if (SemaRef.checkArgCount(Call, 1))
507  return true;
508 
509  if (!Call->getArg(0)->getType()->isPipeType()) {
510  Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_first_arg)
511  << Call->getDirectCallee() << Call->getArg(0)->getSourceRange();
512  return true;
513  }
514 
515  return false;
516 }
517 
518 bool SemaOpenCL::checkBuiltinToAddr(unsigned BuiltinID, CallExpr *Call) {
519  if (SemaRef.checkArgCount(Call, 1))
520  return true;
521 
522  auto RT = Call->getArg(0)->getType();
523  if (!RT->isPointerType() ||
524  RT->getPointeeType().getAddressSpace() == LangAS::opencl_constant) {
525  Diag(Call->getBeginLoc(), diag::err_opencl_builtin_to_addr_invalid_arg)
526  << Call->getArg(0) << Call->getDirectCallee() << Call->getSourceRange();
527  return true;
528  }
529 
530  if (RT->getPointeeType().getAddressSpace() != LangAS::opencl_generic) {
531  Diag(Call->getArg(0)->getBeginLoc(),
532  diag::warn_opencl_generic_address_space_arg)
533  << Call->getDirectCallee()->getNameInfo().getAsString()
534  << Call->getArg(0)->getSourceRange();
535  }
536 
537  RT = RT->getPointeeType();
538  auto Qual = RT.getQualifiers();
539  switch (BuiltinID) {
540  case Builtin::BIto_global:
541  Qual.setAddressSpace(LangAS::opencl_global);
542  break;
543  case Builtin::BIto_local:
544  Qual.setAddressSpace(LangAS::opencl_local);
545  break;
546  case Builtin::BIto_private:
547  Qual.setAddressSpace(LangAS::opencl_private);
548  break;
549  default:
550  llvm_unreachable("Invalid builtin function");
551  }
552  Call->setType(getASTContext().getPointerType(
553  getASTContext().getQualifiedType(RT.getUnqualifiedType(), Qual)));
554 
555  return false;
556 }
557 
558 } // namespace clang
const Decl * D
Expr * E
This file declares semantic analysis routines for OpenCL.
SourceLocation End
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:187
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:2649
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:1129
CanQualType OCLReserveIDTy
Definition: ASTContext.h:1162
CanQualType OCLQueueTy
Definition: ASTContext.h:1162
const IdentifierInfo * getAttrName() const
SourceLocation getLoc() const
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Definition: Decl.h:4472
const ParmVarDecl * getParamDecl(unsigned i) const
Definition: Decl.h:4578
Pointer to a block type.
Definition: Type.h:3407
QualType getPointeeType() const
Definition: Type.h:3419
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2882
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.cpp:1693
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition: Expr.h:3060
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: Expr.h:3073
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition: Expr.h:3052
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
T * getAttr() const
Definition: DeclBase.h:580
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Decl.h:784
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:3998
QualType getType() const
Definition: Expr.h:142
Represents a prototype with parameter type info, e.g.
Definition: Type.h:5012
unsigned getNumParams() const
Definition: Type.h:5265
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:266
PipeType - OpenCL20.
Definition: Type.h:7609
QualType getElementType() const
Definition: Type.h:7620
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:3197
QualType getPointeeType() const
Definition: Type.h:3207
A (possibly-)qualified type.
Definition: Type.h:941
QualType getCanonicalType() const
Definition: Type.h:7812
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:7854
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition: Type.h:1339
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:64
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:134
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:158
bool checkBuiltinEnqueueKernel(CallExpr *TheCall)
OpenCL C v2.0, s6.13.17 - Enqueue kernel function contains four different overload formats specified ...
Definition: SemaOpenCL.cpp:219
bool checkBuiltinCommitRWPipe(CallExpr *Call)
Definition: SemaOpenCL.cpp:487
bool checkBuiltinPipePackets(CallExpr *Call)
Definition: SemaOpenCL.cpp:505
void handleNoSVMAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaOpenCL.cpp:23
bool checkSubgroupExt(CallExpr *Call)
Definition: SemaOpenCL.cpp:118
void handleAccessAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaOpenCL.cpp:32
bool checkBuiltinToAddr(unsigned BuiltinID, CallExpr *Call)
Definition: SemaOpenCL.cpp:518
bool checkBuiltinRWPipe(CallExpr *Call)
Definition: SemaOpenCL.cpp:413
bool checkBuiltinReserveRWPipe(CallExpr *Call)
Definition: SemaOpenCL.cpp:463
SemaOpenCL(Sema &S)
Definition: SemaOpenCL.cpp:21
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:493
OpenCLOptions & getOpenCLOptions()
Definition: Sema.h:554
ASTContext & Context
Definition: Sema.h:962
void CheckImplicitConversion(Expr *E, QualType T, SourceLocation CC, bool *ICContext=nullptr, bool IsListInit=false)
bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount)
Checks that a call expression's argument count is the desired number.
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:1829
bool isBlockPointerType() const
Definition: Type.h:8027
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
Definition: Type.h:8525
bool isPointerType() const
Definition: Type.h:8013
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: Type.h:8387
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:8635
bool isClkEventT() const
Definition: Type.h:8236
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:8265
QualType getCanonicalTypeInternal() const
Definition: Type.h:2984
bool isQueueT() const
Definition: Type.h:8240
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:2196
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8568
unsigned llvm::PointerUnion< const Decl *, const Expr * > DeclTy
Definition: Descriptor.h:28
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:85
static bool checkOpenCLEnqueueIntType(Sema &S, Expr *E, const QualType &IntT)
Diagnose integer type and any valid implicit conversion to it.
Definition: SemaOpenCL.cpp:172
static bool checkPipeArg(Sema &S, CallExpr *Call)
Returns true if pipe element type is different from the pointer.
Definition: SemaOpenCL.cpp:344
static bool isBlockPointer(Expr *Arg)
Definition: SemaOpenCL.cpp:79
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:197
static bool checkOpenCLEnqueueLocalSizeArgs(Sema &S, CallExpr *TheCall, unsigned Start, unsigned End)
Definition: SemaOpenCL.cpp:186
static bool checkPipePacketType(Sema &S, CallExpr *Call, unsigned Idx)
Returns true if pipe element type is different from the pointer.
Definition: SemaOpenCL.cpp:394
static OpenCLAccessAttr * getOpenCLArgAccess(const Decl *D)
Returns OpenCL access qual.
Definition: SemaOpenCL.cpp:339