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   enum Kind {
53 #define PARSED_ATTR(NAME) AT_##NAME,
54 #include "clang/Sema/AttrParsedAttrList.inc"
55 #undef PARSED_ATTR
56     NoSemaHandlerAttribute,
57     IgnoredAttribute,
58     UnknownAttribute,
59   };
60 
61 private:
62   const IdentifierInfo *AttrName = nullptr;
63   const IdentifierInfo *ScopeName = nullptr;
64   SourceRange AttrRange;
65   const SourceLocation ScopeLoc;
66   // Corresponds to the Kind enum.
67   unsigned AttrKind : 16;
68   /// Corresponds to the Syntax enum.
69   unsigned SyntaxUsed : 3;
70   unsigned SpellingIndex : 4;
71 
72 protected:
73   static constexpr unsigned SpellingNotCalculated = 0xf;
74 
75 public:
AttributeCommonInfo(SourceRange AttrRange)76   AttributeCommonInfo(SourceRange AttrRange)
77       : AttrRange(AttrRange), ScopeLoc(), AttrKind(0), SyntaxUsed(0),
78         SpellingIndex(SpellingNotCalculated) {}
79 
AttributeCommonInfo(SourceLocation AttrLoc)80   AttributeCommonInfo(SourceLocation AttrLoc)
81       : AttrRange(AttrLoc), ScopeLoc(), AttrKind(0), SyntaxUsed(0),
82         SpellingIndex(SpellingNotCalculated) {}
83 
AttributeCommonInfo(const IdentifierInfo * AttrName,const IdentifierInfo * ScopeName,SourceRange AttrRange,SourceLocation ScopeLoc,Syntax SyntaxUsed)84   AttributeCommonInfo(const IdentifierInfo *AttrName,
85                       const IdentifierInfo *ScopeName, SourceRange AttrRange,
86                       SourceLocation ScopeLoc, Syntax SyntaxUsed)
87       : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange),
88         ScopeLoc(ScopeLoc),
89         AttrKind(getParsedKind(AttrName, ScopeName, SyntaxUsed)),
90         SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingNotCalculated) {}
91 
AttributeCommonInfo(const IdentifierInfo * AttrName,const IdentifierInfo * ScopeName,SourceRange AttrRange,SourceLocation ScopeLoc,Kind AttrKind,Syntax SyntaxUsed)92   AttributeCommonInfo(const IdentifierInfo *AttrName,
93                       const IdentifierInfo *ScopeName, SourceRange AttrRange,
94                       SourceLocation ScopeLoc, Kind AttrKind, Syntax SyntaxUsed)
95       : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange),
96         ScopeLoc(ScopeLoc), AttrKind(AttrKind), SyntaxUsed(SyntaxUsed),
97         SpellingIndex(SpellingNotCalculated) {}
98 
AttributeCommonInfo(const IdentifierInfo * AttrName,const IdentifierInfo * ScopeName,SourceRange AttrRange,SourceLocation ScopeLoc,Kind AttrKind,Syntax SyntaxUsed,unsigned Spelling)99   AttributeCommonInfo(const IdentifierInfo *AttrName,
100                       const IdentifierInfo *ScopeName, SourceRange AttrRange,
101                       SourceLocation ScopeLoc, Kind AttrKind, Syntax SyntaxUsed,
102                       unsigned Spelling)
103       : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange),
104         ScopeLoc(ScopeLoc), AttrKind(AttrKind), SyntaxUsed(SyntaxUsed),
105         SpellingIndex(Spelling) {}
106 
AttributeCommonInfo(const IdentifierInfo * AttrName,SourceRange AttrRange,Syntax SyntaxUsed)107   AttributeCommonInfo(const IdentifierInfo *AttrName, SourceRange AttrRange,
108                       Syntax SyntaxUsed)
109       : AttrName(AttrName), ScopeName(nullptr), AttrRange(AttrRange),
110         ScopeLoc(), AttrKind(getParsedKind(AttrName, ScopeName, SyntaxUsed)),
111         SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingNotCalculated) {}
112 
AttributeCommonInfo(SourceRange AttrRange,Kind K,Syntax SyntaxUsed)113   AttributeCommonInfo(SourceRange AttrRange, Kind K, Syntax SyntaxUsed)
114       : AttrName(nullptr), ScopeName(nullptr), AttrRange(AttrRange), ScopeLoc(),
115         AttrKind(K), SyntaxUsed(SyntaxUsed),
116         SpellingIndex(SpellingNotCalculated) {}
117 
AttributeCommonInfo(SourceRange AttrRange,Kind K,Syntax SyntaxUsed,unsigned Spelling)118   AttributeCommonInfo(SourceRange AttrRange, Kind K, Syntax SyntaxUsed,
119                       unsigned Spelling)
120       : AttrName(nullptr), ScopeName(nullptr), AttrRange(AttrRange), ScopeLoc(),
121         AttrKind(K), SyntaxUsed(SyntaxUsed), SpellingIndex(Spelling) {}
122 
123   AttributeCommonInfo(AttributeCommonInfo &&) = default;
124   AttributeCommonInfo(const AttributeCommonInfo &) = default;
125 
getParsedKind()126   Kind getParsedKind() const { return Kind(AttrKind); }
getSyntax()127   Syntax getSyntax() const { return Syntax(SyntaxUsed); }
getAttrName()128   const IdentifierInfo *getAttrName() const { return AttrName; }
getLoc()129   SourceLocation getLoc() const { return AttrRange.getBegin(); }
getRange()130   SourceRange getRange() const { return AttrRange; }
setRange(SourceRange R)131   void setRange(SourceRange R) { AttrRange = R; }
132 
hasScope()133   bool hasScope() const { return ScopeName; }
getScopeName()134   const IdentifierInfo *getScopeName() const { return ScopeName; }
getScopeLoc()135   SourceLocation getScopeLoc() const { return ScopeLoc; }
136 
137   /// Gets the normalized full name, which consists of both scope and name and
138   /// with surrounding underscores removed as appropriate (e.g.
139   /// __gnu__::__attr__ will be normalized to gnu::attr).
140   std::string getNormalizedFullName() const;
141 
isDeclspecAttribute()142   bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
isMicrosoftAttribute()143   bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; }
144 
145   bool isGNUScope() const;
146 
isAlignasAttribute()147   bool isAlignasAttribute() const {
148     // FIXME: Use a better mechanism to determine this.
149     return getParsedKind() == AT_Aligned && isKeywordAttribute();
150   }
151 
isCXX11Attribute()152   bool isCXX11Attribute() const {
153     return SyntaxUsed == AS_CXX11 || isAlignasAttribute();
154   }
155 
isC2xAttribute()156   bool isC2xAttribute() const { return SyntaxUsed == AS_C2x; }
157 
isKeywordAttribute()158   bool isKeywordAttribute() const {
159     return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword;
160   }
161 
isContextSensitiveKeywordAttribute()162   bool isContextSensitiveKeywordAttribute() const {
163     return SyntaxUsed == AS_ContextSensitiveKeyword;
164   }
165 
getAttributeSpellingListIndex()166   unsigned getAttributeSpellingListIndex() const {
167     assert((isAttributeSpellingListCalculated() || AttrName) &&
168            "Spelling cannot be found");
169     return isAttributeSpellingListCalculated()
170                ? SpellingIndex
171                : calculateAttributeSpellingListIndex();
172   }
setAttributeSpellingListIndex(unsigned V)173   void setAttributeSpellingListIndex(unsigned V) { SpellingIndex = V; }
174 
175   static Kind getParsedKind(const IdentifierInfo *Name,
176                             const IdentifierInfo *Scope, Syntax SyntaxUsed);
177 
178 private:
179   /// Get an index into the attribute spelling list
180   /// defined in Attr.td. This index is used by an attribute
181   /// to pretty print itself.
182   unsigned calculateAttributeSpellingListIndex() const;
183 
184   friend class clang::ASTRecordWriter;
185   // Used exclusively by ASTDeclWriter to get the raw spelling list state.
getAttributeSpellingListIndexRaw()186   unsigned getAttributeSpellingListIndexRaw() const { return SpellingIndex; }
187 
188 protected:
isAttributeSpellingListCalculated()189   bool isAttributeSpellingListCalculated() const {
190     return SpellingIndex != SpellingNotCalculated;
191   }
192 };
193 } // namespace clang
194 
195 #endif // LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
196