+ if (SS.isEmpty() && TUK != TUK_Reference && TUK != TUK_Friend && + isDeclInScope(Shadow, SearchDC, S, isExplicitSpecialization) && + !(OldTag && + (getLangOpts().MSVCCompat + ? SearchDC->getRedeclContext()->Encloses( + OldTag->getDeclContext()->getRedeclContext()) || + OldTag->getDeclContext()->getRedeclContext()->Encloses( + SearchDC->getRedeclContext()) + : SearchDC->getRedeclContext()->Equals( + OldTag->getDeclContext()->getRedeclContext())))) {
Can you simplify this? It has a ways to go yet, but it is starting to smell of the infamous https://github.com/gcc-mirror/gcc/blob/7057506456ba18f080679b2fe55ec56ee90fd81c/gcc/reload.c#L1056-L1111 -- Sean Silva On Sun, Jul 5, 2015 at 9:43 PM, Richard Smith <richard-l...@metafoo.co.uk> wrote: > Author: rsmith > Date: Sun Jul 5 23:43:58 2015 > New Revision: 241428 > > URL: http://llvm.org/viewvc/llvm-project?rev=241428&view=rev > Log: > PR24030, PR24033: Consistently check whether a new declaration conflicts > with > an existing using shadow declaration if they define entities of the same > kind > in different namespaces. > > We'd previously check this consistently if the using-declaration came > after the > other declaration, but not if it came before. > > Modified: > cfe/trunk/lib/Sema/SemaDecl.cpp > cfe/trunk/lib/Sema/SemaTemplate.cpp > cfe/trunk/test/SemaCXX/lookup-member.cpp > cfe/trunk/test/SemaCXX/using-decl-1.cpp > > Modified: cfe/trunk/lib/Sema/SemaDecl.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=241428&r1=241427&r2=241428&view=diff > > ============================================================================== > --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) > +++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun Jul 5 23:43:58 2015 > @@ -2577,6 +2577,48 @@ static bool haveIncompatibleLanguageLink > return false; > } > > +template<typename T> static bool isExternC(T *D) { return D->isExternC(); > } > +static bool isExternC(VarTemplateDecl *) { return false; } > + > +/// \brief Check whether a redeclaration of an entity introduced by a > +/// using-declaration is valid, given that we know it's not an overload > +/// (nor a hidden tag declaration). > +template<typename ExpectedDecl> > +static bool checkUsingShadowRedecl(Sema &S, UsingShadowDecl *OldS, > + ExpectedDecl *New) { > + // C++11 [basic.scope.declarative]p4: > + // Given a set of declarations in a single declarative region, each of > + // which specifies the same unqualified name, > + // -- they shall all refer to the same entity, or all refer to > functions > + // and function templates; or > + // -- exactly one declaration shall declare a class name or > enumeration > + // name that is not a typedef name and the other declarations > shall all > + // refer to the same variable or enumerator, or all refer to > functions > + // and function templates; in this case the class name or > enumeration > + // name is hidden (3.3.10). > + > + // C++11 [namespace.udecl]p14: > + // If a function declaration in namespace scope or block scope has the > + // same name and the same parameter-type-list as a function introduced > + // by a using-declaration, and the declarations do not declare the > same > + // function, the program is ill-formed. > + > + auto *Old = dyn_cast<ExpectedDecl>(OldS->getTargetDecl()); > + if (Old && > + !Old->getDeclContext()->getRedeclContext()->Equals( > + New->getDeclContext()->getRedeclContext()) && > + !(isExternC(Old) && isExternC(New))) > + Old = nullptr; > + > + if (!Old) { > + S.Diag(New->getLocation(), diag::err_using_decl_conflict_reverse); > + S.Diag(OldS->getTargetDecl()->getLocation(), > diag::note_using_decl_target); > + S.Diag(OldS->getUsingDecl()->getLocation(), diag::note_using_decl) << > 0; > + return true; > + } > + return false; > +} > + > /// MergeFunctionDecl - We just parsed a function 'New' from > /// declarator D which has the same name and scope as a previous > /// declaration 'Old'. Figure out how to resolve this situation, > @@ -2603,28 +2645,10 @@ bool Sema::MergeFunctionDecl(FunctionDec > return true; > } > > - // C++11 [namespace.udecl]p14: > - // If a function declaration in namespace scope or block scope > has the > - // same name and the same parameter-type-list as a function > introduced > - // by a using-declaration, and the declarations do not declare > the same > - // function, the program is ill-formed. > - > // Check whether the two declarations might declare the same > function. > - Old = dyn_cast<FunctionDecl>(Shadow->getTargetDecl()); > - if (Old && > - !Old->getDeclContext()->getRedeclContext()->Equals( > - New->getDeclContext()->getRedeclContext()) && > - !(Old->isExternC() && New->isExternC())) > - Old = nullptr; > - > - if (!Old) { > - Diag(New->getLocation(), diag::err_using_decl_conflict_reverse); > - Diag(Shadow->getTargetDecl()->getLocation(), > - diag::note_using_decl_target); > - Diag(Shadow->getUsingDecl()->getLocation(), > diag::note_using_decl) << 0; > + if (checkUsingShadowRedecl<FunctionDecl>(*this, Shadow, New)) > return true; > - } > - OldD = Old; > + OldD = Old = cast<FunctionDecl>(Shadow->getTargetDecl()); > } else { > Diag(New->getLocation(), diag::err_redefinition_different_kind) > << New->getDeclName(); > @@ -3309,8 +3333,19 @@ void Sema::MergeVarDecl(VarDecl *New, Lo > if (NewTemplate) { > OldTemplate = dyn_cast<VarTemplateDecl>(Previous.getFoundDecl()); > Old = OldTemplate ? OldTemplate->getTemplatedDecl() : nullptr; > - } else > + > + if (auto *Shadow = > + dyn_cast<UsingShadowDecl>(Previous.getRepresentativeDecl())) > + if (checkUsingShadowRedecl<VarTemplateDecl>(*this, Shadow, > NewTemplate)) > + return New->setInvalidDecl(); > + } else { > Old = dyn_cast<VarDecl>(Previous.getFoundDecl()); > + > + if (auto *Shadow = > + dyn_cast<UsingShadowDecl>(Previous.getRepresentativeDecl())) > + if (checkUsingShadowRedecl<VarDecl>(*this, Shadow, New)) > + return New->setInvalidDecl(); > + } > } > if (!Old) { > Diag(New->getLocation(), diag::err_redefinition_different_kind) > @@ -11733,8 +11768,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned > > if (!Previous.empty()) { > NamedDecl *PrevDecl = Previous.getFoundDecl(); > - NamedDecl *DirectPrevDecl = > - getLangOpts().MSVCCompat ? *Previous.begin() : PrevDecl; > + NamedDecl *DirectPrevDecl = Previous.getRepresentativeDecl(); > > // It's okay to have a tag decl in the same scope as a typedef > // which hides a tag decl in the same scope. Finding this > @@ -11761,6 +11795,32 @@ Decl *Sema::ActOnTag(Scope *S, unsigned > } > } > > + // If this is a redeclaration of a using shadow declaration, it must > + // declare a tag in the same context. In MSVC mode, we allow a > + // redefinition if either context is within the other. > + if (auto *Shadow = dyn_cast<UsingShadowDecl>(DirectPrevDecl)) { > + auto *OldTag = dyn_cast<TagDecl>(PrevDecl); > + if (SS.isEmpty() && TUK != TUK_Reference && TUK != TUK_Friend && > + isDeclInScope(Shadow, SearchDC, S, isExplicitSpecialization) && > + !(OldTag && > + (getLangOpts().MSVCCompat > + ? SearchDC->getRedeclContext()->Encloses( > + OldTag->getDeclContext()->getRedeclContext()) || > + OldTag->getDeclContext()->getRedeclContext()->Encloses( > + SearchDC->getRedeclContext()) > + : SearchDC->getRedeclContext()->Equals( > + OldTag->getDeclContext()->getRedeclContext())))) { > + Diag(KWLoc, diag::err_using_decl_conflict_reverse); > + Diag(Shadow->getTargetDecl()->getLocation(), > + diag::note_using_decl_target); > + Diag(Shadow->getUsingDecl()->getLocation(), diag::note_using_decl) > + << 0; > + // Recover by ignoring the old declaration. > + Previous.clear(); > + goto CreateNewDecl; > + } > + } > + > if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) { > // If this is a use of a previous tag, or if the tag is already > declared > // in the same scope (so that the definition/declaration completes > or > @@ -11949,7 +12009,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned > Invalid = true; > > // Otherwise, only diagnose if the declaration is in scope. > - } else if (!isDeclInScope(PrevDecl, SearchDC, S, > + } else if (!isDeclInScope(DirectPrevDecl, SearchDC, S, > SS.isNotEmpty() || > isExplicitSpecialization)) { > // do nothing > > > Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=241428&r1=241427&r2=241428&view=diff > > ============================================================================== > --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original) > +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Sun Jul 5 23:43:58 2015 > @@ -957,8 +957,7 @@ Sema::CheckClassTemplate(Scope *S, unsig > > // Check that the chosen semantic context doesn't already contain > a > // declaration of this name as a non-tag type. > - LookupResult Previous(*this, Name, NameLoc, LookupOrdinaryName, > - ForRedeclaration); > + Previous.clear(LookupOrdinaryName); > DeclContext *LookupContext = SemanticContext; > while (LookupContext->isTransparentContext()) > LookupContext = LookupContext->getLookupParent(); > @@ -972,9 +971,25 @@ Sema::CheckClassTemplate(Scope *S, unsig > } > } > } else if (PrevDecl && > - !isDeclInScope(PrevDecl, SemanticContext, S, SS.isValid())) > + !isDeclInScope(Previous.getRepresentativeDecl(), > SemanticContext, > + S, SS.isValid())) > PrevDecl = PrevClassTemplate = nullptr; > > + if (auto *Shadow = dyn_cast_or_null<UsingShadowDecl>( > + PrevDecl ? Previous.getRepresentativeDecl() : nullptr)) { > + if (SS.isEmpty() && > + !(PrevClassTemplate && > + PrevClassTemplate->getDeclContext()->getRedeclContext()->Equals( > + SemanticContext->getRedeclContext()))) { > + Diag(KWLoc, diag::err_using_decl_conflict_reverse); > + Diag(Shadow->getTargetDecl()->getLocation(), > + diag::note_using_decl_target); > + Diag(Shadow->getUsingDecl()->getLocation(), diag::note_using_decl) > << 0; > + // Recover by ignoring the old declaration. > + PrevDecl = PrevClassTemplate = nullptr; > + } > + } > + > if (PrevClassTemplate) { > // Ensure that the template parameter lists are compatible. Skip this > check > // for a friend in a dependent context: the template parameter list > itself > > Modified: cfe/trunk/test/SemaCXX/lookup-member.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/lookup-member.cpp?rev=241428&r1=241427&r2=241428&view=diff > > ============================================================================== > --- cfe/trunk/test/SemaCXX/lookup-member.cpp (original) > +++ cfe/trunk/test/SemaCXX/lookup-member.cpp Sun Jul 5 23:43:58 2015 > @@ -1,12 +1,11 @@ > // RUN: %clang_cc1 -fsyntax-only -verify %s > -// expected-no-diagnostics > > namespace A { > - class String; > + class String; // expected-note {{target of using declaration}} > }; > > -using A::String; > -class String; > +using A::String; // expected-note {{using declaration}} > +class String; // expected-error {{conflicts with target of using > declaration}} > > // rdar://8603569 > union value { > > Modified: cfe/trunk/test/SemaCXX/using-decl-1.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/using-decl-1.cpp?rev=241428&r1=241427&r2=241428&view=diff > > ============================================================================== > --- cfe/trunk/test/SemaCXX/using-decl-1.cpp (original) > +++ cfe/trunk/test/SemaCXX/using-decl-1.cpp Sun Jul 5 23:43:58 2015 > @@ -263,3 +263,67 @@ struct B : A { > static int f() { return n; } // expected-error {{invalid use of member > 'n' in static member function}} > }; > } > + > +namespace PR24030 { > + namespace X { > + class A; // expected-note {{target}} > + int i; // expected-note {{target}} > + } > + namespace Y { > + using X::A; // expected-note {{using}} > + using X::i; // expected-note {{using}} > + class A {}; // expected-error {{conflicts}} > + int i; // expected-error {{conflicts}} > + } > +} > + > +namespace PR24033 { > + extern int a; // expected-note 2{{target of using declaration}} > + void f(); // expected-note 2{{target of using declaration}} > + struct s; // expected-note 2{{target of using declaration}} > + enum e {}; // expected-note 2{{target of using declaration}} > + > + template<typename> extern int vt; // expected-note 2{{target of using > declaration}} expected-warning 0-1{{extension}} > + template<typename> void ft(); // expected-note 2{{target of using > declaration}} > + template<typename> struct st; // expected-note 2{{target of using > declaration}} > + > + namespace X { > + using PR24033::a; // expected-note {{using declaration}} > + using PR24033::f; // expected-note {{using declaration}} > + using PR24033::s; // expected-note {{using declaration}} > + using PR24033::e; // expected-note {{using declaration}} > + > + using PR24033::vt; // expected-note {{using declaration}} > + using PR24033::ft; // expected-note {{using declaration}} > + using PR24033::st; // expected-note {{using declaration}} > + > + extern int a; // expected-error {{declaration conflicts with target > of using declaration already in scope}} > + void f(); // expected-error {{declaration conflicts with target of > using declaration already in scope}} > + struct s; // expected-error {{declaration conflicts with target of > using declaration already in scope}} > + enum e {}; // expected-error {{declaration conflicts with target of > using declaration already in scope}} > + > + template<typename> extern int vt; // expected-error {{declaration > conflicts with target of using declaration already in scope}} > expected-warning 0-1{{extension}} > + template<typename> void ft(); // expected-error {{declaration > conflicts with target of using declaration already in scope}} > + template<typename> struct st; // expected-error {{declaration > conflicts with target of using declaration already in scope}} > + } > + > + namespace Y { > + extern int a; // expected-note {{conflicting declaration}} > + void f(); // expected-note {{conflicting declaration}} > + struct s; // expected-note {{conflicting declaration}} > + enum e {}; // expected-note {{conflicting declaration}} > + > + template<typename> extern int vt; // expected-note {{conflicting > declaration}} expected-warning 0-1{{extension}} > + template<typename> void ft(); // expected-note {{conflicting > declaration}} > + template<typename> struct st; // expected-note {{conflicting > declaration}} > + > + using PR24033::a; // expected-error {{target of using declaration > conflicts with declaration already in scope}} > + using PR24033::f; // expected-error {{target of using declaration > conflicts with declaration already in scope}} > + using PR24033::s; // expected-error {{target of using declaration > conflicts with declaration already in scope}} > + using PR24033::e; // expected-error {{target of using declaration > conflicts with declaration already in scope}} > + > + using PR24033::vt; // expected-error {{target of using declaration > conflicts with declaration already in scope}} > + using PR24033::ft; // expected-error {{target of using declaration > conflicts with declaration already in scope}} > + using PR24033::st; // expected-error {{target of using declaration > conflicts with declaration already in scope}} > + } > +} > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits