diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 66d8b967ac10af832bf6c68a91fb8adaffba2e66..8a5efb30b1664e86a1c079e1965d3e2a8b50c9d1 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -285,7 +285,7 @@ void ETSAnalyzer::CheckMethodModifiers(ir::MethodDefinition *node) const auto const notValidInAbstract = ir::ModifierFlags::NATIVE | ir::ModifierFlags::PRIVATE | ir::ModifierFlags::OVERRIDE | ir::ModifierFlags::FINAL | ir::ModifierFlags::STATIC; - if (node->IsAbstract() && (node->flags_ & notValidInAbstract) != 0U) { + if (node->IsAbstract() && (static_cast(node->bitFields_.flags_) & notValidInAbstract) != 0U) { checker->LogError(diagnostic::ABSTRACT_METHOD_INVALID_MODIFIER, {}, node->Start()); node->SetTsType(checker->GlobalTypeError()); return; @@ -300,14 +300,14 @@ void ETSAnalyzer::CheckMethodModifiers(ir::MethodDefinition *node) const auto const notValidInFinal = ir::ModifierFlags::ABSTRACT | ir::ModifierFlags::STATIC; - if (node->IsFinal() && (node->flags_ & notValidInFinal) != 0U) { + if (node->IsFinal() && (static_cast(node->bitFields_.flags_) & notValidInFinal) != 0U) { checker->LogError(diagnostic::FINAL_METHOD_INVALID_MODIFIER, {}, node->Start()); node->SetTsType(checker->GlobalTypeError()); } auto const notValidInStatic = ir::ModifierFlags::ABSTRACT | ir::ModifierFlags::FINAL | ir::ModifierFlags::OVERRIDE; - if (node->IsStatic() && (node->flags_ & notValidInStatic) != 0U) { + if (node->IsStatic() && (static_cast(node->bitFields_.flags_) & notValidInStatic) != 0U) { checker->LogError(diagnostic::STATIC_METHOD_INVALID_MODIFIER, {}, node->Start()); node->SetTsType(checker->GlobalTypeError()); } diff --git a/ets2panda/ir/astNode.cpp b/ets2panda/ir/astNode.cpp index 811496115396c1ea9419798713265ad6ff4134b0..daf2c3587f4329cc93d478861c9b27e234ce45fe 100644 --- a/ets2panda/ir/astNode.cpp +++ b/ets2panda/ir/astNode.cpp @@ -26,12 +26,12 @@ AstNode::AstNode(AstNode const &other) { auto otherHistoryNode = other.GetHistoryNode(); range_ = otherHistoryNode->range_; - type_ = otherHistoryNode->type_; + bitFields_.type_ = otherHistoryNode->bitFields_.type_; if (otherHistoryNode->variable_ != nullptr) { variable_ = otherHistoryNode->variable_; } - flags_ = otherHistoryNode->flags_; - astNodeFlags_ = otherHistoryNode->astNodeFlags_; + bitFields_.flags_ = otherHistoryNode->bitFields_.flags_; + bitFields_.astNodeFlags_ = otherHistoryNode->bitFields_.astNodeFlags_; // boxing_unboxing_flags_ {}; leave default value! } @@ -68,7 +68,7 @@ AstNode::AstNode(AstNode const &other) return GetHistoryNode()->parent_->HasExportAlias(); } - return (GetHistoryNode()->astNodeFlags_ & AstNodeFlags::HAS_EXPORT_ALIAS) != 0; + return (static_cast(GetHistoryNode()->bitFields_.astNodeFlags_) & AstNodeFlags::HAS_EXPORT_ALIAS) != 0; } bool AstNode::IsScopeBearer() const noexcept @@ -223,12 +223,12 @@ AstNode *AstNode::ShallowClone(ArenaAllocator *allocator) void AstNode::CopyTo(AstNode *other) const { - ES2PANDA_ASSERT(other->type_ == type_); + ES2PANDA_ASSERT(static_cast(other->bitFields_.type_) == static_cast(bitFields_.type_)); other->parent_ = parent_; other->range_ = range_; - other->flags_ = flags_; - other->astNodeFlags_ = astNodeFlags_; + other->bitFields_.flags_ = bitFields_.flags_; + other->bitFields_.astNodeFlags_ = bitFields_.astNodeFlags_; other->history_ = history_; other->variable_ = variable_; other->originalNode_ = originalNode_; @@ -286,14 +286,14 @@ AstNode *AstNode::GetOrCreateHistoryNode() const void AstNode::AddModifier(ModifierFlags const flags) noexcept { if (!All(Modifiers(), flags)) { - GetOrCreateHistoryNode()->flags_ |= flags; + GetOrCreateHistoryNode()->bitFields_.flags_ |= static_cast(flags); } } void AstNode::ClearModifier(ModifierFlags const flags) noexcept { if (Any(Modifiers(), flags)) { - GetOrCreateHistoryNode()->flags_ &= ~flags; + GetOrCreateHistoryNode()->bitFields_.flags_ &= ~static_cast(flags); } } diff --git a/ets2panda/ir/astNode.h b/ets2panda/ir/astNode.h index b81ef364ad381aaab1a77ee2a2fdb963f7f93faa..a014d5dd25e061643a0787feb5b31c39666f000a 100644 --- a/ets2panda/ir/astNode.h +++ b/ets2panda/ir/astNode.h @@ -134,8 +134,8 @@ AST_NODE_REINTERPRET_MAPPING(DECLARE_CLASSES) class AstNode { public: - explicit AstNode(AstNodeType type) : type_(type) {}; - explicit AstNode(AstNodeType type, ModifierFlags flags) : flags_(flags), type_(type) {}; + explicit AstNode(AstNodeType type) : bitFields_{0, 0, static_cast(type)} {}; + explicit AstNode(AstNodeType type, ModifierFlags flags) : bitFields_{static_cast(flags), 0, static_cast(type)} {}; virtual ~AstNode() = default; AstNode() = delete; @@ -152,7 +152,7 @@ public: { \ /* CC-OFFNXT(G.PRE.02) name part*/ \ /* CC-OFFNXT(G.PRE.05) The macro is used to generate a function. Return is needed */ \ - return GetHistoryNode()->type_ == AstNodeType::nodeType; /* CC-OFF(G.PRE.02) name part*/ \ + return static_cast(GetHistoryNode()->bitFields_.type_) == AstNodeType::nodeType; /* CC-OFF(G.PRE.02) name part*/ \ } AST_NODE_MAPPING(DECLARE_IS_CHECKS) #undef DECLARE_IS_CHECKS @@ -162,12 +162,12 @@ public: bool Is##baseClass() const \ { \ /* CC-OFFNXT(G.PRE.05) The macro is used to generate a function. Return is needed */ \ - return GetHistoryNode()->type_ == AstNodeType::nodeType1; /* CC-OFF(G.PRE.02) name part*/ \ + return static_cast(GetHistoryNode()->bitFields_.type_) == AstNodeType::nodeType1; /* CC-OFF(G.PRE.02) name part*/ \ } \ bool Is##reinterpretClass() const \ { \ /* CC-OFFNXT(G.PRE.05) The macro is used to generate a function. Return is needed */ \ - return GetHistoryNode()->type_ == AstNodeType::nodeType2; /* CC-OFF(G.PRE.02) name part*/ \ + return static_cast(GetHistoryNode()->bitFields_.type_) == AstNodeType::nodeType2; /* CC-OFF(G.PRE.02) name part*/ \ } AST_NODE_REINTERPRET_MAPPING(DECLARE_IS_CHECKS) #undef DECLARE_IS_CHECKS @@ -329,7 +329,7 @@ public: [[nodiscard]] AstNodeType Type() const noexcept { - return GetHistoryNode()->type_; + return static_cast(GetHistoryNode()->bitFields_.type_); } [[nodiscard]] AstNode *Parent() noexcept @@ -485,12 +485,12 @@ public: [[nodiscard]] ModifierFlags Modifiers() noexcept { - return GetHistoryNode()->flags_; + return static_cast(GetHistoryNode()->bitFields_.flags_); } [[nodiscard]] ModifierFlags Modifiers() const noexcept { - return GetHistoryNode()->flags_; + return static_cast(GetHistoryNode()->bitFields_.flags_); } [[nodiscard]] bool HasExportAlias() const noexcept; @@ -532,6 +532,45 @@ public: DECLARE_FLAG_OPERATIONS(AstNodeFlags, astNodeFlags_); #undef DECLARE_FLAG_OPERATIONS + // CC-OFFNXT(G.PRE.06) solid logic + // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define DECLARE_BITFIELD_FLAG_OPERATIONS(flag_type, member_name) \ + void Set##flag_type(flag_type flags) const noexcept \ + { \ + if (static_cast(GetHistoryNode()->member_name) != flags) { \ + GetOrCreateHistoryNode()->member_name = static_cast(flags); \ + } \ + } \ + \ + void Add##flag_type(flag_type flag) const noexcept \ + { \ + if (!All(static_cast(GetHistoryNode()->member_name), flag)) { \ + GetOrCreateHistoryNode()->member_name |= static_cast(flag); \ + } \ + } \ + \ + [[nodiscard]] flag_type Get##flag_type() const noexcept \ + { \ + /* CC-OFFNXT(G.PRE.05) The macro is used to generate a function. Return is needed*/ \ + return static_cast(GetHistoryNode()->member_name); \ + } \ + \ + bool Has##flag_type(flag_type flag) const noexcept \ + { \ + /* CC-OFFNXT(G.PRE.05) The macro is used to generate a function. Return is needed*/ \ + return (static_cast(GetHistoryNode()->member_name) & flag) != 0U; \ + } \ + void Remove##flag_type(flag_type flag) const noexcept \ + { \ + if (Any(static_cast(GetHistoryNode()->member_name), flag)) { \ + GetOrCreateHistoryNode()->member_name &= ~static_cast(flag); \ + } \ + } + + // Use macro to generate AstNodeFlags operations + DECLARE_BITFIELD_FLAG_OPERATIONS(AstNodeFlags, bitFields_.astNodeFlags_) +#undef DECLARE_BITFIELD_FLAG_OPERATIONS + ir::ClassElement *AsClassElement(); const ir::ClassElement *AsClassElement() const; @@ -717,7 +756,7 @@ protected: void SetType(AstNodeType const type) noexcept { if (Type() != type) { - GetOrCreateHistoryNode()->type_ = type; + GetOrCreateHistoryNode()->bitFields_.type_ = static_cast(type); } } @@ -743,9 +782,11 @@ protected: AstNode *parent_ {}; AstNodeHistory *history_ {nullptr}; lexer::CompressedSourceRange range_ {}; - ModifierFlags flags_ {}; - mutable AstNodeFlags astNodeFlags_ {}; - AstNodeType type_; + struct { + uint64_t flags_ : 32; + uint64_t astNodeFlags_ : 24; + uint64_t type_ : 8; + } bitFields_ {}; // NOLINTEND(misc-non-private-member-variables-in-classes) private: diff --git a/ets2panda/ir/base/overloadDeclaration.cpp b/ets2panda/ir/base/overloadDeclaration.cpp index 7af8f592ff7f7d3ece7a2d44b487e374152dae84..ff3e81fd935b4e8835f9472165cad66a55083758 100644 --- a/ets2panda/ir/base/overloadDeclaration.cpp +++ b/ets2panda/ir/base/overloadDeclaration.cpp @@ -55,7 +55,7 @@ void OverloadDeclaration::Dump(ir::AstDumper *dumper) const { dumper->Add({{"type", "OverloadDeclaration"}, {"key", key_}, - {"optional", AstDumper::Optional(AstDumper::ModifierToString(flags_))}, + {"optional", AstDumper::Optional(AstDumper::ModifierToString(Modifiers()))}, {"static", IsStatic()}, {"overloadedList", overloadedList_}}); } diff --git a/ets2panda/ir/base/spreadElement.cpp b/ets2panda/ir/base/spreadElement.cpp index 9b504315154444509a9647ceb807d7c9d9109def..d2071abf9583f420fcebf1f17195d317ae74b254 100644 --- a/ets2panda/ir/base/spreadElement.cpp +++ b/ets2panda/ir/base/spreadElement.cpp @@ -118,7 +118,7 @@ void SpreadElement::Iterate(const NodeTraverser &cb) const void SpreadElement::Dump(ir::AstDumper *dumper) const { - dumper->Add({{"type", (type_ == AstNodeType::SPREAD_ELEMENT) ? "SpreadElement" : "RestElement"}, + dumper->Add({{"type", (Type() == AstNodeType::SPREAD_ELEMENT) ? "SpreadElement" : "RestElement"}, {"argument", argument_}, {"typeAnnotation", AstDumper::Optional(TypeAnnotation())}}); } diff --git a/ets2panda/ir/ets/etsModule.h b/ets2panda/ir/ets/etsModule.h index abc2a5eca1b40aa271e3706b1834926fbc9fe88c..ed06c3f6cc4995e11aa7c76d63554da192cb3b75 100644 --- a/ets2panda/ir/ets/etsModule.h +++ b/ets2panda/ir/ets/etsModule.h @@ -54,7 +54,7 @@ public: lang_(lang), program_(program) { - type_ = AstNodeType::ETS_MODULE; + SetType(AstNodeType::ETS_MODULE); InitHistory(); } @@ -67,7 +67,7 @@ public: lang_(lang), program_(program) { - type_ = AstNodeType::ETS_MODULE; + SetType(AstNodeType::ETS_MODULE); if (history != nullptr) { history_ = history; } else { diff --git a/ets2panda/ir/ets/etsTuple.cpp b/ets2panda/ir/ets/etsTuple.cpp index 3012e89b118d2c08d04028b9c9ba06f00ce84d7d..5d95ba0474e9078ff7f0b0a32b81913856e318a6 100644 --- a/ets2panda/ir/ets/etsTuple.cpp +++ b/ets2panda/ir/ets/etsTuple.cpp @@ -137,7 +137,7 @@ ETSTuple *ETSTuple::Clone(ArenaAllocator *const allocator, AstNode *const parent auto *const clone = allocator->New(allocator, size_); ES2PANDA_ASSERT(clone != nullptr); - clone->AddModifier(flags_); + clone->AddModifier(Modifiers()); if (parent != nullptr) { clone->SetParent(parent); diff --git a/ets2panda/ir/ets/etsTypeReference.cpp b/ets2panda/ir/ets/etsTypeReference.cpp index dc213924fba70e2a3af09fa5a49baae1f6fbc510..2246505ce13fdbb3d96c79a28c111e3f61e00d55 100644 --- a/ets2panda/ir/ets/etsTypeReference.cpp +++ b/ets2panda/ir/ets/etsTypeReference.cpp @@ -157,7 +157,7 @@ ETSTypeReference *ETSTypeReference::Clone(ArenaAllocator *const allocator, AstNo partClone->SetParent(clone); } - clone->flags_ = Modifiers(); + clone->AddModifier(Modifiers()); if (parent != nullptr) { clone->SetParent(parent); diff --git a/ets2panda/ir/expressions/arrayExpression.cpp b/ets2panda/ir/expressions/arrayExpression.cpp index b74e9c4d71a55b9a9f7974a728e5d1c04f6d2abd..e64ee3a6bddc676e4e6bef9a61febc21832fab2e 100644 --- a/ets2panda/ir/expressions/arrayExpression.cpp +++ b/ets2panda/ir/expressions/arrayExpression.cpp @@ -181,7 +181,7 @@ void ArrayExpression::Iterate(const NodeTraverser &cb) const void ArrayExpression::Dump(ir::AstDumper *dumper) const { - dumper->Add({{"type", type_ == AstNodeType::ARRAY_EXPRESSION ? "ArrayExpression" : "ArrayPattern"}, + dumper->Add({{"type", Type() == AstNodeType::ARRAY_EXPRESSION ? "ArrayExpression" : "ArrayPattern"}, {"elements", elements_}, {"typeAnnotation", AstDumper::Optional(TypeAnnotation())}, {"optional", AstDumper::Optional(optional_)}}); diff --git a/ets2panda/ir/expressions/assignmentExpression.cpp b/ets2panda/ir/expressions/assignmentExpression.cpp index 2505910c5f663426231c9b860261e1ff6eb67cf2..30f2d7888dce309e984ad128f179df7634882968 100644 --- a/ets2panda/ir/expressions/assignmentExpression.cpp +++ b/ets2panda/ir/expressions/assignmentExpression.cpp @@ -103,7 +103,7 @@ void AssignmentExpression::Iterate(const NodeTraverser &cb) const void AssignmentExpression::Dump(ir::AstDumper *dumper) const { - if (type_ == AstNodeType::ASSIGNMENT_EXPRESSION) { + if (Type() == AstNodeType::ASSIGNMENT_EXPRESSION) { dumper->Add({{"type", "AssignmentExpression"}, {"operator", operator_}, {"left", left_}, {"right", right_}}); } else { dumper->Add({{"type", "AssignmentPattern"}, {"left", left_}, {"right", right_}}); diff --git a/ets2panda/ir/expressions/binaryExpression.h b/ets2panda/ir/expressions/binaryExpression.h index 87c4377c8668a3e8449d9a40cd09275ff52da9eb..ad023949044cdfc8e980e75ec84e810abec7ccf2 100644 --- a/ets2panda/ir/expressions/binaryExpression.h +++ b/ets2panda/ir/expressions/binaryExpression.h @@ -133,7 +133,7 @@ public: void SetOperator(lexer::TokenType operatorType) noexcept { operator_ = operatorType; - type_ = AstNodeType::BINARY_EXPRESSION; + SetType(AstNodeType::BINARY_EXPRESSION); } [[nodiscard]] checker::Type *OperationType() noexcept diff --git a/ets2panda/ir/expressions/directEvalExpression.h b/ets2panda/ir/expressions/directEvalExpression.h index 3e959c30f2cb756d6414aaf9dd0c71008d2d9a3f..f51e7aa56386737d9882dbc7cb10bb3204c4cb32 100644 --- a/ets2panda/ir/expressions/directEvalExpression.h +++ b/ets2panda/ir/expressions/directEvalExpression.h @@ -29,7 +29,7 @@ public: TSTypeParameterInstantiation *typeParams, bool optional, uint32_t parserStatus) : CallExpression(callee, std::move(arguments), typeParams, optional), parserStatus_(parserStatus) { - type_ = AstNodeType::DIRECT_EVAL; + SetType(AstNodeType::DIRECT_EVAL); } // NOTE (csabahurton): friend relationship can be removed once there are getters for private fields diff --git a/ets2panda/ir/expressions/identifier.cpp b/ets2panda/ir/expressions/identifier.cpp index 050fd78b378553fa2a3a49ef2c12fb4a4d7d29ee..bd6206ee8ab7f5bec916c73b0771c768b5fedf67 100644 --- a/ets2panda/ir/expressions/identifier.cpp +++ b/ets2panda/ir/expressions/identifier.cpp @@ -31,7 +31,7 @@ Identifier::Identifier([[maybe_unused]] Tag const tag, Identifier const &other, Identifier::Identifier(ArenaAllocator *const allocator) : Identifier(ERROR_LITERAL, allocator) { - flags_ |= IdentifierFlags::ERROR_PLACEHOLDER; + AddIdFlags(IdentifierFlags::ERROR_PLACEHOLDER); InitHistory(); } @@ -39,7 +39,7 @@ Identifier::Identifier(util::StringView const name, [[maybe_unused]] ArenaAlloca : AnnotatedExpression(AstNodeType::IDENTIFIER), name_(name) { if (name == ERROR_LITERAL) { - flags_ |= IdentifierFlags::ERROR_PLACEHOLDER; + AddIdFlags(IdentifierFlags::ERROR_PLACEHOLDER); } InitHistory(); } @@ -49,7 +49,7 @@ Identifier::Identifier(util::StringView const name, TypeNode *const typeAnnotati : AnnotatedExpression(AstNodeType::IDENTIFIER, typeAnnotation), name_(name) { if (name == ERROR_LITERAL) { - flags_ |= IdentifierFlags::ERROR_PLACEHOLDER; + AddIdFlags(IdentifierFlags::ERROR_PLACEHOLDER); } InitHistory(); } diff --git a/ets2panda/ir/expressions/objectExpression.cpp b/ets2panda/ir/expressions/objectExpression.cpp index 36bc52d2fffd16d886d8fed240cafe2d8e6163e8..c5724676c15992baa3523f72c8099c1e117f2291 100644 --- a/ets2panda/ir/expressions/objectExpression.cpp +++ b/ets2panda/ir/expressions/objectExpression.cpp @@ -198,7 +198,7 @@ void ObjectExpression::Iterate(const NodeTraverser &cb) const void ObjectExpression::Dump(ir::AstDumper *dumper) const { - dumper->Add({{"type", (type_ == AstNodeType::OBJECT_EXPRESSION) ? "ObjectExpression" : "ObjectPattern"}, + dumper->Add({{"type", (Type() == AstNodeType::OBJECT_EXPRESSION) ? "ObjectExpression" : "ObjectPattern"}, {"properties", properties_}, {"typeAnnotation", AstDumper::Optional(TypeAnnotation())}, {"optional", AstDumper::Optional(optional_)}}); diff --git a/ets2panda/ir/statements/functionDeclaration.h b/ets2panda/ir/statements/functionDeclaration.h index 3700dd77872e2bafe57cf8cc733e01ade3321b61..57c784f3e2441be689054878457faed6a28ebd45 100644 --- a/ets2panda/ir/statements/functionDeclaration.h +++ b/ets2panda/ir/statements/functionDeclaration.h @@ -34,7 +34,7 @@ public: { InitHistory(); if (func != nullptr) { - flags_ = func->Modifiers(); + AddModifier(func->Modifiers()); } } @@ -46,7 +46,7 @@ public: { InitHistory(); if (func != nullptr) { - flags_ = func->Modifiers(); + AddModifier(func->Modifiers()); } } diff --git a/ets2panda/ir/ts/tsArrayType.cpp b/ets2panda/ir/ts/tsArrayType.cpp index 970e2762306f8b11ff8a5db72ff2fd899a8a96d8..80fe1dda9a01a30c10f4e40a379be1bb1a2f9f20 100644 --- a/ets2panda/ir/ts/tsArrayType.cpp +++ b/ets2panda/ir/ts/tsArrayType.cpp @@ -99,7 +99,7 @@ TSArrayType *TSArrayType::Clone(ArenaAllocator *const allocator, AstNode *const auto *const clone = allocator->New(elementTypeClone, allocator); ES2PANDA_ASSERT(clone != nullptr); - clone->AddModifier(flags_); + clone->AddModifier(Modifiers()); if (elementTypeClone != nullptr) { elementTypeClone->SetParent(clone);