On Mon, Jul 6, 2015 at 2:56 PM, Sean Silva <chisophu...@gmail.com> wrote:
> + 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? > Sure, r241518. > 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 > Hah, low blow :-) > -- 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