Skip to content

Commit a4eee6d

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

File tree

5 files changed

+53
-4
lines changed

5 files changed

+53
-4
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: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1477,8 +1477,16 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
14771477
// void foo(A::private_type);
14781478
// void B::foo(A::private_type);
14791479
if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
1480-
S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity));
1481-
return Sema::AR_delayed;
1480+
Scope *TS = S.getCurScope();
1481+
bool IsFriendDeclaration = false;
1482+
while (TS && !IsFriendDeclaration) {
1483+
IsFriendDeclaration = TS->isFriendScope();
1484+
TS = TS->getParent();
1485+
}
1486+
if (!IsFriendDeclaration) {
1487+
S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity));
1488+
return Sema::AR_delayed;
1489+
}
14821490
}
14831491

14841492
EffectiveContext EC(S.CurContext);

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)