1 //===--- Attr.h - Classes for representing attributes ----------*- C++ -*-===//
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 //
9 // This file defines the Attr interface and subclasses.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_CLANG_AST_ATTR_H
14 #define LLVM_CLANG_AST_ATTR_H
15
16 #include "clang/AST/ASTFwd.h"
17 #include "clang/AST/AttrIterator.h"
18 #include "clang/AST/Decl.h"
19 #include "clang/AST/Type.h"
20 #include "clang/Basic/AttrKinds.h"
21 #include "clang/Basic/AttributeCommonInfo.h"
22 #include "clang/Basic/LLVM.h"
23 #include "clang/Basic/LangOptions.h"
24 #include "clang/Basic/OpenMPKinds.h"
25 #include "clang/Basic/Sanitizers.h"
26 #include "clang/Basic/SourceLocation.h"
27 #include "clang/Support/Compiler.h"
28 #include "llvm/Frontend/HLSL/HLSLResource.h"
29 #include "llvm/Support/CodeGen.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/VersionTuple.h"
32 #include "llvm/Support/raw_ostream.h"
33 #include <algorithm>
34 #include <cassert>
35
36 namespace clang {
37 class ASTContext;
38 class AttributeCommonInfo;
39 class FunctionDecl;
40 class OMPTraitInfo;
41 class OpenACCClause;
42
43 /// Attr - This represents one attribute.
44 class Attr : public AttributeCommonInfo {
45 private:
46 LLVM_PREFERRED_TYPE(attr::Kind)
47 unsigned AttrKind : 16;
48
49 protected:
50 /// An index into the spelling list of an
51 /// attribute defined in Attr.td file.
52 LLVM_PREFERRED_TYPE(bool)
53 unsigned Inherited : 1;
54 LLVM_PREFERRED_TYPE(bool)
55 unsigned IsPackExpansion : 1;
56 LLVM_PREFERRED_TYPE(bool)
57 unsigned Implicit : 1;
58 // FIXME: These are properties of the attribute kind, not state for this
59 // instance of the attribute.
60 LLVM_PREFERRED_TYPE(bool)
61 unsigned IsLateParsed : 1;
62 LLVM_PREFERRED_TYPE(bool)
63 unsigned InheritEvenIfAlreadyPresent : 1;
64
new(size_t bytes)65 void *operator new(size_t bytes) noexcept {
66 llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
67 }
delete(void * data)68 void operator delete(void *data) noexcept {
69 llvm_unreachable("Attrs cannot be released with regular 'delete'.");
70 }
71
72 public:
73 // Forward so that the regular new and delete do not hide global ones.
74 void *operator new(size_t Bytes, ASTContext &C,
75 size_t Alignment = 8) noexcept {
76 return ::operator new(Bytes, C, Alignment);
77 }
delete(void * Ptr,ASTContext & C,size_t Alignment)78 void operator delete(void *Ptr, ASTContext &C, size_t Alignment) noexcept {
79 return ::operator delete(Ptr, C, Alignment);
80 }
81
82 protected:
Attr(ASTContext & Context,const AttributeCommonInfo & CommonInfo,attr::Kind AK,bool IsLateParsed)83 Attr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
84 attr::Kind AK, bool IsLateParsed)
85 : AttributeCommonInfo(CommonInfo), AttrKind(AK), Inherited(false),
86 IsPackExpansion(false), Implicit(false), IsLateParsed(IsLateParsed),
87 InheritEvenIfAlreadyPresent(false) {}
88
89 public:
getKind()90 attr::Kind getKind() const { return static_cast<attr::Kind>(AttrKind); }
91
getSpellingListIndex()92 unsigned getSpellingListIndex() const {
93 return getAttributeSpellingListIndex();
94 }
95 const char *getSpelling() const;
96
getLocation()97 SourceLocation getLocation() const { return getRange().getBegin(); }
98
isInherited()99 bool isInherited() const { return Inherited; }
100
101 /// Returns true if the attribute has been implicitly created instead
102 /// of explicitly written by the user.
isImplicit()103 bool isImplicit() const { return Implicit; }
setImplicit(bool I)104 void setImplicit(bool I) { Implicit = I; }
105
setPackExpansion(bool PE)106 void setPackExpansion(bool PE) { IsPackExpansion = PE; }
isPackExpansion()107 bool isPackExpansion() const { return IsPackExpansion; }
108
109 // Clone this attribute.
110 Attr *clone(ASTContext &C) const;
111
isLateParsed()112 bool isLateParsed() const { return IsLateParsed; }
113
114 // Pretty print this attribute.
115 void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;
116
117 static StringRef getDocumentation(attr::Kind);
118 };
119
120 class TypeAttr : public Attr {
121 protected:
TypeAttr(ASTContext & Context,const AttributeCommonInfo & CommonInfo,attr::Kind AK,bool IsLateParsed)122 TypeAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
123 attr::Kind AK, bool IsLateParsed)
124 : Attr(Context, CommonInfo, AK, IsLateParsed) {}
125
126 public:
classof(const Attr * A)127 static bool classof(const Attr *A) {
128 return A->getKind() >= attr::FirstTypeAttr &&
129 A->getKind() <= attr::LastTypeAttr;
130 }
131 };
132
133 class StmtAttr : public Attr {
134 protected:
StmtAttr(ASTContext & Context,const AttributeCommonInfo & CommonInfo,attr::Kind AK,bool IsLateParsed)135 StmtAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
136 attr::Kind AK, bool IsLateParsed)
137 : Attr(Context, CommonInfo, AK, IsLateParsed) {}
138
139 public:
classof(const Attr * A)140 static bool classof(const Attr *A) {
141 return A->getKind() >= attr::FirstStmtAttr &&
142 A->getKind() <= attr::LastStmtAttr;
143 }
144 };
145
146 class InheritableAttr : public Attr {
147 protected:
InheritableAttr(ASTContext & Context,const AttributeCommonInfo & CommonInfo,attr::Kind AK,bool IsLateParsed,bool InheritEvenIfAlreadyPresent)148 InheritableAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
149 attr::Kind AK, bool IsLateParsed,
150 bool InheritEvenIfAlreadyPresent)
151 : Attr(Context, CommonInfo, AK, IsLateParsed) {
152 this->InheritEvenIfAlreadyPresent = InheritEvenIfAlreadyPresent;
153 }
154
155 public:
setInherited(bool I)156 void setInherited(bool I) { Inherited = I; }
157
158 /// Should this attribute be inherited from a prior declaration even if it's
159 /// explicitly provided in the current declaration?
shouldInheritEvenIfAlreadyPresent()160 bool shouldInheritEvenIfAlreadyPresent() const {
161 return InheritEvenIfAlreadyPresent;
162 }
163
164 // Implement isa/cast/dyncast/etc.
classof(const Attr * A)165 static bool classof(const Attr *A) {
166 return A->getKind() >= attr::FirstInheritableAttr &&
167 A->getKind() <= attr::LastInheritableAttr;
168 }
169 };
170
171 class DeclOrStmtAttr : public InheritableAttr {
172 protected:
DeclOrStmtAttr(ASTContext & Context,const AttributeCommonInfo & CommonInfo,attr::Kind AK,bool IsLateParsed,bool InheritEvenIfAlreadyPresent)173 DeclOrStmtAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
174 attr::Kind AK, bool IsLateParsed,
175 bool InheritEvenIfAlreadyPresent)
176 : InheritableAttr(Context, CommonInfo, AK, IsLateParsed,
177 InheritEvenIfAlreadyPresent) {}
178
179 public:
classof(const Attr * A)180 static bool classof(const Attr *A) {
181 return A->getKind() >= attr::FirstDeclOrStmtAttr &&
182 A->getKind() <= attr::LastDeclOrStmtAttr;
183 }
184 };
185
186 class InheritableParamAttr : public InheritableAttr {
187 protected:
InheritableParamAttr(ASTContext & Context,const AttributeCommonInfo & CommonInfo,attr::Kind AK,bool IsLateParsed,bool InheritEvenIfAlreadyPresent)188 InheritableParamAttr(ASTContext &Context,
189 const AttributeCommonInfo &CommonInfo, attr::Kind AK,
190 bool IsLateParsed, bool InheritEvenIfAlreadyPresent)
191 : InheritableAttr(Context, CommonInfo, AK, IsLateParsed,
192 InheritEvenIfAlreadyPresent) {}
193
194 public:
195 // Implement isa/cast/dyncast/etc.
classof(const Attr * A)196 static bool classof(const Attr *A) {
197 return A->getKind() >= attr::FirstInheritableParamAttr &&
198 A->getKind() <= attr::LastInheritableParamAttr;
199 }
200 };
201
202 class InheritableParamOrStmtAttr : public InheritableParamAttr {
203 protected:
InheritableParamOrStmtAttr(ASTContext & Context,const AttributeCommonInfo & CommonInfo,attr::Kind AK,bool IsLateParsed,bool InheritEvenIfAlreadyPresent)204 InheritableParamOrStmtAttr(ASTContext &Context,
205 const AttributeCommonInfo &CommonInfo,
206 attr::Kind AK, bool IsLateParsed,
207 bool InheritEvenIfAlreadyPresent)
208 : InheritableParamAttr(Context, CommonInfo, AK, IsLateParsed,
209 InheritEvenIfAlreadyPresent) {}
210
211 public:
212 // Implement isa/cast/dyncast/etc.
classof(const Attr * A)213 static bool classof(const Attr *A) {
214 return A->getKind() >= attr::FirstInheritableParamOrStmtAttr &&
215 A->getKind() <= attr::LastInheritableParamOrStmtAttr;
216 }
217 };
218
219 class HLSLAnnotationAttr : public InheritableAttr {
220 protected:
HLSLAnnotationAttr(ASTContext & Context,const AttributeCommonInfo & CommonInfo,attr::Kind AK,bool IsLateParsed,bool InheritEvenIfAlreadyPresent)221 HLSLAnnotationAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
222 attr::Kind AK, bool IsLateParsed,
223 bool InheritEvenIfAlreadyPresent)
224 : InheritableAttr(Context, CommonInfo, AK, IsLateParsed,
225 InheritEvenIfAlreadyPresent) {}
226
227 public:
228 // Implement isa/cast/dyncast/etc.
classof(const Attr * A)229 static bool classof(const Attr *A) {
230 return A->getKind() >= attr::FirstHLSLAnnotationAttr &&
231 A->getKind() <= attr::LastHLSLAnnotationAttr;
232 }
233 };
234
235 /// A parameter attribute which changes the argument-passing ABI rule
236 /// for the parameter.
237 class ParameterABIAttr : public InheritableParamAttr {
238 protected:
ParameterABIAttr(ASTContext & Context,const AttributeCommonInfo & CommonInfo,attr::Kind AK,bool IsLateParsed,bool InheritEvenIfAlreadyPresent)239 ParameterABIAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
240 attr::Kind AK, bool IsLateParsed,
241 bool InheritEvenIfAlreadyPresent)
242 : InheritableParamAttr(Context, CommonInfo, AK, IsLateParsed,
243 InheritEvenIfAlreadyPresent) {}
244
245 public:
246 ParameterABI getABI() const;
247
classof(const Attr * A)248 static bool classof(const Attr *A) {
249 return A->getKind() >= attr::FirstParameterABIAttr &&
250 A->getKind() <= attr::LastParameterABIAttr;
251 }
252 };
253
254 /// A single parameter index whose accessors require each use to make explicit
255 /// the parameter index encoding needed.
256 class ParamIdx {
257 // Idx is exposed only via accessors that specify specific encodings.
258 unsigned Idx : 30;
259 LLVM_PREFERRED_TYPE(bool)
260 unsigned HasThis : 1;
261 LLVM_PREFERRED_TYPE(bool)
262 unsigned IsValid : 1;
263
assertComparable(const ParamIdx & I)264 void assertComparable(const ParamIdx &I) const {
265 assert(isValid() && I.isValid() &&
266 "ParamIdx must be valid to be compared");
267 // It's possible to compare indices from separate functions, but so far
268 // it's not proven useful. Moreover, it might be confusing because a
269 // comparison on the results of getASTIndex might be inconsistent with a
270 // comparison on the ParamIdx objects themselves.
271 assert(HasThis == I.HasThis &&
272 "ParamIdx must be for the same function to be compared");
273 }
274
275 public:
276 /// Construct an invalid parameter index (\c isValid returns false and
277 /// accessors fail an assert).
ParamIdx()278 ParamIdx() : Idx(0), HasThis(false), IsValid(false) {}
279
280 /// \param Idx is the parameter index as it is normally specified in
281 /// attributes in the source: one-origin including any C++ implicit this
282 /// parameter.
283 ///
284 /// \param D is the declaration containing the parameters. It is used to
285 /// determine if there is a C++ implicit this parameter.
ParamIdx(unsigned Idx,const Decl * D)286 ParamIdx(unsigned Idx, const Decl *D)
287 : Idx(Idx), HasThis(false), IsValid(true) {
288 assert(Idx >= 1 && "Idx must be one-origin");
289 if (const auto *FD = dyn_cast<FunctionDecl>(D))
290 HasThis = FD->isCXXInstanceMember();
291 }
292
293 /// A type into which \c ParamIdx can be serialized.
294 ///
295 /// A static assertion that it's of the correct size follows the \c ParamIdx
296 /// class definition.
297 typedef uint32_t SerialType;
298
299 /// Produce a representation that can later be passed to \c deserialize to
300 /// construct an equivalent \c ParamIdx.
serialize()301 SerialType serialize() const {
302 return *reinterpret_cast<const SerialType *>(this);
303 }
304
305 /// Construct from a result from \c serialize.
deserialize(SerialType S)306 static ParamIdx deserialize(SerialType S) {
307 // Using this two-step static_cast via void * instead of reinterpret_cast
308 // silences a -Wstrict-aliasing false positive from GCC7 and earlier.
309 void *ParamIdxPtr = static_cast<void *>(&S);
310 ParamIdx P(*static_cast<ParamIdx *>(ParamIdxPtr));
311 assert((!P.IsValid || P.Idx >= 1) && "valid Idx must be one-origin");
312 return P;
313 }
314
315 /// Is this parameter index valid?
isValid()316 bool isValid() const { return IsValid; }
317
318 /// Get the parameter index as it would normally be encoded for attributes at
319 /// the source level of representation: one-origin including any C++ implicit
320 /// this parameter.
321 ///
322 /// This encoding thus makes sense for diagnostics, pretty printing, and
323 /// constructing new attributes from a source-like specification.
getSourceIndex()324 unsigned getSourceIndex() const {
325 assert(isValid() && "ParamIdx must be valid");
326 return Idx;
327 }
328
329 /// Get the parameter index as it would normally be encoded at the AST level
330 /// of representation: zero-origin not including any C++ implicit this
331 /// parameter.
332 ///
333 /// This is the encoding primarily used in Sema. However, in diagnostics,
334 /// Sema uses \c getSourceIndex instead.
getASTIndex()335 unsigned getASTIndex() const {
336 assert(isValid() && "ParamIdx must be valid");
337 assert(Idx >= 1 + HasThis &&
338 "stored index must be base-1 and not specify C++ implicit this");
339 return Idx - 1 - HasThis;
340 }
341
342 /// Get the parameter index as it would normally be encoded at the LLVM level
343 /// of representation: zero-origin including any C++ implicit this parameter.
344 ///
345 /// This is the encoding primarily used in CodeGen.
getLLVMIndex()346 unsigned getLLVMIndex() const {
347 assert(isValid() && "ParamIdx must be valid");
348 assert(Idx >= 1 && "stored index must be base-1");
349 return Idx - 1;
350 }
351
352 bool operator==(const ParamIdx &I) const {
353 assertComparable(I);
354 return Idx == I.Idx;
355 }
356 bool operator!=(const ParamIdx &I) const {
357 assertComparable(I);
358 return Idx != I.Idx;
359 }
360 bool operator<(const ParamIdx &I) const {
361 assertComparable(I);
362 return Idx < I.Idx;
363 }
364 bool operator>(const ParamIdx &I) const {
365 assertComparable(I);
366 return Idx > I.Idx;
367 }
368 bool operator<=(const ParamIdx &I) const {
369 assertComparable(I);
370 return Idx <= I.Idx;
371 }
372 bool operator>=(const ParamIdx &I) const {
373 assertComparable(I);
374 return Idx >= I.Idx;
375 }
376 };
377
378 static_assert(sizeof(ParamIdx) == sizeof(ParamIdx::SerialType),
379 "ParamIdx does not fit its serialization type");
380
381 #include "clang/AST/Attrs.inc" // IWYU pragma: export
382
383 inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
384 const Attr *At) {
385 DB.AddTaggedVal(reinterpret_cast<uint64_t>(At), DiagnosticsEngine::ak_attr);
386 return DB;
387 }
388
getABI()389 inline ParameterABI ParameterABIAttr::getABI() const {
390 switch (getKind()) {
391 case attr::SwiftContext:
392 return ParameterABI::SwiftContext;
393 case attr::SwiftAsyncContext:
394 return ParameterABI::SwiftAsyncContext;
395 case attr::SwiftErrorResult:
396 return ParameterABI::SwiftErrorResult;
397 case attr::SwiftIndirectResult:
398 return ParameterABI::SwiftIndirectResult;
399 case attr::HLSLParamModifier: {
400 const auto *A = cast<HLSLParamModifierAttr>(this);
401 if (A->isOut())
402 return ParameterABI::HLSLOut;
403 if (A->isInOut())
404 return ParameterABI::HLSLInOut;
405 return ParameterABI::Ordinary;
406 }
407 default:
408 llvm_unreachable("bad parameter ABI attribute kind");
409 }
410 }
411 } // end namespace clang
412
413 #endif
414