Index: cfe/trunk/include/clang/Sema/Sema.h =================================================================== --- cfe/trunk/include/clang/Sema/Sema.h +++ cfe/trunk/include/clang/Sema/Sema.h @@ -1709,7 +1709,8 @@ static bool adjustContextForLocalExternDecl(DeclContext *&DC); void DiagnoseFunctionSpecifiers(const DeclSpec &DS); - void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R); + NamedDecl *getShadowedDeclaration(const VarDecl *D, const LookupResult &R); + void CheckShadow(VarDecl *D, NamedDecl *ShadowedDecl, const LookupResult &R); void CheckShadow(Scope *S, VarDecl *D); /// Warn if 'E', which is an expression that is about to be modified, refers Index: cfe/trunk/lib/Sema/SemaDecl.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp +++ cfe/trunk/lib/Sema/SemaDecl.cpp @@ -6426,9 +6426,10 @@ } } - // Diagnose shadowed variables before filtering for scope. - if (D.getCXXScopeSpec().isEmpty()) - CheckShadow(S, NewVD, Previous); + // Find the shadowed declaration before filtering for scope. + NamedDecl *ShadowedDecl = D.getCXXScopeSpec().isEmpty() + ? getShadowedDeclaration(NewVD, Previous) + : nullptr; // Don't consider existing declarations that are in a different // scope and are out-of-semantic-context declarations (if the new @@ -6523,6 +6524,10 @@ } } + // Diagnose shadowed variables iff this isn't a redeclaration. + if (ShadowedDecl && !D.isRedeclaration()) + CheckShadow(NewVD, ShadowedDecl, Previous); + ProcessPragmaWeak(S, NewVD); // If this is the first declaration of an extern C variable, update @@ -6596,33 +6601,40 @@ return SourceLocation(); } -/// \brief Diagnose variable or built-in function shadowing. Implements -/// -Wshadow. -/// -/// This method is called whenever a VarDecl is added to a "useful" -/// scope. -/// -/// \param S the scope in which the shadowing name is being declared -/// \param R the lookup of the name -/// -void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) { +/// \brief Return the declaration shadowed by the given variable \p D, or null +/// if it doesn't shadow any declaration or shadowing warnings are disabled. +NamedDecl *Sema::getShadowedDeclaration(const VarDecl *D, + const LookupResult &R) { // Return if warning is ignored. if (Diags.isIgnored(diag::warn_decl_shadow, R.getNameLoc())) - return; + return nullptr; // Don't diagnose declarations at file scope. if (D->hasGlobalStorage()) - return; - - DeclContext *NewDC = D->getDeclContext(); + return nullptr; // Only diagnose if we're shadowing an unambiguous field or variable. if (R.getResultKind() != LookupResult::Found) - return; + return nullptr; - NamedDecl* ShadowedDecl = R.getFoundDecl(); - if (!isa(ShadowedDecl) && !isa(ShadowedDecl)) - return; + NamedDecl *ShadowedDecl = R.getFoundDecl(); + return isa(ShadowedDecl) || isa(ShadowedDecl) + ? ShadowedDecl + : nullptr; +} + +/// \brief Diagnose variable or built-in function shadowing. Implements +/// -Wshadow. +/// +/// This method is called whenever a VarDecl is added to a "useful" +/// scope. +/// +/// \param ShadowedDecl the declaration that is shadowed by the given variable +/// \param R the lookup of the name +/// +void Sema::CheckShadow(VarDecl *D, NamedDecl *ShadowedDecl, + const LookupResult &R) { + DeclContext *NewDC = D->getDeclContext(); if (FieldDecl *FD = dyn_cast(ShadowedDecl)) { // Fields are not shadowed by variables in C++ static methods. @@ -6733,7 +6745,8 @@ LookupResult R(*this, D->getDeclName(), D->getLocation(), Sema::LookupOrdinaryName, Sema::ForRedeclaration); LookupName(R, S); - CheckShadow(S, D, R); + if (NamedDecl *ShadowedDecl = getShadowedDeclaration(D, R)) + CheckShadow(D, ShadowedDecl, R); } /// Check if 'E', which is an expression that is about to be modified, refers Index: cfe/trunk/test/SemaCXX/warn-shadow-in-lambdas.cpp =================================================================== --- cfe/trunk/test/SemaCXX/warn-shadow-in-lambdas.cpp +++ cfe/trunk/test/SemaCXX/warn-shadow-in-lambdas.cpp @@ -137,3 +137,11 @@ auto g3 = [param] // expected-note {{variable 'param' is explicitly captured here}} (auto param) { ; }; // expected-warning {{declaration shadows a local variable}} } + +void avoidWarningWhenRedefining() { + int a = 1; + auto l = [b = a] { // expected-note {{previous definition is here}} + // Don't warn on redefinitions. + int b = 0; // expected-error {{redefinition of 'b'}} + }; +} Index: cfe/trunk/test/SemaCXX/warn-shadow.cpp =================================================================== --- cfe/trunk/test/SemaCXX/warn-shadow.cpp +++ cfe/trunk/test/SemaCXX/warn-shadow.cpp @@ -97,3 +97,13 @@ void test8() { int bob; // expected-warning {{declaration shadows a variable in the global namespace}} } + +namespace rdar29067894 { + +void avoidWarningWhenRedefining(int b) { // expected-note {{previous definition is here}} + int a = 0; // expected-note {{previous definition is here}} + int a = 1; // expected-error {{redefinition of 'a'}} + int b = 2; // expected-error {{redefinition of 'b'}} +} + +}