Skip to content

Commit 99b66fb

Browse files
author
huqizhi
committed
[Clang][Sema] Allow access to a public template alias declaration that refers to friend's private nested type
1 parent d9ae4a6 commit 99b66fb

File tree

4 files changed

+48
-0
lines changed

4 files changed

+48
-0
lines changed

clang/include/clang/Sema/Lookup.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,10 @@ class LookupResult {
752752
IDNS &= ~Decl::IDNS_LocalExtern;
753753
}
754754

755+
void setNestedNameSpecifier(NestedNameSpecifier *Q) { Qualifier = Q; }
756+
757+
NestedNameSpecifier *getNestedNameSpecifier() const { return Qualifier; }
758+
755759
private:
756760
void diagnoseAccess() {
757761
if (!isAmbiguous() && isClassLookup() &&
@@ -792,6 +796,7 @@ class LookupResult {
792796
CXXBasePaths *Paths = nullptr;
793797
CXXRecordDecl *NamingClass = nullptr;
794798
QualType BaseObjectType;
799+
NestedNameSpecifier *Qualifier = nullptr;
795800

796801
// Parameters.
797802
Sema *SemaPtr;

clang/lib/Sema/SemaAccess.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,9 @@ struct AccessTarget : public AccessedEntity {
254254
namingClass = cast<CXXRecordDecl>(namingClass->getParent());
255255
return namingClass->getCanonicalDecl();
256256
}
257+
void setNestedNameSpecifier(NestedNameSpecifier *Q) { Qualifier = Q; }
258+
259+
NestedNameSpecifier *getNestedNameSpecifier() const { return Qualifier; }
257260

258261
private:
259262
void initialize() {
@@ -274,6 +277,7 @@ struct AccessTarget : public AccessedEntity {
274277
mutable bool CalculatedInstanceContext : 1;
275278
mutable const CXXRecordDecl *InstanceContext;
276279
const CXXRecordDecl *DeclaringClass;
280+
NestedNameSpecifier *Qualifier = nullptr;
277281
};
278282

279283
}
@@ -1481,6 +1485,20 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
14811485
}
14821486

14831487
EffectiveContext EC(S.CurContext);
1488+
if (Entity.getNestedNameSpecifier())
1489+
if (const Type *Ty = Entity.getNestedNameSpecifier()->getAsType())
1490+
switch (Ty->getTypeClass()) {
1491+
case Type::TypeClass::SubstTemplateTypeParm:
1492+
if (auto *SubstTemplateTy = Ty->getAs<SubstTemplateTypeParmType>())
1493+
if (auto *D = SubstTemplateTy->getAssociatedDecl())
1494+
if (auto *RD = dyn_cast_or_null<CXXRecordDecl>(D->getDeclContext()))
1495+
EC.Records.push_back(RD);
1496+
1497+
break;
1498+
default:
1499+
break;
1500+
}
1501+
14841502
switch (CheckEffectiveAccess(S, EC, Loc, Entity)) {
14851503
case AR_accessible: return Sema::AR_accessible;
14861504
case AR_inaccessible: return Sema::AR_inaccessible;
@@ -1916,6 +1934,7 @@ void Sema::CheckLookupAccess(const LookupResult &R) {
19161934
AccessTarget Entity(Context, AccessedEntity::Member,
19171935
R.getNamingClass(), I.getPair(),
19181936
R.getBaseObjectType());
1937+
Entity.setNestedNameSpecifier(R.getNestedNameSpecifier());
19191938
Entity.setDiag(diag::err_access);
19201939
CheckAccess(*this, R.getNameLoc(), Entity);
19211940
}

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11275,6 +11275,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
1127511275

1127611276
DeclarationName Name(&II);
1127711277
LookupResult Result(*this, Name, IILoc, LookupOrdinaryName);
11278+
Result.setNestedNameSpecifier(QualifierLoc.getNestedNameSpecifier());
1127811279
if (Ctx)
1127911280
LookupQualifiedName(Result, Ctx, SS);
1128011281
else

clang/test/SemaTemplate/PR25708.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %clang_cc1 -std=c++11 -verify %s
2+
// RUN: %clang_cc1 -std=c++14 -verify %s
3+
// RUN: %clang_cc1 -std=c++17 -verify %s
4+
// RUN: %clang_cc1 -std=c++20 -verify %s
5+
// expected-no-diagnostics
6+
7+
struct FooAccessor
8+
{
9+
template <typename T>
10+
using Foo = typename T::Foo;
11+
};
12+
13+
class Type
14+
{
15+
friend struct FooAccessor;
16+
17+
using Foo = int;
18+
};
19+
20+
int main()
21+
{
22+
FooAccessor::Foo<Type> t;
23+
}

0 commit comments

Comments
 (0)