1 //======- AttributeCommonInfo.h - Base info about 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 AttributeCommonInfo type, which is the base for a
10 // ParsedAttr and is used by Attr as a way to share info between the two.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
15 #define LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
16 #include "clang/Basic/SourceLocation.h"
17 #include "clang/Basic/TokenKinds.h"
18 
19 namespace clang {
20 class IdentifierInfo;
21 class ASTRecordWriter;
22 
23 class AttributeCommonInfo {
24 public:
25   /// The style used to specify an attribute.
26   enum Syntax {
27     /// __attribute__((...))
28     AS_GNU = 1,
29 
30     /// [[...]]
31     AS_CXX11,
32 
33     /// [[...]]
34     AS_C2x,
35 
36     /// __declspec(...)
37     AS_Declspec,
38 
39     /// [uuid("...")] class Foo
40     AS_Microsoft,
41 
42     /// __ptr16, alignas(...), etc.
43     AS_Keyword,
44 
45     /// #pragma ...
46     AS_Pragma,
47 
48     // Note TableGen depends on the order above.  Do not add or change the order
49     // without adding related code to TableGen/ClangAttrEmitter.cpp.
50     /// Context-sensitive version of a keyword attribute.
51     AS_ContextSensitiveKeyword,
52 
53     /// <vardecl> : <semantic>
54     AS_HLSLSemantic,
55 
56     /// The attibute has no source code manifestation and is only created
57     /// implicitly.
58     AS_Implicit
59   };
60   enum Kind {
61 #define PARSED_ATTR(NAME) AT_##NAME,
62 #include "clang/Sema/AttrParsedAttrList.inc"
63 #undef PARSED_ATTR
64     NoSemaHandlerAttribute,
65     IgnoredAttribute,
66     UnknownAttribute,
67   };
68 
69 private:
70   const IdentifierInfo *AttrName = nullptr;
71   const IdentifierInfo *ScopeName = nullptr;
72   SourceRange AttrRange;
73   const SourceLocation ScopeLoc;
74   // Corresponds to the Kind enum.
75   unsigned AttrKind : 16;
76   /// Corresponds to the Syntax enum.
77   unsigned SyntaxUsed : 4;
78   unsigned SpellingIndex : 4;
79   unsigned IsAlignas : 1;
80   unsigned IsRegularKeywordAttribute : 1;
81 
82 protected:
83   static constexpr unsigned SpellingNotCalculated = 0xf;
84 
85 public:
86   /// Combines information about the source-code form of an attribute,
87   /// including its syntax and spelling.
88   class Form {
89   public:
90     constexpr Form(Syntax SyntaxUsed, unsigned SpellingIndex, bool IsAlignas,
91                    bool IsRegularKeywordAttribute)
92         : SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingIndex),
93           IsAlignas(IsAlignas),
94           IsRegularKeywordAttribute(IsRegularKeywordAttribute) {}
95     constexpr Form(tok::TokenKind Tok)
96         : SyntaxUsed(AS_Keyword), SpellingIndex(SpellingNotCalculated),
97           IsAlignas(Tok == tok::kw_alignas),
98           IsRegularKeywordAttribute(tok::isRegularKeywordAttribute(Tok)) {}
99 
100     Syntax getSyntax() const { return Syntax(SyntaxUsed); }
101     unsigned getSpellingIndex() const { return SpellingIndex; }
102     bool isAlignas() const { return IsAlignas; }
103     bool isRegularKeywordAttribute() const { return IsRegularKeywordAttribute; }
104 
105     static Form GNU() { return AS_GNU; }
106     static Form CXX11() { return AS_CXX11; }
107     static Form C2x() { return AS_C2x; }
108     static Form Declspec() { return AS_Declspec; }
109     static Form Microsoft() { return AS_Microsoft; }
110     static Form Keyword(bool IsAlignas, bool IsRegularKeywordAttribute) {
111       return Form(AS_Keyword, SpellingNotCalculated, IsAlignas,
112                   IsRegularKeywordAttribute);
113     }
114     static Form Pragma() { return AS_Pragma; }
115     static Form ContextSensitiveKeyword() { return AS_ContextSensitiveKeyword; }
116     static Form HLSLSemantic() { return AS_HLSLSemantic; }
117     static Form Implicit() { return AS_Implicit; }
118 
119   private:
120     constexpr Form(Syntax SyntaxUsed)
121         : SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingNotCalculated),
122           IsAlignas(0), IsRegularKeywordAttribute(0) {}
123 
124     unsigned SyntaxUsed : 4;
125     unsigned SpellingIndex : 4;
126     unsigned IsAlignas : 1;
127     unsigned IsRegularKeywordAttribute : 1;
128   };
129 
130   AttributeCommonInfo(const IdentifierInfo *AttrName,
131                       const IdentifierInfo *ScopeName, SourceRange AttrRange,
132                       SourceLocation ScopeLoc, Kind AttrKind, Form FormUsed)
133       : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange),
134         ScopeLoc(ScopeLoc), AttrKind(AttrKind),
135         SyntaxUsed(FormUsed.getSyntax()),
136         SpellingIndex(FormUsed.getSpellingIndex()),
137         IsAlignas(FormUsed.isAlignas()),
138         IsRegularKeywordAttribute(FormUsed.isRegularKeywordAttribute()) {
139     assert(SyntaxUsed >= AS_GNU && SyntaxUsed <= AS_Implicit &&
140            "Invalid syntax!");
141   }
142 
143   AttributeCommonInfo(const IdentifierInfo *AttrName,
144                       const IdentifierInfo *ScopeName, SourceRange AttrRange,
145                       SourceLocation ScopeLoc, Form FormUsed)
146       : AttributeCommonInfo(
147             AttrName, ScopeName, AttrRange, ScopeLoc,
148             getParsedKind(AttrName, ScopeName, FormUsed.getSyntax()),
149             FormUsed) {}
150 
151   AttributeCommonInfo(const IdentifierInfo *AttrName, SourceRange AttrRange,
152                       Form FormUsed)
153       : AttributeCommonInfo(AttrName, nullptr, AttrRange, SourceLocation(),
154                             FormUsed) {}
155 
156   AttributeCommonInfo(SourceRange AttrRange, Kind K, Form FormUsed)
157       : AttributeCommonInfo(nullptr, nullptr, AttrRange, SourceLocation(), K,
158                             FormUsed) {}
159 
160   AttributeCommonInfo(AttributeCommonInfo &&) = default;
161   AttributeCommonInfo(const AttributeCommonInfo &) = default;
162 
163   Kind getParsedKind() const { return Kind(AttrKind); }
164   Syntax getSyntax() const { return Syntax(SyntaxUsed); }
165   Form getForm() const {
166     return Form(getSyntax(), SpellingIndex, IsAlignas,
167                 IsRegularKeywordAttribute);
168   }
169   const IdentifierInfo *getAttrName() const { return AttrName; }
170   SourceLocation getLoc() const { return AttrRange.getBegin(); }
171   SourceRange getRange() const { return AttrRange; }
172   void setRange(SourceRange R) { AttrRange = R; }
173 
174   bool hasScope() const { return ScopeName; }
175   const IdentifierInfo *getScopeName() const { return ScopeName; }
176   SourceLocation getScopeLoc() const { return ScopeLoc; }
177 
178   /// Gets the normalized full name, which consists of both scope and name and
179   /// with surrounding underscores removed as appropriate (e.g.
180   /// __gnu__::__attr__ will be normalized to gnu::attr).
181   std::string getNormalizedFullName() const;
182 
183   bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
184   bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; }
185 
186   bool isGNUScope() const;
187   bool isClangScope() const;
188 
189   bool isCXX11Attribute() const { return SyntaxUsed == AS_CXX11 || IsAlignas; }
190 
191   bool isC2xAttribute() const { return SyntaxUsed == AS_C2x; }
192 
193   /// The attribute is spelled [[]] in either C or C++ mode, including standard
194   /// attributes spelled with a keyword, like alignas.
195   bool isStandardAttributeSyntax() const {
196     return isCXX11Attribute() || isC2xAttribute();
197   }
198 
199   bool isGNUAttribute() const { return SyntaxUsed == AS_GNU; }
200 
201   bool isKeywordAttribute() const {
202     return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword;
203   }
204 
205   bool isRegularKeywordAttribute() const { return IsRegularKeywordAttribute; }
206 
207   bool isContextSensitiveKeywordAttribute() const {
208     return SyntaxUsed == AS_ContextSensitiveKeyword;
209   }
210 
211   unsigned getAttributeSpellingListIndex() const {
212     assert((isAttributeSpellingListCalculated() || AttrName) &&
213            "Spelling cannot be found");
214     return isAttributeSpellingListCalculated()
215                ? SpellingIndex
216                : calculateAttributeSpellingListIndex();
217   }
218   void setAttributeSpellingListIndex(unsigned V) { SpellingIndex = V; }
219 
220   static Kind getParsedKind(const IdentifierInfo *Name,
221                             const IdentifierInfo *Scope, Syntax SyntaxUsed);
222 
223 private:
224   /// Get an index into the attribute spelling list
225   /// defined in Attr.td. This index is used by an attribute
226   /// to pretty print itself.
227   unsigned calculateAttributeSpellingListIndex() const;
228 
229   friend class clang::ASTRecordWriter;
230   // Used exclusively by ASTDeclWriter to get the raw spelling list state.
231   unsigned getAttributeSpellingListIndexRaw() const { return SpellingIndex; }
232 
233 protected:
234   bool isAttributeSpellingListCalculated() const {
235     return SpellingIndex != SpellingNotCalculated;
236   }
237 };
238 } // namespace clang
239 
240 #endif // LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
241