Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions clang/lib/Sema/SemaFunctionEffects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1208,8 +1208,16 @@ class Analyzer {
return true;
}

// No Decl, just an Expr. Just check based on its type.
checkIndirectCall(Call, CalleeExpr->getType());
// No Decl, just an Expr. Just check based on its type. Bound member
// functions are a special expression type and need to be specially
// unpacked.
QualType CalleeExprQT = CalleeExpr->getType();
if (CalleeExpr->isBoundMemberFunction(Outer.S.getASTContext())) {
QualType QT = Expr::findBoundMemberType(CalleeExpr);
if (!QT.isNull())
CalleeExprQT = QT;
}
checkIndirectCall(Call, CalleeExprQT);

return true;
}
Expand Down
33 changes: 26 additions & 7 deletions clang/test/Sema/attr-nonblocking-constraints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,16 +235,35 @@ void nb13() [[clang::nonblocking]] { nb12(); }
// C++ member function pointers
struct PTMFTester {
typedef void (PTMFTester::*ConvertFunction)() [[clang::nonblocking]];

void convert() [[clang::nonblocking]];
typedef void (PTMFTester::*BlockingFunction)();

ConvertFunction mConvertFunc;
};

void PTMFTester::convert() [[clang::nonblocking]]
{
(this->*mConvertFunc)();
}
void convert() [[clang::nonblocking]]
{
(this->*mConvertFunc)(); // This should not generate a warning.
}

template <typename T>
struct Holder {
T value;

T& operator*() { return value; }
};


void ptmfInExpr(Holder<ConvertFunction>& holder) [[clang::nonblocking]]
{
(this->*(*holder))(); // Should not generate a warning.
((*this).*(*holder))(); // Should not generate a warning.
}

void ptmfInExpr(Holder<BlockingFunction>& holder) [[clang::nonblocking]]
{
(this->*(*holder))(); // expected-warning {{function with 'nonblocking' attribute must not call non-'nonblocking' expression}}
((*this).*(*holder))(); // expected-warning {{function with 'nonblocking' attribute must not call non-'nonblocking' expression}}
}
};

// Allow implicit conversion from array to pointer.
void nb14(unsigned idx) [[clang::nonblocking]]
Expand Down