xref: /freebsd/contrib/llvm-project/clang/lib/Sema/ParsedAttr.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
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"
22*5ffd83dbSDimitry Andric #include "llvm/Support/ManagedStatic.h"
230b57cec5SDimitry Andric #include <cassert>
240b57cec5SDimitry Andric #include <cstddef>
250b57cec5SDimitry Andric #include <utility>
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric using namespace clang;
280b57cec5SDimitry Andric 
29*5ffd83dbSDimitry Andric LLVM_INSTANTIATE_REGISTRY(ParsedAttrInfoRegistry)
30*5ffd83dbSDimitry Andric 
310b57cec5SDimitry Andric IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
320b57cec5SDimitry Andric                                      IdentifierInfo *Ident) {
330b57cec5SDimitry Andric   IdentifierLoc *Result = new (Ctx) IdentifierLoc;
340b57cec5SDimitry Andric   Result->Loc = Loc;
350b57cec5SDimitry Andric   Result->Ident = Ident;
360b57cec5SDimitry Andric   return Result;
370b57cec5SDimitry Andric }
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric size_t ParsedAttr::allocated_size() const {
400b57cec5SDimitry Andric   if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
410b57cec5SDimitry Andric   else if (IsTypeTagForDatatype)
420b57cec5SDimitry Andric     return AttributeFactory::TypeTagForDatatypeAllocSize;
430b57cec5SDimitry Andric   else if (IsProperty)
440b57cec5SDimitry Andric     return AttributeFactory::PropertyAllocSize;
450b57cec5SDimitry Andric   else if (HasParsedType)
460b57cec5SDimitry Andric     return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
470b57cec5SDimitry Andric                             detail::TypeTagForDatatypeData, ParsedType,
480b57cec5SDimitry Andric                             detail::PropertyData>(0, 0, 0, 1, 0);
490b57cec5SDimitry Andric   return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
500b57cec5SDimitry Andric                           detail::TypeTagForDatatypeData, ParsedType,
510b57cec5SDimitry Andric                           detail::PropertyData>(NumArgs, 0, 0, 0, 0);
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric AttributeFactory::AttributeFactory() {
550b57cec5SDimitry Andric   // Go ahead and configure all the inline capacity.  This is just a memset.
560b57cec5SDimitry Andric   FreeLists.resize(InlineFreeListsCapacity);
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric AttributeFactory::~AttributeFactory() = default;
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric static size_t getFreeListIndexForSize(size_t size) {
610b57cec5SDimitry Andric   assert(size >= sizeof(ParsedAttr));
620b57cec5SDimitry Andric   assert((size % sizeof(void*)) == 0);
630b57cec5SDimitry Andric   return ((size - sizeof(ParsedAttr)) / sizeof(void *));
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric void *AttributeFactory::allocate(size_t size) {
670b57cec5SDimitry Andric   // Check for a previously reclaimed attribute.
680b57cec5SDimitry Andric   size_t index = getFreeListIndexForSize(size);
690b57cec5SDimitry Andric   if (index < FreeLists.size() && !FreeLists[index].empty()) {
700b57cec5SDimitry Andric     ParsedAttr *attr = FreeLists[index].back();
710b57cec5SDimitry Andric     FreeLists[index].pop_back();
720b57cec5SDimitry Andric     return attr;
730b57cec5SDimitry Andric   }
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   // Otherwise, allocate something new.
760b57cec5SDimitry Andric   return Alloc.Allocate(size, alignof(AttributeFactory));
770b57cec5SDimitry Andric }
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric void AttributeFactory::deallocate(ParsedAttr *Attr) {
800b57cec5SDimitry Andric   size_t size = Attr->allocated_size();
810b57cec5SDimitry Andric   size_t freeListIndex = getFreeListIndexForSize(size);
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   // Expand FreeLists to the appropriate size, if required.
840b57cec5SDimitry Andric   if (freeListIndex >= FreeLists.size())
850b57cec5SDimitry Andric     FreeLists.resize(freeListIndex + 1);
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric #ifndef NDEBUG
880b57cec5SDimitry Andric   // In debug mode, zero out the attribute to help find memory overwriting.
890b57cec5SDimitry Andric   memset(Attr, 0, size);
900b57cec5SDimitry Andric #endif
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   // Add 'Attr' to the appropriate free-list.
930b57cec5SDimitry Andric   FreeLists[freeListIndex].push_back(Attr);
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric void AttributeFactory::reclaimPool(AttributePool &cur) {
970b57cec5SDimitry Andric   for (ParsedAttr *AL : cur.Attrs)
980b57cec5SDimitry Andric     deallocate(AL);
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric void AttributePool::takePool(AttributePool &pool) {
1020b57cec5SDimitry Andric   Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
1030b57cec5SDimitry Andric   pool.Attrs.clear();
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric namespace {
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric #include "clang/Sema/AttrParsedAttrImpl.inc"
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric } // namespace
1110b57cec5SDimitry Andric 
112*5ffd83dbSDimitry Andric const ParsedAttrInfo &ParsedAttrInfo::get(const AttributeCommonInfo &A) {
113*5ffd83dbSDimitry Andric   // If we have a ParsedAttrInfo for this ParsedAttr then return that.
114*5ffd83dbSDimitry Andric   if ((size_t)A.getParsedKind() < llvm::array_lengthof(AttrInfoMap))
115*5ffd83dbSDimitry Andric     return *AttrInfoMap[A.getParsedKind()];
116*5ffd83dbSDimitry Andric 
117*5ffd83dbSDimitry Andric   // If this is an ignored attribute then return an appropriate ParsedAttrInfo.
118*5ffd83dbSDimitry Andric   static const ParsedAttrInfo IgnoredParsedAttrInfo(
119*5ffd83dbSDimitry Andric       AttributeCommonInfo::IgnoredAttribute);
120*5ffd83dbSDimitry Andric   if (A.getParsedKind() == AttributeCommonInfo::IgnoredAttribute)
121*5ffd83dbSDimitry Andric     return IgnoredParsedAttrInfo;
122*5ffd83dbSDimitry Andric 
123*5ffd83dbSDimitry Andric   // Otherwise this may be an attribute defined by a plugin. First instantiate
124*5ffd83dbSDimitry Andric   // all plugin attributes if we haven't already done so.
125*5ffd83dbSDimitry Andric   static llvm::ManagedStatic<std::list<std::unique_ptr<ParsedAttrInfo>>>
126*5ffd83dbSDimitry Andric       PluginAttrInstances;
127*5ffd83dbSDimitry Andric   if (PluginAttrInstances->empty())
128*5ffd83dbSDimitry Andric     for (auto It : ParsedAttrInfoRegistry::entries())
129*5ffd83dbSDimitry Andric       PluginAttrInstances->emplace_back(It.instantiate());
130*5ffd83dbSDimitry Andric 
131*5ffd83dbSDimitry Andric   // Search for a ParsedAttrInfo whose name and syntax match.
132*5ffd83dbSDimitry Andric   std::string FullName = A.getNormalizedFullName();
133*5ffd83dbSDimitry Andric   AttributeCommonInfo::Syntax SyntaxUsed = A.getSyntax();
134*5ffd83dbSDimitry Andric   if (SyntaxUsed == AttributeCommonInfo::AS_ContextSensitiveKeyword)
135*5ffd83dbSDimitry Andric     SyntaxUsed = AttributeCommonInfo::AS_Keyword;
136*5ffd83dbSDimitry Andric 
137*5ffd83dbSDimitry Andric   for (auto &Ptr : *PluginAttrInstances)
138*5ffd83dbSDimitry Andric     for (auto &S : Ptr->Spellings)
139*5ffd83dbSDimitry Andric       if (S.Syntax == SyntaxUsed && S.NormalizedFullName == FullName)
140*5ffd83dbSDimitry Andric         return *Ptr;
141*5ffd83dbSDimitry Andric 
142*5ffd83dbSDimitry Andric   // If we failed to find a match then return a default ParsedAttrInfo.
143*5ffd83dbSDimitry Andric   static const ParsedAttrInfo DefaultParsedAttrInfo(
144*5ffd83dbSDimitry Andric       AttributeCommonInfo::UnknownAttribute);
145*5ffd83dbSDimitry Andric   return DefaultParsedAttrInfo;
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric 
148*5ffd83dbSDimitry Andric unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; }
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric unsigned ParsedAttr::getMaxArgs() const {
151*5ffd83dbSDimitry Andric   return getMinArgs() + getInfo().OptArgs;
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric bool ParsedAttr::hasCustomParsing() const {
155*5ffd83dbSDimitry Andric   return getInfo().HasCustomParsing;
1560b57cec5SDimitry Andric }
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
159*5ffd83dbSDimitry Andric   return getInfo().diagAppertainsToDecl(S, *this, D);
1600b57cec5SDimitry Andric }
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric bool ParsedAttr::appliesToDecl(const Decl *D,
1630b57cec5SDimitry Andric                                attr::SubjectMatchRule MatchRule) const {
1640b57cec5SDimitry Andric   return checkAttributeMatchRuleAppliesTo(D, MatchRule);
1650b57cec5SDimitry Andric }
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric void ParsedAttr::getMatchRules(
1680b57cec5SDimitry Andric     const LangOptions &LangOpts,
1690b57cec5SDimitry Andric     SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
1700b57cec5SDimitry Andric     const {
171*5ffd83dbSDimitry Andric   return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts);
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric bool ParsedAttr::diagnoseLangOpts(Sema &S) const {
175*5ffd83dbSDimitry Andric   return getInfo().diagLangOpts(S, *this);
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric bool ParsedAttr::isTargetSpecificAttr() const {
179*5ffd83dbSDimitry Andric   return getInfo().IsTargetSpecific;
1800b57cec5SDimitry Andric }
1810b57cec5SDimitry Andric 
182*5ffd83dbSDimitry Andric bool ParsedAttr::isTypeAttr() const { return getInfo().IsType; }
1830b57cec5SDimitry Andric 
184*5ffd83dbSDimitry Andric bool ParsedAttr::isStmtAttr() const { return getInfo().IsStmt; }
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {
187*5ffd83dbSDimitry Andric   return getInfo().existsInTarget(Target);
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric 
190*5ffd83dbSDimitry Andric bool ParsedAttr::isKnownToGCC() const { return getInfo().IsKnownToGCC; }
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric bool ParsedAttr::isSupportedByPragmaAttribute() const {
193*5ffd83dbSDimitry Andric   return getInfo().IsSupportedByPragmaAttribute;
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric unsigned ParsedAttr::getSemanticSpelling() const {
197*5ffd83dbSDimitry Andric   return getInfo().spellingIndexToSemanticSpelling(*this);
1980b57cec5SDimitry Andric }
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric bool ParsedAttr::hasVariadicArg() const {
2010b57cec5SDimitry Andric   // If the attribute has the maximum number of optional arguments, we will
2020b57cec5SDimitry Andric   // claim that as being variadic. If we someday get an attribute that
2030b57cec5SDimitry Andric   // legitimately bumps up against that maximum, we can use another bit to track
2040b57cec5SDimitry Andric   // whether it's truly variadic or not.
205*5ffd83dbSDimitry Andric   return getInfo().OptArgs == 15;
2060b57cec5SDimitry Andric }
207