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