xref: /freebsd-src/contrib/llvm-project/clang/include/clang/Basic/AttributeCommonInfo.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1a7dea167SDimitry Andric //======- AttributeCommonInfo.h - Base info about Attributes-----*- C++ -*-===//
2a7dea167SDimitry Andric //
3a7dea167SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a7dea167SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5a7dea167SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a7dea167SDimitry Andric //
7a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
8a7dea167SDimitry Andric //
9a7dea167SDimitry Andric // This file defines the AttributeCommonInfo type, which is the base for a
10a7dea167SDimitry Andric // ParsedAttr and is used by Attr as a way to share info between the two.
11a7dea167SDimitry Andric //
12a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
13a7dea167SDimitry Andric 
14a7dea167SDimitry Andric #ifndef LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
15a7dea167SDimitry Andric #define LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
165f757f3fSDimitry Andric 
17a7dea167SDimitry Andric #include "clang/Basic/SourceLocation.h"
1806c3fb27SDimitry Andric #include "clang/Basic/TokenKinds.h"
19a7dea167SDimitry Andric 
20a7dea167SDimitry Andric namespace clang {
215f757f3fSDimitry Andric 
22a7dea167SDimitry Andric class ASTRecordWriter;
235f757f3fSDimitry Andric class IdentifierInfo;
24a7dea167SDimitry Andric 
25a7dea167SDimitry Andric class AttributeCommonInfo {
26a7dea167SDimitry Andric public:
27a7dea167SDimitry Andric   /// The style used to specify an attribute.
28a7dea167SDimitry Andric   enum Syntax {
29a7dea167SDimitry Andric     /// __attribute__((...))
3006c3fb27SDimitry Andric     AS_GNU = 1,
31a7dea167SDimitry Andric 
32a7dea167SDimitry Andric     /// [[...]]
33a7dea167SDimitry Andric     AS_CXX11,
34a7dea167SDimitry Andric 
35a7dea167SDimitry Andric     /// [[...]]
365f757f3fSDimitry Andric     AS_C23,
37a7dea167SDimitry Andric 
38a7dea167SDimitry Andric     /// __declspec(...)
39a7dea167SDimitry Andric     AS_Declspec,
40a7dea167SDimitry Andric 
41a7dea167SDimitry Andric     /// [uuid("...")] class Foo
42a7dea167SDimitry Andric     AS_Microsoft,
43a7dea167SDimitry Andric 
44a7dea167SDimitry Andric     /// __ptr16, alignas(...), etc.
45a7dea167SDimitry Andric     AS_Keyword,
46a7dea167SDimitry Andric 
47a7dea167SDimitry Andric     /// #pragma ...
48a7dea167SDimitry Andric     AS_Pragma,
49a7dea167SDimitry Andric 
50a7dea167SDimitry Andric     // Note TableGen depends on the order above.  Do not add or change the order
51a7dea167SDimitry Andric     // without adding related code to TableGen/ClangAttrEmitter.cpp.
52a7dea167SDimitry Andric     /// Context-sensitive version of a keyword attribute.
53a7dea167SDimitry Andric     AS_ContextSensitiveKeyword,
5481ad6265SDimitry Andric 
55*0fca6ea1SDimitry Andric     /// <vardecl> : <annotation>
56*0fca6ea1SDimitry Andric     AS_HLSLAnnotation,
5706c3fb27SDimitry Andric 
5806c3fb27SDimitry Andric     /// The attibute has no source code manifestation and is only created
5906c3fb27SDimitry Andric     /// implicitly.
6006c3fb27SDimitry Andric     AS_Implicit
61a7dea167SDimitry Andric   };
62a7dea167SDimitry Andric   enum Kind {
63a7dea167SDimitry Andric #define PARSED_ATTR(NAME) AT_##NAME,
64a7dea167SDimitry Andric #include "clang/Sema/AttrParsedAttrList.inc"
65a7dea167SDimitry Andric #undef PARSED_ATTR
66a7dea167SDimitry Andric     NoSemaHandlerAttribute,
67a7dea167SDimitry Andric     IgnoredAttribute,
68a7dea167SDimitry Andric     UnknownAttribute,
69a7dea167SDimitry Andric   };
70a7dea167SDimitry Andric 
71a7dea167SDimitry Andric private:
72a7dea167SDimitry Andric   const IdentifierInfo *AttrName = nullptr;
73a7dea167SDimitry Andric   const IdentifierInfo *ScopeName = nullptr;
74a7dea167SDimitry Andric   SourceRange AttrRange;
75a7dea167SDimitry Andric   const SourceLocation ScopeLoc;
76a7dea167SDimitry Andric   // Corresponds to the Kind enum.
775f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(Kind)
78a7dea167SDimitry Andric   unsigned AttrKind : 16;
79a7dea167SDimitry Andric   /// Corresponds to the Syntax enum.
805f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(Syntax)
8181ad6265SDimitry Andric   unsigned SyntaxUsed : 4;
825f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
83a7dea167SDimitry Andric   unsigned SpellingIndex : 4;
845f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
8506c3fb27SDimitry Andric   unsigned IsAlignas : 1;
865f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
8706c3fb27SDimitry Andric   unsigned IsRegularKeywordAttribute : 1;
88a7dea167SDimitry Andric 
89a7dea167SDimitry Andric protected:
90a7dea167SDimitry Andric   static constexpr unsigned SpellingNotCalculated = 0xf;
91a7dea167SDimitry Andric 
92a7dea167SDimitry Andric public:
9306c3fb27SDimitry Andric   /// Combines information about the source-code form of an attribute,
9406c3fb27SDimitry Andric   /// including its syntax and spelling.
9506c3fb27SDimitry Andric   class Form {
9606c3fb27SDimitry Andric   public:
9706c3fb27SDimitry Andric     constexpr Form(Syntax SyntaxUsed, unsigned SpellingIndex, bool IsAlignas,
9806c3fb27SDimitry Andric                    bool IsRegularKeywordAttribute)
9906c3fb27SDimitry Andric         : SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingIndex),
10006c3fb27SDimitry Andric           IsAlignas(IsAlignas),
10106c3fb27SDimitry Andric           IsRegularKeywordAttribute(IsRegularKeywordAttribute) {}
10206c3fb27SDimitry Andric     constexpr Form(tok::TokenKind Tok)
10306c3fb27SDimitry Andric         : SyntaxUsed(AS_Keyword), SpellingIndex(SpellingNotCalculated),
10406c3fb27SDimitry Andric           IsAlignas(Tok == tok::kw_alignas),
10506c3fb27SDimitry Andric           IsRegularKeywordAttribute(tok::isRegularKeywordAttribute(Tok)) {}
106a7dea167SDimitry Andric 
10706c3fb27SDimitry Andric     Syntax getSyntax() const { return Syntax(SyntaxUsed); }
10806c3fb27SDimitry Andric     unsigned getSpellingIndex() const { return SpellingIndex; }
10906c3fb27SDimitry Andric     bool isAlignas() const { return IsAlignas; }
11006c3fb27SDimitry Andric     bool isRegularKeywordAttribute() const { return IsRegularKeywordAttribute; }
11106c3fb27SDimitry Andric 
11206c3fb27SDimitry Andric     static Form GNU() { return AS_GNU; }
11306c3fb27SDimitry Andric     static Form CXX11() { return AS_CXX11; }
1145f757f3fSDimitry Andric     static Form C23() { return AS_C23; }
11506c3fb27SDimitry Andric     static Form Declspec() { return AS_Declspec; }
11606c3fb27SDimitry Andric     static Form Microsoft() { return AS_Microsoft; }
11706c3fb27SDimitry Andric     static Form Keyword(bool IsAlignas, bool IsRegularKeywordAttribute) {
11806c3fb27SDimitry Andric       return Form(AS_Keyword, SpellingNotCalculated, IsAlignas,
11906c3fb27SDimitry Andric                   IsRegularKeywordAttribute);
12006c3fb27SDimitry Andric     }
12106c3fb27SDimitry Andric     static Form Pragma() { return AS_Pragma; }
12206c3fb27SDimitry Andric     static Form ContextSensitiveKeyword() { return AS_ContextSensitiveKeyword; }
123*0fca6ea1SDimitry Andric     static Form HLSLAnnotation() { return AS_HLSLAnnotation; }
12406c3fb27SDimitry Andric     static Form Implicit() { return AS_Implicit; }
12506c3fb27SDimitry Andric 
12606c3fb27SDimitry Andric   private:
12706c3fb27SDimitry Andric     constexpr Form(Syntax SyntaxUsed)
12806c3fb27SDimitry Andric         : SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingNotCalculated),
12906c3fb27SDimitry Andric           IsAlignas(0), IsRegularKeywordAttribute(0) {}
13006c3fb27SDimitry Andric 
1315f757f3fSDimitry Andric     LLVM_PREFERRED_TYPE(Syntax)
13206c3fb27SDimitry Andric     unsigned SyntaxUsed : 4;
13306c3fb27SDimitry Andric     unsigned SpellingIndex : 4;
1345f757f3fSDimitry Andric     LLVM_PREFERRED_TYPE(bool)
13506c3fb27SDimitry Andric     unsigned IsAlignas : 1;
1365f757f3fSDimitry Andric     LLVM_PREFERRED_TYPE(bool)
13706c3fb27SDimitry Andric     unsigned IsRegularKeywordAttribute : 1;
13806c3fb27SDimitry Andric   };
139a7dea167SDimitry Andric 
140a7dea167SDimitry Andric   AttributeCommonInfo(const IdentifierInfo *AttrName,
141a7dea167SDimitry Andric                       const IdentifierInfo *ScopeName, SourceRange AttrRange,
14206c3fb27SDimitry Andric                       SourceLocation ScopeLoc, Kind AttrKind, Form FormUsed)
143a7dea167SDimitry Andric       : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange),
14406c3fb27SDimitry Andric         ScopeLoc(ScopeLoc), AttrKind(AttrKind),
14506c3fb27SDimitry Andric         SyntaxUsed(FormUsed.getSyntax()),
14606c3fb27SDimitry Andric         SpellingIndex(FormUsed.getSpellingIndex()),
14706c3fb27SDimitry Andric         IsAlignas(FormUsed.isAlignas()),
14806c3fb27SDimitry Andric         IsRegularKeywordAttribute(FormUsed.isRegularKeywordAttribute()) {
14906c3fb27SDimitry Andric     assert(SyntaxUsed >= AS_GNU && SyntaxUsed <= AS_Implicit &&
15006c3fb27SDimitry Andric            "Invalid syntax!");
15106c3fb27SDimitry Andric   }
152a7dea167SDimitry Andric 
153a7dea167SDimitry Andric   AttributeCommonInfo(const IdentifierInfo *AttrName,
154a7dea167SDimitry Andric                       const IdentifierInfo *ScopeName, SourceRange AttrRange,
15506c3fb27SDimitry Andric                       SourceLocation ScopeLoc, Form FormUsed)
15606c3fb27SDimitry Andric       : AttributeCommonInfo(
15706c3fb27SDimitry Andric             AttrName, ScopeName, AttrRange, ScopeLoc,
15806c3fb27SDimitry Andric             getParsedKind(AttrName, ScopeName, FormUsed.getSyntax()),
15906c3fb27SDimitry Andric             FormUsed) {}
160a7dea167SDimitry Andric 
161a7dea167SDimitry Andric   AttributeCommonInfo(const IdentifierInfo *AttrName, SourceRange AttrRange,
16206c3fb27SDimitry Andric                       Form FormUsed)
16306c3fb27SDimitry Andric       : AttributeCommonInfo(AttrName, nullptr, AttrRange, SourceLocation(),
16406c3fb27SDimitry Andric                             FormUsed) {}
165a7dea167SDimitry Andric 
16606c3fb27SDimitry Andric   AttributeCommonInfo(SourceRange AttrRange, Kind K, Form FormUsed)
16706c3fb27SDimitry Andric       : AttributeCommonInfo(nullptr, nullptr, AttrRange, SourceLocation(), K,
16806c3fb27SDimitry Andric                             FormUsed) {}
169a7dea167SDimitry Andric 
170a7dea167SDimitry Andric   AttributeCommonInfo(AttributeCommonInfo &&) = default;
171a7dea167SDimitry Andric   AttributeCommonInfo(const AttributeCommonInfo &) = default;
172a7dea167SDimitry Andric 
173a7dea167SDimitry Andric   Kind getParsedKind() const { return Kind(AttrKind); }
174a7dea167SDimitry Andric   Syntax getSyntax() const { return Syntax(SyntaxUsed); }
17506c3fb27SDimitry Andric   Form getForm() const {
17606c3fb27SDimitry Andric     return Form(getSyntax(), SpellingIndex, IsAlignas,
17706c3fb27SDimitry Andric                 IsRegularKeywordAttribute);
17806c3fb27SDimitry Andric   }
179a7dea167SDimitry Andric   const IdentifierInfo *getAttrName() const { return AttrName; }
1805f757f3fSDimitry Andric   void setAttrName(const IdentifierInfo *AttrNameII) { AttrName = AttrNameII; }
181a7dea167SDimitry Andric   SourceLocation getLoc() const { return AttrRange.getBegin(); }
182a7dea167SDimitry Andric   SourceRange getRange() const { return AttrRange; }
183a7dea167SDimitry Andric   void setRange(SourceRange R) { AttrRange = R; }
184a7dea167SDimitry Andric 
185a7dea167SDimitry Andric   bool hasScope() const { return ScopeName; }
186a7dea167SDimitry Andric   const IdentifierInfo *getScopeName() const { return ScopeName; }
187a7dea167SDimitry Andric   SourceLocation getScopeLoc() const { return ScopeLoc; }
188a7dea167SDimitry Andric 
1895ffd83dbSDimitry Andric   /// Gets the normalized full name, which consists of both scope and name and
1905ffd83dbSDimitry Andric   /// with surrounding underscores removed as appropriate (e.g.
1915ffd83dbSDimitry Andric   /// __gnu__::__attr__ will be normalized to gnu::attr).
1925ffd83dbSDimitry Andric   std::string getNormalizedFullName() const;
1935ffd83dbSDimitry Andric 
194a7dea167SDimitry Andric   bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
195a7dea167SDimitry Andric   bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; }
196a7dea167SDimitry Andric 
197a7dea167SDimitry Andric   bool isGNUScope() const;
19881ad6265SDimitry Andric   bool isClangScope() const;
199a7dea167SDimitry Andric 
20006c3fb27SDimitry Andric   bool isCXX11Attribute() const { return SyntaxUsed == AS_CXX11 || IsAlignas; }
201a7dea167SDimitry Andric 
2025f757f3fSDimitry Andric   bool isC23Attribute() const { return SyntaxUsed == AS_C23; }
2035f757f3fSDimitry Andric 
2045f757f3fSDimitry Andric   bool isAlignas() const {
2055f757f3fSDimitry Andric     // FIXME: In the current state, the IsAlignas member variable is only true
2065f757f3fSDimitry Andric     // with the C++  `alignas` keyword but not `_Alignas`. The following
2075f757f3fSDimitry Andric     // expression works around the otherwise lost information so it will return
2085f757f3fSDimitry Andric     // true for `alignas` or `_Alignas` while still returning false for things
2095f757f3fSDimitry Andric     // like  `__attribute__((aligned))`.
2105f757f3fSDimitry Andric     return (getParsedKind() == AT_Aligned && isKeywordAttribute());
2115f757f3fSDimitry Andric   }
212a7dea167SDimitry Andric 
213fe6060f1SDimitry Andric   /// The attribute is spelled [[]] in either C or C++ mode, including standard
214fe6060f1SDimitry Andric   /// attributes spelled with a keyword, like alignas.
215fe6060f1SDimitry Andric   bool isStandardAttributeSyntax() const {
2165f757f3fSDimitry Andric     return isCXX11Attribute() || isC23Attribute();
217fe6060f1SDimitry Andric   }
218fe6060f1SDimitry Andric 
21981ad6265SDimitry Andric   bool isGNUAttribute() const { return SyntaxUsed == AS_GNU; }
22081ad6265SDimitry Andric 
221a7dea167SDimitry Andric   bool isKeywordAttribute() const {
222a7dea167SDimitry Andric     return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword;
223a7dea167SDimitry Andric   }
224a7dea167SDimitry Andric 
22506c3fb27SDimitry Andric   bool isRegularKeywordAttribute() const { return IsRegularKeywordAttribute; }
22606c3fb27SDimitry Andric 
227a7dea167SDimitry Andric   bool isContextSensitiveKeywordAttribute() const {
228a7dea167SDimitry Andric     return SyntaxUsed == AS_ContextSensitiveKeyword;
229a7dea167SDimitry Andric   }
230a7dea167SDimitry Andric 
231a7dea167SDimitry Andric   unsigned getAttributeSpellingListIndex() const {
232a7dea167SDimitry Andric     assert((isAttributeSpellingListCalculated() || AttrName) &&
233a7dea167SDimitry Andric            "Spelling cannot be found");
234a7dea167SDimitry Andric     return isAttributeSpellingListCalculated()
235a7dea167SDimitry Andric                ? SpellingIndex
236a7dea167SDimitry Andric                : calculateAttributeSpellingListIndex();
237a7dea167SDimitry Andric   }
238a7dea167SDimitry Andric   void setAttributeSpellingListIndex(unsigned V) { SpellingIndex = V; }
239a7dea167SDimitry Andric 
240a7dea167SDimitry Andric   static Kind getParsedKind(const IdentifierInfo *Name,
241a7dea167SDimitry Andric                             const IdentifierInfo *Scope, Syntax SyntaxUsed);
242a7dea167SDimitry Andric 
243a7dea167SDimitry Andric private:
244a7dea167SDimitry Andric   /// Get an index into the attribute spelling list
245a7dea167SDimitry Andric   /// defined in Attr.td. This index is used by an attribute
246a7dea167SDimitry Andric   /// to pretty print itself.
247a7dea167SDimitry Andric   unsigned calculateAttributeSpellingListIndex() const;
248a7dea167SDimitry Andric 
249a7dea167SDimitry Andric   friend class clang::ASTRecordWriter;
250a7dea167SDimitry Andric   // Used exclusively by ASTDeclWriter to get the raw spelling list state.
251a7dea167SDimitry Andric   unsigned getAttributeSpellingListIndexRaw() const { return SpellingIndex; }
252a7dea167SDimitry Andric 
253a7dea167SDimitry Andric protected:
254a7dea167SDimitry Andric   bool isAttributeSpellingListCalculated() const {
255a7dea167SDimitry Andric     return SpellingIndex != SpellingNotCalculated;
256a7dea167SDimitry Andric   }
257a7dea167SDimitry Andric };
2587a6dacacSDimitry Andric 
2597a6dacacSDimitry Andric inline bool doesKeywordAttributeTakeArgs(tok::TokenKind Kind) {
2607a6dacacSDimitry Andric   switch (Kind) {
2617a6dacacSDimitry Andric   default:
2627a6dacacSDimitry Andric     return false;
2637a6dacacSDimitry Andric #define KEYWORD_ATTRIBUTE(NAME, HASARG, ...)                                   \
2647a6dacacSDimitry Andric   case tok::kw_##NAME:                                                         \
2657a6dacacSDimitry Andric     return HASARG;
2667a6dacacSDimitry Andric #include "clang/Basic/RegularKeywordAttrInfo.inc"
2677a6dacacSDimitry Andric #undef KEYWORD_ATTRIBUTE
2687a6dacacSDimitry Andric   }
2697a6dacacSDimitry Andric }
2707a6dacacSDimitry Andric 
271a7dea167SDimitry Andric } // namespace clang
272a7dea167SDimitry Andric 
273a7dea167SDimitry Andric #endif // LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
274