clang 19.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"
13#include "clang/Sema/Sema.h"
15
16using namespace clang;
17
18// -----------------------------------------------------------------------------
19// SYCL device specific diagnostics implementation
20// -----------------------------------------------------------------------------
21
23
25 unsigned DiagID) {
26 assert(getLangOpts().SYCLIsDevice &&
27 "Should only be called during SYCL compilation");
28 FunctionDecl *FD = dyn_cast<FunctionDecl>(SemaRef.getCurLexicalContext());
29 SemaDiagnosticBuilder::Kind DiagKind = [this, FD] {
30 if (!FD)
31 return SemaDiagnosticBuilder::K_Nop;
33 return SemaDiagnosticBuilder::K_ImmediateWithCallStack;
34 return SemaDiagnosticBuilder::K_Deferred;
35 }();
36 return SemaDiagnosticBuilder(DiagKind, Loc, DiagID, FD, SemaRef);
37}
38
39static bool isZeroSizedArray(SemaSYCL &S, QualType Ty) {
40 if (const auto *CAT = S.getASTContext().getAsConstantArrayType(Ty))
41 return CAT->isZeroSize();
42 return false;
43}
44
47 ValueDecl *DeclToCheck) {
48 assert(getLangOpts().SYCLIsDevice &&
49 "Should only be called during SYCL compilation");
50 // Emit notes only for the first discovered declaration of unsupported type
51 // to avoid mess of notes. This flag is to track that error already happened.
52 bool NeedToEmitNotes = true;
53
54 auto Check = [&](QualType TypeToCheck, const ValueDecl *D) {
55 bool ErrorFound = false;
56 if (isZeroSizedArray(*this, TypeToCheck)) {
57 DiagIfDeviceCode(UsedAt, diag::err_typecheck_zero_array_size) << 1;
58 ErrorFound = true;
59 }
60 // Checks for other types can also be done here.
61 if (ErrorFound) {
62 if (NeedToEmitNotes) {
63 if (auto *FD = dyn_cast<FieldDecl>(D))
64 DiagIfDeviceCode(FD->getLocation(),
65 diag::note_illegal_field_declared_here)
66 << FD->getType()->isPointerType() << FD->getType();
67 else
68 DiagIfDeviceCode(D->getLocation(), diag::note_declared_at);
69 }
70 }
71
72 return ErrorFound;
73 };
74
75 // In case we have a Record used do the DFS for a bad field.
76 SmallVector<const ValueDecl *, 4> StackForRecursion;
77 StackForRecursion.push_back(DeclToCheck);
78
79 // While doing DFS save how we get there to emit a nice set of notes.
81 History.push_back(nullptr);
82
83 do {
84 const ValueDecl *Next = StackForRecursion.pop_back_val();
85 if (!Next) {
86 assert(!History.empty());
87 // Found a marker, we have gone up a level.
88 History.pop_back();
89 continue;
90 }
91 QualType NextTy = Next->getType();
92
93 if (!Visited.insert(NextTy).second)
94 continue;
95
96 auto EmitHistory = [&]() {
97 // The first element is always nullptr.
98 for (uint64_t Index = 1; Index < History.size(); ++Index) {
99 DiagIfDeviceCode(History[Index]->getLocation(),
100 diag::note_within_field_of_type)
101 << History[Index]->getType();
102 }
103 };
104
105 if (Check(NextTy, Next)) {
106 if (NeedToEmitNotes)
107 EmitHistory();
108 NeedToEmitNotes = false;
109 }
110
111 // In case pointer/array/reference type is met get pointee type, then
112 // proceed with that type.
113 while (NextTy->isAnyPointerType() || NextTy->isArrayType() ||
114 NextTy->isReferenceType()) {
115 if (NextTy->isArrayType())
116 NextTy = QualType{NextTy->getArrayElementTypeNoTypeQual(), 0};
117 else
118 NextTy = NextTy->getPointeeType();
119 if (Check(NextTy, Next)) {
120 if (NeedToEmitNotes)
121 EmitHistory();
122 NeedToEmitNotes = false;
123 }
124 }
125
126 if (const auto *RecDecl = NextTy->getAsRecordDecl()) {
127 if (auto *NextFD = dyn_cast<FieldDecl>(Next))
128 History.push_back(NextFD);
129 // When nullptr is discovered, this means we've gone back up a level, so
130 // the history should be cleaned.
131 StackForRecursion.push_back(nullptr);
132 llvm::copy(RecDecl->fields(), std::back_inserter(StackForRecursion));
133 }
134 } while (!StackForRecursion.empty());
135}
136
138 SourceLocation LParen,
139 SourceLocation RParen,
140 TypeSourceInfo *TSI) {
141 return SYCLUniqueStableNameExpr::Create(getASTContext(), OpLoc, LParen,
142 RParen, TSI);
143}
144
146 SourceLocation LParen,
147 SourceLocation RParen,
148 ParsedType ParsedTy) {
149 TypeSourceInfo *TSI = nullptr;
150 QualType Ty = SemaRef.GetTypeFromParser(ParsedTy, &TSI);
151
152 if (Ty.isNull())
153 return ExprError();
154 if (!TSI)
155 TSI = getASTContext().getTrivialTypeSourceInfo(Ty, LParen);
156
157 return BuildUniqueStableNameExpr(OpLoc, LParen, RParen, TSI);
158}
llvm::DenseSet< const void * > Visited
Definition: HTMLLogger.cpp:146
static bool isZeroSizedArray(SemaSYCL &S, QualType Ty)
Definition: SemaSYCL.cpp:39
This file declares semantic analysis for SYCL constructs.
const ConstantArrayType * getAsConstantArrayType(QualType T) const
Definition: ASTContext.h:2756
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
Represents a function declaration or definition.
Definition: Decl.h:1971
A (possibly-)qualified type.
Definition: Type.h:738
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:805
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
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:24
ExprResult BuildUniqueStableNameExpr(SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, TypeSourceInfo *TSI)
Definition: SemaSYCL.cpp:137
void deepTypeCheckForDevice(SourceLocation UsedAt, llvm::DenseSet< QualType > Visited, ValueDecl *DeclToCheck)
Definition: SemaSYCL.cpp:45
SemaSYCL(Sema &S)
Definition: SemaSYCL.cpp:22
ExprResult ActOnUniqueStableNameExpr(SourceLocation OpLoc, SourceLocation LParen, SourceLocation RParen, ParsedType ParsedTy)
Definition: SemaSYCL.cpp:145
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:457
ASTContext & getASTContext() const
Definition: Sema.h:527
DeclContext * getCurLexicalContext() const
Definition: Sema.h:702
FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, bool Final=false)
Definition: SemaDecl.cpp:20625
static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo=nullptr)
Definition: SemaType.cpp:3222
Encodes a location in the source.
A container of type source information.
Definition: Type.h:7120
bool isArrayType() const
Definition: Type.h:7468
bool isReferenceType() const
Definition: Type.h:7414
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:426
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:694
bool isAnyPointerType() const
Definition: Type.h:7406
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition: Type.cpp:1874
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:706
The JSON file list parser is used to communicate input to InstallAPI.
ExprResult ExprError()
Definition: Ownership.h:264