[PATCH] D154559: [clang] Fix constant evaluation about static member function

Yaxun Liu via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 5 19:27:44 PDT 2023


yaxunl created this revision.
yaxunl added reviewers: rjmccall, tra, rsmith.
Herald added a project: All.
yaxunl requested review of this revision.

Currently, clang does not allow static constexpr member
functions called through a const reference of an object
in constant expression, e.g. the following code

  class static_multimap{
      public:
          static constexpr int size() noexcept{
              return 8;
          }
  };
  
  template <typename Map>
  void test_non_shmem_pair_retrieve(Map& map){
      auto constexpr cg_size = map.size();
  }
  
  int main(){
      static_multimap map;
      test_non_shmem_pair_retrieve(map);
      return 0;
  }

fails to compile with clang. (https://godbolt.org/z/T17vTWYcs)

This does not make sense since the evaluation of map.size
does not rely on map. The same code compiles with GCC.


https://reviews.llvm.org/D154559

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/test/SemaCXX/constant-expression-cxx11.cpp


Index: clang/test/SemaCXX/constant-expression-cxx11.cpp
===================================================================
--- clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -2379,15 +2379,19 @@
   template<typename T> void f1(T t) {
     constexpr int k = t.size();
   }
-  template<typename T> void f2(const T &t) { // expected-note 2{{declared here}}
-    constexpr int k = t.size(); // expected-error 2{{constant}} expected-note 2{{function parameter 't' with unknown value cannot be used in a constant expression}}
+  template<typename T> void f2a(const T &t) {
+    constexpr int k1 = t.size();
+    constexpr int k2 = (t).size();
+  }
+  template<typename T> void f2b(const T &t) { // expected-note {{declared here}}
+    constexpr int k = t.size(); // expected-error {{constant}} expected-note {{function parameter 't' with unknown value cannot be used in a constant expression}}
   }
   template<typename T> void f3(const T &t) {
     constexpr int k = T::size();
   }
   void g(array<3> a) {
     f1(a);
-    f2(a); // expected-note {{instantiation of}}
+    f2a(a);
     f3(a);
   }
 
@@ -2396,7 +2400,7 @@
   };
   void h(array_nonstatic<3> a) {
     f1(a);
-    f2(a); // expected-note {{instantiation of}}
+    f2b(a); // expected-note {{instantiation of}}
   }
 }
 
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -8031,6 +8031,15 @@
 
   /// Potentially visit a MemberExpr's base expression.
   void VisitIgnoredBaseExpression(const Expr *E) {
+    // If E is a reference, and if so, there is no side effect.
+    if (const DeclRefExpr *DRE =
+            dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) {
+      if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+        if (VD->getType()->isReferenceType()) {
+          return;
+        }
+      }
+    }
     // While MSVC doesn't evaluate the base expression, it does diagnose the
     // presence of side-effecting behavior.
     if (Info.getLangOpts().MSVCCompat && !E->HasSideEffects(Info.Ctx))


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D154559.537562.patch
Type: text/x-patch
Size: 2171 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20230706/81080c4a/attachment.bin>


More information about the cfe-commits mailing list