xref: /llvm-project/clang/lib/Sema/ParsedAttr.cpp (revision 46d750be2e19220c318bc907dfaf6c61d3a0de92)
1e891aa97SErich Keane //======- ParsedAttr.cpp --------------------------------------------------===//
2e891aa97SErich Keane //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e891aa97SErich Keane //
7e891aa97SErich Keane //===----------------------------------------------------------------------===//
8e891aa97SErich Keane //
9e891aa97SErich Keane // This file defines the ParsedAttr class implementation
10e891aa97SErich Keane //
11e891aa97SErich Keane //===----------------------------------------------------------------------===//
12e891aa97SErich Keane 
13e891aa97SErich Keane #include "clang/Sema/ParsedAttr.h"
14e891aa97SErich Keane #include "clang/AST/ASTContext.h"
15e891aa97SErich Keane #include "clang/Basic/AttrSubjectMatchRules.h"
16e891aa97SErich Keane #include "clang/Basic/IdentifierTable.h"
17e891aa97SErich Keane #include "clang/Basic/TargetInfo.h"
18e891aa97SErich Keane #include "clang/Sema/SemaInternal.h"
19e891aa97SErich Keane #include "llvm/ADT/SmallVector.h"
20e891aa97SErich Keane #include <cassert>
21e891aa97SErich Keane #include <cstddef>
22e891aa97SErich Keane #include <utility>
23e891aa97SErich Keane 
24e891aa97SErich Keane using namespace clang;
25e891aa97SErich Keane 
26e891aa97SErich Keane IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
27e891aa97SErich Keane                                      IdentifierInfo *Ident) {
28e891aa97SErich Keane   IdentifierLoc *Result = new (Ctx) IdentifierLoc;
29e891aa97SErich Keane   Result->Loc = Loc;
30e891aa97SErich Keane   Result->Ident = Ident;
31e891aa97SErich Keane   return Result;
32e891aa97SErich Keane }
33e891aa97SErich Keane 
34e891aa97SErich Keane size_t ParsedAttr::allocated_size() const {
35e891aa97SErich Keane   if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
36e891aa97SErich Keane   else if (IsTypeTagForDatatype)
37e891aa97SErich Keane     return AttributeFactory::TypeTagForDatatypeAllocSize;
38e891aa97SErich Keane   else if (IsProperty)
39e891aa97SErich Keane     return AttributeFactory::PropertyAllocSize;
40e891aa97SErich Keane   else if (HasParsedType)
4103406c50SErich Keane     return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
4203406c50SErich Keane                             detail::TypeTagForDatatypeData, ParsedType,
4303406c50SErich Keane                             detail::PropertyData>(0, 0, 0, 1, 0);
4403406c50SErich Keane   return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
4503406c50SErich Keane                           detail::TypeTagForDatatypeData, ParsedType,
4603406c50SErich Keane                           detail::PropertyData>(NumArgs, 0, 0, 0, 0);
47e891aa97SErich Keane }
48e891aa97SErich Keane 
49e891aa97SErich Keane AttributeFactory::AttributeFactory() {
50e891aa97SErich Keane   // Go ahead and configure all the inline capacity.  This is just a memset.
51e891aa97SErich Keane   FreeLists.resize(InlineFreeListsCapacity);
52e891aa97SErich Keane }
53e891aa97SErich Keane AttributeFactory::~AttributeFactory() = default;
54e891aa97SErich Keane 
55e891aa97SErich Keane static size_t getFreeListIndexForSize(size_t size) {
56e891aa97SErich Keane   assert(size >= sizeof(ParsedAttr));
57e891aa97SErich Keane   assert((size % sizeof(void*)) == 0);
58e891aa97SErich Keane   return ((size - sizeof(ParsedAttr)) / sizeof(void *));
59e891aa97SErich Keane }
60e891aa97SErich Keane 
61e891aa97SErich Keane void *AttributeFactory::allocate(size_t size) {
62e891aa97SErich Keane   // Check for a previously reclaimed attribute.
63e891aa97SErich Keane   size_t index = getFreeListIndexForSize(size);
64e891aa97SErich Keane   if (index < FreeLists.size() && !FreeLists[index].empty()) {
65e891aa97SErich Keane     ParsedAttr *attr = FreeLists[index].back();
66e891aa97SErich Keane     FreeLists[index].pop_back();
67e891aa97SErich Keane     return attr;
68e891aa97SErich Keane   }
69e891aa97SErich Keane 
70e891aa97SErich Keane   // Otherwise, allocate something new.
71e891aa97SErich Keane   return Alloc.Allocate(size, alignof(AttributeFactory));
72e891aa97SErich Keane }
73e891aa97SErich Keane 
74e891aa97SErich Keane void AttributeFactory::deallocate(ParsedAttr *Attr) {
75e891aa97SErich Keane   size_t size = Attr->allocated_size();
76e891aa97SErich Keane   size_t freeListIndex = getFreeListIndexForSize(size);
77e891aa97SErich Keane 
78e891aa97SErich Keane   // Expand FreeLists to the appropriate size, if required.
79e891aa97SErich Keane   if (freeListIndex >= FreeLists.size())
80e891aa97SErich Keane     FreeLists.resize(freeListIndex + 1);
81e891aa97SErich Keane 
827b39a085SSven van Haastregt #ifndef NDEBUG
83e891aa97SErich Keane   // In debug mode, zero out the attribute to help find memory overwriting.
84e891aa97SErich Keane   memset(Attr, 0, size);
85e891aa97SErich Keane #endif
86e891aa97SErich Keane 
87e891aa97SErich Keane   // Add 'Attr' to the appropriate free-list.
88e891aa97SErich Keane   FreeLists[freeListIndex].push_back(Attr);
89e891aa97SErich Keane }
90e891aa97SErich Keane 
91e891aa97SErich Keane void AttributeFactory::reclaimPool(AttributePool &cur) {
92e891aa97SErich Keane   for (ParsedAttr *AL : cur.Attrs)
93e891aa97SErich Keane     deallocate(AL);
94e891aa97SErich Keane }
95e891aa97SErich Keane 
96e891aa97SErich Keane void AttributePool::takePool(AttributePool &pool) {
97e891aa97SErich Keane   Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
98e891aa97SErich Keane   pool.Attrs.clear();
99e891aa97SErich Keane }
100e891aa97SErich Keane 
101bd7bce2cSErich Keane void AttributePool::takeFrom(ParsedAttributesView &List, AttributePool &Pool) {
102bd7bce2cSErich Keane   assert(&Pool != this && "AttributePool can't take attributes from itself");
103bd7bce2cSErich Keane   llvm::for_each(List.AttrList, [&Pool](ParsedAttr *A) { Pool.remove(A); });
104bd7bce2cSErich Keane   Attrs.insert(Attrs.end(), List.AttrList.begin(), List.AttrList.end());
105bd7bce2cSErich Keane }
106bd7bce2cSErich Keane 
107e891aa97SErich Keane namespace {
108e891aa97SErich Keane 
109e891aa97SErich Keane #include "clang/Sema/AttrParsedAttrImpl.inc"
110e891aa97SErich Keane 
111e891aa97SErich Keane } // namespace
112e891aa97SErich Keane 
11375d4d4bdSJohn Brawn const ParsedAttrInfo &ParsedAttrInfo::get(const AttributeCommonInfo &A) {
11475d4d4bdSJohn Brawn   // If we have a ParsedAttrInfo for this ParsedAttr then return that.
1151b3a78d1SJoe Loser   if ((size_t)A.getParsedKind() < std::size(AttrInfoMap))
11675d4d4bdSJohn Brawn     return *AttrInfoMap[A.getParsedKind()];
117590dc8d0SJohn Brawn 
11875d4d4bdSJohn Brawn   // If this is an ignored attribute then return an appropriate ParsedAttrInfo.
119e8743c0fSBenjamin Kramer   static const ParsedAttrInfo IgnoredParsedAttrInfo(
12075d4d4bdSJohn Brawn       AttributeCommonInfo::IgnoredAttribute);
12175d4d4bdSJohn Brawn   if (A.getParsedKind() == AttributeCommonInfo::IgnoredAttribute)
12275d4d4bdSJohn Brawn     return IgnoredParsedAttrInfo;
12375d4d4bdSJohn Brawn 
124f5f1813dSAnders Waldenborg   // Otherwise this may be an attribute defined by a plugin.
12575d4d4bdSJohn Brawn 
12675d4d4bdSJohn Brawn   // Search for a ParsedAttrInfo whose name and syntax match.
12775d4d4bdSJohn Brawn   std::string FullName = A.getNormalizedFullName();
12875d4d4bdSJohn Brawn   AttributeCommonInfo::Syntax SyntaxUsed = A.getSyntax();
12975d4d4bdSJohn Brawn   if (SyntaxUsed == AttributeCommonInfo::AS_ContextSensitiveKeyword)
13075d4d4bdSJohn Brawn     SyntaxUsed = AttributeCommonInfo::AS_Keyword;
13175d4d4bdSJohn Brawn 
132f5f1813dSAnders Waldenborg   for (auto &Ptr : getAttributePluginInstances())
133446f7809SAnders Waldenborg     if (Ptr->hasSpelling(SyntaxUsed, FullName))
13475d4d4bdSJohn Brawn       return *Ptr;
13575d4d4bdSJohn Brawn 
13675d4d4bdSJohn Brawn   // If we failed to find a match then return a default ParsedAttrInfo.
137e8743c0fSBenjamin Kramer   static const ParsedAttrInfo DefaultParsedAttrInfo(
138fa0320ddSJohn Brawn       AttributeCommonInfo::UnknownAttribute);
139590dc8d0SJohn Brawn   return DefaultParsedAttrInfo;
140e891aa97SErich Keane }
141e891aa97SErich Keane 
142ece4e920SSam McCall ArrayRef<const ParsedAttrInfo *> ParsedAttrInfo::getAllBuiltin() {
143a3c248dbSserge-sans-paille   return llvm::ArrayRef(AttrInfoMap);
144ece4e920SSam McCall }
145ece4e920SSam McCall 
14675d4d4bdSJohn Brawn unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; }
147e891aa97SErich Keane 
148e891aa97SErich Keane unsigned ParsedAttr::getMaxArgs() const {
14975d4d4bdSJohn Brawn   return getMinArgs() + getInfo().OptArgs;
150e891aa97SErich Keane }
151e891aa97SErich Keane 
152ead1690dSSteffen Larsen unsigned ParsedAttr::getNumArgMembers() const {
153ead1690dSSteffen Larsen   return getInfo().NumArgMembers;
154ead1690dSSteffen Larsen }
155ead1690dSSteffen Larsen 
156e891aa97SErich Keane bool ParsedAttr::hasCustomParsing() const {
15775d4d4bdSJohn Brawn   return getInfo().HasCustomParsing;
158e891aa97SErich Keane }
159e891aa97SErich Keane 
160e891aa97SErich Keane bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
16175d4d4bdSJohn Brawn   return getInfo().diagAppertainsToDecl(S, *this, D);
162e891aa97SErich Keane }
163e891aa97SErich Keane 
164fa4e7297SAaron Ballman bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Stmt *St) const {
165fa4e7297SAaron Ballman   return getInfo().diagAppertainsToStmt(S, *this, St);
166fa4e7297SAaron Ballman }
167fa4e7297SAaron Ballman 
1684be8a269SAaron Ballman bool ParsedAttr::diagnoseMutualExclusion(Sema &S, const Decl *D) const {
1694be8a269SAaron Ballman   return getInfo().diagMutualExclusion(S, *this, D);
1704be8a269SAaron Ballman }
1714be8a269SAaron Ballman 
172e891aa97SErich Keane bool ParsedAttr::appliesToDecl(const Decl *D,
173e891aa97SErich Keane                                attr::SubjectMatchRule MatchRule) const {
174e891aa97SErich Keane   return checkAttributeMatchRuleAppliesTo(D, MatchRule);
175e891aa97SErich Keane }
176e891aa97SErich Keane 
177e891aa97SErich Keane void ParsedAttr::getMatchRules(
178e891aa97SErich Keane     const LangOptions &LangOpts,
179e891aa97SErich Keane     SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
180e891aa97SErich Keane     const {
18175d4d4bdSJohn Brawn   return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts);
182e891aa97SErich Keane }
183e891aa97SErich Keane 
184e891aa97SErich Keane bool ParsedAttr::diagnoseLangOpts(Sema &S) const {
1853b99acbfSSam McCall   if (getInfo().acceptsLangOpts(S.getLangOpts()))
1863b99acbfSSam McCall     return true;
1873b99acbfSSam McCall   S.Diag(getLoc(), diag::warn_attribute_ignored) << *this;
1883b99acbfSSam McCall   return false;
189e891aa97SErich Keane }
190e891aa97SErich Keane 
191e891aa97SErich Keane bool ParsedAttr::isTargetSpecificAttr() const {
19275d4d4bdSJohn Brawn   return getInfo().IsTargetSpecific;
193e891aa97SErich Keane }
194e891aa97SErich Keane 
19575d4d4bdSJohn Brawn bool ParsedAttr::isTypeAttr() const { return getInfo().IsType; }
196e891aa97SErich Keane 
19775d4d4bdSJohn Brawn bool ParsedAttr::isStmtAttr() const { return getInfo().IsStmt; }
198e891aa97SErich Keane 
199e891aa97SErich Keane bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {
2000ba5f6e6SAmy Huang   Kind K = getParsedKind();
2010ba5f6e6SAmy Huang 
2020ba5f6e6SAmy Huang   // If the attribute has a target-specific spelling, check that it exists.
2030ba5f6e6SAmy Huang   // Only call this if the attr is not ignored/unknown. For most targets, this
2040ba5f6e6SAmy Huang   // function just returns true.
2050ba5f6e6SAmy Huang   bool HasSpelling = K != IgnoredAttribute && K != UnknownAttribute &&
2060ba5f6e6SAmy Huang                      K != NoSemaHandlerAttribute;
2070ba5f6e6SAmy Huang   bool TargetSpecificSpellingExists =
2080ba5f6e6SAmy Huang       !HasSpelling ||
2090ba5f6e6SAmy Huang       getInfo().spellingExistsInTarget(Target, getAttributeSpellingListIndex());
2100ba5f6e6SAmy Huang 
2110ba5f6e6SAmy Huang   return getInfo().existsInTarget(Target) && TargetSpecificSpellingExists;
212e891aa97SErich Keane }
213e891aa97SErich Keane 
21475d4d4bdSJohn Brawn bool ParsedAttr::isKnownToGCC() const { return getInfo().IsKnownToGCC; }
215e891aa97SErich Keane 
216e891aa97SErich Keane bool ParsedAttr::isSupportedByPragmaAttribute() const {
21775d4d4bdSJohn Brawn   return getInfo().IsSupportedByPragmaAttribute;
218e891aa97SErich Keane }
219e891aa97SErich Keane 
2208c7b64b5SMartin Boehme bool ParsedAttr::slidesFromDeclToDeclSpecLegacyBehavior() const {
22133ee5c46SRichard Sandiford   if (isRegularKeywordAttribute())
22233ee5c46SRichard Sandiford     // The appurtenance rules are applied strictly for all regular keyword
22333ee5c46SRichard Sandiford     // atributes.
22433ee5c46SRichard Sandiford     return false;
22533ee5c46SRichard Sandiford 
226*bf02f417SAaron Ballman   assert(isStandardAttributeSyntax() || isAlignas());
2278c7b64b5SMartin Boehme 
2288c7b64b5SMartin Boehme   // We have historically allowed some type attributes with standard attribute
2298c7b64b5SMartin Boehme   // syntax to slide to the decl-specifier-seq, so we have to keep supporting
2308c7b64b5SMartin Boehme   // it. This property is consciously not defined as a flag in Attr.td because
2318c7b64b5SMartin Boehme   // we don't want new attributes to specify it.
2328c7b64b5SMartin Boehme   //
2338c7b64b5SMartin Boehme   // Note: No new entries should be added to this list. Entries should be
2348c7b64b5SMartin Boehme   // removed from this list after a suitable deprecation period, provided that
2358c7b64b5SMartin Boehme   // there are no compatibility considerations with other compilers. If
2368c7b64b5SMartin Boehme   // possible, we would like this list to go away entirely.
2378c7b64b5SMartin Boehme   switch (getParsedKind()) {
2388c7b64b5SMartin Boehme   case AT_AddressSpace:
2398c7b64b5SMartin Boehme   case AT_OpenCLPrivateAddressSpace:
2408c7b64b5SMartin Boehme   case AT_OpenCLGlobalAddressSpace:
2418c7b64b5SMartin Boehme   case AT_OpenCLGlobalDeviceAddressSpace:
2428c7b64b5SMartin Boehme   case AT_OpenCLGlobalHostAddressSpace:
2438c7b64b5SMartin Boehme   case AT_OpenCLLocalAddressSpace:
2448c7b64b5SMartin Boehme   case AT_OpenCLConstantAddressSpace:
2458c7b64b5SMartin Boehme   case AT_OpenCLGenericAddressSpace:
2468c7b64b5SMartin Boehme   case AT_NeonPolyVectorType:
2478c7b64b5SMartin Boehme   case AT_NeonVectorType:
2488c7b64b5SMartin Boehme   case AT_ArmMveStrictPolymorphism:
2498c7b64b5SMartin Boehme   case AT_BTFTypeTag:
2508c7b64b5SMartin Boehme   case AT_ObjCGC:
2518c7b64b5SMartin Boehme   case AT_MatrixType:
2528c7b64b5SMartin Boehme     return true;
2538c7b64b5SMartin Boehme   default:
2548c7b64b5SMartin Boehme     return false;
2558c7b64b5SMartin Boehme   }
2568c7b64b5SMartin Boehme }
2578c7b64b5SMartin Boehme 
258ead1690dSSteffen Larsen bool ParsedAttr::acceptsExprPack() const { return getInfo().AcceptsExprPack; }
259ead1690dSSteffen Larsen 
260e891aa97SErich Keane unsigned ParsedAttr::getSemanticSpelling() const {
26175d4d4bdSJohn Brawn   return getInfo().spellingIndexToSemanticSpelling(*this);
262e891aa97SErich Keane }
263e891aa97SErich Keane 
264e891aa97SErich Keane bool ParsedAttr::hasVariadicArg() const {
265e891aa97SErich Keane   // If the attribute has the maximum number of optional arguments, we will
266e891aa97SErich Keane   // claim that as being variadic. If we someday get an attribute that
267e891aa97SErich Keane   // legitimately bumps up against that maximum, we can use another bit to track
268e891aa97SErich Keane   // whether it's truly variadic or not.
26975d4d4bdSJohn Brawn   return getInfo().OptArgs == 15;
270e891aa97SErich Keane }
2718bb8d65eSAaron Ballman 
272ead1690dSSteffen Larsen bool ParsedAttr::isParamExpr(size_t N) const {
273ead1690dSSteffen Larsen   return getInfo().isParamExpr(N);
274ead1690dSSteffen Larsen }
275ead1690dSSteffen Larsen 
276ead1690dSSteffen Larsen void ParsedAttr::handleAttrWithDelayedArgs(Sema &S, Decl *D) const {
277ead1690dSSteffen Larsen   ::handleAttrWithDelayedArgs(S, D, *this);
278ead1690dSSteffen Larsen }
279ead1690dSSteffen Larsen 
2808bb8d65eSAaron Ballman static unsigned getNumAttributeArgs(const ParsedAttr &AL) {
2818bb8d65eSAaron Ballman   // FIXME: Include the type in the argument list.
2828bb8d65eSAaron Ballman   return AL.getNumArgs() + AL.hasParsedType();
2838bb8d65eSAaron Ballman }
2848bb8d65eSAaron Ballman 
2858bb8d65eSAaron Ballman template <typename Compare>
2868bb8d65eSAaron Ballman static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL,
2878bb8d65eSAaron Ballman                                       unsigned Num, unsigned Diag,
2888bb8d65eSAaron Ballman                                       Compare Comp) {
2898bb8d65eSAaron Ballman   if (Comp(getNumAttributeArgs(AL), Num)) {
2908bb8d65eSAaron Ballman     S.Diag(AL.getLoc(), Diag) << AL << Num;
2918bb8d65eSAaron Ballman     return false;
2928bb8d65eSAaron Ballman   }
2938bb8d65eSAaron Ballman   return true;
2948bb8d65eSAaron Ballman }
2958bb8d65eSAaron Ballman 
2968bb8d65eSAaron Ballman bool ParsedAttr::checkExactlyNumArgs(Sema &S, unsigned Num) const {
2978bb8d65eSAaron Ballman   return checkAttributeNumArgsImpl(S, *this, Num,
2988bb8d65eSAaron Ballman                                    diag::err_attribute_wrong_number_arguments,
2998bb8d65eSAaron Ballman                                    std::not_equal_to<unsigned>());
3008bb8d65eSAaron Ballman }
3018bb8d65eSAaron Ballman bool ParsedAttr::checkAtLeastNumArgs(Sema &S, unsigned Num) const {
3028bb8d65eSAaron Ballman   return checkAttributeNumArgsImpl(S, *this, Num,
3038bb8d65eSAaron Ballman                                    diag::err_attribute_too_few_arguments,
3048bb8d65eSAaron Ballman                                    std::less<unsigned>());
3058bb8d65eSAaron Ballman }
3068bb8d65eSAaron Ballman bool ParsedAttr::checkAtMostNumArgs(Sema &S, unsigned Num) const {
3078bb8d65eSAaron Ballman   return checkAttributeNumArgsImpl(S, *this, Num,
3088bb8d65eSAaron Ballman                                    diag::err_attribute_too_many_arguments,
3098bb8d65eSAaron Ballman                                    std::greater<unsigned>());
3108bb8d65eSAaron Ballman }
3118c7b64b5SMartin Boehme 
3128c7b64b5SMartin Boehme void clang::takeAndConcatenateAttrs(ParsedAttributes &First,
3138c7b64b5SMartin Boehme                                     ParsedAttributes &Second,
3148c7b64b5SMartin Boehme                                     ParsedAttributes &Result) {
3158c7b64b5SMartin Boehme   // Note that takeAllFrom() puts the attributes at the beginning of the list,
3168c7b64b5SMartin Boehme   // so to obtain the correct ordering, we add `Second`, then `First`.
3178c7b64b5SMartin Boehme   Result.takeAllFrom(Second);
3188c7b64b5SMartin Boehme   Result.takeAllFrom(First);
3198c7b64b5SMartin Boehme   if (First.Range.getBegin().isValid())
3208c7b64b5SMartin Boehme     Result.Range.setBegin(First.Range.getBegin());
3218c7b64b5SMartin Boehme   else
3228c7b64b5SMartin Boehme     Result.Range.setBegin(Second.Range.getBegin());
3238c7b64b5SMartin Boehme   if (Second.Range.getEnd().isValid())
3248c7b64b5SMartin Boehme     Result.Range.setEnd(Second.Range.getEnd());
3258c7b64b5SMartin Boehme   else
3268c7b64b5SMartin Boehme     Result.Range.setEnd(First.Range.getEnd());
3278c7b64b5SMartin Boehme }
328