AttributeList.h revision e53ac8aea2d9e8bbb11191398ea3cc2edb2d171a
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===--- AttributeList.h - Parsed attribute sets ----------------*- C++ -*-===// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file defines the AttributeList class, which is used to collect 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// parsed attributes. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef LLVM_CLANG_SEMA_ATTRLIST_H 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define LLVM_CLANG_SEMA_ATTRLIST_H 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/Support/Allocator.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/ADT/SmallVector.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/Basic/SourceLocation.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/Basic/VersionTuple.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cassert> 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace clang { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class ASTContext; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class IdentifierInfo; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class Expr; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// \brief Represents information about a change in availability for 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// an entity, which is part of the encoding of the 'availability' 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// attribute. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct AvailabilityChange { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// \brief The location of the keyword indicating the kind of change. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SourceLocation KeywordLoc; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// \brief The version number at which the change occurred. 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VersionTuple Version; 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// \brief The source range covering the version number. 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SourceRange VersionRange; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// \brief Determine whether this availability change is valid. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool isValid() const { return !Version.empty(); } 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// AttributeList - Represents GCC's __attribute__ declaration. There are 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// 4 forms of this construct...they are: 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// 1: __attribute__(( const )). ParmName/Args/NumArgs will all be unused. 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// 2: __attribute__(( mode(byte) )). ParmName used, Args/NumArgs unused. 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used. 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used. 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class AttributeList { // TODO: This should really be called ParsedAttribute 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)private: 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IdentifierInfo *AttrName; 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IdentifierInfo *ScopeName; 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IdentifierInfo *ParmName; 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SourceRange AttrRange; 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SourceLocation ScopeLoc; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SourceLocation ParmLoc; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// The number of expression arguments this attribute has. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// The expressions themselves are stored after the object. 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned NumArgs : 16; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// True if Microsoft style: declspec(foo). 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned DeclspecAttribute : 1; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// True if C++0x-style: [[foo]]. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned CXX0XAttribute : 1; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// True if already diagnosed as invalid. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable unsigned Invalid : 1; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// True if this attribute was used as a type attribute. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable unsigned UsedAsTypeAttr : 1; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// True if this has the extra information associated with an 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// availability attribute. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned IsAvailability : 1; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned AttrKind : 8; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// \brief The location of the 'unavailable' keyword in an 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// availability attribute. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SourceLocation UnavailableLoc; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Expr *MessageExpr; 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// The next attribute in the current position. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AttributeList *NextInPosition; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// The next attribute allocated in the current Pool. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AttributeList *NextInPool; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Expr **getArgsBuffer() { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<Expr**>(this+1); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Expr * const *getArgsBuffer() const { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<Expr* const *>(this+1); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum AvailabilitySlot { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IntroducedSlot, DeprecatedSlot, ObsoletedSlot 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<AvailabilityChange*>(this+1)[index]; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) const { 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return reinterpret_cast<const AvailabilityChange*>(this+1)[index]; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AttributeList(const AttributeList &); // DO NOT IMPLEMENT 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void operator=(const AttributeList &); // DO NOT IMPLEMENT 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void operator delete(void *); // DO NOT IMPLEMENT 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ~AttributeList(); // DO NOT IMPLEMENT 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t allocated_size() const; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AttributeList(IdentifierInfo *attrName, SourceRange attrRange, 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IdentifierInfo *scopeName, SourceLocation scopeLoc, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IdentifierInfo *parmName, SourceLocation parmLoc, 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Expr **args, unsigned numArgs, 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool declspec, bool cxx0x) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NumArgs(numArgs), 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), Invalid(false), 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UsedAsTypeAttr(false), IsAvailability(false), 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NextInPosition(0), NextInPool(0) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*)); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AttrKind = getKind(getName()); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AttributeList(IdentifierInfo *attrName, SourceRange attrRange, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IdentifierInfo *scopeName, SourceLocation scopeLoc, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IdentifierInfo *parmName, SourceLocation parmLoc, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AvailabilityChange &introduced, 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AvailabilityChange &deprecated, 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const AvailabilityChange &obsoleted, 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SourceLocation unavailable, 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Expr *messageExpr, 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool declspec, bool cxx0x) 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc), 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NumArgs(0), DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UnavailableLoc(unavailable), MessageExpr(messageExpr), 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NextInPosition(0), NextInPool(0) { 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced); 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated); 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted); 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AttrKind = getKind(getName()); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class AttributePool; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class AttributeFactory; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public: 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum Kind { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #define PARSED_ATTR(NAME) AT_##NAME, 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #include "clang/Sema/AttrParsedAttrList.inc" 165 PARSED_ATTR(address_space) 166 PARSED_ATTR(base_check) 167 PARSED_ATTR(cf_returns_autoreleased) 168 PARSED_ATTR(ext_vector_type) 169 PARSED_ATTR(mode) 170 PARSED_ATTR(neon_polyvector_type) 171 PARSED_ATTR(neon_vector_type) 172 PARSED_ATTR(objc_gc) 173 PARSED_ATTR(objc_ownership) 174 PARSED_ATTR(opencl_image_access) 175 PARSED_ATTR(vector_size) 176 #undef PARSED_ATTR 177 IgnoredAttribute, 178 UnknownAttribute 179 }; 180 181 IdentifierInfo *getName() const { return AttrName; } 182 SourceLocation getLoc() const { return AttrRange.getBegin(); } 183 SourceRange getRange() const { return AttrRange; } 184 185 bool hasScope() const { return ScopeName; } 186 IdentifierInfo *getScopeName() const { return ScopeName; } 187 SourceLocation getScopeLoc() const { return ScopeLoc; } 188 189 IdentifierInfo *getParameterName() const { return ParmName; } 190 SourceLocation getParameterLoc() const { return ParmLoc; } 191 192 bool isDeclspecAttribute() const { return DeclspecAttribute; } 193 bool isCXX0XAttribute() const { return CXX0XAttribute; } 194 195 bool isInvalid() const { return Invalid; } 196 void setInvalid(bool b = true) const { Invalid = b; } 197 198 bool isUsedAsTypeAttr() const { return UsedAsTypeAttr; } 199 void setUsedAsTypeAttr() { UsedAsTypeAttr = true; } 200 201 Kind getKind() const { return Kind(AttrKind); } 202 static Kind getKind(const IdentifierInfo *Name); 203 204 AttributeList *getNext() const { return NextInPosition; } 205 void setNext(AttributeList *N) { NextInPosition = N; } 206 207 /// getNumArgs - Return the number of actual arguments to this attribute. 208 unsigned getNumArgs() const { return NumArgs; } 209 210 /// hasParameterOrArguments - Return true if this attribute has a parameter, 211 /// or has a non empty argument expression list. 212 bool hasParameterOrArguments() const { return ParmName || NumArgs; } 213 214 /// getArg - Return the specified argument. 215 Expr *getArg(unsigned Arg) const { 216 assert(Arg < NumArgs && "Arg access out of range!"); 217 return getArgsBuffer()[Arg]; 218 } 219 220 class arg_iterator { 221 Expr * const *X; 222 unsigned Idx; 223 public: 224 arg_iterator(Expr * const *x, unsigned idx) : X(x), Idx(idx) {} 225 226 arg_iterator& operator++() { 227 ++Idx; 228 return *this; 229 } 230 231 bool operator==(const arg_iterator& I) const { 232 assert (X == I.X && 233 "compared arg_iterators are for different argument lists"); 234 return Idx == I.Idx; 235 } 236 237 bool operator!=(const arg_iterator& I) const { 238 return !operator==(I); 239 } 240 241 Expr* operator*() const { 242 return X[Idx]; 243 } 244 245 unsigned getArgNum() const { 246 return Idx+1; 247 } 248 }; 249 250 arg_iterator arg_begin() const { 251 return arg_iterator(getArgsBuffer(), 0); 252 } 253 254 arg_iterator arg_end() const { 255 return arg_iterator(getArgsBuffer(), NumArgs); 256 } 257 258 const AvailabilityChange &getAvailabilityIntroduced() const { 259 assert(getKind() == AT_availability && "Not an availability attribute"); 260 return getAvailabilitySlot(IntroducedSlot); 261 } 262 263 const AvailabilityChange &getAvailabilityDeprecated() const { 264 assert(getKind() == AT_availability && "Not an availability attribute"); 265 return getAvailabilitySlot(DeprecatedSlot); 266 } 267 268 const AvailabilityChange &getAvailabilityObsoleted() const { 269 assert(getKind() == AT_availability && "Not an availability attribute"); 270 return getAvailabilitySlot(ObsoletedSlot); 271 } 272 273 SourceLocation getUnavailableLoc() const { 274 assert(getKind() == AT_availability && "Not an availability attribute"); 275 return UnavailableLoc; 276 } 277 278 const Expr * getMessageExpr() const { 279 assert(getKind() == AT_availability && "Not an availability attribute"); 280 return MessageExpr; 281 } 282}; 283 284/// A factory, from which one makes pools, from which one creates 285/// individual attributes which are deallocated with the pool. 286/// 287/// Note that it's tolerably cheap to create and destroy one of 288/// these as long as you don't actually allocate anything in it. 289class AttributeFactory { 290public: 291 enum { 292 /// The required allocation size of an availability attribute, 293 /// which we want to ensure is a multiple of sizeof(void*). 294 AvailabilityAllocSize = 295 sizeof(AttributeList) 296 + ((3 * sizeof(AvailabilityChange) + sizeof(void*) - 1) 297 / sizeof(void*) * sizeof(void*)) 298 }; 299 300private: 301 enum { 302 /// The number of free lists we want to be sure to support 303 /// inline. This is just enough that availability attributes 304 /// don't surpass it. It's actually very unlikely we'll see an 305 /// attribute that needs more than that; on x86-64 you'd need 10 306 /// expression arguments, and on i386 you'd need 19. 307 InlineFreeListsCapacity = 308 1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*) 309 }; 310 311 llvm::BumpPtrAllocator Alloc; 312 313 /// Free lists. The index is determined by the following formula: 314 /// (size - sizeof(AttributeList)) / sizeof(void*) 315 SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists; 316 317 // The following are the private interface used by AttributePool. 318 friend class AttributePool; 319 320 /// Allocate an attribute of the given size. 321 void *allocate(size_t size); 322 323 /// Reclaim all the attributes in the given pool chain, which is 324 /// non-empty. Note that the current implementation is safe 325 /// against reclaiming things which were not actually allocated 326 /// with the allocator, although of course it's important to make 327 /// sure that their allocator lives at least as long as this one. 328 void reclaimPool(AttributeList *head); 329 330public: 331 AttributeFactory(); 332 ~AttributeFactory(); 333}; 334 335class AttributePool { 336 AttributeFactory &Factory; 337 AttributeList *Head; 338 339 void *allocate(size_t size) { 340 return Factory.allocate(size); 341 } 342 343 AttributeList *add(AttributeList *attr) { 344 // We don't care about the order of the pool. 345 attr->NextInPool = Head; 346 Head = attr; 347 return attr; 348 } 349 350 void takePool(AttributeList *pool); 351 352public: 353 /// Create a new pool for a factory. 354 AttributePool(AttributeFactory &factory) : Factory(factory), Head(0) {} 355 356 /// Move the given pool's allocations to this pool. 357 AttributePool(AttributePool &pool) : Factory(pool.Factory), Head(pool.Head) { 358 pool.Head = 0; 359 } 360 361 AttributeFactory &getFactory() const { return Factory; } 362 363 void clear() { 364 if (Head) { 365 Factory.reclaimPool(Head); 366 Head = 0; 367 } 368 } 369 370 /// Take the given pool's allocations and add them to this pool. 371 void takeAllFrom(AttributePool &pool) { 372 if (pool.Head) { 373 takePool(pool.Head); 374 pool.Head = 0; 375 } 376 } 377 378 ~AttributePool() { 379 if (Head) Factory.reclaimPool(Head); 380 } 381 382 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, 383 IdentifierInfo *scopeName, SourceLocation scopeLoc, 384 IdentifierInfo *parmName, SourceLocation parmLoc, 385 Expr **args, unsigned numArgs, 386 bool declspec = false, bool cxx0x = false) { 387 void *memory = allocate(sizeof(AttributeList) 388 + numArgs * sizeof(Expr*)); 389 return add(new (memory) AttributeList(attrName, attrRange, 390 scopeName, scopeLoc, 391 parmName, parmLoc, 392 args, numArgs, 393 declspec, cxx0x)); 394 } 395 396 AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, 397 IdentifierInfo *scopeName, SourceLocation scopeLoc, 398 IdentifierInfo *parmName, SourceLocation parmLoc, 399 const AvailabilityChange &introduced, 400 const AvailabilityChange &deprecated, 401 const AvailabilityChange &obsoleted, 402 SourceLocation unavailable, 403 const Expr *MessageExpr, 404 bool declspec = false, bool cxx0x = false) { 405 void *memory = allocate(AttributeFactory::AvailabilityAllocSize); 406 return add(new (memory) AttributeList(attrName, attrRange, 407 scopeName, scopeLoc, 408 parmName, parmLoc, 409 introduced, deprecated, obsoleted, 410 unavailable, MessageExpr, 411 declspec, cxx0x)); 412 } 413 414 AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name, 415 SourceLocation TokLoc, int Arg); 416}; 417 418/// addAttributeLists - Add two AttributeLists together 419/// The right-hand list is appended to the left-hand list, if any 420/// A pointer to the joined list is returned. 421/// Note: the lists are not left unmodified. 422inline AttributeList *addAttributeLists(AttributeList *Left, 423 AttributeList *Right) { 424 if (!Left) 425 return Right; 426 427 AttributeList *next = Left, *prev; 428 do { 429 prev = next; 430 next = next->getNext(); 431 } while (next); 432 prev->setNext(Right); 433 return Left; 434} 435 436/// CXX0XAttributeList - A wrapper around a C++0x attribute list. 437/// Stores, in addition to the list proper, whether or not an actual list was 438/// (as opposed to an empty list, which may be ill-formed in some places) and 439/// the source range of the list. 440struct CXX0XAttributeList { 441 AttributeList *AttrList; 442 SourceRange Range; 443 bool HasAttr; 444 CXX0XAttributeList (AttributeList *attrList, SourceRange range, bool hasAttr) 445 : AttrList(attrList), Range(range), HasAttr (hasAttr) { 446 } 447 CXX0XAttributeList () 448 : AttrList(0), Range(), HasAttr(false) { 449 } 450}; 451 452/// ParsedAttributes - A collection of parsed attributes. Currently 453/// we don't differentiate between the various attribute syntaxes, 454/// which is basically silly. 455/// 456/// Right now this is a very lightweight container, but the expectation 457/// is that this will become significantly more serious. 458class ParsedAttributes { 459public: 460 ParsedAttributes(AttributeFactory &factory) 461 : pool(factory), list(0) { 462 } 463 464 ParsedAttributes(ParsedAttributes &attrs) 465 : pool(attrs.pool), list(attrs.list) { 466 attrs.list = 0; 467 } 468 469 AttributePool &getPool() const { return pool; } 470 471 bool empty() const { return list == 0; } 472 473 void add(AttributeList *newAttr) { 474 assert(newAttr); 475 assert(newAttr->getNext() == 0); 476 newAttr->setNext(list); 477 list = newAttr; 478 } 479 480 void addAll(AttributeList *newList) { 481 if (!newList) return; 482 483 AttributeList *lastInNewList = newList; 484 while (AttributeList *next = lastInNewList->getNext()) 485 lastInNewList = next; 486 487 lastInNewList->setNext(list); 488 list = newList; 489 } 490 491 void set(AttributeList *newList) { 492 list = newList; 493 } 494 495 void takeAllFrom(ParsedAttributes &attrs) { 496 addAll(attrs.list); 497 attrs.list = 0; 498 pool.takeAllFrom(attrs.pool); 499 } 500 501 void clear() { list = 0; pool.clear(); } 502 AttributeList *getList() const { return list; } 503 504 /// Returns a reference to the attribute list. Try not to introduce 505 /// dependencies on this method, it may not be long-lived. 506 AttributeList *&getListRef() { return list; } 507 508 509 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, 510 IdentifierInfo *scopeName, SourceLocation scopeLoc, 511 IdentifierInfo *parmName, SourceLocation parmLoc, 512 Expr **args, unsigned numArgs, 513 bool declspec = false, bool cxx0x = false) { 514 AttributeList *attr = 515 pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc, 516 args, numArgs, declspec, cxx0x); 517 add(attr); 518 return attr; 519 } 520 521 AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, 522 IdentifierInfo *scopeName, SourceLocation scopeLoc, 523 IdentifierInfo *parmName, SourceLocation parmLoc, 524 const AvailabilityChange &introduced, 525 const AvailabilityChange &deprecated, 526 const AvailabilityChange &obsoleted, 527 SourceLocation unavailable, 528 const Expr *MessageExpr, 529 bool declspec = false, bool cxx0x = false) { 530 AttributeList *attr = 531 pool.create(attrName, attrRange, scopeName, scopeLoc, parmName, parmLoc, 532 introduced, deprecated, obsoleted, unavailable, 533 MessageExpr, 534 declspec, cxx0x); 535 add(attr); 536 return attr; 537 } 538 539 AttributeList *addNewInteger(ASTContext &C, IdentifierInfo *name, 540 SourceLocation loc, int arg) { 541 AttributeList *attr = 542 pool.createIntegerAttribute(C, name, loc, arg); 543 add(attr); 544 return attr; 545 } 546 547 548private: 549 mutable AttributePool pool; 550 AttributeList *list; 551}; 552 553} // end namespace clang 554 555#endif 556