Attr.h revision 212904
1//===--- Attr.h - Classes for representing expressions ----------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines the Attr interface and subclasses. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef LLVM_CLANG_AST_ATTR_H 15#define LLVM_CLANG_AST_ATTR_H 16 17#include "llvm/Support/Casting.h" 18#include "llvm/ADT/SmallVector.h" 19#include "llvm/ADT/StringRef.h" 20#include "clang/Basic/AttrKinds.h" 21#include "clang/AST/Type.h" 22#include "clang/Basic/SourceLocation.h" 23#include <cassert> 24#include <cstring> 25#include <algorithm> 26using llvm::dyn_cast; 27 28namespace clang { 29 class ASTContext; 30 class IdentifierInfo; 31 class ObjCInterfaceDecl; 32 class Expr; 33 class QualType; 34 class FunctionDecl; 35 class TypeSourceInfo; 36} 37 38// Defined in ASTContext.h 39void *operator new(size_t Bytes, clang::ASTContext &C, 40 size_t Alignment = 16) throw (); 41// FIXME: Being forced to not have a default argument here due to redeclaration 42// rules on default arguments sucks 43void *operator new[](size_t Bytes, clang::ASTContext &C, 44 size_t Alignment) throw (); 45 46// It is good practice to pair new/delete operators. Also, MSVC gives many 47// warnings if a matching delete overload is not declared, even though the 48// throw() spec guarantees it will not be implicitly called. 49void operator delete(void *Ptr, clang::ASTContext &C, size_t) 50 throw (); 51void operator delete[](void *Ptr, clang::ASTContext &C, size_t) 52 throw (); 53 54namespace clang { 55 56/// Attr - This represents one attribute. 57class Attr { 58private: 59 SourceLocation Loc; 60 unsigned AttrKind : 16; 61 bool Inherited : 1; 62 63protected: 64 virtual ~Attr(); 65 66 void* operator new(size_t bytes) throw() { 67 assert(0 && "Attrs cannot be allocated with regular 'new'."); 68 return 0; 69 } 70 void operator delete(void* data) throw() { 71 assert(0 && "Attrs cannot be released with regular 'delete'."); 72 } 73 74public: 75 // Forward so that the regular new and delete do not hide global ones. 76 void* operator new(size_t Bytes, ASTContext &C, 77 size_t Alignment = 16) throw() { 78 return ::operator new(Bytes, C, Alignment); 79 } 80 void operator delete(void *Ptr, ASTContext &C, 81 size_t Alignment) throw() { 82 return ::operator delete(Ptr, C, Alignment); 83 } 84 85protected: 86 Attr(attr::Kind AK, SourceLocation L) 87 : Loc(L), AttrKind(AK), Inherited(false) {} 88 89public: 90 91 /// \brief Whether this attribute should be merged to new 92 /// declarations. 93 virtual bool isMerged() const { return true; } 94 95 attr::Kind getKind() const { 96 return static_cast<attr::Kind>(AttrKind); 97 } 98 99 SourceLocation getLocation() const { return Loc; } 100 void setLocation(SourceLocation L) { Loc = L; } 101 102 bool isInherited() const { return Inherited; } 103 void setInherited(bool I) { Inherited = I; } 104 105 // Clone this attribute. 106 virtual Attr* clone(ASTContext &C) const = 0; 107 108 // Implement isa/cast/dyncast/etc. 109 static bool classof(const Attr *) { return true; } 110}; 111 112#include "clang/AST/Attrs.inc" 113 114/// AttrVec - A vector of Attr, which is how they are stored on the AST. 115typedef llvm::SmallVector<Attr*, 2> AttrVec; 116typedef llvm::SmallVector<const Attr*, 2> ConstAttrVec; 117 118/// DestroyAttrs - Destroy the contents of an AttrVec. 119inline void DestroyAttrs (AttrVec& V, ASTContext &C) { 120} 121 122/// specific_attr_iterator - Iterates over a subrange of an AttrVec, only 123/// providing attributes that are of a specifc type. 124template <typename SpecificAttr> 125class specific_attr_iterator { 126 /// Current - The current, underlying iterator. 127 /// In order to ensure we don't dereference an invalid iterator unless 128 /// specifically requested, we don't necessarily advance this all the 129 /// way. Instead, we advance it when an operation is requested; if the 130 /// operation is acting on what should be a past-the-end iterator, 131 /// then we offer no guarantees, but this way we do not dererence a 132 /// past-the-end iterator when we move to a past-the-end position. 133 mutable AttrVec::const_iterator Current; 134 135 void AdvanceToNext() const { 136 while (!llvm::isa<SpecificAttr>(*Current)) 137 ++Current; 138 } 139 140 void AdvanceToNext(AttrVec::const_iterator I) const { 141 while (Current != I && !llvm::isa<SpecificAttr>(*Current)) 142 ++Current; 143 } 144 145public: 146 typedef SpecificAttr* value_type; 147 typedef SpecificAttr* reference; 148 typedef SpecificAttr* pointer; 149 typedef std::forward_iterator_tag iterator_category; 150 typedef std::ptrdiff_t difference_type; 151 152 specific_attr_iterator() : Current() { } 153 explicit specific_attr_iterator(AttrVec::const_iterator i) : Current(i) { } 154 155 reference operator*() const { 156 AdvanceToNext(); 157 return llvm::cast<SpecificAttr>(*Current); 158 } 159 pointer operator->() const { 160 AdvanceToNext(); 161 return llvm::cast<SpecificAttr>(*Current); 162 } 163 164 specific_attr_iterator& operator++() { 165 ++Current; 166 return *this; 167 } 168 specific_attr_iterator operator++(int) { 169 specific_attr_iterator Tmp(*this); 170 ++(*this); 171 return Tmp; 172 } 173 174 friend bool operator==(specific_attr_iterator Left, 175 specific_attr_iterator Right) { 176 if (Left.Current < Right.Current) 177 Left.AdvanceToNext(Right.Current); 178 else 179 Right.AdvanceToNext(Left.Current); 180 return Left.Current == Right.Current; 181 } 182 friend bool operator!=(specific_attr_iterator Left, 183 specific_attr_iterator Right) { 184 return !(Left == Right); 185 } 186}; 187 188template <typename T> 189inline specific_attr_iterator<T> specific_attr_begin(const AttrVec& vec) { 190 return specific_attr_iterator<T>(vec.begin()); 191} 192template <typename T> 193inline specific_attr_iterator<T> specific_attr_end(const AttrVec& vec) { 194 return specific_attr_iterator<T>(vec.end()); 195} 196 197template <typename T> 198inline bool hasSpecificAttr(const AttrVec& vec) { 199 return specific_attr_begin<T>(vec) != specific_attr_end<T>(vec); 200} 201template <typename T> 202inline T *getSpecificAttr(const AttrVec& vec) { 203 specific_attr_iterator<T> i = specific_attr_begin<T>(vec); 204 if (i != specific_attr_end<T>(vec)) 205 return *i; 206 else 207 return 0; 208} 209 210/// getMaxAlignment - Returns the highest alignment value found among 211/// AlignedAttrs in an AttrVec, or 0 if there are none. 212inline unsigned getMaxAttrAlignment(const AttrVec& V, ASTContext &Ctx) { 213 unsigned Align = 0; 214 specific_attr_iterator<AlignedAttr> i(V.begin()), e(V.end()); 215 for(; i != e; ++i) 216 Align = std::max(Align, i->getAlignment(Ctx)); 217 return Align; 218} 219 220} // end namespace clang 221 222#endif 223