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

source code of clang/include/clang/Sema/ParsedAttr.h