1 //======- ParsedAttr.cpp --------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines the ParsedAttr class implementation 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/Sema/ParsedAttr.h" 14 #include "clang/AST/ASTContext.h" 15 #include "clang/Basic/AttrSubjectMatchRules.h" 16 #include "clang/Basic/IdentifierTable.h" 17 #include "clang/Basic/TargetInfo.h" 18 #include "clang/Sema/SemaInternal.h" 19 #include "llvm/ADT/SmallString.h" 20 #include "llvm/ADT/SmallVector.h" 21 #include "llvm/ADT/StringRef.h" 22 #include <cassert> 23 #include <cstddef> 24 #include <utility> 25 26 using namespace clang; 27 28 IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc, 29 IdentifierInfo *Ident) { 30 IdentifierLoc *Result = new (Ctx) IdentifierLoc; 31 Result->Loc = Loc; 32 Result->Ident = Ident; 33 return Result; 34 } 35 36 size_t ParsedAttr::allocated_size() const { 37 if (IsAvailability) return AttributeFactory::AvailabilityAllocSize; 38 else if (IsTypeTagForDatatype) 39 return AttributeFactory::TypeTagForDatatypeAllocSize; 40 else if (IsProperty) 41 return AttributeFactory::PropertyAllocSize; 42 else if (HasParsedType) 43 return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 44 detail::TypeTagForDatatypeData, ParsedType, 45 detail::PropertyData>(0, 0, 0, 1, 0); 46 return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 47 detail::TypeTagForDatatypeData, ParsedType, 48 detail::PropertyData>(NumArgs, 0, 0, 0, 0); 49 } 50 51 AttributeFactory::AttributeFactory() { 52 // Go ahead and configure all the inline capacity. This is just a memset. 53 FreeLists.resize(InlineFreeListsCapacity); 54 } 55 AttributeFactory::~AttributeFactory() = default; 56 57 static size_t getFreeListIndexForSize(size_t size) { 58 assert(size >= sizeof(ParsedAttr)); 59 assert((size % sizeof(void*)) == 0); 60 return ((size - sizeof(ParsedAttr)) / sizeof(void *)); 61 } 62 63 void *AttributeFactory::allocate(size_t size) { 64 // Check for a previously reclaimed attribute. 65 size_t index = getFreeListIndexForSize(size); 66 if (index < FreeLists.size() && !FreeLists[index].empty()) { 67 ParsedAttr *attr = FreeLists[index].back(); 68 FreeLists[index].pop_back(); 69 return attr; 70 } 71 72 // Otherwise, allocate something new. 73 return Alloc.Allocate(size, alignof(AttributeFactory)); 74 } 75 76 void AttributeFactory::deallocate(ParsedAttr *Attr) { 77 size_t size = Attr->allocated_size(); 78 size_t freeListIndex = getFreeListIndexForSize(size); 79 80 // Expand FreeLists to the appropriate size, if required. 81 if (freeListIndex >= FreeLists.size()) 82 FreeLists.resize(freeListIndex + 1); 83 84 #ifndef NDEBUG 85 // In debug mode, zero out the attribute to help find memory overwriting. 86 memset(Attr, 0, size); 87 #endif 88 89 // Add 'Attr' to the appropriate free-list. 90 FreeLists[freeListIndex].push_back(Attr); 91 } 92 93 void AttributeFactory::reclaimPool(AttributePool &cur) { 94 for (ParsedAttr *AL : cur.Attrs) 95 deallocate(AL); 96 } 97 98 void AttributePool::takePool(AttributePool &pool) { 99 Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end()); 100 pool.Attrs.clear(); 101 } 102 103 struct ParsedAttrInfo { 104 unsigned NumArgs : 4; 105 unsigned OptArgs : 4; 106 unsigned HasCustomParsing : 1; 107 unsigned IsTargetSpecific : 1; 108 unsigned IsType : 1; 109 unsigned IsStmt : 1; 110 unsigned IsKnownToGCC : 1; 111 unsigned IsSupportedByPragmaAttribute : 1; 112 113 bool (*DiagAppertainsToDecl)(Sema &S, const ParsedAttr &Attr, const Decl *); 114 bool (*DiagLangOpts)(Sema &S, const ParsedAttr &Attr); 115 bool (*ExistsInTarget)(const TargetInfo &Target); 116 unsigned (*SpellingIndexToSemanticSpelling)(const ParsedAttr &Attr); 117 void (*GetPragmaAttributeMatchRules)( 118 llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules, 119 const LangOptions &LangOpts); 120 }; 121 122 namespace { 123 124 #include "clang/Sema/AttrParsedAttrImpl.inc" 125 126 } // namespace 127 128 static const ParsedAttrInfo &getInfo(const ParsedAttr &A) { 129 return AttrInfoMap[A.getKind()]; 130 } 131 132 unsigned ParsedAttr::getMinArgs() const { return getInfo(*this).NumArgs; } 133 134 unsigned ParsedAttr::getMaxArgs() const { 135 return getMinArgs() + getInfo(*this).OptArgs; 136 } 137 138 bool ParsedAttr::hasCustomParsing() const { 139 return getInfo(*this).HasCustomParsing; 140 } 141 142 bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const { 143 return getInfo(*this).DiagAppertainsToDecl(S, *this, D); 144 } 145 146 bool ParsedAttr::appliesToDecl(const Decl *D, 147 attr::SubjectMatchRule MatchRule) const { 148 return checkAttributeMatchRuleAppliesTo(D, MatchRule); 149 } 150 151 void ParsedAttr::getMatchRules( 152 const LangOptions &LangOpts, 153 SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules) 154 const { 155 return getInfo(*this).GetPragmaAttributeMatchRules(MatchRules, LangOpts); 156 } 157 158 bool ParsedAttr::diagnoseLangOpts(Sema &S) const { 159 return getInfo(*this).DiagLangOpts(S, *this); 160 } 161 162 bool ParsedAttr::isTargetSpecificAttr() const { 163 return getInfo(*this).IsTargetSpecific; 164 } 165 166 bool ParsedAttr::isTypeAttr() const { return getInfo(*this).IsType; } 167 168 bool ParsedAttr::isStmtAttr() const { return getInfo(*this).IsStmt; } 169 170 bool ParsedAttr::existsInTarget(const TargetInfo &Target) const { 171 return getInfo(*this).ExistsInTarget(Target); 172 } 173 174 bool ParsedAttr::isKnownToGCC() const { return getInfo(*this).IsKnownToGCC; } 175 176 bool ParsedAttr::isSupportedByPragmaAttribute() const { 177 return getInfo(*this).IsSupportedByPragmaAttribute; 178 } 179 180 unsigned ParsedAttr::getSemanticSpelling() const { 181 return getInfo(*this).SpellingIndexToSemanticSpelling(*this); 182 } 183 184 bool ParsedAttr::hasVariadicArg() const { 185 // If the attribute has the maximum number of optional arguments, we will 186 // claim that as being variadic. If we someday get an attribute that 187 // legitimately bumps up against that maximum, we can use another bit to track 188 // whether it's truly variadic or not. 189 return getInfo(*this).OptArgs == 15; 190 } 191