diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:04:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:04:05 +0000 |
commit | 676fbe8105eeb6ff4bb2ed261cb212fcfdbe7b63 (patch) | |
tree | 02a1ac369cb734d0abfa5000dd86e5b7797e6a74 /include/clang/Basic/IdentifierTable.h | |
parent | c7e70c433efc6953dc3888b9fbf9f3512d7da2b0 (diff) |
Diffstat (limited to 'include/clang/Basic/IdentifierTable.h')
-rw-r--r-- | include/clang/Basic/IdentifierTable.h | 237 |
1 files changed, 144 insertions, 93 deletions
diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index c2e9c71b0f0d2..82e8c8c34951b 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -34,6 +34,8 @@ namespace clang { +class DeclarationName; +class DeclarationNameTable; class IdentifierInfo; class LangOptions; class MultiKeywordSelector; @@ -42,52 +44,91 @@ class SourceLocation; /// A simple pair of identifier info and location. using IdentifierLocPair = std::pair<IdentifierInfo *, SourceLocation>; +/// IdentifierInfo and other related classes are aligned to +/// 8 bytes so that DeclarationName can use the lower 3 bits +/// of a pointer to one of these classes. +enum { IdentifierInfoAlignment = 8 }; + /// One of these records is kept for each identifier that /// is lexed. This contains information about whether the token was \#define'd, /// is a language keyword, or if it is a front-end token of some sort (e.g. a /// variable or function name). The preprocessor keeps this information in a /// set, and all tok::identifier tokens have a pointer to one of these. -class IdentifierInfo { +/// It is aligned to 8 bytes because DeclarationName needs the lower 3 bits. +class alignas(IdentifierInfoAlignment) IdentifierInfo { friend class IdentifierTable; - unsigned TokenID : 9; // Front-end token ID or tok::identifier. - // Objective-C keyword ('protocol' in '@protocol') or builtin (__builtin_inf). - // First NUM_OBJC_KEYWORDS values are for Objective-C, the remaining values - // are for builtins. - unsigned ObjCOrBuiltinID :13; - bool HasMacro : 1; // True if there is a #define for this. - bool HadMacro : 1; // True if there was a #define for this. - bool IsExtension : 1; // True if identifier is a lang extension. - bool IsFutureCompatKeyword : 1; // True if identifier is a keyword in a - // newer Standard or proposed Standard. - bool IsPoisoned : 1; // True if identifier is poisoned. - bool IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword. - bool NeedsHandleIdentifier : 1; // See "RecomputeNeedsHandleIdentifier". - bool IsFromAST : 1; // True if identifier was loaded (at least - // partially) from an AST file. - bool ChangedAfterLoad : 1; // True if identifier has changed from the - // definition loaded from an AST file. - bool FEChangedAfterLoad : 1; // True if identifier's frontend information - // has changed from the definition loaded - // from an AST file. - bool RevertedTokenID : 1; // True if revertTokenIDToIdentifier was - // called. - bool OutOfDate : 1; // True if there may be additional - // information about this identifier - // stored externally. - bool IsModulesImport : 1; // True if this is the 'import' contextual - // keyword. - // 29 bit left in 64-bit word. + // Front-end token ID or tok::identifier. + unsigned TokenID : 9; + + // ObjC keyword ('protocol' in '@protocol') or builtin (__builtin_inf). + // First NUM_OBJC_KEYWORDS values are for Objective-C, + // the remaining values are for builtins. + unsigned ObjCOrBuiltinID : 13; + + // True if there is a #define for this. + unsigned HasMacro : 1; + + // True if there was a #define for this. + unsigned HadMacro : 1; + + // True if the identifier is a language extension. + unsigned IsExtension : 1; + + // True if the identifier is a keyword in a newer or proposed Standard. + unsigned IsFutureCompatKeyword : 1; + + // True if the identifier is poisoned. + unsigned IsPoisoned : 1; + + // True if the identifier is a C++ operator keyword. + unsigned IsCPPOperatorKeyword : 1; + + // Internal bit set by the member function RecomputeNeedsHandleIdentifier. + // See comment about RecomputeNeedsHandleIdentifier for more info. + unsigned NeedsHandleIdentifier : 1; + + // True if the identifier was loaded (at least partially) from an AST file. + unsigned IsFromAST : 1; + + // True if the identifier has changed from the definition + // loaded from an AST file. + unsigned ChangedAfterLoad : 1; + + // True if the identifier's frontend information has changed from the + // definition loaded from an AST file. + unsigned FEChangedAfterLoad : 1; + + // True if revertTokenIDToIdentifier was called. + unsigned RevertedTokenID : 1; + + // True if there may be additional information about + // this identifier stored externally. + unsigned OutOfDate : 1; + + // True if this is the 'import' contextual keyword. + unsigned IsModulesImport : 1; + + // 29 bits left in a 64-bit word. // Managed by the language front-end. void *FETokenInfo = nullptr; llvm::StringMapEntry<IdentifierInfo *> *Entry = nullptr; + IdentifierInfo() + : TokenID(tok::identifier), ObjCOrBuiltinID(0), HasMacro(false), + HadMacro(false), IsExtension(false), IsFutureCompatKeyword(false), + IsPoisoned(false), IsCPPOperatorKeyword(false), + NeedsHandleIdentifier(false), IsFromAST(false), ChangedAfterLoad(false), + FEChangedAfterLoad(false), RevertedTokenID(false), OutOfDate(false), + IsModulesImport(false) {} + public: - IdentifierInfo(); IdentifierInfo(const IdentifierInfo &) = delete; IdentifierInfo &operator=(const IdentifierInfo &) = delete; + IdentifierInfo(IdentifierInfo &&) = delete; + IdentifierInfo &operator=(IdentifierInfo &&) = delete; /// Return true if this is the identifier for the specified string. /// @@ -106,31 +147,10 @@ public: /// Return the beginning of the actual null-terminated string for this /// identifier. - const char *getNameStart() const { - if (Entry) return Entry->getKeyData(); - // FIXME: This is gross. It would be best not to embed specific details - // of the PTH file format here. - // The 'this' pointer really points to a - // std::pair<IdentifierInfo, const char*>, where internal pointer - // points to the external string data. - using actualtype = std::pair<IdentifierInfo, const char *>; - - return ((const actualtype*) this)->second; - } + const char *getNameStart() const { return Entry->getKeyData(); } /// Efficiently return the length of this identifier info. - unsigned getLength() const { - if (Entry) return Entry->getKeyLength(); - // FIXME: This is gross. It would be best not to embed specific details - // of the PTH file format here. - // The 'this' pointer really points to a - // std::pair<IdentifierInfo, const char*>, where internal pointer - // points to the external string data. - using actualtype = std::pair<IdentifierInfo, const char *>; - - const char* p = ((const actualtype*) this)->second - 2; - return (((unsigned) p[0]) | (((unsigned) p[1]) << 8)) - 1; - } + unsigned getLength() const { return Entry->getKeyLength(); } /// Return the actual identifier string. StringRef getName() const { @@ -284,10 +304,9 @@ public: /// language. bool isCPlusPlusKeyword(const LangOptions &LangOpts) const; - /// getFETokenInfo/setFETokenInfo - The language front-end is allowed to - /// associate arbitrary metadata with this token. - template<typename T> - T *getFETokenInfo() const { return static_cast<T*>(FETokenInfo); } + /// Get and set FETokenInfo. The language front-end is allowed to associate + /// arbitrary metadata with this token. + void *getFETokenInfo() const { return FETokenInfo; } void setFETokenInfo(void *T) { FETokenInfo = T; } /// Return true if the Preprocessor::HandleIdentifier must be called @@ -653,16 +672,22 @@ enum ObjCStringFormatFamily { /// accounts for 78% of all selectors in Cocoa.h. class Selector { friend class Diagnostic; + friend class SelectorTable; // only the SelectorTable can create these + friend class DeclarationName; // and the AST's DeclarationName. enum IdentifierInfoFlag { - // Empty selector = 0. - ZeroArg = 0x1, - OneArg = 0x2, - MultiArg = 0x3, - ArgFlags = ZeroArg|OneArg + // Empty selector = 0. Note that these enumeration values must + // correspond to the enumeration values of DeclarationName::StoredNameKind + ZeroArg = 0x01, + OneArg = 0x02, + MultiArg = 0x07, + ArgFlags = 0x07 }; - // a pointer to the MultiKeywordSelector or IdentifierInfo. + /// A pointer to the MultiKeywordSelector or IdentifierInfo. We use the low + /// three bits of InfoPtr to store an IdentifierInfoFlag. Note that in any + /// case IdentifierInfo and MultiKeywordSelector are already aligned to + /// 8 bytes even on 32 bits archs because of DeclarationName. uintptr_t InfoPtr = 0; Selector(IdentifierInfo *II, unsigned nArgs) { @@ -697,13 +722,10 @@ class Selector { static ObjCStringFormatFamily getStringFormatFamilyImpl(Selector sel); public: - friend class SelectorTable; // only the SelectorTable can create these - friend class DeclarationName; // and the AST's DeclarationName. - /// The default ctor should only be used when creating data structures that /// will contain selectors. Selector() = default; - Selector(uintptr_t V) : InfoPtr(V) {} + explicit Selector(uintptr_t V) : InfoPtr(V) {} /// operator==/!= - Indicate whether the specified selectors are identical. bool operator==(Selector RHS) const { @@ -832,39 +854,68 @@ public: static std::string getPropertyNameFromSetterSelector(Selector Sel); }; -/// DeclarationNameExtra - Common base of the MultiKeywordSelector, -/// CXXSpecialName, and CXXOperatorIdName classes, all of which are -/// private classes that describe different kinds of names. -class DeclarationNameExtra { -public: - /// ExtraKind - The kind of "extra" information stored in the - /// DeclarationName. See @c ExtraKindOrNumArgs for an explanation of - /// how these enumerator values are used. +namespace detail { + +/// DeclarationNameExtra is used as a base of various uncommon special names. +/// This class is needed since DeclarationName has not enough space to store +/// the kind of every possible names. Therefore the kind of common names is +/// stored directly in DeclarationName, and the kind of uncommon names is +/// stored in DeclarationNameExtra. It is aligned to 8 bytes because +/// DeclarationName needs the lower 3 bits to store the kind of common names. +/// DeclarationNameExtra is tightly coupled to DeclarationName and any change +/// here is very likely to require changes in DeclarationName(Table). +class alignas(IdentifierInfoAlignment) DeclarationNameExtra { + friend class clang::DeclarationName; + friend class clang::DeclarationNameTable; + +protected: + /// The kind of "extra" information stored in the DeclarationName. See + /// @c ExtraKindOrNumArgs for an explanation of how these enumerator values + /// are used. Note that DeclarationName depends on the numerical values + /// of the enumerators in this enum. See DeclarationName::StoredNameKind + /// for more info. enum ExtraKind { - CXXConstructor = 0, - CXXDestructor, - CXXConversionFunction, -#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ - CXXOperator##Name, -#include "clang/Basic/OperatorKinds.def" - CXXDeductionGuide, - CXXLiteralOperator, + CXXDeductionGuideName, + CXXLiteralOperatorName, CXXUsingDirective, - NUM_EXTRA_KINDS + ObjCMultiArgSelector }; - /// ExtraKindOrNumArgs - Either the kind of C++ special name or - /// operator-id (if the value is one of the CXX* enumerators of - /// ExtraKind), in which case the DeclarationNameExtra is also a - /// CXXSpecialName, (for CXXConstructor, CXXDestructor, or - /// CXXConversionFunction) CXXOperatorIdName, or CXXLiteralOperatorName, - /// it may be also name common to C++ using-directives (CXXUsingDirective), - /// otherwise it is NUM_EXTRA_KINDS+NumArgs, where NumArgs is the number of - /// arguments in the Objective-C selector, in which case the - /// DeclarationNameExtra is also a MultiKeywordSelector. + /// ExtraKindOrNumArgs has one of the following meaning: + /// * The kind of an uncommon C++ special name. This DeclarationNameExtra + /// is in this case in fact either a CXXDeductionGuideNameExtra or + /// a CXXLiteralOperatorIdName. + /// + /// * It may be also name common to C++ using-directives (CXXUsingDirective), + /// + /// * Otherwise it is ObjCMultiArgSelector+NumArgs, where NumArgs is + /// the number of arguments in the Objective-C selector, in which + /// case the DeclarationNameExtra is also a MultiKeywordSelector. unsigned ExtraKindOrNumArgs; + + DeclarationNameExtra(ExtraKind Kind) : ExtraKindOrNumArgs(Kind) {} + DeclarationNameExtra(unsigned NumArgs) + : ExtraKindOrNumArgs(ObjCMultiArgSelector + NumArgs) {} + + /// Return the corresponding ExtraKind. + ExtraKind getKind() const { + return static_cast<ExtraKind>(ExtraKindOrNumArgs > + (unsigned)ObjCMultiArgSelector + ? (unsigned)ObjCMultiArgSelector + : ExtraKindOrNumArgs); + } + + /// Return the number of arguments in an ObjC selector. Only valid when this + /// is indeed an ObjCMultiArgSelector. + unsigned getNumArgs() const { + assert(ExtraKindOrNumArgs >= (unsigned)ObjCMultiArgSelector && + "getNumArgs called but this is not an ObjC selector!"); + return ExtraKindOrNumArgs - (unsigned)ObjCMultiArgSelector; + } }; +} // namespace detail + } // namespace clang namespace llvm { |