clang 18.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/SmallString.h"
20#include "llvm/ADT/SmallVector.h"
21#include "llvm/ADT/StringRef.h"
22#include <cassert>
23#include <cstddef>
24#include <utility>
25
26using namespace clang;
27
29 IdentifierInfo *Ident) {
31 Result->Loc = Loc;
32 Result->Ident = Ident;
33 return Result;
34}
35
36size_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
57static 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
63void *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
76void 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
93void AttributeFactory::reclaimPool(AttributePool &cur) {
94 for (ParsedAttr *AL : cur.Attrs)
95 deallocate(AL);
96}
97
98void AttributePool::takePool(AttributePool &pool) {
99 Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
100 pool.Attrs.clear();
101}
102
103namespace {
104
105#include "clang/Sema/AttrParsedAttrImpl.inc"
106
107} // namespace
108
110 // If we have a ParsedAttrInfo for this ParsedAttr then return that.
111 if ((size_t)A.getParsedKind() < std::size(AttrInfoMap))
112 return *AttrInfoMap[A.getParsedKind()];
113
114 // If this is an ignored attribute then return an appropriate ParsedAttrInfo.
115 static const ParsedAttrInfo IgnoredParsedAttrInfo(
118 return IgnoredParsedAttrInfo;
119
120 // Otherwise this may be an attribute defined by a plugin.
121
122 // Search for a ParsedAttrInfo whose name and syntax match.
123 std::string FullName = A.getNormalizedFullName();
124 AttributeCommonInfo::Syntax SyntaxUsed = A.getSyntax();
127
128 for (auto &Ptr : getAttributePluginInstances())
129 if (Ptr->hasSpelling(SyntaxUsed, FullName))
130 return *Ptr;
131
132 // If we failed to find a match then return a default ParsedAttrInfo.
133 static const ParsedAttrInfo DefaultParsedAttrInfo(
135 return DefaultParsedAttrInfo;
136}
137
139 return llvm::ArrayRef(AttrInfoMap);
140}
141
142unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; }
143
144unsigned ParsedAttr::getMaxArgs() const {
145 return getMinArgs() + getInfo().OptArgs;
146}
147
149 return getInfo().NumArgMembers;
150}
151
153 return getInfo().HasCustomParsing;
154}
155
157 return getInfo().diagAppertainsToDecl(S, *this, D);
158}
159
160bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Stmt *St) const {
161 return getInfo().diagAppertainsToStmt(S, *this, St);
162}
163
165 return getInfo().diagMutualExclusion(S, *this, D);
166}
167
169 attr::SubjectMatchRule MatchRule) const {
170 return checkAttributeMatchRuleAppliesTo(D, MatchRule);
171}
172
174 const LangOptions &LangOpts,
175 SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
176 const {
177 return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts);
178}
179
181 if (getInfo().acceptsLangOpts(S.getLangOpts()))
182 return true;
183 S.Diag(getLoc(), diag::warn_attribute_ignored) << *this;
184 return false;
185}
186
188 return getInfo().IsTargetSpecific;
189}
190
191bool ParsedAttr::isTypeAttr() const { return getInfo().IsType; }
192
193bool ParsedAttr::isStmtAttr() const { return getInfo().IsStmt; }
194
196 return getInfo().existsInTarget(Target) &&
199}
200
202
205}
206
209 // The appurtenance rules are applied strictly for all regular keyword
210 // atributes.
211 return false;
212
214
215 // We have historically allowed some type attributes with standard attribute
216 // syntax to slide to the decl-specifier-seq, so we have to keep supporting
217 // it. This property is consciously not defined as a flag in Attr.td because
218 // we don't want new attributes to specify it.
219 //
220 // Note: No new entries should be added to this list. Entries should be
221 // removed from this list after a suitable deprecation period, provided that
222 // there are no compatibility considerations with other compilers. If
223 // possible, we would like this list to go away entirely.
224 switch (getParsedKind()) {
225 case AT_AddressSpace:
226 case AT_OpenCLPrivateAddressSpace:
227 case AT_OpenCLGlobalAddressSpace:
228 case AT_OpenCLGlobalDeviceAddressSpace:
229 case AT_OpenCLGlobalHostAddressSpace:
230 case AT_OpenCLLocalAddressSpace:
231 case AT_OpenCLConstantAddressSpace:
232 case AT_OpenCLGenericAddressSpace:
233 case AT_NeonPolyVectorType:
234 case AT_NeonVectorType:
235 case AT_ArmMveStrictPolymorphism:
236 case AT_BTFTypeTag:
237 case AT_ObjCGC:
238 case AT_MatrixType:
239 return true;
240 default:
241 return false;
242 }
243}
244
246
249}
250
252 // If the attribute has the maximum number of optional arguments, we will
253 // claim that as being variadic. If we someday get an attribute that
254 // legitimately bumps up against that maximum, we can use another bit to track
255 // whether it's truly variadic or not.
256 return getInfo().OptArgs == 15;
257}
258
259bool ParsedAttr::isParamExpr(size_t N) const {
260 return getInfo().isParamExpr(N);
261}
262
264 ::handleAttrWithDelayedArgs(S, D, *this);
265}
266
267static unsigned getNumAttributeArgs(const ParsedAttr &AL) {
268 // FIXME: Include the type in the argument list.
269 return AL.getNumArgs() + AL.hasParsedType();
270}
271
272template <typename Compare>
273static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL,
274 unsigned Num, unsigned Diag,
275 Compare Comp) {
276 if (Comp(getNumAttributeArgs(AL), Num)) {
277 S.Diag(AL.getLoc(), Diag) << AL << Num;
278 return false;
279 }
280 return true;
281}
282
283bool ParsedAttr::checkExactlyNumArgs(Sema &S, unsigned Num) const {
284 return checkAttributeNumArgsImpl(S, *this, Num,
285 diag::err_attribute_wrong_number_arguments,
286 std::not_equal_to<unsigned>());
287}
288bool ParsedAttr::checkAtLeastNumArgs(Sema &S, unsigned Num) const {
289 return checkAttributeNumArgsImpl(S, *this, Num,
290 diag::err_attribute_too_few_arguments,
291 std::less<unsigned>());
292}
293bool ParsedAttr::checkAtMostNumArgs(Sema &S, unsigned Num) const {
294 return checkAttributeNumArgsImpl(S, *this, Num,
295 diag::err_attribute_too_many_arguments,
296 std::greater<unsigned>());
297}
298
300 ParsedAttributes &Second,
302 // Note that takeAllFrom() puts the attributes at the beginning of the list,
303 // so to obtain the correct ordering, we add `Second`, then `First`.
304 Result.takeAllFrom(Second);
305 Result.takeAllFrom(First);
306 if (First.Range.getBegin().isValid())
307 Result.Range.setBegin(First.Range.getBegin());
308 else
309 Result.Range.setBegin(Second.Range.getBegin());
310 if (Second.Range.getEnd().isValid())
311 Result.Range.setEnd(Second.Range.getEnd());
312 else
313 Result.Range.setEnd(First.Range.getEnd());
314}
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.
static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL, unsigned Num, unsigned Diag, Compare Comp)
Definition: ParsedAttr.cpp:273
static size_t getFreeListIndexForSize(size_t size)
Definition: ParsedAttr.cpp:57
static unsigned getNumAttributeArgs(const ParsedAttr &AL)
Definition: ParsedAttr.cpp:267
__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:182
Attr - This represents one attribute.
Definition: Attr.h:40
std::string getNormalizedFullName() const
Gets the normalized full name, which consists of both scope and name and with surrounding underscores...
Definition: Attributes.cpp:147
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:619
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:83
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:83
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:124
bool isTargetSpecificAttr() const
Definition: ParsedAttr.cpp:187
bool hasCustomParsing() const
Definition: ParsedAttr.cpp:152
unsigned getSemanticSpelling() const
If the parsed attribute has a semantic equivalent, and it would have a semantic Spelling enumeration ...
Definition: ParsedAttr.cpp:247
bool appliesToDecl(const Decl *D, attr::SubjectMatchRule MatchRule) const
Definition: ParsedAttr.cpp:168
bool isKnownToGCC() const
Definition: ParsedAttr.cpp:201
bool existsInTarget(const TargetInfo &Target) const
Definition: ParsedAttr.cpp:195
unsigned getMinArgs() const
Definition: ParsedAttr.cpp:142
bool checkExactlyNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has exactly as many args as Num.
Definition: ParsedAttr.cpp:283
bool hasParsedType() const
Definition: ParsedAttr.h:338
bool hasVariadicArg() const
Definition: ParsedAttr.cpp:251
const ParsedAttrInfo & getInfo() const
Definition: ParsedAttr.h:610
void handleAttrWithDelayedArgs(Sema &S, Decl *D) const
Definition: ParsedAttr.cpp:263
bool diagnoseMutualExclusion(class Sema &S, const Decl *D) const
Definition: ParsedAttr.cpp:164
bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const
Definition: ParsedAttr.cpp:156
bool acceptsExprPack() const
Definition: ParsedAttr.cpp:245
bool isTypeAttr() const
Definition: ParsedAttr.cpp:191
bool isSupportedByPragmaAttribute() const
Definition: ParsedAttr.cpp:203
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this attribute.
Definition: ParsedAttr.h:372
bool checkAtLeastNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has at least as many args as Num.
Definition: ParsedAttr.cpp:288
unsigned getNumArgMembers() const
Definition: ParsedAttr.cpp:148
bool isStmtAttr() const
Definition: ParsedAttr.cpp:193
unsigned getMaxArgs() const
Definition: ParsedAttr.cpp:144
bool slidesFromDeclToDeclSpecLegacyBehavior() const
Returns whether a [[]] attribute, if specified ahead of a declaration, should be applied to the decl-...
Definition: ParsedAttr.cpp:207
void getMatchRules(const LangOptions &LangOpts, SmallVectorImpl< std::pair< attr::SubjectMatchRule, bool > > &MatchRules) const
Definition: ParsedAttr.cpp:173
bool isParamExpr(size_t N) const
Definition: ParsedAttr.cpp:259
bool diagnoseLangOpts(class Sema &S) const
Definition: ParsedAttr.cpp:180
bool checkAtMostNumArgs(class Sema &S, unsigned Num) const
Check if the attribute has at most as many args as Num.
Definition: ParsedAttr.cpp:293
ParsedAttributes - A collection of parsed attributes.
Definition: ParsedAttr.h:935
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:356
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: Sema.cpp:1919
const LangOptions & getLangOpts() const
Definition: Sema.h:1685
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:72
Exposes information about the current target.
Definition: TargetInfo.h:207
Defines the clang::TargetInfo interface.
const internal::VariadicAllOfMatcher< Attr > attr
Matches attributes.
SubjectMatchRule
A list of all the recognized kinds of attributes.
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:108
void takeAndConcatenateAttrs(ParsedAttributes &First, ParsedAttributes &Second, ParsedAttributes &Result)
Consumes the attributes from First and Second and concatenates them into Result.
Definition: ParsedAttr.cpp:299
@ Result
The result type of a method or function.
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:98
SourceLocation Loc
Definition: ParsedAttr.h:99
IdentifierInfo * Ident
Definition: ParsedAttr.h:100
static IdentifierLoc * create(ASTContext &Ctx, SourceLocation Loc, IdentifierInfo *Ident)
Definition: ParsedAttr.cpp:28
static ArrayRef< const ParsedAttrInfo * > getAllBuiltin()
Definition: ParsedAttr.cpp:138
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:109
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