Attr.h revision a87cdc03f4014545a8440110c1f4f68701100576
1d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson//===--- Attr.h - Classes for representing expressions ----------*- 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
17d406bf0e8c17012110a8476d03c6f9a97b56ecf7Anders Carlsson#include "llvm/Support/Casting.h"
18cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt#include "llvm/ADT/SmallVector.h"
19bb377edda2656752016a0bc01fe4f9f8b6f80e19Benjamin Kramer#include "llvm/ADT/StringRef.h"
20387475d0c18aaeb022108de9d33b6c9fb7998843Sean Hunt#include "clang/Basic/AttrKinds.h"
21a8fb24fa3151567056f6125999cea69e39604f35Fariborz Jahanian#include "clang/AST/Type.h"
22cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt#include "clang/Basic/SourceLocation.h"
23baa66fc389ca0a9f11e0c864304bcfd89de39439Anders Carlsson#include <cassert>
24ea7e97e14f2f1f9817d2ae8a25ec6ea652e5287fArgyrios Kyrtzidis#include <cstring>
25eb2b2a3f1898f146c6e153a64ec58ec5e1750bd2Ted Kremenek#include <algorithm>
26bb377edda2656752016a0bc01fe4f9f8b6f80e19Benjamin Kramerusing llvm::dyn_cast;
27adf21bdb3d17acfdb74657fcbc5035a404c6c8f4Anders Carlsson
28d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlssonnamespace clang {
29cc5814732edc0c382d0136ab57ec6149566043e2Chris Lattner  class ASTContext;
30857e918a8a40deb128840308a318bf623d68295fTed Kremenek  class IdentifierInfo;
31857e918a8a40deb128840308a318bf623d68295fTed Kremenek  class ObjCInterfaceDecl;
324ced79f0971592e6e7122037de69ee9ae534ce72Chandler Carruth  class Expr;
33a8fb24fa3151567056f6125999cea69e39604f35Fariborz Jahanian  class QualType;
34cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  class FunctionDecl;
35cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  class TypeSourceInfo;
369f9bf258f8ebae30bfb70feb9d797d6eb67b0460Douglas Gregor}
379f9bf258f8ebae30bfb70feb9d797d6eb67b0460Douglas Gregor
389509108b3dde280dca1999b5c054f5b789581e68Chris Lattner// Defined in ASTContext.h
399f9bf258f8ebae30bfb70feb9d797d6eb67b0460Douglas Gregorvoid *operator new(size_t Bytes, clang::ASTContext &C,
409f9bf258f8ebae30bfb70feb9d797d6eb67b0460Douglas Gregor                   size_t Alignment = 16) throw ();
41cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt// FIXME: Being forced to not have a default argument here due to redeclaration
42cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt//        rules on default arguments sucks
43cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Huntvoid *operator new[](size_t Bytes, clang::ASTContext &C,
44cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt                     size_t Alignment) throw ();
459f9bf258f8ebae30bfb70feb9d797d6eb67b0460Douglas Gregor
469509108b3dde280dca1999b5c054f5b789581e68Chris Lattner// It is good practice to pair new/delete operators.  Also, MSVC gives many
479509108b3dde280dca1999b5c054f5b789581e68Chris Lattner// warnings if a matching delete overload is not declared, even though the
489509108b3dde280dca1999b5c054f5b789581e68Chris Lattner// throw() spec guarantees it will not be implicitly called.
499509108b3dde280dca1999b5c054f5b789581e68Chris Lattnervoid operator delete(void *Ptr, clang::ASTContext &C, size_t)
509509108b3dde280dca1999b5c054f5b789581e68Chris Lattner              throw ();
51cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Huntvoid operator delete[](void *Ptr, clang::ASTContext &C, size_t)
52cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt              throw ();
539509108b3dde280dca1999b5c054f5b789581e68Chris Lattner
549f9bf258f8ebae30bfb70feb9d797d6eb67b0460Douglas Gregornamespace clang {
55d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson
56d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson/// Attr - This represents one attribute.
57d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlssonclass Attr {
58d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlssonprivate:
59cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  SourceLocation Loc;
60cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  unsigned AttrKind : 16;
612f402708e62f89fb875442802e3d3f20fc909d33Anton Korobeynikov  bool Inherited : 1;
622f402708e62f89fb875442802e3d3f20fc909d33Anton Korobeynikov
63d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlssonprotected:
641de22a26c0e126b08edb2eda9d9091c021d96dc6Douglas Gregor  virtual ~Attr();
651de22a26c0e126b08edb2eda9d9091c021d96dc6Douglas Gregor
660b2b6e1cb1573bb295c0a65813dc4df8d57f305bChris Lattner  void* operator new(size_t bytes) throw() {
670b2b6e1cb1573bb295c0a65813dc4df8d57f305bChris Lattner    assert(0 && "Attrs cannot be allocated with regular 'new'.");
680b2b6e1cb1573bb295c0a65813dc4df8d57f305bChris Lattner    return 0;
690b2b6e1cb1573bb295c0a65813dc4df8d57f305bChris Lattner  }
700b2b6e1cb1573bb295c0a65813dc4df8d57f305bChris Lattner  void operator delete(void* data) throw() {
710b2b6e1cb1573bb295c0a65813dc4df8d57f305bChris Lattner    assert(0 && "Attrs cannot be released with regular 'delete'.");
720b2b6e1cb1573bb295c0a65813dc4df8d57f305bChris Lattner  }
731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
74cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Huntpublic:
75cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  // Forward so that the regular new and delete do not hide global ones.
76cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  void* operator new(size_t Bytes, ASTContext &C,
77cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt                     size_t Alignment = 16) throw() {
78cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    return ::operator new(Bytes, C, Alignment);
79cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  }
80cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  void operator delete(void *Ptr, ASTContext &C,
81a87cdc03f4014545a8440110c1f4f68701100576Eli Friedman                       size_t Alignment) throw() {
82cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    return ::operator delete(Ptr, C, Alignment);
83cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  }
84cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt
850b2b6e1cb1573bb295c0a65813dc4df8d57f305bChris Lattnerprotected:
86cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  Attr(attr::Kind AK, SourceLocation L)
871bf8d6f3a9dc636c3d1217d6fff11acf358e44beSean Hunt    : Loc(L), AttrKind(AK), Inherited(false) {}
88cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt
89cc5814732edc0c382d0136ab57ec6149566043e2Chris Lattnerpublic:
901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
91ae17094c001972a5949944a0a77ef6adf2a92c8fDouglas Gregor  /// \brief Whether this attribute should be merged to new
92ae17094c001972a5949944a0a77ef6adf2a92c8fDouglas Gregor  /// declarations.
93ae17094c001972a5949944a0a77ef6adf2a92c8fDouglas Gregor  virtual bool isMerged() const { return true; }
94ae17094c001972a5949944a0a77ef6adf2a92c8fDouglas Gregor
95cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  attr::Kind getKind() const {
96cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    return static_cast<attr::Kind>(AttrKind);
97d406bf0e8c17012110a8476d03c6f9a97b56ecf7Anders Carlsson  }
981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
99cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  SourceLocation getLocation() const { return Loc; }
100cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  void setLocation(SourceLocation L) { Loc = L; }
1011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
102cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  bool isInherited() const { return Inherited; }
103cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  void setInherited(bool I) { Inherited = I; }
1041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1059f9bf258f8ebae30bfb70feb9d797d6eb67b0460Douglas Gregor  // Clone this attribute.
1069f9bf258f8ebae30bfb70feb9d797d6eb67b0460Douglas Gregor  virtual Attr* clone(ASTContext &C) const = 0;
1079f9bf258f8ebae30bfb70feb9d797d6eb67b0460Douglas Gregor
108d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson  // Implement isa/cast/dyncast/etc.
109d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson  static bool classof(const Attr *) { return true; }
110d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson};
111387475d0c18aaeb022108de9d33b6c9fb7998843Sean Hunt
112387475d0c18aaeb022108de9d33b6c9fb7998843Sean Hunt#include "clang/AST/Attrs.inc"
1131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
114cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt/// AttrVec - A vector of Attr, which is how they are stored on the AST.
115cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunttypedef llvm::SmallVector<Attr*, 2> AttrVec;
116cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunttypedef llvm::SmallVector<const Attr*, 2> ConstAttrVec;
117dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek
118cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt/// DestroyAttrs - Destroy the contents of an AttrVec.
119cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Huntinline void DestroyAttrs (AttrVec& V, ASTContext &C) {
120cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt}
121dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek
122cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
123cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt/// providing attributes that are of a specifc type.
124cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunttemplate <typename SpecificAttr>
125cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Huntclass specific_attr_iterator {
126cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  /// Current - The current, underlying iterator.
127cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  /// In order to ensure we don't dereference an invalid iterator unless
128cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  /// specifically requested, we don't necessarily advance this all the
129cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  /// way. Instead, we advance it when an operation is requested; if the
130cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  /// operation is acting on what should be a past-the-end iterator,
131cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  /// then we offer no guarantees, but this way we do not dererence a
132cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  /// past-the-end iterator when we move to a past-the-end position.
133cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  mutable AttrVec::const_iterator Current;
134dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek
135cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  void AdvanceToNext() const {
136cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    while (!llvm::isa<SpecificAttr>(*Current))
137cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt      ++Current;
138dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek  }
139dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek
140cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  void AdvanceToNext(AttrVec::const_iterator I) const {
141cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    while (Current != I && !llvm::isa<SpecificAttr>(*Current))
142cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt      ++Current;
143dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek  }
144dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek
145dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenekpublic:
146cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  typedef SpecificAttr*             value_type;
147cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  typedef SpecificAttr*             reference;
148cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  typedef SpecificAttr*             pointer;
149cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  typedef std::forward_iterator_tag iterator_category;
150cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  typedef std::ptrdiff_t            difference_type;
151dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek
152cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  specific_attr_iterator() : Current() { }
153cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  explicit specific_attr_iterator(AttrVec::const_iterator i) : Current(i) { }
154dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek
155cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  reference operator*() const {
156cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    AdvanceToNext();
157cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    return llvm::cast<SpecificAttr>(*Current);
158dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek  }
159cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  pointer operator->() const {
160cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    AdvanceToNext();
161cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    return llvm::cast<SpecificAttr>(*Current);
162dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek  }
163dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek
164cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  specific_attr_iterator& operator++() {
165cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    ++Current;
166cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    return *this;
167dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek  }
168cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  specific_attr_iterator operator++(int) {
169cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    specific_attr_iterator Tmp(*this);
170cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    ++(*this);
171cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    return Tmp;
172dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek  }
173dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek
174cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  friend bool operator==(specific_attr_iterator Left,
175cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt                         specific_attr_iterator Right) {
176cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    if (Left.Current < Right.Current)
177cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt      Left.AdvanceToNext(Right.Current);
178cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    else
179cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt      Right.AdvanceToNext(Left.Current);
180cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    return Left.Current == Right.Current;
181dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek  }
182cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  friend bool operator!=(specific_attr_iterator Left,
183cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt                         specific_attr_iterator Right) {
184cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    return !(Left == Right);
185dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek  }
186dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek};
187dd0e490c24aeade2c59ca4cae171199f6af9f02eTed Kremenek
188cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunttemplate <typename T>
189cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Huntinline specific_attr_iterator<T> specific_attr_begin(const AttrVec& vec) {
190cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  return specific_attr_iterator<T>(vec.begin());
191cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt}
192cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunttemplate <typename T>
193cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Huntinline specific_attr_iterator<T> specific_attr_end(const AttrVec& vec) {
194cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  return specific_attr_iterator<T>(vec.end());
195cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt}
19682d0a418c8699fc6f4a9417457ffe93d43bba1c1Anton Korobeynikov
197cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunttemplate <typename T>
198cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Huntinline bool hasSpecificAttr(const AttrVec& vec) {
199cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  return specific_attr_begin<T>(vec) != specific_attr_end<T>(vec);
200cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt}
201cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunttemplate <typename T>
202cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Huntinline T *getSpecificAttr(const AttrVec& vec) {
203cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  specific_attr_iterator<T> i = specific_attr_begin<T>(vec);
204cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  if (i != specific_attr_end<T>(vec))
205cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    return *i;
206cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  else
207cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    return 0;
208cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt}
2095a0164d6ab843ca61437ec59a504365cb1c98f43Charles Davis
210cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt/// getMaxAlignment - Returns the highest alignment value found among
211cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt/// AlignedAttrs in an AttrVec, or 0 if there are none.
212cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Huntinline unsigned getMaxAttrAlignment(const AttrVec& V, ASTContext &Ctx) {
213cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  unsigned Align = 0;
214cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  specific_attr_iterator<AlignedAttr> i(V.begin()), e(V.end());
215cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  for(; i != e; ++i)
216cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt    Align = std::max(Align, i->getAlignment(Ctx));
217cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt  return Align;
218cf807c4dfdb23e8fa3f400e0b24ef5b79db7a530Sean Hunt}
2191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
220d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson}  // end namespace clang
221d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson
222d429cd459aef723fa0e7a44ac957d4c2256e241cAnders Carlsson#endif
223