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/AttributeCommonInfo.h" 23 #include "clang/Basic/LLVM.h" 24 #include "clang/Basic/OpenMPKinds.h" 25 #include "clang/Basic/Sanitizers.h" 26 #include "clang/Basic/SourceLocation.h" 27 #include "llvm/ADT/StringSwitch.h" 28 #include "llvm/Support/ErrorHandling.h" 29 #include "llvm/Support/VersionTuple.h" 30 #include "llvm/Support/raw_ostream.h" 31 #include <algorithm> 32 #include <cassert> 33 34 namespace clang { 35 class ASTContext; 36 class AttributeCommonInfo; 37 class IdentifierInfo; 38 class ObjCInterfaceDecl; 39 class Expr; 40 class QualType; 41 class FunctionDecl; 42 class TypeSourceInfo; 43 44 /// Attr - This represents one attribute. 45 class Attr : public AttributeCommonInfo { 46 private: 47 unsigned AttrKind : 16; 48 49 protected: 50 /// An index into the spelling list of an 51 /// attribute defined in Attr.td file. 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(ASTContext &Context, const AttributeCommonInfo &CommonInfo, 79 attr::Kind AK, bool IsLateParsed) 80 : AttributeCommonInfo(CommonInfo), AttrKind(AK), Inherited(false), 81 IsPackExpansion(false), Implicit(false), IsLateParsed(IsLateParsed), 82 InheritEvenIfAlreadyPresent(false) {} 83 84 public: 85 attr::Kind getKind() const { return static_cast<attr::Kind>(AttrKind); } 86 87 unsigned getSpellingListIndex() const { 88 return getAttributeSpellingListIndex(); 89 } 90 const char *getSpelling() const; 91 92 SourceLocation getLocation() const { return getRange().getBegin(); } 93 94 bool isInherited() const { return Inherited; } 95 96 /// Returns true if the attribute has been implicitly created instead 97 /// of explicitly written by the user. 98 bool isImplicit() const { return Implicit; } 99 void setImplicit(bool I) { Implicit = I; } 100 101 void setPackExpansion(bool PE) { IsPackExpansion = PE; } 102 bool isPackExpansion() const { return IsPackExpansion; } 103 104 // Clone this attribute. 105 Attr *clone(ASTContext &C) const; 106 107 bool isLateParsed() const { return IsLateParsed; } 108 109 // Pretty print this attribute. 110 void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const; 111 }; 112 113 class TypeAttr : public Attr { 114 protected: 115 TypeAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo, 116 attr::Kind AK, bool IsLateParsed) 117 : Attr(Context, CommonInfo, AK, IsLateParsed) {} 118 119 public: 120 static bool classof(const Attr *A) { 121 return A->getKind() >= attr::FirstTypeAttr && 122 A->getKind() <= attr::LastTypeAttr; 123 } 124 }; 125 126 class StmtAttr : public Attr { 127 protected: 128 StmtAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo, 129 attr::Kind AK, bool IsLateParsed) 130 : Attr(Context, CommonInfo, AK, IsLateParsed) {} 131 132 public: 133 static bool classof(const Attr *A) { 134 return A->getKind() >= attr::FirstStmtAttr && 135 A->getKind() <= attr::LastStmtAttr; 136 } 137 }; 138 139 class InheritableAttr : public Attr { 140 protected: 141 InheritableAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo, 142 attr::Kind AK, bool IsLateParsed, 143 bool InheritEvenIfAlreadyPresent) 144 : Attr(Context, CommonInfo, AK, IsLateParsed) { 145 this->InheritEvenIfAlreadyPresent = InheritEvenIfAlreadyPresent; 146 } 147 148 public: 149 void setInherited(bool I) { Inherited = I; } 150 151 /// Should this attribute be inherited from a prior declaration even if it's 152 /// explicitly provided in the current declaration? 153 bool shouldInheritEvenIfAlreadyPresent() const { 154 return InheritEvenIfAlreadyPresent; 155 } 156 157 // Implement isa/cast/dyncast/etc. 158 static bool classof(const Attr *A) { 159 return A->getKind() >= attr::FirstInheritableAttr && 160 A->getKind() <= attr::LastInheritableAttr; 161 } 162 }; 163 164 class InheritableParamAttr : public InheritableAttr { 165 protected: 166 InheritableParamAttr(ASTContext &Context, 167 const AttributeCommonInfo &CommonInfo, attr::Kind AK, 168 bool IsLateParsed, bool InheritEvenIfAlreadyPresent) 169 : InheritableAttr(Context, CommonInfo, AK, IsLateParsed, 170 InheritEvenIfAlreadyPresent) {} 171 172 public: 173 // Implement isa/cast/dyncast/etc. 174 static bool classof(const Attr *A) { 175 return A->getKind() >= attr::FirstInheritableParamAttr && 176 A->getKind() <= attr::LastInheritableParamAttr; 177 } 178 }; 179 180 /// A parameter attribute which changes the argument-passing ABI rule 181 /// for the parameter. 182 class ParameterABIAttr : public InheritableParamAttr { 183 protected: 184 ParameterABIAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo, 185 attr::Kind AK, bool IsLateParsed, 186 bool InheritEvenIfAlreadyPresent) 187 : InheritableParamAttr(Context, CommonInfo, AK, IsLateParsed, 188 InheritEvenIfAlreadyPresent) {} 189 190 public: 191 ParameterABI getABI() const { 192 switch (getKind()) { 193 case attr::SwiftContext: 194 return ParameterABI::SwiftContext; 195 case attr::SwiftErrorResult: 196 return ParameterABI::SwiftErrorResult; 197 case attr::SwiftIndirectResult: 198 return ParameterABI::SwiftIndirectResult; 199 default: 200 llvm_unreachable("bad parameter ABI attribute kind"); 201 } 202 } 203 204 static bool classof(const Attr *A) { 205 return A->getKind() >= attr::FirstParameterABIAttr && 206 A->getKind() <= attr::LastParameterABIAttr; 207 } 208 }; 209 210 /// A single parameter index whose accessors require each use to make explicit 211 /// the parameter index encoding needed. 212 class ParamIdx { 213 // Idx is exposed only via accessors that specify specific encodings. 214 unsigned Idx : 30; 215 unsigned HasThis : 1; 216 unsigned IsValid : 1; 217 218 void assertComparable(const ParamIdx &I) const { 219 assert(isValid() && I.isValid() && 220 "ParamIdx must be valid to be compared"); 221 // It's possible to compare indices from separate functions, but so far 222 // it's not proven useful. Moreover, it might be confusing because a 223 // comparison on the results of getASTIndex might be inconsistent with a 224 // comparison on the ParamIdx objects themselves. 225 assert(HasThis == I.HasThis && 226 "ParamIdx must be for the same function to be compared"); 227 } 228 229 public: 230 /// Construct an invalid parameter index (\c isValid returns false and 231 /// accessors fail an assert). 232 ParamIdx() : Idx(0), HasThis(false), IsValid(false) {} 233 234 /// \param Idx is the parameter index as it is normally specified in 235 /// attributes in the source: one-origin including any C++ implicit this 236 /// parameter. 237 /// 238 /// \param D is the declaration containing the parameters. It is used to 239 /// determine if there is a C++ implicit this parameter. 240 ParamIdx(unsigned Idx, const Decl *D) 241 : Idx(Idx), HasThis(false), IsValid(true) { 242 assert(Idx >= 1 && "Idx must be one-origin"); 243 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 244 HasThis = FD->isCXXInstanceMember(); 245 } 246 247 /// A type into which \c ParamIdx can be serialized. 248 /// 249 /// A static assertion that it's of the correct size follows the \c ParamIdx 250 /// class definition. 251 typedef uint32_t SerialType; 252 253 /// Produce a representation that can later be passed to \c deserialize to 254 /// construct an equivalent \c ParamIdx. 255 SerialType serialize() const { 256 return *reinterpret_cast<const SerialType *>(this); 257 } 258 259 /// Construct from a result from \c serialize. 260 static ParamIdx deserialize(SerialType S) { 261 ParamIdx P(*reinterpret_cast<ParamIdx *>(&S)); 262 assert((!P.IsValid || P.Idx >= 1) && "valid Idx must be one-origin"); 263 return P; 264 } 265 266 /// Is this parameter index valid? 267 bool isValid() const { return IsValid; } 268 269 /// Get the parameter index as it would normally be encoded for attributes at 270 /// the source level of representation: one-origin including any C++ implicit 271 /// this parameter. 272 /// 273 /// This encoding thus makes sense for diagnostics, pretty printing, and 274 /// constructing new attributes from a source-like specification. 275 unsigned getSourceIndex() const { 276 assert(isValid() && "ParamIdx must be valid"); 277 return Idx; 278 } 279 280 /// Get the parameter index as it would normally be encoded at the AST level 281 /// of representation: zero-origin not including any C++ implicit this 282 /// parameter. 283 /// 284 /// This is the encoding primarily used in Sema. However, in diagnostics, 285 /// Sema uses \c getSourceIndex instead. 286 unsigned getASTIndex() const { 287 assert(isValid() && "ParamIdx must be valid"); 288 assert(Idx >= 1 + HasThis && 289 "stored index must be base-1 and not specify C++ implicit this"); 290 return Idx - 1 - HasThis; 291 } 292 293 /// Get the parameter index as it would normally be encoded at the LLVM level 294 /// of representation: zero-origin including any C++ implicit this parameter. 295 /// 296 /// This is the encoding primarily used in CodeGen. 297 unsigned getLLVMIndex() const { 298 assert(isValid() && "ParamIdx must be valid"); 299 assert(Idx >= 1 && "stored index must be base-1"); 300 return Idx - 1; 301 } 302 303 bool operator==(const ParamIdx &I) const { 304 assertComparable(I); 305 return Idx == I.Idx; 306 } 307 bool operator!=(const ParamIdx &I) const { 308 assertComparable(I); 309 return Idx != I.Idx; 310 } 311 bool operator<(const ParamIdx &I) const { 312 assertComparable(I); 313 return Idx < I.Idx; 314 } 315 bool operator>(const ParamIdx &I) const { 316 assertComparable(I); 317 return Idx > I.Idx; 318 } 319 bool operator<=(const ParamIdx &I) const { 320 assertComparable(I); 321 return Idx <= I.Idx; 322 } 323 bool operator>=(const ParamIdx &I) const { 324 assertComparable(I); 325 return Idx >= I.Idx; 326 } 327 }; 328 329 static_assert(sizeof(ParamIdx) == sizeof(ParamIdx::SerialType), 330 "ParamIdx does not fit its serialization type"); 331 332 /// Contains information gathered from parsing the contents of TargetAttr. 333 struct ParsedTargetAttr { 334 std::vector<std::string> Features; 335 StringRef Architecture; 336 StringRef BranchProtection; 337 bool DuplicateArchitecture = false; 338 bool operator ==(const ParsedTargetAttr &Other) const { 339 return DuplicateArchitecture == Other.DuplicateArchitecture && 340 Architecture == Other.Architecture && Features == Other.Features; 341 } 342 }; 343 344 #include "clang/AST/Attrs.inc" 345 346 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 347 const Attr *At) { 348 DB.AddTaggedVal(reinterpret_cast<intptr_t>(At), 349 DiagnosticsEngine::ak_attr); 350 return DB; 351 } 352 353 inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, 354 const Attr *At) { 355 PD.AddTaggedVal(reinterpret_cast<intptr_t>(At), 356 DiagnosticsEngine::ak_attr); 357 return PD; 358 } 359 } // end namespace clang 360 361 #endif 362