clang  19.0.0git
ParsedAttr.cpp
Go to the documentation of this file.
1 //======- ParsedAttr.cpp --------------------------------------------------===//
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 implementation
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "clang/Sema/ParsedAttr.h"
14 #include "clang/AST/ASTContext.h"
17 #include "clang/Basic/TargetInfo.h"
19 #include "llvm/ADT/SmallString.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/StringRef.h"
22 #include <cassert>
23 #include <cstddef>
24 #include <utility>
25 
26 using namespace clang;
27 
29  IdentifierInfo *Ident) {
30  IdentifierLoc *Result = new (Ctx) IdentifierLoc;
31  Result->Loc = Loc;
32  Result->Ident = Ident;
33  return Result;
34 }
35 
36 size_t ParsedAttr::allocated_size() const {
37  if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
38  else if (IsTypeTagForDatatype)
40  else if (IsProperty)
42  else if (HasParsedType)
43  return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
45  detail::PropertyData>(0, 0, 0, 1, 0);
46  return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
48  detail::PropertyData>(NumArgs, 0, 0, 0, 0);
49 }
50 
52  // Go ahead and configure all the inline capacity. This is just a memset.
53  FreeLists.resize(InlineFreeListsCapacity);
54 }
56 
57 static size_t getFreeListIndexForSize(size_t size) {
58  assert(size >= sizeof(ParsedAttr));
59  assert((size % sizeof(void*)) == 0);
60  return ((size - sizeof(ParsedAttr)) / sizeof(void *));
61 }
62 
63 void *AttributeFactory::allocate(size_t size) {
64  // Check for a previously reclaimed attribute.
65  size_t index = getFreeListIndexForSize(size);
66  if (index < FreeLists.size() && !FreeLists[index].empty()) {
67  ParsedAttr *attr = FreeLists[index].back();
68  FreeLists[index].pop_back();
69  return attr;
70  }
71 
72  // Otherwise, allocate something new.
73  return Alloc.Allocate(size, alignof(AttributeFactory));
74 }
75 
76 void AttributeFactory::deallocate(ParsedAttr *Attr) {
77  size_t size = Attr->allocated_size();
78  size_t freeListIndex = getFreeListIndexForSize(size);
79 
80  // Expand FreeLists to the appropriate size, if required.
81  if (freeListIndex >= FreeLists.size())
82  FreeLists.resize(freeListIndex + 1);
83 
84 #ifndef NDEBUG
85  // In debug mode, zero out the attribute to help find memory overwriting.
86  memset(Attr, 0, size);
87 #endif
88 
89  // Add 'Attr' to the appropriate free-list.
90  FreeLists[freeListIndex].push_back(Attr);
91 }
92 
93 void AttributeFactory::reclaimPool(AttributePool &cur) {
94  for (ParsedAttr *AL : cur.Attrs)
95  deallocate(AL);
96 }
97 
98 void AttributePool::takePool(AttributePool &pool) {
99  Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
100  pool.Attrs.clear();
101 }
102 
104  assert(&Pool != this && "AttributePool can't take attributes from itself");
105  llvm::for_each(List.AttrList, [&Pool](ParsedAttr *A) { Pool.remove(A); });
106  Attrs.insert(Attrs.end(), List.AttrList.begin(), List.AttrList.end());
107 }
108 
109 namespace {
110 
111 #include "clang/Sema/AttrParsedAttrImpl.inc"
112 
113 } // namespace
114 
116  // If we have a ParsedAttrInfo for this ParsedAttr then return that.
117  if ((size_t)A.getParsedKind() < std::size(AttrInfoMap))
118  return *AttrInfoMap[A.getParsedKind()];
119 
120  // If this is an ignored attribute then return an appropriate ParsedAttrInfo.
121  static const ParsedAttrInfo IgnoredParsedAttrInfo(
124  return IgnoredParsedAttrInfo;
125 
126  // Otherwise this may be an attribute defined by a plugin.
127 
128  // Search for a ParsedAttrInfo whose name and syntax match.
129  std::string FullName = A.getNormalizedFullName();
130  AttributeCommonInfo::Syntax SyntaxUsed = A.getSyntax();
132  SyntaxUsed = AttributeCommonInfo::AS_Keyword;
133 
134  for (auto &Ptr : getAttributePluginInstances())
135  if (Ptr->hasSpelling(SyntaxUsed, FullName))
136  return *Ptr;
137 
138  // If we failed to find a match then return a default ParsedAttrInfo.
139  static const ParsedAttrInfo DefaultParsedAttrInfo(
141  return DefaultParsedAttrInfo;
142 }
143 
145  return llvm::ArrayRef(AttrInfoMap);
146 }
147 
148 unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; }
149 
150 unsigned ParsedAttr::getMaxArgs() const {
151  return getMinArgs() + getInfo().OptArgs;
152 }
153 
155  return getInfo().NumArgMembers;
156 }
157 
159  return getInfo().HasCustomParsing;
160 }
161 
162 bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
163  return getInfo().diagAppertainsToDecl(S, *this, D);
164 }
165 
166 bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Stmt *St) const {
167  return getInfo().diagAppertainsToStmt(S, *this, St);
168 }
169 
171  return getInfo().diagMutualExclusion(S, *this, D);
172 }
173 
175  attr::SubjectMatchRule MatchRule) const {
176  return checkAttributeMatchRuleAppliesTo(D, MatchRule);
177 }
178 
180  const LangOptions &LangOpts,
181  SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
182  const {
183  return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts);
184 }
185 
187  if (getInfo().acceptsLangOpts(S.getLangOpts()))
188  return true;
189  S.Diag(getLoc(), diag::warn_attribute_ignored) << *this;
190  return false;
191 }
192 
194  return getInfo().IsTargetSpecific;
195 }
196 
197 bool ParsedAttr::isTypeAttr() const { return getInfo().IsType; }
198 
199 bool ParsedAttr::isStmtAttr() const { return getInfo().IsStmt; }
200 
202  Kind K = getParsedKind();
203 
204  // If the attribute has a target-specific spelling, check that it exists.
205  // Only call this if the attr is not ignored/unknown. For most targets, this
206  // function just returns true.
207  bool HasSpelling = K != IgnoredAttribute && K != UnknownAttribute &&
209  bool TargetSpecificSpellingExists =
210  !HasSpelling ||
212 
213  return getInfo().existsInTarget(Target) && TargetSpecificSpellingExists;
214 }
215 
217 
220 }
221 
224 }
225 
228  // The appurtenance rules are applied strictly for all regular keyword
229  // atributes.
230  return false;
231 
232  assert(isStandardAttributeSyntax());
233 
234  // We have historically allowed some type attributes with standard attribute
235  // syntax to slide to the decl-specifier-seq, so we have to keep supporting
236  // it. This property is consciously not defined as a flag in Attr.td because
237  // we don't want new attributes to specify it.
238  //
239  // Note: No new entries should be added to this list. Entries should be
240  // removed from this list after a suitable deprecation period, provided that
241  // there are no compatibility considerations with other compilers. If
242  // possible, we would like this list to go away entirely.
243  switch (getParsedKind()) {
244  case AT_AddressSpace:
245  case AT_OpenCLPrivateAddressSpace:
246  case AT_OpenCLGlobalAddressSpace:
247  case AT_OpenCLGlobalDeviceAddressSpace:
248  case AT_OpenCLGlobalHostAddressSpace:
249  case AT_OpenCLLocalAddressSpace:
250  case AT_OpenCLConstantAddressSpace:
251  case AT_OpenCLGenericAddressSpace:
252  case AT_NeonPolyVectorType:
253  case AT_NeonVectorType:
254  case AT_ArmMveStrictPolymorphism:
255  case AT_BTFTypeTag:
256  case AT_ObjCGC:
257  case AT_MatrixType:
258  return true;
259  default:
260  return false;
261  }
262 }
263 
265 
268 }
269 
271  // If the attribute has the maximum number of optional arguments, we will
272  // claim that as being variadic. If we someday get an attribute that
273  // legitimately bumps up against that maximum, we can use another bit to track
274  // whether it's truly variadic or not.
275  return getInfo().OptArgs == 15;
276 }
277 
278 bool ParsedAttr::isParamExpr(size_t N) const {
279  return getInfo().isParamExpr(N);
280 }
281 
283  ::handleAttrWithDelayedArgs(S, D, *this);
284 }
285 
286 static unsigned getNumAttributeArgs(const ParsedAttr &AL) {
287  // FIXME: Include the type in the argument list.
288  return AL.getNumArgs() + AL.hasParsedType();
289 }
290 
291 template <typename Compare>
292 static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL,
293  unsigned Num, unsigned Diag,
294  Compare Comp) {
295  if (Comp(getNumAttributeArgs(AL), Num)) {
296  S.Diag(AL.getLoc(), Diag) << AL << Num;
297  return false;
298  }
299  return true;
300 }
301 
302 bool ParsedAttr::checkExactlyNumArgs(Sema &S, unsigned Num) const {
303  return checkAttributeNumArgsImpl(S, *this, Num,
304  diag::err_attribute_wrong_number_arguments,
305  std::not_equal_to<unsigned>());
306 }
307 bool ParsedAttr::checkAtLeastNumArgs(Sema &S, unsigned Num) const {
308  return checkAttributeNumArgsImpl(S, *this, Num,
309  diag::err_attribute_too_few_arguments,
310  std::less<unsigned>());
311 }
312 bool ParsedAttr::checkAtMostNumArgs(Sema &S, unsigned Num) const {
313  return checkAttributeNumArgsImpl(S, *this, Num,
314  diag::err_attribute_too_many_arguments,
315  std::greater<unsigned>());
316 }
317 
319  ParsedAttributes &Second,
320  ParsedAttributes &Result) {
321  // Note that takeAllFrom() puts the attributes at the beginning of the list,
322  // so to obtain the correct ordering, we add `Second`, then `First`.
323  Result.takeAllFrom(Second);
324  Result.takeAllFrom(First);
325  if (First.Range.getBegin().isValid())
326  Result.Range.setBegin(First.Range.getBegin());
327  else
328  Result.Range.setBegin(Second.Range.getBegin());
329  if (Second.Range.getEnd().isValid())
330  Result.Range.setEnd(Second.Range.getEnd());
331  else
332  Result.Range.setEnd(First.Range.getEnd());
333 }
Defines the clang::ASTContext interface.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
llvm::MachO::Target Target
Definition: MachO.h:50
static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL, unsigned Num, unsigned Diag, Compare Comp)
Definition: ParsedAttr.cpp:292
static size_t getFreeListIndexForSize(size_t size)
Definition: ParsedAttr.cpp:57
static unsigned getNumAttributeArgs(const ParsedAttr &AL)
Definition: ParsedAttr.cpp:286
SourceLocation Loc
Definition: SemaObjC.cpp:755
__DEVICE__ void * memset(void *__a, int __b, size_t __c)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:185
Attr - This represents one attribute.
Definition: Attr.h:46
std::string getNormalizedFullName() const
Gets the normalized full name, which consists of both scope and name and with surrounding underscores...
Definition: Attributes.cpp:155
Syntax
The style used to specify an attribute.
@ AS_Keyword
__ptr16, alignas(...), etc.
@ AS_ContextSensitiveKeyword
Context-sensitive version of a keyword attribute.
unsigned getAttributeSpellingListIndex() const
SourceLocation getLoc() const
bool isStandardAttributeSyntax() const
The attribute is spelled [[]] in either C or C++ mode, including standard attributes spelled with a k...
A factory, from which one makes pools, from which one creates individual attributes which are dealloc...
Definition: ParsedAttr.h:644
void takeFrom(ParsedAttributesView &List, AttributePool &Pool)
Removes the attributes from List, which are owned by Pool, and adds them at the end of this Attribute...
Definition: ParsedAttr.cpp:103
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
One of these records is kept for each identifier that is lexed.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:482
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:129
bool isTargetSpecificAttr() const
Definition: ParsedAttr.cpp:193
bool hasCustomParsing() const
Definition: ParsedAttr.cpp:158
unsigned getSemanticSpelling() const
If the parsed attribute has a semantic equivalent, and it would have a semantic Spelling enumeration ...
Definition: ParsedAttr.cpp:266
bool appliesToDecl(const Decl *D, attr::SubjectMatchRule MatchRule) const
Definition: ParsedAttr.cpp:174
bool supportsNonconformingLambdaSyntax() const
Definition: ParsedAttr.cpp:222
bool isKnownToGCC() const
Definition: ParsedAttr.cpp:216
bool existsInTarget(const TargetInfo &Target) const
Definition: ParsedAttr.cpp:201
unsigned getMinArgs() const
Definition: ParsedAttr.cpp:148
bool checkExactlyNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has exactly as many args as Num.
Definition: ParsedAttr.cpp:302
bool hasParsedType() const
Definition: ParsedAttr.h:352
bool hasVariadicArg() const
Definition: ParsedAttr.cpp:270
void handleAttrWithDelayedArgs(Sema &S, Decl *D) const
Definition: ParsedAttr.cpp:282
const ParsedAttrInfo & getInfo() const
Definition: ParsedAttr.h:635
bool diagnoseMutualExclusion(class Sema &S, const Decl *D) const
Definition: ParsedAttr.cpp:170
bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const
Definition: ParsedAttr.cpp:162
bool acceptsExprPack() const
Definition: ParsedAttr.cpp:264
void getMatchRules(const LangOptions &LangOpts, SmallVectorImpl< std::pair< attr::SubjectMatchRule, bool >> &MatchRules) const
Definition: ParsedAttr.cpp:179
bool isTypeAttr() const
Definition: ParsedAttr.cpp:197
bool isSupportedByPragmaAttribute() const
Definition: ParsedAttr.cpp:218
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
Definition: ParsedAttr.h:386
bool checkAtLeastNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has at least as many args as Num.
Definition: ParsedAttr.cpp:307
unsigned getNumArgMembers() const
Definition: ParsedAttr.cpp:154
bool isStmtAttr() const
Definition: ParsedAttr.cpp:199
unsigned getMaxArgs() const
Definition: ParsedAttr.cpp:150
bool slidesFromDeclToDeclSpecLegacyBehavior() const
Returns whether a [[]] attribute, if specified ahead of a declaration, should be applied to the decl-...
Definition: ParsedAttr.cpp:226
bool isParamExpr(size_t N) const
Definition: ParsedAttr.cpp:278
bool diagnoseLangOpts(class Sema &S) const
Definition: ParsedAttr.cpp:186
bool checkAtMostNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has at most as many args as Num.
Definition: ParsedAttr.cpp:312
ParsedAttributes - A collection of parsed attributes.
Definition: ParsedAttr.h:963
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:57
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:462
const LangOptions & getLangOpts() const
Definition: Sema.h:519
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getEnd() const
SourceLocation getBegin() const
Stmt - This represents one statement.
Definition: Stmt.h:84
Exposes information about the current target.
Definition: TargetInfo.h:218
Defines the clang::TargetInfo interface.
const internal::VariadicAllOfMatcher< Attr > attr
Matches attributes.
SubjectMatchRule
A list of all the recognized kinds of attributes.
ComparisonCategoryResult Compare(const T &X, const T &Y)
Helper to compare two comparable types.
Definition: Primitives.h:25
bool Comp(InterpState &S, CodePtr OpPC)
1) Pops the value from the stack.
Definition: Interp.h:709
The JSON file list parser is used to communicate input to InstallAPI.
llvm::PointerUnion< Expr *, IdentifierLoc * > ArgsUnion
A union of the various pointer types that can be passed to an ParsedAttr as an argument.
Definition: ParsedAttr.h:113
void takeAndConcatenateAttrs(ParsedAttributes &First, ParsedAttributes &Second, ParsedAttributes &Result)
Consumes the attributes from First and Second and concatenates them into Result.
Definition: ParsedAttr.cpp:318
const std::list< std::unique_ptr< ParsedAttrInfo > > & getAttributePluginInstances()
OpaquePtr< QualType > ParsedType
An opaque type for threading parsed type information through the parser.
Definition: Ownership.h:229
Wraps an identifier and optional source location for the identifier.
Definition: ParsedAttr.h:103
SourceLocation Loc
Definition: ParsedAttr.h:104
IdentifierInfo * Ident
Definition: ParsedAttr.h:105
static IdentifierLoc * create(ASTContext &Ctx, SourceLocation Loc, IdentifierInfo *Ident)
Definition: ParsedAttr.cpp:28
unsigned SupportsNonconformingLambdaSyntax
True if this attribute supports a nonconforming behavior when applied to a lambda in the type positio...
static ArrayRef< const ParsedAttrInfo * > getAllBuiltin()
Definition: ParsedAttr.cpp:144
unsigned IsKnownToGCC
True if this attribute has any spellings that are known to gcc.
unsigned HasCustomParsing
True if the parsing does not match the semantic content.
unsigned IsType
True if this attribute applies to types.
unsigned IsTargetSpecific
True if this attribute is only available for certain targets.
unsigned IsSupportedByPragmaAttribute
True if this attribute is supported by #pragma clang attribute.
unsigned NumArgs
The number of required arguments of this attribute.
virtual bool diagAppertainsToStmt(Sema &S, const ParsedAttr &Attr, const Stmt *St) const
Check if this attribute appertains to St, and issue a diagnostic if not.
virtual unsigned spellingIndexToSemanticSpelling(const ParsedAttr &Attr) const
Convert the spelling index of Attr to a semantic spelling enum value.
static const ParsedAttrInfo & get(const AttributeCommonInfo &A)
Definition: ParsedAttr.cpp:115
virtual bool isParamExpr(size_t N) const
Returns true if the specified parameter index for this attribute in Attr.td is an ExprArgument or Var...
virtual void getPragmaAttributeMatchRules(llvm::SmallVectorImpl< std::pair< attr::SubjectMatchRule, bool >> &Rules, const LangOptions &LangOpts) const
Populate Rules with the match rules of this attribute.
virtual bool existsInTarget(const TargetInfo &Target) const
Check if this attribute is allowed when compiling for the given target.
virtual bool spellingExistsInTarget(const TargetInfo &Target, const unsigned SpellingListIndex) const
Check if this attribute's spelling is allowed when compiling for the given target.
virtual bool diagAppertainsToDecl(Sema &S, const ParsedAttr &Attr, const Decl *D) const
Check if this attribute appertains to D, and issue a diagnostic if not.
unsigned OptArgs
The number of optional arguments of this attributes.
virtual bool diagMutualExclusion(Sema &S, const ParsedAttr &A, const Decl *D) const
Check if the given attribute is mutually exclusive with other attributes already applied to the given...
unsigned IsStmt
True if this attribute applies to statements.
unsigned NumArgMembers
The number of non-fake arguments specified in the attribute definition.
Describes the trailing object for Availability attribute in ParsedAttr.
Definition: ParsedAttr.h:68