1 //===--- AttributeList.cpp --------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the AttributeList class implementation 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/Sema/AttributeList.h" 15 #include "clang/AST/ASTContext.h" 16 #include "clang/AST/DeclCXX.h" 17 #include "clang/AST/DeclTemplate.h" 18 #include "clang/AST/Expr.h" 19 #include "clang/Basic/IdentifierTable.h" 20 #include "clang/Sema/SemaInternal.h" 21 #include "llvm/ADT/SmallString.h" 22 #include "llvm/ADT/StringSwitch.h" 23 using namespace clang; 24 25 IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc, 26 IdentifierInfo *Ident) { 27 IdentifierLoc *Result = new (Ctx) IdentifierLoc; 28 Result->Loc = Loc; 29 Result->Ident = Ident; 30 return Result; 31 } 32 33 size_t AttributeList::allocated_size() const { 34 if (IsAvailability) return AttributeFactory::AvailabilityAllocSize; 35 else if (IsTypeTagForDatatype) 36 return AttributeFactory::TypeTagForDatatypeAllocSize; 37 else if (IsProperty) 38 return AttributeFactory::PropertyAllocSize; 39 return (sizeof(AttributeList) + NumArgs * sizeof(ArgsUnion)); 40 } 41 42 AttributeFactory::AttributeFactory() { 43 // Go ahead and configure all the inline capacity. This is just a memset. 44 FreeLists.resize(InlineFreeListsCapacity); 45 } 46 AttributeFactory::~AttributeFactory() {} 47 48 static size_t getFreeListIndexForSize(size_t size) { 49 assert(size >= sizeof(AttributeList)); 50 assert((size % sizeof(void*)) == 0); 51 return ((size - sizeof(AttributeList)) / sizeof(void*)); 52 } 53 54 void *AttributeFactory::allocate(size_t size) { 55 // Check for a previously reclaimed attribute. 56 size_t index = getFreeListIndexForSize(size); 57 if (index < FreeLists.size()) { 58 if (AttributeList *attr = FreeLists[index]) { 59 FreeLists[index] = attr->NextInPool; 60 return attr; 61 } 62 } 63 64 // Otherwise, allocate something new. 65 return Alloc.Allocate(size, llvm::AlignOf<AttributeFactory>::Alignment); 66 } 67 68 void AttributeFactory::reclaimPool(AttributeList *cur) { 69 assert(cur && "reclaiming empty pool!"); 70 do { 71 // Read this here, because we're going to overwrite NextInPool 72 // when we toss 'cur' into the appropriate queue. 73 AttributeList *next = cur->NextInPool; 74 75 size_t size = cur->allocated_size(); 76 size_t freeListIndex = getFreeListIndexForSize(size); 77 78 // Expand FreeLists to the appropriate size, if required. 79 if (freeListIndex >= FreeLists.size()) 80 FreeLists.resize(freeListIndex+1); 81 82 // Add 'cur' to the appropriate free-list. 83 cur->NextInPool = FreeLists[freeListIndex]; 84 FreeLists[freeListIndex] = cur; 85 86 cur = next; 87 } while (cur); 88 } 89 90 void AttributePool::takePool(AttributeList *pool) { 91 assert(pool); 92 93 // Fast path: this pool is empty. 94 if (!Head) { 95 Head = pool; 96 return; 97 } 98 99 // Reverse the pool onto the current head. This optimizes for the 100 // pattern of pulling a lot of pools into a single pool. 101 do { 102 AttributeList *next = pool->NextInPool; 103 pool->NextInPool = Head; 104 Head = pool; 105 pool = next; 106 } while (pool); 107 } 108 109 #include "clang/Sema/AttrParsedAttrKinds.inc" 110 111 AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name, 112 const IdentifierInfo *ScopeName, 113 Syntax SyntaxUsed) { 114 StringRef AttrName = Name->getName(); 115 116 SmallString<64> FullName; 117 if (ScopeName) 118 FullName += ScopeName->getName(); 119 120 // Normalize the attribute name, __foo__ becomes foo. This is only allowable 121 // for GNU attributes. 122 bool IsGNU = SyntaxUsed == AS_GNU || (SyntaxUsed == AS_CXX11 && 123 FullName == "gnu"); 124 if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") && 125 AttrName.endswith("__")) 126 AttrName = AttrName.slice(2, AttrName.size() - 2); 127 128 // Ensure that in the case of C++11 attributes, we look for '::foo' if it is 129 // unscoped. 130 if (ScopeName || SyntaxUsed == AS_CXX11) 131 FullName += "::"; 132 FullName += AttrName; 133 134 return ::getAttrKind(FullName, SyntaxUsed); 135 } 136 137 unsigned AttributeList::getAttributeSpellingListIndex() const { 138 // Both variables will be used in tablegen generated 139 // attribute spell list index matching code. 140 StringRef Name = AttrName->getName(); 141 StringRef Scope = ScopeName ? ScopeName->getName() : ""; 142 143 #include "clang/Sema/AttrSpellingListIndex.inc" 144 145 } 146 147 struct ParsedAttrInfo { 148 unsigned NumArgs : 4; 149 unsigned OptArgs : 4; 150 unsigned HasCustomParsing : 1; 151 unsigned IsTargetSpecific : 1; 152 unsigned IsType : 1; 153 unsigned IsKnownToGCC : 1; 154 155 bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr, 156 const Decl *); 157 bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr); 158 bool (*ExistsInTarget)(const llvm::Triple &T); 159 unsigned (*SpellingIndexToSemanticSpelling)(const AttributeList &Attr); 160 }; 161 162 namespace { 163 #include "clang/Sema/AttrParsedAttrImpl.inc" 164 } 165 166 static const ParsedAttrInfo &getInfo(const AttributeList &A) { 167 return AttrInfoMap[A.getKind()]; 168 } 169 170 unsigned AttributeList::getMinArgs() const { 171 return getInfo(*this).NumArgs; 172 } 173 174 unsigned AttributeList::getMaxArgs() const { 175 return getMinArgs() + getInfo(*this).OptArgs; 176 } 177 178 bool AttributeList::hasCustomParsing() const { 179 return getInfo(*this).HasCustomParsing; 180 } 181 182 bool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const { 183 return getInfo(*this).DiagAppertainsToDecl(S, *this, D); 184 } 185 186 bool AttributeList::diagnoseLangOpts(Sema &S) const { 187 return getInfo(*this).DiagLangOpts(S, *this); 188 } 189 190 bool AttributeList::isTargetSpecificAttr() const { 191 return getInfo(*this).IsTargetSpecific; 192 } 193 194 bool AttributeList::isTypeAttr() const { 195 return getInfo(*this).IsType; 196 } 197 198 bool AttributeList::existsInTarget(const llvm::Triple &T) const { 199 return getInfo(*this).ExistsInTarget(T); 200 } 201 202 bool AttributeList::isKnownToGCC() const { 203 return getInfo(*this).IsKnownToGCC; 204 } 205 206 unsigned AttributeList::getSemanticSpelling() const { 207 return getInfo(*this).SpellingIndexToSemanticSpelling(*this); 208 } 209