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