// Part of the Carbon Language project, under the Apache License v2.0 with LLVM // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #ifndef CARBON_TOOLCHAIN_PARSE_NODE_CATEGORY_H_ #define CARBON_TOOLCHAIN_PARSE_NODE_CATEGORY_H_ #include "common/ostream.h" #include "llvm/ADT/BitmaskEnum.h" namespace Carbon::Parse { LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); // An X-macro for node categories. Uses should look like: // // #define CARBON_NODE_CATEGORY_FOR_XYZ(Name) ... // CARBON_NODE_CATEGORY(CARBON_NODE_CATEGORY_FOR_XYZ) // #undef CARBON_NODE_CATEGORY_FOR_XYZ #define CARBON_NODE_CATEGORY(X) \ X(Decl) \ X(Expr) \ X(ImplAs) \ X(IntConst) \ X(MemberExpr) \ X(MemberName) \ X(Modifier) \ X(NonExprName) \ X(PackageName) \ X(Pattern) \ X(Requirement) \ X(Statement) // Represents a set of keyword modifiers, using a separate bit per modifier. class NodeCategory : public Printable { private: // Use an enum to get incremental bit shifts. enum class BitShift : uint8_t { #define CARBON_NODE_CATEGORY_FOR_BIT_SHIFT(Name) Name, CARBON_NODE_CATEGORY(CARBON_NODE_CATEGORY_FOR_BIT_SHIFT) #undef CARBON_NODE_CATEGORY_FOR_BIT_SHIFT // For `LLVM_MARK_AS_BITMASK_ENUM`. LargestValueMarker, }; public: // Provide values as an enum. This doesn't expose these as NodeCategory // instances just due to the duplication of declarations that would cause. // // We expect this to grow, so are using a bigger size than needed. // NOLINTNEXTLINE(performance-enum-size) enum RawEnumType : uint32_t { #define CARBON_NODE_CATEGORY_FOR_BIT_MASK(Name) \ Name = 1 << static_cast(BitShift::Name), CARBON_NODE_CATEGORY(CARBON_NODE_CATEGORY_FOR_BIT_MASK) #undef CARBON_NODE_CATEGORY_FOR_BIT_MASK // If you add a new category here, also add it to the Print function. None = 0, LLVM_MARK_AS_BITMASK_ENUM( /*LargestValue=*/1 << (static_cast(BitShift::LargestValueMarker) - 1)) }; // Support implicit conversion so that the difference with the member enum is // opaque. // NOLINTNEXTLINE(google-explicit-constructor) constexpr NodeCategory(RawEnumType value) : value_(value) {} // Returns true if there's a non-empty set intersection. constexpr auto HasAnyOf(NodeCategory other) const -> bool { return value_ & other.value_; } // Returns the set inverse. constexpr auto operator~() const -> NodeCategory { return ~value_; } friend auto operator==(NodeCategory lhs, NodeCategory rhs) -> bool { return lhs.value_ == rhs.value_; } auto Print(llvm::raw_ostream& out) const -> void; private: RawEnumType value_; }; } // namespace Carbon::Parse #endif // CARBON_TOOLCHAIN_PARSE_NODE_CATEGORY_H_