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