15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===--- AttributeList.cpp --------------------------------------*- C++ -*-===//
25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//                     The LLVM Compiler Infrastructure
45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source
60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details.
75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===//
95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// This file defines the AttributeList class implementation
115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===//
135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1419510856727e0e14a3696b2a72c35163bff2a71fJohn McCall#include "clang/Sema/AttributeList.h"
15478851c3ed6bd784e7377dffd8e57b200c1b9ba9Benjamin Kramer#include "clang/AST/ASTContext.h"
16651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/AST/DeclCXX.h"
17651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/AST/DeclTemplate.h"
180b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall#include "clang/AST/Expr.h"
198f823d2d3c557326d22699d66e5d367d0f0e44efChris Lattner#include "clang/Basic/IdentifierTable.h"
20651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/Sema/SemaInternal.h"
21e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith#include "llvm/ADT/SmallString.h"
2255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "llvm/ADT/StringSwitch.h"
235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang;
245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
258edabd95dd4c9099fd124c5e50322730b9200d23Richard SmithIdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
268edabd95dd4c9099fd124c5e50322730b9200d23Richard Smith                                     IdentifierInfo *Ident) {
278edabd95dd4c9099fd124c5e50322730b9200d23Richard Smith  IdentifierLoc *Result = new (Ctx) IdentifierLoc;
288edabd95dd4c9099fd124c5e50322730b9200d23Richard Smith  Result->Loc = Loc;
298edabd95dd4c9099fd124c5e50322730b9200d23Richard Smith  Result->Ident = Ident;
308edabd95dd4c9099fd124c5e50322730b9200d23Richard Smith  return Result;
318edabd95dd4c9099fd124c5e50322730b9200d23Richard Smith}
328edabd95dd4c9099fd124c5e50322730b9200d23Richard Smith
330b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCallsize_t AttributeList::allocated_size() const {
340b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
350d5a069f66df09b3308ccfdce84a88170034c657Dmitri Gribenko  else if (IsTypeTagForDatatype)
360d5a069f66df09b3308ccfdce84a88170034c657Dmitri Gribenko    return AttributeFactory::TypeTagForDatatypeAllocSize;
3776da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall  else if (IsProperty)
3876da55d3a49e1805f51b1ced7c5da5bcd7f759d8John McCall    return AttributeFactory::PropertyAllocSize;
39624421f98d8fcb8ed8ebc406da41217682159aa8Aaron Ballman  return (sizeof(AttributeList) + NumArgs * sizeof(ArgsUnion));
400b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall}
410b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
420b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCallAttributeFactory::AttributeFactory() {
430b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  // Go ahead and configure all the inline capacity.  This is just a memset.
440b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  FreeLists.resize(InlineFreeListsCapacity);
450b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall}
460b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCallAttributeFactory::~AttributeFactory() {}
470b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
480b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCallstatic size_t getFreeListIndexForSize(size_t size) {
490b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  assert(size >= sizeof(AttributeList));
500b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  assert((size % sizeof(void*)) == 0);
510b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  return ((size - sizeof(AttributeList)) / sizeof(void*));
520b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall}
530b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
540b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCallvoid *AttributeFactory::allocate(size_t size) {
550b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  // Check for a previously reclaimed attribute.
560b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  size_t index = getFreeListIndexForSize(size);
570b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  if (index < FreeLists.size()) {
580b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    if (AttributeList *attr = FreeLists[index]) {
590b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall      FreeLists[index] = attr->NextInPool;
600b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall      return attr;
610b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    }
62005b235fbc8449142befa81ec30e8e4c654182c5Chris Lattner  }
630b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
640b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  // Otherwise, allocate something new.
650b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  return Alloc.Allocate(size, llvm::AlignOf<AttributeFactory>::Alignment);
660b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall}
670b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
680b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCallvoid AttributeFactory::reclaimPool(AttributeList *cur) {
690b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  assert(cur && "reclaiming empty pool!");
700b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  do {
710b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    // Read this here, because we're going to overwrite NextInPool
720b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    // when we toss 'cur' into the appropriate queue.
730b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    AttributeList *next = cur->NextInPool;
740b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
750b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    size_t size = cur->allocated_size();
760b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    size_t freeListIndex = getFreeListIndexForSize(size);
770b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
780b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    // Expand FreeLists to the appropriate size, if required.
790b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    if (freeListIndex >= FreeLists.size())
800b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall      FreeLists.resize(freeListIndex+1);
810b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
820b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    // Add 'cur' to the appropriate free-list.
830b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    cur->NextInPool = FreeLists[freeListIndex];
840b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    FreeLists[freeListIndex] = cur;
850b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
860b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    cur = next;
870b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  } while (cur);
880b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall}
890b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
900b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCallvoid AttributePool::takePool(AttributeList *pool) {
910b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  assert(pool);
920b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
930b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  // Fast path:  this pool is empty.
940b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  if (!Head) {
950b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    Head = pool;
960b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    return;
970b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  }
980b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall
990b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  // Reverse the pool onto the current head.  This optimizes for the
1000b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  // pattern of pulling a lot of pools into a single pool.
1010b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  do {
1020b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    AttributeList *next = pool->NextInPool;
1030b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    pool->NextInPool = Head;
1040b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    Head = pool;
1050b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall    pool = next;
1060b7e678a11ece4288dc01aebb5b17e5eef8f8d2dJohn McCall  } while (pool);
1075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
1082335191341a58fa3f8abea3c9b391c5bb03d67b3Chris Lattner
1090c19b3c38e356058aeb2424d175eae232bf014d9Douglas Gregor#include "clang/Sema/AttrParsedAttrKinds.inc"
1100c19b3c38e356058aeb2424d175eae232bf014d9Douglas Gregor
111e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard SmithAttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
11293f95f2a2cbb6bb3d17bfb5fc74ce1cccea751b6Sean Hunt                                           const IdentifierInfo *ScopeName,
11393f95f2a2cbb6bb3d17bfb5fc74ce1cccea751b6Sean Hunt                                           Syntax SyntaxUsed) {
1145f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  StringRef AttrName = Name->getName();
1152335191341a58fa3f8abea3c9b391c5bb03d67b3Chris Lattner
116651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  SmallString<64> FullName;
117e0d3b4cd2b66f1cef26cacbed5820ab7c22ad5b3Richard Smith  if (ScopeName)
118651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    FullName += ScopeName->getName();
119651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
120651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Normalize the attribute name, __foo__ becomes foo. This is only allowable
121651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // for GNU attributes.
122651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool IsGNU = SyntaxUsed == AS_GNU || (SyntaxUsed == AS_CXX11 &&
123651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                        FullName == "gnu");
124651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") &&
125651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      AttrName.endswith("__"))
126651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    AttrName = AttrName.slice(2, AttrName.size() - 2);
127651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
12893f95f2a2cbb6bb3d17bfb5fc74ce1cccea751b6Sean Hunt  // Ensure that in the case of C++11 attributes, we look for '::foo' if it is
12993f95f2a2cbb6bb3d17bfb5fc74ce1cccea751b6Sean Hunt  // unscoped.
13093f95f2a2cbb6bb3d17bfb5fc74ce1cccea751b6Sean Hunt  if (ScopeName || SyntaxUsed == AS_CXX11)
131651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    FullName += "::";
132651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  FullName += AttrName;
13393f95f2a2cbb6bb3d17bfb5fc74ce1cccea751b6Sean Hunt
134651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return ::getAttrKind(FullName, SyntaxUsed);
1352335191341a58fa3f8abea3c9b391c5bb03d67b3Chris Lattner}
13651d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han
13751d8c52ad36129760eaa586f85176037e2cd0d0eMichael Hanunsigned AttributeList::getAttributeSpellingListIndex() const {
13851d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han  // Both variables will be used in tablegen generated
13951d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han  // attribute spell list index matching code.
14051d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han  StringRef Name = AttrName->getName();
14151d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han  StringRef Scope = ScopeName ? ScopeName->getName() : "";
14251d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han
14351d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han#include "clang/Sema/AttrSpellingListIndex.inc"
14451d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han
14551d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han}
14651d8c52ad36129760eaa586f85176037e2cd0d0eMichael Han
147bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballmanstruct ParsedAttrInfo {
148bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman  unsigned NumArgs : 4;
149bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman  unsigned OptArgs : 4;
150bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman  unsigned HasCustomParsing : 1;
151651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  unsigned IsTargetSpecific : 1;
152651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  unsigned IsType : 1;
153651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  unsigned IsKnownToGCC : 1;
154651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
155651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr,
156651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                               const Decl *);
157651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr);
158651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool (*ExistsInTarget)(const llvm::Triple &T);
159651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  unsigned (*SpellingIndexToSemanticSpelling)(const AttributeList &Attr);
160bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman};
161bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman
162bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballmannamespace {
163bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman  #include "clang/Sema/AttrParsedAttrImpl.inc"
164bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman}
165bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman
1666ad3cdd401f35217aaa7b00fe765247aaf133cf2Benjamin Kramerstatic const ParsedAttrInfo &getInfo(const AttributeList &A) {
167bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman  return AttrInfoMap[A.getKind()];
168bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman}
169bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman
170bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballmanunsigned AttributeList::getMinArgs() const {
171bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman  return getInfo(*this).NumArgs;
172bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman}
173bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman
174bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballmanunsigned AttributeList::getMaxArgs() const {
175bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman  return getMinArgs() + getInfo(*this).OptArgs;
176bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman}
177bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman
178bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballmanbool AttributeList::hasCustomParsing() const {
179bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman  return getInfo(*this).HasCustomParsing;
180bbb3b3237df2284f6f3c34798944fcfa4b43fd34Aaron Ballman}
181651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
182651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesbool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
183651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return getInfo(*this).DiagAppertainsToDecl(S, *this, D);
184651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
185651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
186651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesbool AttributeList::diagnoseLangOpts(Sema &S) const {
187651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return getInfo(*this).DiagLangOpts(S, *this);
188651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
189651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
190651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesbool AttributeList::isTargetSpecificAttr() const {
191651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return getInfo(*this).IsTargetSpecific;
192651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
193651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
194651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesbool AttributeList::isTypeAttr() const {
195651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return getInfo(*this).IsType;
196651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
197651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
198651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesbool AttributeList::existsInTarget(const llvm::Triple &T) const {
199651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return getInfo(*this).ExistsInTarget(T);
200651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
201651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
202651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesbool AttributeList::isKnownToGCC() const {
203651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return getInfo(*this).IsKnownToGCC;
204651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
205651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
206651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesunsigned AttributeList::getSemanticSpelling() const {
207651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return getInfo(*this).SpellingIndexToSemanticSpelling(*this);
208651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
209176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines
210176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesbool AttributeList::hasVariadicArg() const {
211176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // If the attribute has the maximum number of optional arguments, we will
212176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // claim that as being variadic. If we someday get an attribute that
213176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // legitimately bumps up against that maximum, we can use another bit to track
214176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  // whether it's truly variadic or not.
215176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines  return getInfo(*this).OptArgs == 15;
216176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines}
217