Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //======- AttributeCommonInfo.h - Base info about 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 AttributeCommonInfo type, which is the base for a
0010 // ParsedAttr and is used by Attr as a way to share info between the two.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
0015 #define LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
0016 
0017 #include "clang/Basic/SourceLocation.h"
0018 #include "clang/Basic/TokenKinds.h"
0019 
0020 namespace clang {
0021 
0022 class ASTRecordWriter;
0023 class IdentifierInfo;
0024 
0025 class AttributeCommonInfo {
0026 public:
0027   /// The style used to specify an attribute.
0028   enum Syntax {
0029     /// __attribute__((...))
0030     AS_GNU = 1,
0031 
0032     /// [[...]]
0033     AS_CXX11,
0034 
0035     /// [[...]]
0036     AS_C23,
0037 
0038     /// __declspec(...)
0039     AS_Declspec,
0040 
0041     /// [uuid("...")] class Foo
0042     AS_Microsoft,
0043 
0044     /// __ptr16, alignas(...), etc.
0045     AS_Keyword,
0046 
0047     /// #pragma ...
0048     AS_Pragma,
0049 
0050     // Note TableGen depends on the order above.  Do not add or change the order
0051     // without adding related code to TableGen/ClangAttrEmitter.cpp.
0052     /// Context-sensitive version of a keyword attribute.
0053     AS_ContextSensitiveKeyword,
0054 
0055     /// <vardecl> : <annotation>
0056     AS_HLSLAnnotation,
0057 
0058     /// The attibute has no source code manifestation and is only created
0059     /// implicitly.
0060     AS_Implicit
0061   };
0062   enum Kind {
0063 #define PARSED_ATTR(NAME) AT_##NAME,
0064 #include "clang/Basic/AttrParsedAttrList.inc"
0065 #undef PARSED_ATTR
0066     NoSemaHandlerAttribute,
0067     IgnoredAttribute,
0068     UnknownAttribute,
0069   };
0070   enum class Scope { NONE, CLANG, GNU, MSVC, OMP, HLSL, GSL, RISCV };
0071   enum class AttrArgsInfo {
0072     None,
0073     Optional,
0074     Required,
0075   };
0076 
0077 private:
0078   const IdentifierInfo *AttrName = nullptr;
0079   const IdentifierInfo *ScopeName = nullptr;
0080   SourceRange AttrRange;
0081   const SourceLocation ScopeLoc;
0082   // Corresponds to the Kind enum.
0083   LLVM_PREFERRED_TYPE(Kind)
0084   unsigned AttrKind : 16;
0085   /// Corresponds to the Syntax enum.
0086   LLVM_PREFERRED_TYPE(Syntax)
0087   unsigned SyntaxUsed : 4;
0088   LLVM_PREFERRED_TYPE(bool)
0089   unsigned SpellingIndex : 4;
0090   LLVM_PREFERRED_TYPE(bool)
0091   unsigned IsAlignas : 1;
0092   LLVM_PREFERRED_TYPE(bool)
0093   unsigned IsRegularKeywordAttribute : 1;
0094 
0095 protected:
0096   static constexpr unsigned SpellingNotCalculated = 0xf;
0097 
0098 public:
0099   /// Combines information about the source-code form of an attribute,
0100   /// including its syntax and spelling.
0101   class Form {
0102   public:
0103     constexpr Form(Syntax SyntaxUsed, unsigned SpellingIndex, bool IsAlignas,
0104                    bool IsRegularKeywordAttribute)
0105         : SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingIndex),
0106           IsAlignas(IsAlignas),
0107           IsRegularKeywordAttribute(IsRegularKeywordAttribute) {}
0108     constexpr Form(tok::TokenKind Tok)
0109         : SyntaxUsed(AS_Keyword), SpellingIndex(SpellingNotCalculated),
0110           IsAlignas(Tok == tok::kw_alignas),
0111           IsRegularKeywordAttribute(tok::isRegularKeywordAttribute(Tok)) {}
0112 
0113     Syntax getSyntax() const { return Syntax(SyntaxUsed); }
0114     unsigned getSpellingIndex() const { return SpellingIndex; }
0115     bool isAlignas() const { return IsAlignas; }
0116     bool isRegularKeywordAttribute() const { return IsRegularKeywordAttribute; }
0117 
0118     static Form GNU() { return AS_GNU; }
0119     static Form CXX11() { return AS_CXX11; }
0120     static Form C23() { return AS_C23; }
0121     static Form Declspec() { return AS_Declspec; }
0122     static Form Microsoft() { return AS_Microsoft; }
0123     static Form Keyword(bool IsAlignas, bool IsRegularKeywordAttribute) {
0124       return Form(AS_Keyword, SpellingNotCalculated, IsAlignas,
0125                   IsRegularKeywordAttribute);
0126     }
0127     static Form Pragma() { return AS_Pragma; }
0128     static Form ContextSensitiveKeyword() { return AS_ContextSensitiveKeyword; }
0129     static Form HLSLAnnotation() { return AS_HLSLAnnotation; }
0130     static Form Implicit() { return AS_Implicit; }
0131 
0132   private:
0133     constexpr Form(Syntax SyntaxUsed)
0134         : SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingNotCalculated),
0135           IsAlignas(0), IsRegularKeywordAttribute(0) {}
0136 
0137     LLVM_PREFERRED_TYPE(Syntax)
0138     unsigned SyntaxUsed : 4;
0139     unsigned SpellingIndex : 4;
0140     LLVM_PREFERRED_TYPE(bool)
0141     unsigned IsAlignas : 1;
0142     LLVM_PREFERRED_TYPE(bool)
0143     unsigned IsRegularKeywordAttribute : 1;
0144   };
0145 
0146   AttributeCommonInfo(const IdentifierInfo *AttrName,
0147                       const IdentifierInfo *ScopeName, SourceRange AttrRange,
0148                       SourceLocation ScopeLoc, Kind AttrKind, Form FormUsed)
0149       : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange),
0150         ScopeLoc(ScopeLoc), AttrKind(AttrKind),
0151         SyntaxUsed(FormUsed.getSyntax()),
0152         SpellingIndex(FormUsed.getSpellingIndex()),
0153         IsAlignas(FormUsed.isAlignas()),
0154         IsRegularKeywordAttribute(FormUsed.isRegularKeywordAttribute()) {
0155     assert(SyntaxUsed >= AS_GNU && SyntaxUsed <= AS_Implicit &&
0156            "Invalid syntax!");
0157   }
0158 
0159   AttributeCommonInfo(const IdentifierInfo *AttrName,
0160                       const IdentifierInfo *ScopeName, SourceRange AttrRange,
0161                       SourceLocation ScopeLoc, Form FormUsed)
0162       : AttributeCommonInfo(
0163             AttrName, ScopeName, AttrRange, ScopeLoc,
0164             getParsedKind(AttrName, ScopeName, FormUsed.getSyntax()),
0165             FormUsed) {}
0166 
0167   AttributeCommonInfo(const IdentifierInfo *AttrName, SourceRange AttrRange,
0168                       Form FormUsed)
0169       : AttributeCommonInfo(AttrName, nullptr, AttrRange, SourceLocation(),
0170                             FormUsed) {}
0171 
0172   AttributeCommonInfo(SourceRange AttrRange, Kind K, Form FormUsed)
0173       : AttributeCommonInfo(nullptr, nullptr, AttrRange, SourceLocation(), K,
0174                             FormUsed) {}
0175 
0176   AttributeCommonInfo(AttributeCommonInfo &&) = default;
0177   AttributeCommonInfo(const AttributeCommonInfo &) = default;
0178 
0179   Kind getParsedKind() const { return Kind(AttrKind); }
0180   Syntax getSyntax() const { return Syntax(SyntaxUsed); }
0181   Form getForm() const {
0182     return Form(getSyntax(), SpellingIndex, IsAlignas,
0183                 IsRegularKeywordAttribute);
0184   }
0185   const IdentifierInfo *getAttrName() const { return AttrName; }
0186   void setAttrName(const IdentifierInfo *AttrNameII) { AttrName = AttrNameII; }
0187   SourceLocation getLoc() const { return AttrRange.getBegin(); }
0188   SourceRange getRange() const { return AttrRange; }
0189   void setRange(SourceRange R) { AttrRange = R; }
0190 
0191   bool hasScope() const { return ScopeName; }
0192   const IdentifierInfo *getScopeName() const { return ScopeName; }
0193   SourceLocation getScopeLoc() const { return ScopeLoc; }
0194 
0195   /// Gets the normalized full name, which consists of both scope and name and
0196   /// with surrounding underscores removed as appropriate (e.g.
0197   /// __gnu__::__attr__ will be normalized to gnu::attr).
0198   std::string getNormalizedFullName() const;
0199 
0200   bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
0201   bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; }
0202 
0203   bool isGNUScope() const;
0204   bool isClangScope() const;
0205 
0206   bool isCXX11Attribute() const { return SyntaxUsed == AS_CXX11 || IsAlignas; }
0207 
0208   bool isC23Attribute() const { return SyntaxUsed == AS_C23; }
0209 
0210   bool isAlignas() const {
0211     // FIXME: In the current state, the IsAlignas member variable is only true
0212     // with the C++  `alignas` keyword but not `_Alignas`. The following
0213     // expression works around the otherwise lost information so it will return
0214     // true for `alignas` or `_Alignas` while still returning false for things
0215     // like  `__attribute__((aligned))`.
0216     return (getParsedKind() == AT_Aligned && isKeywordAttribute());
0217   }
0218 
0219   /// The attribute is spelled [[]] in either C or C++ mode, including standard
0220   /// attributes spelled with a keyword, like alignas.
0221   bool isStandardAttributeSyntax() const {
0222     return isCXX11Attribute() || isC23Attribute();
0223   }
0224 
0225   bool isGNUAttribute() const { return SyntaxUsed == AS_GNU; }
0226 
0227   bool isKeywordAttribute() const {
0228     return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword;
0229   }
0230 
0231   bool isRegularKeywordAttribute() const { return IsRegularKeywordAttribute; }
0232 
0233   bool isContextSensitiveKeywordAttribute() const {
0234     return SyntaxUsed == AS_ContextSensitiveKeyword;
0235   }
0236 
0237   unsigned getAttributeSpellingListIndex() const {
0238     assert((isAttributeSpellingListCalculated() || AttrName) &&
0239            "Spelling cannot be found");
0240     return isAttributeSpellingListCalculated()
0241                ? SpellingIndex
0242                : calculateAttributeSpellingListIndex();
0243   }
0244   void setAttributeSpellingListIndex(unsigned V) { SpellingIndex = V; }
0245 
0246   static Kind getParsedKind(const IdentifierInfo *Name,
0247                             const IdentifierInfo *Scope, Syntax SyntaxUsed);
0248 
0249   static AttrArgsInfo getCXX11AttrArgsInfo(const IdentifierInfo *Name);
0250 
0251 private:
0252   /// Get an index into the attribute spelling list
0253   /// defined in Attr.td. This index is used by an attribute
0254   /// to pretty print itself.
0255   unsigned calculateAttributeSpellingListIndex() const;
0256 
0257   friend class clang::ASTRecordWriter;
0258   // Used exclusively by ASTDeclWriter to get the raw spelling list state.
0259   unsigned getAttributeSpellingListIndexRaw() const { return SpellingIndex; }
0260 
0261 protected:
0262   bool isAttributeSpellingListCalculated() const {
0263     return SpellingIndex != SpellingNotCalculated;
0264   }
0265 };
0266 
0267 inline bool doesKeywordAttributeTakeArgs(tok::TokenKind Kind) {
0268   switch (Kind) {
0269   default:
0270     return false;
0271 #define KEYWORD_ATTRIBUTE(NAME, HASARG, ...)                                   \
0272   case tok::kw_##NAME:                                                         \
0273     return HASARG;
0274 #include "clang/Basic/RegularKeywordAttrInfo.inc"
0275 #undef KEYWORD_ATTRIBUTE
0276   }
0277 }
0278 
0279 } // namespace clang
0280 
0281 #endif // LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H