diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 065349bfe6b8f..53ce87faf3d78 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -488,6 +488,8 @@ class ASTReader using ModuleReverseIterator = ModuleManager::ModuleReverseIterator; private: + using LocSeq = SourceLocationSequence; + /// The receiver of some callbacks invoked by ASTReader. std::unique_ptr Listener; @@ -2450,16 +2452,18 @@ class ASTReader /// Read a source location from raw form and return it in its /// originating module file's source location space. std::pair - ReadUntranslatedSourceLocation(RawLocEncoding Raw) const { - return SourceLocationEncoding::decode(Raw); + ReadUntranslatedSourceLocation(RawLocEncoding Raw, + LocSeq *Seq = nullptr) const { + return SourceLocationEncoding::decode(Raw, Seq); } /// Read a source location from raw form. - SourceLocation ReadSourceLocation(ModuleFile &MF, RawLocEncoding Raw) const { + SourceLocation ReadSourceLocation(ModuleFile &MF, RawLocEncoding Raw, + LocSeq *Seq = nullptr) const { if (!MF.ModuleOffsetMap.empty()) ReadModuleOffsetMap(MF); - auto [Loc, ModuleFileIndex] = ReadUntranslatedSourceLocation(Raw); + auto [Loc, ModuleFileIndex] = ReadUntranslatedSourceLocation(Raw, Seq); ModuleFile *OwningModuleFile = ModuleFileIndex == 0 ? &MF : MF.TransitiveImports[ModuleFileIndex - 1]; @@ -2487,9 +2491,9 @@ class ASTReader /// Read a source location. SourceLocation ReadSourceLocation(ModuleFile &ModuleFile, - const RecordDataImpl &Record, - unsigned &Idx) { - return ReadSourceLocation(ModuleFile, Record[Idx++]); + const RecordDataImpl &Record, unsigned &Idx, + LocSeq *Seq = nullptr) { + return ReadSourceLocation(ModuleFile, Record[Idx++], Seq); } /// Read a FileID. @@ -2508,7 +2512,7 @@ class ASTReader /// Read a source range. SourceRange ReadSourceRange(ModuleFile &F, const RecordData &Record, - unsigned &Idx); + unsigned &Idx, LocSeq *Seq = nullptr); static llvm::BitVector ReadBitVector(const RecordData &Record, const StringRef Blob); diff --git a/clang/include/clang/Serialization/ASTRecordReader.h b/clang/include/clang/Serialization/ASTRecordReader.h index 0cd9abde832df..900ea585bc242 100644 --- a/clang/include/clang/Serialization/ASTRecordReader.h +++ b/clang/include/clang/Serialization/ASTRecordReader.h @@ -32,6 +32,7 @@ class OMPChildren; class ASTRecordReader : public serialization::DataStreamBasicReader { using ModuleFile = serialization::ModuleFile; + using LocSeq = SourceLocationSequence; ASTReader *Reader; ModuleFile *F; @@ -159,7 +160,7 @@ class ASTRecordReader TypeSourceInfo *readTypeSourceInfo(); /// Reads the location information for a type. - void readTypeLoc(TypeLoc TL); + void readTypeLoc(TypeLoc TL, LocSeq *Seq = nullptr); /// Map a local type ID within a given AST file to a global type ID. serialization::TypeID getGlobalTypeID(serialization::TypeID LocalID) const { @@ -292,13 +293,13 @@ class ASTRecordReader void readOpenACCRoutineDeclAttr(OpenACCRoutineDeclAttr *A); /// Read a source location, advancing Idx. - SourceLocation readSourceLocation() { - return Reader->ReadSourceLocation(*F, Record, Idx); + SourceLocation readSourceLocation(LocSeq *Seq = nullptr) { + return Reader->ReadSourceLocation(*F, Record, Idx, Seq); } /// Read a source range, advancing Idx. - SourceRange readSourceRange() { - return Reader->ReadSourceRange(*F, Record, Idx); + SourceRange readSourceRange(LocSeq *Seq = nullptr) { + return Reader->ReadSourceRange(*F, Record, Idx, Seq); } /// Read an arbitrary constant value, advancing Idx. diff --git a/clang/include/clang/Serialization/ASTRecordWriter.h b/clang/include/clang/Serialization/ASTRecordWriter.h index c8c0a6d22f23c..f9baa755f4015 100644 --- a/clang/include/clang/Serialization/ASTRecordWriter.h +++ b/clang/include/clang/Serialization/ASTRecordWriter.h @@ -29,6 +29,7 @@ class TypeLoc; /// An object for streaming information to a record. class ASTRecordWriter : public serialization::DataStreamBasicWriter { + using LocSeq = SourceLocationSequence; ASTWriter *Writer; ASTWriter::RecordDataImpl *Record; @@ -146,8 +147,8 @@ class ASTRecordWriter void AddFunctionDefinition(const FunctionDecl *FD); /// Emit a source location. - void AddSourceLocation(SourceLocation Loc) { - return Writer->AddSourceLocation(Loc, *Record); + void AddSourceLocation(SourceLocation Loc, LocSeq *Seq = nullptr) { + return Writer->AddSourceLocation(Loc, *Record, Seq); } void writeSourceLocation(SourceLocation Loc) { AddSourceLocation(Loc); @@ -174,8 +175,8 @@ class ASTRecordWriter } /// Emit a source range. - void AddSourceRange(SourceRange Range) { - return Writer->AddSourceRange(Range, *Record); + void AddSourceRange(SourceRange Range, LocSeq *Seq = nullptr) { + return Writer->AddSourceRange(Range, *Record, Seq); } void writeBool(bool Value) { @@ -245,7 +246,7 @@ class ASTRecordWriter void AddTypeSourceInfo(TypeSourceInfo *TInfo); /// Emits source location information for a type. Does not emit the type. - void AddTypeLoc(TypeLoc TL); + void AddTypeLoc(TypeLoc TL, LocSeq *Seq = nullptr); /// Emits a template argument location info. void AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 63a0452959d7e..522a0a112799b 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -115,6 +115,8 @@ class ASTWriter : public ASTDeserializationListener, using TypeIdxMap = llvm::DenseMap; + using LocSeq = SourceLocationSequence; + /// The bitstream writer used to emit this precompiled header. llvm::BitstreamWriter &Stream; @@ -733,14 +735,16 @@ class ASTWriter : public ASTDeserializationListener, void AddFileID(FileID FID, RecordDataImpl &Record); /// Emit a source location. - void AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record); + void AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record, + LocSeq *Seq = nullptr); /// Return the raw encodings for source locations. SourceLocationEncoding::RawLocEncoding - getRawSourceLocationEncoding(SourceLocation Loc); + getRawSourceLocationEncoding(SourceLocation Loc, LocSeq *Seq = nullptr); /// Emit a source range. - void AddSourceRange(SourceRange Range, RecordDataImpl &Record); + void AddSourceRange(SourceRange Range, RecordDataImpl &Record, + LocSeq *Seq = nullptr); /// Emit a reference to an identifier. void AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record); diff --git a/clang/include/clang/Serialization/SourceLocationEncoding.h b/clang/include/clang/Serialization/SourceLocationEncoding.h index 5b2485dbc719f..bb222ac91ecbe 100644 --- a/clang/include/clang/Serialization/SourceLocationEncoding.h +++ b/clang/include/clang/Serialization/SourceLocationEncoding.h @@ -25,6 +25,8 @@ // * C: The macro bit. We rotate it to the lowest bit so that we can save some // space in case the index of the module file is 0. // +// Specially, if the index of the module file is 0, we allow to encode a +// sequence of locations we store only differences between successive elements. // //===----------------------------------------------------------------------===// @@ -36,6 +38,7 @@ #include namespace clang { +class SourceLocationSequence; /// Serialized encoding of SourceLocations without context. /// Optimized to have small unsigned values (=> small after VBR encoding). @@ -51,22 +54,119 @@ class SourceLocationEncoding { static UIntTy decodeRaw(UIntTy Raw) { return (Raw >> 1) | (Raw << (UIntBits - 1)); } + friend SourceLocationSequence; public: using RawLocEncoding = uint64_t; static RawLocEncoding encode(SourceLocation Loc, UIntTy BaseOffset, - unsigned BaseModuleFileIndex); - static std::pair decode(RawLocEncoding); + unsigned BaseModuleFileIndex, + SourceLocationSequence * = nullptr); + static std::pair + decode(RawLocEncoding, SourceLocationSequence * = nullptr); +}; + +/// Serialized encoding of a sequence of SourceLocations. +/// +/// Optimized to produce small values when locations with the sequence are +/// similar. Each element can be delta-encoded against the last nonzero element. +/// +/// Sequences should be started by creating a SourceLocationSequence::State, +/// and then passed around as SourceLocationSequence*. Example: +/// +/// // establishes a sequence +/// void EmitTopLevelThing() { +/// SourceLocationSequence::State Seq; +/// EmitContainedThing(Seq); +/// EmitRecursiveThing(Seq); +/// } +/// +/// // optionally part of a sequence +/// void EmitContainedThing(SourceLocationSequence *Seq = nullptr) { +/// Record.push_back(SourceLocationEncoding::encode(SomeLoc, Seq)); +/// } +/// +/// // establishes a sequence if there isn't one already +/// void EmitRecursiveThing(SourceLocationSequence *ParentSeq = nullptr) { +/// SourceLocationSequence::State Seq(ParentSeq); +/// Record.push_back(SourceLocationEncoding::encode(SomeLoc, Seq)); +/// EmitRecursiveThing(Seq); +/// } +/// +class SourceLocationSequence { + using UIntTy = SourceLocation::UIntTy; + using EncodedTy = uint64_t; + constexpr static auto UIntBits = SourceLocationEncoding::UIntBits; + static_assert(sizeof(EncodedTy) > sizeof(UIntTy), "Need one extra bit!"); + + // Prev stores the rotated last nonzero location. + UIntTy &Prev; + + // Zig-zag encoding turns small signed integers into small unsigned integers. + // 0 => 0, -1 => 1, 1 => 2, -2 => 3, ... + static UIntTy zigZag(UIntTy V) { + UIntTy Sign = (V & (1 << (UIntBits - 1))) ? UIntTy(-1) : UIntTy(0); + return Sign ^ (V << 1); + } + static UIntTy zagZig(UIntTy V) { return (V >> 1) ^ -(V & 1); } + + SourceLocationSequence(UIntTy &Prev) : Prev(Prev) {} + + EncodedTy encodeRaw(UIntTy Raw) { + if (Raw == 0) + return 0; + UIntTy Rotated = SourceLocationEncoding::encodeRaw(Raw); + if (Prev == 0) + return Prev = Rotated; + UIntTy Delta = Rotated - Prev; + Prev = Rotated; + // Exactly one 33 bit value is possible! (1 << 32). + // This is because we have two representations of zero: trivial & relative. + return 1 + EncodedTy{zigZag(Delta)}; + } + UIntTy decodeRaw(EncodedTy Encoded) { + if (Encoded == 0) + return 0; + if (Prev == 0) + return SourceLocationEncoding::decodeRaw(Prev = Encoded); + return SourceLocationEncoding::decodeRaw(Prev += zagZig(Encoded - 1)); + } + +public: + SourceLocation decode(EncodedTy Encoded) { + return SourceLocation::getFromRawEncoding(decodeRaw(Encoded)); + } + EncodedTy encode(SourceLocation Loc) { + return encodeRaw(Loc.getRawEncoding()); + } + + class State; +}; + +/// This object establishes a SourceLocationSequence. +class SourceLocationSequence::State { + UIntTy Prev = 0; + SourceLocationSequence Seq; + +public: + // If Parent is provided and non-null, then this root becomes part of that + // enclosing sequence instead of establishing a new one. + State(SourceLocationSequence *Parent = nullptr) + : Seq(Parent ? Parent->Prev : Prev) {} + + // Implicit conversion for uniform use of roots vs propagated sequences. + operator SourceLocationSequence *() { return &Seq; } }; inline SourceLocationEncoding::RawLocEncoding SourceLocationEncoding::encode(SourceLocation Loc, UIntTy BaseOffset, - unsigned BaseModuleFileIndex) { + unsigned BaseModuleFileIndex, + SourceLocationSequence *Seq) { // If the source location is a local source location, we can try to optimize // the similar sequences to only record the differences. if (!BaseOffset) - return encodeRaw(Loc.getRawEncoding()); + return Seq ? Seq->encode(Loc) : encodeRaw(Loc.getRawEncoding()); + if (Loc.isInvalid()) return 0; @@ -83,11 +183,13 @@ SourceLocationEncoding::encode(SourceLocation Loc, UIntTy BaseOffset, return Encoded; } inline std::pair -SourceLocationEncoding::decode(RawLocEncoding Encoded) { +SourceLocationEncoding::decode(RawLocEncoding Encoded, + SourceLocationSequence *Seq) { unsigned ModuleFileIndex = Encoded >> 32; if (!ModuleFileIndex) - return {SourceLocation::getFromRawEncoding(decodeRaw(Encoded)), + return {Seq ? Seq->decode(Encoded) + : SourceLocation::getFromRawEncoding(decodeRaw(Encoded)), ModuleFileIndex}; Encoded &= llvm::maskTrailingOnes(32); diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index e1ffe6c4a8eef..956931b372d03 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -1935,9 +1935,10 @@ bool ASTReader::ReadSLocEntry(int ID) { } case SM_SLOC_EXPANSION_ENTRY: { - SourceLocation SpellingLoc = ReadSourceLocation(*F, Record[1]); - SourceLocation ExpansionBegin = ReadSourceLocation(*F, Record[2]); - SourceLocation ExpansionEnd = ReadSourceLocation(*F, Record[3]); + LocSeq::State Seq; + SourceLocation SpellingLoc = ReadSourceLocation(*F, Record[1], Seq); + SourceLocation ExpansionBegin = ReadSourceLocation(*F, Record[2], Seq); + SourceLocation ExpansionEnd = ReadSourceLocation(*F, Record[3], Seq); SourceMgr.createExpansionLoc(SpellingLoc, ExpansionBegin, ExpansionEnd, Record[5], Record[4], ID, BaseOffset + Record[0]); @@ -7192,10 +7193,13 @@ QualType ASTReader::readTypeRecord(TypeID ID) { namespace clang { class TypeLocReader : public TypeLocVisitor { + using LocSeq = SourceLocationSequence; + ASTRecordReader &Reader; + LocSeq *Seq; - SourceLocation readSourceLocation() { return Reader.readSourceLocation(); } - SourceRange readSourceRange() { return Reader.readSourceRange(); } + SourceLocation readSourceLocation() { return Reader.readSourceLocation(Seq); } + SourceRange readSourceRange() { return Reader.readSourceRange(Seq); } TypeSourceInfo *GetTypeSourceInfo() { return Reader.readTypeSourceInfo(); @@ -7210,7 +7214,8 @@ class TypeLocReader : public TypeLocVisitor { } public: - TypeLocReader(ASTRecordReader &Reader) : Reader(Reader) {} + TypeLocReader(ASTRecordReader &Reader, LocSeq *Seq) + : Reader(Reader), Seq(Seq) {} // We want compile-time assurance that we've enumerated all of // these, so unfortunately we have to declare them first, then @@ -7585,8 +7590,9 @@ void TypeLocReader::VisitDependentBitIntTypeLoc( TL.setNameLoc(readSourceLocation()); } -void ASTRecordReader::readTypeLoc(TypeLoc TL) { - TypeLocReader TLR(*this); +void ASTRecordReader::readTypeLoc(TypeLoc TL, LocSeq *ParentSeq) { + LocSeq::State Seq(ParentSeq); + TypeLocReader TLR(*this, Seq); for (; !TL.isNull(); TL = TL.getNextTypeLoc()) TLR.Visit(TL); } @@ -10157,9 +10163,9 @@ ASTRecordReader::readNestedNameSpecifierLoc() { } SourceRange ASTReader::ReadSourceRange(ModuleFile &F, const RecordData &Record, - unsigned &Idx) { - SourceLocation beg = ReadSourceLocation(F, Record, Idx); - SourceLocation end = ReadSourceLocation(F, Record, Idx); + unsigned &Idx, LocSeq *Seq) { + SourceLocation beg = ReadSourceLocation(F, Record, Idx, Seq); + SourceLocation end = ReadSourceLocation(F, Record, Idx, Seq); return SourceRange(beg, end); } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 4a784d4a62c2b..ca1053a44e4d5 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -330,13 +330,19 @@ class ASTTypeWriter { }; class TypeLocWriter : public TypeLocVisitor { + using LocSeq = SourceLocationSequence; + ASTRecordWriter &Record; + LocSeq *Seq; - void addSourceLocation(SourceLocation Loc) { Record.AddSourceLocation(Loc); } - void addSourceRange(SourceRange Range) { Record.AddSourceRange(Range); } + void addSourceLocation(SourceLocation Loc) { + Record.AddSourceLocation(Loc, Seq); + } + void addSourceRange(SourceRange Range) { Record.AddSourceRange(Range, Seq); } public: - TypeLocWriter(ASTRecordWriter &Record) : Record(Record) {} + TypeLocWriter(ASTRecordWriter &Record, LocSeq *Seq) + : Record(Record), Seq(Seq) {} #define ABSTRACT_TYPELOC(CLASS, PARENT) #define TYPELOC(CLASS, PARENT) \ @@ -2493,12 +2499,13 @@ void ASTWriter::WriteSourceManagerBlock(SourceManager &SourceMgr) { SLocEntryOffsets.push_back(Offset); // Starting offset of this entry within this module, so skip the dummy. Record.push_back(getAdjustedOffset(SLoc->getOffset()) - 2); - AddSourceLocation(Expansion.getSpellingLoc(), Record); - AddSourceLocation(Expansion.getExpansionLocStart(), Record); + LocSeq::State Seq; + AddSourceLocation(Expansion.getSpellingLoc(), Record, Seq); + AddSourceLocation(Expansion.getExpansionLocStart(), Record, Seq); AddSourceLocation(Expansion.isMacroArgExpansion() ? SourceLocation() : Expansion.getExpansionLocEnd(), - Record); + Record, Seq); Record.push_back(Expansion.isExpansionTokenRange()); // Compute the token length for this macro expansion. @@ -6757,8 +6764,8 @@ void ASTWriter::AddFileID(FileID FID, RecordDataImpl &Record) { } SourceLocationEncoding::RawLocEncoding -ASTWriter::getRawSourceLocationEncoding(SourceLocation Loc) { - SourceLocation::UIntTy BaseOffset = 0; +ASTWriter::getRawSourceLocationEncoding(SourceLocation Loc, LocSeq *Seq) { + unsigned BaseOffset = 0; unsigned ModuleFileIndex = 0; // See SourceLocationEncoding.h for the encoding details. @@ -6776,17 +6783,19 @@ ASTWriter::getRawSourceLocationEncoding(SourceLocation Loc) { assert(&getChain()->getModuleManager()[F->Index] == F); } - return SourceLocationEncoding::encode(Loc, BaseOffset, ModuleFileIndex); + return SourceLocationEncoding::encode(Loc, BaseOffset, ModuleFileIndex, Seq); } -void ASTWriter::AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record) { +void ASTWriter::AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record, + SourceLocationSequence *Seq) { Loc = getAdjustedLocation(Loc); - Record.push_back(getRawSourceLocationEncoding(Loc)); + Record.push_back(getRawSourceLocationEncoding(Loc, Seq)); } -void ASTWriter::AddSourceRange(SourceRange Range, RecordDataImpl &Record) { - AddSourceLocation(Range.getBegin(), Record); - AddSourceLocation(Range.getEnd(), Record); +void ASTWriter::AddSourceRange(SourceRange Range, RecordDataImpl &Record, + SourceLocationSequence *Seq) { + AddSourceLocation(Range.getBegin(), Record, Seq); + AddSourceLocation(Range.getEnd(), Record, Seq); } void ASTRecordWriter::AddAPFloat(const llvm::APFloat &Value) { @@ -6906,8 +6915,9 @@ void ASTRecordWriter::AddTypeSourceInfo(TypeSourceInfo *TInfo) { AddTypeLoc(TInfo->getTypeLoc()); } -void ASTRecordWriter::AddTypeLoc(TypeLoc TL) { - TypeLocWriter TLW(*this); +void ASTRecordWriter::AddTypeLoc(TypeLoc TL, LocSeq *OuterSeq) { + LocSeq::State Seq(OuterSeq); + TypeLocWriter TLW(*this, Seq); for (; !TL.isNull(); TL = TL.getNextTypeLoc()) TLW.Visit(TL); } diff --git a/clang/unittests/Serialization/SourceLocationEncodingTest.cpp b/clang/unittests/Serialization/SourceLocationEncodingTest.cpp index 18fedd4de3973..c80a8fd0e52b1 100644 --- a/clang/unittests/Serialization/SourceLocationEncodingTest.cpp +++ b/clang/unittests/Serialization/SourceLocationEncodingTest.cpp @@ -16,6 +16,7 @@ using namespace llvm; using namespace clang; namespace { +using LocSeq = SourceLocationSequence; // Convert a single source location into encoded form and back. // If ExpectedEncoded is provided, verify the encoded value too. @@ -33,9 +34,37 @@ void roundTrip(SourceLocation::UIntTy Loc, ASSERT_EQ(DecodedEncoded, Loc) << "Decoding " << ActualEncoded; } +// As above, but use sequence encoding for a series of locations. +void roundTrip(std::vector Locs, + std::vector ExpectedEncoded = {}) { + std::vector ActualEncoded; + { + LocSeq::State Seq; + for (auto L : Locs) + ActualEncoded.push_back(SourceLocationEncoding::encode( + SourceLocation::getFromRawEncoding(L), /*BaseOffset=*/0, + /*BaseModuleFileIndex=*/0, Seq)); + if (!ExpectedEncoded.empty()) { + ASSERT_EQ(ActualEncoded, ExpectedEncoded) + << "Encoding " << testing::PrintToString(Locs); + } + } + std::vector DecodedEncoded; + { + LocSeq::State Seq; + for (auto L : ActualEncoded) { + SourceLocation Loc = SourceLocationEncoding::decode(L, Seq).first; + DecodedEncoded.push_back(Loc.getRawEncoding()); + } + ASSERT_EQ(DecodedEncoded, Locs) + << "Decoding " << testing::PrintToString(ActualEncoded); + } +} + constexpr SourceLocation::UIntTy MacroBit = 1 << (sizeof(SourceLocation::UIntTy) * CHAR_BIT - 1); constexpr SourceLocation::UIntTy Big = MacroBit >> 1; +constexpr SourceLocation::UIntTy Biggest = -1; TEST(SourceLocationEncoding, Individual) { roundTrip(1, 2); @@ -48,4 +77,33 @@ TEST(SourceLocationEncoding, Individual) { roundTrip(MacroBit | (Big + 1)); } +TEST(SourceLocationEncoding, Sequence) { + roundTrip({1, 2, 3, 3, 2, 1}, + {2, // 1 + 5, // +2 (+1 of non-raw) + 5, // +2 + 1, // +0 + 4, // -2 + 4} // -2 + ); + roundTrip({100, 0, 100}, + {200, // 100 + 0, // 0 + 1} // +0 + ); + + roundTrip({1, Big}, {2, ((Big - 1) << 2) + 1}); + roundTrip({2, MacroBit | Big}, {4, ((Big - 1) << 2) - 1}); + + roundTrip({3, MacroBit | 5, MacroBit | 4, 3}, + {6, // 3 + 11, // +5 (+2 of non-raw + set macro bit) + 4, // -2 + 6} // -3 (-2 of non-raw, clear macro bit) + ); + + roundTrip( + {123 | MacroBit, 1, 9, Biggest, Big, Big + 1, 0, MacroBit | Big, 0}); +} + } // namespace