Author: Liming Liu Date: 2023-03-13T22:22:06+08:00 New Revision: 3951c28b37ff67c87da59df961c4af19818c24c2
URL: https://github.com/llvm/llvm-project/commit/3951c28b37ff67c87da59df961c4af19818c24c2 DIFF: https://github.com/llvm/llvm-project/commit/3951c28b37ff67c87da59df961c4af19818c24c2.diff LOG: [clang] Replace Member Expressions During Instantiation If Necessary This patch replaces member accesses to declaration references during template instantiation if the context is the unevaluated context and the class does not contain the declaration. The replacement fixes the issue #58674. Unlike previous fixes such as D143840, it checks the membership during instantiation rather than right after parsing, so the check is more accurate and efficient. This patch also includes cases that previous fixes had once failed on. Differential Revision: https://reviews.llvm.org/D145491 Added: clang/test/CodeGenCXX/decl-ref-inheritance.cpp Modified: clang/docs/ReleaseNotes.rst clang/lib/Sema/TreeTransform.h clang/test/SemaCXX/decltype.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index dac81ecd48e34..47fee3ef6b248 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -202,6 +202,9 @@ Bug Fixes to C++ Support - 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 ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 590f0b4d2474c..e9b35f658c206 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -2803,6 +2803,21 @@ class TreeTransform { R.addDecl(FoundDecl); R.resolveKind(); + if (getSema().isUnevaluatedContext() && Base->isImplicitCXXThis() && + isa<FieldDecl, IndirectFieldDecl, MSPropertyDecl>(Member)) { + if (auto *ThisClass = cast<CXXThisExpr>(Base) + ->getType() + ->getPointeeType() + ->getAsCXXRecordDecl()) { + auto *Class = cast<CXXRecordDecl>(Member->getDeclContext()); + // In unevaluated contexts, an expression supposed to be a member access + // might reference a member in an unrelated class. + if (!ThisClass->Equals(Class) && !ThisClass->isDerivedFrom(Class)) + return getSema().BuildDeclRefExpr(Member, Member->getType(), + VK_LValue, Member->getLocation()); + } + } + return getSema().BuildMemberReferenceExpr(Base, BaseType, OpLoc, isArrow, SS, TemplateKWLoc, FirstQualifierInScope, diff --git a/clang/test/CodeGenCXX/decl-ref-inheritance.cpp b/clang/test/CodeGenCXX/decl-ref-inheritance.cpp new file mode 100644 index 0000000000000..9206ee5ac9369 --- /dev/null +++ b/clang/test/CodeGenCXX/decl-ref-inheritance.cpp @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 -triple=x86_64-unknown-linux -emit-llvm %s -o - | FileCheck \ +// RUN: -check-prefix=CHECK-1 %s +// RUN: %clang_cc1 -triple=x86_64-unknown-linux -emit-llvm %s -o - | FileCheck \ +// RUN: -check-prefix=CHECK-2 %s +// RUN: %clang_cc1 -triple=x86_64-unknown-linux -emit-llvm %s -o - | FileCheck \ +// RUN: -check-prefix=CHECK-3 %s + +// CHECK-1: [[FOO:%.+]] = type { float } +struct foo { + float val; +}; + +template <typename T> struct bar : T { +}; + +struct baz : bar<foo> { + // CHECK-1: define{{.*}} float @_ZN3baz3getEv + // CHECK-1: {{%.+}} = getelementptr inbounds [[FOO]], ptr {{%.+}}, i32 0, i32 0 + float get() { + return val; + } +}; + +int qux() { + auto f = baz{}; + return f.get(); +} + +// CHECK-2: [[F:%.+]] = type { ptr } +struct f { + void *g; +}; + +template <typename j> struct k : j { + // CHECK-2: define{{.*}} void @_ZN1kI1fE1lEv + // CHECK-2: {{%.+}} = getelementptr inbounds [[F]], ptr {{%.+}}, i32 0, i32 0 + virtual void l(){ (void)f::g; } +}; + +k<f> q; + +// CHECK-3: [[BASE:%.+]] = type { i32 } +class Base { +protected: + int member; +}; + +template <typename Parent> +struct Subclass : public Parent { + // CHECK-3: define{{.*}} i32 @_ZN8SubclassI4BaseE4funcEv + // CHECK-3: {{%.+}} = getelementptr inbounds [[BASE]], ptr {{%.+}}, i32 0, i32 0 + int func() { return Base::member; } +}; + +using Impl = Subclass<Base>; + +int use() { + Impl i; + return i.func(); +} 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