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" 20296417Sdim#include "clang/Basic/TargetInfo.h" 21276479Sdim#include "clang/Sema/SemaInternal.h" 22249423Sdim#include "llvm/ADT/SmallString.h" 23212795Sdim#include "llvm/ADT/StringSwitch.h" 24212795Sdimusing namespace clang; 25212795Sdim 26261991SdimIdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc, 27261991Sdim IdentifierInfo *Ident) { 28261991Sdim IdentifierLoc *Result = new (Ctx) IdentifierLoc; 29261991Sdim Result->Loc = Loc; 30261991Sdim Result->Ident = Ident; 31261991Sdim return Result; 32261991Sdim} 33261991Sdim 34221345Sdimsize_t AttributeList::allocated_size() const { 35221345Sdim if (IsAvailability) return AttributeFactory::AvailabilityAllocSize; 36239462Sdim else if (IsTypeTagForDatatype) 37239462Sdim return AttributeFactory::TypeTagForDatatypeAllocSize; 38251662Sdim else if (IsProperty) 39251662Sdim return AttributeFactory::PropertyAllocSize; 40261991Sdim return (sizeof(AttributeList) + NumArgs * sizeof(ArgsUnion)); 41221345Sdim} 42212795Sdim 43221345SdimAttributeFactory::AttributeFactory() { 44221345Sdim // Go ahead and configure all the inline capacity. This is just a memset. 45221345Sdim FreeLists.resize(InlineFreeListsCapacity); 46221345Sdim} 47221345SdimAttributeFactory::~AttributeFactory() {} 48221345Sdim 49221345Sdimstatic size_t getFreeListIndexForSize(size_t size) { 50221345Sdim assert(size >= sizeof(AttributeList)); 51221345Sdim assert((size % sizeof(void*)) == 0); 52221345Sdim return ((size - sizeof(AttributeList)) / sizeof(void*)); 53221345Sdim} 54221345Sdim 55221345Sdimvoid *AttributeFactory::allocate(size_t size) { 56221345Sdim // Check for a previously reclaimed attribute. 57221345Sdim size_t index = getFreeListIndexForSize(size); 58221345Sdim if (index < FreeLists.size()) { 59221345Sdim if (AttributeList *attr = FreeLists[index]) { 60221345Sdim FreeLists[index] = attr->NextInPool; 61221345Sdim return attr; 62221345Sdim } 63212795Sdim } 64221345Sdim 65221345Sdim // Otherwise, allocate something new. 66221345Sdim return Alloc.Allocate(size, llvm::AlignOf<AttributeFactory>::Alignment); 67212795Sdim} 68212795Sdim 69221345Sdimvoid AttributeFactory::reclaimPool(AttributeList *cur) { 70221345Sdim assert(cur && "reclaiming empty pool!"); 71221345Sdim do { 72221345Sdim // Read this here, because we're going to overwrite NextInPool 73221345Sdim // when we toss 'cur' into the appropriate queue. 74221345Sdim AttributeList *next = cur->NextInPool; 75221345Sdim 76221345Sdim size_t size = cur->allocated_size(); 77221345Sdim size_t freeListIndex = getFreeListIndexForSize(size); 78221345Sdim 79221345Sdim // Expand FreeLists to the appropriate size, if required. 80221345Sdim if (freeListIndex >= FreeLists.size()) 81221345Sdim FreeLists.resize(freeListIndex+1); 82221345Sdim 83221345Sdim // Add 'cur' to the appropriate free-list. 84221345Sdim cur->NextInPool = FreeLists[freeListIndex]; 85221345Sdim FreeLists[freeListIndex] = cur; 86221345Sdim 87221345Sdim cur = next; 88221345Sdim } while (cur); 89221345Sdim} 90221345Sdim 91221345Sdimvoid AttributePool::takePool(AttributeList *pool) { 92221345Sdim assert(pool); 93221345Sdim 94221345Sdim // Fast path: this pool is empty. 95221345Sdim if (!Head) { 96221345Sdim Head = pool; 97221345Sdim return; 98221345Sdim } 99221345Sdim 100221345Sdim // Reverse the pool onto the current head. This optimizes for the 101221345Sdim // pattern of pulling a lot of pools into a single pool. 102221345Sdim do { 103221345Sdim AttributeList *next = pool->NextInPool; 104221345Sdim pool->NextInPool = Head; 105221345Sdim Head = pool; 106221345Sdim pool = next; 107221345Sdim } while (pool); 108221345Sdim} 109221345Sdim 110239462Sdim#include "clang/Sema/AttrParsedAttrKinds.inc" 111239462Sdim 112296417Sdimstatic StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName, 113296417Sdim AttributeList::Syntax SyntaxUsed) { 114296417Sdim // Normalize the attribute name, __foo__ becomes foo. This is only allowable 115296417Sdim // for GNU attributes. 116296417Sdim bool IsGNU = SyntaxUsed == AttributeList::AS_GNU || 117296417Sdim (SyntaxUsed == AttributeList::AS_CXX11 && ScopeName == "gnu"); 118296417Sdim if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") && 119296417Sdim AttrName.endswith("__")) 120296417Sdim AttrName = AttrName.slice(2, AttrName.size() - 2); 121296417Sdim 122296417Sdim return AttrName; 123296417Sdim} 124296417Sdim 125239462SdimAttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name, 126239462Sdim const IdentifierInfo *ScopeName, 127239462Sdim Syntax SyntaxUsed) { 128226633Sdim StringRef AttrName = Name->getName(); 129212795Sdim 130276479Sdim SmallString<64> FullName; 131276479Sdim if (ScopeName) 132276479Sdim FullName += ScopeName->getName(); 133212795Sdim 134296417Sdim AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed); 135276479Sdim 136239462Sdim // Ensure that in the case of C++11 attributes, we look for '::foo' if it is 137239462Sdim // unscoped. 138239462Sdim if (ScopeName || SyntaxUsed == AS_CXX11) 139276479Sdim FullName += "::"; 140276479Sdim FullName += AttrName; 141239462Sdim 142276479Sdim return ::getAttrKind(FullName, SyntaxUsed); 143212795Sdim} 144249423Sdim 145249423Sdimunsigned AttributeList::getAttributeSpellingListIndex() const { 146249423Sdim // Both variables will be used in tablegen generated 147249423Sdim // attribute spell list index matching code. 148249423Sdim StringRef Scope = ScopeName ? ScopeName->getName() : ""; 149296417Sdim StringRef Name = normalizeAttrName(AttrName->getName(), Scope, 150296417Sdim (AttributeList::Syntax)SyntaxUsed); 151249423Sdim 152249423Sdim#include "clang/Sema/AttrSpellingListIndex.inc" 153249423Sdim 154249423Sdim} 155249423Sdim 156261991Sdimstruct ParsedAttrInfo { 157261991Sdim unsigned NumArgs : 4; 158261991Sdim unsigned OptArgs : 4; 159261991Sdim unsigned HasCustomParsing : 1; 160276479Sdim unsigned IsTargetSpecific : 1; 161276479Sdim unsigned IsType : 1; 162276479Sdim unsigned IsKnownToGCC : 1; 163276479Sdim 164276479Sdim bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr, 165276479Sdim const Decl *); 166276479Sdim bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr); 167296417Sdim bool (*ExistsInTarget)(const TargetInfo &Target); 168276479Sdim unsigned (*SpellingIndexToSemanticSpelling)(const AttributeList &Attr); 169261991Sdim}; 170261991Sdim 171261991Sdimnamespace { 172261991Sdim #include "clang/Sema/AttrParsedAttrImpl.inc" 173261991Sdim} 174261991Sdim 175261991Sdimstatic const ParsedAttrInfo &getInfo(const AttributeList &A) { 176261991Sdim return AttrInfoMap[A.getKind()]; 177261991Sdim} 178261991Sdim 179261991Sdimunsigned AttributeList::getMinArgs() const { 180261991Sdim return getInfo(*this).NumArgs; 181261991Sdim} 182261991Sdim 183261991Sdimunsigned AttributeList::getMaxArgs() const { 184261991Sdim return getMinArgs() + getInfo(*this).OptArgs; 185261991Sdim} 186261991Sdim 187261991Sdimbool AttributeList::hasCustomParsing() const { 188261991Sdim return getInfo(*this).HasCustomParsing; 189261991Sdim} 190276479Sdim 191276479Sdimbool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const { 192276479Sdim return getInfo(*this).DiagAppertainsToDecl(S, *this, D); 193276479Sdim} 194276479Sdim 195276479Sdimbool AttributeList::diagnoseLangOpts(Sema &S) const { 196276479Sdim return getInfo(*this).DiagLangOpts(S, *this); 197276479Sdim} 198276479Sdim 199276479Sdimbool AttributeList::isTargetSpecificAttr() const { 200276479Sdim return getInfo(*this).IsTargetSpecific; 201276479Sdim} 202276479Sdim 203276479Sdimbool AttributeList::isTypeAttr() const { 204276479Sdim return getInfo(*this).IsType; 205276479Sdim} 206276479Sdim 207296417Sdimbool AttributeList::existsInTarget(const TargetInfo &Target) const { 208296417Sdim return getInfo(*this).ExistsInTarget(Target); 209276479Sdim} 210276479Sdim 211276479Sdimbool AttributeList::isKnownToGCC() const { 212276479Sdim return getInfo(*this).IsKnownToGCC; 213276479Sdim} 214276479Sdim 215276479Sdimunsigned AttributeList::getSemanticSpelling() const { 216276479Sdim return getInfo(*this).SpellingIndexToSemanticSpelling(*this); 217276479Sdim} 218280031Sdim 219280031Sdimbool AttributeList::hasVariadicArg() const { 220280031Sdim // If the attribute has the maximum number of optional arguments, we will 221280031Sdim // claim that as being variadic. If we someday get an attribute that 222280031Sdim // legitimately bumps up against that maximum, we can use another bit to track 223280031Sdim // whether it's truly variadic or not. 224280031Sdim return getInfo(*this).OptArgs == 15; 225280031Sdim} 226