clang 22.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
19#include "llvm/ADT/SmallVector.h"
20#include <cassert>
21#include <cstddef>
22#include <utility>
23
24using namespace clang;
25
26size_t ParsedAttr::allocated_size() const {
27 if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
28 else if (IsTypeTagForDatatype)
30 else if (IsProperty)
32 else if (HasParsedType)
33 return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
35 detail::PropertyData>(0, 0, 0, 1, 0);
36 return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
38 detail::PropertyData>(NumArgs, 0, 0, 0, 0);
39}
40
42 // Go ahead and configure all the inline capacity. This is just a memset.
43 FreeLists.resize(InlineFreeListsCapacity);
44}
46
47static size_t getFreeListIndexForSize(size_t size) {
48 assert(size >= sizeof(ParsedAttr));
49 assert((size % sizeof(void*)) == 0);
50 return ((size - sizeof(ParsedAttr)) / sizeof(void *));
51}
52
53void *AttributeFactory::allocate(size_t size) {
54 // Check for a previously reclaimed attribute.
55 size_t index = getFreeListIndexForSize(size);
56 if (index < FreeLists.size() && !FreeLists[index].empty()) {
57 ParsedAttr *attr = FreeLists[index].pop_back_val();
58 return attr;
59 }
60
61 // Otherwise, allocate something new.
62 return Alloc.Allocate(size, alignof(AttributeFactory));
63}
64
65void AttributeFactory::deallocate(ParsedAttr *Attr) {
66 size_t size = Attr->allocated_size();
67 size_t freeListIndex = getFreeListIndexForSize(size);
68
69 // Expand FreeLists to the appropriate size, if required.
70 if (freeListIndex >= FreeLists.size())
71 FreeLists.resize(freeListIndex + 1);
72
73#ifndef NDEBUG
74 // In debug mode, zero out the attribute to help find memory overwriting.
75 memset(Attr, 0, size);
76#endif
77
78 // Add 'Attr' to the appropriate free-list.
79 FreeLists[freeListIndex].push_back(Attr);
80}
81
82void AttributeFactory::reclaimPool(AttributePool &cur) {
83 for (ParsedAttr *AL : cur.Attrs)
84 deallocate(AL);
85}
86
87void AttributePool::takePool(AttributePool &pool) {
88 llvm::append_range(Attrs, pool.Attrs);
89 pool.Attrs.clear();
90}
91
93 assert(&Pool != this && "AttributePool can't take attributes from itself");
94 for (ParsedAttr *A : List.AttrList)
95 Pool.remove(A);
96 llvm::append_range(Attrs, List.AttrList);
97}
98
99namespace {
100
101#include "clang/Sema/AttrParsedAttrImpl.inc"
102
103} // namespace
104
106 // If we have a ParsedAttrInfo for this ParsedAttr then return that.
107 if ((size_t)A.getParsedKind() < std::size(AttrInfoMap))
108 return *AttrInfoMap[A.getParsedKind()];
109
110 // If this is an ignored attribute then return an appropriate ParsedAttrInfo.
111 static const ParsedAttrInfo IgnoredParsedAttrInfo(
114 return IgnoredParsedAttrInfo;
115
116 // Otherwise this may be an attribute defined by a plugin.
117
118 // Search for a ParsedAttrInfo whose name and syntax match.
119 std::string FullName = A.getNormalizedFullName();
120 AttributeCommonInfo::Syntax SyntaxUsed = A.getSyntax();
123
124 for (auto &Ptr : getAttributePluginInstances())
125 if (Ptr->hasSpelling(SyntaxUsed, FullName))
126 return *Ptr;
127
128 // If we failed to find a match then return a default ParsedAttrInfo.
129 static const ParsedAttrInfo DefaultParsedAttrInfo(
131 return DefaultParsedAttrInfo;
132}
133
135 return llvm::ArrayRef(AttrInfoMap);
136}
137
138unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; }
139
140unsigned ParsedAttr::getMaxArgs() const {
141 return getMinArgs() + getInfo().OptArgs;
142}
143
145 return getInfo().NumArgMembers;
146}
147
149 return getInfo().HasCustomParsing;
150}
151
153 return getInfo().diagAppertainsToDecl(S, *this, D);
154}
155
156bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Stmt *St) const {
157 return getInfo().diagAppertainsToStmt(S, *this, St);
158}
159
161 return getInfo().diagMutualExclusion(S, *this, D);
162}
163
165 attr::SubjectMatchRule MatchRule) const {
166 return checkAttributeMatchRuleAppliesTo(D, MatchRule);
167}
168
170 const LangOptions &LangOpts,
171 SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
172 const {
173 return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts);
174}
175
177 if (getInfo().acceptsLangOpts(S.getLangOpts()))
178 return true;
179 S.Diag(getLoc(), diag::warn_attribute_ignored) << *this;
180 return false;
181}
182
184 return getInfo().IsTargetSpecific;
185}
186
187bool ParsedAttr::isTypeAttr() const { return getInfo().IsType; }
188
189bool ParsedAttr::isStmtAttr() const { return getInfo().IsStmt; }
190
192 Kind K = getParsedKind();
193
194 // If the attribute has a target-specific spelling, check that it exists.
195 // Only call this if the attr is not ignored/unknown. For most targets, this
196 // function just returns true.
197 bool HasSpelling = K != IgnoredAttribute && K != UnknownAttribute &&
199 bool TargetSpecificSpellingExists =
200 !HasSpelling ||
202
203 return getInfo().existsInTarget(Target) && TargetSpecificSpellingExists;
204}
205
207
210}
211
214 // The appurtenance rules are applied strictly for all regular keyword
215 // atributes.
216 return false;
217
219
220 // We have historically allowed some type attributes with standard attribute
221 // syntax to slide to the decl-specifier-seq, so we have to keep supporting
222 // it. This property is consciously not defined as a flag in Attr.td because
223 // we don't want new attributes to specify it.
224 //
225 // Note: No new entries should be added to this list. Entries should be
226 // removed from this list after a suitable deprecation period, provided that
227 // there are no compatibility considerations with other compilers. If
228 // possible, we would like this list to go away entirely.
229 switch (getParsedKind()) {
230 case AT_AddressSpace:
231 case AT_OpenCLPrivateAddressSpace:
232 case AT_OpenCLGlobalAddressSpace:
233 case AT_OpenCLGlobalDeviceAddressSpace:
234 case AT_OpenCLGlobalHostAddressSpace:
235 case AT_OpenCLLocalAddressSpace:
236 case AT_OpenCLConstantAddressSpace:
237 case AT_OpenCLGenericAddressSpace:
238 case AT_NeonPolyVectorType:
239 case AT_NeonVectorType:
240 case AT_ArmMveStrictPolymorphism:
241 case AT_BTFTypeTag:
242 case AT_ObjCGC:
243 case AT_MatrixType:
244 return true;
245 default:
246 return false;
247 }
248}
249
251
254}
255
257 // If the attribute has the maximum number of optional arguments, we will
258 // claim that as being variadic. If we someday get an attribute that
259 // legitimately bumps up against that maximum, we can use another bit to track
260 // whether it's truly variadic or not.
261 return getInfo().OptArgs == 15;
262}
263
264bool ParsedAttr::isParamExpr(size_t N) const {
265 return getInfo().isParamExpr(N);
266}
267
270}
271
272static unsigned getNumAttributeArgs(const ParsedAttr &AL) {
273 // FIXME: Include the type in the argument list.
274 return AL.getNumArgs() + AL.hasParsedType();
275}
276
277template <typename Compare>
278static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL,
279 unsigned Num, unsigned Diag,
280 Compare Comp) {
281 if (Comp(getNumAttributeArgs(AL), Num)) {
282 S.Diag(AL.getLoc(), Diag) << AL << Num;
283 return false;
284 }
285 return true;
286}
287
288bool ParsedAttr::checkExactlyNumArgs(Sema &S, unsigned Num) const {
289 return checkAttributeNumArgsImpl(S, *this, Num,
290 diag::err_attribute_wrong_number_arguments,
291 std::not_equal_to<unsigned>());
292}
293bool ParsedAttr::checkAtLeastNumArgs(Sema &S, unsigned Num) const {
294 return checkAttributeNumArgsImpl(S, *this, Num,
295 diag::err_attribute_too_few_arguments,
296 std::less<unsigned>());
297}
298bool ParsedAttr::checkAtMostNumArgs(Sema &S, unsigned Num) const {
299 return checkAttributeNumArgsImpl(S, *this, Num,
300 diag::err_attribute_too_many_arguments,
301 std::greater<unsigned>());
302}
303
305 ParsedAttributes &&Second) {
306
307 First.takeAllAtEndFrom(Second);
308
309 if (!First.Range.getBegin().isValid())
310 First.Range.setBegin(Second.Range.getBegin());
311
312 if (Second.Range.getEnd().isValid())
313 First.Range.setEnd(Second.Range.getEnd());
314}
Defines the clang::ASTContext interface.
const Decl * D
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:51
static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL, unsigned Num, unsigned Diag, Compare Comp)
Definition: ParsedAttr.cpp:278
static size_t getFreeListIndexForSize(size_t size)
Definition: ParsedAttr.cpp:47
static unsigned getNumAttributeArgs(const ParsedAttr &AL)
Definition: ParsedAttr.cpp:272
int32_t FullName
Definition: SemaARM.cpp:1180
__DEVICE__ void * memset(void *__a, int __b, size_t __c)
Attr - This represents one attribute.
Definition: Attr.h:44
std::string getNormalizedFullName() const
Gets the normalized full name, which consists of both scope and name and with surrounding underscores...
Definition: Attributes.cpp:206
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:622
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:92
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:434
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:119
bool isTargetSpecificAttr() const
Definition: ParsedAttr.cpp:183
bool hasCustomParsing() const
Definition: ParsedAttr.cpp:148
unsigned getSemanticSpelling() const
If the parsed attribute has a semantic equivalent, and it would have a semantic Spelling enumeration ...
Definition: ParsedAttr.cpp:252
bool appliesToDecl(const Decl *D, attr::SubjectMatchRule MatchRule) const
Definition: ParsedAttr.cpp:164
bool isKnownToGCC() const
Definition: ParsedAttr.cpp:206
bool existsInTarget(const TargetInfo &Target) const
Definition: ParsedAttr.cpp:191
unsigned getMinArgs() const
Definition: ParsedAttr.cpp:138
bool checkExactlyNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has exactly as many args as Num.
Definition: ParsedAttr.cpp:288
bool hasParsedType() const
Definition: ParsedAttr.h:337
bool hasVariadicArg() const
Definition: ParsedAttr.cpp:256
const ParsedAttrInfo & getInfo() const
Definition: ParsedAttr.h:613
void handleAttrWithDelayedArgs(Sema &S, Decl *D) const
Definition: ParsedAttr.cpp:268
bool diagnoseMutualExclusion(class Sema &S, const Decl *D) const
Definition: ParsedAttr.cpp:160
bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const
Definition: ParsedAttr.cpp:152
bool acceptsExprPack() const
Definition: ParsedAttr.cpp:250
bool isTypeAttr() const
Definition: ParsedAttr.cpp:187
bool isSupportedByPragmaAttribute() const
Definition: ParsedAttr.cpp:208
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
Definition: ParsedAttr.h:371
bool checkAtLeastNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has at least as many args as Num.
Definition: ParsedAttr.cpp:293
unsigned getNumArgMembers() const
Definition: ParsedAttr.cpp:144
bool isStmtAttr() const
Definition: ParsedAttr.cpp:189
unsigned getMaxArgs() const
Definition: ParsedAttr.cpp:140
bool slidesFromDeclToDeclSpecLegacyBehavior() const
Returns whether a [[]] attribute, if specified ahead of a declaration, should be applied to the decl-...
Definition: ParsedAttr.cpp:212
void getMatchRules(const LangOptions &LangOpts, SmallVectorImpl< std::pair< attr::SubjectMatchRule, bool > > &MatchRules) const
Definition: ParsedAttr.cpp:169
bool isParamExpr(size_t N) const
Definition: ParsedAttr.cpp:264
bool diagnoseLangOpts(class Sema &S) const
Definition: ParsedAttr.cpp:176
bool checkAtMostNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has at most as many args as Num.
Definition: ParsedAttr.cpp:298
ParsedAttributes - A collection of parsed attributes.
Definition: ParsedAttr.h:937
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:61
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:850
const LangOptions & getLangOpts() const
Definition: Sema.h:911
Stmt - This represents one statement.
Definition: Stmt.h:85
Exposes information about the current target.
Definition: TargetInfo.h:226
Defines the clang::TargetInfo interface.
const internal::VariadicAllOfMatcher< Attr > attr
Matches attributes.
SubjectMatchRule
A list of all the recognized kinds of attributes.
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:103
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:230
void takeAndConcatenateAttrs(ParsedAttributes &First, ParsedAttributes &&Second)
Consumes the attributes from Second and concatenates them at the end of First.
Definition: ParsedAttr.cpp:304
static ArrayRef< const ParsedAttrInfo * > getAllBuiltin()
Definition: ParsedAttr.cpp:134
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:105
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:67