r241428 - PR24030, PR24033: Consistently check whether a new declaration conflicts with

Richard Smith richard at metafoo.co.uk
Mon Jul 6 15:56:46 PDT 2015


On Mon, Jul 6, 2015 at 2:56 PM, Sean Silva <chisophugis at 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-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/cbcace83/attachment.html>


More information about the cfe-commits mailing list