/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/Sema/ParsedAttr.h
Line | Count | Source (jump to first uncovered line) |
1 | | //======- ParsedAttr.h - Parsed attribute sets ------------------*- 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 ParsedAttr class, which is used to collect |
10 | | // parsed attributes. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #ifndef LLVM_CLANG_SEMA_PARSEDATTR_H |
15 | | #define LLVM_CLANG_SEMA_PARSEDATTR_H |
16 | | |
17 | | #include "clang/Basic/AttrSubjectMatchRules.h" |
18 | | #include "clang/Basic/AttributeCommonInfo.h" |
19 | | #include "clang/Basic/Diagnostic.h" |
20 | | #include "clang/Basic/SourceLocation.h" |
21 | | #include "clang/Sema/Ownership.h" |
22 | | #include "llvm/ADT/PointerUnion.h" |
23 | | #include "llvm/ADT/SmallVector.h" |
24 | | #include "llvm/ADT/TinyPtrVector.h" |
25 | | #include "llvm/Support/Allocator.h" |
26 | | #include "llvm/Support/Registry.h" |
27 | | #include "llvm/Support/VersionTuple.h" |
28 | | #include <cassert> |
29 | | #include <cstddef> |
30 | | #include <cstring> |
31 | | #include <utility> |
32 | | |
33 | | namespace clang { |
34 | | |
35 | | class ASTContext; |
36 | | class Decl; |
37 | | class Expr; |
38 | | class IdentifierInfo; |
39 | | class LangOptions; |
40 | | class ParsedAttr; |
41 | | class Sema; |
42 | | class Stmt; |
43 | | class TargetInfo; |
44 | | |
45 | | struct ParsedAttrInfo { |
46 | | /// Corresponds to the Kind enum. |
47 | | unsigned AttrKind : 16; |
48 | | /// The number of required arguments of this attribute. |
49 | | unsigned NumArgs : 4; |
50 | | /// The number of optional arguments of this attributes. |
51 | | unsigned OptArgs : 4; |
52 | | /// The number of non-fake arguments specified in the attribute definition. |
53 | | unsigned NumArgMembers : 4; |
54 | | /// True if the parsing does not match the semantic content. |
55 | | unsigned HasCustomParsing : 1; |
56 | | // True if this attribute accepts expression parameter pack expansions. |
57 | | unsigned AcceptsExprPack : 1; |
58 | | /// True if this attribute is only available for certain targets. |
59 | | unsigned IsTargetSpecific : 1; |
60 | | /// True if this attribute applies to types. |
61 | | unsigned IsType : 1; |
62 | | /// True if this attribute applies to statements. |
63 | | unsigned IsStmt : 1; |
64 | | /// True if this attribute has any spellings that are known to gcc. |
65 | | unsigned IsKnownToGCC : 1; |
66 | | /// True if this attribute is supported by #pragma clang attribute. |
67 | | unsigned IsSupportedByPragmaAttribute : 1; |
68 | | /// The syntaxes supported by this attribute and how they're spelled. |
69 | | struct Spelling { |
70 | | AttributeCommonInfo::Syntax Syntax; |
71 | | const char *NormalizedFullName; |
72 | | }; |
73 | | ArrayRef<Spelling> Spellings; |
74 | | // The names of the known arguments of this attribute. |
75 | | ArrayRef<const char *> ArgNames; |
76 | | |
77 | | protected: |
78 | | constexpr ParsedAttrInfo(AttributeCommonInfo::Kind AttrKind = |
79 | | AttributeCommonInfo::NoSemaHandlerAttribute) |
80 | | : AttrKind(AttrKind), NumArgs(0), OptArgs(0), NumArgMembers(0), |
81 | | HasCustomParsing(0), AcceptsExprPack(0), IsTargetSpecific(0), IsType(0), |
82 | 0 | IsStmt(0), IsKnownToGCC(0), IsSupportedByPragmaAttribute(0) {} |
83 | | |
84 | | constexpr ParsedAttrInfo(AttributeCommonInfo::Kind AttrKind, unsigned NumArgs, |
85 | | unsigned OptArgs, unsigned NumArgMembers, |
86 | | unsigned HasCustomParsing, unsigned AcceptsExprPack, |
87 | | unsigned IsTargetSpecific, unsigned IsType, |
88 | | unsigned IsStmt, unsigned IsKnownToGCC, |
89 | | unsigned IsSupportedByPragmaAttribute, |
90 | | ArrayRef<Spelling> Spellings, |
91 | | ArrayRef<const char *> ArgNames) |
92 | | : AttrKind(AttrKind), NumArgs(NumArgs), OptArgs(OptArgs), |
93 | | NumArgMembers(NumArgMembers), HasCustomParsing(HasCustomParsing), |
94 | | AcceptsExprPack(AcceptsExprPack), IsTargetSpecific(IsTargetSpecific), |
95 | | IsType(IsType), IsStmt(IsStmt), IsKnownToGCC(IsKnownToGCC), |
96 | | IsSupportedByPragmaAttribute(IsSupportedByPragmaAttribute), |
97 | 0 | Spellings(Spellings), ArgNames(ArgNames) {} |
98 | | |
99 | | public: |
100 | 136 | virtual ~ParsedAttrInfo() = default; |
101 | | |
102 | | /// Check if this attribute appertains to D, and issue a diagnostic if not. |
103 | | virtual bool diagAppertainsToDecl(Sema &S, const ParsedAttr &Attr, |
104 | 4.32M | const Decl *D) const { |
105 | 4.32M | return true; |
106 | 4.32M | } |
107 | | /// Check if this attribute appertains to St, and issue a diagnostic if not. |
108 | | virtual bool diagAppertainsToStmt(Sema &S, const ParsedAttr &Attr, |
109 | 521 | const Stmt *St) const { |
110 | 521 | return true; |
111 | 521 | } |
112 | | /// Check if the given attribute is mutually exclusive with other attributes |
113 | | /// already applied to the given declaration. |
114 | | virtual bool diagMutualExclusion(Sema &S, const ParsedAttr &A, |
115 | 59.6M | const Decl *D) const { |
116 | 59.6M | return true; |
117 | 59.6M | } |
118 | | /// Check if this attribute is allowed by the language we are compiling. |
119 | 79.7M | virtual bool acceptsLangOpts(const LangOptions &LO) const { return true; } |
120 | | |
121 | | /// Check if this attribute is allowed when compiling for the given target. |
122 | 123M | virtual bool existsInTarget(const TargetInfo &Target) const { |
123 | 123M | return true; |
124 | 123M | } |
125 | | /// Convert the spelling index of Attr to a semantic spelling enum value. |
126 | | virtual unsigned |
127 | 0 | spellingIndexToSemanticSpelling(const ParsedAttr &Attr) const { |
128 | 0 | return UINT_MAX; |
129 | 0 | } |
130 | | /// Returns true if the specified parameter index for this attribute in |
131 | | /// Attr.td is an ExprArgument or VariadicExprArgument, or a subclass thereof; |
132 | | /// returns false otherwise. |
133 | 0 | virtual bool isParamExpr(size_t N) const { return false; } |
134 | | /// Populate Rules with the match rules of this attribute. |
135 | | virtual void getPragmaAttributeMatchRules( |
136 | | llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules, |
137 | 95 | const LangOptions &LangOpts) const { |
138 | 95 | } |
139 | | enum AttrHandling { |
140 | | NotHandled, |
141 | | AttributeApplied, |
142 | | AttributeNotApplied |
143 | | }; |
144 | | /// If this ParsedAttrInfo knows how to handle this ParsedAttr applied to this |
145 | | /// Decl then do so and return either AttributeApplied if it was applied or |
146 | | /// AttributeNotApplied if it wasn't. Otherwise return NotHandled. |
147 | | virtual AttrHandling handleDeclAttribute(Sema &S, Decl *D, |
148 | 2.23M | const ParsedAttr &Attr) const { |
149 | 2.23M | return NotHandled; |
150 | 2.23M | } |
151 | | |
152 | | static const ParsedAttrInfo &get(const AttributeCommonInfo &A); |
153 | | static ArrayRef<const ParsedAttrInfo *> getAllBuiltin(); |
154 | | }; |
155 | | |
156 | | typedef llvm::Registry<ParsedAttrInfo> ParsedAttrInfoRegistry; |
157 | | |
158 | | /// Represents information about a change in availability for |
159 | | /// an entity, which is part of the encoding of the 'availability' |
160 | | /// attribute. |
161 | | struct AvailabilityChange { |
162 | | /// The location of the keyword indicating the kind of change. |
163 | | SourceLocation KeywordLoc; |
164 | | |
165 | | /// The version number at which the change occurred. |
166 | | VersionTuple Version; |
167 | | |
168 | | /// The source range covering the version number. |
169 | | SourceRange VersionRange; |
170 | | |
171 | | /// Determine whether this availability change is valid. |
172 | 73.5k | bool isValid() const { return !Version.empty(); } |
173 | | }; |
174 | | |
175 | | namespace detail { |
176 | | enum AvailabilitySlot { |
177 | | IntroducedSlot, DeprecatedSlot, ObsoletedSlot, NumAvailabilitySlots |
178 | | }; |
179 | | |
180 | | /// Describes the trailing object for Availability attribute in ParsedAttr. |
181 | | struct AvailabilityData { |
182 | | AvailabilityChange Changes[NumAvailabilitySlots]; |
183 | | SourceLocation StrictLoc; |
184 | | const Expr *Replacement; |
185 | | |
186 | | AvailabilityData(const AvailabilityChange &Introduced, |
187 | | const AvailabilityChange &Deprecated, |
188 | | const AvailabilityChange &Obsoleted, |
189 | | SourceLocation Strict, const Expr *ReplaceExpr) |
190 | 6.00M | : StrictLoc(Strict), Replacement(ReplaceExpr) { |
191 | 6.00M | Changes[IntroducedSlot] = Introduced; |
192 | 6.00M | Changes[DeprecatedSlot] = Deprecated; |
193 | 6.00M | Changes[ObsoletedSlot] = Obsoleted; |
194 | 6.00M | } |
195 | | }; |
196 | | |
197 | | struct TypeTagForDatatypeData { |
198 | | ParsedType MatchingCType; |
199 | | unsigned LayoutCompatible : 1; |
200 | | unsigned MustBeNull : 1; |
201 | | }; |
202 | | struct PropertyData { |
203 | | IdentifierInfo *GetterId, *SetterId; |
204 | | |
205 | | PropertyData(IdentifierInfo *getterId, IdentifierInfo *setterId) |
206 | 101 | : GetterId(getterId), SetterId(setterId) {} |
207 | | }; |
208 | | |
209 | | } // namespace |
210 | | |
211 | | /// Wraps an identifier and optional source location for the identifier. |
212 | | struct IdentifierLoc { |
213 | | SourceLocation Loc; |
214 | | IdentifierInfo *Ident; |
215 | | |
216 | | static IdentifierLoc *create(ASTContext &Ctx, SourceLocation Loc, |
217 | | IdentifierInfo *Ident); |
218 | | }; |
219 | | |
220 | | /// A union of the various pointer types that can be passed to an |
221 | | /// ParsedAttr as an argument. |
222 | | using ArgsUnion = llvm::PointerUnion<Expr *, IdentifierLoc *>; |
223 | | using ArgsVector = llvm::SmallVector<ArgsUnion, 12U>; |
224 | | |
225 | | /// ParsedAttr - Represents a syntactic attribute. |
226 | | /// |
227 | | /// For a GNU attribute, there are four forms of this construct: |
228 | | /// |
229 | | /// 1: __attribute__(( const )). ParmName/Args/NumArgs will all be unused. |
230 | | /// 2: __attribute__(( mode(byte) )). ParmName used, Args/NumArgs unused. |
231 | | /// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used. |
232 | | /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used. |
233 | | /// |
234 | | class ParsedAttr final |
235 | | : public AttributeCommonInfo, |
236 | | private llvm::TrailingObjects< |
237 | | ParsedAttr, ArgsUnion, detail::AvailabilityData, |
238 | | detail::TypeTagForDatatypeData, ParsedType, detail::PropertyData> { |
239 | | friend TrailingObjects; |
240 | | |
241 | 36.3M | size_t numTrailingObjects(OverloadToken<ArgsUnion>) const { return NumArgs; } |
242 | 30.2k | size_t numTrailingObjects(OverloadToken<detail::AvailabilityData>) const { |
243 | 30.2k | return IsAvailability; |
244 | 30.2k | } |
245 | | size_t |
246 | 29.5k | numTrailingObjects(OverloadToken<detail::TypeTagForDatatypeData>) const { |
247 | 29.5k | return IsTypeTagForDatatype; |
248 | 29.5k | } |
249 | 293 | size_t numTrailingObjects(OverloadToken<ParsedType>) const { |
250 | 293 | return HasParsedType; |
251 | 293 | } |
252 | 0 | size_t numTrailingObjects(OverloadToken<detail::PropertyData>) const { |
253 | 0 | return IsProperty; |
254 | 0 | } |
255 | | |
256 | | private: |
257 | | IdentifierInfo *MacroII = nullptr; |
258 | | SourceLocation MacroExpansionLoc; |
259 | | SourceLocation EllipsisLoc; |
260 | | |
261 | | /// The number of expression arguments this attribute has. |
262 | | /// The expressions themselves are stored after the object. |
263 | | unsigned NumArgs : 16; |
264 | | |
265 | | /// True if already diagnosed as invalid. |
266 | | mutable unsigned Invalid : 1; |
267 | | |
268 | | /// True if this attribute was used as a type attribute. |
269 | | mutable unsigned UsedAsTypeAttr : 1; |
270 | | |
271 | | /// True if this has the extra information associated with an |
272 | | /// availability attribute. |
273 | | unsigned IsAvailability : 1; |
274 | | |
275 | | /// True if this has extra information associated with a |
276 | | /// type_tag_for_datatype attribute. |
277 | | unsigned IsTypeTagForDatatype : 1; |
278 | | |
279 | | /// True if this has extra information associated with a |
280 | | /// Microsoft __delcspec(property) attribute. |
281 | | unsigned IsProperty : 1; |
282 | | |
283 | | /// True if this has a ParsedType |
284 | | unsigned HasParsedType : 1; |
285 | | |
286 | | /// True if the processing cache is valid. |
287 | | mutable unsigned HasProcessingCache : 1; |
288 | | |
289 | | /// A cached value. |
290 | | mutable unsigned ProcessingCache : 8; |
291 | | |
292 | | /// True if the attribute is specified using '#pragma clang attribute'. |
293 | | mutable unsigned IsPragmaClangAttribute : 1; |
294 | | |
295 | | /// The location of the 'unavailable' keyword in an |
296 | | /// availability attribute. |
297 | | SourceLocation UnavailableLoc; |
298 | | |
299 | | const Expr *MessageExpr; |
300 | | |
301 | | const ParsedAttrInfo &Info; |
302 | | |
303 | 28.6M | ArgsUnion *getArgsBuffer() { return getTrailingObjects<ArgsUnion>(); } |
304 | 50.2M | ArgsUnion const *getArgsBuffer() const { |
305 | 50.2M | return getTrailingObjects<ArgsUnion>(); |
306 | 50.2M | } |
307 | | |
308 | 6.00M | detail::AvailabilityData *getAvailabilityData() { |
309 | 6.00M | return getTrailingObjects<detail::AvailabilityData>(); |
310 | 6.00M | } |
311 | 30.3M | const detail::AvailabilityData *getAvailabilityData() const { |
312 | 30.3M | return getTrailingObjects<detail::AvailabilityData>(); |
313 | 30.3M | } |
314 | | |
315 | | private: |
316 | | friend class AttributeFactory; |
317 | | friend class AttributePool; |
318 | | |
319 | | /// Constructor for attributes with expression arguments. |
320 | | ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, |
321 | | IdentifierInfo *scopeName, SourceLocation scopeLoc, |
322 | | ArgsUnion *args, unsigned numArgs, Syntax syntaxUsed, |
323 | | SourceLocation ellipsisLoc) |
324 | | : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, |
325 | | syntaxUsed), |
326 | | EllipsisLoc(ellipsisLoc), NumArgs(numArgs), Invalid(false), |
327 | | UsedAsTypeAttr(false), IsAvailability(false), |
328 | | IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), |
329 | | HasProcessingCache(false), IsPragmaClangAttribute(false), |
330 | 74.7M | Info(ParsedAttrInfo::get(*this)) { |
331 | 74.7M | if (numArgs) |
332 | 22.6M | memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion)); |
333 | 74.7M | } |
334 | | |
335 | | /// Constructor for availability attributes. |
336 | | ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, |
337 | | IdentifierInfo *scopeName, SourceLocation scopeLoc, |
338 | | IdentifierLoc *Parm, const AvailabilityChange &introduced, |
339 | | const AvailabilityChange &deprecated, |
340 | | const AvailabilityChange &obsoleted, SourceLocation unavailable, |
341 | | const Expr *messageExpr, Syntax syntaxUsed, SourceLocation strict, |
342 | | const Expr *replacementExpr) |
343 | | : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, |
344 | | syntaxUsed), |
345 | | NumArgs(1), Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), |
346 | | IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), |
347 | | HasProcessingCache(false), IsPragmaClangAttribute(false), |
348 | | UnavailableLoc(unavailable), MessageExpr(messageExpr), |
349 | 6.00M | Info(ParsedAttrInfo::get(*this)) { |
350 | 6.00M | ArgsUnion PVal(Parm); |
351 | 6.00M | memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); |
352 | 6.00M | new (getAvailabilityData()) detail::AvailabilityData( |
353 | 6.00M | introduced, deprecated, obsoleted, strict, replacementExpr); |
354 | 6.00M | } |
355 | | |
356 | | /// Constructor for objc_bridge_related attributes. |
357 | | ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, |
358 | | IdentifierInfo *scopeName, SourceLocation scopeLoc, |
359 | | IdentifierLoc *Parm1, IdentifierLoc *Parm2, IdentifierLoc *Parm3, |
360 | | Syntax syntaxUsed) |
361 | | : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, |
362 | | syntaxUsed), |
363 | | NumArgs(3), Invalid(false), UsedAsTypeAttr(false), |
364 | | IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), |
365 | | HasParsedType(false), HasProcessingCache(false), |
366 | 475 | IsPragmaClangAttribute(false), Info(ParsedAttrInfo::get(*this)) { |
367 | 475 | ArgsUnion *Args = getArgsBuffer(); |
368 | 475 | Args[0] = Parm1; |
369 | 475 | Args[1] = Parm2; |
370 | 475 | Args[2] = Parm3; |
371 | 475 | } |
372 | | |
373 | | /// Constructor for type_tag_for_datatype attribute. |
374 | | ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, |
375 | | IdentifierInfo *scopeName, SourceLocation scopeLoc, |
376 | | IdentifierLoc *ArgKind, ParsedType matchingCType, |
377 | | bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed) |
378 | | : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, |
379 | | syntaxUsed), |
380 | | NumArgs(1), Invalid(false), UsedAsTypeAttr(false), |
381 | | IsAvailability(false), IsTypeTagForDatatype(true), IsProperty(false), |
382 | | HasParsedType(false), HasProcessingCache(false), |
383 | 169 | IsPragmaClangAttribute(false), Info(ParsedAttrInfo::get(*this)) { |
384 | 169 | ArgsUnion PVal(ArgKind); |
385 | 169 | memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); |
386 | 169 | detail::TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot(); |
387 | 169 | new (&ExtraData.MatchingCType) ParsedType(matchingCType); |
388 | 169 | ExtraData.LayoutCompatible = layoutCompatible; |
389 | 169 | ExtraData.MustBeNull = mustBeNull; |
390 | 169 | } |
391 | | |
392 | | /// Constructor for attributes with a single type argument. |
393 | | ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, |
394 | | IdentifierInfo *scopeName, SourceLocation scopeLoc, |
395 | | ParsedType typeArg, Syntax syntaxUsed) |
396 | | : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, |
397 | | syntaxUsed), |
398 | | NumArgs(0), Invalid(false), UsedAsTypeAttr(false), |
399 | | IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), |
400 | | HasParsedType(true), HasProcessingCache(false), |
401 | 14.6k | IsPragmaClangAttribute(false), Info(ParsedAttrInfo::get(*this)) { |
402 | 14.6k | new (&getTypeBuffer()) ParsedType(typeArg); |
403 | 14.6k | } |
404 | | |
405 | | /// Constructor for microsoft __declspec(property) attribute. |
406 | | ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, |
407 | | IdentifierInfo *scopeName, SourceLocation scopeLoc, |
408 | | IdentifierInfo *getterId, IdentifierInfo *setterId, |
409 | | Syntax syntaxUsed) |
410 | | : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, |
411 | | syntaxUsed), |
412 | | NumArgs(0), Invalid(false), UsedAsTypeAttr(false), |
413 | | IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(true), |
414 | | HasParsedType(false), HasProcessingCache(false), |
415 | 101 | IsPragmaClangAttribute(false), Info(ParsedAttrInfo::get(*this)) { |
416 | 101 | new (&getPropertyDataBuffer()) detail::PropertyData(getterId, setterId); |
417 | 101 | } |
418 | | |
419 | | /// Type tag information is stored immediately following the arguments, if |
420 | | /// any, at the end of the object. They are mutually exclusive with |
421 | | /// availability slots. |
422 | 169 | detail::TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() { |
423 | 169 | return *getTrailingObjects<detail::TypeTagForDatatypeData>(); |
424 | 169 | } |
425 | 498 | const detail::TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const { |
426 | 498 | return *getTrailingObjects<detail::TypeTagForDatatypeData>(); |
427 | 498 | } |
428 | | |
429 | | /// The type buffer immediately follows the object and are mutually exclusive |
430 | | /// with arguments. |
431 | 14.6k | ParsedType &getTypeBuffer() { return *getTrailingObjects<ParsedType>(); } |
432 | 14.6k | const ParsedType &getTypeBuffer() const { |
433 | 14.6k | return *getTrailingObjects<ParsedType>(); |
434 | 14.6k | } |
435 | | |
436 | | /// The property data immediately follows the object is is mutually exclusive |
437 | | /// with arguments. |
438 | 101 | detail::PropertyData &getPropertyDataBuffer() { |
439 | 101 | assert(IsProperty); |
440 | 0 | return *getTrailingObjects<detail::PropertyData>(); |
441 | 101 | } |
442 | 192 | const detail::PropertyData &getPropertyDataBuffer() const { |
443 | 192 | assert(IsProperty); |
444 | 0 | return *getTrailingObjects<detail::PropertyData>(); |
445 | 192 | } |
446 | | |
447 | | size_t allocated_size() const; |
448 | | |
449 | | public: |
450 | | ParsedAttr(const ParsedAttr &) = delete; |
451 | | ParsedAttr(ParsedAttr &&) = delete; |
452 | | ParsedAttr &operator=(const ParsedAttr &) = delete; |
453 | | ParsedAttr &operator=(ParsedAttr &&) = delete; |
454 | | ~ParsedAttr() = delete; |
455 | | |
456 | | void operator delete(void *) = delete; |
457 | | |
458 | 79.7M | bool hasParsedType() const { return HasParsedType; } |
459 | | |
460 | | /// Is this the Microsoft __declspec(property) attribute? |
461 | 1.16M | bool isDeclspecPropertyAttribute() const { |
462 | 1.16M | return IsProperty; |
463 | 1.16M | } |
464 | | |
465 | 157M | bool isInvalid() const { return Invalid; } |
466 | 497 | void setInvalid(bool b = true) const { Invalid = b; } |
467 | | |
468 | 8.43k | bool hasProcessingCache() const { return HasProcessingCache; } |
469 | | |
470 | 2.70k | unsigned getProcessingCache() const { |
471 | 2.70k | assert(hasProcessingCache()); |
472 | 0 | return ProcessingCache; |
473 | 2.70k | } |
474 | | |
475 | 2.98k | void setProcessingCache(unsigned value) const { |
476 | 2.98k | ProcessingCache = value; |
477 | 2.98k | HasProcessingCache = true; |
478 | 2.98k | } |
479 | | |
480 | 1.17M | bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; } |
481 | 5.51M | void setUsedAsTypeAttr(bool Used = true) { UsedAsTypeAttr = Used; } |
482 | | |
483 | | /// True if the attribute is specified using '#pragma clang attribute'. |
484 | 6.13M | bool isPragmaClangAttribute() const { return IsPragmaClangAttribute; } |
485 | | |
486 | 1.07k | void setIsPragmaClangAttribute() { IsPragmaClangAttribute = true; } |
487 | | |
488 | 95.7k | bool isPackExpansion() const { return EllipsisLoc.isValid(); } |
489 | 1 | SourceLocation getEllipsisLoc() const { return EllipsisLoc; } |
490 | | |
491 | | /// getNumArgs - Return the number of actual arguments to this attribute. |
492 | 80.0M | unsigned getNumArgs() const { return NumArgs; } |
493 | | |
494 | | /// getArg - Return the specified argument. |
495 | 50.2M | ArgsUnion getArg(unsigned Arg) const { |
496 | 50.2M | assert(Arg < NumArgs && "Arg access out of range!"); |
497 | 0 | return getArgsBuffer()[Arg]; |
498 | 50.2M | } |
499 | | |
500 | 37.1k | bool isArgExpr(unsigned Arg) const { |
501 | 37.1k | return Arg < NumArgs && getArg(Arg).is<Expr*>()11.0k ; |
502 | 37.1k | } |
503 | | |
504 | 4.39M | Expr *getArgAsExpr(unsigned Arg) const { |
505 | 4.39M | return getArg(Arg).get<Expr*>(); |
506 | 4.39M | } |
507 | | |
508 | 21.3M | bool isArgIdent(unsigned Arg) const { |
509 | 21.3M | return Arg < NumArgs && getArg(Arg).is<IdentifierLoc*>()21.3M ; |
510 | 21.3M | } |
511 | | |
512 | 24.4M | IdentifierLoc *getArgAsIdent(unsigned Arg) const { |
513 | 24.4M | return getArg(Arg).get<IdentifierLoc*>(); |
514 | 24.4M | } |
515 | | |
516 | 6.06M | const AvailabilityChange &getAvailabilityIntroduced() const { |
517 | 6.06M | assert(getParsedKind() == AT_Availability && |
518 | 6.06M | "Not an availability attribute"); |
519 | 0 | return getAvailabilityData()->Changes[detail::IntroducedSlot]; |
520 | 6.06M | } |
521 | | |
522 | 6.06M | const AvailabilityChange &getAvailabilityDeprecated() const { |
523 | 6.06M | assert(getParsedKind() == AT_Availability && |
524 | 6.06M | "Not an availability attribute"); |
525 | 0 | return getAvailabilityData()->Changes[detail::DeprecatedSlot]; |
526 | 6.06M | } |
527 | | |
528 | 6.06M | const AvailabilityChange &getAvailabilityObsoleted() const { |
529 | 6.06M | assert(getParsedKind() == AT_Availability && |
530 | 6.06M | "Not an availability attribute"); |
531 | 0 | return getAvailabilityData()->Changes[detail::ObsoletedSlot]; |
532 | 6.06M | } |
533 | | |
534 | 6.06M | SourceLocation getStrictLoc() const { |
535 | 6.06M | assert(getParsedKind() == AT_Availability && |
536 | 6.06M | "Not an availability attribute"); |
537 | 0 | return getAvailabilityData()->StrictLoc; |
538 | 6.06M | } |
539 | | |
540 | 6.06M | SourceLocation getUnavailableLoc() const { |
541 | 6.06M | assert(getParsedKind() == AT_Availability && |
542 | 6.06M | "Not an availability attribute"); |
543 | 0 | return UnavailableLoc; |
544 | 6.06M | } |
545 | | |
546 | 6.06M | const Expr * getMessageExpr() const { |
547 | 6.06M | assert(getParsedKind() == AT_Availability && |
548 | 6.06M | "Not an availability attribute"); |
549 | 0 | return MessageExpr; |
550 | 6.06M | } |
551 | | |
552 | 6.06M | const Expr *getReplacementExpr() const { |
553 | 6.06M | assert(getParsedKind() == AT_Availability && |
554 | 6.06M | "Not an availability attribute"); |
555 | 0 | return getAvailabilityData()->Replacement; |
556 | 6.06M | } |
557 | | |
558 | 166 | const ParsedType &getMatchingCType() const { |
559 | 166 | assert(getParsedKind() == AT_TypeTagForDatatype && |
560 | 166 | "Not a type_tag_for_datatype attribute"); |
561 | 0 | return getTypeTagForDatatypeDataSlot().MatchingCType; |
562 | 166 | } |
563 | | |
564 | 166 | bool getLayoutCompatible() const { |
565 | 166 | assert(getParsedKind() == AT_TypeTagForDatatype && |
566 | 166 | "Not a type_tag_for_datatype attribute"); |
567 | 0 | return getTypeTagForDatatypeDataSlot().LayoutCompatible; |
568 | 166 | } |
569 | | |
570 | 166 | bool getMustBeNull() const { |
571 | 166 | assert(getParsedKind() == AT_TypeTagForDatatype && |
572 | 166 | "Not a type_tag_for_datatype attribute"); |
573 | 0 | return getTypeTagForDatatypeDataSlot().MustBeNull; |
574 | 166 | } |
575 | | |
576 | 14.6k | const ParsedType &getTypeArg() const { |
577 | 14.6k | assert(HasParsedType && "Not a type attribute"); |
578 | 0 | return getTypeBuffer(); |
579 | 14.6k | } |
580 | | |
581 | 96 | IdentifierInfo *getPropertyDataGetter() const { |
582 | 96 | assert(isDeclspecPropertyAttribute() && |
583 | 96 | "Not a __delcspec(property) attribute"); |
584 | 0 | return getPropertyDataBuffer().GetterId; |
585 | 96 | } |
586 | | |
587 | 96 | IdentifierInfo *getPropertyDataSetter() const { |
588 | 96 | assert(isDeclspecPropertyAttribute() && |
589 | 96 | "Not a __delcspec(property) attribute"); |
590 | 0 | return getPropertyDataBuffer().SetterId; |
591 | 96 | } |
592 | | |
593 | | /// Set the macro identifier info object that this parsed attribute was |
594 | | /// declared in if it was declared in a macro. Also set the expansion location |
595 | | /// of the macro. |
596 | 7.67M | void setMacroIdentifier(IdentifierInfo *MacroName, SourceLocation Loc) { |
597 | 7.67M | MacroII = MacroName; |
598 | 7.67M | MacroExpansionLoc = Loc; |
599 | 7.67M | } |
600 | | |
601 | | /// Returns true if this attribute was declared in a macro. |
602 | 3.80M | bool hasMacroIdentifier() const { return MacroII != nullptr; } |
603 | | |
604 | | /// Return the macro identifier if this attribute was declared in a macro. |
605 | | /// nullptr is returned if it was not declared in a macro. |
606 | 244k | IdentifierInfo *getMacroIdentifier() const { return MacroII; } |
607 | | |
608 | 244k | SourceLocation getMacroExpansionLoc() const { |
609 | 244k | assert(hasMacroIdentifier() && "Can only get the macro expansion location " |
610 | 244k | "if this attribute has a macro identifier."); |
611 | 0 | return MacroExpansionLoc; |
612 | 244k | } |
613 | | |
614 | | /// Check if the attribute has exactly as many args as Num. May output an |
615 | | /// error. Returns false if a diagnostic is produced. |
616 | | bool checkExactlyNumArgs(class Sema &S, unsigned Num) const; |
617 | | /// Check if the attribute has at least as many args as Num. May output an |
618 | | /// error. Returns false if a diagnostic is produced. |
619 | | bool checkAtLeastNumArgs(class Sema &S, unsigned Num) const; |
620 | | /// Check if the attribute has at most as many args as Num. May output an |
621 | | /// error. Returns false if a diagnostic is produced. |
622 | | bool checkAtMostNumArgs(class Sema &S, unsigned Num) const; |
623 | | |
624 | | bool isTargetSpecificAttr() const; |
625 | | bool isTypeAttr() const; |
626 | | bool isStmtAttr() const; |
627 | | |
628 | | bool hasCustomParsing() const; |
629 | | bool acceptsExprPack() const; |
630 | | bool isParamExpr(size_t N) const; |
631 | | unsigned getMinArgs() const; |
632 | | unsigned getMaxArgs() const; |
633 | | unsigned getNumArgMembers() const; |
634 | | bool hasVariadicArg() const; |
635 | | void handleAttrWithDelayedArgs(Sema &S, Decl *D) const; |
636 | | bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const; |
637 | | bool diagnoseAppertainsTo(class Sema &S, const Stmt *St) const; |
638 | | bool diagnoseMutualExclusion(class Sema &S, const Decl *D) const; |
639 | | // This function stub exists for parity with the declaration checking code so |
640 | | // that checkCommonAttributeFeatures() can work generically on declarations |
641 | | // or statements. |
642 | 1.73k | bool diagnoseMutualExclusion(class Sema &S, const Stmt *St) const { |
643 | 1.73k | return true; |
644 | 1.73k | } |
645 | | bool appliesToDecl(const Decl *D, attr::SubjectMatchRule MatchRule) const; |
646 | | void getMatchRules(const LangOptions &LangOpts, |
647 | | SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> |
648 | | &MatchRules) const; |
649 | | bool diagnoseLangOpts(class Sema &S) const; |
650 | | bool existsInTarget(const TargetInfo &Target) const; |
651 | | bool isKnownToGCC() const; |
652 | | bool isSupportedByPragmaAttribute() const; |
653 | | |
654 | | /// If the parsed attribute has a semantic equivalent, and it would |
655 | | /// have a semantic Spelling enumeration (due to having semantically-distinct |
656 | | /// spelling variations), return the value of that semantic spelling. If the |
657 | | /// parsed attribute does not have a semantic equivalent, or would not have |
658 | | /// a Spelling enumeration, the value UINT_MAX is returned. |
659 | | unsigned getSemanticSpelling() const; |
660 | | |
661 | | /// If this is an OpenCL address space attribute, returns its representation |
662 | | /// in LangAS, otherwise returns default address space. |
663 | 33.8k | LangAS asOpenCLLangAS() const { |
664 | 33.8k | switch (getParsedKind()) { |
665 | 2.34k | case ParsedAttr::AT_OpenCLConstantAddressSpace: |
666 | 2.34k | return LangAS::opencl_constant; |
667 | 13.8k | case ParsedAttr::AT_OpenCLGlobalAddressSpace: |
668 | 13.8k | return LangAS::opencl_global; |
669 | 37 | case ParsedAttr::AT_OpenCLGlobalDeviceAddressSpace: |
670 | 37 | return LangAS::opencl_global_device; |
671 | 37 | case ParsedAttr::AT_OpenCLGlobalHostAddressSpace: |
672 | 37 | return LangAS::opencl_global_host; |
673 | 11.9k | case ParsedAttr::AT_OpenCLLocalAddressSpace: |
674 | 11.9k | return LangAS::opencl_local; |
675 | 3.72k | case ParsedAttr::AT_OpenCLPrivateAddressSpace: |
676 | 3.72k | return LangAS::opencl_private; |
677 | 1.97k | case ParsedAttr::AT_OpenCLGenericAddressSpace: |
678 | 1.97k | return LangAS::opencl_generic; |
679 | 0 | default: |
680 | 0 | return LangAS::Default; |
681 | 33.8k | } |
682 | 33.8k | } |
683 | | |
684 | | /// If this is an OpenCL address space attribute, returns its SYCL |
685 | | /// representation in LangAS, otherwise returns default address space. |
686 | 38 | LangAS asSYCLLangAS() const { |
687 | 38 | switch (getKind()) { |
688 | 10 | case ParsedAttr::AT_OpenCLGlobalAddressSpace: |
689 | 10 | return LangAS::sycl_global; |
690 | 3 | case ParsedAttr::AT_OpenCLGlobalDeviceAddressSpace: |
691 | 3 | return LangAS::sycl_global_device; |
692 | 3 | case ParsedAttr::AT_OpenCLGlobalHostAddressSpace: |
693 | 3 | return LangAS::sycl_global_host; |
694 | 10 | case ParsedAttr::AT_OpenCLLocalAddressSpace: |
695 | 10 | return LangAS::sycl_local; |
696 | 12 | case ParsedAttr::AT_OpenCLPrivateAddressSpace: |
697 | 12 | return LangAS::sycl_private; |
698 | 0 | case ParsedAttr::AT_OpenCLGenericAddressSpace: |
699 | 0 | default: |
700 | 0 | return LangAS::Default; |
701 | 38 | } |
702 | 38 | } |
703 | | |
704 | 407M | AttributeCommonInfo::Kind getKind() const { |
705 | 407M | return AttributeCommonInfo::Kind(Info.AttrKind); |
706 | 407M | } |
707 | 870M | const ParsedAttrInfo &getInfo() const { return Info; } |
708 | | }; |
709 | | |
710 | | class AttributePool; |
711 | | /// A factory, from which one makes pools, from which one creates |
712 | | /// individual attributes which are deallocated with the pool. |
713 | | /// |
714 | | /// Note that it's tolerably cheap to create and destroy one of |
715 | | /// these as long as you don't actually allocate anything in it. |
716 | | class AttributeFactory { |
717 | | public: |
718 | | enum { |
719 | | AvailabilityAllocSize = |
720 | | ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, |
721 | | detail::TypeTagForDatatypeData, ParsedType, |
722 | | detail::PropertyData>(1, 1, 0, 0, 0), |
723 | | TypeTagForDatatypeAllocSize = |
724 | | ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, |
725 | | detail::TypeTagForDatatypeData, ParsedType, |
726 | | detail::PropertyData>(1, 0, 1, 0, 0), |
727 | | PropertyAllocSize = |
728 | | ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, |
729 | | detail::TypeTagForDatatypeData, ParsedType, |
730 | | detail::PropertyData>(0, 0, 0, 0, 1), |
731 | | }; |
732 | | |
733 | | private: |
734 | | enum { |
735 | | /// The number of free lists we want to be sure to support |
736 | | /// inline. This is just enough that availability attributes |
737 | | /// don't surpass it. It's actually very unlikely we'll see an |
738 | | /// attribute that needs more than that; on x86-64 you'd need 10 |
739 | | /// expression arguments, and on i386 you'd need 19. |
740 | | InlineFreeListsCapacity = |
741 | | 1 + (AvailabilityAllocSize - sizeof(ParsedAttr)) / sizeof(void *) |
742 | | }; |
743 | | |
744 | | llvm::BumpPtrAllocator Alloc; |
745 | | |
746 | | /// Free lists. The index is determined by the following formula: |
747 | | /// (size - sizeof(ParsedAttr)) / sizeof(void*) |
748 | | SmallVector<SmallVector<ParsedAttr *, 8>, InlineFreeListsCapacity> FreeLists; |
749 | | |
750 | | // The following are the private interface used by AttributePool. |
751 | | friend class AttributePool; |
752 | | |
753 | | /// Allocate an attribute of the given size. |
754 | | void *allocate(size_t size); |
755 | | |
756 | | void deallocate(ParsedAttr *AL); |
757 | | |
758 | | /// Reclaim all the attributes in the given pool chain, which is |
759 | | /// non-empty. Note that the current implementation is safe |
760 | | /// against reclaiming things which were not actually allocated |
761 | | /// with the allocator, although of course it's important to make |
762 | | /// sure that their allocator lives at least as long as this one. |
763 | | void reclaimPool(AttributePool &head); |
764 | | |
765 | | public: |
766 | | AttributeFactory(); |
767 | | ~AttributeFactory(); |
768 | | }; |
769 | | |
770 | | class AttributePool { |
771 | | friend class AttributeFactory; |
772 | | friend class ParsedAttributes; |
773 | | AttributeFactory &Factory; |
774 | | llvm::TinyPtrVector<ParsedAttr *> Attrs; |
775 | | |
776 | 80.7M | void *allocate(size_t size) { |
777 | 80.7M | return Factory.allocate(size); |
778 | 80.7M | } |
779 | | |
780 | 80.7M | ParsedAttr *add(ParsedAttr *attr) { |
781 | 80.7M | Attrs.push_back(attr); |
782 | 80.7M | return attr; |
783 | 80.7M | } |
784 | | |
785 | 13 | void remove(ParsedAttr *attr) { |
786 | 13 | assert(llvm::is_contained(Attrs, attr) && |
787 | 13 | "Can't take attribute from a pool that doesn't own it!"); |
788 | 0 | Attrs.erase(llvm::find(Attrs, attr)); |
789 | 13 | } |
790 | | |
791 | | void takePool(AttributePool &pool); |
792 | | |
793 | | public: |
794 | | /// Create a new pool for a factory. |
795 | 478M | AttributePool(AttributeFactory &factory) : Factory(factory) {} |
796 | | |
797 | | AttributePool(const AttributePool &) = delete; |
798 | | |
799 | 478M | ~AttributePool() { Factory.reclaimPool(*this); } |
800 | | |
801 | | /// Move the given pool's allocations to this pool. |
802 | | AttributePool(AttributePool &&pool) = default; |
803 | | |
804 | 108M | AttributeFactory &getFactory() const { return Factory; } |
805 | | |
806 | 108M | void clear() { |
807 | 108M | Factory.reclaimPool(*this); |
808 | 108M | Attrs.clear(); |
809 | 108M | } |
810 | | |
811 | | /// Take the given pool's allocations and add them to this pool. |
812 | 136M | void takeAllFrom(AttributePool &pool) { |
813 | 136M | takePool(pool); |
814 | 136M | pool.Attrs.clear(); |
815 | 136M | } |
816 | | |
817 | | ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange, |
818 | | IdentifierInfo *scopeName, SourceLocation scopeLoc, |
819 | | ArgsUnion *args, unsigned numArgs, |
820 | | ParsedAttr::Syntax syntax, |
821 | 74.7M | SourceLocation ellipsisLoc = SourceLocation()) { |
822 | 74.7M | size_t temp = |
823 | 74.7M | ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, |
824 | 74.7M | detail::TypeTagForDatatypeData, ParsedType, |
825 | 74.7M | detail::PropertyData>(numArgs, 0, 0, 0, 0); |
826 | 74.7M | (void)temp; |
827 | 74.7M | void *memory = allocate( |
828 | 74.7M | ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, |
829 | 74.7M | detail::TypeTagForDatatypeData, ParsedType, |
830 | 74.7M | detail::PropertyData>(numArgs, 0, 0, 0, |
831 | 74.7M | 0)); |
832 | 74.7M | return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, |
833 | 74.7M | args, numArgs, syntax, ellipsisLoc)); |
834 | 74.7M | } |
835 | | |
836 | | ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange, |
837 | | IdentifierInfo *scopeName, SourceLocation scopeLoc, |
838 | | IdentifierLoc *Param, const AvailabilityChange &introduced, |
839 | | const AvailabilityChange &deprecated, |
840 | | const AvailabilityChange &obsoleted, |
841 | | SourceLocation unavailable, const Expr *MessageExpr, |
842 | | ParsedAttr::Syntax syntax, SourceLocation strict, |
843 | 6.00M | const Expr *ReplacementExpr) { |
844 | 6.00M | void *memory = allocate(AttributeFactory::AvailabilityAllocSize); |
845 | 6.00M | return add(new (memory) ParsedAttr( |
846 | 6.00M | attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated, |
847 | 6.00M | obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr)); |
848 | 6.00M | } |
849 | | |
850 | | ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange, |
851 | | IdentifierInfo *scopeName, SourceLocation scopeLoc, |
852 | | IdentifierLoc *Param1, IdentifierLoc *Param2, |
853 | 475 | IdentifierLoc *Param3, ParsedAttr::Syntax syntax) { |
854 | 475 | void *memory = allocate( |
855 | 475 | ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, |
856 | 475 | detail::TypeTagForDatatypeData, ParsedType, |
857 | 475 | detail::PropertyData>(3, 0, 0, 0, 0)); |
858 | 475 | return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, |
859 | 475 | Param1, Param2, Param3, syntax)); |
860 | 475 | } |
861 | | |
862 | | ParsedAttr * |
863 | | createTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange, |
864 | | IdentifierInfo *scopeName, SourceLocation scopeLoc, |
865 | | IdentifierLoc *argumentKind, |
866 | | ParsedType matchingCType, bool layoutCompatible, |
867 | 169 | bool mustBeNull, ParsedAttr::Syntax syntax) { |
868 | 169 | void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize); |
869 | 169 | return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, |
870 | 169 | argumentKind, matchingCType, |
871 | 169 | layoutCompatible, mustBeNull, syntax)); |
872 | 169 | } |
873 | | |
874 | | ParsedAttr *createTypeAttribute(IdentifierInfo *attrName, |
875 | | SourceRange attrRange, |
876 | | IdentifierInfo *scopeName, |
877 | | SourceLocation scopeLoc, ParsedType typeArg, |
878 | 14.6k | ParsedAttr::Syntax syntaxUsed) { |
879 | 14.6k | void *memory = allocate( |
880 | 14.6k | ParsedAttr::totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, |
881 | 14.6k | detail::TypeTagForDatatypeData, ParsedType, |
882 | 14.6k | detail::PropertyData>(0, 0, 0, 1, 0)); |
883 | 14.6k | return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, |
884 | 14.6k | typeArg, syntaxUsed)); |
885 | 14.6k | } |
886 | | |
887 | | ParsedAttr * |
888 | | createPropertyAttribute(IdentifierInfo *attrName, SourceRange attrRange, |
889 | | IdentifierInfo *scopeName, SourceLocation scopeLoc, |
890 | | IdentifierInfo *getterId, IdentifierInfo *setterId, |
891 | 101 | ParsedAttr::Syntax syntaxUsed) { |
892 | 101 | void *memory = allocate(AttributeFactory::PropertyAllocSize); |
893 | 101 | return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, |
894 | 101 | getterId, setterId, syntaxUsed)); |
895 | 101 | } |
896 | | }; |
897 | | |
898 | | class ParsedAttributesView { |
899 | | using VecTy = llvm::TinyPtrVector<ParsedAttr *>; |
900 | | using SizeType = decltype(std::declval<VecTy>().size()); |
901 | | |
902 | | public: |
903 | | SourceRange Range; |
904 | 641M | bool empty() const { return AttrList.empty(); } |
905 | 83.1M | SizeType size() const { return AttrList.size(); } |
906 | 7.67M | ParsedAttr &operator[](SizeType pos) { return *AttrList[pos]; } |
907 | 0 | const ParsedAttr &operator[](SizeType pos) const { return *AttrList[pos]; } |
908 | | |
909 | 81.0M | void addAtEnd(ParsedAttr *newAttr) { |
910 | 81.0M | assert(newAttr); |
911 | 0 | AttrList.push_back(newAttr); |
912 | 81.0M | } |
913 | | |
914 | 66.2k | void remove(ParsedAttr *ToBeRemoved) { |
915 | 66.2k | assert(is_contained(AttrList, ToBeRemoved) && |
916 | 66.2k | "Cannot remove attribute that isn't in the list"); |
917 | 0 | AttrList.erase(llvm::find(AttrList, ToBeRemoved)); |
918 | 66.2k | } |
919 | | |
920 | 207M | void clearListOnly() { AttrList.clear(); } |
921 | | |
922 | | struct iterator : llvm::iterator_adaptor_base<iterator, VecTy::iterator, |
923 | | std::random_access_iterator_tag, |
924 | | ParsedAttr> { |
925 | 0 | iterator() : iterator_adaptor_base(nullptr) {} |
926 | 345M | iterator(VecTy::iterator I) : iterator_adaptor_base(I) {} |
927 | 83.3M | reference operator*() const { return **I; } |
928 | | friend class ParsedAttributesView; |
929 | | }; |
930 | | struct const_iterator |
931 | | : llvm::iterator_adaptor_base<const_iterator, VecTy::const_iterator, |
932 | | std::random_access_iterator_tag, |
933 | | ParsedAttr> { |
934 | 0 | const_iterator() : iterator_adaptor_base(nullptr) {} |
935 | 180M | const_iterator(VecTy::const_iterator I) : iterator_adaptor_base(I) {} |
936 | | |
937 | 82.8M | reference operator*() const { return **I; } |
938 | | friend class ParsedAttributesView; |
939 | | }; |
940 | | |
941 | 135M | void addAll(iterator B, iterator E) { |
942 | 135M | AttrList.insert(AttrList.begin(), B.I, E.I); |
943 | 135M | } |
944 | | |
945 | 90.3k | void addAll(const_iterator B, const_iterator E) { |
946 | 90.3k | AttrList.insert(AttrList.begin(), B.I, E.I); |
947 | 90.3k | } |
948 | | |
949 | 0 | void addAllAtEnd(iterator B, iterator E) { |
950 | 0 | AttrList.insert(AttrList.end(), B.I, E.I); |
951 | 0 | } |
952 | | |
953 | 0 | void addAllAtEnd(const_iterator B, const_iterator E) { |
954 | 0 | AttrList.insert(AttrList.end(), B.I, E.I); |
955 | 0 | } |
956 | | |
957 | 172M | iterator begin() { return iterator(AttrList.begin()); } |
958 | 89.0M | const_iterator begin() const { return const_iterator(AttrList.begin()); } |
959 | 172M | iterator end() { return iterator(AttrList.end()); } |
960 | 91.6M | const_iterator end() const { return const_iterator(AttrList.end()); } |
961 | | |
962 | 0 | ParsedAttr &front() { |
963 | 0 | assert(!empty()); |
964 | 0 | return *AttrList.front(); |
965 | 0 | } |
966 | 0 | const ParsedAttr &front() const { |
967 | 0 | assert(!empty()); |
968 | 0 | return *AttrList.front(); |
969 | 0 | } |
970 | 535 | ParsedAttr &back() { |
971 | 535 | assert(!empty()); |
972 | 0 | return *AttrList.back(); |
973 | 535 | } |
974 | 0 | const ParsedAttr &back() const { |
975 | 0 | assert(!empty()); |
976 | 0 | return *AttrList.back(); |
977 | 0 | } |
978 | | |
979 | 240M | bool hasAttribute(ParsedAttr::Kind K) const { |
980 | 240M | return llvm::any_of(AttrList, [K](const ParsedAttr *AL) { |
981 | 144M | return AL->getParsedKind() == K; |
982 | 144M | }); |
983 | 240M | } |
984 | | |
985 | | private: |
986 | | VecTy AttrList; |
987 | | }; |
988 | | |
989 | | /// ParsedAttributes - A collection of parsed attributes. Currently |
990 | | /// we don't differentiate between the various attribute syntaxes, |
991 | | /// which is basically silly. |
992 | | /// |
993 | | /// Right now this is a very lightweight container, but the expectation |
994 | | /// is that this will become significantly more serious. |
995 | | class ParsedAttributes : public ParsedAttributesView { |
996 | | public: |
997 | 477M | ParsedAttributes(AttributeFactory &factory) : pool(factory) {} |
998 | | ParsedAttributes(const ParsedAttributes &) = delete; |
999 | | |
1000 | 192M | AttributePool &getPool() const { return pool; } |
1001 | | |
1002 | 98.8M | void takeAllFrom(ParsedAttributes &Other) { |
1003 | 98.8M | assert(&Other != this && |
1004 | 98.8M | "ParsedAttributes can't take attributes from itself"); |
1005 | 0 | addAll(Other.begin(), Other.end()); |
1006 | 98.8M | Other.clearListOnly(); |
1007 | 98.8M | pool.takeAllFrom(Other.pool); |
1008 | 98.8M | } |
1009 | | |
1010 | 13 | void takeOneFrom(ParsedAttributes &Other, ParsedAttr *PA) { |
1011 | 13 | assert(&Other != this && |
1012 | 13 | "ParsedAttributes can't take attribute from itself"); |
1013 | 0 | Other.getPool().remove(PA); |
1014 | 13 | Other.remove(PA); |
1015 | 13 | getPool().add(PA); |
1016 | 13 | addAtEnd(PA); |
1017 | 13 | } |
1018 | | |
1019 | 108M | void clear() { |
1020 | 108M | clearListOnly(); |
1021 | 108M | pool.clear(); |
1022 | 108M | Range = SourceRange(); |
1023 | 108M | } |
1024 | | |
1025 | | /// Add attribute with expression arguments. |
1026 | | ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange, |
1027 | | IdentifierInfo *scopeName, SourceLocation scopeLoc, |
1028 | | ArgsUnion *args, unsigned numArgs, |
1029 | | ParsedAttr::Syntax syntax, |
1030 | 72.1M | SourceLocation ellipsisLoc = SourceLocation()) { |
1031 | 72.1M | ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc, |
1032 | 72.1M | args, numArgs, syntax, ellipsisLoc); |
1033 | 72.1M | addAtEnd(attr); |
1034 | 72.1M | return attr; |
1035 | 72.1M | } |
1036 | | |
1037 | | /// Add availability attribute. |
1038 | | ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange, |
1039 | | IdentifierInfo *scopeName, SourceLocation scopeLoc, |
1040 | | IdentifierLoc *Param, const AvailabilityChange &introduced, |
1041 | | const AvailabilityChange &deprecated, |
1042 | | const AvailabilityChange &obsoleted, |
1043 | | SourceLocation unavailable, const Expr *MessageExpr, |
1044 | | ParsedAttr::Syntax syntax, SourceLocation strict, |
1045 | 6.00M | const Expr *ReplacementExpr) { |
1046 | 6.00M | ParsedAttr *attr = pool.create( |
1047 | 6.00M | attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated, |
1048 | 6.00M | obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr); |
1049 | 6.00M | addAtEnd(attr); |
1050 | 6.00M | return attr; |
1051 | 6.00M | } |
1052 | | |
1053 | | /// Add objc_bridge_related attribute. |
1054 | | ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange, |
1055 | | IdentifierInfo *scopeName, SourceLocation scopeLoc, |
1056 | | IdentifierLoc *Param1, IdentifierLoc *Param2, |
1057 | 475 | IdentifierLoc *Param3, ParsedAttr::Syntax syntax) { |
1058 | 475 | ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc, |
1059 | 475 | Param1, Param2, Param3, syntax); |
1060 | 475 | addAtEnd(attr); |
1061 | 475 | return attr; |
1062 | 475 | } |
1063 | | |
1064 | | /// Add type_tag_for_datatype attribute. |
1065 | | ParsedAttr * |
1066 | | addNewTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange, |
1067 | | IdentifierInfo *scopeName, SourceLocation scopeLoc, |
1068 | | IdentifierLoc *argumentKind, |
1069 | | ParsedType matchingCType, bool layoutCompatible, |
1070 | 169 | bool mustBeNull, ParsedAttr::Syntax syntax) { |
1071 | 169 | ParsedAttr *attr = pool.createTypeTagForDatatype( |
1072 | 169 | attrName, attrRange, scopeName, scopeLoc, argumentKind, matchingCType, |
1073 | 169 | layoutCompatible, mustBeNull, syntax); |
1074 | 169 | addAtEnd(attr); |
1075 | 169 | return attr; |
1076 | 169 | } |
1077 | | |
1078 | | /// Add an attribute with a single type argument. |
1079 | | ParsedAttr *addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange, |
1080 | | IdentifierInfo *scopeName, SourceLocation scopeLoc, |
1081 | | ParsedType typeArg, |
1082 | 14.6k | ParsedAttr::Syntax syntaxUsed) { |
1083 | 14.6k | ParsedAttr *attr = pool.createTypeAttribute(attrName, attrRange, scopeName, |
1084 | 14.6k | scopeLoc, typeArg, syntaxUsed); |
1085 | 14.6k | addAtEnd(attr); |
1086 | 14.6k | return attr; |
1087 | 14.6k | } |
1088 | | |
1089 | | /// Add microsoft __delspec(property) attribute. |
1090 | | ParsedAttr * |
1091 | | addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange, |
1092 | | IdentifierInfo *scopeName, SourceLocation scopeLoc, |
1093 | | IdentifierInfo *getterId, IdentifierInfo *setterId, |
1094 | 101 | ParsedAttr::Syntax syntaxUsed) { |
1095 | 101 | ParsedAttr *attr = |
1096 | 101 | pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc, |
1097 | 101 | getterId, setterId, syntaxUsed); |
1098 | 101 | addAtEnd(attr); |
1099 | 101 | return attr; |
1100 | 101 | } |
1101 | | |
1102 | | private: |
1103 | | mutable AttributePool pool; |
1104 | | }; |
1105 | | |
1106 | | /// These constants match the enumerated choices of |
1107 | | /// err_attribute_argument_n_type and err_attribute_argument_type. |
1108 | | enum AttributeArgumentNType { |
1109 | | AANT_ArgumentIntOrBool, |
1110 | | AANT_ArgumentIntegerConstant, |
1111 | | AANT_ArgumentString, |
1112 | | AANT_ArgumentIdentifier, |
1113 | | AANT_ArgumentConstantExpr, |
1114 | | AANT_ArgumentBuiltinFunction, |
1115 | | }; |
1116 | | |
1117 | | /// These constants match the enumerated choices of |
1118 | | /// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type. |
1119 | | enum AttributeDeclKind { |
1120 | | ExpectedFunction, |
1121 | | ExpectedUnion, |
1122 | | ExpectedVariableOrFunction, |
1123 | | ExpectedFunctionOrMethod, |
1124 | | ExpectedFunctionMethodOrBlock, |
1125 | | ExpectedFunctionMethodOrParameter, |
1126 | | ExpectedVariable, |
1127 | | ExpectedVariableOrField, |
1128 | | ExpectedVariableFieldOrTag, |
1129 | | ExpectedTypeOrNamespace, |
1130 | | ExpectedFunctionVariableOrClass, |
1131 | | ExpectedKernelFunction, |
1132 | | ExpectedFunctionWithProtoType, |
1133 | | }; |
1134 | | |
1135 | | inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |
1136 | 19.5k | const ParsedAttr &At) { |
1137 | 19.5k | DB.AddTaggedVal(reinterpret_cast<uint64_t>(At.getAttrName()), |
1138 | 19.5k | DiagnosticsEngine::ak_identifierinfo); |
1139 | 19.5k | return DB; |
1140 | 19.5k | } |
1141 | | |
1142 | | inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |
1143 | 86 | const ParsedAttr *At) { |
1144 | 86 | DB.AddTaggedVal(reinterpret_cast<uint64_t>(At->getAttrName()), |
1145 | 86 | DiagnosticsEngine::ak_identifierinfo); |
1146 | 86 | return DB; |
1147 | 86 | } |
1148 | | |
1149 | | /// AttributeCommonInfo has a non-explicit constructor which takes an |
1150 | | /// SourceRange as its only argument, this constructor has many uses so making |
1151 | | /// it explicit is hard. This constructor causes ambiguity with |
1152 | | /// DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, SourceRange R). |
1153 | | /// We use SFINAE to disable any conversion and remove any ambiguity. |
1154 | | template <typename ACI, |
1155 | | typename std::enable_if_t< |
1156 | | std::is_same<ACI, AttributeCommonInfo>::value, int> = 0> |
1157 | | inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |
1158 | 61 | const ACI &CI) { |
1159 | 61 | DB.AddTaggedVal(reinterpret_cast<uint64_t>(CI.getAttrName()), |
1160 | 61 | DiagnosticsEngine::ak_identifierinfo); |
1161 | 61 | return DB; |
1162 | 61 | } |
1163 | | |
1164 | | template <typename ACI, |
1165 | | typename std::enable_if_t< |
1166 | | std::is_same<ACI, AttributeCommonInfo>::value, int> = 0> |
1167 | | inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, |
1168 | | const ACI* CI) { |
1169 | | DB.AddTaggedVal(reinterpret_cast<uint64_t>(CI->getAttrName()), |
1170 | | DiagnosticsEngine::ak_identifierinfo); |
1171 | | return DB; |
1172 | | } |
1173 | | |
1174 | | } // namespace clang |
1175 | | |
1176 | | #endif // LLVM_CLANG_SEMA_PARSEDATTR_H |