lime updated this revision to Diff 499374.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D143840/new/
https://reviews.llvm.org/D143840
Files:
clang/docs/ReleaseNotes.rst
clang/include/clang/AST/DeclCXX.h
clang/lib/AST/CXXInheritance.cpp
clang/lib/Sema/SemaExpr.cpp
clang/test/CodeGenCXX/decl-ref-inheritance.cpp
clang/test/SemaCXX/decltype.cpp
Index: clang/test/SemaCXX/decltype.cpp
===================================================================
--- clang/test/SemaCXX/decltype.cpp
+++ clang/test/SemaCXX/decltype.cpp
@@ -101,6 +101,44 @@
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 {
};
Index: clang/test/CodeGenCXX/decl-ref-inheritance.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/decl-ref-inheritance.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux -emit-llvm %s -o - | FileCheck %s
+
+// CHECK: [[FOO:%.+]] = type { i32 }
+struct foo {
+ int val;
+};
+
+template <typename T> struct bar : T {
+};
+
+struct baz : bar<foo> {
+ // CHECK-LABEL: define{{.*}} i32 @_ZN3baz3getEv
+ // CHECK: {{%.+}} = getelementptr inbounds [[FOO]], ptr {{%.+}}, i32 0, i32 0
+ int get() {
+ return val;
+ }
+};
+
+int qux() {
+ auto f = baz{};
+ return f.get();
+}
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -2698,20 +2698,36 @@
// 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,
Index: clang/lib/AST/CXXInheritance.cpp
===================================================================
--- clang/lib/AST/CXXInheritance.cpp
+++ clang/lib/AST/CXXInheritance.cpp
@@ -64,14 +64,16 @@
std::swap(DetectedVirtual, Other.DetectedVirtual);
}
-bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base) const {
+bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base,
+ bool LookupInDependentTypes) const {
CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false,
/*DetectVirtual=*/false);
- return isDerivedFrom(Base, Paths);
+ return isDerivedFrom(Base, Paths, LookupInDependentTypes);
}
bool CXXRecordDecl::isDerivedFrom(const CXXRecordDecl *Base,
- CXXBasePaths &Paths) const {
+ CXXBasePaths &Paths,
+ bool LookupInDependentTypes) const {
if (getCanonicalDecl() == Base->getCanonicalDecl())
return false;
@@ -83,7 +85,7 @@
return Specifier->getType()->getAsRecordDecl() &&
FindBaseClass(Specifier, Path, BaseDecl);
},
- Paths);
+ Paths, LookupInDependentTypes);
}
bool CXXRecordDecl::isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const {
@@ -246,17 +248,16 @@
} else if (VisitBase) {
CXXRecordDecl *BaseRecord;
if (LookupInDependent) {
- BaseRecord = nullptr;
- const TemplateSpecializationType *TST =
- BaseSpec.getType()->getAs<TemplateSpecializationType>();
- if (!TST) {
- if (auto *RT = BaseSpec.getType()->getAs<RecordType>())
- BaseRecord = cast<CXXRecordDecl>(RT->getDecl());
- } else {
- TemplateName TN = TST->getTemplateName();
- if (auto *TD =
- dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl()))
- BaseRecord = TD->getTemplatedDecl();
+ BaseRecord = cast_if_present<CXXRecordDecl>(
+ BaseSpec.getType()->getAsRecordDecl());
+ if (!BaseRecord) {
+ if (const TemplateSpecializationType *TST =
+ BaseSpec.getType()->getAs<TemplateSpecializationType>()) {
+ TemplateName TN = TST->getTemplateName();
+ if (auto *TD =
+ dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl()))
+ BaseRecord = TD->getTemplatedDecl();
+ }
}
if (BaseRecord) {
if (!BaseRecord->hasDefinition() ||
Index: clang/include/clang/AST/DeclCXX.h
===================================================================
--- clang/include/clang/AST/DeclCXX.h
+++ clang/include/clang/AST/DeclCXX.h
@@ -1546,8 +1546,11 @@
///
/// \param Base the base class we are searching for.
///
+ /// \param LookupInDependentTypes whether to look up in dependent types.
+ ///
/// \returns true if this class is derived from Base, false otherwise.
- bool isDerivedFrom(const CXXRecordDecl *Base) const;
+ bool isDerivedFrom(const CXXRecordDecl *Base,
+ bool LookupInDependentTypes = false) const;
/// Determine whether this class is derived from the type \p Base.
///
@@ -1561,11 +1564,14 @@
/// \param Paths will contain the paths taken from the current class to the
/// given \p Base class.
///
+ /// \param LookupInDependentTypes whether to look up independent types.
+ ///
/// \returns true if this class is derived from \p Base, false otherwise.
///
/// \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 LookupInDependentTypes = false) const;
/// Determine whether this class is virtually derived from
/// the class \p Base.
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -165,6 +165,9 @@
- Fix crash when evaluating consteval constructor of derived class whose base
has more than one field.
(`#60166 <https://github.com/llvm/llvm-project/issues/60166>`_)
+- Fix an issue about ``decltype`` in the members of class templates derived from
+ templates with related parameters.
+ (`#58674 <https://github.com/llvm/llvm-project/issues/58674>`_)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits