Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -9418,10 +9418,9 @@ "__final is a GNU extension, consider using C++11 final">, InGroup; -def warn_shadow_field : - Warning<"non-static data member %0 of %1 shadows member inherited from " - "type %2">, - InGroup, DefaultIgnore; +def warn_shadow_field : Warning< + "%select{parameter|non-static data member}3 %0 %select{|of %1 }3shadows " + "member inherited from type %2">, InGroup, DefaultIgnore; def note_shadow_field : Note<"declared here">; def err_multiversion_required_in_redecl : Error< Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -10524,7 +10524,8 @@ /// Check if there is a field shadowing. void CheckShadowInheritedFields(const SourceLocation &Loc, DeclarationName FieldName, - const CXXRecordDecl *RD); + const CXXRecordDecl *RD, + bool DeclIsField = true); /// Check if the given expression contains 'break' or 'continue' /// statement that produces control flow different from GCC. Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -12379,6 +12379,13 @@ } } + if (LangOpts.CPlusPlus && II) { + DeclarationNameInfo DNI = GetNameForDeclarator(D); + if (auto *RD = dyn_cast(CurContext)) + CheckShadowInheritedFields(DNI.getLoc(), DNI.getName(), RD, + /*DeclIsField*/ false); + } + // Temporarily put parameter variables in the translation unit, not // the enclosing context. This prevents them from accidentally // looking like class members in C++. Index: lib/Sema/SemaDeclCXX.cpp =================================================================== --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -2852,7 +2852,8 @@ // Check if there is a field shadowing. void Sema::CheckShadowInheritedFields(const SourceLocation &Loc, DeclarationName FieldName, - const CXXRecordDecl *RD) { + const CXXRecordDecl *RD, + bool DeclIsField) { if (Diags.isIgnored(diag::warn_shadow_field, Loc)) return; @@ -2892,7 +2893,7 @@ if (AS_none != CXXRecordDecl::MergeAccess(P.Access, BaseField->getAccess())) { Diag(Loc, diag::warn_shadow_field) - << FieldName << RD << Base; + << FieldName << RD << Base << DeclIsField; Diag(BaseField->getLocation(), diag::note_shadow_field); Bases.erase(It); } Index: test/SemaCXX/warn-shadow.cpp =================================================================== --- test/SemaCXX/warn-shadow.cpp +++ test/SemaCXX/warn-shadow.cpp @@ -222,3 +222,23 @@ }; } } + +namespace PR34120 { +struct A { + int B; // expected-note {{declared here}} +}; + +class C : public A { + void D(int B) {} // expected-warning {{parameter 'B' shadows member inherited from type 'A'}} + void E() { + extern void f(int B); // Ok + } +}; + +class Private { + int B; +}; +class Derived : Private { + void D(int B) {} // Ok +}; +}