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 @@ -12377,6 +12377,13 @@ D.setInvalidType(true); } } + + if (LangOpts.CPlusPlus) { + 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 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 @@ -62,7 +62,7 @@ void test() { char *field; // expected-warning {{declaration shadows a field of 'A'}} char *data; // expected-warning {{declaration shadows a static data member of 'A'}} - char *a1; // no warning + char *a1; // no warning char *a2; // no warning char *jj; // no warning char *jjj; // no warning @@ -199,8 +199,8 @@ using l=char; // no warning or error. using l=char; // no warning or error. typedef char l; // no warning or error. - - typedef char n; // no warning or error. + + typedef char n; // no warning or error. typedef char n; // no warning or error. using n=char; // no warning or error. } @@ -222,3 +222,31 @@ }; } } + +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 +}; + +struct Static { + static int B; +}; + +struct Derived2 : Static { + void D(int B) {} +}; +}