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