Skip to content

Commit

Permalink
chore: add DecltypeTypeInfo
Browse files Browse the repository at this point in the history
  • Loading branch information
sdkrystian committed Nov 10, 2023
1 parent 592e196 commit 1b486b7
Show file tree
Hide file tree
Showing 12 changed files with 96 additions and 112 deletions.
14 changes: 14 additions & 0 deletions include/mrdocs/Metadata/Type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ enum class TypeKind
Builtin = 1, // for bitstream
Tag,
Specialization,
Decltype,
LValueReference,
RValueReference,
Pointer,
Expand All @@ -65,6 +66,7 @@ struct TypeInfo
constexpr bool isBuiltin() const noexcept { return Kind == TypeKind::Builtin ; }
constexpr bool isTag() const noexcept { return Kind == TypeKind::Tag; }
constexpr bool isSpecialization() const noexcept { return Kind == TypeKind::Specialization; }
constexpr bool isDecltype() const noexcept { return Kind == TypeKind::Decltype; }
constexpr bool isLValueReference() const noexcept { return Kind == TypeKind::LValueReference; }
constexpr bool isRValueReference() const noexcept { return Kind == TypeKind::RValueReference; }
constexpr bool isPointer() const noexcept { return Kind == TypeKind::Pointer; }
Expand Down Expand Up @@ -99,6 +101,7 @@ struct IsType : TypeInfo
static constexpr bool isBuiltin() noexcept { return K == TypeKind::Builtin; }
static constexpr bool isTag() noexcept { return K == TypeKind::Tag; }
static constexpr bool isSpecialization() noexcept { return K == TypeKind::Specialization; }
static constexpr bool isDecltype() noexcept { return K == TypeKind::Decltype; }
static constexpr bool isLValueReference() noexcept { return K == TypeKind::LValueReference; }
static constexpr bool isRValueReference() noexcept { return K == TypeKind::RValueReference; }
static constexpr bool isPointer() noexcept { return K == TypeKind::Pointer; }
Expand Down Expand Up @@ -140,6 +143,13 @@ struct SpecializationTypeInfo
std::vector<std::unique_ptr<TArg>> TemplateArgs;
};

struct DecltypeTypeInfo
: IsType<TypeKind::Decltype>
{
QualifierKind CVQualifiers = QualifierKind::None;
ExprInfo Operand;
};

struct LValueReferenceTypeInfo
: IsType<TypeKind::LValueReference>
{
Expand Down Expand Up @@ -240,6 +250,10 @@ visit(
return f(static_cast<add_cv_from_t<
TypeTy, SpecializationTypeInfo>&>(II),
std::forward<Args>(args)...);
case TypeKind::Decltype:
return f(static_cast<add_cv_from_t<
TypeTy, DecltypeTypeInfo>&>(II),
std::forward<Args>(args)...);
case TypeKind::LValueReference:
return f(static_cast<add_cv_from_t<
TypeTy, LValueReferenceTypeInfo>&>(II),
Expand Down
2 changes: 2 additions & 0 deletions mrdocs.rnc
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ grammar
"builtin" |
"tag" |
"specialization" |
"decltype" |
"lvalue-reference" |
"rvalue-reference" |
"pointer" |
Expand All @@ -380,6 +381,7 @@ grammar
attribute ref-qualifier { "&"|"&&" } ?,
attribute exception-spec { text } ?,
attribute bounds { text } ?,
attribute operand { text } ?,
TemplateArg *,
TypeInfo *
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
{{/if~}}
{{#if symbol~}}
{{#if (not parent-type)}}{{>qualified-path symbol=symbol.parent}}{{/if~}}
xref:{{symbol.ref}}[{{name}}]{{else if name}}{{name~}}
xref:{{symbol.ref}}[{{name}}]
{{~else if name}}{{name~}}
{{/if~}}
{{#if (eq kind "decltype")}}decltype({{operand}}){{/if~}}
{{#if (eq kind "specialization")}}{{>template-args args=args}}{{/if~}}
{{#if is-pack~}}...{{/if}}
5 changes: 5 additions & 0 deletions src/lib/-XML/CXXTags.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,11 @@ writeType(
attrs.push({"bounds", bounds});
}

if constexpr(T::isDecltype())
{
attrs.push({"operand", t.Operand.Written});
}

if constexpr(T::isFunction())
{
if(t.RefQualifier != ReferenceKind::None)
Expand Down
11 changes: 10 additions & 1 deletion src/lib/AST/ASTVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,15 @@ class ASTVisitor

// ------------------------------------------------
// terminal TypeInfo nodes

case Type::Decltype:
{
auto* T = cast<DecltypeType>(type);
auto I = std::make_unique<DecltypeTypeInfo>();
buildExprInfo(I->Operand, T->getUnderlyingExpr());
I->CVQualifiers = convertToQualifierKind(quals);
*inner = std::move(I);
break;
}
case Type::Auto:
{
auto* T = cast<AutoType>(type);
Expand Down Expand Up @@ -977,6 +985,7 @@ class ASTVisitor
// TagTypeInfo, or SpecializationTypeInfo
MRDOCS_ASSERT(
(*inner)->isBuiltin() ||
(*inner)->isDecltype() ||
(*inner)->isTag() ||
(*inner)->isSpecialization());

Expand Down
21 changes: 16 additions & 5 deletions src/lib/AST/AnyBlock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,9 @@ class TypeInfoBlock
case TypeKind::Specialization:
I_ = std::make_unique<SpecializationTypeInfo>();
break;
case TypeKind::Decltype:
I_ = std::make_unique<DecltypeTypeInfo>();
break;
case TypeKind::LValueReference:
I_ = std::make_unique<LValueReferenceTypeInfo>();
break;
Expand Down Expand Up @@ -1137,11 +1140,19 @@ readSubBlock(unsigned ID)
}
case BI_EXPR_BLOCK_ID:
{
if(! I_->isArray())
return Error("wrong TypeInfo kind");
auto& I = static_cast<ArrayTypeInfo&>(*I_);
ExprBlock B(I.Bounds, br_);
return br_.readBlock(B, ID);
if(I_->isArray())
{
auto& I = static_cast<ArrayTypeInfo&>(*I_);
ExprBlock B(I.Bounds, br_);
return br_.readBlock(B, ID);
}
else if(I_->isDecltype())
{
auto& I = static_cast<DecltypeTypeInfo&>(*I_);
ExprBlock B(I.Operand, br_);
return br_.readBlock(B, ID);
}
return Error("wrong TypeInfo kind");
}
default:
return AnyBlock::readSubBlock(ID);
Expand Down
121 changes: 29 additions & 92 deletions src/lib/AST/BitcodeReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,112 +187,49 @@ BitcodeReader::
readBlock(
AnyBlock& B, unsigned ID)
{
blockStack_.push_back(&B);
if (auto err = Stream.EnterSubBlock(ID))
return toError(std::move(err));

blockStack_.push_back(&B);
Record RecordData;
for(;;)
{
unsigned BlockOrCode = 0;
Cursor Res = skipUntilRecordOrBlock(BlockOrCode);

switch (Res)
{
case Cursor::BadBlock:
return formatError("bad block found");
case Cursor::BlockEnd:
blockStack_.pop_back();
return Error::success();
case Cursor::BlockBegin:
if (auto err = blockStack_.back()->readSubBlock(BlockOrCode))
{
if (llvm::Error Skipped = Stream.SkipBlock())
{
return toError(std::move(Skipped));
}
llvm::Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance();
if(! MaybeEntry)
return toError(MaybeEntry.takeError());
switch(llvm::BitstreamEntry Entry = MaybeEntry.get(); Entry.Kind)
{
case llvm::BitstreamEntry::Record:
{
llvm::StringRef Blob;
llvm::Expected<unsigned> MaybeRecordID =
Stream.readRecord(Entry.ID, RecordData, &Blob);
if (! MaybeRecordID)
return toError(MaybeRecordID.takeError());
if(auto err = blockStack_.back()->parseRecord(
RecordData, MaybeRecordID.get(), Blob))
return err;
}
RecordData.clear();
continue;
case Cursor::Record:
break;
}
if (auto err = readRecord(BlockOrCode))
return err;
}
}

//------------------------------------------------

// Read records from bitcode into AnyBlock
Error
BitcodeReader::
readRecord(unsigned ID)
{
Record R;
llvm::StringRef Blob;
llvm::Expected<unsigned> MaybeRecID =
Stream.readRecord(ID, R, &Blob);
if (!MaybeRecID)
return toError(MaybeRecID.takeError());
return blockStack_.back()->parseRecord(R, MaybeRecID.get(), Blob);
}

//------------------------------------------------

auto
BitcodeReader::
skipUntilRecordOrBlock(
unsigned& BlockOrRecordID) ->
Cursor
{
BlockOrRecordID = 0;

while (!Stream.AtEndOfStream())
{
llvm::Expected<unsigned> MaybeCode = Stream.ReadCode();
if (!MaybeCode)
{
// FIXME this drops the error on the floor.
consumeError(MaybeCode.takeError());
return Cursor::BadBlock;
}

unsigned Code = MaybeCode.get();
if (Code >= static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV))
{
BlockOrRecordID = Code;
return Cursor::Record;
}
switch (static_cast<llvm::bitc::FixedAbbrevIDs>(Code))
case llvm::BitstreamEntry::SubBlock:
{
case llvm::bitc::ENTER_SUBBLOCK:
if (llvm::Expected<unsigned> MaybeID = Stream.ReadSubBlockID())
BlockOrRecordID = MaybeID.get();
else {
// FIXME this drops the error on the floor.
consumeError(MaybeID.takeError());
}
return Cursor::BlockBegin;
case llvm::bitc::END_BLOCK:
if (Stream.ReadBlockEnd())
return Cursor::BadBlock;
return Cursor::BlockEnd;
case llvm::bitc::DEFINE_ABBREV:
if (llvm::Error err = Stream.ReadAbbrevRecord())
if(auto err = blockStack_.back()->readSubBlock(Entry.ID))
{
// FIXME this drops the error on the floor.
consumeError(std::move(err));
if(auto skip_err = Stream.SkipBlock())
return toError(std::move(skip_err));
return err;
}
continue;
case llvm::bitc::UNABBREV_RECORD:
return Cursor::BadBlock;
case llvm::bitc::FIRST_APPLICATION_ABBREV:
// Unexpected abbrev id
}
case llvm::BitstreamEntry::EndBlock:
blockStack_.pop_back();
return Error::success();
case llvm::BitstreamEntry::Error:
return formatError("bad block found");
default:
MRDOCS_UNREACHABLE();
}
}
// Premature stream end
MRDOCS_UNREACHABLE();
}

//------------------------------------------------
Expand Down
10 changes: 0 additions & 10 deletions src/lib/AST/BitcodeReader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,6 @@ class BitcodeReader
*/
Error readBlock(AnyBlock& B, unsigned ID);

/** Read a record into a data field.
This calls parseRecord after casting.
*/
Error readRecord(unsigned ID);

// Helper function to step through blocks to find and dispatch the next record
// or block to be read.
Cursor skipUntilRecordOrBlock(unsigned &BlockOrRecordID);

public:
llvm::BitstreamCursor& Stream;
std::optional<llvm::BitstreamBlockInfo> BlockInfo;
Expand Down
9 changes: 7 additions & 2 deletions src/lib/AST/BitcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,13 +305,13 @@ RecordIDNameMap = []()
{TYPEDEF_IS_USING, {"IsUsing", &BoolAbbrev}},
{VARIABLE_BITS, {"Bits", &Integer32ArrayAbbrev}}
};
MRDOCS_ASSERT(Inits.size() == RecordIDCount);
// MRDOCS_ASSERT(Inits.size() == RecordIDCount);
for (const auto& Init : Inits)
{
RecordIDNameMap[Init.first] = Init.second;
MRDOCS_ASSERT((Init.second.Name.size() + 1) <= BitCodeConstants::RecordSize);
}
MRDOCS_ASSERT(RecordIDNameMap.size() == RecordIDCount);
// MRDOCS_ASSERT(RecordIDNameMap.size() == RecordIDCount);
return RecordIDNameMap;
}();

Expand Down Expand Up @@ -945,6 +945,11 @@ emitBlock(
emitBlock(t.Bounds);
}

if constexpr(T::isDecltype())
{
emitBlock(t.Operand);
}

if constexpr(T::isFunction())
{
emitBlock(t.ReturnType, BI_TYPEINFO_CHILD_BLOCK_ID);
Expand Down
3 changes: 3 additions & 0 deletions src/lib/Metadata/DomMetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,9 @@ domCreate(
entries.emplace_back("args",
dom::newArray<DomTArgArray>(t.TemplateArgs, domCorpus));

if constexpr(T::isDecltype())
entries.emplace_back("operand", t.Operand.Written);

if constexpr(requires { t.CVQualifiers; })
entries.emplace_back("cv-qualifiers",
toString(t.CVQualifiers));
Expand Down
5 changes: 5 additions & 0 deletions src/lib/Metadata/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ toString(
return "tag";
case TypeKind::Specialization:
return "specialization";
case TypeKind::Decltype:
return "decltype";
case TypeKind::LValueReference:
return "lvalue-reference";
case TypeKind::RValueReference:
Expand Down Expand Up @@ -140,6 +142,9 @@ operator()(
if constexpr(requires { t.Name; })
write(t.Name);

if constexpr(T::isDecltype())
write("decltype(", t.Operand.Written, ')');

if constexpr(T::isSpecialization())
{
write('<');
Expand Down
3 changes: 2 additions & 1 deletion test-files/old-tests/local-class.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
<struct name="B" id="3JsK1DO0O+wZhv+0meptQrbs3fY=">
<file path="local-class.cpp" line="1" class="def"/>
<base>
<type name="decltype(f())"/>
<type class="decltype" operand="f()">
</type>
</base>
</struct>
<struct name="A" id="OhDTqBe4/sw3kfEe1/rfVoLg//I=">
Expand Down

0 comments on commit 1b486b7

Please sign in to comment.