Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:29

0001 //===--- Attr.h - Classes for representing attributes ----------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 //  This file defines the Attr interface and subclasses.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_CLANG_AST_ATTR_H
0014 #define LLVM_CLANG_AST_ATTR_H
0015 
0016 #include "clang/AST/ASTFwd.h"
0017 #include "clang/AST/AttrIterator.h"
0018 #include "clang/AST/Decl.h"
0019 #include "clang/AST/Type.h"
0020 #include "clang/Basic/AttrKinds.h"
0021 #include "clang/Basic/AttributeCommonInfo.h"
0022 #include "clang/Basic/LLVM.h"
0023 #include "clang/Basic/LangOptions.h"
0024 #include "clang/Basic/OpenMPKinds.h"
0025 #include "clang/Basic/Sanitizers.h"
0026 #include "clang/Basic/SourceLocation.h"
0027 #include "clang/Support/Compiler.h"
0028 #include "llvm/Frontend/HLSL/HLSLResource.h"
0029 #include "llvm/Support/CodeGen.h"
0030 #include "llvm/Support/ErrorHandling.h"
0031 #include "llvm/Support/VersionTuple.h"
0032 #include "llvm/Support/raw_ostream.h"
0033 #include <algorithm>
0034 #include <cassert>
0035 
0036 namespace clang {
0037 class ASTContext;
0038 class AttributeCommonInfo;
0039 class FunctionDecl;
0040 class OMPTraitInfo;
0041 
0042 /// Attr - This represents one attribute.
0043 class Attr : public AttributeCommonInfo {
0044 private:
0045   LLVM_PREFERRED_TYPE(attr::Kind)
0046   unsigned AttrKind : 16;
0047 
0048 protected:
0049   /// An index into the spelling list of an
0050   /// attribute defined in Attr.td file.
0051   LLVM_PREFERRED_TYPE(bool)
0052   unsigned Inherited : 1;
0053   LLVM_PREFERRED_TYPE(bool)
0054   unsigned IsPackExpansion : 1;
0055   LLVM_PREFERRED_TYPE(bool)
0056   unsigned Implicit : 1;
0057   // FIXME: These are properties of the attribute kind, not state for this
0058   // instance of the attribute.
0059   LLVM_PREFERRED_TYPE(bool)
0060   unsigned IsLateParsed : 1;
0061   LLVM_PREFERRED_TYPE(bool)
0062   unsigned InheritEvenIfAlreadyPresent : 1;
0063 
0064   void *operator new(size_t bytes) noexcept {
0065     llvm_unreachable("Attrs cannot be allocated with regular 'new'.");
0066   }
0067   void operator delete(void *data) noexcept {
0068     llvm_unreachable("Attrs cannot be released with regular 'delete'.");
0069   }
0070 
0071 public:
0072   // Forward so that the regular new and delete do not hide global ones.
0073   void *operator new(size_t Bytes, ASTContext &C,
0074                      size_t Alignment = 8) noexcept {
0075     return ::operator new(Bytes, C, Alignment);
0076   }
0077   void operator delete(void *Ptr, ASTContext &C, size_t Alignment) noexcept {
0078     return ::operator delete(Ptr, C, Alignment);
0079   }
0080 
0081 protected:
0082   Attr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
0083        attr::Kind AK, bool IsLateParsed)
0084       : AttributeCommonInfo(CommonInfo), AttrKind(AK), Inherited(false),
0085         IsPackExpansion(false), Implicit(false), IsLateParsed(IsLateParsed),
0086         InheritEvenIfAlreadyPresent(false) {}
0087 
0088 public:
0089   attr::Kind getKind() const { return static_cast<attr::Kind>(AttrKind); }
0090 
0091   unsigned getSpellingListIndex() const {
0092     return getAttributeSpellingListIndex();
0093   }
0094   const char *getSpelling() const;
0095 
0096   SourceLocation getLocation() const { return getRange().getBegin(); }
0097 
0098   bool isInherited() const { return Inherited; }
0099 
0100   /// Returns true if the attribute has been implicitly created instead
0101   /// of explicitly written by the user.
0102   bool isImplicit() const { return Implicit; }
0103   void setImplicit(bool I) { Implicit = I; }
0104 
0105   void setPackExpansion(bool PE) { IsPackExpansion = PE; }
0106   bool isPackExpansion() const { return IsPackExpansion; }
0107 
0108   // Clone this attribute.
0109   Attr *clone(ASTContext &C) const;
0110 
0111   bool isLateParsed() const { return IsLateParsed; }
0112 
0113   // Pretty print this attribute.
0114   void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;
0115 
0116   static StringRef getDocumentation(attr::Kind);
0117 };
0118 
0119 class TypeAttr : public Attr {
0120 protected:
0121   TypeAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
0122            attr::Kind AK, bool IsLateParsed)
0123       : Attr(Context, CommonInfo, AK, IsLateParsed) {}
0124 
0125 public:
0126   static bool classof(const Attr *A) {
0127     return A->getKind() >= attr::FirstTypeAttr &&
0128            A->getKind() <= attr::LastTypeAttr;
0129   }
0130 };
0131 
0132 class StmtAttr : public Attr {
0133 protected:
0134   StmtAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
0135            attr::Kind AK, bool IsLateParsed)
0136       : Attr(Context, CommonInfo, AK, IsLateParsed) {}
0137 
0138 public:
0139   static bool classof(const Attr *A) {
0140     return A->getKind() >= attr::FirstStmtAttr &&
0141            A->getKind() <= attr::LastStmtAttr;
0142   }
0143 };
0144 
0145 class InheritableAttr : public Attr {
0146 protected:
0147   InheritableAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
0148                   attr::Kind AK, bool IsLateParsed,
0149                   bool InheritEvenIfAlreadyPresent)
0150       : Attr(Context, CommonInfo, AK, IsLateParsed) {
0151     this->InheritEvenIfAlreadyPresent = InheritEvenIfAlreadyPresent;
0152   }
0153 
0154 public:
0155   void setInherited(bool I) { Inherited = I; }
0156 
0157   /// Should this attribute be inherited from a prior declaration even if it's
0158   /// explicitly provided in the current declaration?
0159   bool shouldInheritEvenIfAlreadyPresent() const {
0160     return InheritEvenIfAlreadyPresent;
0161   }
0162 
0163   // Implement isa/cast/dyncast/etc.
0164   static bool classof(const Attr *A) {
0165     return A->getKind() >= attr::FirstInheritableAttr &&
0166            A->getKind() <= attr::LastInheritableAttr;
0167   }
0168 };
0169 
0170 class DeclOrStmtAttr : public InheritableAttr {
0171 protected:
0172   DeclOrStmtAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
0173                  attr::Kind AK, bool IsLateParsed,
0174                  bool InheritEvenIfAlreadyPresent)
0175       : InheritableAttr(Context, CommonInfo, AK, IsLateParsed,
0176                         InheritEvenIfAlreadyPresent) {}
0177 
0178 public:
0179   static bool classof(const Attr *A) {
0180     return A->getKind() >= attr::FirstDeclOrStmtAttr &&
0181            A->getKind() <= attr::LastDeclOrStmtAttr;
0182   }
0183 };
0184 
0185 class InheritableParamAttr : public InheritableAttr {
0186 protected:
0187   InheritableParamAttr(ASTContext &Context,
0188                        const AttributeCommonInfo &CommonInfo, attr::Kind AK,
0189                        bool IsLateParsed, bool InheritEvenIfAlreadyPresent)
0190       : InheritableAttr(Context, CommonInfo, AK, IsLateParsed,
0191                         InheritEvenIfAlreadyPresent) {}
0192 
0193 public:
0194   // Implement isa/cast/dyncast/etc.
0195   static bool classof(const Attr *A) {
0196     return A->getKind() >= attr::FirstInheritableParamAttr &&
0197            A->getKind() <= attr::LastInheritableParamAttr;
0198   }
0199 };
0200 
0201 class InheritableParamOrStmtAttr : public InheritableParamAttr {
0202 protected:
0203   InheritableParamOrStmtAttr(ASTContext &Context,
0204                              const AttributeCommonInfo &CommonInfo,
0205                              attr::Kind AK, bool IsLateParsed,
0206                              bool InheritEvenIfAlreadyPresent)
0207       : InheritableParamAttr(Context, CommonInfo, AK, IsLateParsed,
0208                              InheritEvenIfAlreadyPresent) {}
0209 
0210 public:
0211   // Implement isa/cast/dyncast/etc.
0212   static bool classof(const Attr *A) {
0213     return A->getKind() >= attr::FirstInheritableParamOrStmtAttr &&
0214            A->getKind() <= attr::LastInheritableParamOrStmtAttr;
0215   }
0216 };
0217 
0218 class HLSLAnnotationAttr : public InheritableAttr {
0219 protected:
0220   HLSLAnnotationAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
0221                      attr::Kind AK, bool IsLateParsed,
0222                      bool InheritEvenIfAlreadyPresent)
0223       : InheritableAttr(Context, CommonInfo, AK, IsLateParsed,
0224                         InheritEvenIfAlreadyPresent) {}
0225 
0226 public:
0227   // Implement isa/cast/dyncast/etc.
0228   static bool classof(const Attr *A) {
0229     return A->getKind() >= attr::FirstHLSLAnnotationAttr &&
0230            A->getKind() <= attr::LastHLSLAnnotationAttr;
0231   }
0232 };
0233 
0234 /// A parameter attribute which changes the argument-passing ABI rule
0235 /// for the parameter.
0236 class ParameterABIAttr : public InheritableParamAttr {
0237 protected:
0238   ParameterABIAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
0239                    attr::Kind AK, bool IsLateParsed,
0240                    bool InheritEvenIfAlreadyPresent)
0241       : InheritableParamAttr(Context, CommonInfo, AK, IsLateParsed,
0242                              InheritEvenIfAlreadyPresent) {}
0243 
0244 public:
0245   ParameterABI getABI() const;
0246 
0247   static bool classof(const Attr *A) {
0248     return A->getKind() >= attr::FirstParameterABIAttr &&
0249            A->getKind() <= attr::LastParameterABIAttr;
0250    }
0251 };
0252 
0253 /// A single parameter index whose accessors require each use to make explicit
0254 /// the parameter index encoding needed.
0255 class ParamIdx {
0256   // Idx is exposed only via accessors that specify specific encodings.
0257   unsigned Idx : 30;
0258   LLVM_PREFERRED_TYPE(bool)
0259   unsigned HasThis : 1;
0260   LLVM_PREFERRED_TYPE(bool)
0261   unsigned IsValid : 1;
0262 
0263   void assertComparable(const ParamIdx &I) const {
0264     assert(isValid() && I.isValid() &&
0265            "ParamIdx must be valid to be compared");
0266     // It's possible to compare indices from separate functions, but so far
0267     // it's not proven useful.  Moreover, it might be confusing because a
0268     // comparison on the results of getASTIndex might be inconsistent with a
0269     // comparison on the ParamIdx objects themselves.
0270     assert(HasThis == I.HasThis &&
0271            "ParamIdx must be for the same function to be compared");
0272   }
0273 
0274 public:
0275   /// Construct an invalid parameter index (\c isValid returns false and
0276   /// accessors fail an assert).
0277   ParamIdx() : Idx(0), HasThis(false), IsValid(false) {}
0278 
0279   /// \param Idx is the parameter index as it is normally specified in
0280   /// attributes in the source: one-origin including any C++ implicit this
0281   /// parameter.
0282   ///
0283   /// \param D is the declaration containing the parameters.  It is used to
0284   /// determine if there is a C++ implicit this parameter.
0285   ParamIdx(unsigned Idx, const Decl *D)
0286       : Idx(Idx), HasThis(false), IsValid(true) {
0287     assert(Idx >= 1 && "Idx must be one-origin");
0288     if (const auto *FD = dyn_cast<FunctionDecl>(D))
0289       HasThis = FD->isCXXInstanceMember();
0290   }
0291 
0292   /// A type into which \c ParamIdx can be serialized.
0293   ///
0294   /// A static assertion that it's of the correct size follows the \c ParamIdx
0295   /// class definition.
0296   typedef uint32_t SerialType;
0297 
0298   /// Produce a representation that can later be passed to \c deserialize to
0299   /// construct an equivalent \c ParamIdx.
0300   SerialType serialize() const {
0301     return *reinterpret_cast<const SerialType *>(this);
0302   }
0303 
0304   /// Construct from a result from \c serialize.
0305   static ParamIdx deserialize(SerialType S) {
0306     // Using this two-step static_cast via void * instead of reinterpret_cast
0307     // silences a -Wstrict-aliasing false positive from GCC7 and earlier.
0308     void *ParamIdxPtr = static_cast<void *>(&S);
0309     ParamIdx P(*static_cast<ParamIdx *>(ParamIdxPtr));
0310     assert((!P.IsValid || P.Idx >= 1) && "valid Idx must be one-origin");
0311     return P;
0312   }
0313 
0314   /// Is this parameter index valid?
0315   bool isValid() const { return IsValid; }
0316 
0317   /// Get the parameter index as it would normally be encoded for attributes at
0318   /// the source level of representation: one-origin including any C++ implicit
0319   /// this parameter.
0320   ///
0321   /// This encoding thus makes sense for diagnostics, pretty printing, and
0322   /// constructing new attributes from a source-like specification.
0323   unsigned getSourceIndex() const {
0324     assert(isValid() && "ParamIdx must be valid");
0325     return Idx;
0326   }
0327 
0328   /// Get the parameter index as it would normally be encoded at the AST level
0329   /// of representation: zero-origin not including any C++ implicit this
0330   /// parameter.
0331   ///
0332   /// This is the encoding primarily used in Sema.  However, in diagnostics,
0333   /// Sema uses \c getSourceIndex instead.
0334   unsigned getASTIndex() const {
0335     assert(isValid() && "ParamIdx must be valid");
0336     assert(Idx >= 1 + HasThis &&
0337            "stored index must be base-1 and not specify C++ implicit this");
0338     return Idx - 1 - HasThis;
0339   }
0340 
0341   /// Get the parameter index as it would normally be encoded at the LLVM level
0342   /// of representation: zero-origin including any C++ implicit this parameter.
0343   ///
0344   /// This is the encoding primarily used in CodeGen.
0345   unsigned getLLVMIndex() const {
0346     assert(isValid() && "ParamIdx must be valid");
0347     assert(Idx >= 1 && "stored index must be base-1");
0348     return Idx - 1;
0349   }
0350 
0351   bool operator==(const ParamIdx &I) const {
0352     assertComparable(I);
0353     return Idx == I.Idx;
0354   }
0355   bool operator!=(const ParamIdx &I) const {
0356     assertComparable(I);
0357     return Idx != I.Idx;
0358   }
0359   bool operator<(const ParamIdx &I) const {
0360     assertComparable(I);
0361     return Idx < I.Idx;
0362   }
0363   bool operator>(const ParamIdx &I) const {
0364     assertComparable(I);
0365     return Idx > I.Idx;
0366   }
0367   bool operator<=(const ParamIdx &I) const {
0368     assertComparable(I);
0369     return Idx <= I.Idx;
0370   }
0371   bool operator>=(const ParamIdx &I) const {
0372     assertComparable(I);
0373     return Idx >= I.Idx;
0374   }
0375 };
0376 
0377 static_assert(sizeof(ParamIdx) == sizeof(ParamIdx::SerialType),
0378               "ParamIdx does not fit its serialization type");
0379 
0380 #include "clang/AST/Attrs.inc" // IWYU pragma: export
0381 
0382 inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
0383                                              const Attr *At) {
0384   DB.AddTaggedVal(reinterpret_cast<uint64_t>(At), DiagnosticsEngine::ak_attr);
0385   return DB;
0386 }
0387 
0388 inline ParameterABI ParameterABIAttr::getABI() const {
0389   switch (getKind()) {
0390   case attr::SwiftContext:
0391     return ParameterABI::SwiftContext;
0392   case attr::SwiftAsyncContext:
0393     return ParameterABI::SwiftAsyncContext;
0394   case attr::SwiftErrorResult:
0395     return ParameterABI::SwiftErrorResult;
0396   case attr::SwiftIndirectResult:
0397     return ParameterABI::SwiftIndirectResult;
0398   case attr::HLSLParamModifier: {
0399     const auto *A = cast<HLSLParamModifierAttr>(this);
0400     if (A->isOut())
0401       return ParameterABI::HLSLOut;
0402     if (A->isInOut())
0403       return ParameterABI::HLSLInOut;
0404     return ParameterABI::Ordinary;
0405   }
0406   default:
0407     llvm_unreachable("bad parameter ABI attribute kind");
0408   }
0409 }
0410 }  // end namespace clang
0411 
0412 #endif