summaryrefslogtreecommitdiffstats
path: root/include/clang/AST/Attr.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/AST/Attr.h')
-rw-r--r--include/clang/AST/Attr.h607
1 files changed, 119 insertions, 488 deletions
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 9faa62e..62ca49f 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -15,8 +15,11 @@
#define LLVM_CLANG_AST_ATTR_H
#include "llvm/Support/Casting.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "clang/Basic/AttrKinds.h"
+#include "clang/AST/Type.h"
+#include "clang/Basic/SourceLocation.h"
#include <cassert>
#include <cstring>
#include <algorithm>
@@ -27,28 +30,39 @@ namespace clang {
class IdentifierInfo;
class ObjCInterfaceDecl;
class Expr;
+ class QualType;
+ class FunctionDecl;
+ class TypeSourceInfo;
}
// Defined in ASTContext.h
void *operator new(size_t Bytes, clang::ASTContext &C,
size_t Alignment = 16) throw ();
+// FIXME: Being forced to not have a default argument here due to redeclaration
+// rules on default arguments sucks
+void *operator new[](size_t Bytes, clang::ASTContext &C,
+ size_t Alignment) throw ();
// It is good practice to pair new/delete operators. Also, MSVC gives many
// warnings if a matching delete overload is not declared, even though the
// throw() spec guarantees it will not be implicitly called.
void operator delete(void *Ptr, clang::ASTContext &C, size_t)
throw ();
+void operator delete[](void *Ptr, clang::ASTContext &C, size_t)
+ throw ();
namespace clang {
/// Attr - This represents one attribute.
class Attr {
private:
- Attr *Next;
- attr::Kind AttrKind;
+ SourceLocation Loc;
+ unsigned AttrKind : 16;
bool Inherited : 1;
protected:
+ virtual ~Attr();
+
void* operator new(size_t bytes) throw() {
assert(0 && "Attrs cannot be allocated with regular 'new'.");
return 0;
@@ -57,41 +71,36 @@ protected:
assert(0 && "Attrs cannot be released with regular 'delete'.");
}
-protected:
- Attr(attr::Kind AK) : Next(0), AttrKind(AK), Inherited(false) {}
- virtual ~Attr() {
- assert(Next == 0 && "Destroy didn't work");
+public:
+ // Forward so that the regular new and delete do not hide global ones.
+ void* operator new(size_t Bytes, ASTContext &C,
+ size_t Alignment = 16) throw() {
+ return ::operator new(Bytes, C, Alignment);
}
+ void operator delete(void *Ptr, ASTContext &C,
+ size_t Alignment) throw() {
+ return ::operator delete(Ptr, C, Alignment);
+ }
+
+protected:
+ Attr(attr::Kind AK, SourceLocation L)
+ : Loc(L), AttrKind(AK), Inherited(false) {}
+
public:
- virtual void Destroy(ASTContext &C);
/// \brief Whether this attribute should be merged to new
/// declarations.
virtual bool isMerged() const { return true; }
- attr::Kind getKind() const { return AttrKind; }
-
- Attr *getNext() { return Next; }
- const Attr *getNext() const { return Next; }
- void setNext(Attr *next) { Next = next; }
-
- template<typename T> const T *getNext() const {
- for (const Attr *attr = getNext(); attr; attr = attr->getNext())
- if (const T *V = dyn_cast<T>(attr))
- return V;
- return 0;
+ attr::Kind getKind() const {
+ return static_cast<attr::Kind>(AttrKind);
}
- bool isInherited() const { return Inherited; }
- void setInherited(bool value) { Inherited = value; }
-
- void addAttr(Attr *attr) {
- assert((attr != 0) && "addAttr(): attr is null");
+ SourceLocation getLocation() const { return Loc; }
+ void setLocation(SourceLocation L) { Loc = L; }
- // FIXME: This doesn't preserve the order in any way.
- attr->Next = Next;
- Next = attr;
- }
+ bool isInherited() const { return Inherited; }
+ void setInherited(bool I) { Inherited = I; }
// Clone this attribute.
virtual Attr* clone(ASTContext &C) const = 0;
@@ -101,490 +110,112 @@ public:
};
#include "clang/AST/Attrs.inc"
-
-class AttrWithString : public Attr {
-private:
- const char *Str;
- unsigned StrLen;
-protected:
- AttrWithString(attr::Kind AK, ASTContext &C, llvm::StringRef s);
- llvm::StringRef getString() const { return llvm::StringRef(Str, StrLen); }
- void ReplaceString(ASTContext &C, llvm::StringRef newS);
-public:
- virtual void Destroy(ASTContext &C);
-};
-
-#define DEF_SIMPLE_ATTR(ATTR) \
-class ATTR##Attr : public Attr { \
-public: \
- ATTR##Attr() : Attr(attr::ATTR) {} \
- virtual Attr *clone(ASTContext &C) const; \
- static bool classof(const Attr *A) { return A->getKind() == attr::ATTR; } \
- static bool classof(const ATTR##Attr *A) { return true; } \
-}
-DEF_SIMPLE_ATTR(Packed);
-
-/// \brief Attribute for specifying a maximum field alignment; this is only
-/// valid on record decls.
-class MaxFieldAlignmentAttr : public Attr {
- unsigned Alignment;
-
-public:
- MaxFieldAlignmentAttr(unsigned alignment)
- : Attr(attr::MaxFieldAlignment), Alignment(alignment) {}
+/// AttrVec - A vector of Attr, which is how they are stored on the AST.
+typedef llvm::SmallVector<Attr*, 2> AttrVec;
+typedef llvm::SmallVector<const Attr*, 2> ConstAttrVec;
- /// getAlignment - The specified alignment in bits.
- unsigned getAlignment() const { return Alignment; }
-
- virtual Attr* clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::MaxFieldAlignment;
- }
- static bool classof(const MaxFieldAlignmentAttr *A) { return true; }
-};
-
-DEF_SIMPLE_ATTR(AlignMac68k);
-
-/// \brief Atribute for specifying the alignment of a variable or type.
-///
-/// This node will either contain the precise Alignment (in bits, not bytes!)
-/// or will contain the expression for the alignment attribute in the case of
-/// a dependent expression within a class or function template. At template
-/// instantiation time these are transformed into concrete attributes.
-class AlignedAttr : public Attr {
- unsigned Alignment;
- Expr *AlignmentExpr;
-public:
- AlignedAttr(unsigned alignment)
- : Attr(attr::Aligned), Alignment(alignment), AlignmentExpr(0) {}
- AlignedAttr(Expr *E)
- : Attr(attr::Aligned), Alignment(0), AlignmentExpr(E) {}
-
- /// getAlignmentExpr - Get a dependent alignment expression if one is present.
- Expr *getAlignmentExpr() const {
- return AlignmentExpr;
- }
-
- /// isDependent - Is the alignment a dependent expression
- bool isDependent() const {
- return getAlignmentExpr();
- }
+/// DestroyAttrs - Destroy the contents of an AttrVec.
+inline void DestroyAttrs (AttrVec& V, ASTContext &C) {
+}
- /// getAlignment - The specified alignment in bits. Requires !isDependent().
- unsigned getAlignment() const {
- assert(!isDependent() && "Cannot get a value dependent alignment");
- return Alignment;
- }
+/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only
+/// providing attributes that are of a specifc type.
+template <typename SpecificAttr>
+class specific_attr_iterator {
+ /// Current - The current, underlying iterator.
+ /// In order to ensure we don't dereference an invalid iterator unless
+ /// specifically requested, we don't necessarily advance this all the
+ /// way. Instead, we advance it when an operation is requested; if the
+ /// operation is acting on what should be a past-the-end iterator,
+ /// then we offer no guarantees, but this way we do not dererence a
+ /// past-the-end iterator when we move to a past-the-end position.
+ mutable AttrVec::const_iterator Current;
- /// getMaxAlignment - Get the maximum alignment of attributes on this list.
- unsigned getMaxAlignment() const {
- const AlignedAttr *Next = getNext<AlignedAttr>();
- if (Next)
- return std::max(Next->getMaxAlignment(), getAlignment());
- else
- return getAlignment();
+ void AdvanceToNext() const {
+ while (!llvm::isa<SpecificAttr>(*Current))
+ ++Current;
}
- virtual Attr* clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::Aligned;
+ void AdvanceToNext(AttrVec::const_iterator I) const {
+ while (Current != I && !llvm::isa<SpecificAttr>(*Current))
+ ++Current;
}
- static bool classof(const AlignedAttr *A) { return true; }
-};
-class AnnotateAttr : public AttrWithString {
public:
- AnnotateAttr(ASTContext &C, llvm::StringRef ann)
- : AttrWithString(attr::Annotate, C, ann) {}
-
- llvm::StringRef getAnnotation() const { return getString(); }
+ typedef SpecificAttr* value_type;
+ typedef SpecificAttr* reference;
+ typedef SpecificAttr* pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef std::ptrdiff_t difference_type;
- virtual Attr* clone(ASTContext &C) const;
+ specific_attr_iterator() : Current() { }
+ explicit specific_attr_iterator(AttrVec::const_iterator i) : Current(i) { }
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::Annotate;
+ reference operator*() const {
+ AdvanceToNext();
+ return llvm::cast<SpecificAttr>(*Current);
}
- static bool classof(const AnnotateAttr *A) { return true; }
-};
-
-class AsmLabelAttr : public AttrWithString {
-public:
- AsmLabelAttr(ASTContext &C, llvm::StringRef L)
- : AttrWithString(attr::AsmLabel, C, L) {}
-
- llvm::StringRef getLabel() const { return getString(); }
-
- virtual Attr* clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::AsmLabel;
- }
- static bool classof(const AsmLabelAttr *A) { return true; }
-};
-
-DEF_SIMPLE_ATTR(AlwaysInline);
-
-class AliasAttr : public AttrWithString {
-public:
- AliasAttr(ASTContext &C, llvm::StringRef aliasee)
- : AttrWithString(attr::Alias, C, aliasee) {}
-
- llvm::StringRef getAliasee() const { return getString(); }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == attr::Alias; }
- static bool classof(const AliasAttr *A) { return true; }
-};
-
-class ConstructorAttr : public Attr {
- int priority;
-public:
- ConstructorAttr(int p) : Attr(attr::Constructor), priority(p) {}
-
- int getPriority() const { return priority; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A)
- { return A->getKind() == attr::Constructor; }
- static bool classof(const ConstructorAttr *A) { return true; }
-};
-
-class DestructorAttr : public Attr {
- int priority;
-public:
- DestructorAttr(int p) : Attr(attr::Destructor), priority(p) {}
-
- int getPriority() const { return priority; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A)
- { return A->getKind() == attr::Destructor; }
- static bool classof(const DestructorAttr *A) { return true; }
-};
-
-class IBOutletAttr : public Attr {
-public:
- IBOutletAttr() : Attr(attr::IBOutlet) {}
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::IBOutlet;
- }
- static bool classof(const IBOutletAttr *A) { return true; }
-};
-
-class IBOutletCollectionAttr : public Attr {
- const ObjCInterfaceDecl *D;
-public:
- IBOutletCollectionAttr(const ObjCInterfaceDecl *d = 0)
- : Attr(attr::IBOutletCollection), D(d) {}
-
- const ObjCInterfaceDecl *getClass() const { return D; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::IBOutletCollection;
+ pointer operator->() const {
+ AdvanceToNext();
+ return llvm::cast<SpecificAttr>(*Current);
}
- static bool classof(const IBOutletCollectionAttr *A) { return true; }
-};
-
-class IBActionAttr : public Attr {
-public:
- IBActionAttr() : Attr(attr::IBAction) {}
-
- virtual Attr *clone(ASTContext &C) const;
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::IBAction;
+ specific_attr_iterator& operator++() {
+ ++Current;
+ return *this;
}
- static bool classof(const IBActionAttr *A) { return true; }
-};
-
-DEF_SIMPLE_ATTR(AnalyzerNoReturn);
-DEF_SIMPLE_ATTR(Deprecated);
-DEF_SIMPLE_ATTR(GNUInline);
-DEF_SIMPLE_ATTR(Malloc);
-DEF_SIMPLE_ATTR(NoReturn);
-DEF_SIMPLE_ATTR(NoInstrumentFunction);
-
-class SectionAttr : public AttrWithString {
-public:
- SectionAttr(ASTContext &C, llvm::StringRef N)
- : AttrWithString(attr::Section, C, N) {}
-
- llvm::StringRef getName() const { return getString(); }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::Section;
+ specific_attr_iterator operator++(int) {
+ specific_attr_iterator Tmp(*this);
+ ++(*this);
+ return Tmp;
}
- static bool classof(const SectionAttr *A) { return true; }
-};
-
-DEF_SIMPLE_ATTR(Unavailable);
-DEF_SIMPLE_ATTR(Unused);
-DEF_SIMPLE_ATTR(Used);
-DEF_SIMPLE_ATTR(Weak);
-DEF_SIMPLE_ATTR(WeakImport);
-DEF_SIMPLE_ATTR(WeakRef);
-DEF_SIMPLE_ATTR(NoThrow);
-DEF_SIMPLE_ATTR(Const);
-DEF_SIMPLE_ATTR(Pure);
-
-class NonNullAttr : public Attr {
- unsigned* ArgNums;
- unsigned Size;
-public:
- NonNullAttr(ASTContext &C, unsigned* arg_nums = 0, unsigned size = 0);
-
- virtual void Destroy(ASTContext &C);
-
- typedef const unsigned *iterator;
- iterator begin() const { return ArgNums; }
- iterator end() const { return ArgNums + Size; }
- unsigned size() const { return Size; }
- bool isNonNull(unsigned arg) const {
- return ArgNums ? std::binary_search(ArgNums, ArgNums+Size, arg) : true;
+ friend bool operator==(specific_attr_iterator Left,
+ specific_attr_iterator Right) {
+ if (Left.Current < Right.Current)
+ Left.AdvanceToNext(Right.Current);
+ else
+ Right.AdvanceToNext(Left.Current);
+ return Left.Current == Right.Current;
}
-
- virtual Attr *clone(ASTContext &C) const;
-
- static bool classof(const Attr *A) { return A->getKind() == attr::NonNull; }
- static bool classof(const NonNullAttr *A) { return true; }
-};
-
-class FormatAttr : public AttrWithString {
- int formatIdx, firstArg;
-public:
- FormatAttr(ASTContext &C, llvm::StringRef type, int idx, int first)
- : AttrWithString(attr::Format, C, type), formatIdx(idx), firstArg(first) {}
-
- llvm::StringRef getType() const { return getString(); }
- void setType(ASTContext &C, llvm::StringRef type);
- int getFormatIdx() const { return formatIdx; }
- int getFirstArg() const { return firstArg; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == attr::Format; }
- static bool classof(const FormatAttr *A) { return true; }
-};
-
-class FormatArgAttr : public Attr {
- int formatIdx;
-public:
- FormatArgAttr(int idx) : Attr(attr::FormatArg), formatIdx(idx) {}
- int getFormatIdx() const { return formatIdx; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == attr::FormatArg; }
- static bool classof(const FormatArgAttr *A) { return true; }
-};
-
-class SentinelAttr : public Attr {
- int sentinel, NullPos;
-public:
- SentinelAttr(int sentinel_val, int nullPos) : Attr(attr::Sentinel),
- sentinel(sentinel_val), NullPos(nullPos) {}
- int getSentinel() const { return sentinel; }
- int getNullPos() const { return NullPos; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == attr::Sentinel; }
- static bool classof(const SentinelAttr *A) { return true; }
-};
-
-class VisibilityAttr : public Attr {
-public:
- /// @brief An enumeration for the kinds of visibility of symbols.
- enum VisibilityTypes {
- DefaultVisibility = 0,
- HiddenVisibility,
- ProtectedVisibility
- };
-private:
- VisibilityTypes VisibilityType;
-public:
- VisibilityAttr(VisibilityTypes v) : Attr(attr::Visibility),
- VisibilityType(v) {}
-
- VisibilityTypes getVisibility() const { return VisibilityType; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A)
- { return A->getKind() == attr::Visibility; }
- static bool classof(const VisibilityAttr *A) { return true; }
-};
-
-DEF_SIMPLE_ATTR(FastCall);
-DEF_SIMPLE_ATTR(StdCall);
-DEF_SIMPLE_ATTR(ThisCall);
-DEF_SIMPLE_ATTR(CDecl);
-DEF_SIMPLE_ATTR(TransparentUnion);
-DEF_SIMPLE_ATTR(ObjCNSObject);
-DEF_SIMPLE_ATTR(ObjCException);
-
-class OverloadableAttr : public Attr {
-public:
- OverloadableAttr() : Attr(attr::Overloadable) { }
-
- virtual bool isMerged() const { return false; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- static bool classof(const Attr *A)
- { return A->getKind() == attr::Overloadable; }
- static bool classof(const OverloadableAttr *) { return true; }
-};
-
-class BlocksAttr : public Attr {
-public:
- enum BlocksAttrTypes {
- ByRef = 0
- };
-private:
- BlocksAttrTypes BlocksAttrType;
-public:
- BlocksAttr(BlocksAttrTypes t) : Attr(attr::Blocks), BlocksAttrType(t) {}
-
- BlocksAttrTypes getType() const { return BlocksAttrType; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == attr::Blocks; }
- static bool classof(const BlocksAttr *A) { return true; }
-};
-
-class FunctionDecl;
-
-class CleanupAttr : public Attr {
- FunctionDecl *FD;
-
-public:
- CleanupAttr(FunctionDecl *fd) : Attr(attr::Cleanup), FD(fd) {}
-
- const FunctionDecl *getFunctionDecl() const { return FD; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == attr::Cleanup; }
- static bool classof(const CleanupAttr *A) { return true; }
-};
-
-DEF_SIMPLE_ATTR(NoDebug);
-DEF_SIMPLE_ATTR(WarnUnusedResult);
-DEF_SIMPLE_ATTR(NoInline);
-
-class RegparmAttr : public Attr {
- unsigned NumParams;
-
-public:
- RegparmAttr(unsigned np) : Attr(attr::Regparm), NumParams(np) {}
-
- unsigned getNumParams() const { return NumParams; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) { return A->getKind() == attr::Regparm; }
- static bool classof(const RegparmAttr *A) { return true; }
-};
-
-class ReqdWorkGroupSizeAttr : public Attr {
- unsigned X, Y, Z;
-public:
- ReqdWorkGroupSizeAttr(unsigned X, unsigned Y, unsigned Z)
- : Attr(attr::ReqdWorkGroupSize), X(X), Y(Y), Z(Z) {}
-
- unsigned getXDim() const { return X; }
- unsigned getYDim() const { return Y; }
- unsigned getZDim() const { return Z; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A) {
- return A->getKind() == attr::ReqdWorkGroupSize;
+ friend bool operator!=(specific_attr_iterator Left,
+ specific_attr_iterator Right) {
+ return !(Left == Right);
}
- static bool classof(const ReqdWorkGroupSizeAttr *A) { return true; }
};
-class InitPriorityAttr : public Attr {
- unsigned Priority;
-public:
- InitPriorityAttr(unsigned priority)
- : Attr(attr::InitPriority), Priority(priority) {}
-
- virtual void Destroy(ASTContext &C) { Attr::Destroy(C); }
-
- unsigned getPriority() const { return Priority; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- static bool classof(const Attr *A)
- { return A->getKind() == attr::InitPriority; }
- static bool classof(const InitPriorityAttr *A) { return true; }
-};
-
-// Checker-specific attributes.
-DEF_SIMPLE_ATTR(CFReturnsNotRetained);
-DEF_SIMPLE_ATTR(CFReturnsRetained);
-DEF_SIMPLE_ATTR(NSReturnsNotRetained);
-DEF_SIMPLE_ATTR(NSReturnsRetained);
-
-// Target-specific attributes
-DEF_SIMPLE_ATTR(DLLImport);
-DEF_SIMPLE_ATTR(DLLExport);
-
-class MSP430InterruptAttr : public Attr {
- unsigned Number;
-
-public:
- MSP430InterruptAttr(unsigned n) : Attr(attr::MSP430Interrupt), Number(n) {}
-
- unsigned getNumber() const { return Number; }
-
- virtual Attr *clone(ASTContext &C) const;
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Attr *A)
- { return A->getKind() == attr::MSP430Interrupt; }
- static bool classof(const MSP430InterruptAttr *A) { return true; }
-};
+template <typename T>
+inline specific_attr_iterator<T> specific_attr_begin(const AttrVec& vec) {
+ return specific_attr_iterator<T>(vec.begin());
+}
+template <typename T>
+inline specific_attr_iterator<T> specific_attr_end(const AttrVec& vec) {
+ return specific_attr_iterator<T>(vec.end());
+}
-DEF_SIMPLE_ATTR(X86ForceAlignArgPointer);
+template <typename T>
+inline bool hasSpecificAttr(const AttrVec& vec) {
+ return specific_attr_begin<T>(vec) != specific_attr_end<T>(vec);
+}
+template <typename T>
+inline T *getSpecificAttr(const AttrVec& vec) {
+ specific_attr_iterator<T> i = specific_attr_begin<T>(vec);
+ if (i != specific_attr_end<T>(vec))
+ return *i;
+ else
+ return 0;
+}
-#undef DEF_SIMPLE_ATTR
+/// getMaxAlignment - Returns the highest alignment value found among
+/// AlignedAttrs in an AttrVec, or 0 if there are none.
+inline unsigned getMaxAttrAlignment(const AttrVec& V, ASTContext &Ctx) {
+ unsigned Align = 0;
+ specific_attr_iterator<AlignedAttr> i(V.begin()), e(V.end());
+ for(; i != e; ++i)
+ Align = std::max(Align, i->getAlignment(Ctx));
+ return Align;
+}
} // end namespace clang
OpenPOWER on IntegriCloud