Author: Liming Liu Date: 2023-01-29T13:44:19+08:00 New Revision: 01adf96ebc8608bcdda0cacc303035b2e60ccb46
URL: https://github.com/llvm/llvm-project/commit/01adf96ebc8608bcdda0cacc303035b2e60ccb46 DIFF: https://github.com/llvm/llvm-project/commit/01adf96ebc8608bcdda0cacc303035b2e60ccb46.diff LOG: [clang] Add the check of membership in decltype for the issue #58674 D137531 had once fixed the issue. However, it caused a crash during compiling llvm/unittests/IR/PatternMatch.cpp in stage-2. The reason is the predicator isDerivedFrom does not consider independent types if the derived type is dependent. This patch improves D137531 by adding an option to make isDerivedFrom consider independent types. Differential Revision: https://reviews.llvm.org/D142437 Added: Modified: clang/docs/ReleaseNotes.rst clang/include/clang/AST/DeclCXX.h clang/lib/AST/CXXInheritance.cpp clang/lib/Sema/SemaExpr.cpp clang/test/SemaCXX/decltype.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 4c72ec64f6e19..a73a750cbe305 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -57,6 +57,9 @@ Bug Fixes - Fix crash on invalid code when looking up a destructor in a templated class inside a namespace. This fixes `Issue 59446 <https://github.com/llvm/llvm-project/issues/59446>`_. +- Fix an issue about ``decltype`` in the members of class templates derived from + templates with related parameters. This fixes + `Issue 58674 <https://github.com/llvm/llvm-project/issues/58674>`_. Improvements to Clang's diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 11276c77490ce..30200a1785a3f 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1547,7 +1547,8 @@ class CXXRecordDecl : public RecordDecl { /// \param Base the base class we are searching for. /// /// \returns true if this class is derived from Base, false otherwise. - bool isDerivedFrom(const CXXRecordDecl *Base) const; + bool isDerivedFrom(const CXXRecordDecl *Base, + bool LookupIndependent = false) const; /// Determine whether this class is derived from the type \p Base. /// @@ -1565,7 +1566,8 @@ class CXXRecordDecl : public RecordDecl { /// /// \todo add a separate parameter to configure IsDerivedFrom, rather than /// tangling input and output in \p Paths - bool isDerivedFrom(const CXXRecordDecl *Base, CXXBasePaths &Paths) const; + bool isDerivedFrom(const CXXRecordDecl *Base, CXXBasePaths &Paths, + bool LookupIndependent = false) const; /// Determine whether this class is virtually derived from /// the class \p Base. diff --git a/clang/lib/AST/CXXInheritance.cpp b/clang/lib/AST/CXXInheritance.cpp index 1abbe8139ae99..175e461787fdf 100644 --- a/clang/lib/AST/CXXInheritance.cpp +++ b/clang/lib/AST/CXXInheritance.cpp @@ -64,14 +64,16 @@ void CXXBasePaths::swap(CXXBasePaths &Other) { std::swap(DetectedVirtual, Other.DetectedVirtual); } -bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base) const { +bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base, + bool LookupIndependent) const { CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false, /*DetectVirtual=*/false); - return isDerivedFrom(Base, Paths); + return isDerivedFrom(Base, Paths, LookupIndependent); } bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base, - CXXBasePaths &Paths) const { + CXXBasePaths &Paths, + bool LookupIndependent) const { if (getCanonicalDecl() == Base->getCanonicalDecl()) return false; @@ -80,9 +82,10 @@ bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base, const CXXRecordDecl *BaseDecl = Base->getCanonicalDecl(); return lookupInBases( [BaseDecl](const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { - return FindBaseClass(Specifier, Path, BaseDecl); + return Specifier->getType()->getAsRecordDecl() && + FindBaseClass(Specifier, Path, BaseDecl); }, - Paths); + Paths, LookupIndependent); } bool CXXRecordDecl::isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const { diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 2842add2cc4af..b7c62f5375e42 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2693,20 +2693,36 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // to get this right here so that we don't end up making a // spuriously dependent expression if we're inside a dependent // instance method. + // + // We also don't need to do this if R resolved to a member in another + // class, which can happen in an unevaluated operand: + // + // C++ [expr.prim.id]p3.3: + // If that id-expression denotes a non-static data member and it + // appears in an unevaluated operand. if (!R.empty() && (*R.begin())->isCXXClassMember()) { - bool MightBeImplicitMember; - if (!IsAddressOfOperand) - MightBeImplicitMember = true; - else if (!SS.isEmpty()) - MightBeImplicitMember = false; - else if (R.isOverloadedResult()) - MightBeImplicitMember = false; - else if (R.isUnresolvableResult()) - MightBeImplicitMember = true; - else - MightBeImplicitMember = isa<FieldDecl>(R.getFoundDecl()) || - isa<IndirectFieldDecl>(R.getFoundDecl()) || - isa<MSPropertyDecl>(R.getFoundDecl()); + bool MightBeImplicitMember = true, CheckField = true; + if (IsAddressOfOperand) { + MightBeImplicitMember = SS.isEmpty() && !R.isOverloadedResult(); + CheckField = !R.isUnresolvableResult(); + } + if (MightBeImplicitMember && CheckField) { + if (R.isSingleResult() && + isa<FieldDecl, IndirectFieldDecl, MSPropertyDecl>(R.getFoundDecl())) { + auto Class = cast<CXXRecordDecl>((*R.begin())->getDeclContext()); + for (auto Curr = S->getLookupEntity(); Curr && !Curr->isFileContext(); + Curr = Curr->getParent()) { + if (auto ThisClass = dyn_cast_if_present<CXXRecordDecl>(Curr)) { + if ((MightBeImplicitMember = + ThisClass->Equals(Class) || + ThisClass->isDerivedFrom(Class, + /*LookupIndependent=*/true))) + break; + } + } + } else if (IsAddressOfOperand) + MightBeImplicitMember = false; + } if (MightBeImplicitMember) return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, diff --git a/clang/test/SemaCXX/decltype.cpp b/clang/test/SemaCXX/decltype.cpp index 32c61bbccc842..96abb60836e40 100644 --- a/clang/test/SemaCXX/decltype.cpp +++ b/clang/test/SemaCXX/decltype.cpp @@ -101,6 +101,44 @@ namespace D5789 { template<class T> void foo(decltype(T(LP1{ .p1 = g1, .p1.x[1] = 'x' }))) {} } +namespace GH58674 { + struct Foo { + float value_; + struct nested { + float value_; + }; + }; + + template <typename T> + struct TemplateFoo { + float value_; + }; + + float bar; + + template <typename T> + struct Animal{}; + + template <typename T> + class Cat : Animal<T> { + using okay = decltype(Foo::value_); + using also_okay = decltype(bar); + using okay2 = decltype(Foo::nested::value_); + using okay3 = decltype(TemplateFoo<T>::value_); + public: + void meow() { + using okay = decltype(Foo::value_); + using also_okay = decltype(bar); + using okay2 = decltype(Foo::nested::value_); + using okay3 = decltype(TemplateFoo<T>::value_); + } + }; + + void baz() { + Cat<void>{}.meow(); + } +} + template<typename> class conditional { }; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits