From: Richard Smith Date: Wed, 23 Mar 2016 20:39:06 +0000 (+0000) Subject: Make SemaAccess smarter about determining when a dependent class might X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c1d4062ba3bb3451703c1d14116b8450201c35e1;p=clang Make SemaAccess smarter about determining when a dependent class might instantiate to match a friend class declaration. It's still pretty dumb, though. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@264189 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp index 4bca280824..28ecc0e406 100644 --- a/lib/Sema/SemaAccess.cpp +++ b/lib/Sema/SemaAccess.cpp @@ -291,9 +291,10 @@ static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived, SmallVector Queue; // actually a stack while (true) { - if (Derived->isDependentContext() && !Derived->hasDefinition()) + if (Derived->isDependentContext() && !Derived->hasDefinition() && + !Derived->isLambda()) return AR_dependent; - + for (const auto &I : Derived->bases()) { const CXXRecordDecl *RD; @@ -410,14 +411,8 @@ static AccessResult MatchesFriend(Sema &S, return AR_accessible; if (EC.isDependent()) { - CanQualType FriendTy - = S.Context.getCanonicalType(S.Context.getTypeDeclType(Friend)); - - for (EffectiveContext::record_iterator - I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { - CanQualType ContextTy - = S.Context.getCanonicalType(S.Context.getTypeDeclType(*I)); - if (MightInstantiateTo(S, ContextTy, FriendTy)) + for (const CXXRecordDecl *Context : EC.Records) { + if (MightInstantiateTo(Context, Friend)) return AR_dependent; } } diff --git a/test/CXX/drs/dr5xx.cpp b/test/CXX/drs/dr5xx.cpp index 96d3494bf0..e0bab57e52 100644 --- a/test/CXX/drs/dr5xx.cpp +++ b/test/CXX/drs/dr5xx.cpp @@ -814,7 +814,7 @@ namespace dr577 { // dr577: yes } } -namespace dr580 { // dr580: no +namespace dr580 { // dr580: partial class C; struct A { static C c; }; struct B { static C c; }; @@ -822,7 +822,7 @@ namespace dr580 { // dr580: no C(); // expected-note {{here}} ~C(); // expected-note {{here}} - typedef int I; // expected-note {{here}} + typedef int I; // expected-note 2{{here}} template struct X; template friend struct Y; template void f(); @@ -832,7 +832,20 @@ namespace dr580 { // dr580: no template struct C::X {}; template struct Y {}; - template struct Z {}; // FIXME: should reject, accepted because C befriends A! + template struct Z {}; // expected-error {{private}} + + struct C2 { + class X { + struct A; + typedef int I; + friend struct A; + }; + class Y { + template struct A {}; // FIXME: We incorrectly accept this + // because we think C2::Y::A<...> might + // instantiate to C2::X::A + }; + }; template void C::f() {} template void g() {} diff --git a/test/SemaCXX/access.cpp b/test/SemaCXX/access.cpp index cd65f907b8..29a58a1388 100644 --- a/test/SemaCXX/access.cpp +++ b/test/SemaCXX/access.cpp @@ -167,5 +167,5 @@ namespace ThisLambdaIsNotMyFriend { template void foo() { []() { A::foo(); }(); // expected-error {{private}} } - void bar() { foo(); } // expected-note {{instantiation}} + void bar() { foo(); } } diff --git a/www/cxx_dr_status.html b/www/cxx_dr_status.html index 28af0749a5..8e0646d8ee 100644 --- a/www/cxx_dr_status.html +++ b/www/cxx_dr_status.html @@ -3523,7 +3523,7 @@ and POD class 580 C++11 Access in template-parameters of member and friend definitions - No + Partial 581