From 175388c00d0a39838a6d61c54ca6256b34e37dab Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Wed, 9 Nov 2016 10:38:57 +0000 Subject: [Sema] Avoid -Wshadow warnings for shadowed variables that aren't captured by lambdas with an explicit capture list This commit avoids the -Wshadow warning for variables which shadow variables that aren't captured by lambdas with an explicit capture list. It provides an additional note that points to location of the explicit capture. The old behaviour is preserved with -Wshadow-all or -Wshadow-uncaptured-local. rdar://17135966 Differential Revision: https://reviews.llvm.org/D26278 llvm-svn: 286354 --- clang/lib/Sema/SemaDecl.cpp | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'clang/lib/Sema/SemaDecl.cpp') diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e20ae1a0151..1859b7f0116 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -6582,6 +6582,17 @@ static ShadowedDeclKind computeShadowedDeclKind(const NamedDecl *ShadowedDecl, return OldDC->isFileContext() ? SDK_Global : SDK_Local; } +/// Return the location of the capture if the given lambda captures the given +/// variable \p VD, or an invalid source location otherwise. +static SourceLocation getCaptureLocation(const LambdaScopeInfo *LSI, + const VarDecl *VD) { + for (const LambdaScopeInfo::Capture &Capture : LSI->Captures) { + if (Capture.isVariableCapture() && Capture.getVariable() == VD) + return Capture.getLocation(); + } + return SourceLocation(); +} + /// \brief Diagnose variable or built-in function shadowing. Implements /// -Wshadow. /// @@ -6640,6 +6651,22 @@ void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) { DeclContext *OldDC = ShadowedDecl->getDeclContext(); + unsigned WarningDiag = diag::warn_decl_shadow; + SourceLocation CaptureLoc; + if (isa(ShadowedDecl) && NewDC && isa(NewDC)) { + if (const auto *RD = dyn_cast(NewDC->getParent())) { + // Try to avoid warnings for lambdas with an explicit capture list. + if (RD->isLambda() && OldDC->Encloses(NewDC->getLexicalParent()) && + RD->getLambdaCaptureDefault() == LCD_None) { + const auto *LSI = cast(getCurFunction()); + // Warn only when the lambda captures the shadowed decl explicitly. + CaptureLoc = getCaptureLocation(LSI, cast(ShadowedDecl)); + if (CaptureLoc.isInvalid()) + WarningDiag = diag::warn_decl_shadow_uncaptured_local; + } + } + } + // Only warn about certain kinds of shadowing for class members. if (NewDC && NewDC->isRecord()) { // In particular, don't warn about shadowing non-class members. @@ -6661,7 +6688,9 @@ void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) { if (getSourceManager().isInSystemMacro(R.getNameLoc())) return; ShadowedDeclKind Kind = computeShadowedDeclKind(ShadowedDecl, OldDC); - Diag(R.getNameLoc(), diag::warn_decl_shadow) << Name << Kind << OldDC; + Diag(R.getNameLoc(), WarningDiag) << Name << Kind << OldDC; + if (!CaptureLoc.isInvalid()) + Diag(CaptureLoc, diag::note_var_explicitly_captured_here) << Name; Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration); } -- cgit v1.2.3