[clang] [Clang] Fix name lookup for dependent bases (PR #114978)
Vladislav Belov via cfe-commits
cfe-commits at lists.llvm.org
Sat Nov 16 19:39:11 PST 2024
https://github.com/vbe-sc updated https://github.com/llvm/llvm-project/pull/114978
>From 5a48960ab73890b10381b4e7ebd32d3f66246bdd Mon Sep 17 00:00:00 2001
From: vb-sc <vladislav.belov at syntacore.com>
Date: Tue, 5 Nov 2024 15:46:57 +0300
Subject: [PATCH] [clang] Fix name lookup for dependent bases
---
clang/lib/AST/CXXInheritance.cpp | 16 +++++++----
clang/test/CXX/drs/cwg5xx.cpp | 48 ++++++++++++++++++++++++++++++--
2 files changed, 57 insertions(+), 7 deletions(-)
diff --git a/clang/lib/AST/CXXInheritance.cpp b/clang/lib/AST/CXXInheritance.cpp
index eb265a872c1259..7961dbc0c7c8a3 100644
--- a/clang/lib/AST/CXXInheritance.cpp
+++ b/clang/lib/AST/CXXInheritance.cpp
@@ -170,13 +170,21 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
QualType BaseType =
Context.getCanonicalType(BaseSpec.getType()).getUnqualifiedType();
+ bool isCurrentInstantiation = isa<InjectedClassNameType>(BaseType);
+ if (!isCurrentInstantiation) {
+ if (auto *BaseRecord = cast_or_null<CXXRecordDecl>(
+ BaseSpec.getType()->getAsRecordDecl()))
+ isCurrentInstantiation = BaseRecord->isDependentContext() &&
+ BaseRecord->isCurrentInstantiation(Record);
+ }
// C++ [temp.dep]p3:
// In the definition of a class template or a member of a class template,
// if a base class of the class template depends on a template-parameter,
// the base class scope is not examined during unqualified name lookup
// either at the point of definition of the class template or member or
// during an instantiation of the class tem- plate or member.
- if (!LookupInDependent && BaseType->isDependentType())
+ if (!LookupInDependent &&
+ (BaseType->isDependentType() && !isCurrentInstantiation))
continue;
// Determine whether we need to visit this base class at all,
@@ -244,9 +252,8 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
return FoundPath;
}
} else if (VisitBase) {
- CXXRecordDecl *BaseRecord;
+ CXXRecordDecl *BaseRecord = nullptr;
if (LookupInDependent) {
- BaseRecord = nullptr;
const TemplateSpecializationType *TST =
BaseSpec.getType()->getAs<TemplateSpecializationType>();
if (!TST) {
@@ -265,8 +272,7 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
BaseRecord = nullptr;
}
} else {
- BaseRecord = cast<CXXRecordDecl>(
- BaseSpec.getType()->castAs<RecordType>()->getDecl());
+ BaseRecord = cast<CXXRecordDecl>(BaseSpec.getType()->getAsRecordDecl());
}
if (BaseRecord &&
lookupInBases(Context, BaseRecord, BaseMatches, LookupInDependent)) {
diff --git a/clang/test/CXX/drs/cwg5xx.cpp b/clang/test/CXX/drs/cwg5xx.cpp
index ed0c7159dfc889..0d53a9d07d76de 100644
--- a/clang/test/CXX/drs/cwg5xx.cpp
+++ b/clang/test/CXX/drs/cwg5xx.cpp
@@ -1178,17 +1178,61 @@ namespace cwg590 { // cwg590: yes
template<typename T> typename A<T>::B::C A<T>::B::C::f(A<T>::B::C) {}
}
-namespace cwg591 { // cwg591: no
+namespace cwg591 { // cwg591: yes
template<typename T> struct A {
typedef int M;
struct B {
typedef void M;
struct C;
+ struct D;
+ };
+ };
+
+ template<typename T> struct G {
+ struct B {
+ typedef int M;
+ struct C {
+ typedef void M;
+ struct D;
+ };
+ };
+ };
+
+ template<typename T> struct H {
+ template<typename U> struct B {
+ typedef int M;
+ template<typename F> struct C {
+ typedef void M;
+ struct D;
+ struct P;
+ };
};
};
template<typename T> struct A<T>::B::C : A<T> {
- // FIXME: Should find member of non-dependent base class A<T>.
+ M m;
+ };
+
+ template<typename T> struct G<T>::B::C::D : B {
+ M m;
+ };
+
+ template<typename T>
+ template<typename U>
+ template<typename F>
+ struct H<T>::B<U>::C<F>::D : B<U> {
+ M m;
+ };
+
+ template<typename T> struct A<T>::B::D : A<T*> {
+ M m;
+ // expected-error at -1 {{field has incomplete type 'M' (aka 'void'}}
+ };
+
+ template<typename T>
+ template<typename U>
+ template<typename F>
+ struct H<T>::B<U>::C<F>::P : B<F> {
M m;
// expected-error at -1 {{field has incomplete type 'M' (aka 'void'}}
};
More information about the cfe-commits
mailing list