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

1

2

3

4

5

6

7

8

9

10

19

20using namespace clang;

21

22

23

24

25

27

29 unsigned DiagID) {

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

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

34 if (!FD)

35 return SemaDiagnosticBuilder::K_Nop;

37 return SemaDiagnosticBuilder::K_ImmediateWithCallStack;

38 return SemaDiagnosticBuilder::K_Deferred;

39 }();

41}

42

45 return CAT->isZeroSize();

46 return false;

47}

48

50 llvm::DenseSet Visited,

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

54

55

56 bool NeedToEmitNotes = true;

57

59 bool ErrorFound = false;

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

62 ErrorFound = true;

63 }

64

65 if (ErrorFound) {

66 if (NeedToEmitNotes) {

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

69 diag::note_illegal_field_declared_here)

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

71 else

73 }

74 }

75

76 return ErrorFound;

77 };

78

79

81 StackForRecursion.push_back(DeclToCheck);

82

83

85 History.push_back(nullptr);

86

87 do {

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

89 if (!Next) {

90 assert(!History.empty());

91

92 History.pop_back();

93 continue;

94 }

95 QualType NextTy = Next->getType();

96

97 if (Visited.insert(NextTy).second)

98 continue;

99

100 auto EmitHistory = [&]() {

101

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

104 diag::note_within_field_of_type)

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

106 }

107 };

108

109 if (Check(NextTy, Next)) {

110 if (NeedToEmitNotes)

111 EmitHistory();

112 NeedToEmitNotes = false;

113 }

114

115

116

121 else

123 if (Check(NextTy, Next)) {

124 if (NeedToEmitNotes)

125 EmitHistory();

126 NeedToEmitNotes = false;

127 }

128 }

129

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

132 History.push_back(NextFD);

133

134

135 StackForRecursion.push_back(nullptr);

136 llvm::copy(RecDecl->fields(), std::back_inserter(StackForRecursion));

137 }

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

139}

140

146 RParen, TSI);

147}

148

155

158 if (!TSI)

160

162}

163

165

166 const auto *FD = cast(D);

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

169

170

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

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

174 return;

175 }

176

177

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

180 if (isa(TParam)) {

182 diag::warn_sycl_kernel_invalid_template_param_type);

183 return;

184 }

185 }

186

187

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

190 return;

191 }

192

193

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

197 return;

198 }

199

200 handleSimpleAttribute(*this, D, AL);

201}

202

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

210}

211

212

213

214

215

216

217

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

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

223 else if (const ObjCInterfaceType *ObjCIT = dyn_cast(T))

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

225 return Loc;

226}

227

231

233

234

235

236

237

238

239

240

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

243 if (DeclTypeLoc.isValid())

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

245 return true;

246 }

247

248 return false;

249}

250

252

253

254 SYCLKernelEntryPointAttr *SKEPAttr = nullptr;

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

256 if (!SKEPAttr) {

257 SKEPAttr = SAI;

258 continue;

259 }

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

261 SKEPAttr->getKernelName())) {

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

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

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

265 SAI->setInvalidAttr();

266 } else {

267 Diag(SAI->getLocation(),

268 diag::warn_sycl_entry_point_redundant_declaration);

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

270 }

271 }

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

273

274

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

277 SKEPAttr->getKernelName()))

278 SKEPAttr->setInvalidAttr();

279

280

281

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

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

287 PrevSKEPAttr->getKernelName())) {

288 Diag(SKEPAttr->getLocation(),

289 diag::err_sycl_entry_point_invalid_redeclaration)

290 << SKEPAttr->getKernelName() << PrevSKEPAttr->getKernelName();

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

292 SKEPAttr->setInvalidAttr();

293 }

294 }

295 }

296

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

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

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

300 << 0;

301 SKEPAttr->setInvalidAttr();

302 }

303 }

304

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

307 << 1;

308 SKEPAttr->setInvalidAttr();

309 }

310

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

313 << 3;

314 SKEPAttr->setInvalidAttr();

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

317 << 2;

318 SKEPAttr->setInvalidAttr();

319 }

320

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

323 << 5;

324 SKEPAttr->setInvalidAttr();

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

327 << 4;

328 SKEPAttr->setInvalidAttr();

329 }

330

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

333 << 6;

334 SKEPAttr->setInvalidAttr();

335 }

336

338 Diag(SKEPAttr->getLocation(),

339 diag::err_sycl_entry_point_deduced_return_type);

340 SKEPAttr->setInvalidAttr();

343 Diag(SKEPAttr->getLocation(), diag::err_sycl_entry_point_return_type);

344 SKEPAttr->setInvalidAttr();

345 }

346

348 !SKEPAttr->isInvalidAttr()) {

351 if (SKI) {

353

354

355 Diag(FD->getLocation(), diag::err_sycl_kernel_name_conflict);

357 diag::note_previous_declaration);

358 SKEPAttr->setInvalidAttr();

359 }

360 } else {

362 }

363 }

364}

Defines the Diagnostic-related interfaces.

llvm::DenseSet< const void * > Visited

This file declares types used to describe SYCL kernels.

static SourceLocation SourceLocationForUserDeclaredType(QualType QT)

static bool isZeroSizedArray(SemaSYCL &S, QualType Ty)

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

This file declares semantic analysis for SYCL constructs.

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

const ConstantArrayType * getAsConstantArrayType(QualType T) const

bool hasSameType(QualType T1, QualType T2) const

Determine whether the given types T1 and T2 are equivalent.

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 * findSYCLKernelInfo(QualType T) const

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

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

Represents a function declaration or definition.

bool isNoReturn() const

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

QualType getReturnType() const

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 isDefaulted() const

Whether this function is defaulted.

Declaration of a template function.

This represents a decl that may have a name.

Interfaces are the core concept in Objective-C for object oriented design.

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.

decl_type * getPreviousDecl()

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

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.

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

Emit a diagnostic.

ASTContext & getASTContext() const

const LangOptions & getLangOpts() const

SemaDiagnosticBuilder DiagIfDeviceCode(SourceLocation Loc, unsigned DiagID)

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

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

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

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

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

void CheckSYCLEntryPointFunctionDecl(FunctionDecl *FD)

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

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

ASTContext & getASTContext() const

DeclContext * getCurLexicalContext() const

FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, bool Final=false)

static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo=nullptr)

Encodes a location in the source.

bool isValid() const

Return true if this is a valid SourceLocation object.

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 container of type source information.

The base class of the type hierarchy.

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

RecordDecl * getAsRecordDecl() const

Retrieves the RecordDecl this type refers to.

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.

QualType getFunctionOrMethodResultType(const Decl *D)

const FunctionProtoType * T

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.