[clang] 3951c28 - [clang] Replace Member Expressions During Instantiation If Necessary

Liming Liu via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 13 07:22:31 PDT 2023


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 {
 };


        


More information about the cfe-commits mailing list