From: Yi Kong Date: Tue, 13 Jun 2017 18:38:31 +0000 (+0000) Subject: Fix spurious Wunused-lambda-capture warning X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6c7060619c4c2c8195dfd974136ab9cf9bac42e9;p=clang Fix spurious Wunused-lambda-capture warning Summary: Clang emits unused-lambda-capture warning for captures in generic lambdas even though they are actually used. Fixes PR31815. Reviewers: malcolm.parsons, aaron.ballman, rsmith Reviewed By: malcolm.parsons Subscribers: ahatanak, cfe-commits Differential Revision: https://reviews.llvm.org/D33526 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@305315 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index a6239283b4..d6b70610d4 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -1492,6 +1492,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, bool ExplicitResultType; CleanupInfo LambdaCleanup; bool ContainsUnexpandedParameterPack; + bool IsGenericLambda; { CallOperator = LSI->CallOperator; Class = LSI->Lambda; @@ -1500,7 +1501,8 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, ExplicitResultType = !LSI->HasImplicitReturnType; LambdaCleanup = LSI->Cleanup; ContainsUnexpandedParameterPack = LSI->ContainsUnexpandedParameterPack; - + IsGenericLambda = Class->isGenericLambda(); + CallOperator->setLexicalDeclContext(Class); Decl *TemplateOrNonTemplateCallOperatorDecl = CallOperator->getDescribedFunctionTemplate() @@ -1520,8 +1522,13 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, bool IsImplicit = I >= LSI->NumExplicitCaptures; // Warn about unused explicit captures. - if (!CurContext->isDependentContext() && !IsImplicit && !From.isODRUsed()) - DiagnoseUnusedLambdaCapture(From); + if (!CurContext->isDependentContext() && !IsImplicit && !From.isODRUsed()) { + // Initialized captures that are non-ODR used may not be eliminated. + bool NonODRUsedInitCapture = + IsGenericLambda && From.isNonODRUsed() && From.getInitExpr(); + if (!NonODRUsedInitCapture) + DiagnoseUnusedLambdaCapture(From); + } // Handle 'this' capture. if (From.isThisCapture()) { @@ -1568,8 +1575,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, // same parameter and return types as the closure type's function call // operator. // FIXME: Fix generic lambda to block conversions. - if (getLangOpts().Blocks && getLangOpts().ObjC1 && - !Class->isGenericLambda()) + if (getLangOpts().Blocks && getLangOpts().ObjC1 && !IsGenericLambda) addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator); // Finalize the lambda class. diff --git a/test/SemaCXX/warn-unused-lambda-capture.cpp b/test/SemaCXX/warn-unused-lambda-capture.cpp index 48f8bfea7e..6ad8e26604 100644 --- a/test/SemaCXX/warn-unused-lambda-capture.cpp +++ b/test/SemaCXX/warn-unused-lambda-capture.cpp @@ -142,11 +142,14 @@ void test_templated() { auto implicit_by_reference = [&] { i++; }; auto explicit_by_value_used = [i] { return i + 1; }; + auto explicit_by_value_used_generic = [i](auto c) { return i + 1; }; auto explicit_by_value_used_void = [i] { (void)i; }; + auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda capture 'i' is not used}} auto explicit_by_value_unused_sizeof = [i] { return sizeof(i); }; // expected-warning{{lambda capture 'i' is not required to be captured for this use}} auto explicit_by_value_unused_decltype = [i] { decltype(i) j = 0; }; // expected-warning{{lambda capture 'i' is not used}} auto explicit_by_value_unused_const = [k] { return k + 1; }; // expected-warning{{lambda capture 'k' is not required to be captured for this use}} + auto explicit_by_value_unused_const_generic = [k](auto c) { return k + 1; }; // expected-warning{{lambda capture 'k' is not required to be captured for this use}} auto explicit_by_reference_used = [&i] { i++; }; auto explicit_by_reference_unused = [&i] {}; // expected-warning{{lambda capture 'i' is not used}} @@ -161,6 +164,8 @@ void test_templated() { auto explicit_initialized_value_trivial_init = [j = Trivial()]{}; // expected-warning{{lambda capture 'j' is not used}} auto explicit_initialized_value_non_trivial_init = [j = Trivial(42)]{}; auto explicit_initialized_value_with_side_effect = [j = side_effect()]{}; + auto explicit_initialized_value_generic_used = [i = 1](auto c) mutable { i++; }; + auto explicit_initialized_value_generic_unused = [i = 1](auto c) mutable {}; // expected-warning{{lambda capture 'i' is not used}} auto nested = [&i] { auto explicit_by_value_used = [i] { return i + 1; };