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