1801e60946bc879afeb37bcd3372e441e8f631c79James Dennett//===--- Attr.h - Classes for representing attributes ----------*- C++ -*-===//
2d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson//
3d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson//                     The LLVM Compiler Infrastructure
4d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson//
5d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson// This file is distributed under the University of Illinois Open Source
6d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson// License. See LICENSE.TXT for details.
7d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson//
8d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson//===----------------------------------------------------------------------===//
9d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson//
10d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson//  This file defines the Attr interface and subclasses.
11d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson//
12d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson//===----------------------------------------------------------------------===//
13d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson
1481226601148d7e7c187b96c6ef86e83df204f59fAnders Carlsson#ifndef LLVM_CLANG_AST_ATTR_H
1581226601148d7e7c187b96c6ef86e83df204f59fAnders Carlsson#define LLVM_CLANG_AST_ATTR_H
16d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson
179594675cc1eb52a054de13c4a21e466643847480Chris Lattner#include "clang/Basic/LLVM.h"
18387475d0c18aaeb022108de9d33b6c9fb7998843Sean Hunt#include "clang/Basic/AttrKinds.h"
19a8fb24fa3151567056f6125999cea69e39604f35Fariborz Jahanian#include "clang/AST/Type.h"
20cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt#include "clang/Basic/SourceLocation.h"
210a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor#include "clang/Basic/VersionTuple.h"
229594675cc1eb52a054de13c4a21e466643847480Chris Lattner#include "llvm/ADT/SmallVector.h"
239594675cc1eb52a054de13c4a21e466643847480Chris Lattner#include "llvm/ADT/StringRef.h"
249594675cc1eb52a054de13c4a21e466643847480Chris Lattner#include "llvm/ADT/StringSwitch.h"
259fe8c74a93ac8e92512615c5f83e7a328b3b0544David Blaikie#include "llvm/Support/ErrorHandling.h"
261bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor#include "llvm/Support/raw_ostream.h"
27baa66fc389ca0a9f11e0c864304bcfd89de39439Anders Carlsson#include <cassert>
28ea7e97e14f2f1f9817d2ae8a25ec6ea652e5287fArgyrios Kyrtzidis#include <cstring>
29eb2b2a3f1898f146c6e153a64ec58ec5e1750bd2Ted Kremenek#include <algorithm>
30adf21bdb3d17acfdb74657fcbc5035a404c6c8f4Anders Carlsson
31d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlssonnamespace clang {
32cc5814732edc0c382d0136ab57ec6149566043e2Chris Lattner  class ASTContext;
33857e918a8a40deb128840308a318bf623d68295fTed Kremenek  class IdentifierInfo;
34857e918a8a40deb128840308a318bf623d68295fTed Kremenek  class ObjCInterfaceDecl;
354ced79f0971592e6e7122037de69ee9ae534ce72Chandler Carruth  class Expr;
36a8fb24fa3151567056f6125999cea69e39604f35Fariborz Jahanian  class QualType;
37cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  class FunctionDecl;
38cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  class TypeSourceInfo;
399f9bf258f8ebae30bfb70feb9d797d6eb67b0460Douglas Gregor}
409f9bf258f8ebae30bfb70feb9d797d6eb67b0460Douglas Gregor
419509108b3dde280dca1999b5c054f5b789581e68Chris Lattner// Defined in ASTContext.h
424ba2a17694148e16eaa8d3917f657ffcd3667be4Jay Foadvoid *operator new(size_t Bytes, const clang::ASTContext &C,
4329293cddc682091a16a71f513e605995473f7f45Dylan Noblesmith                   size_t Alignment = 16);
44cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt// FIXME: Being forced to not have a default argument here due to redeclaration
45cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt//        rules on default arguments sucks
464ba2a17694148e16eaa8d3917f657ffcd3667be4Jay Foadvoid *operator new[](size_t Bytes, const clang::ASTContext &C,
4729293cddc682091a16a71f513e605995473f7f45Dylan Noblesmith                     size_t Alignment);
489f9bf258f8ebae30bfb70feb9d797d6eb67b0460Douglas Gregor
499509108b3dde280dca1999b5c054f5b789581e68Chris Lattner// It is good practice to pair new/delete operators.  Also, MSVC gives many
509509108b3dde280dca1999b5c054f5b789581e68Chris Lattner// warnings if a matching delete overload is not declared, even though the
519509108b3dde280dca1999b5c054f5b789581e68Chris Lattner// throw() spec guarantees it will not be implicitly called.
5229293cddc682091a16a71f513e605995473f7f45Dylan Noblesmithvoid operator delete(void *Ptr, const clang::ASTContext &C, size_t);
5329293cddc682091a16a71f513e605995473f7f45Dylan Noblesmithvoid operator delete[](void *Ptr, const clang::ASTContext &C, size_t);
549509108b3dde280dca1999b5c054f5b789581e68Chris Lattner
559f9bf258f8ebae30bfb70feb9d797d6eb67b0460Douglas Gregornamespace clang {
56d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson
57d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson/// Attr - This represents one attribute.
58d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlssonclass Attr {
59d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlssonprivate:
60ffcc3105d223899740e79f3f8199f3881df4d1deArgyrios Kyrtzidis  SourceRange Range;
61cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  unsigned AttrKind : 16;
622f402708e62f89fb875442802e3d3f20fc909d33Anton Korobeynikov
63d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlssonprotected:
64a97d70b7ea9633e8cbf976510d7a9ea66f4ac96cPeter Collingbourne  bool Inherited : 1;
65a97d70b7ea9633e8cbf976510d7a9ea66f4ac96cPeter Collingbourne
661de22a26c0e126b08edb2eda9d9091c021d96dc6Douglas Gregor  virtual ~Attr();
671de22a26c0e126b08edb2eda9d9091c021d96dc6Douglas Gregor
680b2b6e1cb1573bb295c0a65813dc4df8d57f305bChris Lattner  void* operator new(size_t bytes) throw() {
69b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie    llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
700b2b6e1cb1573bb295c0a65813dc4df8d57f305bChris Lattner  }
710b2b6e1cb1573bb295c0a65813dc4df8d57f305bChris Lattner  void operator delete(void* data) throw() {
72b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie    llvm_unreachable("Attrs cannot be released with regular 'delete'.");
730b2b6e1cb1573bb295c0a65813dc4df8d57f305bChris Lattner  }
741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
75cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Huntpublic:
76cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  // Forward so that the regular new and delete do not hide global ones.
77cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  void* operator new(size_t Bytes, ASTContext &C,
78cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt                     size_t Alignment = 16) throw() {
79cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    return ::operator new(Bytes, C, Alignment);
80cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  }
81cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  void operator delete(void *Ptr, ASTContext &C,
82a87cdc03f4014545a8440110c1f4f68701100576Eli Friedman                       size_t Alignment) throw() {
83cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    return ::operator delete(Ptr, C, Alignment);
84cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  }
85cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt
860b2b6e1cb1573bb295c0a65813dc4df8d57f305bChris Lattnerprotected:
87ffcc3105d223899740e79f3f8199f3881df4d1deArgyrios Kyrtzidis  Attr(attr::Kind AK, SourceRange R)
88ffcc3105d223899740e79f3f8199f3881df4d1deArgyrios Kyrtzidis    : Range(R), AttrKind(AK), Inherited(false) {}
89cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt
90cc5814732edc0c382d0136ab57ec6149566043e2Chris Lattnerpublic:
911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
92cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  attr::Kind getKind() const {
93cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    return static_cast<attr::Kind>(AttrKind);
94d406bf0e8c17012110a8476d03c6f9a97b56ecf7Anders Carlsson  }
951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
96ffcc3105d223899740e79f3f8199f3881df4d1deArgyrios Kyrtzidis  SourceLocation getLocation() const { return Range.getBegin(); }
97ffcc3105d223899740e79f3f8199f3881df4d1deArgyrios Kyrtzidis  SourceRange getRange() const { return Range; }
98ffcc3105d223899740e79f3f8199f3881df4d1deArgyrios Kyrtzidis  void setRange(SourceRange R) { Range = R; }
991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
100192e7f7e7f0493f7cdfda1d752e6de340d4e3ffePeter Collingbourne  bool isInherited() const { return Inherited; }
101192e7f7e7f0493f7cdfda1d752e6de340d4e3ffePeter Collingbourne
1029f9bf258f8ebae30bfb70feb9d797d6eb67b0460Douglas Gregor  // Clone this attribute.
1039f9bf258f8ebae30bfb70feb9d797d6eb67b0460Douglas Gregor  virtual Attr* clone(ASTContext &C) const = 0;
1049f9bf258f8ebae30bfb70feb9d797d6eb67b0460Douglas Gregor
10523323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins  virtual bool isLateParsed() const { return false; }
10623323e0253716ff03c95a00fb6903019daafe3aaDeLesley Hutchins
1071bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor  // Pretty print this attribute.
1080dae729a69c4fccc38c97d5dd44f7b20bb20de1cRichard Smith  virtual void printPretty(llvm::raw_ostream &OS,
1090dae729a69c4fccc38c97d5dd44f7b20bb20de1cRichard Smith                           const PrintingPolicy &Policy) const = 0;
1101bea8807bcd2be10bf6309a3a848489434464cedDouglas Gregor
111d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson  // Implement isa/cast/dyncast/etc.
112d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson  static bool classof(const Attr *) { return true; }
113d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson};
114387475d0c18aaeb022108de9d33b6c9fb7998843Sean Hunt
115a97d70b7ea9633e8cbf976510d7a9ea66f4ac96cPeter Collingbourneclass InheritableAttr : public Attr {
11699ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie  virtual void anchor();
117a97d70b7ea9633e8cbf976510d7a9ea66f4ac96cPeter Collingbourneprotected:
118768d6cae40ad4ff3aed5483269d068ff7a45e229Argyrios Kyrtzidis  InheritableAttr(attr::Kind AK, SourceRange R)
119768d6cae40ad4ff3aed5483269d068ff7a45e229Argyrios Kyrtzidis    : Attr(AK, R) {}
120a97d70b7ea9633e8cbf976510d7a9ea66f4ac96cPeter Collingbourne
121a97d70b7ea9633e8cbf976510d7a9ea66f4ac96cPeter Collingbournepublic:
122a97d70b7ea9633e8cbf976510d7a9ea66f4ac96cPeter Collingbourne  void setInherited(bool I) { Inherited = I; }
123a97d70b7ea9633e8cbf976510d7a9ea66f4ac96cPeter Collingbourne
124a97d70b7ea9633e8cbf976510d7a9ea66f4ac96cPeter Collingbourne  // Implement isa/cast/dyncast/etc.
125a97d70b7ea9633e8cbf976510d7a9ea66f4ac96cPeter Collingbourne  static bool classof(const Attr *A) {
126a97d70b7ea9633e8cbf976510d7a9ea66f4ac96cPeter Collingbourne    return A->getKind() <= attr::LAST_INHERITABLE;
127a97d70b7ea9633e8cbf976510d7a9ea66f4ac96cPeter Collingbourne  }
128a97d70b7ea9633e8cbf976510d7a9ea66f4ac96cPeter Collingbourne  static bool classof(const InheritableAttr *) { return true; }
129a97d70b7ea9633e8cbf976510d7a9ea66f4ac96cPeter Collingbourne};
130a97d70b7ea9633e8cbf976510d7a9ea66f4ac96cPeter Collingbourne
131eca5d22c16eb784e5f35ca816fa22e0c0e060417John McCallclass InheritableParamAttr : public InheritableAttr {
13299ba9e3bd70671f3441fb974895f226a83ce0e66David Blaikie  virtual void anchor();
133eca5d22c16eb784e5f35ca816fa22e0c0e060417John McCallprotected:
134768d6cae40ad4ff3aed5483269d068ff7a45e229Argyrios Kyrtzidis  InheritableParamAttr(attr::Kind AK, SourceRange R)
135768d6cae40ad4ff3aed5483269d068ff7a45e229Argyrios Kyrtzidis    : InheritableAttr(AK, R) {}
136eca5d22c16eb784e5f35ca816fa22e0c0e060417John McCall
137eca5d22c16eb784e5f35ca816fa22e0c0e060417John McCallpublic:
138eca5d22c16eb784e5f35ca816fa22e0c0e060417John McCall  // Implement isa/cast/dyncast/etc.
139eca5d22c16eb784e5f35ca816fa22e0c0e060417John McCall  static bool classof(const Attr *A) {
140eca5d22c16eb784e5f35ca816fa22e0c0e060417John McCall    return A->getKind() <= attr::LAST_INHERITABLE_PARAM;
141eca5d22c16eb784e5f35ca816fa22e0c0e060417John McCall  }
142eca5d22c16eb784e5f35ca816fa22e0c0e060417John McCall  static bool classof(const InheritableParamAttr *) { return true; }
143eca5d22c16eb784e5f35ca816fa22e0c0e060417John McCall};
144eca5d22c16eb784e5f35ca816fa22e0c0e060417John McCall
145387475d0c18aaeb022108de9d33b6c9fb7998843Sean Hunt#include "clang/AST/Attrs.inc"
1461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
147cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt/// AttrVec - A vector of Attr, which is how they are stored on the AST.
148686775deca8b8685eb90801495880e3abdd844c2Chris Lattnertypedef SmallVector<Attr*, 2> AttrVec;
149686775deca8b8685eb90801495880e3abdd844c2Chris Lattnertypedef SmallVector<const Attr*, 2> ConstAttrVec;
150dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek
151cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
152cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt/// providing attributes that are of a specifc type.
1534990890fc9428f98bef90ba349203a648c592778Alexander Kornienkotemplate <typename SpecificAttr, typename Container = AttrVec>
154cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Huntclass specific_attr_iterator {
1554990890fc9428f98bef90ba349203a648c592778Alexander Kornienko  typedef typename Container::const_iterator Iterator;
1564990890fc9428f98bef90ba349203a648c592778Alexander Kornienko
157cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  /// Current - The current, underlying iterator.
158cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  /// In order to ensure we don't dereference an invalid iterator unless
159cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  /// specifically requested, we don't necessarily advance this all the
160cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  /// way. Instead, we advance it when an operation is requested; if the
161cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  /// operation is acting on what should be a past-the-end iterator,
162cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  /// then we offer no guarantees, but this way we do not dererence a
163cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  /// past-the-end iterator when we move to a past-the-end position.
1644990890fc9428f98bef90ba349203a648c592778Alexander Kornienko  mutable Iterator Current;
165dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek
166cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  void AdvanceToNext() const {
1679594675cc1eb52a054de13c4a21e466643847480Chris Lattner    while (!isa<SpecificAttr>(*Current))
168cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt      ++Current;
169dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek  }
170dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek
1714990890fc9428f98bef90ba349203a648c592778Alexander Kornienko  void AdvanceToNext(Iterator I) const {
1729594675cc1eb52a054de13c4a21e466643847480Chris Lattner    while (Current != I && !isa<SpecificAttr>(*Current))
173cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt      ++Current;
174dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek  }
175dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek
176dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenekpublic:
177cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  typedef SpecificAttr*             value_type;
178cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  typedef SpecificAttr*             reference;
179cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  typedef SpecificAttr*             pointer;
180cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  typedef std::forward_iterator_tag iterator_category;
181cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  typedef std::ptrdiff_t            difference_type;
182dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek
183cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  specific_attr_iterator() : Current() { }
1844990890fc9428f98bef90ba349203a648c592778Alexander Kornienko  explicit specific_attr_iterator(Iterator i) : Current(i) { }
185dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek
186cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  reference operator*() const {
187cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    AdvanceToNext();
1889594675cc1eb52a054de13c4a21e466643847480Chris Lattner    return cast<SpecificAttr>(*Current);
189dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek  }
190cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  pointer operator->() const {
191cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    AdvanceToNext();
1929594675cc1eb52a054de13c4a21e466643847480Chris Lattner    return cast<SpecificAttr>(*Current);
193dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek  }
194dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek
195cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  specific_attr_iterator& operator++() {
196cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    ++Current;
197cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    return *this;
198dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek  }
199cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  specific_attr_iterator operator++(int) {
200cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    specific_attr_iterator Tmp(*this);
201cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    ++(*this);
202cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    return Tmp;
203dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek  }
204dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek
205cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  friend bool operator==(specific_attr_iterator Left,
206cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt                         specific_attr_iterator Right) {
207cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    if (Left.Current < Right.Current)
208cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt      Left.AdvanceToNext(Right.Current);
209cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    else
210cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt      Right.AdvanceToNext(Left.Current);
211cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    return Left.Current == Right.Current;
212dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek  }
213cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  friend bool operator!=(specific_attr_iterator Left,
214cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt                         specific_attr_iterator Right) {
215cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    return !(Left == Right);
216dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek  }
217dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek};
218dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek
2194990890fc9428f98bef90ba349203a648c592778Alexander Kornienkotemplate <typename SpecificAttr, typename Container>
2204990890fc9428f98bef90ba349203a648c592778Alexander Kornienkoinline specific_attr_iterator<SpecificAttr, Container>
2214990890fc9428f98bef90ba349203a648c592778Alexander Kornienko          specific_attr_begin(const Container& container) {
2224990890fc9428f98bef90ba349203a648c592778Alexander Kornienko  return specific_attr_iterator<SpecificAttr, Container>(container.begin());
223cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt}
2244990890fc9428f98bef90ba349203a648c592778Alexander Kornienkotemplate <typename SpecificAttr, typename Container>
2254990890fc9428f98bef90ba349203a648c592778Alexander Kornienkoinline specific_attr_iterator<SpecificAttr, Container>
2264990890fc9428f98bef90ba349203a648c592778Alexander Kornienko          specific_attr_end(const Container& container) {
2274990890fc9428f98bef90ba349203a648c592778Alexander Kornienko  return specific_attr_iterator<SpecificAttr, Container>(container.end());
228cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt}
22982d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov
2304990890fc9428f98bef90ba349203a648c592778Alexander Kornienkotemplate <typename SpecificAttr, typename Container>
2314990890fc9428f98bef90ba349203a648c592778Alexander Kornienkoinline bool hasSpecificAttr(const Container& container) {
2324990890fc9428f98bef90ba349203a648c592778Alexander Kornienko  return specific_attr_begin<SpecificAttr>(container) !=
2334990890fc9428f98bef90ba349203a648c592778Alexander Kornienko          specific_attr_end<SpecificAttr>(container);
234cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt}
2354990890fc9428f98bef90ba349203a648c592778Alexander Kornienkotemplate <typename SpecificAttr, typename Container>
2364990890fc9428f98bef90ba349203a648c592778Alexander Kornienkoinline SpecificAttr *getSpecificAttr(const Container& container) {
2374990890fc9428f98bef90ba349203a648c592778Alexander Kornienko  specific_attr_iterator<SpecificAttr, Container> i =
2384990890fc9428f98bef90ba349203a648c592778Alexander Kornienko      specific_attr_begin<SpecificAttr>(container);
2394990890fc9428f98bef90ba349203a648c592778Alexander Kornienko  if (i != specific_attr_end<SpecificAttr>(container))
240cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    return *i;
241cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  else
242cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    return 0;
243cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt}
2445a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis
245cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt/// getMaxAlignment - Returns the highest alignment value found among
246cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt/// AlignedAttrs in an AttrVec, or 0 if there are none.
247cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Huntinline unsigned getMaxAttrAlignment(const AttrVec& V, ASTContext &Ctx) {
248cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  unsigned Align = 0;
249cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  specific_attr_iterator<AlignedAttr> i(V.begin()), e(V.end());
250cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  for(; i != e; ++i)
251cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    Align = std::max(Align, i->getAlignment(Ctx));
252cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  return Align;
253cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt}
2541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
255d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson}  // end namespace clang
256d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson
257d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson#endif
258