r241428 - PR24030, PR24033: Consistently check whether a new declaration conflicts with
Sean Silva
chisophugis at gmail.com
Mon Jul 6 14:56:38 PDT 2015
+ 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-llvm at 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 at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150706/c39a3121/attachment.html>
More information about the cfe-commits
mailing list