//======- ParsedAttr.cpp --------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file defines the ParsedAttr class implementation // //===----------------------------------------------------------------------===// #include "clang/Sema/ParsedAttr.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/AttrSubjectMatchRules.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/SemaInternal.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include #include #include using namespace clang; IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc, IdentifierInfo *Ident) { IdentifierLoc *Result = new (Ctx) IdentifierLoc; Result->Loc = Loc; Result->Ident = Ident; return Result; } size_t ParsedAttr::allocated_size() const { if (IsAvailability) return AttributeFactory::AvailabilityAllocSize; else if (IsTypeTagForDatatype) return AttributeFactory::TypeTagForDatatypeAllocSize; else if (IsProperty) return AttributeFactory::PropertyAllocSize; else if (HasParsedType) return totalSizeToAlloc(0, 0, 0, 1, 0); return totalSizeToAlloc(NumArgs, 0, 0, 0, 0); } AttributeFactory::AttributeFactory() { // Go ahead and configure all the inline capacity. This is just a memset. FreeLists.resize(InlineFreeListsCapacity); } AttributeFactory::~AttributeFactory() = default; static size_t getFreeListIndexForSize(size_t size) { assert(size >= sizeof(ParsedAttr)); assert((size % sizeof(void*)) == 0); return ((size - sizeof(ParsedAttr)) / sizeof(void *)); } void *AttributeFactory::allocate(size_t size) { // Check for a previously reclaimed attribute. size_t index = getFreeListIndexForSize(size); if (index < FreeLists.size() && !FreeLists[index].empty()) { ParsedAttr *attr = FreeLists[index].back(); FreeLists[index].pop_back(); return attr; } // Otherwise, allocate something new. return Alloc.Allocate(size, alignof(AttributeFactory)); } void AttributeFactory::deallocate(ParsedAttr *Attr) { size_t size = Attr->allocated_size(); size_t freeListIndex = getFreeListIndexForSize(size); // Expand FreeLists to the appropriate size, if required. if (freeListIndex >= FreeLists.size()) FreeLists.resize(freeListIndex + 1); #ifndef NDEBUG // In debug mode, zero out the attribute to help find memory overwriting. memset(Attr, 0, size); #endif // Add 'Attr' to the appropriate free-list. FreeLists[freeListIndex].push_back(Attr); } void AttributeFactory::reclaimPool(AttributePool &cur) { for (ParsedAttr *AL : cur.Attrs) deallocate(AL); } void AttributePool::takePool(AttributePool &pool) { Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end()); pool.Attrs.clear(); } struct ParsedAttrInfo { unsigned NumArgs : 4; unsigned OptArgs : 4; unsigned HasCustomParsing : 1; unsigned IsTargetSpecific : 1; unsigned IsType : 1; unsigned IsStmt : 1; unsigned IsKnownToGCC : 1; unsigned IsSupportedByPragmaAttribute : 1; bool (*DiagAppertainsToDecl)(Sema &S, const ParsedAttr &Attr, const Decl *); bool (*DiagLangOpts)(Sema &S, const ParsedAttr &Attr); bool (*ExistsInTarget)(const TargetInfo &Target); unsigned (*SpellingIndexToSemanticSpelling)(const ParsedAttr &Attr); void (*GetPragmaAttributeMatchRules)( llvm::SmallVectorImpl> &Rules, const LangOptions &LangOpts); }; namespace { #include "clang/Sema/AttrParsedAttrImpl.inc" } // namespace static const ParsedAttrInfo &getInfo(const ParsedAttr &A) { return AttrInfoMap[A.getKind()]; } unsigned ParsedAttr::getMinArgs() const { return getInfo(*this).NumArgs; } unsigned ParsedAttr::getMaxArgs() const { return getMinArgs() + getInfo(*this).OptArgs; } bool ParsedAttr::hasCustomParsing() const { return getInfo(*this).HasCustomParsing; } bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const { return getInfo(*this).DiagAppertainsToDecl(S, *this, D); } bool ParsedAttr::appliesToDecl(const Decl *D, attr::SubjectMatchRule MatchRule) const { return checkAttributeMatchRuleAppliesTo(D, MatchRule); } void ParsedAttr::getMatchRules( const LangOptions &LangOpts, SmallVectorImpl> &MatchRules) const { return getInfo(*this).GetPragmaAttributeMatchRules(MatchRules, LangOpts); } bool ParsedAttr::diagnoseLangOpts(Sema &S) const { return getInfo(*this).DiagLangOpts(S, *this); } bool ParsedAttr::isTargetSpecificAttr() const { return getInfo(*this).IsTargetSpecific; } bool ParsedAttr::isTypeAttr() const { return getInfo(*this).IsType; } bool ParsedAttr::isStmtAttr() const { return getInfo(*this).IsStmt; } bool ParsedAttr::existsInTarget(const TargetInfo &Target) const { return getInfo(*this).ExistsInTarget(Target); } bool ParsedAttr::isKnownToGCC() const { return getInfo(*this).IsKnownToGCC; } bool ParsedAttr::isSupportedByPragmaAttribute() const { return getInfo(*this).IsSupportedByPragmaAttribute; } unsigned ParsedAttr::getSemanticSpelling() const { return getInfo(*this).SpellingIndexToSemanticSpelling(*this); } bool ParsedAttr::hasVariadicArg() const { // If the attribute has the maximum number of optional arguments, we will // claim that as being variadic. If we someday get an attribute that // legitimately bumps up against that maximum, we can use another bit to track // whether it's truly variadic or not. return getInfo(*this).OptArgs == 15; }