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