clang 20.0.0git
SemaSYCL.cpp
Go to the documentation of this file.
1//===- SemaSYCL.cpp - Semantic Analysis for SYCL 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// This implements Semantic Analysis for SYCL constructs.
9//===----------------------------------------------------------------------===//
10
11#include "clang/Sema/SemaSYCL.h"
12#include "clang/AST/Mangle.h"
14#include "clang/Sema/Attr.h"
16#include "clang/Sema/Sema.h"
18
19using namespace clang;
20
21// -----------------------------------------------------------------------------
22// SYCL device specific diagnostics implementation
23// -----------------------------------------------------------------------------
24
26
28 unsigned DiagID) {
29 assert(getLangOpts().SYCLIsDevice &&
30 "Should only be called during SYCL compilation");
31 FunctionDecl *FD = dyn_cast<FunctionDecl>(SemaRef.getCurLexicalContext());
32 SemaDiagnosticBuilder::Kind DiagKind = [this, FD] {
33 if (!FD)
34 return SemaDiagnosticBuilder::K_Nop;
36 return SemaDiagnosticBuilder::K_ImmediateWithCallStack;
37 return SemaDiagnosticBuilder::K_Deferred;
38 }();
39 return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, FD, SemaRef);
40}
41
42static bool isZeroSizedArray(SemaSYCL &S, QualType Ty) {
43 if (const auto *CAT = S.getASTContext().getAsConstantArrayType(Ty))
44 return CAT->isZeroSize();
45 return false;
46}
47
49 llvm::DenseSet<QualType> Visited,
50 ValueDecl *DeclToCheck) {
51 assert(getLangOpts().SYCLIsDevice &&
52 "Should only be called during SYCL compilation");
53 // Emit notes only for the first discovered declaration of unsupported type
54 // to avoid mess of notes. This flag is to track that error already happened.
55 bool NeedToEmitNotes = true;
56
57 auto Check = [&](QualType TypeToCheck, const ValueDecl *D) {
58 bool ErrorFound = false;
59 if (isZeroSizedArray(*this, TypeToCheck)) {
60 DiagIfDeviceCode(UsedAt, diag::err_typecheck_zero_array_size) << 1;
61 ErrorFound = true;
62 }
63 // Checks for other types can also be done here.
64 if (ErrorFound) {
65 if (NeedToEmitNotes) {
66 if (auto *FD = dyn_cast<FieldDecl>(D))
67 DiagIfDeviceCode(FD->getLocation(),
68 diag::note_illegal_field_declared_here)
69 << FD->getType()->isPointerType() << FD->getType();
70 else
71 DiagIfDeviceCode(D->getLocation(), diag::note_declared_at);
72 }
73 }
74
75 return ErrorFound;
76 };
77
78 // In case we have a Record used do the DFS for a bad field.
79 SmallVector<const ValueDecl *, 4> StackForRecursion;
80 StackForRecursion.push_back(DeclToCheck);
81
82 // While doing DFS save how we get there to emit a nice set of notes.
84 History.push_back(nullptr);
85
86 do {
87 const ValueDecl *Next = StackForRecursion.pop_back_val();
88 if (!Next) {
89 assert(!History.empty());
90 // Found a marker, we have gone up a level.
91 History.pop_back();
92 continue;
93 }
94 QualType NextTy = Next->getType();
95
96 if (!Visited.insert(NextTy).second)
97 continue;
98
99 auto EmitHistory = [&]() {
100 // The first element is always nullptr.
101 for (uint64_t Index = 1; Index < History.size(); ++Index) {
102 DiagIfDeviceCode(History[Index]->getLocation(),
103 diag::note_within_field_of_type)
104 << History[Index]->getType();
105 }
106 };
107
108 if (Check(NextTy, Next)) {
109 if (NeedToEmitNotes)
110 EmitHistory();
111 NeedToEmitNotes = false;
112 }
113
114 // In case pointer/array/reference type is met get pointee type, then
115 // proceed with that type.
116 while (NextTy->isAnyPointerType() || NextTy->isArrayType() ||
117 NextTy->isReferenceType()) {
118 if (NextTy->isArrayType())
119 NextTy = QualType{NextTy->getArrayElementTypeNoTypeQual(), 0};
120 else
121 NextTy = NextTy->getPointeeType();
122 if (Check(NextTy, Next)) {
123 if (NeedToEmitNotes)
124 EmitHistory();
125 NeedToEmitNotes = false;
126 }
127 }
128
129 if (const auto *RecDecl = NextTy->getAsRecordDecl()) {
130 if (auto *NextFD = dyn_cast<FieldDecl>(Next))
131 History.push_back(NextFD);
132 // When nullptr is discovered, this means we've gone back up a level, so
133 // the history should be cleaned.
134 StackForRecursion.push_back(nullptr);
135 llvm::copy(RecDecl->fields(), std::back_inserter(StackForRecursion));
136 }
137 } while (!StackForRecursion.empty());
138}
139
141 SourceLocation LParen,
142 SourceLocation RParen,
143 TypeSourceInfo *TSI) {
144 return SYCLUniqueStableNameExpr::Create(getASTContext(), OpLoc, LParen,
145 RParen, TSI);
146}
147
149 SourceLocation LParen,
150 SourceLocation RParen,
151 ParsedType ParsedTy) {
152 TypeSourceInfo *TSI = nullptr;
153 QualType Ty = SemaRef.GetTypeFromParser(ParsedTy, &TSI);
154
155 if (Ty.isNull())
156 return ExprError();
157 if (!TSI)
158 TSI = getASTContext().getTrivialTypeSourceInfo(Ty, LParen);
159
160 return BuildUniqueStableNameExpr(OpLoc, LParen, RParen, TSI);
161}
162
164 // The 'sycl_kernel' attribute applies only to function templates.
165 const auto *FD = cast<FunctionDecl>(D);
166 const FunctionTemplateDecl *FT = FD->getDescribedFunctionTemplate();
167 assert(FT && "Function template is expected");
168
169 // Function template must have at least two template parameters.
171 if (TL->size() < 2) {
172 Diag(FT->getLocation(), diag::warn_sycl_kernel_num_of_template_params);
173 return;
174 }
175
176 // Template parameters must be typenames.
177 for (unsigned I = 0; I < 2; ++I) {
178 const NamedDecl *TParam = TL->getParam(I);
179 if (isa<NonTypeTemplateParmDecl>(TParam)) {
180 Diag(FT->getLocation(),
181 diag::warn_sycl_kernel_invalid_template_param_type);
182 return;
183 }
184 }
185
186 // Function must have at least one argument.
188 Diag(FT->getLocation(), diag::warn_sycl_kernel_num_of_function_params);
189 return;
190 }
191
192 // Function must return void.
194 if (!RetTy->isVoidType()) {
195 Diag(FT->getLocation(), diag::warn_sycl_kernel_return_type);
196 return;
197 }
198
199 handleSimpleAttribute<SYCLKernelAttr>(*this, D, AL);
200}
const Decl * D
llvm::DenseSet< const void * > Visited
Definition: HTMLLogger.cpp:146
SourceLocation Loc
Definition: SemaObjC.cpp:759
static bool isZeroSizedArray(SemaSYCL &S, QualType Ty)
Definition: SemaSYCL.cpp:42
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
Definition: ASTContext.h:2825
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
SourceLocation getLocation() const
Definition: DeclBase.h:446
Represents a function declaration or definition.
Definition: Decl.h:1932
Declaration of a template function.
Definition: DeclTemplate.h:957
This represents a decl that may have a name.
Definition: Decl.h:249
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:129
A (possibly-)qualified type.
Definition: Type.h:941
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:1008
static SYCLUniqueStableNameExpr * Create(const ASTContext &Ctx, SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, TypeSourceInfo *TSI)
Definition: Expr.cpp:578
A generic diagnostic builder for errors which may or may not be deferred.
Definition: SemaBase.h:110
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:60
ASTContext & getASTContext() const
Definition: SemaBase.cpp:9
Sema & SemaRef
Definition: SemaBase.h:40
const LangOptions & getLangOpts() const
Definition: SemaBase.cpp:11
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:27
ExprResult BuildUniqueStableNameExpr(SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, TypeSourceInfo *TSI)
Definition: SemaSYCL.cpp:140
void deepTypeCheckForDevice(SourceLocation UsedAt, llvm::DenseSet< QualType > Visited, ValueDecl *DeclToCheck)
Definition: SemaSYCL.cpp:48
void handleKernelAttr(Decl *D, const ParsedAttr &AL)
Definition: SemaSYCL.cpp:163
SemaSYCL(Sema &S)
Definition: SemaSYCL.cpp:25
ExprResult ActOnUniqueStableNameExpr(SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, ParsedType ParsedTy)
Definition: SemaSYCL.cpp:148
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:493
ASTContext & getASTContext() const
Definition: Sema.h:560
DeclContext * getCurLexicalContext() const
Definition: Sema.h:767
FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, bool Final=false)
Definition: SemaDecl.cpp:20204
static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo=nullptr)
Definition: SemaType.cpp:2731
Encodes a location in the source.
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Definition: DeclTemplate.h:413
Stores a list of template parameters for a TemplateDecl and its derived classes.
Definition: DeclTemplate.h:73
NamedDecl * getParam(unsigned Idx)
Definition: DeclTemplate.h:144
A container of type source information.
Definition: Type.h:7721
bool isVoidType() const
Definition: Type.h:8319
bool isArrayType() const
Definition: Type.h:8075
bool isReferenceType() const
Definition: Type.h:8021
const Type * getArrayElementTypeNoTypeQual() const
If this is an array type, return the element type of the array, potentially with type qualifiers miss...
Definition: Type.cpp:427
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:705
bool isAnyPointerType() const
Definition: Type.h:8011
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition: Type.cpp:1886
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:667
The JSON file list parser is used to communicate input to InstallAPI.
QualType getFunctionOrMethodResultType(const Decl *D)
Definition: Attr.h:98
ExprResult ExprError()
Definition: Ownership.h:264
unsigned getFunctionOrMethodNumParams(const Decl *D)
getFunctionOrMethodNumParams - Return number of function or method parameters.
Definition: Attr.h:64