Skip to content

Commit

Permalink
[FOLD]
Browse files Browse the repository at this point in the history
  • Loading branch information
sdkrystian committed Dec 1, 2023
1 parent 3f83fd0 commit 86644f2
Show file tree
Hide file tree
Showing 13 changed files with 243 additions and 125 deletions.
58 changes: 33 additions & 25 deletions include/mrdocs/Metadata/Specifiers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,37 +71,30 @@ enum class ExplicitKind
*/
enum class NoexceptKind
{
None = 0,
// throw()
ThrowNone,
// throw(type-id-list)
Throw,
// throw(...) (microsoft extension)
ThrowAny,
// __declspec(nothrow) (microsoft extension)
NoThrow,
// noexcept-specifier, no constant-expression
Noexcept,
// noexcept-specifier, constant-expression evaluates to false
NoexceptFalse,
// noexcept-specifier, constant-expression evaluates to true
NoexceptTrue,
// noexcept-specifier, dependent constant-expression
NoexceptDependent,

// not evaluated yet, for special member function
Unevaluated,
// not instantiated yet
Uninstantiated,
// not parsed yet
Unparsed
/** Potentially-throwing exception specification
*/
False = 0,
/** Non-throwing exception specification
*/
True,
/** Dependent exception specification
*/
Dependent
};

// KRYSTIAN FIXME: this needs to be improved (a lot)
struct NoexceptInfo
{
NoexceptKind Kind = NoexceptKind::None;
/** Whether a noexcept-specifier was user-written.
*/
bool Implicit = true;

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

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

Expand Down Expand Up @@ -192,6 +185,21 @@ MRDOCS_DECL dom::String toString(NoexceptKind kind) noexcept;
MRDOCS_DECL dom::String toString(ReferenceKind kind) noexcept;
MRDOCS_DECL dom::String toString(StorageClassKind kind) noexcept;

/** Convert NoexceptInfo to a string.
@param resolved If true, the operand is not shown when
the exception specification is non-dependent.
@param implicit If true, implicit exception specifications
are shown.
*/
MRDOCS_DECL
dom::String
toString(
NoexceptInfo info,
bool resolved = false,
bool implicit = false);

} // mrdocs
} // clang

Expand Down
2 changes: 1 addition & 1 deletion include/mrdocs/Metadata/Type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ struct FunctionTypeInfo
std::vector<std::unique_ptr<TypeInfo>> ParamTypes;
QualifierKind CVQualifiers = QualifierKind::None;
ReferenceKind RefQualifier = ReferenceKind::None;
NoexceptKind ExceptionSpec = NoexceptKind::None;
NoexceptKind ExceptionSpec = NoexceptKind::False;

TypeInfo* innerType() const noexcept override
{
Expand Down
94 changes: 85 additions & 9 deletions src/lib/AST/ASTVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -709,9 +709,15 @@ class ASTVisitor

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

std::string
getTypeAsString(
QualType T)
std::string getExprAsString(const Expr* E)
{
std::string result;
llvm::raw_string_ostream stream(result);
E->printPretty(stream, nullptr, context_.getPrintingPolicy());
return result;
}

std::string getTypeAsString(QualType T)
{
return T.getAsString(context_.getPrintingPolicy());
}
Expand Down Expand Up @@ -1270,6 +1276,59 @@ class ASTVisitor
V.getZExtValue());
}

void
buildNoexceptInfo(
NoexceptInfo& I,
ExceptionSpecificationType Kind,
const Expr* E)
{
I.Implicit = Kind == ExceptionSpecificationType::EST_None;
I.Kind = convertToNoexceptKind(Kind);

if(! E)
return;

I.Operand = getExprAsString(E);
}

void
buildNoexceptInfo(
NoexceptInfo& I,
TypeSourceInfo* FTSI)
{
MRDOCS_ASSERT(FTSI && FTSI->getType()->isFunctionProtoType());
if(auto* FPT = FTSI->getType()->getAs<FunctionProtoType>())
{
buildNoexceptInfo(I,
FPT->getExceptionSpecType(),
FPT->getNoexceptExpr());
}
}

void
buildNoexceptInfo(
NoexceptInfo& I,
const FunctionProtoType* FPT)
{
MRDOCS_ASSERT(FPT);
I.Implicit = ! FPT->hasNoexceptExceptionSpec();
#if 0
// if the exception specification is unevaluated,
// we just consider it to be dependent
if(FPT->getExceptionSpecType() ==
ExceptionSpecificationType::EST_Unevaluated)
I.Kind = NoexceptKind::Dependent;
else
I.Kind = convertToNoexceptKind(FPT->canThrow());
#endif
I.Kind = convertToNoexceptKind(FPT->getExceptionSpecType());

// store the operand, if any
if(Expr* NoexceptExpr = FPT->getNoexceptExpr())
I.Operand = getExprAsString(NoexceptExpr);
}

#if 0
void
buildNoexceptInfo(
NoexceptInfo& I,
Expand Down Expand Up @@ -1308,6 +1367,7 @@ class ASTVisitor
}
buildNoexceptInfo(I, Kind, E);
}
#endif

void
buildExprInfo(
Expand Down Expand Up @@ -1347,6 +1407,16 @@ class ASTVisitor
I.Value.emplace(getValue<T>(V));
}

QualType
getDeclaratorType(
const DeclaratorDecl* DD)
{
if(auto* TSI = DD->getTypeSourceInfo();
TSI && ! TSI->getType().isNull())
return TSI->getType();
return DD->getType();
}

std::unique_ptr<TParam>
buildTemplateParam(
const NamedDecl* N)
Expand Down Expand Up @@ -2190,6 +2260,17 @@ class ASTVisitor
addSourceLocation(I, D->getBeginLoc(),
D->isThisDeclarationADefinition(), documented);

// KRYSTIAN TODO: move other extraction that requires
// a valid function type here
if(auto FT = getDeclaratorType(D); ! FT.isNull())
{
const auto* FPT = FT->getAs<FunctionProtoType>();

Check failure on line 2267 in src/lib/AST/ASTVisitor.cpp

View workflow job for this annotation

GitHub Actions / Clang 16.0: C++20

clang++-16: use 'template' keyword to treat 'getAs' as a dependent template name

Check warning on line 2267 in src/lib/AST/ASTVisitor.cpp

View workflow job for this annotation

GitHub Actions / GCC 13.1: C++20

g++-13: expected ‘template’ keyword before dependent template name ([-Wmissing-template-keyword])

Check failure on line 2267 in src/lib/AST/ASTVisitor.cpp

View workflow job for this annotation

GitHub Actions / GCC 13.1: C++20

g++-13: expected primary-expression before ‘>’ token

Check failure on line 2267 in src/lib/AST/ASTVisitor.cpp

View workflow job for this annotation

GitHub Actions / GCC 13.1: C++20

g++-13: expected primary-expression before ‘)’ token

buildNoexceptInfo(I.Noexcept, FPT);

I.specs0.hasTrailingReturn |= FPT->hasTrailingReturn();
}

//
// FunctionDecl
//
Expand All @@ -2204,15 +2285,10 @@ class ASTVisitor
// subsumes D->hasAttr<C11NoReturnAttr>()
// subsumes D->getType()->getAs<FunctionType>()->getNoReturnAttr()
I.specs0.hasOverrideAttr |= D->template hasAttr<OverrideAttr>();
if(auto const* FP = D->getType()->template getAs<FunctionProtoType>())
I.specs0.hasTrailingReturn |= FP->hasTrailingReturn();
I.specs0.constexprKind |=
convertToConstexprKind(
D->getConstexprKind());
buildNoexceptInfo(I.Noexcept, D);
// I.specs0.exceptionSpec |=
// convertToNoexceptKind(
// D->getExceptionSpecType());

I.specs0.overloadedOperator |=
convertToOperatorKind(
D->getOverloadedOperator());
Expand Down
47 changes: 35 additions & 12 deletions src/lib/AST/ASTVisitorHelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,20 +114,43 @@ convertToNoexceptKind(
{
using OldKind = ExceptionSpecificationType;
using NewKind = NoexceptKind;
// KRYSTIAN TODO: right now we convert pre-C++17 dynamic exception
// specifications to an (roughly) equivalent noexcept-specifier
switch(spec)
{
case OldKind::EST_None: return NewKind::None;
case OldKind::EST_DynamicNone: return NewKind::ThrowNone;
case OldKind::EST_Dynamic: return NewKind::Throw;
case OldKind::EST_MSAny: return NewKind::ThrowAny;
case OldKind::EST_NoThrow: return NewKind::NoThrow;
case OldKind::EST_BasicNoexcept: return NewKind::Noexcept;
case OldKind::EST_DependentNoexcept: return NewKind::NoexceptDependent;
case OldKind::EST_NoexceptFalse: return NewKind::NoexceptFalse;
case OldKind::EST_NoexceptTrue: return NewKind::NoexceptTrue;
case OldKind::EST_Unevaluated: return NewKind::Unevaluated;
case OldKind::EST_Uninstantiated: return NewKind::Uninstantiated;
case OldKind::EST_Unparsed: return NewKind::Unparsed;
case OldKind::EST_None:
case OldKind::EST_MSAny:
case OldKind::EST_Unevaluated:
case OldKind::EST_Uninstantiated:
// we *shouldn't* ever encounter an unparsed exception specification,
// assuming that clang is working correctly...
case OldKind::EST_Unparsed:
case OldKind::EST_Dynamic:
case OldKind::EST_NoexceptFalse:
return NewKind::False;
case OldKind::EST_NoThrow:
case OldKind::EST_BasicNoexcept:
case OldKind::EST_NoexceptTrue:
case OldKind::EST_DynamicNone:
return NewKind::True;
case OldKind::EST_DependentNoexcept:
return NewKind::Dependent;
default:
MRDOCS_UNREACHABLE();
}
}

NoexceptKind
convertToNoexceptKind(

Check warning on line 144 in src/lib/AST/ASTVisitorHelpers.hpp

View workflow job for this annotation

GitHub Actions / GCC 13.1: C++20

g++-13: ‘clang::mrdocs::NoexceptKind clang::mrdocs::{anonymous}::convertToNoexceptKind(clang::CanThrowResult)’ defined but not used ([-Wunused-function])
CanThrowResult kind)
{
using OldKind = CanThrowResult;
using NewKind = NoexceptKind;
switch(kind)
{
case OldKind::CT_Can: return NewKind::False;
case OldKind::CT_Cannot: return NewKind::True;
case OldKind::CT_Dependent: return NewKind::Dependent;
default:
MRDOCS_UNREACHABLE();
}
Expand Down
55 changes: 15 additions & 40 deletions src/lib/AST/AnyBlock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,19 @@ decodeRecord(
return Error::success();
}

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

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

struct BitcodeReader::AnyBlock
Expand Down Expand Up @@ -1314,41 +1327,6 @@ 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);
}
}
};

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

template<class T>
class TopLevelBlock
: public BitcodeReader::AnyBlock
Expand Down Expand Up @@ -1461,6 +1439,8 @@ class FunctionBlock
return decodeRecord(R, {&I->specs0.raw, &I->specs1.raw}, Blob);
case FUNCTION_CLASS:
return decodeRecord(R, I->Class, Blob);
case FUNCTION_NOEXCEPT:
return decodeRecord(R, I->Noexcept, Blob);
default:
return TopLevelBlock::parseRecord(R, ID, Blob);
}
Expand Down Expand Up @@ -1488,11 +1468,6 @@ 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);
}
Expand Down
4 changes: 1 addition & 3 deletions src/lib/AST/BitcodeIDs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ 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
};
Expand Down Expand Up @@ -118,11 +117,10 @@ enum RecordID
FRIEND_SYMBOL,
FUNCTION_BITS,
FUNCTION_CLASS,
FUNCTION_NOEXCEPT,
FUNCTION_PARAM_NAME,
FUNCTION_PARAM_DEFAULT,
GUIDE_EXPLICIT,
NOEXCEPT_KIND,
NOEXCEPT_OPERAND,
JAVADOC_NODE_ADMONISH,
JAVADOC_NODE_HREF,
JAVADOC_NODE_KIND,
Expand Down
Loading

0 comments on commit 86644f2

Please sign in to comment.