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))
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))
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits