xref: /freebsd/contrib/llvm-project/clang/lib/Sema/ParsedAttr.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric //======- ParsedAttr.cpp --------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines the ParsedAttr class implementation
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "clang/Sema/ParsedAttr.h"
140b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
150b57cec5SDimitry Andric #include "clang/Basic/AttrSubjectMatchRules.h"
160b57cec5SDimitry Andric #include "clang/Basic/IdentifierTable.h"
170b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h"
180b57cec5SDimitry Andric #include "clang/Sema/SemaInternal.h"
190b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
200b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
210b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
220b57cec5SDimitry Andric #include <cassert>
230b57cec5SDimitry Andric #include <cstddef>
240b57cec5SDimitry Andric #include <utility>
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric using namespace clang;
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
290b57cec5SDimitry Andric                                      IdentifierInfo *Ident) {
300b57cec5SDimitry Andric   IdentifierLoc *Result = new (Ctx) IdentifierLoc;
310b57cec5SDimitry Andric   Result->Loc = Loc;
320b57cec5SDimitry Andric   Result->Ident = Ident;
330b57cec5SDimitry Andric   return Result;
340b57cec5SDimitry Andric }
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric size_t ParsedAttr::allocated_size() const {
370b57cec5SDimitry Andric   if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
380b57cec5SDimitry Andric   else if (IsTypeTagForDatatype)
390b57cec5SDimitry Andric     return AttributeFactory::TypeTagForDatatypeAllocSize;
400b57cec5SDimitry Andric   else if (IsProperty)
410b57cec5SDimitry Andric     return AttributeFactory::PropertyAllocSize;
420b57cec5SDimitry Andric   else if (HasParsedType)
430b57cec5SDimitry Andric     return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
440b57cec5SDimitry Andric                             detail::TypeTagForDatatypeData, ParsedType,
450b57cec5SDimitry Andric                             detail::PropertyData>(0, 0, 0, 1, 0);
460b57cec5SDimitry Andric   return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
470b57cec5SDimitry Andric                           detail::TypeTagForDatatypeData, ParsedType,
480b57cec5SDimitry Andric                           detail::PropertyData>(NumArgs, 0, 0, 0, 0);
490b57cec5SDimitry Andric }
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric AttributeFactory::AttributeFactory() {
520b57cec5SDimitry Andric   // Go ahead and configure all the inline capacity.  This is just a memset.
530b57cec5SDimitry Andric   FreeLists.resize(InlineFreeListsCapacity);
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric AttributeFactory::~AttributeFactory() = default;
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric static size_t getFreeListIndexForSize(size_t size) {
580b57cec5SDimitry Andric   assert(size >= sizeof(ParsedAttr));
590b57cec5SDimitry Andric   assert((size % sizeof(void*)) == 0);
600b57cec5SDimitry Andric   return ((size - sizeof(ParsedAttr)) / sizeof(void *));
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric void *AttributeFactory::allocate(size_t size) {
640b57cec5SDimitry Andric   // Check for a previously reclaimed attribute.
650b57cec5SDimitry Andric   size_t index = getFreeListIndexForSize(size);
660b57cec5SDimitry Andric   if (index < FreeLists.size() && !FreeLists[index].empty()) {
670b57cec5SDimitry Andric     ParsedAttr *attr = FreeLists[index].back();
680b57cec5SDimitry Andric     FreeLists[index].pop_back();
690b57cec5SDimitry Andric     return attr;
700b57cec5SDimitry Andric   }
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   // Otherwise, allocate something new.
730b57cec5SDimitry Andric   return Alloc.Allocate(size, alignof(AttributeFactory));
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric void AttributeFactory::deallocate(ParsedAttr *Attr) {
770b57cec5SDimitry Andric   size_t size = Attr->allocated_size();
780b57cec5SDimitry Andric   size_t freeListIndex = getFreeListIndexForSize(size);
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   // Expand FreeLists to the appropriate size, if required.
810b57cec5SDimitry Andric   if (freeListIndex >= FreeLists.size())
820b57cec5SDimitry Andric     FreeLists.resize(freeListIndex + 1);
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric #ifndef NDEBUG
850b57cec5SDimitry Andric   // In debug mode, zero out the attribute to help find memory overwriting.
860b57cec5SDimitry Andric   memset(Attr, 0, size);
870b57cec5SDimitry Andric #endif
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   // Add 'Attr' to the appropriate free-list.
900b57cec5SDimitry Andric   FreeLists[freeListIndex].push_back(Attr);
910b57cec5SDimitry Andric }
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric void AttributeFactory::reclaimPool(AttributePool &cur) {
940b57cec5SDimitry Andric   for (ParsedAttr *AL : cur.Attrs)
950b57cec5SDimitry Andric     deallocate(AL);
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric void AttributePool::takePool(AttributePool &pool) {
990b57cec5SDimitry Andric   Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
1000b57cec5SDimitry Andric   pool.Attrs.clear();
1010b57cec5SDimitry Andric }
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric namespace {
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric #include "clang/Sema/AttrParsedAttrImpl.inc"
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric } // namespace
1080b57cec5SDimitry Andric 
1095ffd83dbSDimitry Andric const ParsedAttrInfo &ParsedAttrInfo::get(const AttributeCommonInfo &A) {
1105ffd83dbSDimitry Andric   // If we have a ParsedAttrInfo for this ParsedAttr then return that.
111bdd1243dSDimitry Andric   if ((size_t)A.getParsedKind() < std::size(AttrInfoMap))
1125ffd83dbSDimitry Andric     return *AttrInfoMap[A.getParsedKind()];
1135ffd83dbSDimitry Andric 
1145ffd83dbSDimitry Andric   // If this is an ignored attribute then return an appropriate ParsedAttrInfo.
1155ffd83dbSDimitry Andric   static const ParsedAttrInfo IgnoredParsedAttrInfo(
1165ffd83dbSDimitry Andric       AttributeCommonInfo::IgnoredAttribute);
1175ffd83dbSDimitry Andric   if (A.getParsedKind() == AttributeCommonInfo::IgnoredAttribute)
1185ffd83dbSDimitry Andric     return IgnoredParsedAttrInfo;
1195ffd83dbSDimitry Andric 
120*06c3fb27SDimitry Andric   // Otherwise this may be an attribute defined by a plugin.
1215ffd83dbSDimitry Andric 
1225ffd83dbSDimitry Andric   // Search for a ParsedAttrInfo whose name and syntax match.
1235ffd83dbSDimitry Andric   std::string FullName = A.getNormalizedFullName();
1245ffd83dbSDimitry Andric   AttributeCommonInfo::Syntax SyntaxUsed = A.getSyntax();
1255ffd83dbSDimitry Andric   if (SyntaxUsed == AttributeCommonInfo::AS_ContextSensitiveKeyword)
1265ffd83dbSDimitry Andric     SyntaxUsed = AttributeCommonInfo::AS_Keyword;
1275ffd83dbSDimitry Andric 
128*06c3fb27SDimitry Andric   for (auto &Ptr : getAttributePluginInstances())
129*06c3fb27SDimitry Andric     if (Ptr->hasSpelling(SyntaxUsed, FullName))
1305ffd83dbSDimitry Andric       return *Ptr;
1315ffd83dbSDimitry Andric 
1325ffd83dbSDimitry Andric   // If we failed to find a match then return a default ParsedAttrInfo.
1335ffd83dbSDimitry Andric   static const ParsedAttrInfo DefaultParsedAttrInfo(
1345ffd83dbSDimitry Andric       AttributeCommonInfo::UnknownAttribute);
1355ffd83dbSDimitry Andric   return DefaultParsedAttrInfo;
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric 
138349cc55cSDimitry Andric ArrayRef<const ParsedAttrInfo *> ParsedAttrInfo::getAllBuiltin() {
139bdd1243dSDimitry Andric   return llvm::ArrayRef(AttrInfoMap);
140349cc55cSDimitry Andric }
141349cc55cSDimitry Andric 
1425ffd83dbSDimitry Andric unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; }
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric unsigned ParsedAttr::getMaxArgs() const {
1455ffd83dbSDimitry Andric   return getMinArgs() + getInfo().OptArgs;
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric 
14881ad6265SDimitry Andric unsigned ParsedAttr::getNumArgMembers() const {
14981ad6265SDimitry Andric   return getInfo().NumArgMembers;
15081ad6265SDimitry Andric }
15181ad6265SDimitry Andric 
1520b57cec5SDimitry Andric bool ParsedAttr::hasCustomParsing() const {
1535ffd83dbSDimitry Andric   return getInfo().HasCustomParsing;
1540b57cec5SDimitry Andric }
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
1575ffd83dbSDimitry Andric   return getInfo().diagAppertainsToDecl(S, *this, D);
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric 
160fe6060f1SDimitry Andric bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Stmt *St) const {
161fe6060f1SDimitry Andric   return getInfo().diagAppertainsToStmt(S, *this, St);
162fe6060f1SDimitry Andric }
163fe6060f1SDimitry Andric 
164fe6060f1SDimitry Andric bool ParsedAttr::diagnoseMutualExclusion(Sema &S, const Decl *D) const {
165fe6060f1SDimitry Andric   return getInfo().diagMutualExclusion(S, *this, D);
166fe6060f1SDimitry Andric }
167fe6060f1SDimitry Andric 
1680b57cec5SDimitry Andric bool ParsedAttr::appliesToDecl(const Decl *D,
1690b57cec5SDimitry Andric                                attr::SubjectMatchRule MatchRule) const {
1700b57cec5SDimitry Andric   return checkAttributeMatchRuleAppliesTo(D, MatchRule);
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric void ParsedAttr::getMatchRules(
1740b57cec5SDimitry Andric     const LangOptions &LangOpts,
1750b57cec5SDimitry Andric     SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
1760b57cec5SDimitry Andric     const {
1775ffd83dbSDimitry Andric   return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts);
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric bool ParsedAttr::diagnoseLangOpts(Sema &S) const {
181349cc55cSDimitry Andric   if (getInfo().acceptsLangOpts(S.getLangOpts()))
182349cc55cSDimitry Andric     return true;
183349cc55cSDimitry Andric   S.Diag(getLoc(), diag::warn_attribute_ignored) << *this;
184349cc55cSDimitry Andric   return false;
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric bool ParsedAttr::isTargetSpecificAttr() const {
1885ffd83dbSDimitry Andric   return getInfo().IsTargetSpecific;
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric 
1915ffd83dbSDimitry Andric bool ParsedAttr::isTypeAttr() const { return getInfo().IsType; }
1920b57cec5SDimitry Andric 
1935ffd83dbSDimitry Andric bool ParsedAttr::isStmtAttr() const { return getInfo().IsStmt; }
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {
1965ffd83dbSDimitry Andric   return getInfo().existsInTarget(Target);
1970b57cec5SDimitry Andric }
1980b57cec5SDimitry Andric 
1995ffd83dbSDimitry Andric bool ParsedAttr::isKnownToGCC() const { return getInfo().IsKnownToGCC; }
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric bool ParsedAttr::isSupportedByPragmaAttribute() const {
2025ffd83dbSDimitry Andric   return getInfo().IsSupportedByPragmaAttribute;
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric 
20581ad6265SDimitry Andric bool ParsedAttr::slidesFromDeclToDeclSpecLegacyBehavior() const {
206*06c3fb27SDimitry Andric   if (isRegularKeywordAttribute())
207*06c3fb27SDimitry Andric     // The appurtenance rules are applied strictly for all regular keyword
208*06c3fb27SDimitry Andric     // atributes.
209*06c3fb27SDimitry Andric     return false;
210*06c3fb27SDimitry Andric 
21181ad6265SDimitry Andric   assert(isStandardAttributeSyntax());
21281ad6265SDimitry Andric 
21381ad6265SDimitry Andric   // We have historically allowed some type attributes with standard attribute
21481ad6265SDimitry Andric   // syntax to slide to the decl-specifier-seq, so we have to keep supporting
21581ad6265SDimitry Andric   // it. This property is consciously not defined as a flag in Attr.td because
21681ad6265SDimitry Andric   // we don't want new attributes to specify it.
21781ad6265SDimitry Andric   //
21881ad6265SDimitry Andric   // Note: No new entries should be added to this list. Entries should be
21981ad6265SDimitry Andric   // removed from this list after a suitable deprecation period, provided that
22081ad6265SDimitry Andric   // there are no compatibility considerations with other compilers. If
22181ad6265SDimitry Andric   // possible, we would like this list to go away entirely.
22281ad6265SDimitry Andric   switch (getParsedKind()) {
22381ad6265SDimitry Andric   case AT_AddressSpace:
22481ad6265SDimitry Andric   case AT_OpenCLPrivateAddressSpace:
22581ad6265SDimitry Andric   case AT_OpenCLGlobalAddressSpace:
22681ad6265SDimitry Andric   case AT_OpenCLGlobalDeviceAddressSpace:
22781ad6265SDimitry Andric   case AT_OpenCLGlobalHostAddressSpace:
22881ad6265SDimitry Andric   case AT_OpenCLLocalAddressSpace:
22981ad6265SDimitry Andric   case AT_OpenCLConstantAddressSpace:
23081ad6265SDimitry Andric   case AT_OpenCLGenericAddressSpace:
23181ad6265SDimitry Andric   case AT_NeonPolyVectorType:
23281ad6265SDimitry Andric   case AT_NeonVectorType:
23381ad6265SDimitry Andric   case AT_ArmMveStrictPolymorphism:
23481ad6265SDimitry Andric   case AT_BTFTypeTag:
23581ad6265SDimitry Andric   case AT_ObjCGC:
23681ad6265SDimitry Andric   case AT_MatrixType:
23781ad6265SDimitry Andric     return true;
23881ad6265SDimitry Andric   default:
23981ad6265SDimitry Andric     return false;
24081ad6265SDimitry Andric   }
24181ad6265SDimitry Andric }
24281ad6265SDimitry Andric 
24381ad6265SDimitry Andric bool ParsedAttr::acceptsExprPack() const { return getInfo().AcceptsExprPack; }
24481ad6265SDimitry Andric 
2450b57cec5SDimitry Andric unsigned ParsedAttr::getSemanticSpelling() const {
2465ffd83dbSDimitry Andric   return getInfo().spellingIndexToSemanticSpelling(*this);
2470b57cec5SDimitry Andric }
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric bool ParsedAttr::hasVariadicArg() const {
2500b57cec5SDimitry Andric   // If the attribute has the maximum number of optional arguments, we will
2510b57cec5SDimitry Andric   // claim that as being variadic. If we someday get an attribute that
2520b57cec5SDimitry Andric   // legitimately bumps up against that maximum, we can use another bit to track
2530b57cec5SDimitry Andric   // whether it's truly variadic or not.
2545ffd83dbSDimitry Andric   return getInfo().OptArgs == 15;
2550b57cec5SDimitry Andric }
256fe6060f1SDimitry Andric 
25781ad6265SDimitry Andric bool ParsedAttr::isParamExpr(size_t N) const {
25881ad6265SDimitry Andric   return getInfo().isParamExpr(N);
25981ad6265SDimitry Andric }
26081ad6265SDimitry Andric 
26181ad6265SDimitry Andric void ParsedAttr::handleAttrWithDelayedArgs(Sema &S, Decl *D) const {
26281ad6265SDimitry Andric   ::handleAttrWithDelayedArgs(S, D, *this);
26381ad6265SDimitry Andric }
26481ad6265SDimitry Andric 
265fe6060f1SDimitry Andric static unsigned getNumAttributeArgs(const ParsedAttr &AL) {
266fe6060f1SDimitry Andric   // FIXME: Include the type in the argument list.
267fe6060f1SDimitry Andric   return AL.getNumArgs() + AL.hasParsedType();
268fe6060f1SDimitry Andric }
269fe6060f1SDimitry Andric 
270fe6060f1SDimitry Andric template <typename Compare>
271fe6060f1SDimitry Andric static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL,
272fe6060f1SDimitry Andric                                       unsigned Num, unsigned Diag,
273fe6060f1SDimitry Andric                                       Compare Comp) {
274fe6060f1SDimitry Andric   if (Comp(getNumAttributeArgs(AL), Num)) {
275fe6060f1SDimitry Andric     S.Diag(AL.getLoc(), Diag) << AL << Num;
276fe6060f1SDimitry Andric     return false;
277fe6060f1SDimitry Andric   }
278fe6060f1SDimitry Andric   return true;
279fe6060f1SDimitry Andric }
280fe6060f1SDimitry Andric 
281fe6060f1SDimitry Andric bool ParsedAttr::checkExactlyNumArgs(Sema &S, unsigned Num) const {
282fe6060f1SDimitry Andric   return checkAttributeNumArgsImpl(S, *this, Num,
283fe6060f1SDimitry Andric                                    diag::err_attribute_wrong_number_arguments,
284fe6060f1SDimitry Andric                                    std::not_equal_to<unsigned>());
285fe6060f1SDimitry Andric }
286fe6060f1SDimitry Andric bool ParsedAttr::checkAtLeastNumArgs(Sema &S, unsigned Num) const {
287fe6060f1SDimitry Andric   return checkAttributeNumArgsImpl(S, *this, Num,
288fe6060f1SDimitry Andric                                    diag::err_attribute_too_few_arguments,
289fe6060f1SDimitry Andric                                    std::less<unsigned>());
290fe6060f1SDimitry Andric }
291fe6060f1SDimitry Andric bool ParsedAttr::checkAtMostNumArgs(Sema &S, unsigned Num) const {
292fe6060f1SDimitry Andric   return checkAttributeNumArgsImpl(S, *this, Num,
293fe6060f1SDimitry Andric                                    diag::err_attribute_too_many_arguments,
294fe6060f1SDimitry Andric                                    std::greater<unsigned>());
295fe6060f1SDimitry Andric }
29681ad6265SDimitry Andric 
29781ad6265SDimitry Andric void clang::takeAndConcatenateAttrs(ParsedAttributes &First,
29881ad6265SDimitry Andric                                     ParsedAttributes &Second,
29981ad6265SDimitry Andric                                     ParsedAttributes &Result) {
30081ad6265SDimitry Andric   // Note that takeAllFrom() puts the attributes at the beginning of the list,
30181ad6265SDimitry Andric   // so to obtain the correct ordering, we add `Second`, then `First`.
30281ad6265SDimitry Andric   Result.takeAllFrom(Second);
30381ad6265SDimitry Andric   Result.takeAllFrom(First);
30481ad6265SDimitry Andric   if (First.Range.getBegin().isValid())
30581ad6265SDimitry Andric     Result.Range.setBegin(First.Range.getBegin());
30681ad6265SDimitry Andric   else
30781ad6265SDimitry Andric     Result.Range.setBegin(Second.Range.getBegin());
30881ad6265SDimitry Andric   if (Second.Range.getEnd().isValid())
30981ad6265SDimitry Andric     Result.Range.setEnd(Second.Range.getEnd());
31081ad6265SDimitry Andric   else
31181ad6265SDimitry Andric     Result.Range.setEnd(First.Range.getEnd());
31281ad6265SDimitry Andric }
313