1 //===--- Attr.h - Classes for representing attributes ----------*- 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 "clang/AST/AttrIterator.h" 18 #include "clang/AST/Decl.h" 19 #include "clang/AST/Expr.h" 20 #include "clang/AST/Type.h" 21 #include "clang/Basic/AttrKinds.h" 22 #include "clang/Basic/LLVM.h" 23 #include "clang/Basic/OpenMPKinds.h" 24 #include "clang/Basic/Sanitizers.h" 25 #include "clang/Basic/SourceLocation.h" 26 #include "clang/Basic/VersionTuple.h" 27 #include "llvm/ADT/StringSwitch.h" 28 #include "llvm/Support/ErrorHandling.h" 29 #include "llvm/Support/raw_ostream.h" 30 #include <algorithm> 31 #include <cassert> 32 33 namespace clang { 34 class ASTContext; 35 class IdentifierInfo; 36 class ObjCInterfaceDecl; 37 class Expr; 38 class QualType; 39 class FunctionDecl; 40 class TypeSourceInfo; 41 42 /// Attr - This represents one attribute. 43 class Attr { 44 private: 45 SourceRange Range; 46 unsigned AttrKind : 16; 47 48 protected: 49 /// An index into the spelling list of an 50 /// attribute defined in Attr.td file. 51 unsigned SpellingListIndex : 4; 52 unsigned Inherited : 1; 53 unsigned IsPackExpansion : 1; 54 unsigned Implicit : 1; 55 unsigned IsLateParsed : 1; 56 unsigned DuplicatesAllowed : 1; 57 58 void *operator new(size_t bytes) noexcept { 59 llvm_unreachable("Attrs cannot be allocated with regular 'new'."); 60 } 61 void operator delete(void *data) noexcept { 62 llvm_unreachable("Attrs cannot be released with regular 'delete'."); 63 } 64 65 public: 66 // Forward so that the regular new and delete do not hide global ones. 67 void *operator new(size_t Bytes, ASTContext &C, 68 size_t Alignment = 8) noexcept { 69 return ::operator new(Bytes, C, Alignment); 70 } 71 void operator delete(void *Ptr, ASTContext &C, size_t Alignment) noexcept { 72 return ::operator delete(Ptr, C, Alignment); 73 } 74 75 protected: 76 Attr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, 77 bool IsLateParsed, bool DuplicatesAllowed) 78 : Range(R), AttrKind(AK), SpellingListIndex(SpellingListIndex), 79 Inherited(false), IsPackExpansion(false), Implicit(false), 80 IsLateParsed(IsLateParsed), DuplicatesAllowed(DuplicatesAllowed) {} 81 82 public: 83 84 attr::Kind getKind() const { 85 return static_cast<attr::Kind>(AttrKind); 86 } 87 88 unsigned getSpellingListIndex() const { return SpellingListIndex; } 89 const char *getSpelling() const; 90 91 SourceLocation getLocation() const { return Range.getBegin(); } 92 SourceRange getRange() const { return Range; } 93 void setRange(SourceRange R) { Range = R; } 94 95 bool isInherited() const { return Inherited; } 96 97 /// \brief Returns true if the attribute has been implicitly created instead 98 /// of explicitly written by the user. 99 bool isImplicit() const { return Implicit; } 100 void setImplicit(bool I) { Implicit = I; } 101 102 void setPackExpansion(bool PE) { IsPackExpansion = PE; } 103 bool isPackExpansion() const { return IsPackExpansion; } 104 105 // Clone this attribute. 106 Attr *clone(ASTContext &C) const; 107 108 bool isLateParsed() const { return IsLateParsed; } 109 110 // Pretty print this attribute. 111 void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const; 112 113 /// \brief By default, attributes cannot be duplicated when being merged; 114 /// however, an attribute can override this. Returns true if the attribute 115 /// can be duplicated when merging. 116 bool duplicatesAllowed() const { return DuplicatesAllowed; } 117 }; 118 119 class StmtAttr : public Attr { 120 protected: 121 StmtAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, 122 bool IsLateParsed, bool DuplicatesAllowed) 123 : Attr(AK, R, SpellingListIndex, IsLateParsed, DuplicatesAllowed) {} 124 125 public: 126 static bool classof(const Attr *A) { 127 return A->getKind() >= attr::FirstStmtAttr && 128 A->getKind() <= attr::LastStmtAttr; 129 } 130 }; 131 132 class InheritableAttr : public Attr { 133 protected: 134 InheritableAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, 135 bool IsLateParsed, bool DuplicatesAllowed) 136 : Attr(AK, R, SpellingListIndex, IsLateParsed, DuplicatesAllowed) {} 137 138 public: 139 void setInherited(bool I) { Inherited = I; } 140 141 // Implement isa/cast/dyncast/etc. 142 static bool classof(const Attr *A) { 143 return A->getKind() >= attr::FirstInheritableAttr && 144 A->getKind() <= attr::LastInheritableAttr; 145 } 146 }; 147 148 class InheritableParamAttr : public InheritableAttr { 149 protected: 150 InheritableParamAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, 151 bool IsLateParsed, bool DuplicatesAllowed) 152 : InheritableAttr(AK, R, SpellingListIndex, IsLateParsed, 153 DuplicatesAllowed) {} 154 155 public: 156 // Implement isa/cast/dyncast/etc. 157 static bool classof(const Attr *A) { 158 return A->getKind() >= attr::FirstInheritableParamAttr && 159 A->getKind() <= attr::LastInheritableParamAttr; 160 } 161 }; 162 163 /// A parameter attribute which changes the argument-passing ABI rule 164 /// for the parameter. 165 class ParameterABIAttr : public InheritableParamAttr { 166 protected: 167 ParameterABIAttr(attr::Kind AK, SourceRange R, 168 unsigned SpellingListIndex, bool IsLateParsed, 169 bool DuplicatesAllowed) 170 : InheritableParamAttr(AK, R, SpellingListIndex, IsLateParsed, 171 DuplicatesAllowed) {} 172 173 public: 174 ParameterABI getABI() const { 175 switch (getKind()) { 176 case attr::SwiftContext: 177 return ParameterABI::SwiftContext; 178 case attr::SwiftErrorResult: 179 return ParameterABI::SwiftErrorResult; 180 case attr::SwiftIndirectResult: 181 return ParameterABI::SwiftIndirectResult; 182 default: 183 llvm_unreachable("bad parameter ABI attribute kind"); 184 } 185 } 186 187 static bool classof(const Attr *A) { 188 return A->getKind() >= attr::FirstParameterABIAttr && 189 A->getKind() <= attr::LastParameterABIAttr; 190 } 191 }; 192 193 #include "clang/AST/Attrs.inc" 194 195 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 196 const Attr *At) { 197 DB.AddTaggedVal(reinterpret_cast<intptr_t>(At), 198 DiagnosticsEngine::ak_attr); 199 return DB; 200 } 201 202 inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, 203 const Attr *At) { 204 PD.AddTaggedVal(reinterpret_cast<intptr_t>(At), 205 DiagnosticsEngine::ak_attr); 206 return PD; 207 } 208 } // end namespace clang 209 210 #endif 211