1a7dea167SDimitry Andric //======- AttributeCommonInfo.h - Base info about Attributes-----*- C++ -*-===// 2a7dea167SDimitry Andric // 3a7dea167SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a7dea167SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5a7dea167SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a7dea167SDimitry Andric // 7a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 8a7dea167SDimitry Andric // 9a7dea167SDimitry Andric // This file defines the AttributeCommonInfo type, which is the base for a 10a7dea167SDimitry Andric // ParsedAttr and is used by Attr as a way to share info between the two. 11a7dea167SDimitry Andric // 12a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 13a7dea167SDimitry Andric 14a7dea167SDimitry Andric #ifndef LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H 15a7dea167SDimitry Andric #define LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H 165f757f3fSDimitry Andric 17a7dea167SDimitry Andric #include "clang/Basic/SourceLocation.h" 1806c3fb27SDimitry Andric #include "clang/Basic/TokenKinds.h" 19a7dea167SDimitry Andric 20a7dea167SDimitry Andric namespace clang { 215f757f3fSDimitry Andric 22a7dea167SDimitry Andric class ASTRecordWriter; 235f757f3fSDimitry Andric class IdentifierInfo; 24a7dea167SDimitry Andric 25a7dea167SDimitry Andric class AttributeCommonInfo { 26a7dea167SDimitry Andric public: 27a7dea167SDimitry Andric /// The style used to specify an attribute. 28a7dea167SDimitry Andric enum Syntax { 29a7dea167SDimitry Andric /// __attribute__((...)) 3006c3fb27SDimitry Andric AS_GNU = 1, 31a7dea167SDimitry Andric 32a7dea167SDimitry Andric /// [[...]] 33a7dea167SDimitry Andric AS_CXX11, 34a7dea167SDimitry Andric 35a7dea167SDimitry Andric /// [[...]] 365f757f3fSDimitry Andric AS_C23, 37a7dea167SDimitry Andric 38a7dea167SDimitry Andric /// __declspec(...) 39a7dea167SDimitry Andric AS_Declspec, 40a7dea167SDimitry Andric 41a7dea167SDimitry Andric /// [uuid("...")] class Foo 42a7dea167SDimitry Andric AS_Microsoft, 43a7dea167SDimitry Andric 44a7dea167SDimitry Andric /// __ptr16, alignas(...), etc. 45a7dea167SDimitry Andric AS_Keyword, 46a7dea167SDimitry Andric 47a7dea167SDimitry Andric /// #pragma ... 48a7dea167SDimitry Andric AS_Pragma, 49a7dea167SDimitry Andric 50a7dea167SDimitry Andric // Note TableGen depends on the order above. Do not add or change the order 51a7dea167SDimitry Andric // without adding related code to TableGen/ClangAttrEmitter.cpp. 52a7dea167SDimitry Andric /// Context-sensitive version of a keyword attribute. 53a7dea167SDimitry Andric AS_ContextSensitiveKeyword, 5481ad6265SDimitry Andric 55*0fca6ea1SDimitry Andric /// <vardecl> : <annotation> 56*0fca6ea1SDimitry Andric AS_HLSLAnnotation, 5706c3fb27SDimitry Andric 5806c3fb27SDimitry Andric /// The attibute has no source code manifestation and is only created 5906c3fb27SDimitry Andric /// implicitly. 6006c3fb27SDimitry Andric AS_Implicit 61a7dea167SDimitry Andric }; 62a7dea167SDimitry Andric enum Kind { 63a7dea167SDimitry Andric #define PARSED_ATTR(NAME) AT_##NAME, 64a7dea167SDimitry Andric #include "clang/Sema/AttrParsedAttrList.inc" 65a7dea167SDimitry Andric #undef PARSED_ATTR 66a7dea167SDimitry Andric NoSemaHandlerAttribute, 67a7dea167SDimitry Andric IgnoredAttribute, 68a7dea167SDimitry Andric UnknownAttribute, 69a7dea167SDimitry Andric }; 70a7dea167SDimitry Andric 71a7dea167SDimitry Andric private: 72a7dea167SDimitry Andric const IdentifierInfo *AttrName = nullptr; 73a7dea167SDimitry Andric const IdentifierInfo *ScopeName = nullptr; 74a7dea167SDimitry Andric SourceRange AttrRange; 75a7dea167SDimitry Andric const SourceLocation ScopeLoc; 76a7dea167SDimitry Andric // Corresponds to the Kind enum. 775f757f3fSDimitry Andric LLVM_PREFERRED_TYPE(Kind) 78a7dea167SDimitry Andric unsigned AttrKind : 16; 79a7dea167SDimitry Andric /// Corresponds to the Syntax enum. 805f757f3fSDimitry Andric LLVM_PREFERRED_TYPE(Syntax) 8181ad6265SDimitry Andric unsigned SyntaxUsed : 4; 825f757f3fSDimitry Andric LLVM_PREFERRED_TYPE(bool) 83a7dea167SDimitry Andric unsigned SpellingIndex : 4; 845f757f3fSDimitry Andric LLVM_PREFERRED_TYPE(bool) 8506c3fb27SDimitry Andric unsigned IsAlignas : 1; 865f757f3fSDimitry Andric LLVM_PREFERRED_TYPE(bool) 8706c3fb27SDimitry Andric unsigned IsRegularKeywordAttribute : 1; 88a7dea167SDimitry Andric 89a7dea167SDimitry Andric protected: 90a7dea167SDimitry Andric static constexpr unsigned SpellingNotCalculated = 0xf; 91a7dea167SDimitry Andric 92a7dea167SDimitry Andric public: 9306c3fb27SDimitry Andric /// Combines information about the source-code form of an attribute, 9406c3fb27SDimitry Andric /// including its syntax and spelling. 9506c3fb27SDimitry Andric class Form { 9606c3fb27SDimitry Andric public: 9706c3fb27SDimitry Andric constexpr Form(Syntax SyntaxUsed, unsigned SpellingIndex, bool IsAlignas, 9806c3fb27SDimitry Andric bool IsRegularKeywordAttribute) 9906c3fb27SDimitry Andric : SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingIndex), 10006c3fb27SDimitry Andric IsAlignas(IsAlignas), 10106c3fb27SDimitry Andric IsRegularKeywordAttribute(IsRegularKeywordAttribute) {} 10206c3fb27SDimitry Andric constexpr Form(tok::TokenKind Tok) 10306c3fb27SDimitry Andric : SyntaxUsed(AS_Keyword), SpellingIndex(SpellingNotCalculated), 10406c3fb27SDimitry Andric IsAlignas(Tok == tok::kw_alignas), 10506c3fb27SDimitry Andric IsRegularKeywordAttribute(tok::isRegularKeywordAttribute(Tok)) {} 106a7dea167SDimitry Andric 10706c3fb27SDimitry Andric Syntax getSyntax() const { return Syntax(SyntaxUsed); } 10806c3fb27SDimitry Andric unsigned getSpellingIndex() const { return SpellingIndex; } 10906c3fb27SDimitry Andric bool isAlignas() const { return IsAlignas; } 11006c3fb27SDimitry Andric bool isRegularKeywordAttribute() const { return IsRegularKeywordAttribute; } 11106c3fb27SDimitry Andric 11206c3fb27SDimitry Andric static Form GNU() { return AS_GNU; } 11306c3fb27SDimitry Andric static Form CXX11() { return AS_CXX11; } 1145f757f3fSDimitry Andric static Form C23() { return AS_C23; } 11506c3fb27SDimitry Andric static Form Declspec() { return AS_Declspec; } 11606c3fb27SDimitry Andric static Form Microsoft() { return AS_Microsoft; } 11706c3fb27SDimitry Andric static Form Keyword(bool IsAlignas, bool IsRegularKeywordAttribute) { 11806c3fb27SDimitry Andric return Form(AS_Keyword, SpellingNotCalculated, IsAlignas, 11906c3fb27SDimitry Andric IsRegularKeywordAttribute); 12006c3fb27SDimitry Andric } 12106c3fb27SDimitry Andric static Form Pragma() { return AS_Pragma; } 12206c3fb27SDimitry Andric static Form ContextSensitiveKeyword() { return AS_ContextSensitiveKeyword; } 123*0fca6ea1SDimitry Andric static Form HLSLAnnotation() { return AS_HLSLAnnotation; } 12406c3fb27SDimitry Andric static Form Implicit() { return AS_Implicit; } 12506c3fb27SDimitry Andric 12606c3fb27SDimitry Andric private: 12706c3fb27SDimitry Andric constexpr Form(Syntax SyntaxUsed) 12806c3fb27SDimitry Andric : SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingNotCalculated), 12906c3fb27SDimitry Andric IsAlignas(0), IsRegularKeywordAttribute(0) {} 13006c3fb27SDimitry Andric 1315f757f3fSDimitry Andric LLVM_PREFERRED_TYPE(Syntax) 13206c3fb27SDimitry Andric unsigned SyntaxUsed : 4; 13306c3fb27SDimitry Andric unsigned SpellingIndex : 4; 1345f757f3fSDimitry Andric LLVM_PREFERRED_TYPE(bool) 13506c3fb27SDimitry Andric unsigned IsAlignas : 1; 1365f757f3fSDimitry Andric LLVM_PREFERRED_TYPE(bool) 13706c3fb27SDimitry Andric unsigned IsRegularKeywordAttribute : 1; 13806c3fb27SDimitry Andric }; 139a7dea167SDimitry Andric 140a7dea167SDimitry Andric AttributeCommonInfo(const IdentifierInfo *AttrName, 141a7dea167SDimitry Andric const IdentifierInfo *ScopeName, SourceRange AttrRange, 14206c3fb27SDimitry Andric SourceLocation ScopeLoc, Kind AttrKind, Form FormUsed) 143a7dea167SDimitry Andric : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange), 14406c3fb27SDimitry Andric ScopeLoc(ScopeLoc), AttrKind(AttrKind), 14506c3fb27SDimitry Andric SyntaxUsed(FormUsed.getSyntax()), 14606c3fb27SDimitry Andric SpellingIndex(FormUsed.getSpellingIndex()), 14706c3fb27SDimitry Andric IsAlignas(FormUsed.isAlignas()), 14806c3fb27SDimitry Andric IsRegularKeywordAttribute(FormUsed.isRegularKeywordAttribute()) { 14906c3fb27SDimitry Andric assert(SyntaxUsed >= AS_GNU && SyntaxUsed <= AS_Implicit && 15006c3fb27SDimitry Andric "Invalid syntax!"); 15106c3fb27SDimitry Andric } 152a7dea167SDimitry Andric 153a7dea167SDimitry Andric AttributeCommonInfo(const IdentifierInfo *AttrName, 154a7dea167SDimitry Andric const IdentifierInfo *ScopeName, SourceRange AttrRange, 15506c3fb27SDimitry Andric SourceLocation ScopeLoc, Form FormUsed) 15606c3fb27SDimitry Andric : AttributeCommonInfo( 15706c3fb27SDimitry Andric AttrName, ScopeName, AttrRange, ScopeLoc, 15806c3fb27SDimitry Andric getParsedKind(AttrName, ScopeName, FormUsed.getSyntax()), 15906c3fb27SDimitry Andric FormUsed) {} 160a7dea167SDimitry Andric 161a7dea167SDimitry Andric AttributeCommonInfo(const IdentifierInfo *AttrName, SourceRange AttrRange, 16206c3fb27SDimitry Andric Form FormUsed) 16306c3fb27SDimitry Andric : AttributeCommonInfo(AttrName, nullptr, AttrRange, SourceLocation(), 16406c3fb27SDimitry Andric FormUsed) {} 165a7dea167SDimitry Andric 16606c3fb27SDimitry Andric AttributeCommonInfo(SourceRange AttrRange, Kind K, Form FormUsed) 16706c3fb27SDimitry Andric : AttributeCommonInfo(nullptr, nullptr, AttrRange, SourceLocation(), K, 16806c3fb27SDimitry Andric FormUsed) {} 169a7dea167SDimitry Andric 170a7dea167SDimitry Andric AttributeCommonInfo(AttributeCommonInfo &&) = default; 171a7dea167SDimitry Andric AttributeCommonInfo(const AttributeCommonInfo &) = default; 172a7dea167SDimitry Andric 173a7dea167SDimitry Andric Kind getParsedKind() const { return Kind(AttrKind); } 174a7dea167SDimitry Andric Syntax getSyntax() const { return Syntax(SyntaxUsed); } 17506c3fb27SDimitry Andric Form getForm() const { 17606c3fb27SDimitry Andric return Form(getSyntax(), SpellingIndex, IsAlignas, 17706c3fb27SDimitry Andric IsRegularKeywordAttribute); 17806c3fb27SDimitry Andric } 179a7dea167SDimitry Andric const IdentifierInfo *getAttrName() const { return AttrName; } 1805f757f3fSDimitry Andric void setAttrName(const IdentifierInfo *AttrNameII) { AttrName = AttrNameII; } 181a7dea167SDimitry Andric SourceLocation getLoc() const { return AttrRange.getBegin(); } 182a7dea167SDimitry Andric SourceRange getRange() const { return AttrRange; } 183a7dea167SDimitry Andric void setRange(SourceRange R) { AttrRange = R; } 184a7dea167SDimitry Andric 185a7dea167SDimitry Andric bool hasScope() const { return ScopeName; } 186a7dea167SDimitry Andric const IdentifierInfo *getScopeName() const { return ScopeName; } 187a7dea167SDimitry Andric SourceLocation getScopeLoc() const { return ScopeLoc; } 188a7dea167SDimitry Andric 1895ffd83dbSDimitry Andric /// Gets the normalized full name, which consists of both scope and name and 1905ffd83dbSDimitry Andric /// with surrounding underscores removed as appropriate (e.g. 1915ffd83dbSDimitry Andric /// __gnu__::__attr__ will be normalized to gnu::attr). 1925ffd83dbSDimitry Andric std::string getNormalizedFullName() const; 1935ffd83dbSDimitry Andric 194a7dea167SDimitry Andric bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; } 195a7dea167SDimitry Andric bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; } 196a7dea167SDimitry Andric 197a7dea167SDimitry Andric bool isGNUScope() const; 19881ad6265SDimitry Andric bool isClangScope() const; 199a7dea167SDimitry Andric 20006c3fb27SDimitry Andric bool isCXX11Attribute() const { return SyntaxUsed == AS_CXX11 || IsAlignas; } 201a7dea167SDimitry Andric 2025f757f3fSDimitry Andric bool isC23Attribute() const { return SyntaxUsed == AS_C23; } 2035f757f3fSDimitry Andric 2045f757f3fSDimitry Andric bool isAlignas() const { 2055f757f3fSDimitry Andric // FIXME: In the current state, the IsAlignas member variable is only true 2065f757f3fSDimitry Andric // with the C++ `alignas` keyword but not `_Alignas`. The following 2075f757f3fSDimitry Andric // expression works around the otherwise lost information so it will return 2085f757f3fSDimitry Andric // true for `alignas` or `_Alignas` while still returning false for things 2095f757f3fSDimitry Andric // like `__attribute__((aligned))`. 2105f757f3fSDimitry Andric return (getParsedKind() == AT_Aligned && isKeywordAttribute()); 2115f757f3fSDimitry Andric } 212a7dea167SDimitry Andric 213fe6060f1SDimitry Andric /// The attribute is spelled [[]] in either C or C++ mode, including standard 214fe6060f1SDimitry Andric /// attributes spelled with a keyword, like alignas. 215fe6060f1SDimitry Andric bool isStandardAttributeSyntax() const { 2165f757f3fSDimitry Andric return isCXX11Attribute() || isC23Attribute(); 217fe6060f1SDimitry Andric } 218fe6060f1SDimitry Andric 21981ad6265SDimitry Andric bool isGNUAttribute() const { return SyntaxUsed == AS_GNU; } 22081ad6265SDimitry Andric 221a7dea167SDimitry Andric bool isKeywordAttribute() const { 222a7dea167SDimitry Andric return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword; 223a7dea167SDimitry Andric } 224a7dea167SDimitry Andric 22506c3fb27SDimitry Andric bool isRegularKeywordAttribute() const { return IsRegularKeywordAttribute; } 22606c3fb27SDimitry Andric 227a7dea167SDimitry Andric bool isContextSensitiveKeywordAttribute() const { 228a7dea167SDimitry Andric return SyntaxUsed == AS_ContextSensitiveKeyword; 229a7dea167SDimitry Andric } 230a7dea167SDimitry Andric 231a7dea167SDimitry Andric unsigned getAttributeSpellingListIndex() const { 232a7dea167SDimitry Andric assert((isAttributeSpellingListCalculated() || AttrName) && 233a7dea167SDimitry Andric "Spelling cannot be found"); 234a7dea167SDimitry Andric return isAttributeSpellingListCalculated() 235a7dea167SDimitry Andric ? SpellingIndex 236a7dea167SDimitry Andric : calculateAttributeSpellingListIndex(); 237a7dea167SDimitry Andric } 238a7dea167SDimitry Andric void setAttributeSpellingListIndex(unsigned V) { SpellingIndex = V; } 239a7dea167SDimitry Andric 240a7dea167SDimitry Andric static Kind getParsedKind(const IdentifierInfo *Name, 241a7dea167SDimitry Andric const IdentifierInfo *Scope, Syntax SyntaxUsed); 242a7dea167SDimitry Andric 243a7dea167SDimitry Andric private: 244a7dea167SDimitry Andric /// Get an index into the attribute spelling list 245a7dea167SDimitry Andric /// defined in Attr.td. This index is used by an attribute 246a7dea167SDimitry Andric /// to pretty print itself. 247a7dea167SDimitry Andric unsigned calculateAttributeSpellingListIndex() const; 248a7dea167SDimitry Andric 249a7dea167SDimitry Andric friend class clang::ASTRecordWriter; 250a7dea167SDimitry Andric // Used exclusively by ASTDeclWriter to get the raw spelling list state. 251a7dea167SDimitry Andric unsigned getAttributeSpellingListIndexRaw() const { return SpellingIndex; } 252a7dea167SDimitry Andric 253a7dea167SDimitry Andric protected: 254a7dea167SDimitry Andric bool isAttributeSpellingListCalculated() const { 255a7dea167SDimitry Andric return SpellingIndex != SpellingNotCalculated; 256a7dea167SDimitry Andric } 257a7dea167SDimitry Andric }; 2587a6dacacSDimitry Andric 2597a6dacacSDimitry Andric inline bool doesKeywordAttributeTakeArgs(tok::TokenKind Kind) { 2607a6dacacSDimitry Andric switch (Kind) { 2617a6dacacSDimitry Andric default: 2627a6dacacSDimitry Andric return false; 2637a6dacacSDimitry Andric #define KEYWORD_ATTRIBUTE(NAME, HASARG, ...) \ 2647a6dacacSDimitry Andric case tok::kw_##NAME: \ 2657a6dacacSDimitry Andric return HASARG; 2667a6dacacSDimitry Andric #include "clang/Basic/RegularKeywordAttrInfo.inc" 2677a6dacacSDimitry Andric #undef KEYWORD_ATTRIBUTE 2687a6dacacSDimitry Andric } 2697a6dacacSDimitry Andric } 2707a6dacacSDimitry Andric 271a7dea167SDimitry Andric } // namespace clang 272a7dea167SDimitry Andric 273a7dea167SDimitry Andric #endif // LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H 274