Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 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 | |||
18 | namespace clang { |
||
19 | class IdentifierInfo; |
||
20 | class ASTRecordWriter; |
||
21 | |||
22 | class AttributeCommonInfo { |
||
23 | public: |
||
24 | /// The style used to specify an attribute. |
||
25 | enum Syntax { |
||
26 | /// __attribute__((...)) |
||
27 | AS_GNU, |
||
28 | |||
29 | /// [[...]] |
||
30 | AS_CXX11, |
||
31 | |||
32 | /// [[...]] |
||
33 | AS_C2x, |
||
34 | |||
35 | /// __declspec(...) |
||
36 | AS_Declspec, |
||
37 | |||
38 | /// [uuid("...")] class Foo |
||
39 | AS_Microsoft, |
||
40 | |||
41 | /// __ptr16, alignas(...), etc. |
||
42 | AS_Keyword, |
||
43 | |||
44 | /// #pragma ... |
||
45 | AS_Pragma, |
||
46 | |||
47 | // Note TableGen depends on the order above. Do not add or change the order |
||
48 | // without adding related code to TableGen/ClangAttrEmitter.cpp. |
||
49 | /// Context-sensitive version of a keyword attribute. |
||
50 | AS_ContextSensitiveKeyword, |
||
51 | |||
52 | /// <vardecl> : <semantic> |
||
53 | AS_HLSLSemantic, |
||
54 | }; |
||
55 | enum Kind { |
||
56 | #define PARSED_ATTR(NAME) AT_##NAME, |
||
57 | #include "clang/Sema/AttrParsedAttrList.inc" |
||
58 | #undef PARSED_ATTR |
||
59 | NoSemaHandlerAttribute, |
||
60 | IgnoredAttribute, |
||
61 | UnknownAttribute, |
||
62 | }; |
||
63 | |||
64 | private: |
||
65 | const IdentifierInfo *AttrName = nullptr; |
||
66 | const IdentifierInfo *ScopeName = nullptr; |
||
67 | SourceRange AttrRange; |
||
68 | const SourceLocation ScopeLoc; |
||
69 | // Corresponds to the Kind enum. |
||
70 | unsigned AttrKind : 16; |
||
71 | /// Corresponds to the Syntax enum. |
||
72 | unsigned SyntaxUsed : 4; |
||
73 | unsigned SpellingIndex : 4; |
||
74 | |||
75 | protected: |
||
76 | static constexpr unsigned SpellingNotCalculated = 0xf; |
||
77 | |||
78 | public: |
||
79 | AttributeCommonInfo(SourceRange AttrRange) |
||
80 | : AttrRange(AttrRange), ScopeLoc(), AttrKind(0), SyntaxUsed(0), |
||
81 | SpellingIndex(SpellingNotCalculated) {} |
||
82 | |||
83 | AttributeCommonInfo(SourceLocation AttrLoc) |
||
84 | : AttrRange(AttrLoc), ScopeLoc(), AttrKind(0), SyntaxUsed(0), |
||
85 | SpellingIndex(SpellingNotCalculated) {} |
||
86 | |||
87 | AttributeCommonInfo(const IdentifierInfo *AttrName, |
||
88 | const IdentifierInfo *ScopeName, SourceRange AttrRange, |
||
89 | SourceLocation ScopeLoc, Syntax SyntaxUsed) |
||
90 | : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange), |
||
91 | ScopeLoc(ScopeLoc), |
||
92 | AttrKind(getParsedKind(AttrName, ScopeName, SyntaxUsed)), |
||
93 | SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingNotCalculated) {} |
||
94 | |||
95 | AttributeCommonInfo(const IdentifierInfo *AttrName, |
||
96 | const IdentifierInfo *ScopeName, SourceRange AttrRange, |
||
97 | SourceLocation ScopeLoc, Kind AttrKind, Syntax SyntaxUsed) |
||
98 | : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange), |
||
99 | ScopeLoc(ScopeLoc), AttrKind(AttrKind), SyntaxUsed(SyntaxUsed), |
||
100 | SpellingIndex(SpellingNotCalculated) {} |
||
101 | |||
102 | AttributeCommonInfo(const IdentifierInfo *AttrName, |
||
103 | const IdentifierInfo *ScopeName, SourceRange AttrRange, |
||
104 | SourceLocation ScopeLoc, Kind AttrKind, Syntax SyntaxUsed, |
||
105 | unsigned Spelling) |
||
106 | : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange), |
||
107 | ScopeLoc(ScopeLoc), AttrKind(AttrKind), SyntaxUsed(SyntaxUsed), |
||
108 | SpellingIndex(Spelling) {} |
||
109 | |||
110 | AttributeCommonInfo(const IdentifierInfo *AttrName, SourceRange AttrRange, |
||
111 | Syntax SyntaxUsed) |
||
112 | : AttrName(AttrName), ScopeName(nullptr), AttrRange(AttrRange), |
||
113 | ScopeLoc(), AttrKind(getParsedKind(AttrName, ScopeName, SyntaxUsed)), |
||
114 | SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingNotCalculated) {} |
||
115 | |||
116 | AttributeCommonInfo(SourceRange AttrRange, Kind K, Syntax SyntaxUsed) |
||
117 | : AttrName(nullptr), ScopeName(nullptr), AttrRange(AttrRange), ScopeLoc(), |
||
118 | AttrKind(K), SyntaxUsed(SyntaxUsed), |
||
119 | SpellingIndex(SpellingNotCalculated) {} |
||
120 | |||
121 | AttributeCommonInfo(SourceRange AttrRange, Kind K, Syntax SyntaxUsed, |
||
122 | unsigned Spelling) |
||
123 | : AttrName(nullptr), ScopeName(nullptr), AttrRange(AttrRange), ScopeLoc(), |
||
124 | AttrKind(K), SyntaxUsed(SyntaxUsed), SpellingIndex(Spelling) {} |
||
125 | |||
126 | AttributeCommonInfo(AttributeCommonInfo &&) = default; |
||
127 | AttributeCommonInfo(const AttributeCommonInfo &) = default; |
||
128 | |||
129 | Kind getParsedKind() const { return Kind(AttrKind); } |
||
130 | Syntax getSyntax() const { return Syntax(SyntaxUsed); } |
||
131 | const IdentifierInfo *getAttrName() const { return AttrName; } |
||
132 | SourceLocation getLoc() const { return AttrRange.getBegin(); } |
||
133 | SourceRange getRange() const { return AttrRange; } |
||
134 | void setRange(SourceRange R) { AttrRange = R; } |
||
135 | |||
136 | bool hasScope() const { return ScopeName; } |
||
137 | const IdentifierInfo *getScopeName() const { return ScopeName; } |
||
138 | SourceLocation getScopeLoc() const { return ScopeLoc; } |
||
139 | |||
140 | /// Gets the normalized full name, which consists of both scope and name and |
||
141 | /// with surrounding underscores removed as appropriate (e.g. |
||
142 | /// __gnu__::__attr__ will be normalized to gnu::attr). |
||
143 | std::string getNormalizedFullName() const; |
||
144 | |||
145 | bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; } |
||
146 | bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; } |
||
147 | |||
148 | bool isGNUScope() const; |
||
149 | bool isClangScope() const; |
||
150 | |||
151 | bool isAlignasAttribute() const { |
||
152 | // FIXME: Use a better mechanism to determine this. |
||
153 | // We use this in `isCXX11Attribute` below, so it _should_ only return |
||
154 | // true for the `alignas` spelling, but it currently also returns true |
||
155 | // for the `_Alignas` spelling, which only exists in C11. Distinguishing |
||
156 | // between the two is important because they behave differently: |
||
157 | // - `alignas` may only appear in the attribute-specifier-seq before |
||
158 | // the decl-specifier-seq and is therefore associated with the |
||
159 | // declaration. |
||
160 | // - `_Alignas` may appear anywhere within the declaration-specifiers |
||
161 | // and is therefore associated with the `DeclSpec`. |
||
162 | // It's not clear how best to fix this: |
||
163 | // - We have the necessary information in the form of the `SpellingIndex`, |
||
164 | // but we would need to compare against AlignedAttr::Keyword_alignas, |
||
165 | // and we can't depend on clang/AST/Attr.h here. |
||
166 | // - We could test `getAttrName()->getName() == "alignas"`, but this is |
||
167 | // inefficient. |
||
168 | return getParsedKind() == AT_Aligned && isKeywordAttribute(); |
||
169 | } |
||
170 | |||
171 | bool isCXX11Attribute() const { |
||
172 | return SyntaxUsed == AS_CXX11 || isAlignasAttribute(); |
||
173 | } |
||
174 | |||
175 | bool isC2xAttribute() const { return SyntaxUsed == AS_C2x; } |
||
176 | |||
177 | /// The attribute is spelled [[]] in either C or C++ mode, including standard |
||
178 | /// attributes spelled with a keyword, like alignas. |
||
179 | bool isStandardAttributeSyntax() const { |
||
180 | return isCXX11Attribute() || isC2xAttribute(); |
||
181 | } |
||
182 | |||
183 | bool isGNUAttribute() const { return SyntaxUsed == AS_GNU; } |
||
184 | |||
185 | bool isKeywordAttribute() const { |
||
186 | return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword; |
||
187 | } |
||
188 | |||
189 | bool isContextSensitiveKeywordAttribute() const { |
||
190 | return SyntaxUsed == AS_ContextSensitiveKeyword; |
||
191 | } |
||
192 | |||
193 | unsigned getAttributeSpellingListIndex() const { |
||
194 | assert((isAttributeSpellingListCalculated() || AttrName) && |
||
195 | "Spelling cannot be found"); |
||
196 | return isAttributeSpellingListCalculated() |
||
197 | ? SpellingIndex |
||
198 | : calculateAttributeSpellingListIndex(); |
||
199 | } |
||
200 | void setAttributeSpellingListIndex(unsigned V) { SpellingIndex = V; } |
||
201 | |||
202 | static Kind getParsedKind(const IdentifierInfo *Name, |
||
203 | const IdentifierInfo *Scope, Syntax SyntaxUsed); |
||
204 | |||
205 | private: |
||
206 | /// Get an index into the attribute spelling list |
||
207 | /// defined in Attr.td. This index is used by an attribute |
||
208 | /// to pretty print itself. |
||
209 | unsigned calculateAttributeSpellingListIndex() const; |
||
210 | |||
211 | friend class clang::ASTRecordWriter; |
||
212 | // Used exclusively by ASTDeclWriter to get the raw spelling list state. |
||
213 | unsigned getAttributeSpellingListIndexRaw() const { return SpellingIndex; } |
||
214 | |||
215 | protected: |
||
216 | bool isAttributeSpellingListCalculated() const { |
||
217 | return SpellingIndex != SpellingNotCalculated; |
||
218 | } |
||
219 | }; |
||
220 | } // namespace clang |
||
221 | |||
222 | #endif // LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H |