summaryrefslogtreecommitdiff
path: root/include/clang/Basic/IdentifierTable.h
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:04:05 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:04:05 +0000
commit676fbe8105eeb6ff4bb2ed261cb212fcfdbe7b63 (patch)
tree02a1ac369cb734d0abfa5000dd86e5b7797e6a74 /include/clang/Basic/IdentifierTable.h
parentc7e70c433efc6953dc3888b9fbf9f3512d7da2b0 (diff)
Diffstat (limited to 'include/clang/Basic/IdentifierTable.h')
-rw-r--r--include/clang/Basic/IdentifierTable.h237
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 {