AttributeList.cpp revision 280031
1212795Sdim//===--- AttributeList.cpp --------------------------------------*- C++ -*-===// 2212795Sdim// 3212795Sdim// The LLVM Compiler Infrastructure 4212795Sdim// 5212795Sdim// This file is distributed under the University of Illinois Open Source 6212795Sdim// License. See LICENSE.TXT for details. 7212795Sdim// 8212795Sdim//===----------------------------------------------------------------------===// 9212795Sdim// 10212795Sdim// This file defines the AttributeList class implementation 11212795Sdim// 12212795Sdim//===----------------------------------------------------------------------===// 13212795Sdim 14212795Sdim#include "clang/Sema/AttributeList.h" 15239462Sdim#include "clang/AST/ASTContext.h" 16276479Sdim#include "clang/AST/DeclCXX.h" 17276479Sdim#include "clang/AST/DeclTemplate.h" 18221345Sdim#include "clang/AST/Expr.h" 19212795Sdim#include "clang/Basic/IdentifierTable.h" 20276479Sdim#include "clang/Sema/SemaInternal.h" 21249423Sdim#include "llvm/ADT/SmallString.h" 22212795Sdim#include "llvm/ADT/StringSwitch.h" 23212795Sdimusing namespace clang; 24212795Sdim 25261991SdimIdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc, 26261991Sdim IdentifierInfo *Ident) { 27261991Sdim IdentifierLoc *Result = new (Ctx) IdentifierLoc; 28261991Sdim Result->Loc = Loc; 29261991Sdim Result->Ident = Ident; 30261991Sdim return Result; 31261991Sdim} 32261991Sdim 33221345Sdimsize_t AttributeList::allocated_size() const { 34221345Sdim if (IsAvailability) return AttributeFactory::AvailabilityAllocSize; 35239462Sdim else if (IsTypeTagForDatatype) 36239462Sdim return AttributeFactory::TypeTagForDatatypeAllocSize; 37251662Sdim else if (IsProperty) 38251662Sdim return AttributeFactory::PropertyAllocSize; 39261991Sdim return (sizeof(AttributeList) + NumArgs * sizeof(ArgsUnion)); 40221345Sdim} 41212795Sdim 42221345SdimAttributeFactory::AttributeFactory() { 43221345Sdim // Go ahead and configure all the inline capacity. This is just a memset. 44221345Sdim FreeLists.resize(InlineFreeListsCapacity); 45221345Sdim} 46221345SdimAttributeFactory::~AttributeFactory() {} 47221345Sdim 48221345Sdimstatic size_t getFreeListIndexForSize(size_t size) { 49221345Sdim assert(size >= sizeof(AttributeList)); 50221345Sdim assert((size % sizeof(void*)) == 0); 51221345Sdim return ((size - sizeof(AttributeList)) / sizeof(void*)); 52221345Sdim} 53221345Sdim 54221345Sdimvoid *AttributeFactory::allocate(size_t size) { 55221345Sdim // Check for a previously reclaimed attribute. 56221345Sdim size_t index = getFreeListIndexForSize(size); 57221345Sdim if (index < FreeLists.size()) { 58221345Sdim if (AttributeList *attr = FreeLists[index]) { 59221345Sdim FreeLists[index] = attr->NextInPool; 60221345Sdim return attr; 61221345Sdim } 62212795Sdim } 63221345Sdim 64221345Sdim // Otherwise, allocate something new. 65221345Sdim return Alloc.Allocate(size, llvm::AlignOf<AttributeFactory>::Alignment); 66212795Sdim} 67212795Sdim 68221345Sdimvoid AttributeFactory::reclaimPool(AttributeList *cur) { 69221345Sdim assert(cur && "reclaiming empty pool!"); 70221345Sdim do { 71221345Sdim // Read this here, because we're going to overwrite NextInPool 72221345Sdim // when we toss 'cur' into the appropriate queue. 73221345Sdim AttributeList *next = cur->NextInPool; 74221345Sdim 75221345Sdim size_t size = cur->allocated_size(); 76221345Sdim size_t freeListIndex = getFreeListIndexForSize(size); 77221345Sdim 78221345Sdim // Expand FreeLists to the appropriate size, if required. 79221345Sdim if (freeListIndex >= FreeLists.size()) 80221345Sdim FreeLists.resize(freeListIndex+1); 81221345Sdim 82221345Sdim // Add 'cur' to the appropriate free-list. 83221345Sdim cur->NextInPool = FreeLists[freeListIndex]; 84221345Sdim FreeLists[freeListIndex] = cur; 85221345Sdim 86221345Sdim cur = next; 87221345Sdim } while (cur); 88221345Sdim} 89221345Sdim 90221345Sdimvoid AttributePool::takePool(AttributeList *pool) { 91221345Sdim assert(pool); 92221345Sdim 93221345Sdim // Fast path: this pool is empty. 94221345Sdim if (!Head) { 95221345Sdim Head = pool; 96221345Sdim return; 97221345Sdim } 98221345Sdim 99221345Sdim // Reverse the pool onto the current head. This optimizes for the 100221345Sdim // pattern of pulling a lot of pools into a single pool. 101221345Sdim do { 102221345Sdim AttributeList *next = pool->NextInPool; 103221345Sdim pool->NextInPool = Head; 104221345Sdim Head = pool; 105221345Sdim pool = next; 106221345Sdim } while (pool); 107221345Sdim} 108221345Sdim 109239462Sdim#include "clang/Sema/AttrParsedAttrKinds.inc" 110239462Sdim 111239462SdimAttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name, 112239462Sdim const IdentifierInfo *ScopeName, 113239462Sdim Syntax SyntaxUsed) { 114226633Sdim StringRef AttrName = Name->getName(); 115212795Sdim 116276479Sdim SmallString<64> FullName; 117276479Sdim if (ScopeName) 118276479Sdim FullName += ScopeName->getName(); 119212795Sdim 120276479Sdim // Normalize the attribute name, __foo__ becomes foo. This is only allowable 121276479Sdim // for GNU attributes. 122276479Sdim bool IsGNU = SyntaxUsed == AS_GNU || (SyntaxUsed == AS_CXX11 && 123276479Sdim FullName == "gnu"); 124276479Sdim if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") && 125276479Sdim AttrName.endswith("__")) 126276479Sdim AttrName = AttrName.slice(2, AttrName.size() - 2); 127276479Sdim 128239462Sdim // Ensure that in the case of C++11 attributes, we look for '::foo' if it is 129239462Sdim // unscoped. 130239462Sdim if (ScopeName || SyntaxUsed == AS_CXX11) 131276479Sdim FullName += "::"; 132276479Sdim FullName += AttrName; 133239462Sdim 134276479Sdim return ::getAttrKind(FullName, SyntaxUsed); 135212795Sdim} 136249423Sdim 137249423Sdimunsigned AttributeList::getAttributeSpellingListIndex() const { 138249423Sdim // Both variables will be used in tablegen generated 139249423Sdim // attribute spell list index matching code. 140249423Sdim StringRef Name = AttrName->getName(); 141249423Sdim StringRef Scope = ScopeName ? ScopeName->getName() : ""; 142249423Sdim 143249423Sdim#include "clang/Sema/AttrSpellingListIndex.inc" 144249423Sdim 145249423Sdim} 146249423Sdim 147261991Sdimstruct ParsedAttrInfo { 148261991Sdim unsigned NumArgs : 4; 149261991Sdim unsigned OptArgs : 4; 150261991Sdim unsigned HasCustomParsing : 1; 151276479Sdim unsigned IsTargetSpecific : 1; 152276479Sdim unsigned IsType : 1; 153276479Sdim unsigned IsKnownToGCC : 1; 154276479Sdim 155276479Sdim bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr, 156276479Sdim const Decl *); 157276479Sdim bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr); 158276479Sdim bool (*ExistsInTarget)(const llvm::Triple &T); 159276479Sdim unsigned (*SpellingIndexToSemanticSpelling)(const AttributeList &Attr); 160261991Sdim}; 161261991Sdim 162261991Sdimnamespace { 163261991Sdim #include "clang/Sema/AttrParsedAttrImpl.inc" 164261991Sdim} 165261991Sdim 166261991Sdimstatic const ParsedAttrInfo &getInfo(const AttributeList &A) { 167261991Sdim return AttrInfoMap[A.getKind()]; 168261991Sdim} 169261991Sdim 170261991Sdimunsigned AttributeList::getMinArgs() const { 171261991Sdim return getInfo(*this).NumArgs; 172261991Sdim} 173261991Sdim 174261991Sdimunsigned AttributeList::getMaxArgs() const { 175261991Sdim return getMinArgs() + getInfo(*this).OptArgs; 176261991Sdim} 177261991Sdim 178261991Sdimbool AttributeList::hasCustomParsing() const { 179261991Sdim return getInfo(*this).HasCustomParsing; 180261991Sdim} 181276479Sdim 182276479Sdimbool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const { 183276479Sdim return getInfo(*this).DiagAppertainsToDecl(S, *this, D); 184276479Sdim} 185276479Sdim 186276479Sdimbool AttributeList::diagnoseLangOpts(Sema &S) const { 187276479Sdim return getInfo(*this).DiagLangOpts(S, *this); 188276479Sdim} 189276479Sdim 190276479Sdimbool AttributeList::isTargetSpecificAttr() const { 191276479Sdim return getInfo(*this).IsTargetSpecific; 192276479Sdim} 193276479Sdim 194276479Sdimbool AttributeList::isTypeAttr() const { 195276479Sdim return getInfo(*this).IsType; 196276479Sdim} 197276479Sdim 198276479Sdimbool AttributeList::existsInTarget(const llvm::Triple &T) const { 199276479Sdim return getInfo(*this).ExistsInTarget(T); 200276479Sdim} 201276479Sdim 202276479Sdimbool AttributeList::isKnownToGCC() const { 203276479Sdim return getInfo(*this).IsKnownToGCC; 204276479Sdim} 205276479Sdim 206276479Sdimunsigned AttributeList::getSemanticSpelling() const { 207276479Sdim return getInfo(*this).SpellingIndexToSemanticSpelling(*this); 208276479Sdim} 209280031Sdim 210280031Sdimbool AttributeList::hasVariadicArg() const { 211280031Sdim // If the attribute has the maximum number of optional arguments, we will 212280031Sdim // claim that as being variadic. If we someday get an attribute that 213280031Sdim // legitimately bumps up against that maximum, we can use another bit to track 214280031Sdim // whether it's truly variadic or not. 215280031Sdim return getInfo(*this).OptArgs == 15; 216280031Sdim} 217