[clang] [Clang][IdentifierInfo] Use llvm::Bitfield for the bitfield (PR #79366)
Bill Wendling via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 24 12:43:34 PST 2024
https://github.com/bwendling created https://github.com/llvm/llvm-project/pull/79366
llvm::Bitfield is a nicer way to represent bitfields in the compiler.
>From 047a96905b4169faf19de30d322943f46cd2fc2a Mon Sep 17 00:00:00 2001
From: Bill Wendling <morbo at google.com>
Date: Wed, 24 Jan 2024 12:09:28 -0800
Subject: [PATCH] [Clang][IdentifierInfo] Use llvm::Bitfield for the bitfield
llvm::Bitfield is a nicer way to represent bitfields in the compiler.
---
clang/include/clang/Basic/IdentifierTable.h | 335 +++++++++-----------
1 file changed, 155 insertions(+), 180 deletions(-)
diff --git a/clang/include/clang/Basic/IdentifierTable.h b/clang/include/clang/Basic/IdentifierTable.h
index 1ac182d4fce26f6..3dc54fee9d16723 100644
--- a/clang/include/clang/Basic/IdentifierTable.h
+++ b/clang/include/clang/Basic/IdentifierTable.h
@@ -18,6 +18,7 @@
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/TokenKinds.h"
+#include "llvm/ADT/Bitfields.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerIntPair.h"
@@ -109,102 +110,77 @@ static constexpr int FirstBuiltinID = LastInterestingIdentifierID + 1;
class alignas(IdentifierInfoAlignment) IdentifierInfo {
friend class IdentifierTable;
- // Front-end token ID or tok::identifier.
- LLVM_PREFERRED_TYPE(tok::TokenKind)
- 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 : ObjCOrBuiltinIDBits;
-
- // True if there is a #define for this.
- LLVM_PREFERRED_TYPE(bool)
- unsigned HasMacro : 1;
-
- // True if there was a #define for this.
- LLVM_PREFERRED_TYPE(bool)
- unsigned HadMacro : 1;
-
- // True if the identifier is a language extension.
- LLVM_PREFERRED_TYPE(bool)
- unsigned IsExtension : 1;
-
- // True if the identifier is a keyword in a newer or proposed Standard.
- LLVM_PREFERRED_TYPE(bool)
- unsigned IsFutureCompatKeyword : 1;
-
- // True if the identifier is poisoned.
- LLVM_PREFERRED_TYPE(bool)
- unsigned IsPoisoned : 1;
-
- // True if the identifier is a C++ operator keyword.
- LLVM_PREFERRED_TYPE(bool)
- unsigned IsCPPOperatorKeyword : 1;
-
- // Internal bit set by the member function RecomputeNeedsHandleIdentifier.
- // See comment about RecomputeNeedsHandleIdentifier for more info.
- LLVM_PREFERRED_TYPE(bool)
- unsigned NeedsHandleIdentifier : 1;
-
- // True if the identifier was loaded (at least partially) from an AST file.
- LLVM_PREFERRED_TYPE(bool)
- unsigned IsFromAST : 1;
-
- // True if the identifier has changed from the definition
- // loaded from an AST file.
- LLVM_PREFERRED_TYPE(bool)
- unsigned ChangedAfterLoad : 1;
-
- // True if the identifier's frontend information has changed from the
- // definition loaded from an AST file.
- LLVM_PREFERRED_TYPE(bool)
- unsigned FEChangedAfterLoad : 1;
-
- // True if revertTokenIDToIdentifier was called.
- LLVM_PREFERRED_TYPE(bool)
- unsigned RevertedTokenID : 1;
-
- // True if there may be additional information about
- // this identifier stored externally.
- LLVM_PREFERRED_TYPE(bool)
- unsigned OutOfDate : 1;
-
- // True if this is the 'import' contextual keyword.
- LLVM_PREFERRED_TYPE(bool)
- unsigned IsModulesImport : 1;
-
- // True if this is a mangled OpenMP variant name.
- LLVM_PREFERRED_TYPE(bool)
- unsigned IsMangledOpenMPVariantName : 1;
-
- // True if this is a deprecated macro.
- LLVM_PREFERRED_TYPE(bool)
- unsigned IsDeprecatedMacro : 1;
-
- // True if this macro is unsafe in headers.
- LLVM_PREFERRED_TYPE(bool)
- unsigned IsRestrictExpansion : 1;
-
- // True if this macro is final.
- LLVM_PREFERRED_TYPE(bool)
- unsigned IsFinal : 1;
-
- // 22 bits left in a 64-bit word.
+ // The fields in storage is currently:
+ //
+ // Bits 8-0 - Front-end token ID or tok::identifier.
+ // Bits 24-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.
+ // Bit 25 - True if there is a #define for the identifier.
+ // Bit 26 - True if there was a #define for the identifier.
+ // Bit 27 - True if the identifier is a language extension.
+ // Bit 28 - True if the identifier is a keyword in a newer or proposed
+ // Standard.
+ // Bit 29 - True if the identifier is poisoned.
+ // Bit 30 - True if the identifier is a C++ operator keyword.
+ // Bit 31 - Internal bit set by the member function
+ // RecomputeNeedsHandleIdentifier. See comment about
+ // RecomputeNeedsHandleIdentifier for more info.
+ // Bit 32 - True if the identifier was loaded (at least partially)
+ // from an AST file.
+ // Bit 33 - True if the identifier has changed from the definition
+ // loaded from an AST file.
+ // Bit 34 - True if the identifier's frontend information has changed
+ // from the definition loaded from an AST file.
+ // Bit 35 - True if revertTokenIDToIdentifier was called.
+ // Bit 36 - True if there may be additional information about this
+ // identifier stored externally.
+ // Bit 37 - True if this is the 'import' contextual keyword.
+ // Bit 38 - True if this is a mangled OpenMP variant name.
+ // Bit 39 - True if this is a deprecated macro.
+ // Bit 40 - True if this macro is unsafe in headers.
+ // Bit 41 - True if this macro is final.
+ //
+ // Bits 42-63 - Unused.
+
+ using Bitfield = llvm::Bitfield;
+
+ uint64_t Storage;
+
+ using TokenID = Bitfield::Element<tok::TokenKind, 0, 9, tok::NUM_TOKENS>;
+ using ObjCOrBuiltinID = Bitfield::Element<unsigned, 9, ObjCOrBuiltinIDBits>;
+ using HasMacro = Bitfield::Element<bool, 25, 1>;
+ using HadMacro = Bitfield::Element<bool, 26, 1>;
+ using IsExtension = Bitfield::Element<bool, 27, 1>;
+ using IsFutureCompatKeyword = Bitfield::Element<bool, 28, 1>;
+ using IsPoisoned = Bitfield::Element<bool, 29, 1>;
+ using IsCPPOperatorKeyword = Bitfield::Element<bool, 30, 1>;
+ using NeedsHandleIdentifier = Bitfield::Element<bool, 31, 1>;
+ using IsFromAST = Bitfield::Element<bool, 32, 1>;
+ using ChangedAfterLoad = Bitfield::Element<bool, 33, 1>;
+ using FEChangedAfterLoad = Bitfield::Element<bool, 34, 1>;
+ using RevertedTokenID = Bitfield::Element<bool, 35, 1>;
+ using OutOfDate = Bitfield::Element<bool, 36, 1>;
+ using IsModulesImport = Bitfield::Element<bool, 37, 1>;
+ using IsMangledOpenMPVariantName = Bitfield::Element<bool, 38, 1>;
+ using IsDeprecatedMacro = Bitfield::Element<bool, 39, 1>;
+ using IsRestrictExpansion = Bitfield::Element<bool, 40, 1>;
+ using IsFinal = Bitfield::Element<bool, 41, 1>;
+
+ // getter/setter for the Bitfields.
+ template <typename T> typename T::Type get() const {
+ return Bitfield::get<T>(Storage);
+ }
+ template <typename T> void set(typename T::Type Val) {
+ Bitfield::set<T>(Storage, Val);
+ }
// 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), IsMangledOpenMPVariantName(false),
- IsDeprecatedMacro(false), IsRestrictExpansion(false), IsFinal(false) {}
+ IdentifierInfo() : Storage(0) { set<TokenID>(tok::identifier); }
public:
IdentifierInfo(const IdentifierInfo &) = delete;
@@ -241,24 +217,23 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo {
/// Return true if this identifier is \#defined to some other value.
/// \note The current definition may be in a module and not currently visible.
- bool hasMacroDefinition() const {
- return HasMacro;
- }
+ bool hasMacroDefinition() const { return get<HasMacro>(); }
void setHasMacroDefinition(bool Val) {
- if (HasMacro == Val) return;
+ if (hasMacroDefinition() == Val)
+ return;
- HasMacro = Val;
+ set<HasMacro>(Val);
if (Val) {
- NeedsHandleIdentifier = true;
- HadMacro = true;
+ set<NeedsHandleIdentifier>(true);
+ set<HadMacro>(true);
} else {
// If this is a final macro, make the deprecation and header unsafe bits
// stick around after the undefinition so they apply to any redefinitions.
- if (!IsFinal) {
+ if (!isFinal()) {
// Because calling the setters of these calls recomputes, just set them
// manually to avoid recomputing a bunch of times.
- IsDeprecatedMacro = false;
- IsRestrictExpansion = false;
+ set<IsDeprecatedMacro>(false);
+ set<IsRestrictExpansion>(false);
}
RecomputeNeedsHandleIdentifier();
}
@@ -266,45 +241,43 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo {
/// Returns true if this identifier was \#defined to some value at any
/// moment. In this case there should be an entry for the identifier in the
/// macro history table in Preprocessor.
- bool hadMacroDefinition() const {
- return HadMacro;
- }
+ bool hadMacroDefinition() const { return get<HadMacro>(); }
- bool isDeprecatedMacro() const { return IsDeprecatedMacro; }
+ bool isDeprecatedMacro() const { return get<IsDeprecatedMacro>(); }
void setIsDeprecatedMacro(bool Val) {
- if (IsDeprecatedMacro == Val)
+ if (isDeprecatedMacro() == Val)
return;
- IsDeprecatedMacro = Val;
+ set<IsDeprecatedMacro>(Val);
if (Val)
- NeedsHandleIdentifier = true;
+ set<NeedsHandleIdentifier>(true);
else
RecomputeNeedsHandleIdentifier();
}
- bool isRestrictExpansion() const { return IsRestrictExpansion; }
+ bool isRestrictExpansion() const { return get<IsRestrictExpansion>(); }
void setIsRestrictExpansion(bool Val) {
- if (IsRestrictExpansion == Val)
+ if (isRestrictExpansion() == Val)
return;
- IsRestrictExpansion = Val;
+ set<IsRestrictExpansion>(Val);
if (Val)
- NeedsHandleIdentifier = true;
+ set<NeedsHandleIdentifier>(true);
else
RecomputeNeedsHandleIdentifier();
}
- bool isFinal() const { return IsFinal; }
+ bool isFinal() const { return get<IsFinal>(); }
+ void setIsFinal(bool Val) { set<IsFinal>(Val); }
- void setIsFinal(bool Val) { IsFinal = Val; }
-
- /// If this is a source-language token (e.g. 'for'), this API
- /// can be used to cause the lexer to map identifiers to source-language
+ /// get/setTokenID - If this is a source-language token (e.g. 'for'), this
+ /// API can be used to cause the lexer to map identifiers to source-language
/// tokens.
- tok::TokenKind getTokenID() const { return (tok::TokenKind)TokenID; }
+ tok::TokenKind getTokenID() const { return get<TokenID>(); }
+ void setTokenID(tok::TokenKind TK) { set<TokenID>(TK); }
/// True if revertTokenIDToIdentifier() was called.
- bool hasRevertedTokenIDToIdentifier() const { return RevertedTokenID; }
+ bool hasRevertedTokenIDToIdentifier() const { return get<RevertedTokenID>(); }
/// Revert TokenID to tok::identifier; used for GNU libstdc++ 4.2
/// compatibility.
@@ -313,14 +286,14 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo {
/// to tok::identifier for libstdc++ 4.2. Keep track of when this happens
/// using this method so we can inform serialization about it.
void revertTokenIDToIdentifier() {
- assert(TokenID != tok::identifier && "Already at tok::identifier");
- TokenID = tok::identifier;
- RevertedTokenID = true;
+ assert(getTokenID() != tok::identifier && "Already at tok::identifier");
+ setTokenID(tok::identifier);
+ set<RevertedTokenID>(true);
}
void revertIdentifierToTokenID(tok::TokenKind TK) {
- assert(TokenID == tok::identifier && "Should be at tok::identifier");
- TokenID = TK;
- RevertedTokenID = false;
+ assert(getTokenID() == tok::identifier && "Should be at tok::identifier");
+ setTokenID(TK);
+ set<RevertedTokenID>(false);
}
/// Return the preprocessor keyword ID for this identifier.
@@ -334,54 +307,54 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo {
tok::ObjCKeywordKind getObjCKeywordID() const {
static_assert(FirstObjCKeywordID == 1,
"hard-coding this assumption to simplify code");
- if (ObjCOrBuiltinID <= LastObjCKeywordID)
- return tok::ObjCKeywordKind(ObjCOrBuiltinID);
- else
- return tok::objc_not_keyword;
+ if (getObjCOrBuiltinID() <= LastObjCKeywordID)
+ return static_cast<tok::ObjCKeywordKind>(getObjCOrBuiltinID());
+ return tok::objc_not_keyword;
}
- void setObjCKeywordID(tok::ObjCKeywordKind ID) { ObjCOrBuiltinID = ID; }
+ void setObjCKeywordID(tok::ObjCKeywordKind ID) { set<ObjCOrBuiltinID>(ID); }
/// Return a value indicating whether this is a builtin function.
///
/// 0 is not-built-in. 1+ are specific builtin functions.
unsigned getBuiltinID() const {
- if (ObjCOrBuiltinID >= FirstBuiltinID)
- return 1 + (ObjCOrBuiltinID - FirstBuiltinID);
- else
- return 0;
+ if (getObjCOrBuiltinID() >= FirstBuiltinID)
+ return 1 + (getObjCOrBuiltinID() - FirstBuiltinID);
+ return 0;
}
void setBuiltinID(unsigned ID) {
assert(ID != 0);
- ObjCOrBuiltinID = FirstBuiltinID + (ID - 1);
+ setObjCOrBuiltinID(FirstBuiltinID + (ID - 1));
assert(getBuiltinID() == ID && "ID too large for field!");
}
- void clearBuiltinID() { ObjCOrBuiltinID = 0; }
+ void clearBuiltinID() { setObjCOrBuiltinID(tok::objc_not_keyword); }
tok::InterestingIdentifierKind getInterestingIdentifierID() const {
- if (ObjCOrBuiltinID >= FirstInterestingIdentifierID &&
- ObjCOrBuiltinID <= LastInterestingIdentifierID)
+ if (getObjCOrBuiltinID() >= FirstInterestingIdentifierID &&
+ getObjCOrBuiltinID() <= LastInterestingIdentifierID)
return tok::InterestingIdentifierKind(
- 1 + (ObjCOrBuiltinID - FirstInterestingIdentifierID));
+ 1 + (getObjCOrBuiltinID() - FirstInterestingIdentifierID));
else
return tok::not_interesting;
}
void setInterestingIdentifierID(unsigned ID) {
assert(ID != tok::not_interesting);
- ObjCOrBuiltinID = FirstInterestingIdentifierID + (ID - 1);
+ setObjCOrBuiltinID(FirstInterestingIdentifierID + (ID - 1));
assert(getInterestingIdentifierID() == ID && "ID too large for field!");
}
- unsigned getObjCOrBuiltinID() const { return ObjCOrBuiltinID; }
- void setObjCOrBuiltinID(unsigned ID) { ObjCOrBuiltinID = ID; }
+ unsigned getObjCOrBuiltinID() const { return get<ObjCOrBuiltinID>(); }
+ void setObjCOrBuiltinID(unsigned ID) {
+ set<ObjCOrBuiltinID>(static_cast<tok::ObjCKeywordKind>(ID));
+ }
- /// get/setExtension - Initialize information about whether or not this
+ /// is/setExtension - Initialize information about whether or not this
/// language token is an extension. This controls extension warnings, and is
/// only valid if a custom token ID is set.
- bool isExtensionToken() const { return IsExtension; }
+ bool isExtensionToken() const { return get<IsExtension>(); }
void setIsExtensionToken(bool Val) {
- IsExtension = Val;
+ set<IsExtension>(Val);
if (Val)
- NeedsHandleIdentifier = true;
+ set<NeedsHandleIdentifier>(true);
else
RecomputeNeedsHandleIdentifier();
}
@@ -391,34 +364,35 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo {
/// controls compatibility warnings, and is only true when not parsing the
/// corresponding Standard. Once a compatibility problem has been diagnosed
/// with this keyword, the flag will be cleared.
- bool isFutureCompatKeyword() const { return IsFutureCompatKeyword; }
+ bool isFutureCompatKeyword() const { return get<IsFutureCompatKeyword>(); }
void setIsFutureCompatKeyword(bool Val) {
- IsFutureCompatKeyword = Val;
+ set<IsFutureCompatKeyword>(Val);
if (Val)
- NeedsHandleIdentifier = true;
+ set<NeedsHandleIdentifier>(true);
else
RecomputeNeedsHandleIdentifier();
}
- /// setIsPoisoned - Mark this identifier as poisoned. After poisoning, the
- /// Preprocessor will emit an error every time this token is used.
+ /// is/setIsPoisoned - Controls whether this identifier is poisoned. After
+ /// poisoning, the Preprocessor will emit an error every time this token is
+ /// used.
+ bool isPoisoned() const { return get<IsPoisoned>(); }
void setIsPoisoned(bool Value = true) {
- IsPoisoned = Value;
+ set<IsPoisoned>(Value);
if (Value)
- NeedsHandleIdentifier = true;
+ set<NeedsHandleIdentifier>(true);
else
RecomputeNeedsHandleIdentifier();
}
- /// Return true if this token has been poisoned.
- bool isPoisoned() const { return IsPoisoned; }
-
/// isCPlusPlusOperatorKeyword/setIsCPlusPlusOperatorKeyword controls whether
/// this identifier is a C++ alternate representation of an operator.
+ bool isCPlusPlusOperatorKeyword() const {
+ return get<IsCPPOperatorKeyword>();
+ }
void setIsCPlusPlusOperatorKeyword(bool Val = true) {
- IsCPPOperatorKeyword = Val;
+ set<IsCPPOperatorKeyword>(Val);
}
- bool isCPlusPlusOperatorKeyword() const { return IsCPPOperatorKeyword; }
/// Return true if this token is a keyword in the specified language.
bool isKeyword(const LangOptions &LangOpts) const;
@@ -437,69 +411,70 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo {
///
/// If this returns false, we know that HandleIdentifier will not affect
/// the token.
- bool isHandleIdentifierCase() const { return NeedsHandleIdentifier; }
+ bool isHandleIdentifierCase() const { return get<NeedsHandleIdentifier>(); }
/// Return true if the identifier in its current state was loaded
/// from an AST file.
- bool isFromAST() const { return IsFromAST; }
-
- void setIsFromAST() { IsFromAST = true; }
+ bool isFromAST() const { return get<IsFromAST>(); }
+ void setIsFromAST() { set<IsFromAST>(true); }
/// Determine whether this identifier has changed since it was loaded
/// from an AST file.
bool hasChangedSinceDeserialization() const {
- return ChangedAfterLoad;
+ return get<ChangedAfterLoad>();
}
/// Note that this identifier has changed since it was loaded from
/// an AST file.
- void setChangedSinceDeserialization() {
- ChangedAfterLoad = true;
- }
+ void setChangedSinceDeserialization() { set<ChangedAfterLoad>(true); }
/// Determine whether the frontend token information for this
/// identifier has changed since it was loaded from an AST file.
bool hasFETokenInfoChangedSinceDeserialization() const {
- return FEChangedAfterLoad;
+ return get<FEChangedAfterLoad>();
}
/// Note that the frontend token information for this identifier has
/// changed since it was loaded from an AST file.
void setFETokenInfoChangedSinceDeserialization() {
- FEChangedAfterLoad = true;
+ set<FEChangedAfterLoad>(true);
}
/// Determine whether the information for this identifier is out of
/// date with respect to the external source.
- bool isOutOfDate() const { return OutOfDate; }
+ bool isOutOfDate() const { return get<OutOfDate>(); }
/// Set whether the information for this identifier is out of
/// date with respect to the external source.
void setOutOfDate(bool OOD) {
- OutOfDate = OOD;
+ set<OutOfDate>(OOD);
if (OOD)
- NeedsHandleIdentifier = true;
+ set<NeedsHandleIdentifier>(true);
else
RecomputeNeedsHandleIdentifier();
}
/// Determine whether this is the contextual keyword \c import.
- bool isModulesImport() const { return IsModulesImport; }
+ bool isModulesImport() const { return get<IsModulesImport>(); }
/// Set whether this identifier is the contextual keyword \c import.
void setModulesImport(bool I) {
- IsModulesImport = I;
+ set<IsModulesImport>(I);
if (I)
- NeedsHandleIdentifier = true;
+ set<NeedsHandleIdentifier>(true);
else
RecomputeNeedsHandleIdentifier();
}
/// Determine whether this is the mangled name of an OpenMP variant.
- bool isMangledOpenMPVariantName() const { return IsMangledOpenMPVariantName; }
+ bool isMangledOpenMPVariantName() const {
+ return get<IsMangledOpenMPVariantName>();
+ }
/// Set whether this is the mangled name of an OpenMP variant.
- void setMangledOpenMPVariantName(bool I) { IsMangledOpenMPVariantName = I; }
+ void setMangledOpenMPVariantName(bool I) {
+ set<IsMangledOpenMPVariantName>(I);
+ }
/// Return true if this identifier is an editor placeholder.
///
@@ -542,9 +517,9 @@ class alignas(IdentifierInfoAlignment) IdentifierInfo {
/// This method is very tied to the definition of HandleIdentifier. Any
/// change to it should be reflected here.
void RecomputeNeedsHandleIdentifier() {
- NeedsHandleIdentifier = isPoisoned() || hasMacroDefinition() ||
- isExtensionToken() || isFutureCompatKeyword() ||
- isOutOfDate() || isModulesImport();
+ set<NeedsHandleIdentifier>(isPoisoned() || hasMacroDefinition() ||
+ isExtensionToken() || isFutureCompatKeyword() ||
+ isOutOfDate() || isModulesImport());
}
};
@@ -686,8 +661,8 @@ class IdentifierTable {
IdentifierInfo &get(StringRef Name, tok::TokenKind TokenCode) {
IdentifierInfo &II = get(Name);
- II.TokenID = TokenCode;
- assert(II.TokenID == (unsigned) TokenCode && "TokenCode too large");
+ II.setTokenID(TokenCode);
+ assert(II.getTokenID() == TokenCode && "TokenCode too large");
return II;
}
More information about the cfe-commits
mailing list