Viewing file: AttributeCommonInfo.h (9.6 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
//======- AttributeCommonInfo.h - Base info about Attributes-----*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file defines the AttributeCommonInfo type, which is the base for a // ParsedAttr and is used by Attr as a way to share info between the two. // //===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H #define LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
#include "clang/Basic/SourceLocation.h" #include "clang/Basic/TokenKinds.h"
namespace clang {
class ASTRecordWriter; class IdentifierInfo;
class AttributeCommonInfo { public: /// The style used to specify an attribute. enum Syntax { /// __attribute__((...)) AS_GNU = 1,
/// [[...]] AS_CXX11,
/// [[...]] AS_C23,
/// __declspec(...) AS_Declspec,
/// [uuid("...")] class Foo AS_Microsoft,
/// __ptr16, alignas(...), etc. AS_Keyword,
/// #pragma ... AS_Pragma,
// Note TableGen depends on the order above. Do not add or change the order // without adding related code to TableGen/ClangAttrEmitter.cpp. /// Context-sensitive version of a keyword attribute. AS_ContextSensitiveKeyword,
/// <vardecl> : <annotation> AS_HLSLAnnotation,
/// The attibute has no source code manifestation and is only created /// implicitly. AS_Implicit }; enum Kind { #define PARSED_ATTR(NAME) AT_##NAME, #include "clang/Sema/AttrParsedAttrList.inc" #undef PARSED_ATTR NoSemaHandlerAttribute, IgnoredAttribute, UnknownAttribute, };
private: const IdentifierInfo *AttrName = nullptr; const IdentifierInfo *ScopeName = nullptr; SourceRange AttrRange; const SourceLocation ScopeLoc; // Corresponds to the Kind enum. LLVM_PREFERRED_TYPE(Kind) unsigned AttrKind : 16; /// Corresponds to the Syntax enum. LLVM_PREFERRED_TYPE(Syntax) unsigned SyntaxUsed : 4; LLVM_PREFERRED_TYPE(bool) unsigned SpellingIndex : 4; LLVM_PREFERRED_TYPE(bool) unsigned IsAlignas : 1; LLVM_PREFERRED_TYPE(bool) unsigned IsRegularKeywordAttribute : 1;
protected: static constexpr unsigned SpellingNotCalculated = 0xf;
public: /// Combines information about the source-code form of an attribute, /// including its syntax and spelling. class Form { public: constexpr Form(Syntax SyntaxUsed, unsigned SpellingIndex, bool IsAlignas, bool IsRegularKeywordAttribute) : SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingIndex), IsAlignas(IsAlignas), IsRegularKeywordAttribute(IsRegularKeywordAttribute) {} constexpr Form(tok::TokenKind Tok) : SyntaxUsed(AS_Keyword), SpellingIndex(SpellingNotCalculated), IsAlignas(Tok == tok::kw_alignas), IsRegularKeywordAttribute(tok::isRegularKeywordAttribute(Tok)) {}
Syntax getSyntax() const { return Syntax(SyntaxUsed); } unsigned getSpellingIndex() const { return SpellingIndex; } bool isAlignas() const { return IsAlignas; } bool isRegularKeywordAttribute() const { return IsRegularKeywordAttribute; }
static Form GNU() { return AS_GNU; } static Form CXX11() { return AS_CXX11; } static Form C23() { return AS_C23; } static Form Declspec() { return AS_Declspec; } static Form Microsoft() { return AS_Microsoft; } static Form Keyword(bool IsAlignas, bool IsRegularKeywordAttribute) { return Form(AS_Keyword, SpellingNotCalculated, IsAlignas, IsRegularKeywordAttribute); } static Form Pragma() { return AS_Pragma; } static Form ContextSensitiveKeyword() { return AS_ContextSensitiveKeyword; } static Form HLSLAnnotation() { return AS_HLSLAnnotation; } static Form Implicit() { return AS_Implicit; }
private: constexpr Form(Syntax SyntaxUsed) : SyntaxUsed(SyntaxUsed), SpellingIndex(SpellingNotCalculated), IsAlignas(0), IsRegularKeywordAttribute(0) {}
LLVM_PREFERRED_TYPE(Syntax) unsigned SyntaxUsed : 4; unsigned SpellingIndex : 4; LLVM_PREFERRED_TYPE(bool) unsigned IsAlignas : 1; LLVM_PREFERRED_TYPE(bool) unsigned IsRegularKeywordAttribute : 1; };
AttributeCommonInfo(const IdentifierInfo *AttrName, const IdentifierInfo *ScopeName, SourceRange AttrRange, SourceLocation ScopeLoc, Kind AttrKind, Form FormUsed) : AttrName(AttrName), ScopeName(ScopeName), AttrRange(AttrRange), ScopeLoc(ScopeLoc), AttrKind(AttrKind), SyntaxUsed(FormUsed.getSyntax()), SpellingIndex(FormUsed.getSpellingIndex()), IsAlignas(FormUsed.isAlignas()), IsRegularKeywordAttribute(FormUsed.isRegularKeywordAttribute()) { assert(SyntaxUsed >= AS_GNU && SyntaxUsed <= AS_Implicit && "Invalid syntax!"); }
AttributeCommonInfo(const IdentifierInfo *AttrName, const IdentifierInfo *ScopeName, SourceRange AttrRange, SourceLocation ScopeLoc, Form FormUsed) : AttributeCommonInfo( AttrName, ScopeName, AttrRange, ScopeLoc, getParsedKind(AttrName, ScopeName, FormUsed.getSyntax()), FormUsed) {}
AttributeCommonInfo(const IdentifierInfo *AttrName, SourceRange AttrRange, Form FormUsed) : AttributeCommonInfo(AttrName, nullptr, AttrRange, SourceLocation(), FormUsed) {}
AttributeCommonInfo(SourceRange AttrRange, Kind K, Form FormUsed) : AttributeCommonInfo(nullptr, nullptr, AttrRange, SourceLocation(), K, FormUsed) {}
AttributeCommonInfo(AttributeCommonInfo &&) = default; AttributeCommonInfo(const AttributeCommonInfo &) = default;
Kind getParsedKind() const { return Kind(AttrKind); } Syntax getSyntax() const { return Syntax(SyntaxUsed); } Form getForm() const { return Form(getSyntax(), SpellingIndex, IsAlignas, IsRegularKeywordAttribute); } const IdentifierInfo *getAttrName() const { return AttrName; } void setAttrName(const IdentifierInfo *AttrNameII) { AttrName = AttrNameII; } SourceLocation getLoc() const { return AttrRange.getBegin(); } SourceRange getRange() const { return AttrRange; } void setRange(SourceRange R) { AttrRange = R; }
bool hasScope() const { return ScopeName; } const IdentifierInfo *getScopeName() const { return ScopeName; } SourceLocation getScopeLoc() const { return ScopeLoc; }
/// Gets the normalized full name, which consists of both scope and name and /// with surrounding underscores removed as appropriate (e.g. /// __gnu__::__attr__ will be normalized to gnu::attr). std::string getNormalizedFullName() const;
bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; } bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; }
bool isGNUScope() const; bool isClangScope() const;
bool isCXX11Attribute() const { return SyntaxUsed == AS_CXX11 || IsAlignas; }
bool isC23Attribute() const { return SyntaxUsed == AS_C23; }
bool isAlignas() const { // FIXME: In the current state, the IsAlignas member variable is only true // with the C++ `alignas` keyword but not `_Alignas`. The following // expression works around the otherwise lost information so it will return // true for `alignas` or `_Alignas` while still returning false for things // like `__attribute__((aligned))`. return (getParsedKind() == AT_Aligned && isKeywordAttribute()); }
/// The attribute is spelled [[]] in either C or C++ mode, including standard /// attributes spelled with a keyword, like alignas. bool isStandardAttributeSyntax() const { return isCXX11Attribute() || isC23Attribute(); }
bool isGNUAttribute() const { return SyntaxUsed == AS_GNU; }
bool isKeywordAttribute() const { return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword; }
bool isRegularKeywordAttribute() const { return IsRegularKeywordAttribute; }
bool isContextSensitiveKeywordAttribute() const { return SyntaxUsed == AS_ContextSensitiveKeyword; }
unsigned getAttributeSpellingListIndex() const { assert((isAttributeSpellingListCalculated() || AttrName) && "Spelling cannot be found"); return isAttributeSpellingListCalculated() ? SpellingIndex : calculateAttributeSpellingListIndex(); } void setAttributeSpellingListIndex(unsigned V) { SpellingIndex = V; }
static Kind getParsedKind(const IdentifierInfo *Name, const IdentifierInfo *Scope, Syntax SyntaxUsed);
private: /// Get an index into the attribute spelling list /// defined in Attr.td. This index is used by an attribute /// to pretty print itself. unsigned calculateAttributeSpellingListIndex() const;
friend class clang::ASTRecordWriter; // Used exclusively by ASTDeclWriter to get the raw spelling list state. unsigned getAttributeSpellingListIndexRaw() const { return SpellingIndex; }
protected: bool isAttributeSpellingListCalculated() const { return SpellingIndex != SpellingNotCalculated; } };
inline bool doesKeywordAttributeTakeArgs(tok::TokenKind Kind) { switch (Kind) { default: return false; #define KEYWORD_ATTRIBUTE(NAME, HASARG, ...) \ case tok::kw_##NAME: \ return HASARG; #include "clang/Basic/RegularKeywordAttrInfo.inc" #undef KEYWORD_ATTRIBUTE } }
} // namespace clang
#endif // LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H
|