hazohelet created this revision.
hazohelet added reviewers: aaron.ballman, erichkeane, tbaeder, cjdb.
Herald added a project: All.
hazohelet requested review of this revision.
Herald added a project: clang.

This patch changes the display of member function calls in constexpr evaluator 
diagnostics from arrow operator to dot operator.
This avoids the syntactical invalidness in notes previously caused by the 
display of `&` operator
(lack of parentheses and reference of rvalue)

Fixes https://github.com/llvm/llvm-project/issues/57081


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D151720

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/AST/ExprConstant.cpp
  clang/test/AST/Interp/constexpr-nqueens.cpp
  clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp
  clang/test/CXX/temp/temp.param/p8-cxx20.cpp
  clang/test/SemaCXX/constant-expression-cxx11.cpp
  clang/test/SemaCXX/cxx2a-consteval.cpp
  clang/test/SemaCXX/deduced-return-type-cxx14.cpp

Index: clang/test/SemaCXX/deduced-return-type-cxx14.cpp
===================================================================
--- clang/test/SemaCXX/deduced-return-type-cxx14.cpp
+++ clang/test/SemaCXX/deduced-return-type-cxx14.cpp
@@ -296,7 +296,7 @@
   void f() {
     X<int>().f();
     Y<void>().f();
-    constexpr int q = Y<int>().f(); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to '&Y<int>()->f()'}}
+    constexpr int q = Y<int>().f(); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'Y<int>().f()'}}
   }
   struct NonLiteral { ~NonLiteral(); } nl; // cxx14-note {{user-provided destructor}}
   // cxx20_23-note@-1 {{'NonLiteral' is not literal because its destructor is not constexpr}}
Index: clang/test/SemaCXX/cxx2a-consteval.cpp
===================================================================
--- clang/test/SemaCXX/cxx2a-consteval.cpp
+++ clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -840,13 +840,13 @@
   copy<foo> fail1{good0}; // expected-error {{call to consteval function 'defaulted_special_member_template::copy<defaulted_special_member_template::foo>::copy' is not a constant expression}} \
                              expected-note {{in call to 'copy(good0)'}}
   fail1 = good0;          // expected-error {{call to consteval function 'defaulted_special_member_template::copy<defaulted_special_member_template::foo>::operator=' is not a constant expression}} \
-                             expected-note {{in call to '&fail1->operator=(good0)'}}
+                             expected-note {{in call to 'fail1.operator=(good0)'}}
 
   move<foo> good1;
   move<foo> fail2{static_cast<move<foo>&&>(good1)}; // expected-error {{call to consteval function 'defaulted_special_member_template::move<defaulted_special_member_template::foo>::move' is not a constant expression}} \
                                                        expected-note {{in call to 'move(good1)'}}
   fail2 = static_cast<move<foo>&&>(good1);          // expected-error {{call to consteval function 'defaulted_special_member_template::move<defaulted_special_member_template::foo>::operator=' is not a constant expression}} \
-                                                       expected-note {{in call to '&fail2->operator=(good1)'}}
+                                                       expected-note {{in call to 'fail2.operator=(good1)'}}
 }
 } // namespace defaulted_special_member_template
 
Index: clang/test/SemaCXX/constant-expression-cxx11.cpp
===================================================================
--- clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -975,7 +975,7 @@
   int n;
 };
 constexpr int S::f() const {
-  return static_cast<const T*>(this)->n; // expected-note {{cannot cast}}
+  return static_cast<const T*>(this)->n; // expected-note 5{{cannot cast}}
 }
 constexpr int S::g() const {
   // FIXME: Better diagnostic for this.
@@ -984,8 +984,16 @@
 // The T temporary is implicitly cast to an S subobject, but we can recover the
 // T full-object via a base-to-derived cast, or a derived-to-base-casted member
 // pointer.
-static_assert(S().f(), ""); // expected-error {{constant expression}} expected-note {{in call to '&S()->f()'}}
-static_assert(S().g(), ""); // expected-error {{constant expression}} expected-note {{in call to '&S()->g()'}}
+static_assert(S().f(), ""); // expected-error {{constant expression}} expected-note {{in call to 'S().f()'}}
+static_assert(S().g(), ""); // expected-error {{constant expression}} expected-note {{in call to 'S().g()'}}
+constexpr S sobj;
+constexpr const S& slref = sobj;
+constexpr const S&& srref = S();
+constexpr const S *sptr = &sobj;
+static_assert(sobj.f(), ""); // expected-error {{constant expression}} expected-note {{in call to 'sobj.f()'}}
+static_assert(sptr->f(), ""); // expected-error {{constant expression}} expected-note {{in call to 'sobj.f()'}}
+static_assert(slref.f(), ""); // expected-error {{constant expression}} expected-note {{in call to 'sobj.f()'}}
+static_assert(srref.f(), ""); // expected-error {{constant expression}} expected-note {{in call to 'S().f()'}}
 static_assert(T(3).f() == 3, "");
 static_assert(T(4).g() == 4, "");
 
Index: clang/test/CXX/temp/temp.param/p8-cxx20.cpp
===================================================================
--- clang/test/CXX/temp/temp.param/p8-cxx20.cpp
+++ clang/test/CXX/temp/temp.param/p8-cxx20.cpp
@@ -61,5 +61,5 @@
 
   template<D d> struct Z {};
   Z<D{2, true}> z1;
-  Z<D{2, false}> z2; // expected-error {{non-type template argument is not a constant expression}} expected-note-re {{in call to '{{.*}}->~D()'}}
+  Z<D{2, false}> z2; // expected-error {{non-type template argument is not a constant expression}} expected-note-re {{in call to '{{.*}}.~D()'}}
 }
Index: clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp
===================================================================
--- clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp
+++ clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp
@@ -42,12 +42,30 @@
   bool ok;
   constexpr A(bool ok) : ok(ok) {}
   constexpr ~A() noexcept(false) {
-    void oops(); // expected-note 2{{declared here}}
-    if (!ok) oops(); // expected-note 2{{non-constexpr function}}
+    void oops(); // expected-note 6{{declared here}}
+    if (!ok) oops(); // expected-note 6{{non-constexpr function}}
   }
 };
 
+struct B {
+  A a[2];
+  constexpr B(bool ok) : a{A(!ok), A(ok)}{}
+};
+
+struct Cons {
+  bool val[2];
+  constexpr Cons() : val{true, false} {}
+};
+
 constexpr A const_dtor(true);
+static_assert(B(false).a[1].ok); // expected-error {{static assertion expression is not an integral constant expression}} \
+                                 // expected-note {{in call to 'B(false).a[1].~A()'}} expected-note {{in call to 'B(false).~B()'}}
+static_assert(B(true).a[1].ok); // expected-error {{static assertion expression is not an integral constant expression}} \
+                                 // expected-note {{in call to 'B(true).a[0].~A()'}} expected-note {{in call to 'B(true).~B()'}}
+static_assert(B(Cons().val[1]).a[1].ok); // expected-error {{static assertion expression is not an integral constant expression}} \
+                                 // expected-note {{in call to 'B(Cons().val[1]).a[1].~A()'}} expected-note {{in call to 'B(Cons().val[1]).~B()'}}
+static_assert(B((new Cons)->val[0]).a[1].ok); // expected-error {{static assertion expression is not an integral constant expression}} \
+                                 // expected-note {{in call to 'B((new Cons)->val[0]).a[0].~A()'}} expected-note {{in call to 'B((new Cons)->val[0]).~B()'}}
 constexpr A non_const_dtor(false); // expected-error {{must have constant destruction}} expected-note {{in call}}
-constexpr A arr_dtor[5] = {true, true, true, false, true}; // expected-error {{must have constant destruction}} expected-note {{in call to '&arr_dtor[3]->~A()'}}
+constexpr A arr_dtor[5] = {true, true, true, false, true}; // expected-error {{must have constant destruction}} expected-note {{in call to 'arr_dtor[3].~A()'}}
 #endif
Index: clang/test/AST/Interp/constexpr-nqueens.cpp
===================================================================
--- clang/test/AST/Interp/constexpr-nqueens.cpp
+++ clang/test/AST/Interp/constexpr-nqueens.cpp
@@ -48,7 +48,7 @@
 constexpr Board buildBoardScan(int N, int Col, int Row, const Board &B) {
   return Row == N ? Board(0, true) :
          B.ok(Row, Col) ?
-         tryBoard(buildBoardRecurse(N, Col + 1, B.addQueen(Row, Col)), // ref-note {{in call to '&Board()->addQueen(0, 0)}} \
+         tryBoard(buildBoardRecurse(N, Col + 1, B.addQueen(Row, Col)), // ref-note {{in call to 'Board().addQueen(0, 0)}} \
                                                                        // expected-note {{in call to '&Board()->addQueen(0, 0)}}
                   N, Col, Row+1, B) :
          buildBoardScan(N, Col, Row + 1, B);
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -1919,10 +1919,11 @@
   if (This && IsMemberCall) {
     APValue Val;
     This->moveInto(Val);
-    Val.printPretty(Out, Info.Ctx,
-                    This->Designator.MostDerivedType);
-    // FIXME: Add parens around Val if needed.
-    Out << "->" << *Callee << '(';
+    Val.printPretty(
+        Out, Info.Ctx,
+        Info.Ctx.getLValueReferenceType(This->Designator.MostDerivedType));
+    Out << "." << *Callee << '(';
+
     IsMemberCall = false;
   }
 
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -314,6 +314,9 @@
   is an incomplete type.
   (`#55175: <https://github.com/llvm/llvm-project/issues/55175>`_, and fixes an
   incorrect mention of ``alignof`` in a diagnostic about ``alignas``).
+- Clang constexpr evaluator now displays member function calls by using dot operator
+  rather than arrow operator in notes to avoid display of syntactically invalid code.
+  (`#57081: <https://github.com/llvm/llvm-project/issues/57081>`_).
 
 Bug Fixes in This Version
 -------------------------
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to