Skip to content

Commit

Permalink
add diagnostic
Browse files Browse the repository at this point in the history
Signed-off-by: Valentyn Yukhymenko <valentin.yukhymenko@gmail.com>
  • Loading branch information
BaLiKfromUA committed Aug 2, 2024
1 parent e7899d2 commit dc8003c
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 10 deletions.
9 changes: 9 additions & 0 deletions clang/include/clang/Basic/DiagnosticMetafnKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ def metafn_returns_non_structural_type : Note<
"represented as a reflection">;
def metafn_invocation_not_constant_expr : Note<
"invocation is not a constant expression">;
def metafn_first_argument_is_not_object : Note<
"expected related object reflection as a first argument for invoking "
"member non-static function">;
def metafn_function_is_not_member_of_object : Note<
"method is not a member of "
"given object reflection">;
def metafn_function_returns_void : Note<
"cannot invoke reflection of void function">;


// Extraction.
def metafn_cannot_extract : Note<
Expand Down
35 changes: 25 additions & 10 deletions clang/lib/Sema/Metafunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4429,7 +4429,9 @@ bool is_nonstatic_member_function(ValueDecl *FD) {
return false;
}

auto* MD = dyn_cast<CXXMethodDecl>(FD);
// todo: check that method is not special??

auto *MD = dyn_cast<CXXMethodDecl>(FD);
if (!MD) {
return false;
}
Expand Down Expand Up @@ -4635,10 +4637,12 @@ bool reflect_invoke(APValue &Result, Sema &S, EvalFn Evaluator,

if (DRE && is_nonstatic_member_function(DRE->getDecl())) {
auto *MD = cast<CXXMethodDecl>(DRE->getDecl());
// todo: add diagnostic notes

if (ArgExprs.size() < 1) {
// need to have object as a first argument
return true;
return Diagnoser(Range.getBegin(),
diag::metafn_first_argument_is_not_object)
<< Range;
}

auto ObjExpr = ArgExprs[0];
Expand All @@ -4650,20 +4654,31 @@ bool reflect_invoke(APValue &Result, Sema &S, EvalFn Evaluator,

if (!ObjType->getAsCXXRecordDecl()) {
// first argument is not an object
return true;
return Diagnoser(Range.getBegin(),
diag::metafn_first_argument_is_not_object)
<< Range;
}

// todo: add check if method belongs to class
// todo: check that return value is not void
// todo: prohibit virtual methods
// check that method belongs to class
if (ObjType->getAsCXXRecordDecl()->getDeclName() !=
MD->getParent()->getDeclName()) {
return Diagnoser(Range.getBegin(),
diag::metafn_function_is_not_member_of_object)
<< Range;
}

if (MD->getReturnType()->isVoidType()) {
// void return type is not supported
return Diagnoser(Range.getBegin(), diag::metafn_function_returns_void)
<< Range;
}

SourceLocation ObjLoc = ObjExpr->getExprLoc();
UnqualifiedId Name;
Name.setIdentifier(MD->getIdentifier(), ObjLoc);

CXXScopeSpec SS;
SourceLocation TemplateKWLoc;
// todo: improve for template member functions if needed

ExprResult MemberAccessResult = S.ActOnMemberAccessExpr(
S.getCurScope(), S.MakeFullExpr(ObjExpr).get(), ObjLoc,
Expand All @@ -4679,8 +4694,8 @@ bool reflect_invoke(APValue &Result, Sema &S, EvalFn Evaluator,
FnArgExprs = {ArgExprs.begin() + 1, ArgExprs.end()};
}

ER = S.ActOnCallExpr(S.getCurScope(), FnExpr, Range.getBegin(), FnArgExprs,
Range.getEnd(), /*ExecConfig=*/nullptr);
ER = S.ActOnCallExpr(S.getCurScope(), FnExpr, Range.getBegin(),
FnArgExprs, Range.getEnd(), /*ExecConfig=*/nullptr);
}
}

Expand Down

0 comments on commit dc8003c

Please sign in to comment.