Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -5619,6 +5619,14 @@ *this, dyn_cast(Fn->IgnoreParens()), Fn->getBeginLoc()); + // Mark this capture as ODR-used if we are in a lambda + // expression and the callee is UnresolvedMemberExpr. + LambdaScopeInfo *CurLSI = getCurLambda(); + if (CurLSI && isa(Fn->IgnoreParens())) + for (auto &Capture : CurLSI->Captures) + if (Capture.isThisCapture()) + Capture.markUsed(/*IsODRUse=*/true); + return CallExpr::Create(Context, Fn, ArgExprs, Context.DependentTy, VK_RValue, RParenLoc); } Index: clang/test/SemaCXX/warn-unused-lambda-capture-this.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/warn-unused-lambda-capture-this.cpp @@ -0,0 +1,80 @@ +// RUN: %clang_cc1 -fsyntax-only -Wunused-lambda-capture -verify %s + +template +class TemplatedStatic { +public: + TemplatedStatic() { + [this](auto value) { Construct(value); }(5); // expected-warning {{lambda capture 'this' is not used}} + } + + template + static void Construct(Arg value) {} +}; + +template +class TemplatedMember { +public: + TemplatedMember() { + [this](auto value) { Construct(value); }(5); + } + + template + void Construct(Arg value) {} +}; + +template +class OverloadedStatic { +public: + OverloadedStatic() { + [this](auto value) { Construct(value); }(5); // expected-warning {{lambda capture 'this' is not used}} + } + + static void Construct(int value) {} + static void Construct(float value) {} +}; + +template +class OverloadedMember { +public: + OverloadedMember() { + [this](auto value) { Construct(value); }(5); + } + + void Construct(int value) {} + void Construct(float value) {} +}; + +template +class OverloadedMixTrueNegative { +public: + OverloadedMixTrueNegative() { + [this](auto value) { Construct(value); }(5); + } + + void Construct(int value) {} + static void Construct(float value) {} +}; + +template +class OverloadedMixFalseNegative { +public: + OverloadedMixFalseNegative() { + // Currently we mark this capture as used whenever UnresolvedMemberExpr + // happens, even if "Construct" will be resolved to the static one. + // Ideally we should issue 'this' not used warning. + [this](auto value) { Construct(value); }(5); + } + + static void Construct(int value) {} + void Construct(float value) {} +}; + +int main() { + TemplatedStatic t1; // expected-note {{in instantiation of member function 'TemplatedStatic::TemplatedStatic' requested here}} + TemplatedMember t2; + OverloadedStatic t3; // expected-note {{in instantiation of member function 'OverloadedStatic::OverloadedStatic' requested here}} + OverloadedMember t4; + OverloadedMixTrueNegative t5; + OverloadedMixFalseNegative t6; + return 0; +}