From c19ee3eb08ce1d77504d5fc27f7c44b94543221b Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 17 Jun 2009 23:37:01 +0000 Subject: [PATCH] Diagnose class members that shadow a template parameter. Fixes . To do this, we actually remove a not-quite-correct optimization in the C++ name lookup routines. We'll revisit this optimization for the general case once more C++ is working. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73659 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDecl.cpp | 8 ++++++++ lib/Sema/SemaLookup.cpp | 4 ++-- lib/Sema/SemaTemplate.cpp | 3 +++ test/Parser/cxx-template-decl.cpp | 11 +++++++++++ test/SemaTemplate/nested-template.cpp | 2 +- 5 files changed, 25 insertions(+), 3 deletions(-) diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 3c6f706f15..77460359f4 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3807,6 +3807,14 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); NamedDecl *PrevDecl = LookupName(S, II, LookupMemberName, true); + + if (PrevDecl && PrevDecl->isTemplateParameter()) { + // Maybe we will complain about the shadowed template parameter. + DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); + // Just pretend that we didn't see the previous declaration. + PrevDecl = 0; + } + if (PrevDecl && !isDeclInScope(PrevDecl, Record, S)) PrevDecl = 0; diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 1d26845fd8..f29cd17481 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -685,7 +685,7 @@ Sema::CppLookupName(Scope *S, DeclarationName Name, // identifier chain. if (isa(Ctx)) { R = LookupQualifiedName(Ctx, Name, NameKind, RedeclarationOnly); - if (R || RedeclarationOnly) + if (R) return std::make_pair(true, R); } if (Ctx->getParent() != Ctx->getLexicalParent() @@ -697,7 +697,7 @@ Sema::CppLookupName(Scope *S, DeclarationName Name, for (OutOfLineCtx = Ctx; OutOfLineCtx && !OutOfLineCtx->isFileContext(); OutOfLineCtx = OutOfLineCtx->getParent()) { R = LookupQualifiedName(OutOfLineCtx, Name, NameKind, RedeclarationOnly); - if (R || RedeclarationOnly) + if (R) return std::make_pair(true, R); } } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 0ae9f1d077..fb41b2b753 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -444,6 +444,9 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK, if (Previous.begin() != Previous.end()) PrevDecl = *Previous.begin(); + if (PrevDecl && !isDeclInScope(PrevDecl, CurContext, S)) + PrevDecl = 0; + DeclContext *SemanticContext = CurContext; if (SS.isNotEmpty() && !SS.isInvalid()) { SemanticContext = computeDeclContext(SS); diff --git a/test/Parser/cxx-template-decl.cpp b/test/Parser/cxx-template-decl.cpp index ae5d8f9e0c..75b26a98e4 100644 --- a/test/Parser/cxx-template-decl.cpp +++ b/test/Parser/cxx-template-decl.cpp @@ -66,6 +66,17 @@ class T { // expected-error{{declaration of 'T' shadows template parameter}} template // expected-note{{template parameter is declared here}} void shadow3(int Size); // expected-error{{declaration of 'Size' shadows template parameter}} +// +template // expected-note{{here}} +struct shadow4 { + int T; // expected-error{{shadows}} +}; + +template // expected-note{{here}} +struct shadow5 { + int T(int, float); // expected-error{{shadows}} +}; + // Non-type template parameters in scope template void f(int& i) { diff --git a/test/SemaTemplate/nested-template.cpp b/test/SemaTemplate/nested-template.cpp index bd9e89f76a..84b1d35ba9 100644 --- a/test/SemaTemplate/nested-template.cpp +++ b/test/SemaTemplate/nested-template.cpp @@ -1,4 +1,4 @@ -// RUN: clang-cc -fsyntax-only %s +// RUN: clang-cc -fsyntax-only -verify %s class A; -- 2.40.0