xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/Sema/ParsedAttr.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //======- ParsedAttr.cpp --------------------------------------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This file defines the ParsedAttr class implementation
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg 
137330f729Sjoerg #include "clang/Sema/ParsedAttr.h"
147330f729Sjoerg #include "clang/AST/ASTContext.h"
157330f729Sjoerg #include "clang/Basic/AttrSubjectMatchRules.h"
167330f729Sjoerg #include "clang/Basic/IdentifierTable.h"
177330f729Sjoerg #include "clang/Basic/TargetInfo.h"
187330f729Sjoerg #include "clang/Sema/SemaInternal.h"
197330f729Sjoerg #include "llvm/ADT/SmallString.h"
207330f729Sjoerg #include "llvm/ADT/SmallVector.h"
217330f729Sjoerg #include "llvm/ADT/StringRef.h"
22*e038c9c4Sjoerg #include "llvm/Support/ManagedStatic.h"
237330f729Sjoerg #include <cassert>
247330f729Sjoerg #include <cstddef>
257330f729Sjoerg #include <utility>
267330f729Sjoerg 
277330f729Sjoerg using namespace clang;
287330f729Sjoerg 
LLVM_INSTANTIATE_REGISTRY(ParsedAttrInfoRegistry)29*e038c9c4Sjoerg LLVM_INSTANTIATE_REGISTRY(ParsedAttrInfoRegistry)
30*e038c9c4Sjoerg 
317330f729Sjoerg IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
327330f729Sjoerg                                      IdentifierInfo *Ident) {
337330f729Sjoerg   IdentifierLoc *Result = new (Ctx) IdentifierLoc;
347330f729Sjoerg   Result->Loc = Loc;
357330f729Sjoerg   Result->Ident = Ident;
367330f729Sjoerg   return Result;
377330f729Sjoerg }
387330f729Sjoerg 
allocated_size() const397330f729Sjoerg size_t ParsedAttr::allocated_size() const {
407330f729Sjoerg   if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
417330f729Sjoerg   else if (IsTypeTagForDatatype)
427330f729Sjoerg     return AttributeFactory::TypeTagForDatatypeAllocSize;
437330f729Sjoerg   else if (IsProperty)
447330f729Sjoerg     return AttributeFactory::PropertyAllocSize;
457330f729Sjoerg   else if (HasParsedType)
467330f729Sjoerg     return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
477330f729Sjoerg                             detail::TypeTagForDatatypeData, ParsedType,
487330f729Sjoerg                             detail::PropertyData>(0, 0, 0, 1, 0);
497330f729Sjoerg   return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
507330f729Sjoerg                           detail::TypeTagForDatatypeData, ParsedType,
517330f729Sjoerg                           detail::PropertyData>(NumArgs, 0, 0, 0, 0);
527330f729Sjoerg }
537330f729Sjoerg 
AttributeFactory()547330f729Sjoerg AttributeFactory::AttributeFactory() {
557330f729Sjoerg   // Go ahead and configure all the inline capacity.  This is just a memset.
567330f729Sjoerg   FreeLists.resize(InlineFreeListsCapacity);
577330f729Sjoerg }
587330f729Sjoerg AttributeFactory::~AttributeFactory() = default;
597330f729Sjoerg 
getFreeListIndexForSize(size_t size)607330f729Sjoerg static size_t getFreeListIndexForSize(size_t size) {
617330f729Sjoerg   assert(size >= sizeof(ParsedAttr));
627330f729Sjoerg   assert((size % sizeof(void*)) == 0);
637330f729Sjoerg   return ((size - sizeof(ParsedAttr)) / sizeof(void *));
647330f729Sjoerg }
657330f729Sjoerg 
allocate(size_t size)667330f729Sjoerg void *AttributeFactory::allocate(size_t size) {
677330f729Sjoerg   // Check for a previously reclaimed attribute.
687330f729Sjoerg   size_t index = getFreeListIndexForSize(size);
697330f729Sjoerg   if (index < FreeLists.size() && !FreeLists[index].empty()) {
707330f729Sjoerg     ParsedAttr *attr = FreeLists[index].back();
717330f729Sjoerg     FreeLists[index].pop_back();
727330f729Sjoerg     return attr;
737330f729Sjoerg   }
747330f729Sjoerg 
757330f729Sjoerg   // Otherwise, allocate something new.
767330f729Sjoerg   return Alloc.Allocate(size, alignof(AttributeFactory));
777330f729Sjoerg }
787330f729Sjoerg 
deallocate(ParsedAttr * Attr)797330f729Sjoerg void AttributeFactory::deallocate(ParsedAttr *Attr) {
807330f729Sjoerg   size_t size = Attr->allocated_size();
817330f729Sjoerg   size_t freeListIndex = getFreeListIndexForSize(size);
827330f729Sjoerg 
837330f729Sjoerg   // Expand FreeLists to the appropriate size, if required.
847330f729Sjoerg   if (freeListIndex >= FreeLists.size())
857330f729Sjoerg     FreeLists.resize(freeListIndex + 1);
867330f729Sjoerg 
877330f729Sjoerg #ifndef NDEBUG
887330f729Sjoerg   // In debug mode, zero out the attribute to help find memory overwriting.
897330f729Sjoerg   memset(Attr, 0, size);
907330f729Sjoerg #endif
917330f729Sjoerg 
927330f729Sjoerg   // Add 'Attr' to the appropriate free-list.
937330f729Sjoerg   FreeLists[freeListIndex].push_back(Attr);
947330f729Sjoerg }
957330f729Sjoerg 
reclaimPool(AttributePool & cur)967330f729Sjoerg void AttributeFactory::reclaimPool(AttributePool &cur) {
977330f729Sjoerg   for (ParsedAttr *AL : cur.Attrs)
987330f729Sjoerg     deallocate(AL);
997330f729Sjoerg }
1007330f729Sjoerg 
takePool(AttributePool & pool)1017330f729Sjoerg void AttributePool::takePool(AttributePool &pool) {
1027330f729Sjoerg   Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
1037330f729Sjoerg   pool.Attrs.clear();
1047330f729Sjoerg }
1057330f729Sjoerg 
1067330f729Sjoerg namespace {
1077330f729Sjoerg 
1087330f729Sjoerg #include "clang/Sema/AttrParsedAttrImpl.inc"
1097330f729Sjoerg 
1107330f729Sjoerg } // namespace
1117330f729Sjoerg 
get(const AttributeCommonInfo & A)112*e038c9c4Sjoerg const ParsedAttrInfo &ParsedAttrInfo::get(const AttributeCommonInfo &A) {
113*e038c9c4Sjoerg   // If we have a ParsedAttrInfo for this ParsedAttr then return that.
114*e038c9c4Sjoerg   if ((size_t)A.getParsedKind() < llvm::array_lengthof(AttrInfoMap))
115*e038c9c4Sjoerg     return *AttrInfoMap[A.getParsedKind()];
116*e038c9c4Sjoerg 
117*e038c9c4Sjoerg   // If this is an ignored attribute then return an appropriate ParsedAttrInfo.
118*e038c9c4Sjoerg   static const ParsedAttrInfo IgnoredParsedAttrInfo(
119*e038c9c4Sjoerg       AttributeCommonInfo::IgnoredAttribute);
120*e038c9c4Sjoerg   if (A.getParsedKind() == AttributeCommonInfo::IgnoredAttribute)
121*e038c9c4Sjoerg     return IgnoredParsedAttrInfo;
122*e038c9c4Sjoerg 
123*e038c9c4Sjoerg   // Otherwise this may be an attribute defined by a plugin. First instantiate
124*e038c9c4Sjoerg   // all plugin attributes if we haven't already done so.
125*e038c9c4Sjoerg   static llvm::ManagedStatic<std::list<std::unique_ptr<ParsedAttrInfo>>>
126*e038c9c4Sjoerg       PluginAttrInstances;
127*e038c9c4Sjoerg   if (PluginAttrInstances->empty())
128*e038c9c4Sjoerg     for (auto It : ParsedAttrInfoRegistry::entries())
129*e038c9c4Sjoerg       PluginAttrInstances->emplace_back(It.instantiate());
130*e038c9c4Sjoerg 
131*e038c9c4Sjoerg   // Search for a ParsedAttrInfo whose name and syntax match.
132*e038c9c4Sjoerg   std::string FullName = A.getNormalizedFullName();
133*e038c9c4Sjoerg   AttributeCommonInfo::Syntax SyntaxUsed = A.getSyntax();
134*e038c9c4Sjoerg   if (SyntaxUsed == AttributeCommonInfo::AS_ContextSensitiveKeyword)
135*e038c9c4Sjoerg     SyntaxUsed = AttributeCommonInfo::AS_Keyword;
136*e038c9c4Sjoerg 
137*e038c9c4Sjoerg   for (auto &Ptr : *PluginAttrInstances)
138*e038c9c4Sjoerg     for (auto &S : Ptr->Spellings)
139*e038c9c4Sjoerg       if (S.Syntax == SyntaxUsed && S.NormalizedFullName == FullName)
140*e038c9c4Sjoerg         return *Ptr;
141*e038c9c4Sjoerg 
142*e038c9c4Sjoerg   // If we failed to find a match then return a default ParsedAttrInfo.
143*e038c9c4Sjoerg   static const ParsedAttrInfo DefaultParsedAttrInfo(
144*e038c9c4Sjoerg       AttributeCommonInfo::UnknownAttribute);
145*e038c9c4Sjoerg   return DefaultParsedAttrInfo;
1467330f729Sjoerg }
1477330f729Sjoerg 
getMinArgs() const148*e038c9c4Sjoerg unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; }
1497330f729Sjoerg 
getMaxArgs() const1507330f729Sjoerg unsigned ParsedAttr::getMaxArgs() const {
151*e038c9c4Sjoerg   return getMinArgs() + getInfo().OptArgs;
1527330f729Sjoerg }
1537330f729Sjoerg 
hasCustomParsing() const1547330f729Sjoerg bool ParsedAttr::hasCustomParsing() const {
155*e038c9c4Sjoerg   return getInfo().HasCustomParsing;
1567330f729Sjoerg }
1577330f729Sjoerg 
diagnoseAppertainsTo(Sema & S,const Decl * D) const1587330f729Sjoerg bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
159*e038c9c4Sjoerg   return getInfo().diagAppertainsToDecl(S, *this, D);
160*e038c9c4Sjoerg }
161*e038c9c4Sjoerg 
diagnoseAppertainsTo(Sema & S,const Stmt * St) const162*e038c9c4Sjoerg bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Stmt *St) const {
163*e038c9c4Sjoerg   return getInfo().diagAppertainsToStmt(S, *this, St);
164*e038c9c4Sjoerg }
165*e038c9c4Sjoerg 
diagnoseMutualExclusion(Sema & S,const Decl * D) const166*e038c9c4Sjoerg bool ParsedAttr::diagnoseMutualExclusion(Sema &S, const Decl *D) const {
167*e038c9c4Sjoerg   return getInfo().diagMutualExclusion(S, *this, D);
1687330f729Sjoerg }
1697330f729Sjoerg 
appliesToDecl(const Decl * D,attr::SubjectMatchRule MatchRule) const1707330f729Sjoerg bool ParsedAttr::appliesToDecl(const Decl *D,
1717330f729Sjoerg                                attr::SubjectMatchRule MatchRule) const {
1727330f729Sjoerg   return checkAttributeMatchRuleAppliesTo(D, MatchRule);
1737330f729Sjoerg }
1747330f729Sjoerg 
getMatchRules(const LangOptions & LangOpts,SmallVectorImpl<std::pair<attr::SubjectMatchRule,bool>> & MatchRules) const1757330f729Sjoerg void ParsedAttr::getMatchRules(
1767330f729Sjoerg     const LangOptions &LangOpts,
1777330f729Sjoerg     SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
1787330f729Sjoerg     const {
179*e038c9c4Sjoerg   return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts);
1807330f729Sjoerg }
1817330f729Sjoerg 
diagnoseLangOpts(Sema & S) const1827330f729Sjoerg bool ParsedAttr::diagnoseLangOpts(Sema &S) const {
183*e038c9c4Sjoerg   return getInfo().diagLangOpts(S, *this);
1847330f729Sjoerg }
1857330f729Sjoerg 
isTargetSpecificAttr() const1867330f729Sjoerg bool ParsedAttr::isTargetSpecificAttr() const {
187*e038c9c4Sjoerg   return getInfo().IsTargetSpecific;
1887330f729Sjoerg }
1897330f729Sjoerg 
isTypeAttr() const190*e038c9c4Sjoerg bool ParsedAttr::isTypeAttr() const { return getInfo().IsType; }
1917330f729Sjoerg 
isStmtAttr() const192*e038c9c4Sjoerg bool ParsedAttr::isStmtAttr() const { return getInfo().IsStmt; }
1937330f729Sjoerg 
existsInTarget(const TargetInfo & Target) const1947330f729Sjoerg bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {
195*e038c9c4Sjoerg   return getInfo().existsInTarget(Target);
1967330f729Sjoerg }
1977330f729Sjoerg 
isKnownToGCC() const198*e038c9c4Sjoerg bool ParsedAttr::isKnownToGCC() const { return getInfo().IsKnownToGCC; }
1997330f729Sjoerg 
isSupportedByPragmaAttribute() const2007330f729Sjoerg bool ParsedAttr::isSupportedByPragmaAttribute() const {
201*e038c9c4Sjoerg   return getInfo().IsSupportedByPragmaAttribute;
2027330f729Sjoerg }
2037330f729Sjoerg 
getSemanticSpelling() const2047330f729Sjoerg unsigned ParsedAttr::getSemanticSpelling() const {
205*e038c9c4Sjoerg   return getInfo().spellingIndexToSemanticSpelling(*this);
2067330f729Sjoerg }
2077330f729Sjoerg 
hasVariadicArg() const2087330f729Sjoerg bool ParsedAttr::hasVariadicArg() const {
2097330f729Sjoerg   // If the attribute has the maximum number of optional arguments, we will
2107330f729Sjoerg   // claim that as being variadic. If we someday get an attribute that
2117330f729Sjoerg   // legitimately bumps up against that maximum, we can use another bit to track
2127330f729Sjoerg   // whether it's truly variadic or not.
213*e038c9c4Sjoerg   return getInfo().OptArgs == 15;
214*e038c9c4Sjoerg }
215*e038c9c4Sjoerg 
getNumAttributeArgs(const ParsedAttr & AL)216*e038c9c4Sjoerg static unsigned getNumAttributeArgs(const ParsedAttr &AL) {
217*e038c9c4Sjoerg   // FIXME: Include the type in the argument list.
218*e038c9c4Sjoerg   return AL.getNumArgs() + AL.hasParsedType();
219*e038c9c4Sjoerg }
220*e038c9c4Sjoerg 
221*e038c9c4Sjoerg template <typename Compare>
checkAttributeNumArgsImpl(Sema & S,const ParsedAttr & AL,unsigned Num,unsigned Diag,Compare Comp)222*e038c9c4Sjoerg static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL,
223*e038c9c4Sjoerg                                       unsigned Num, unsigned Diag,
224*e038c9c4Sjoerg                                       Compare Comp) {
225*e038c9c4Sjoerg   if (Comp(getNumAttributeArgs(AL), Num)) {
226*e038c9c4Sjoerg     S.Diag(AL.getLoc(), Diag) << AL << Num;
227*e038c9c4Sjoerg     return false;
228*e038c9c4Sjoerg   }
229*e038c9c4Sjoerg   return true;
230*e038c9c4Sjoerg }
231*e038c9c4Sjoerg 
checkExactlyNumArgs(Sema & S,unsigned Num) const232*e038c9c4Sjoerg bool ParsedAttr::checkExactlyNumArgs(Sema &S, unsigned Num) const {
233*e038c9c4Sjoerg   return checkAttributeNumArgsImpl(S, *this, Num,
234*e038c9c4Sjoerg                                    diag::err_attribute_wrong_number_arguments,
235*e038c9c4Sjoerg                                    std::not_equal_to<unsigned>());
236*e038c9c4Sjoerg }
checkAtLeastNumArgs(Sema & S,unsigned Num) const237*e038c9c4Sjoerg bool ParsedAttr::checkAtLeastNumArgs(Sema &S, unsigned Num) const {
238*e038c9c4Sjoerg   return checkAttributeNumArgsImpl(S, *this, Num,
239*e038c9c4Sjoerg                                    diag::err_attribute_too_few_arguments,
240*e038c9c4Sjoerg                                    std::less<unsigned>());
241*e038c9c4Sjoerg }
checkAtMostNumArgs(Sema & S,unsigned Num) const242*e038c9c4Sjoerg bool ParsedAttr::checkAtMostNumArgs(Sema &S, unsigned Num) const {
243*e038c9c4Sjoerg   return checkAttributeNumArgsImpl(S, *this, Num,
244*e038c9c4Sjoerg                                    diag::err_attribute_too_many_arguments,
245*e038c9c4Sjoerg                                    std::greater<unsigned>());
2467330f729Sjoerg }
247