[clang] [Clang][Sema] Allow access to a public template alias declaration that refers to friend's private nested type (PR #83847)
Qizhi Hu via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 4 18:41:14 PST 2024
https://github.com/jcsxky updated https://github.com/llvm/llvm-project/pull/83847
>From e3c4715acdc1ead6596b1368590696a04e559414 Mon Sep 17 00:00:00 2001
From: huqizhi <huqizhi at feysh.com>
Date: Mon, 4 Mar 2024 21:51:07 +0800
Subject: [PATCH] [Clang][Sema] Allow access to a public template alias
declaration that refers to friend's private nested type
---
clang/docs/ReleaseNotes.rst | 3 +++
clang/include/clang/Sema/Lookup.h | 5 +++++
clang/lib/Sema/SemaAccess.cpp | 19 +++++++++++++++++++
clang/lib/Sema/SemaTemplate.cpp | 1 +
clang/test/SemaTemplate/PR25708.cpp | 23 +++++++++++++++++++++++
5 files changed, 51 insertions(+)
create mode 100644 clang/test/SemaTemplate/PR25708.cpp
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 612b4329727455..02e378cf838a27 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -224,6 +224,9 @@ Bug Fixes in This Version
for variables created through copy initialization having side-effects in C++17 and later.
Fixes (#GH64356) (#GH79518).
+- Allow access to a public template alias declaration that refers to friend's
+ private nested type (`#29217 <https://github.com/llvm/llvm-project/issues/29217>`).
+
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Sema/Lookup.h b/clang/include/clang/Sema/Lookup.h
index 2f2f2607a937fe..a07609bfb7c9bc 100644
--- a/clang/include/clang/Sema/Lookup.h
+++ b/clang/include/clang/Sema/Lookup.h
@@ -752,6 +752,10 @@ class LookupResult {
IDNS &= ~Decl::IDNS_LocalExtern;
}
+ void setNestedNameSpecifier(NestedNameSpecifier *Q) { Qualifier = Q; }
+
+ NestedNameSpecifier *getNestedNameSpecifier() const { return Qualifier; }
+
private:
void diagnoseAccess() {
if (!isAmbiguous() && isClassLookup() &&
@@ -792,6 +796,7 @@ class LookupResult {
CXXBasePaths *Paths = nullptr;
CXXRecordDecl *NamingClass = nullptr;
QualType BaseObjectType;
+ NestedNameSpecifier *Qualifier = nullptr;
// Parameters.
Sema *SemaPtr;
diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp
index 4af3c0f30a8e8a..9077066da29d61 100644
--- a/clang/lib/Sema/SemaAccess.cpp
+++ b/clang/lib/Sema/SemaAccess.cpp
@@ -254,6 +254,9 @@ struct AccessTarget : public AccessedEntity {
namingClass = cast<CXXRecordDecl>(namingClass->getParent());
return namingClass->getCanonicalDecl();
}
+ void setNestedNameSpecifier(NestedNameSpecifier *Q) { Qualifier = Q; }
+
+ NestedNameSpecifier *getNestedNameSpecifier() const { return Qualifier; }
private:
void initialize() {
@@ -274,6 +277,7 @@ struct AccessTarget : public AccessedEntity {
mutable bool CalculatedInstanceContext : 1;
mutable const CXXRecordDecl *InstanceContext;
const CXXRecordDecl *DeclaringClass;
+ NestedNameSpecifier *Qualifier = nullptr;
};
}
@@ -1481,6 +1485,20 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc,
}
EffectiveContext EC(S.CurContext);
+ if (Entity.getNestedNameSpecifier())
+ if (const Type *Ty = Entity.getNestedNameSpecifier()->getAsType())
+ switch (Ty->getTypeClass()) {
+ case Type::TypeClass::SubstTemplateTypeParm:
+ if (auto *SubstTemplateTy = Ty->getAs<SubstTemplateTypeParmType>())
+ if (auto *D = SubstTemplateTy->getAssociatedDecl())
+ if (auto *RD = dyn_cast_or_null<CXXRecordDecl>(D->getDeclContext()))
+ EC.Records.push_back(RD);
+
+ break;
+ default:
+ break;
+ }
+
switch (CheckEffectiveAccess(S, EC, Loc, Entity)) {
case AR_accessible: return Sema::AR_accessible;
case AR_inaccessible: return Sema::AR_inaccessible;
@@ -1916,6 +1934,7 @@ void Sema::CheckLookupAccess(const LookupResult &R) {
AccessTarget Entity(Context, AccessedEntity::Member,
R.getNamingClass(), I.getPair(),
R.getBaseObjectType());
+ Entity.setNestedNameSpecifier(R.getNestedNameSpecifier());
Entity.setDiag(diag::err_access);
CheckAccess(*this, R.getNameLoc(), Entity);
}
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 873ea10ebe0660..2786a1fa9acbc3 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -11273,6 +11273,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
DeclarationName Name(&II);
LookupResult Result(*this, Name, IILoc, LookupOrdinaryName);
+ Result.setNestedNameSpecifier(QualifierLoc.getNestedNameSpecifier());
if (Ctx)
LookupQualifiedName(Result, Ctx, SS);
else
diff --git a/clang/test/SemaTemplate/PR25708.cpp b/clang/test/SemaTemplate/PR25708.cpp
new file mode 100644
index 00000000000000..685c8298c48f6b
--- /dev/null
+++ b/clang/test/SemaTemplate/PR25708.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s
+// RUN: %clang_cc1 -std=c++14 -verify %s
+// RUN: %clang_cc1 -std=c++17 -verify %s
+// RUN: %clang_cc1 -std=c++20 -verify %s
+// expected-no-diagnostics
+
+struct FooAccessor
+{
+ template <typename T>
+ using Foo = typename T::Foo;
+};
+
+class Type
+{
+ friend struct FooAccessor;
+
+ using Foo = int;
+};
+
+int main()
+{
+ FooAccessor::Foo<Type> t;
+}
More information about the cfe-commits
mailing list