Author: Vladislav Belov Date: 2024-11-26T12:56:46+01:00 New Revision: 486644723038555a224fd09d462bb5099e64809e
URL: https://github.com/llvm/llvm-project/commit/486644723038555a224fd09d462bb5099e64809e DIFF: https://github.com/llvm/llvm-project/commit/486644723038555a224fd09d462bb5099e64809e.diff LOG: [Clang] Fix name lookup for dependent bases (#114978) Currently the following example is a compilation failure: ```cpp template<typename T> struct A { typedef int M; struct B { typedef void M; struct C; }; }; template<typename T> struct A<T>::B::C : A<T> { M m; // void or int ? }; ``` According to the point 13.8.3.2 ``` A dependent base class is a base class that is a dependent type and is not the current instantiation. Note 2 : A base class can be the current instantiation in the case of a nested class naming an enclosing class as a base. ``` The base class `A` is the current instantiation, because `C` is a nested class for an enclosing class `A<T>`, it's is the not-dependent base class and we need to search the names through its scope. This patch makes this example compile Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/AST/CXXInheritance.cpp clang/test/CXX/drs/cwg5xx.cpp clang/www/cxx_dr_status.html Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 954fe61f3d1d69..ff24161de493c7 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -279,6 +279,9 @@ Resolutions to C++ Defect Reports by default. (`CWG2521: User-defined literals and reserved identifiers <https://cplusplus.github.io/CWG/issues/2521.html>`_). +- Fix name lookup for a dependent base class that is the current instantiation. + (`CWG591: When a dependent base class is the current instantiation <https://cplusplus.github.io/CWG/issues/591.html>`_). + C Language Changes ------------------ diff --git a/clang/lib/AST/CXXInheritance.cpp b/clang/lib/AST/CXXInheritance.cpp index aefc06e9197cfb..10b8d524ff8978 100644 --- a/clang/lib/AST/CXXInheritance.cpp +++ b/clang/lib/AST/CXXInheritance.cpp @@ -134,7 +134,7 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback BaseMatches) const { return false; CXXRecordDecl *Base = - cast_or_null<CXXRecordDecl>(Ty->getDecl()->getDefinition()); + cast_if_present<CXXRecordDecl>(Ty->getDecl()->getDefinition()); if (!Base || (Base->isDependentContext() && !Base->isCurrentInstantiation(Record))) { @@ -169,13 +169,21 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, QualType BaseType = Context.getCanonicalType(BaseSpec.getType()).getUnqualifiedType(); + bool isCurrentInstantiation = isa<InjectedClassNameType>(BaseType); + if (!isCurrentInstantiation) { + if (auto *BaseRecord = cast_if_present<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, @@ -243,9 +251,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) { @@ -264,8 +271,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@-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@-1 {{field has incomplete type 'M' (aka 'void'}} }; diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index 186f7cc0ace546..c773c58fac4d0f 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -3599,7 +3599,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td><a href="https://cplusplus.github.io/CWG/issues/591.html">591</a></td> <td>CD4</td> <td>When a dependent base class is the current instantiation</td> - <td class="none" align="center">No</td> + <td class="none" align="center">Yes</td> </tr> <tr id="592"> <td><a href="https://cplusplus.github.io/CWG/issues/592.html">592</a></td> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits