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

1

2

3

4

5

6

7

8

9

10

21

22using namespace clang;

23

24

25

26

27

29

31 unsigned DiagID) {

33 "Should only be called during SYCL compilation");

34 FunctionDecl *FD = dyn_cast(SemaRef.getCurLexicalContext());

35 SemaDiagnosticBuilder::Kind DiagKind = [this, FD] {

36 if (!FD)

37 return SemaDiagnosticBuilder::K_Nop;

39 return SemaDiagnosticBuilder::K_ImmediateWithCallStack;

40 return SemaDiagnosticBuilder::K_Deferred;

41 }();

43}

44

47 return CAT->isZeroSize();

48 return false;

49}

50

52 llvm::DenseSet Visited,

55 "Should only be called during SYCL compilation");

56

57

58 bool NeedToEmitNotes = true;

59

61 bool ErrorFound = false;

63 DiagIfDeviceCode(UsedAt, diag::err_typecheck_zero_array_size) << 1;

64 ErrorFound = true;

65 }

66

67 if (ErrorFound) {

68 if (NeedToEmitNotes) {

69 if (auto *FD = dyn_cast(D))

71 diag::note_illegal_field_declared_here)

72 << FD->getType()->isPointerType() << FD->getType();

73 else

75 }

76 }

77

78 return ErrorFound;

79 };

80

81

83 StackForRecursion.push_back(DeclToCheck);

84

85

87 History.push_back(nullptr);

88

89 do {

90 const ValueDecl *Next = StackForRecursion.pop_back_val();

92 assert(!History.empty());

93

94 History.pop_back();

95 continue;

96 }

98

99 if (!Visited.insert(NextTy).second)

100 continue;

101

102 auto EmitHistory = [&]() {

103

104 for (uint64_t Index = 1; Index < History.size(); ++Index) {

106 diag::note_within_field_of_type)

107 << History[Index]->getType();

108 }

109 };

110

111 if (Check(NextTy, Next)) {

112 if (NeedToEmitNotes)

113 EmitHistory();

114 NeedToEmitNotes = false;

115 }

116

117

118

123 else

125 if (Check(NextTy, Next)) {

126 if (NeedToEmitNotes)

127 EmitHistory();

128 NeedToEmitNotes = false;

129 }

130 }

131

133 if (auto *NextFD = dyn_cast(Next))

134 History.push_back(NextFD);

135

136

137 StackForRecursion.push_back(nullptr);

138 llvm::append_range(StackForRecursion, RecDecl->fields());

139 }

140 } while (!StackForRecursion.empty());

141}

142

150

157

160 if (!TSI)

162

164}

165

167

170 assert(FT && "Function template is expected");

171

172

174 if (TL->size() < 2) {

175 Diag(FT->getLocation(), diag::warn_sycl_kernel_num_of_template_params);

176 return;

177 }

178

179

180 for (unsigned I = 0; I < 2; ++I) {

184 diag::warn_sycl_kernel_invalid_template_param_type);

185 return;

186 }

187 }

188

189

191 Diag(FT->getLocation(), diag::warn_sycl_kernel_num_of_function_params);

192 return;

193 }

194

195

198 Diag(FT->getLocation(), diag::warn_sycl_kernel_return_type);

199 return;

200 }

201

203}

204

208 (void)SemaRef.GetTypeFromParser(PT, &TSI);

209 assert(TSI && "no type source info for attribute argument");

211 SYCLKernelEntryPointAttr(SemaRef.Context, AL, TSI));

212}

213

214

215

216

217

218

219

223 if (const TagType *TT = dyn_cast(T))

224 Loc = TT->getDecl()->getLocation();

225 else if (const auto *ObjCIT = dyn_cast(T))

226 Loc = ObjCIT->getDecl()->getLocation();

227 return Loc;

228}

229

233

235

236

237

238

239

240

241

242

243 S.Diag(Loc, diag::warn_sycl_kernel_name_not_a_class_type) << KernelName;

245 if (DeclTypeLoc.isValid())

246 S.Diag(DeclTypeLoc, diag::note_entity_declared_at) << KernelName;

247 return true;

248 }

249

250 return false;

251}

252

254 const auto *SEAttr = FD->getAttr();

255 assert(SEAttr && "Missing sycl_external attribute");

260 Diag(SEAttr->getLocation(), diag::err_sycl_external_invalid_linkage)

261 << SEAttr;

262 }

264 Diag(SEAttr->getLocation(),

265 diag::err_sycl_external_invalid_deleted_function)

266 << SEAttr;

267 }

268}

269

271

272

273 SYCLKernelEntryPointAttr *SKEPAttr = nullptr;

274 for (auto *SAI : FD->specific_attrs()) {

275 if (!SKEPAttr) {

276 SKEPAttr = SAI;

277 continue;

278 }

279 if (getASTContext().hasSameType(SAI->getKernelName(),

280 SKEPAttr->getKernelName())) {

281 Diag(SAI->getLocation(), diag::err_sycl_entry_point_invalid_redeclaration)

282 << SKEPAttr << SAI->getKernelName() << SKEPAttr->getKernelName();

283 Diag(SKEPAttr->getLocation(), diag::note_previous_attribute);

284 SAI->setInvalidAttr();

285 } else {

286 Diag(SAI->getLocation(),

287 diag::warn_sycl_entry_point_redundant_declaration)

288 << SAI;

289 Diag(SKEPAttr->getLocation(), diag::note_previous_attribute);

290 }

291 }

292 assert(SKEPAttr && "Missing sycl_kernel_entry_point attribute");

293

294

295 if (!SKEPAttr->getKernelName()->isDependentType() &&

297 SKEPAttr->getKernelName()))

298 SKEPAttr->setInvalidAttr();

299

300

301

304 const auto *PrevSKEPAttr = PrevFD->getAttr();

305 if (PrevSKEPAttr && !PrevSKEPAttr->isInvalidAttr()) {

306 if (getASTContext().hasSameType(SKEPAttr->getKernelName(),

307 PrevSKEPAttr->getKernelName())) {

308 Diag(SKEPAttr->getLocation(),

309 diag::err_sycl_entry_point_invalid_redeclaration)

310 << SKEPAttr << SKEPAttr->getKernelName()

311 << PrevSKEPAttr->getKernelName();

312 Diag(PrevSKEPAttr->getLocation(), diag::note_previous_decl) << PrevFD;

313 SKEPAttr->setInvalidAttr();

314 }

315 }

316 }

317

318 if (const auto *MD = dyn_cast(FD)) {

319 if (!MD->isStatic()) {

320 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)

321 << SKEPAttr << 0;

322 SKEPAttr->setInvalidAttr();

323 }

324 }

325

327 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)

328 << SKEPAttr << 1;

329 SKEPAttr->setInvalidAttr();

330 }

331

333 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)

334 << SKEPAttr << 3;

335 SKEPAttr->setInvalidAttr();

337 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)

338 << SKEPAttr << 2;

339 SKEPAttr->setInvalidAttr();

340 }

341

343 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)

344 << SKEPAttr << 5;

345 SKEPAttr->setInvalidAttr();

347 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)

348 << SKEPAttr << 4;

349 SKEPAttr->setInvalidAttr();

350 }

351

353 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_invalid)

354 << SKEPAttr << 6;

355 SKEPAttr->setInvalidAttr();

356 }

357

359 Diag(SKEPAttr->getLocation(),

360 diag::err_sycl_entry_point_deduced_return_type)

361 << SKEPAttr;

362 SKEPAttr->setInvalidAttr();

365 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_return_type)

366 << SKEPAttr;

367 SKEPAttr->setInvalidAttr();

368 }

369

371 !SKEPAttr->isInvalidAttr()) {

374 if (SKI) {

376

377

378 Diag(FD->getLocation(), diag::err_sycl_kernel_name_conflict)

379 << SKEPAttr;

381 diag::note_previous_declaration);

382 SKEPAttr->setInvalidAttr();

383 }

384 } else {

386 }

387 }

388}

389

390namespace {

391

392

393

394

395

396

397class OutlinedFunctionDeclBodyInstantiator

398 : public TreeTransform {

399public:

400 using ParmDeclMap = llvm::DenseMap<ParmVarDecl *, VarDecl *>;

401

402 OutlinedFunctionDeclBodyInstantiator(Sema &S, ParmDeclMap &M)

403 : TreeTransform(S), SemaRef(S),

404 MapRef(M) {}

405

406

407 bool AlwaysRebuild() { return true; }

408

409

410 ExprResult TransformDeclRefExpr(DeclRefExpr *DRE) {

411 const ParmVarDecl *PVD = dyn_cast(DRE->getDecl());

412 if (PVD) {

413 ParmDeclMap::iterator I = MapRef.find(PVD);

414 if (I != MapRef.end()) {

415 VarDecl *VD = I->second;

416 assert(SemaRef.getASTContext().hasSameUnqualifiedType(PVD->getType(),

419 SemaRef.getASTContext()));

425 }

426 }

427 return DRE;

428 }

429

430private:

431 Sema &SemaRef;

432 ParmDeclMap &MapRef;

433};

434

435}

436

442

443 const auto *SKEPAttr = FD->getAttr();

444 assert(SKEPAttr && "Missing sycl_kernel_entry_point attribute");

445 assert(!SKEPAttr->isInvalidAttr() &&

446 "sycl_kernel_entry_point attribute is invalid");

447

448

449

453 "SYCL kernel name conflict");

454 (void)SKI;

455

456 using ParmDeclMap = OutlinedFunctionDeclBodyInstantiator::ParmDeclMap;

457 ParmDeclMap ParmMap;

458

459 assert(SemaRef.CurContext == FD);

462 unsigned i = 0;

468 ParmMap[PVD] = IPD;

469 ++i;

470 }

471

472 OutlinedFunctionDeclBodyInstantiator OFDBodyInstantiator(SemaRef, ParmMap);

473 Stmt *OFDBody = OFDBodyInstantiator.TransformStmt(Body).get();

477

478 return NewBody;

479}

Defines the Diagnostic-related interfaces.

FormatToken * Next

The next token in the unwrapped line.

This file declares types used to describe SYCL kernels.

static bool isZeroSizedArray(const ConstantArrayType *CAT)

static SourceLocation SourceLocationForUserDeclaredType(QualType QT)

Definition SemaSYCL.cpp:220

static bool CheckSYCLKernelName(Sema &S, SourceLocation Loc, QualType KernelName)

Definition SemaSYCL.cpp:230

This file declares semantic analysis for SYCL constructs.

This file defines SYCL AST classes used to represent calls to SYCL kernels.

Allows QualTypes to be sorted and hence used in maps and sets.

const ConstantArrayType * getAsConstantArrayType(QualType T) const

TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const

Allocate a TypeSourceInfo where all locations have been initialized to a given location,...

void registerSYCLEntryPointFunction(FunctionDecl *FD)

Generates and stores SYCL kernel metadata for the provided SYCL kernel entry point function.

const SYCLKernelInfo & getSYCLKernelInfo(QualType T) const

Given a type used as a SYCL kernel name, returns a reference to the metadata generated from the corre...

const SYCLKernelInfo * findSYCLKernelInfo(QualType T) const

Returns a pointer to the metadata generated from the corresponding SYCLkernel entry point if the prov...

CompoundStmt - This represents a group of statements like { stmt stmt }.

DeclarationNameInfo getNameInfo() const

SourceLocation getTemplateKeywordLoc() const

Retrieve the location of the template keyword preceding this name, if any.

static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)

NestedNameSpecifierLoc getQualifierLoc() const

If the name was qualified, retrieves the nested-name-specifier that precedes the name,...

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

bool isTemplated() const

Determine whether this declaration is a templated entity (whether it is.

bool isInvalidDecl() const

llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const

SourceLocation getLocation() const

void setIsUsed()

Set whether the declaration is used, in the sense of odr-use.

ExprValueKind getValueKind() const

getValueKind - The value kind that this expression produces.

Represents a function declaration or definition.

bool isFunctionTemplateSpecialization() const

Determine whether this function is a function template specialization.

bool isNoReturn() const

Determines whether this function is known to be 'noreturn', through an attribute on its declaration o...

QualType getReturnType() const

ArrayRef< ParmVarDecl * > parameters() const

bool hasPrototype() const

Whether this function has a prototype, either because one was explicitly written or because it was "i...

FunctionTemplateSpecializationInfo * getTemplateSpecializationInfo() const

If this function is actually a function template specialization, retrieve information about this func...

bool isVariadic() const

Whether this function is variadic.

bool isDeleted() const

Whether this function has been deleted.

bool isConstexpr() const

Whether this is a (C++11) constexpr function or constexpr constructor.

bool isDeletedAsWritten() const

bool isDefaulted() const

Whether this function is defaulted.

unsigned getNumParams() const

Return the number of parameters this function must have based on its FunctionType.

FunctionDecl * getPreviousDecl()

Return the previous declaration of this declaration or NULL if this is the first declaration.

Declaration of a template function.

bool isExplicitSpecialization() const

static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)

Create implicit parameter.

This represents a decl that may have a name.

IdentifierInfo * getIdentifier() const

Get the identifier that names this declaration, if there is one.

bool isExternallyVisible() const

Represents a partial function definition.

static OutlinedFunctionDecl * Create(ASTContext &C, DeclContext *DC, unsigned NumParams)

void setNothrow(bool Nothrow=true)

void setParam(unsigned i, ImplicitParamDecl *P)

Represents a parameter to a function.

ParsedAttr - Represents a syntactic attribute.

const ParsedType & getTypeArg() const

A (possibly-)qualified type.

bool isNull() const

Return true if this QualType doesn't point to a type yet.

bool isMoreQualifiedThan(QualType Other, const ASTContext &Ctx) const

Determine whether this type is more qualified than the other given type, requiring exact equality for...

SYCLKernelCallStmt represents the transformation that is applied to the body of a function declared w...

const FunctionDecl * getKernelEntryPointDecl() const

static SYCLUniqueStableNameExpr * Create(const ASTContext &Ctx, SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, TypeSourceInfo *TSI)

A generic diagnostic builder for errors which may or may not be deferred.

ASTContext & getASTContext() const

const LangOptions & getLangOpts() const

SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)

Emit a diagnostic.

SemaDiagnosticBuilder DiagIfDeviceCode(SourceLocation Loc, unsigned DiagID)

Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as device c...

Definition SemaSYCL.cpp:30

void CheckSYCLExternalFunctionDecl(FunctionDecl *FD)

Definition SemaSYCL.cpp:253

ExprResult BuildUniqueStableNameExpr(SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, TypeSourceInfo *TSI)

Definition SemaSYCL.cpp:143

void handleKernelEntryPointAttr(Decl *D, const ParsedAttr &AL)

Definition SemaSYCL.cpp:205

void deepTypeCheckForDevice(SourceLocation UsedAt, llvm::DenseSet< QualType > Visited, ValueDecl *DeclToCheck)

Definition SemaSYCL.cpp:51

void handleKernelAttr(Decl *D, const ParsedAttr &AL)

Definition SemaSYCL.cpp:166

SemaSYCL(Sema &S)

Definition SemaSYCL.cpp:28

StmtResult BuildSYCLKernelCallStmt(FunctionDecl *FD, CompoundStmt *Body)

Definition SemaSYCL.cpp:437

void CheckSYCLEntryPointFunctionDecl(FunctionDecl *FD)

Definition SemaSYCL.cpp:270

ExprResult ActOnUniqueStableNameExpr(SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, ParsedType ParsedTy)

Definition SemaSYCL.cpp:151

Sema - This implements semantic analysis and AST building for C.

Encodes a location in the source.

bool isValid() const

Return true if this is a valid SourceLocation object.

Stmt - This represents one statement.

TemplateParameterList * getTemplateParameters() const

Get the list of template parameters.

Stores a list of template parameters for a TemplateDecl and its derived classes.

NamedDecl * getParam(unsigned Idx)

A semantic tree transformation that allows one to transform one abstract syntax tree into another.

A container of type source information.

The base class of the type hierarchy.

RecordDecl * getAsRecordDecl() const

Retrieves the RecordDecl this type refers to.

bool isReferenceType() const

const Type * getArrayElementTypeNoTypeQual() const

If this is an array type, return the element type of the array, potentially with type qualifiers miss...

QualType getPointeeType() const

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

bool isDependentType() const

Whether this type is a dependent type, meaning that its definition somehow depends on a template para...

bool isUndeducedType() const

Determine whether this type is an undeduced type, meaning that it somehow involves a C++11 'auto' typ...

bool isStructureOrClassType() const

bool isAnyPointerType() const

const Type * getUnqualifiedDesugaredType() const

Return the specified type with any "sugar" removed from the type, removing any typedefs,...

Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...

The JSON file list parser is used to communicate input to InstallAPI.

bool isa(CodeGen::Address addr)

QualType getFunctionOrMethodResultType(const Decl *D)

const FunctionProtoType * T

void handleSimpleAttribute(SemaBase &S, Decl *D, const AttributeCommonInfo &CI)

Applies the given attribute to the Decl without performing any additional semantic checking.

unsigned getFunctionOrMethodNumParams(const Decl *D)

getFunctionOrMethodNumParams - Return number of function or method parameters.

bool declaresSameEntity(const Decl *D1, const Decl *D2)

Determine whether two declarations declare the same entity.

U cast(CodeGen::Address addr)

OpaquePtr< QualType > ParsedType

An opaque type for threading parsed type information through the parser.

ActionResult< Expr * > ExprResult

@ Other

Other implicit parameter.

ActionResult< Stmt * > StmtResult