diff --git a/include/mrdocs/Metadata/Function.hpp b/include/mrdocs/Metadata/Function.hpp index fc0866548..a1d4f385b 100644 --- a/include/mrdocs/Metadata/Function.hpp +++ b/include/mrdocs/Metadata/Function.hpp @@ -155,6 +155,8 @@ struct FunctionInfo FnFlags0 specs0{.raw{0}}; FnFlags1 specs1{.raw{0}}; + NoexceptInfo Noexcept; + //-------------------------------------------- explicit FunctionInfo(SymbolID ID) noexcept diff --git a/include/mrdocs/Metadata/Specifiers.hpp b/include/mrdocs/Metadata/Specifiers.hpp index f10492079..4b668cb11 100644 --- a/include/mrdocs/Metadata/Specifiers.hpp +++ b/include/mrdocs/Metadata/Specifiers.hpp @@ -13,6 +13,7 @@ #include #include +#include #include namespace clang { @@ -96,6 +97,14 @@ enum class NoexceptKind Unparsed }; +// KRYSTIAN FIXME: this needs to be improved (a lot) +struct NoexceptInfo +{ + NoexceptKind Kind = NoexceptKind::None; + + std::string Operand; +}; + /** Operator kinds */ enum class OperatorKind diff --git a/share/mrdocs/addons/generator/asciidoc/partials/signature/function.adoc.hbs b/share/mrdocs/addons/generator/asciidoc/partials/signature/function.adoc.hbs index ea0b18f9c..9904bb83e 100644 --- a/share/mrdocs/addons/generator/asciidoc/partials/signature/function.adoc.hbs +++ b/share/mrdocs/addons/generator/asciidoc/partials/signature/function.adoc.hbs @@ -19,7 +19,7 @@ {{~#if symbol.isConst}} const{{/if~}} {{#if symbol.isVolatile}} volatile{{/if~}} {{#if symbol.refQualifier}} {{symbol.refQualifier}}{{/if~}} -{{#if (eq symbol.exceptionSpec "noexcept")}} noexcept{{/if~}} +{{#if symbol.exceptionSpec}} {{symbol.exceptionSpec}}{{/if~}} {{#if (eq symbol.class "normal")}}{{>declarator-after symbol.return}}{{/if~}} {{#if symbol.hasOverrideAttr}} override{{/if~}} {{#if symbol.isFinal}} final{{/if~}} diff --git a/src/lib/AST/ASTVisitor.cpp b/src/lib/AST/ASTVisitor.cpp index f7476898f..430dc5d74 100644 --- a/src/lib/AST/ASTVisitor.cpp +++ b/src/lib/AST/ASTVisitor.cpp @@ -1270,6 +1270,45 @@ class ASTVisitor V.getZExtValue()); } + void + buildNoexceptInfo( + NoexceptInfo& I, + ExceptionSpecificationType Kind, + const Expr* E) + { + if(Kind == ExceptionSpecificationType::EST_None) + return; + I.Kind = convertToNoexceptKind(Kind); + + if(! E) + return; + #if 0 + I.Operand = getSourceCode( + E->getSourceRange()); + #else + + llvm::raw_string_ostream stream(I.Operand); + E->printPretty(stream, nullptr, context_.getPrintingPolicy()); + #endif + } + + void + buildNoexceptInfo( + NoexceptInfo& I, + FunctionDecl* FD) + { + auto Kind = FD->getExceptionSpecType(); + if(Kind == ExceptionSpecificationType::EST_None) + return; + const Expr* E = nullptr; + if(auto FTL = FD->getFunctionTypeLoc()) + { + if(auto* FPT = FTL.getAs().getTypePtr()) + E = FPT->getNoexceptExpr(); + } + buildNoexceptInfo(I, Kind, E); + } + void buildExprInfo( ExprInfo& I, @@ -2170,9 +2209,10 @@ class ASTVisitor I.specs0.constexprKind |= convertToConstexprKind( D->getConstexprKind()); - I.specs0.exceptionSpec |= - convertToNoexceptKind( - D->getExceptionSpecType()); + buildNoexceptInfo(I.Noexcept, D); + // I.specs0.exceptionSpec |= + // convertToNoexceptKind( + // D->getExceptionSpecType()); I.specs0.overloadedOperator |= convertToOperatorKind( D->getOverloadedOperator()); diff --git a/src/lib/AST/AnyBlock.hpp b/src/lib/AST/AnyBlock.hpp index 6c37cdb1b..d99375f92 100644 --- a/src/lib/AST/AnyBlock.hpp +++ b/src/lib/AST/AnyBlock.hpp @@ -1312,6 +1312,40 @@ class FunctionParamBlock } }; +//------------------------------------------------ + +class NoexceptBlock + : public BitcodeReader::AnyBlock +{ + BitcodeReader& br_; + NoexceptInfo& I_; + +public: + NoexceptBlock( + NoexceptInfo& I, + BitcodeReader& br) noexcept + : br_(br) + , I_(I) + { + } + + Error + parseRecord( + Record const& R, + unsigned ID, + llvm::StringRef Blob) override + { + switch(ID) + { + case NOEXCEPT_KIND: + return decodeRecord(R, I_.Kind, Blob); + case NOEXCEPT_OPERAND: + return decodeRecord(R, I_.Operand, Blob); + default: + return AnyBlock::parseRecord(R, ID, Blob); + } + } +}; //------------------------------------------------ @@ -1454,6 +1488,11 @@ class FunctionBlock TemplateBlock B(*I->Template, br_); return br_.readBlock(B, ID); } + case BI_NOEXCEPT_BLOCK_ID: + { + NoexceptBlock B(I->Noexcept, br_); + return br_.readBlock(B, ID); + } default: return TopLevelBlock::readSubBlock(ID); } diff --git a/src/lib/AST/BitcodeIDs.hpp b/src/lib/AST/BitcodeIDs.hpp index 6f7553b4d..2609c4735 100644 --- a/src/lib/AST/BitcodeIDs.hpp +++ b/src/lib/AST/BitcodeIDs.hpp @@ -79,6 +79,7 @@ enum BlockID BI_TYPEINFO_PARAM_BLOCK_ID, BI_TYPEDEF_BLOCK_ID, BI_VARIABLE_BLOCK_ID, + BI_NOEXCEPT_BLOCK_ID, BI_LAST, BI_FIRST = BI_VERSION_BLOCK_ID }; @@ -120,6 +121,8 @@ enum RecordID FUNCTION_PARAM_NAME, FUNCTION_PARAM_DEFAULT, GUIDE_EXPLICIT, + NOEXCEPT_KIND, + NOEXCEPT_OPERAND, JAVADOC_NODE_ADMONISH, JAVADOC_NODE_HREF, JAVADOC_NODE_KIND, diff --git a/src/lib/AST/BitcodeWriter.cpp b/src/lib/AST/BitcodeWriter.cpp index 8c4a86f5a..0ae462b2c 100644 --- a/src/lib/AST/BitcodeWriter.cpp +++ b/src/lib/AST/BitcodeWriter.cpp @@ -235,7 +235,8 @@ BlockIdNameMap = []() {BI_SPECIALIZATION_BLOCK_ID, "SpecializationBlock"}, {BI_FRIEND_BLOCK_ID, "FriendBlock"}, {BI_ENUMERATOR_BLOCK_ID, "EnumeratorBlock"}, - {BI_VARIABLE_BLOCK_ID, "VarBlock"} + {BI_VARIABLE_BLOCK_ID, "VarBlock"}, + {BI_NOEXCEPT_BLOCK_ID, "NoexceptBlock"} }; MRDOCS_ASSERT(Inits.size() == BlockIdCount); for (const auto& Init : Inits) @@ -270,6 +271,8 @@ RecordIDNameMap = []() {FUNCTION_PARAM_NAME, {"Name", &StringAbbrev}}, {FUNCTION_PARAM_DEFAULT, {"Default", &StringAbbrev}}, {GUIDE_EXPLICIT, {"Explicit", &Integer32Abbrev}}, + {NOEXCEPT_KIND, {"NoexceptKind", &Integer32Abbrev}}, + {NOEXCEPT_OPERAND, {"NoexceptOperand", &StringAbbrev}}, {INFO_PART_ACCESS, {"InfoAccess", &Integer32Abbrev}}, {INFO_PART_ID, {"InfoID", &SymbolIDAbbrev}}, {INFO_PART_IMPLICIT, {"InfoImplicit", &BoolAbbrev}}, @@ -414,7 +417,9 @@ RecordsByBlock{ // VariableInfo {BI_VARIABLE_BLOCK_ID, {VARIABLE_BITS}}, // GuideInfo - {BI_GUIDE_BLOCK_ID, {GUIDE_EXPLICIT}} + {BI_GUIDE_BLOCK_ID, {GUIDE_EXPLICIT}}, + // NoexceptInfo + {BI_NOEXCEPT_BLOCK_ID, {NOEXCEPT_KIND, NOEXCEPT_OPERAND}} }; //------------------------------------------------ @@ -831,6 +836,16 @@ emitBlock( emitBlock(P.Type); } +void +BitcodeWriter:: +emitBlock( + const NoexceptInfo& I) +{ + StreamSubBlockGuard Block(Stream, BI_NOEXCEPT_BLOCK_ID); + emitRecord(I.Kind, NOEXCEPT_KIND); + emitRecord(I.Operand, NOEXCEPT_OPERAND); +} + void BitcodeWriter:: emitBlock( @@ -846,6 +861,8 @@ emitBlock( emitBlock(I.ReturnType); for (const auto& N : I.Params) emitBlock(N); + if(I.Noexcept.Kind != NoexceptKind::None) + emitBlock(I.Noexcept); } void diff --git a/src/lib/AST/BitcodeWriter.hpp b/src/lib/AST/BitcodeWriter.hpp index 050b6371c..f4888cca3 100644 --- a/src/lib/AST/BitcodeWriter.hpp +++ b/src/lib/AST/BitcodeWriter.hpp @@ -116,6 +116,7 @@ class BitcodeWriter void emitBlock(FunctionInfo const& I); void emitBlock(GuideInfo const& I); void emitBlock(Param const& I); + void emitBlock(NoexceptInfo const& I); void emitBlock(std::unique_ptr const& jd); void emitBlock(doc::Node const& I); void emitBlock(NamespaceInfo const& I); diff --git a/src/lib/Metadata/DomMetadata.cpp b/src/lib/Metadata/DomMetadata.cpp index 4566904bf..f13fe7e1c 100644 --- a/src/lib/Metadata/DomMetadata.cpp +++ b/src/lib/Metadata/DomMetadata.cpp @@ -776,6 +776,16 @@ DomInfo::construct() const { "template", domCreate(I_.Template, domCorpus_) }, { "overloadedOperator", I_.specs0.overloadedOperator.get() }, }); + + if(I_.Noexcept.Kind != NoexceptKind::None) + { + dom::String exceptSpec = "noexcept"; + if(! I_.Noexcept.Operand.empty()) + exceptSpec = fmt::format( + "noexcept({})", + I_.Noexcept.Operand); + entries.emplace_back("exceptionSpec", std::move(exceptSpec)); + } } if constexpr(T::isTypedef()) { diff --git a/src/lib/Metadata/Reduce.cpp b/src/lib/Metadata/Reduce.cpp index 6dcced0eb..fb8d4cdd5 100644 --- a/src/lib/Metadata/Reduce.cpp +++ b/src/lib/Metadata/Reduce.cpp @@ -200,6 +200,8 @@ void merge(FunctionInfo& I, FunctionInfo&& Other) I.Template = std::move(Other.Template); I.specs0.raw.value |= Other.specs0.raw.value; I.specs1.raw.value |= Other.specs1.raw.value; + if(I.Noexcept.Kind == NoexceptKind::None) + I.Noexcept = std::move(Other.Noexcept); } void merge(GuideInfo& I, GuideInfo&& Other)