Skip to content

Commit

Permalink
feat: better support for explicit-specifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
sdkrystian committed May 27, 2024
1 parent a28f265 commit 7ebe30a
Show file tree
Hide file tree
Showing 18 changed files with 183 additions and 92 deletions.
4 changes: 2 additions & 2 deletions include/mrdocs/Metadata/Function.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,6 @@ union FnFlags1

BitFlag<0> isNodiscard;

BitField<1, 3, ExplicitKind> explicitSpec;

BitFlag<4> isExplicitObjectMemberFunction;
};

Expand Down Expand Up @@ -159,6 +157,8 @@ struct FunctionInfo

NoexceptInfo Noexcept;

ExplicitInfo Explicit;

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

explicit FunctionInfo(SymbolID ID) noexcept
Expand Down
2 changes: 1 addition & 1 deletion include/mrdocs/Metadata/Guide.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ struct GuideInfo

/** The explicit-specifier, if any.
*/
ExplicitKind Explicit = ExplicitKind::None;
ExplicitInfo Explicit;

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

Expand Down
51 changes: 40 additions & 11 deletions include/mrdocs/Metadata/Specifiers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,31 @@ enum class ConstexprKind
*/
enum class ExplicitKind
{
// no explicit-specifier present
None = 0,
// explicit-specifier, no constant-expression
Explicit,
// explicit-specifier, constant-expression evaluates to false
ExplicitFalse,
// explicit-specifier, constant-expression evaluates to true
ExplicitTrue,
// explicit-specifier, unresolved
ExplicitUnresolved
/** No explicit-specifier or explicit-specifier evaluated to false
*/
False = 0,
/** explicit-specifier evaluates to true
*/
True,
/** Dependent explicit-specifier
*/
Dependent
};

// KRYSTIAN FIXME: this needs to be improved (a lot)
struct ExplicitInfo
{
/** Whether an explicit-specifier was user-written.
*/
bool Implicit = true;

/** The evaluated exception specification.
*/
ExplicitKind Kind = ExplicitKind::False;

/** The operand of the explicit-specifier, if any.
*/
std::string Operand;
};

/** Exception specification kinds
Expand Down Expand Up @@ -196,7 +211,21 @@ MRDOCS_DECL dom::String toString(StorageClassKind kind) noexcept;
MRDOCS_DECL
dom::String
toString(
NoexceptInfo info,
const NoexceptInfo& info,
bool resolved = false,
bool implicit = false);

/** Convert ExplicitInfo to a string.
@param resolved If true, the operand is not shown when
the explicit-specifier is non-dependent.
@param implicit If true, implicit explicit-specifiers are shown.
*/
MRDOCS_DECL
dom::String
toString(
const ExplicitInfo& info,
bool resolved = false,
bool implicit = false);

Expand Down
3 changes: 2 additions & 1 deletion mrdocs.rnc
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ grammar
ID,
attribute class { "constructor"|"destructor"|"conversion" } ?,
attribute exception-spec { text } ?,
attribute explicit-spec { text } ?,
Location *,
(
Attr * |
Expand All @@ -99,7 +100,7 @@ grammar
{
Name,
Access?,
attribute explicit { "1" } ?,
attribute explicit-spec { text } ?,
ID,
Location *,
(
Expand Down
24 changes: 16 additions & 8 deletions src/lib/AST/ASTVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,19 @@ class ASTVisitor
I.Operand = getExprAsString(NoexceptExpr);
}

void
buildExplicitInfo(
ExplicitInfo& I,
const ExplicitSpecifier& ES)
{
I.Implicit = ! ES.isSpecified();
I.Kind = convertToExplicitKind(ES);

// store the operand, if any
if(const Expr* ExplicitExpr = ES.getExpr())
I.Operand = getExprAsString(ExplicitExpr);
}

void
buildExprInfo(
ExprInfo& I,
Expand Down Expand Up @@ -2032,19 +2045,15 @@ class ASTVisitor
//
if constexpr(std::derived_from<DeclTy, CXXConstructorDecl>)
{
I.specs1.explicitSpec |=
convertToExplicitKind(
D->getExplicitSpecifier());
buildExplicitInfo(I.Explicit, D->getExplicitSpecifier());
}

//
// CXXConversionDecl
//
if constexpr(std::derived_from<DeclTy, CXXConversionDecl>)
{
I.specs1.explicitSpec |=
convertToExplicitKind(
D->getExplicitSpecifier());
buildExplicitInfo(I.Explicit, D->getExplicitSpecifier());
}

for(const ParmVarDecl* P : D->parameters())
Expand Down Expand Up @@ -2120,8 +2129,7 @@ class ASTVisitor
std::string());
}

I.Explicit = convertToExplicitKind(
D->getExplicitSpecifier());
buildExplicitInfo(I.Explicit, D->getExplicitSpecifier());

getParentNamespaces(I, D);
}
Expand Down
11 changes: 4 additions & 7 deletions src/lib/AST/ASTVisitorHelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,19 +143,16 @@ convertToExplicitKind(

// no explicit-specifier
if(! spec.isSpecified())
return NewKind::None;
return NewKind::False;

switch(spec.getKind())
{
case OldKind::ResolvedFalse:
return NewKind::ExplicitFalse;
return NewKind::False;
case OldKind::ResolvedTrue:
if(spec.getExpr())
return NewKind::ExplicitTrue;
// explicit-specifier without constant-expression
return NewKind::Explicit;
return NewKind::True;
case OldKind::Unresolved:
return NewKind::ExplicitUnresolved;
return NewKind::Dependent;
default:
MRDOCS_UNREACHABLE();
}
Expand Down
15 changes: 15 additions & 0 deletions src/lib/AST/AnyBlock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,19 @@ decodeRecord(
return Error::success();
}

inline
Error
decodeRecord(
Record const& R,
ExplicitInfo& I,
llvm::StringRef Blob)
{
I.Implicit = R[0];
I.Kind = static_cast<ExplicitKind>(R[1]);
I.Operand = Blob;
return Error::success();
}

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

struct BitcodeReader::AnyBlock
Expand Down Expand Up @@ -1530,6 +1543,8 @@ class FunctionBlock
return decodeRecord(R, I->Class, Blob);
case FUNCTION_NOEXCEPT:
return decodeRecord(R, I->Noexcept, Blob);
case FUNCTION_EXPLICIT:
return decodeRecord(R, I->Explicit, Blob);
default:
return TopLevelBlock::parseRecord(R, ID, Blob);
}
Expand Down
1 change: 1 addition & 0 deletions src/lib/AST/BitcodeIDs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ enum RecordID
FUNCTION_BITS,
FUNCTION_CLASS,
FUNCTION_NOEXCEPT,
FUNCTION_EXPLICIT,
FUNCTION_PARAM_NAME,
FUNCTION_PARAM_DEFAULT,
GUIDE_EXPLICIT,
Expand Down
43 changes: 41 additions & 2 deletions src/lib/AST/BitcodeWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,25 @@ static void NoexceptAbbrev(
llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob) });
}

static void ExplicitAbbrev(
std::shared_ptr<llvm::BitCodeAbbrev>& Abbrev)
{
AbbrevGen(Abbrev, {
// ExplicitInfo::Implicit
llvm::BitCodeAbbrevOp(
llvm::BitCodeAbbrevOp::Fixed,
BitCodeConstants::BoolSize),
// ExplicitInfo::Kind
llvm::BitCodeAbbrevOp(
llvm::BitCodeAbbrevOp::Fixed, 2),
// ExplicitInfo::Operand
llvm::BitCodeAbbrevOp(
llvm::BitCodeAbbrevOp::Fixed,
BitCodeConstants::StringLengthSize),
// 5. The string blob
llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob) });
}

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

struct RecordIDDsc
Expand Down Expand Up @@ -292,9 +311,10 @@ RecordIDNameMap = []()
{FUNCTION_BITS, {"Bits", &Integer32ArrayAbbrev}},
{FUNCTION_CLASS, {"FunctionClass", &Integer32Abbrev}},
{FUNCTION_NOEXCEPT, {"FunctionNoexcept", &NoexceptAbbrev}},
{FUNCTION_EXPLICIT, {"FunctionExplicit", &ExplicitAbbrev}},
{FUNCTION_PARAM_NAME, {"Name", &StringAbbrev}},
{FUNCTION_PARAM_DEFAULT, {"Default", &StringAbbrev}},
{GUIDE_EXPLICIT, {"Explicit", &Integer32Abbrev}},
{GUIDE_EXPLICIT, {"GuideExplicit", &ExplicitAbbrev}},
{INFO_PART_ACCESS, {"InfoAccess", &Integer32Abbrev}},
{INFO_PART_ID, {"InfoID", &SymbolIDAbbrev}},
{INFO_PART_IMPLICIT, {"InfoImplicit", &BoolAbbrev}},
Expand Down Expand Up @@ -388,7 +408,8 @@ RecordsByBlock{
FIELD_IS_MUTABLE, FIELD_IS_BITFIELD}},
// FunctionInfo
{BI_FUNCTION_BLOCK_ID,
{FUNCTION_BITS, FUNCTION_CLASS, FUNCTION_NOEXCEPT}},
{FUNCTION_BITS, FUNCTION_CLASS, FUNCTION_NOEXCEPT,
FUNCTION_EXPLICIT}},
// Param
{BI_FUNCTION_PARAM_BLOCK_ID,
{FUNCTION_PARAM_NAME, FUNCTION_PARAM_DEFAULT}},
Expand Down Expand Up @@ -741,6 +762,23 @@ emitRecord(
Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, I.Operand);
}

void
BitcodeWriter::
emitRecord(
ExplicitInfo const& I, RecordID ID)
{
MRDOCS_ASSERT(RecordIDNameMap[ID] && "Unknown RecordID.");
MRDOCS_ASSERT(RecordIDNameMap[ID].Abbrev == &ExplicitAbbrev &&
"Abbrev type mismatch.");
if (!prepRecordData(ID, true))
return;

Record.push_back(I.Implicit);
Record.push_back(to_underlying(I.Kind));
Record.push_back(I.Operand.size());
Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, I.Operand);
}

void
BitcodeWriter::
emitRecord(
Expand Down Expand Up @@ -902,6 +940,7 @@ emitBlock(
for (const auto& N : I.Params)
emitBlock(N);
emitRecord(I.Noexcept, FUNCTION_NOEXCEPT);
emitRecord(I.Explicit, FUNCTION_EXPLICIT);
}

void
Expand Down
1 change: 1 addition & 0 deletions src/lib/AST/BitcodeWriter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ class BitcodeWriter
void emitRecord(llvm::StringRef Str, RecordID ID);
void emitRecord(Location const& Loc, RecordID ID);
void emitRecord(NoexceptInfo const& I, RecordID ID);
void emitRecord(ExplicitInfo const& I, RecordID ID);
void emitRecord(bool Value, RecordID ID);
void emitRecord(std::initializer_list<BitFieldFullValue> values, RecordID ID);

Expand Down
1 change: 0 additions & 1 deletion src/lib/Gen/xml/CXXTags.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,6 @@ inline void write(FnFlags1 const& bits, XMLTags& tags)
{
BitFieldWriter<FnFlags1> fw(bits, tags);

fw.write(&FnFlags1::explicitSpec, "explicit-spec");
fw.write(&FnFlags1::isNodiscard, "nodiscard");
fw.write(&FnFlags1::isExplicitObjectMemberFunction, "is-explicit-object-member-function");
}
Expand Down
10 changes: 6 additions & 4 deletions src/lib/Gen/xml/XMLWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ writeFunction(
openTemplate(I.Template);

auto except_spec = toString(I.Noexcept);
auto explicit_spec = toString(I.Explicit);

tags_.open(functionTagName, {
{ "class", toString(I.Class),
Expand All @@ -331,6 +332,8 @@ writeFunction(
{ I.Access },
{ "exception-spec", except_spec,
! except_spec.empty() },
{ "explicit-spec", explicit_spec,
! explicit_spec.empty() },
{ I.id }
});

Expand Down Expand Up @@ -358,14 +361,13 @@ writeGuide(
{
openTemplate(I.Template);

bool IsExplicit = I.Explicit != ExplicitKind::None &&
I.Explicit != ExplicitKind::ExplicitFalse;

auto explicit_spec = toString(I.Explicit);

tags_.open(guideTagName, {
{ "name", I.Name },
{ I.Access },
{ "explicit", "1", IsExplicit},
{ "explicit-spec", explicit_spec,
! explicit_spec.empty() },
{ I.id }
});

Expand Down
5 changes: 2 additions & 3 deletions src/lib/Metadata/DomMetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -791,7 +791,6 @@ DomInfo<T>::construct() const
set_string("exceptionSpec", toString(I_.specs0.exceptionSpec.get()));
set_string("storageClass", toString(I_.specs0.storageClass.get()));
set_string("refQualifier", toString(I_.specs0.refQualifier.get()));
set_string("explicitSpec", toString(I_.specs1.explicitSpec.get()));

entries.insert(entries.end(), {
{ "class", toString(I_.Class) },
Expand All @@ -802,6 +801,7 @@ DomInfo<T>::construct() const
});

entries.emplace_back("exceptionSpec", toString(I_.Noexcept));
entries.emplace_back("explicitSpec", toString(I_.Explicit));
#if 0
if(I_.Noexcept.Kind != NoexceptKind::None)
{
Expand Down Expand Up @@ -895,8 +895,7 @@ DomInfo<T>::construct() const
{ "template", domCreate(I_.Template, domCorpus_) }
});

if(I_.Explicit != ExplicitKind::None)
entries.emplace_back("explicitSpec", toString(I_.Explicit));
entries.emplace_back("explicitSpec", toString(I_.Explicit));
}
return dom::Object(std::move(entries));
}
Expand Down
6 changes: 4 additions & 2 deletions src/lib/Metadata/Reduce.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ void merge(FunctionInfo& I, FunctionInfo&& Other)
I.specs1.raw.value |= Other.specs1.raw.value;
if(I.Noexcept.Implicit)
I.Noexcept = std::move(Other.Noexcept);
if(I.Explicit.Implicit)
I.Explicit = std::move(Other.Explicit);
}

void merge(GuideInfo& I, GuideInfo&& Other)
Expand All @@ -216,8 +218,8 @@ void merge(GuideInfo& I, GuideInfo&& Other)
mergeInfo(I, std::move(Other));
if (!I.Template)
I.Template = std::move(Other.Template);
if(I.Explicit == ExplicitKind::None)
I.Explicit = Other.Explicit;
if(I.Explicit.Implicit)
I.Explicit = std::move(Other.Explicit);
}

void merge(TypedefInfo& I, TypedefInfo&& Other)
Expand Down
Loading

0 comments on commit 7ebe30a

Please sign in to comment.