clang: lib/Sema/SemaOpenCL.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

19

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

37 if (D->hasAttr()) {

38 if (D->getAttr()->getSemanticSpelling() ==

40 Diag(AL.getLoc(), diag::warn_duplicate_declspec)

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

51

52

53

54

55

56

57

58

59 if (const auto *PDecl = dyn_cast(D)) {

60 const Type *DeclTy = PDecl->getType().getCanonicalType().getTypePtr();

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

77}

78

80 uint32_t 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();

92 if (Existing && Existing->getSubGroupSize() != SGSize)

93 Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL;

94

96 OpenCLIntelReqdSubGroupSizeAttr(getASTContext(), AL, SGSize));

97}

98

101}

102

103

104

110 unsigned ArgCounter = 0;

111 bool IllegalParams = false;

112

113

115 I != E; ++I, ++ArgCounter) {

116 if (!(*I)->isPointerType() || !(*I)->getPointeeType()->isVoidType() ||

117 (*I)->getPointeeType().getQualifiers().getAddressSpace() !=

119

120

121

123 if (isa(BlockArg)) {

124 BlockDecl *BD = cast(BlockArg)->getBlockDecl();

126 } else if (isa(BlockArg)) {

127 ErrorLoc = cast(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

140

141

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

156 return true;

157

159 return true;

160

161

162 Expr *NDRangeArg = TheCall->getArg(0);

164 Diag(NDRangeArg->getBeginLoc(), diag::err_opencl_builtin_expected_type)

166 return true;

167 }

168

171 Diag(BlockArg->getBeginLoc(), diag::err_opencl_builtin_expected_type)

173 return true;

174 }

176}

177

180 return true;

181

184 Diag(BlockArg->getBeginLoc(), diag::err_opencl_builtin_expected_type)

186 return true;

187 }

189}

190

191

193

194

197 diag::err_opencl_enqueue_kernel_invalid_local_size_type);

198 return true;

199 }

200

201

203 return false;

204}

205

207 unsigned Start, unsigned End) {

208 bool IllegalParams = false;

209 for (unsigned I = Start; I <= End; ++I)

212 return IllegalParams;

213}

214

215

216

218 Expr *BlockArg,

219 unsigned NumNonVarArgs) {

222 unsigned NumBlockParams =

224 unsigned TotalNumArgs = TheCall->getNumArgs();

225

226

227

228 if (TotalNumArgs != NumBlockParams + NumNonVarArgs) {

230 diag::err_opencl_enqueue_kernel_local_size_args);

231 return true;

232 }

233

234

236 TotalNumArgs - 1);

237}

238

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 << 0;

246 return true;

247 }

248

253

254

257 diag::err_opencl_builtin_expected_type)

259 return true;

260 }

261

262

265 diag::err_opencl_builtin_expected_type)

266 << TheCall->getDirectCallee() << "'kernel_enqueue_flags_t' (i.e. uint)";

267 return true;

268 }

269

270

273 diag::err_opencl_builtin_expected_type)

275 return true;

276 }

277

278

279

280 if (NumArgs == 4) {

281

283 Diag(Arg3->getBeginLoc(), diag::err_opencl_builtin_expected_type)

285 return true;

286 }

287

291 0) {

292 Diag(Arg3->getBeginLoc(), diag::err_opencl_enqueue_kernel_blocks_no_args);

293 return true;

294 }

295 return false;

296 }

297

301

302 if (NumArgs >= 7) {

303

306 Diag(Arg6->getBeginLoc(), diag::err_opencl_builtin_expected_type)

308 return true;

309 }

311 return true;

312

313

316 diag::err_opencl_builtin_expected_type)

318 return true;

319 }

320

323

324

329 diag::err_opencl_builtin_expected_type)

331 << Context.getPointerType(Context.OCLClkEventTy);

332 return true;

333 }

334

335

341 diag::err_opencl_builtin_expected_type)

343 << Context.getPointerType(Context.OCLClkEventTy);

344 return true;

345 }

346

347 if (NumArgs == 7)

348 return false;

349

351 }

352

353

354 Diag(TheCall->getBeginLoc(), diag::err_opencl_enqueue_kernel_incorrect_args);

355 return true;

356}

357

358

360 return D->getAttr();

361}

362

363

365 const Expr *Arg0 = Call->getArg(0);

366

368 S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_first_arg)

370 return true;

371 }

372 OpenCLAccessAttr *AccessQual =

374

375

376

377

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())) {

388 diag::err_opencl_builtin_pipe_invalid_access_modifier)

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())) {

402 diag::err_opencl_builtin_pipe_invalid_access_modifier)

404 return true;

405 }

406 break;

407 default:

408 break;

409 }

410 return false;

411}

412

413

415 const Expr *Arg0 = Call->getArg(0);

416 const Expr *ArgIdx = Call->getArg(Idx);

417 const PipeType *PipeTy = cast(Arg0->getType());

420

421

422 if (!ArgTy ||

425 S.Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)

428 return true;

429 }

430 return false;

431}

432

434

435

436 switch (Call->getNumArgs()) {

437 case 2:

439 return true;

440

441

442

444 return true;

445 break;

446

447 case 4: {

449 return true;

450

451

452

453 if (Call->getArg(1)->getType()->isReserveIDT()) {

454 Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)

456 << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange();

457 return true;

458 }

459

460

461 const Expr *Arg2 = Call->getArg(2);

464 Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)

467 return true;

468 }

469

470

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

485 return true;

486

488 return true;

489

490

491 if (Call->getArg(1)->getType()->isIntegerType() &&

492 Call->getArg(1)->getType()->isUnsignedIntegerType()) {

493 Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)

495 << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange();

496 return true;

497 }

498

499

500

501

503

504 return false;

505}

506

509 return true;

510

512 return true;

513

514

515 if (Call->getArg(1)->getType()->isReserveIDT()) {

516 Diag(Call->getBeginLoc(), diag::err_opencl_builtin_pipe_invalid_arg)

518 << Call->getArg(1)->getType() << Call->getArg(1)->getSourceRange();

519 return true;

520 }

521

522 return false;

523}

524

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

540 return true;

541

542 auto RT = Call->getArg(0)->getType();

543 if (!RT->isPointerType() ||

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

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:

562 break;

563 case Builtin::BIto_local:

565 break;

566 case Builtin::BIto_private:

568 break;

569 default:

570 llvm_unreachable("Invalid builtin function");

571 }

573 getASTContext().getQualifiedType(RT.getUnqualifiedType(), Qual)));

574

575 return false;

576}

577

578}

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 ...

bool hasSameType(QualType T1, QualType T2) const

Determine whether the given types T1 and T2 are equivalent.

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

CanQualType OCLReserveIDTy

SourceRange getRange() const

SourceLocation getLoc() const

const IdentifierInfo * getAttrName() const

Represents a block literal declaration, which is like an unnamed FunctionDecl.

const ParmVarDecl * getParamDecl(unsigned i) const

QualType getPointeeType() const

CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).

Expr * getArg(unsigned Arg)

getArg - Return the specified argument.

SourceLocation getBeginLoc() const LLVM_READONLY

FunctionDecl * getDirectCallee()

If the callee is a FunctionDecl, return it. Otherwise return null.

unsigned getNumArgs() const

getNumArgs - Return the number of actual arguments to this call.

Decl - This represents one declaration (or definition), e.g.

SourceLocation getBeginLoc() const LLVM_READONLY

This represents one expression.

@ NPC_ValueDependentIsNotNull

Specifies that a value-dependent expression should be considered to never be a null pointer constant.

NullPointerConstantKind isNullPointerConstant(ASTContext &Ctx, NullPointerConstantValueDependence NPC) const

isNullPointerConstant - C99 6.3.2.3p3 - Test if this reduces down to a Null pointer constant.

Represents a prototype with parameter type info, e.g.

unsigned getNumParams() const

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.

bool isSupported(llvm::StringRef Ext, const LangOptions &LO) const

ParsedAttr - Represents a syntactic attribute.

unsigned getSemanticSpelling() const

If the parsed attribute has a semantic equivalent, and it would have a semantic Spelling enumeration ...

Expr * getArgAsExpr(unsigned Arg) const

QualType getElementType() const

PointerType - C99 6.7.5.1 - Pointer Declarators.

QualType getPointeeType() const

A (possibly-)qualified type.

QualType getCanonicalType() const

QualType getUnqualifiedType() const

Retrieve the unqualified variant of the given type, removing as little sugar as possible.

static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)

SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)

Emit a diagnostic.

ASTContext & getASTContext() const

const LangOptions & getLangOpts() const

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.

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...

bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount)

Checks that a call expression's argument count is the desired number.

OpenCLOptions & getOpenCLOptions()

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...

SourceLocation getBeginLoc() const LLVM_READONLY

The base class of the type hierarchy.

bool isBlockPointerType() const

const Type * getPointeeOrArrayElementType() const

If this is a pointer type, return the pointee type.

bool isPointerType() const

bool isIntegerType() const

isIntegerType() does not include complex integers (a GCC extension).

const T * castAs() const

Member-template castAs.

QualType getPointeeType() const

If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.

QualType getCanonicalTypeInternal() const

bool isUnsignedIntegerType() const

Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...

const T * getAs() const

Member-template getAs'.

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...

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.

static bool checkPipePacketType(Sema &S, CallExpr *Call, unsigned Idx)

Returns true if pipe element type is different from the pointer.