[Github] Label lldb-dap PRs (#125139)
[llvm-project.git] / clang / lib / Sema / ParsedAttr.cpp
blobeadc6ed6e6f581f5bf48cb7ad95af9218f506808
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
11 //===----------------------------------------------------------------------===//
13 #include "clang/Sema/ParsedAttr.h"
14 #include "clang/AST/ASTContext.h"
15 #include "clang/Basic/AttrSubjectMatchRules.h"
16 #include "clang/Basic/IdentifierTable.h"
17 #include "clang/Basic/TargetInfo.h"
18 #include "clang/Sema/SemaInternal.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include <cassert>
21 #include <cstddef>
22 #include <utility>
24 using namespace clang;
26 IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
27 IdentifierInfo *Ident) {
28 IdentifierLoc *Result = new (Ctx) IdentifierLoc;
29 Result->Loc = Loc;
30 Result->Ident = Ident;
31 return Result;
34 size_t ParsedAttr::allocated_size() const {
35 if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
36 else if (IsTypeTagForDatatype)
37 return AttributeFactory::TypeTagForDatatypeAllocSize;
38 else if (IsProperty)
39 return AttributeFactory::PropertyAllocSize;
40 else if (HasParsedType)
41 return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
42 detail::TypeTagForDatatypeData, ParsedType,
43 detail::PropertyData>(0, 0, 0, 1, 0);
44 return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
45 detail::TypeTagForDatatypeData, ParsedType,
46 detail::PropertyData>(NumArgs, 0, 0, 0, 0);
49 AttributeFactory::AttributeFactory() {
50 // Go ahead and configure all the inline capacity. This is just a memset.
51 FreeLists.resize(InlineFreeListsCapacity);
53 AttributeFactory::~AttributeFactory() = default;
55 static size_t getFreeListIndexForSize(size_t size) {
56 assert(size >= sizeof(ParsedAttr));
57 assert((size % sizeof(void*)) == 0);
58 return ((size - sizeof(ParsedAttr)) / sizeof(void *));
61 void *AttributeFactory::allocate(size_t size) {
62 // Check for a previously reclaimed attribute.
63 size_t index = getFreeListIndexForSize(size);
64 if (index < FreeLists.size() && !FreeLists[index].empty()) {
65 ParsedAttr *attr = FreeLists[index].back();
66 FreeLists[index].pop_back();
67 return attr;
70 // Otherwise, allocate something new.
71 return Alloc.Allocate(size, alignof(AttributeFactory));
74 void AttributeFactory::deallocate(ParsedAttr *Attr) {
75 size_t size = Attr->allocated_size();
76 size_t freeListIndex = getFreeListIndexForSize(size);
78 // Expand FreeLists to the appropriate size, if required.
79 if (freeListIndex >= FreeLists.size())
80 FreeLists.resize(freeListIndex + 1);
82 #ifndef NDEBUG
83 // In debug mode, zero out the attribute to help find memory overwriting.
84 memset(Attr, 0, size);
85 #endif
87 // Add 'Attr' to the appropriate free-list.
88 FreeLists[freeListIndex].push_back(Attr);
91 void AttributeFactory::reclaimPool(AttributePool &cur) {
92 for (ParsedAttr *AL : cur.Attrs)
93 deallocate(AL);
96 void AttributePool::takePool(AttributePool &pool) {
97 Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
98 pool.Attrs.clear();
101 void AttributePool::takeFrom(ParsedAttributesView &List, AttributePool &Pool) {
102 assert(&Pool != this && "AttributePool can't take attributes from itself");
103 llvm::for_each(List.AttrList, [&Pool](ParsedAttr *A) { Pool.remove(A); });
104 Attrs.insert(Attrs.end(), List.AttrList.begin(), List.AttrList.end());
107 namespace {
109 #include "clang/Sema/AttrParsedAttrImpl.inc"
111 } // namespace
113 const ParsedAttrInfo &ParsedAttrInfo::get(const AttributeCommonInfo &A) {
114 // If we have a ParsedAttrInfo for this ParsedAttr then return that.
115 if ((size_t)A.getParsedKind() < std::size(AttrInfoMap))
116 return *AttrInfoMap[A.getParsedKind()];
118 // If this is an ignored attribute then return an appropriate ParsedAttrInfo.
119 static const ParsedAttrInfo IgnoredParsedAttrInfo(
120 AttributeCommonInfo::IgnoredAttribute);
121 if (A.getParsedKind() == AttributeCommonInfo::IgnoredAttribute)
122 return IgnoredParsedAttrInfo;
124 // Otherwise this may be an attribute defined by a plugin.
126 // Search for a ParsedAttrInfo whose name and syntax match.
127 std::string FullName = A.getNormalizedFullName();
128 AttributeCommonInfo::Syntax SyntaxUsed = A.getSyntax();
129 if (SyntaxUsed == AttributeCommonInfo::AS_ContextSensitiveKeyword)
130 SyntaxUsed = AttributeCommonInfo::AS_Keyword;
132 for (auto &Ptr : getAttributePluginInstances())
133 if (Ptr->hasSpelling(SyntaxUsed, FullName))
134 return *Ptr;
136 // If we failed to find a match then return a default ParsedAttrInfo.
137 static const ParsedAttrInfo DefaultParsedAttrInfo(
138 AttributeCommonInfo::UnknownAttribute);
139 return DefaultParsedAttrInfo;
142 ArrayRef<const ParsedAttrInfo *> ParsedAttrInfo::getAllBuiltin() {
143 return llvm::ArrayRef(AttrInfoMap);
146 unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; }
148 unsigned ParsedAttr::getMaxArgs() const {
149 return getMinArgs() + getInfo().OptArgs;
152 unsigned ParsedAttr::getNumArgMembers() const {
153 return getInfo().NumArgMembers;
156 bool ParsedAttr::hasCustomParsing() const {
157 return getInfo().HasCustomParsing;
160 bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
161 return getInfo().diagAppertainsToDecl(S, *this, D);
164 bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Stmt *St) const {
165 return getInfo().diagAppertainsToStmt(S, *this, St);
168 bool ParsedAttr::diagnoseMutualExclusion(Sema &S, const Decl *D) const {
169 return getInfo().diagMutualExclusion(S, *this, D);
172 bool ParsedAttr::appliesToDecl(const Decl *D,
173 attr::SubjectMatchRule MatchRule) const {
174 return checkAttributeMatchRuleAppliesTo(D, MatchRule);
177 void ParsedAttr::getMatchRules(
178 const LangOptions &LangOpts,
179 SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
180 const {
181 return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts);
184 bool ParsedAttr::diagnoseLangOpts(Sema &S) const {
185 if (getInfo().acceptsLangOpts(S.getLangOpts()))
186 return true;
187 S.Diag(getLoc(), diag::warn_attribute_ignored) << *this;
188 return false;
191 bool ParsedAttr::isTargetSpecificAttr() const {
192 return getInfo().IsTargetSpecific;
195 bool ParsedAttr::isTypeAttr() const { return getInfo().IsType; }
197 bool ParsedAttr::isStmtAttr() const { return getInfo().IsStmt; }
199 bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {
200 Kind K = getParsedKind();
202 // If the attribute has a target-specific spelling, check that it exists.
203 // Only call this if the attr is not ignored/unknown. For most targets, this
204 // function just returns true.
205 bool HasSpelling = K != IgnoredAttribute && K != UnknownAttribute &&
206 K != NoSemaHandlerAttribute;
207 bool TargetSpecificSpellingExists =
208 !HasSpelling ||
209 getInfo().spellingExistsInTarget(Target, getAttributeSpellingListIndex());
211 return getInfo().existsInTarget(Target) && TargetSpecificSpellingExists;
214 bool ParsedAttr::isKnownToGCC() const { return getInfo().IsKnownToGCC; }
216 bool ParsedAttr::isSupportedByPragmaAttribute() const {
217 return getInfo().IsSupportedByPragmaAttribute;
220 bool ParsedAttr::slidesFromDeclToDeclSpecLegacyBehavior() const {
221 if (isRegularKeywordAttribute())
222 // The appurtenance rules are applied strictly for all regular keyword
223 // atributes.
224 return false;
226 assert(isStandardAttributeSyntax() || isAlignas());
228 // We have historically allowed some type attributes with standard attribute
229 // syntax to slide to the decl-specifier-seq, so we have to keep supporting
230 // it. This property is consciously not defined as a flag in Attr.td because
231 // we don't want new attributes to specify it.
233 // Note: No new entries should be added to this list. Entries should be
234 // removed from this list after a suitable deprecation period, provided that
235 // there are no compatibility considerations with other compilers. If
236 // possible, we would like this list to go away entirely.
237 switch (getParsedKind()) {
238 case AT_AddressSpace:
239 case AT_OpenCLPrivateAddressSpace:
240 case AT_OpenCLGlobalAddressSpace:
241 case AT_OpenCLGlobalDeviceAddressSpace:
242 case AT_OpenCLGlobalHostAddressSpace:
243 case AT_OpenCLLocalAddressSpace:
244 case AT_OpenCLConstantAddressSpace:
245 case AT_OpenCLGenericAddressSpace:
246 case AT_NeonPolyVectorType:
247 case AT_NeonVectorType:
248 case AT_ArmMveStrictPolymorphism:
249 case AT_BTFTypeTag:
250 case AT_ObjCGC:
251 case AT_MatrixType:
252 return true;
253 default:
254 return false;
258 bool ParsedAttr::acceptsExprPack() const { return getInfo().AcceptsExprPack; }
260 unsigned ParsedAttr::getSemanticSpelling() const {
261 return getInfo().spellingIndexToSemanticSpelling(*this);
264 bool ParsedAttr::hasVariadicArg() const {
265 // If the attribute has the maximum number of optional arguments, we will
266 // claim that as being variadic. If we someday get an attribute that
267 // legitimately bumps up against that maximum, we can use another bit to track
268 // whether it's truly variadic or not.
269 return getInfo().OptArgs == 15;
272 bool ParsedAttr::isParamExpr(size_t N) const {
273 return getInfo().isParamExpr(N);
276 void ParsedAttr::handleAttrWithDelayedArgs(Sema &S, Decl *D) const {
277 ::handleAttrWithDelayedArgs(S, D, *this);
280 static unsigned getNumAttributeArgs(const ParsedAttr &AL) {
281 // FIXME: Include the type in the argument list.
282 return AL.getNumArgs() + AL.hasParsedType();
285 template <typename Compare>
286 static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL,
287 unsigned Num, unsigned Diag,
288 Compare Comp) {
289 if (Comp(getNumAttributeArgs(AL), Num)) {
290 S.Diag(AL.getLoc(), Diag) << AL << Num;
291 return false;
293 return true;
296 bool ParsedAttr::checkExactlyNumArgs(Sema &S, unsigned Num) const {
297 return checkAttributeNumArgsImpl(S, *this, Num,
298 diag::err_attribute_wrong_number_arguments,
299 std::not_equal_to<unsigned>());
301 bool ParsedAttr::checkAtLeastNumArgs(Sema &S, unsigned Num) const {
302 return checkAttributeNumArgsImpl(S, *this, Num,
303 diag::err_attribute_too_few_arguments,
304 std::less<unsigned>());
306 bool ParsedAttr::checkAtMostNumArgs(Sema &S, unsigned Num) const {
307 return checkAttributeNumArgsImpl(S, *this, Num,
308 diag::err_attribute_too_many_arguments,
309 std::greater<unsigned>());
312 void clang::takeAndConcatenateAttrs(ParsedAttributes &First,
313 ParsedAttributes &Second,
314 ParsedAttributes &Result) {
315 // Note that takeAllFrom() puts the attributes at the beginning of the list,
316 // so to obtain the correct ordering, we add `Second`, then `First`.
317 Result.takeAllFrom(Second);
318 Result.takeAllFrom(First);
319 if (First.Range.getBegin().isValid())
320 Result.Range.setBegin(First.Range.getBegin());
321 else
322 Result.Range.setBegin(Second.Range.getBegin());
323 if (Second.Range.getEnd().isValid())
324 Result.Range.setEnd(Second.Range.getEnd());
325 else
326 Result.Range.setEnd(First.Range.getEnd());