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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

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