Skip to content

Commit d17588a

Browse files
committed
[clang] Fix name lookup for dependent bases
1 parent 73bb022 commit d17588a

File tree

4 files changed

+62
-9
lines changed

4 files changed

+62
-9
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,9 @@ Resolutions to C++ Defect Reports
268268
by default.
269269
(`CWG2521: User-defined literals and reserved identifiers <https://cplusplus.github.io/CWG/issues/2521.html>`_).
270270

271+
- Clang now make correct name lookup when dependent base class is the current instantiation.
272+
(`CWG591: When a dependent base class is the current instantiation <https://cplusplus.github.io/CWG/issues/591.html>`_).
273+
271274
C Language Changes
272275
------------------
273276

clang/lib/AST/CXXInheritance.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches) const {
135135
return false;
136136

137137
CXXRecordDecl *Base =
138-
cast_or_null<CXXRecordDecl>(Ty->getDecl()->getDefinition());
138+
cast_if_present<CXXRecordDecl>(Ty->getDecl()->getDefinition());
139139
if (!Base ||
140140
(Base->isDependentContext() &&
141141
!Base->isCurrentInstantiation(Record))) {
@@ -170,13 +170,21 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
170170
QualType BaseType =
171171
Context.getCanonicalType(BaseSpec.getType()).getUnqualifiedType();
172172

173+
bool isCurrentInstantiation = isa<InjectedClassNameType>(BaseType);
174+
if (!isCurrentInstantiation) {
175+
if (auto *BaseRecord = cast_if_present<CXXRecordDecl>(
176+
BaseSpec.getType()->getAsRecordDecl()))
177+
isCurrentInstantiation = BaseRecord->isDependentContext() &&
178+
BaseRecord->isCurrentInstantiation(Record);
179+
}
173180
// C++ [temp.dep]p3:
174181
// In the definition of a class template or a member of a class template,
175182
// if a base class of the class template depends on a template-parameter,
176183
// the base class scope is not examined during unqualified name lookup
177184
// either at the point of definition of the class template or member or
178185
// during an instantiation of the class tem- plate or member.
179-
if (!LookupInDependent && BaseType->isDependentType())
186+
if (!LookupInDependent &&
187+
(BaseType->isDependentType() && !isCurrentInstantiation))
180188
continue;
181189

182190
// Determine whether we need to visit this base class at all,
@@ -244,9 +252,8 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
244252
return FoundPath;
245253
}
246254
} else if (VisitBase) {
247-
CXXRecordDecl *BaseRecord;
255+
CXXRecordDecl *BaseRecord = nullptr;
248256
if (LookupInDependent) {
249-
BaseRecord = nullptr;
250257
const TemplateSpecializationType *TST =
251258
BaseSpec.getType()->getAs<TemplateSpecializationType>();
252259
if (!TST) {
@@ -265,8 +272,7 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
265272
BaseRecord = nullptr;
266273
}
267274
} else {
268-
BaseRecord = cast<CXXRecordDecl>(
269-
BaseSpec.getType()->castAs<RecordType>()->getDecl());
275+
BaseRecord = cast<CXXRecordDecl>(BaseSpec.getType()->getAsRecordDecl());
270276
}
271277
if (BaseRecord &&
272278
lookupInBases(Context, BaseRecord, BaseMatches, LookupInDependent)) {

clang/test/CXX/drs/cwg5xx.cpp

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,17 +1178,61 @@ namespace cwg590 { // cwg590: yes
11781178
template<typename T> typename A<T>::B::C A<T>::B::C::f(A<T>::B::C) {}
11791179
}
11801180

1181-
namespace cwg591 { // cwg591: no
1181+
namespace cwg591 { // cwg591: yes
11821182
template<typename T> struct A {
11831183
typedef int M;
11841184
struct B {
11851185
typedef void M;
11861186
struct C;
1187+
struct D;
1188+
};
1189+
};
1190+
1191+
template<typename T> struct G {
1192+
struct B {
1193+
typedef int M;
1194+
struct C {
1195+
typedef void M;
1196+
struct D;
1197+
};
1198+
};
1199+
};
1200+
1201+
template<typename T> struct H {
1202+
template<typename U> struct B {
1203+
typedef int M;
1204+
template<typename F> struct C {
1205+
typedef void M;
1206+
struct D;
1207+
struct P;
1208+
};
11871209
};
11881210
};
11891211

11901212
template<typename T> struct A<T>::B::C : A<T> {
1191-
// FIXME: Should find member of non-dependent base class A<T>.
1213+
M m;
1214+
};
1215+
1216+
template<typename T> struct G<T>::B::C::D : B {
1217+
M m;
1218+
};
1219+
1220+
template<typename T>
1221+
template<typename U>
1222+
template<typename F>
1223+
struct H<T>::B<U>::C<F>::D : B<U> {
1224+
M m;
1225+
};
1226+
1227+
template<typename T> struct A<T>::B::D : A<T*> {
1228+
M m;
1229+
// expected-error@-1 {{field has incomplete type 'M' (aka 'void'}}
1230+
};
1231+
1232+
template<typename T>
1233+
template<typename U>
1234+
template<typename F>
1235+
struct H<T>::B<U>::C<F>::P : B<F> {
11921236
M m;
11931237
// expected-error@-1 {{field has incomplete type 'M' (aka 'void'}}
11941238
};

clang/www/cxx_dr_status.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3599,7 +3599,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
35993599
<td><a href="https://cplusplus.github.io/CWG/issues/591.html">591</a></td>
36003600
<td>CD4</td>
36013601
<td>When a dependent base class is the current instantiation</td>
3602-
<td class="none" align="center">No</td>
3602+
<td class="none" align="center">Yes</td>
36033603
</tr>
36043604
<tr id="592">
36053605
<td><a href="https://cplusplus.github.io/CWG/issues/592.html">592</a></td>

0 commit comments

Comments
 (0)