llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Vladislav Belov (vbe-sc) <details> <summary>Changes</summary> Currently the following example is a compilation failure: ``` 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 --- Full diff: https://github.com/llvm/llvm-project/pull/114978.diff 2 Files Affected: - (modified) clang/lib/AST/CXXInheritance.cpp (+8-5) - (modified) clang/test/CXX/drs/cwg5xx.cpp (+6-2) ``````````diff diff --git a/clang/lib/AST/CXXInheritance.cpp b/clang/lib/AST/CXXInheritance.cpp index eb265a872c1259..049532f942d051 100644 --- a/clang/lib/AST/CXXInheritance.cpp +++ b/clang/lib/AST/CXXInheritance.cpp @@ -169,6 +169,9 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, // Find the record of the base class subobjects for this type. QualType BaseType = Context.getCanonicalType(BaseSpec.getType()).getUnqualifiedType(); + bool isCurrentInstantiation = false; + if (auto *TST = BaseSpec.getType()->getAs<TemplateSpecializationType>()) + isCurrentInstantiation = TST->isCurrentInstantiation(); // C++ [temp.dep]p3: // In the definition of a class template or a member of a class template, @@ -176,7 +179,8 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, // 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 +248,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 +268,8 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, BaseRecord = nullptr; } } else { - BaseRecord = cast<CXXRecordDecl>( - BaseSpec.getType()->castAs<RecordType>()->getDecl()); + if (auto *RT = BaseSpec.getType()->getAs<RecordType>()) + BaseRecord = cast<CXXRecordDecl>(RT->getDecl()); } 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..b283684aef2f7e 100644 --- a/clang/test/CXX/drs/cwg5xx.cpp +++ b/clang/test/CXX/drs/cwg5xx.cpp @@ -1178,17 +1178,21 @@ 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 A<T>::B::C : A<T> { - // FIXME: Should find member of non-dependent base class A<T>. + M m; + }; + + template<typename T> struct A<T>::B::D : A<T*> { M m; // expected-error@-1 {{field has incomplete type 'M' (aka 'void'}} }; `````````` </details> https://github.com/llvm/llvm-project/pull/114978 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits