1 //===--- Attr.h - Classes for representing attributes ----------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines the Attr interface and subclasses. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_CLANG_AST_ATTR_H 14 #define LLVM_CLANG_AST_ATTR_H 15 16 #include "clang/AST/ASTContextAllocate.h" // For Attrs.inc 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 "llvm/ADT/StringSwitch.h" 27 #include "llvm/Support/ErrorHandling.h" 28 #include "llvm/Support/VersionTuple.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 // FIXME: These are properties of the attribute kind, not state for this 56 // instance of the attribute. 57 unsigned IsLateParsed : 1; 58 unsigned InheritEvenIfAlreadyPresent : 1; 59 60 void *operator new(size_t bytes) noexcept { 61 llvm_unreachable("Attrs cannot be allocated with regular 'new'."); 62 } 63 void operator delete(void *data) noexcept { 64 llvm_unreachable("Attrs cannot be released with regular 'delete'."); 65 } 66 67 public: 68 // Forward so that the regular new and delete do not hide global ones. 69 void *operator new(size_t Bytes, ASTContext &C, 70 size_t Alignment = 8) noexcept { 71 return ::operator new(Bytes, C, Alignment); 72 } 73 void operator delete(void *Ptr, ASTContext &C, size_t Alignment) noexcept { 74 return ::operator delete(Ptr, C, Alignment); 75 } 76 77 protected: 78 Attr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, 79 bool IsLateParsed) 80 : Range(R), AttrKind(AK), SpellingListIndex(SpellingListIndex), 81 Inherited(false), IsPackExpansion(false), Implicit(false), 82 IsLateParsed(IsLateParsed), InheritEvenIfAlreadyPresent(false) {} 83 84 public: 85 86 attr::Kind getKind() const { 87 return static_cast<attr::Kind>(AttrKind); 88 } 89 90 unsigned getSpellingListIndex() const { return SpellingListIndex; } 91 const char *getSpelling() const; 92 93 SourceLocation getLocation() const { return Range.getBegin(); } 94 SourceRange getRange() const { return Range; } 95 void setRange(SourceRange R) { Range = R; } 96 97 bool isInherited() const { return Inherited; } 98 99 /// Returns true if the attribute has been implicitly created instead 100 /// of explicitly written by the user. 101 bool isImplicit() const { return Implicit; } 102 void setImplicit(bool I) { Implicit = I; } 103 104 void setPackExpansion(bool PE) { IsPackExpansion = PE; } 105 bool isPackExpansion() const { return IsPackExpansion; } 106 107 // Clone this attribute. 108 Attr *clone(ASTContext &C) const; 109 110 bool isLateParsed() const { return IsLateParsed; } 111 112 // Pretty print this attribute. 113 void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const; 114 }; 115 116 class TypeAttr : public Attr { 117 protected: 118 TypeAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, 119 bool IsLateParsed) 120 : Attr(AK, R, SpellingListIndex, IsLateParsed) {} 121 122 public: 123 static bool classof(const Attr *A) { 124 return A->getKind() >= attr::FirstTypeAttr && 125 A->getKind() <= attr::LastTypeAttr; 126 } 127 }; 128 129 class StmtAttr : public Attr { 130 protected: 131 StmtAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, 132 bool IsLateParsed) 133 : Attr(AK, R, SpellingListIndex, IsLateParsed) {} 134 135 public: 136 static bool classof(const Attr *A) { 137 return A->getKind() >= attr::FirstStmtAttr && 138 A->getKind() <= attr::LastStmtAttr; 139 } 140 }; 141 142 class InheritableAttr : public Attr { 143 protected: 144 InheritableAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, 145 bool IsLateParsed, bool InheritEvenIfAlreadyPresent) 146 : Attr(AK, R, SpellingListIndex, IsLateParsed) { 147 this->InheritEvenIfAlreadyPresent = InheritEvenIfAlreadyPresent; 148 } 149 150 public: 151 void setInherited(bool I) { Inherited = I; } 152 153 /// Should this attribute be inherited from a prior declaration even if it's 154 /// explicitly provided in the current declaration? 155 bool shouldInheritEvenIfAlreadyPresent() const { 156 return InheritEvenIfAlreadyPresent; 157 } 158 159 // Implement isa/cast/dyncast/etc. 160 static bool classof(const Attr *A) { 161 return A->getKind() >= attr::FirstInheritableAttr && 162 A->getKind() <= attr::LastInheritableAttr; 163 } 164 }; 165 166 class InheritableParamAttr : public InheritableAttr { 167 protected: 168 InheritableParamAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, 169 bool IsLateParsed, bool InheritEvenIfAlreadyPresent) 170 : InheritableAttr(AK, R, SpellingListIndex, IsLateParsed, 171 InheritEvenIfAlreadyPresent) {} 172 173 public: 174 // Implement isa/cast/dyncast/etc. 175 static bool classof(const Attr *A) { 176 return A->getKind() >= attr::FirstInheritableParamAttr && 177 A->getKind() <= attr::LastInheritableParamAttr; 178 } 179 }; 180 181 /// A parameter attribute which changes the argument-passing ABI rule 182 /// for the parameter. 183 class ParameterABIAttr : public InheritableParamAttr { 184 protected: 185 ParameterABIAttr(attr::Kind AK, SourceRange R, 186 unsigned SpellingListIndex, bool IsLateParsed, 187 bool InheritEvenIfAlreadyPresent) 188 : InheritableParamAttr(AK, R, SpellingListIndex, IsLateParsed, 189 InheritEvenIfAlreadyPresent) {} 190 191 public: 192 ParameterABI getABI() const { 193 switch (getKind()) { 194 case attr::SwiftContext: 195 return ParameterABI::SwiftContext; 196 case attr::SwiftErrorResult: 197 return ParameterABI::SwiftErrorResult; 198 case attr::SwiftIndirectResult: 199 return ParameterABI::SwiftIndirectResult; 200 default: 201 llvm_unreachable("bad parameter ABI attribute kind"); 202 } 203 } 204 205 static bool classof(const Attr *A) { 206 return A->getKind() >= attr::FirstParameterABIAttr && 207 A->getKind() <= attr::LastParameterABIAttr; 208 } 209 }; 210 211 /// A single parameter index whose accessors require each use to make explicit 212 /// the parameter index encoding needed. 213 class ParamIdx { 214 // Idx is exposed only via accessors that specify specific encodings. 215 unsigned Idx : 30; 216 unsigned HasThis : 1; 217 unsigned IsValid : 1; 218 219 void assertComparable(const ParamIdx &I) const { 220 assert(isValid() && I.isValid() && 221 "ParamIdx must be valid to be compared"); 222 // It's possible to compare indices from separate functions, but so far 223 // it's not proven useful. Moreover, it might be confusing because a 224 // comparison on the results of getASTIndex might be inconsistent with a 225 // comparison on the ParamIdx objects themselves. 226 assert(HasThis == I.HasThis && 227 "ParamIdx must be for the same function to be compared"); 228 } 229 230 public: 231 /// Construct an invalid parameter index (\c isValid returns false and 232 /// accessors fail an assert). 233 ParamIdx() : Idx(0), HasThis(false), IsValid(false) {} 234 235 /// \param Idx is the parameter index as it is normally specified in 236 /// attributes in the source: one-origin including any C++ implicit this 237 /// parameter. 238 /// 239 /// \param D is the declaration containing the parameters. It is used to 240 /// determine if there is a C++ implicit this parameter. 241 ParamIdx(unsigned Idx, const Decl *D) 242 : Idx(Idx), HasThis(false), IsValid(true) { 243 assert(Idx >= 1 && "Idx must be one-origin"); 244 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 245 HasThis = FD->isCXXInstanceMember(); 246 } 247 248 /// A type into which \c ParamIdx can be serialized. 249 /// 250 /// A static assertion that it's of the correct size follows the \c ParamIdx 251 /// class definition. 252 typedef uint32_t SerialType; 253 254 /// Produce a representation that can later be passed to \c deserialize to 255 /// construct an equivalent \c ParamIdx. 256 SerialType serialize() const { 257 return *reinterpret_cast<const SerialType *>(this); 258 } 259 260 /// Construct from a result from \c serialize. 261 static ParamIdx deserialize(SerialType S) { 262 ParamIdx P(*reinterpret_cast<ParamIdx *>(&S)); 263 assert((!P.IsValid || P.Idx >= 1) && "valid Idx must be one-origin"); 264 return P; 265 } 266 267 /// Is this parameter index valid? 268 bool isValid() const { return IsValid; } 269 270 /// Get the parameter index as it would normally be encoded for attributes at 271 /// the source level of representation: one-origin including any C++ implicit 272 /// this parameter. 273 /// 274 /// This encoding thus makes sense for diagnostics, pretty printing, and 275 /// constructing new attributes from a source-like specification. 276 unsigned getSourceIndex() const { 277 assert(isValid() && "ParamIdx must be valid"); 278 return Idx; 279 } 280 281 /// Get the parameter index as it would normally be encoded at the AST level 282 /// of representation: zero-origin not including any C++ implicit this 283 /// parameter. 284 /// 285 /// This is the encoding primarily used in Sema. However, in diagnostics, 286 /// Sema uses \c getSourceIndex instead. 287 unsigned getASTIndex() const { 288 assert(isValid() && "ParamIdx must be valid"); 289 assert(Idx >= 1 + HasThis && 290 "stored index must be base-1 and not specify C++ implicit this"); 291 return Idx - 1 - HasThis; 292 } 293 294 /// Get the parameter index as it would normally be encoded at the LLVM level 295 /// of representation: zero-origin including any C++ implicit this parameter. 296 /// 297 /// This is the encoding primarily used in CodeGen. 298 unsigned getLLVMIndex() const { 299 assert(isValid() && "ParamIdx must be valid"); 300 assert(Idx >= 1 && "stored index must be base-1"); 301 return Idx - 1; 302 } 303 304 bool operator==(const ParamIdx &I) const { 305 assertComparable(I); 306 return Idx == I.Idx; 307 } 308 bool operator!=(const ParamIdx &I) const { 309 assertComparable(I); 310 return Idx != I.Idx; 311 } 312 bool operator<(const ParamIdx &I) const { 313 assertComparable(I); 314 return Idx < I.Idx; 315 } 316 bool operator>(const ParamIdx &I) const { 317 assertComparable(I); 318 return Idx > I.Idx; 319 } 320 bool operator<=(const ParamIdx &I) const { 321 assertComparable(I); 322 return Idx <= I.Idx; 323 } 324 bool operator>=(const ParamIdx &I) const { 325 assertComparable(I); 326 return Idx >= I.Idx; 327 } 328 }; 329 330 static_assert(sizeof(ParamIdx) == sizeof(ParamIdx::SerialType), 331 "ParamIdx does not fit its serialization type"); 332 333 #include "clang/AST/Attrs.inc" 334 335 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 336 const Attr *At) { 337 DB.AddTaggedVal(reinterpret_cast<intptr_t>(At), 338 DiagnosticsEngine::ak_attr); 339 return DB; 340 } 341 342 inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, 343 const Attr *At) { 344 PD.AddTaggedVal(reinterpret_cast<intptr_t>(At), 345 DiagnosticsEngine::ak_attr); 346 return PD; 347 } 348 } // end namespace clang 349 350 #endif 351