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