Skip to content

Commit 836a66f

Browse files
jcsxkyhuqizhi
authored and
huqizhi
committed
[Clang][Sema] access checking of friend declaration should not be delayed
1 parent 83f3b1c commit 836a66f

File tree

5 files changed

+50
-3
lines changed

5 files changed

+50
-3
lines changed

clang/include/clang/Sema/Scope.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,9 @@ class Scope {
159159

160160
/// This is a scope of type alias declaration.
161161
TypeAliasScope = 0x20000000,
162+
163+
/// This is a scope of friend declaration.
164+
FriendScope = 0x40000000,
162165
};
163166

164167
private:
@@ -586,6 +589,9 @@ class Scope {
586589
/// Determine whether this scope is a type alias scope.
587590
bool isTypeAliasScope() const { return getFlags() & Scope::TypeAliasScope; }
588591

592+
/// Determine whether this scope is a friend scope.
593+
bool isFriendScope() const { return getFlags() & Scope::FriendScope; }
594+
589595
/// Returns if rhs has a higher scope depth than this.
590596
///
591597
/// The caller is responsible for calling this only if one of the two scopes

clang/lib/Parse/ParseDecl.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4332,9 +4332,12 @@ void Parser::ParseDeclarationSpecifiers(
43324332

43334333
// friend
43344334
case tok::kw_friend:
4335-
if (DSContext == DeclSpecContext::DSC_class)
4335+
if (DSContext == DeclSpecContext::DSC_class) {
43364336
isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID);
4337-
else {
4337+
Scope *CurS = getCurScope();
4338+
if (!isInvalid && CurS)
4339+
CurS->setFlags(CurS->getFlags() | Scope::FriendScope);
4340+
} else {
43384341
PrevSpec = ""; // not actually used by the diagnostic
43394342
DiagID = diag::err_friend_invalid_in_context;
43404343
isInvalid = true;

clang/lib/Sema/Scope.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ void Scope::dumpImpl(raw_ostream &OS) const {
229229
{ClassInheritanceScope, "ClassInheritanceScope"},
230230
{CatchScope, "CatchScope"},
231231
{OpenACCComputeConstructScope, "OpenACCComputeConstructScope"},
232+
{TypeAliasScope, "TypeAliasScope"},
233+
{FriendScope, "FriendScope"},
232234
};
233235

234236
for (auto Info : FlagInfo) {

clang/lib/Sema/SemaAccess.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1476,7 +1476,13 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
14761476
// Or we might be parsing something that will turn out to be a friend:
14771477
// void foo(A::private_type);
14781478
// void B::foo(A::private_type);
1479-
if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
1479+
Scope *TS = S.getCurScope();
1480+
bool IsFriendDeclaration = false;
1481+
while (TS && !IsFriendDeclaration) {
1482+
IsFriendDeclaration = TS->isFriendScope();
1483+
TS = TS->getParent();
1484+
}
1485+
if (S.DelayedDiagnostics.shouldDelayDiagnostics() && !IsFriendDeclaration) {
14801486
S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity));
14811487
return Sema::AR_delayed;
14821488
}

clang/test/SemaCXX/PR12361.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
2+
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s
3+
4+
class D {
5+
class E{
6+
class F{}; // expected-note{{implicitly declared private here}}
7+
friend void foo(D::E::F& q);
8+
};
9+
friend void foo(D::E::F& q); // expected-error{{'F' is a private member of 'D::E'}}
10+
};
11+
12+
void foo(D::E::F& q) {}
13+
14+
class D1 {
15+
class E1{
16+
class F1{}; // expected-note{{implicitly declared private here}}
17+
friend D1::E1::F1 foo1();
18+
};
19+
friend D1::E1::F1 foo1(); // expected-error{{'F1' is a private member of 'D1::E1'}}
20+
};
21+
22+
D1::E1::F1 foo1() { return D1::E1::F1(); }
23+
24+
class D2 {
25+
class E2{
26+
class F2{};
27+
friend void foo2();
28+
};
29+
friend void foo2(){ D2::E2::F2 c;}
30+
};

0 commit comments

Comments
 (0)