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