diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 3f5467c8283a1473a37cdebea469edc4834998ed..2ea32101f07f9e81de34de05aaba6b7db01d7f05 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -1231,12 +1231,14 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
     case CALL_EXPR:   /* We have a special meaning for volatile void fn().  */
       /* cdtors may return this or void, depending on
 	 targetm.cxx.cdtor_returns_this, but this shouldn't affect our
-	 decisions here: neither nodiscard warnings (nodiscard cdtors
-	 are nonsensical), nor should any constexpr or template
-	 instantiations be affected by an ABI property that is, or at
-	 least ought to be transparent to the language.  */
+	 decisions here: neither nodiscard warnings (nodiscard dtors
+	 are nonsensical and ctors have a different behavior with that
+	 attribute that is handled in the TARGET_EXPR case), nor should
+	 any constexpr or template instantiations be affected by an ABI
+	 property that is, or at least ought to be transparent to the
+	 language.  */
       if (tree fn = cp_get_callee_fndecl_nofold (expr))
-	if (DECL_DESTRUCTOR_P (fn))
+	if (DECL_CONSTRUCTOR_P (fn) || DECL_DESTRUCTOR_P (fn))
 	  return expr;
 
       if (complain & tf_warning)
diff --git a/gcc/testsuite/g++.dg/cpp2a/nodiscard-constructor.c b/gcc/testsuite/g++.dg/cpp2a/nodiscard-constructor1.C
similarity index 54%
rename from gcc/testsuite/g++.dg/cpp2a/nodiscard-constructor.c
rename to gcc/testsuite/g++.dg/cpp2a/nodiscard-constructor1.C
index 9af4e59c3dca5a03145fccd7b7e7baf8014612f0..6aa33149a0f8dd1b7f67ac01296223b04c89d1fd 100644
--- a/gcc/testsuite/g++.dg/cpp2a/nodiscard-constructor.c
+++ b/gcc/testsuite/g++.dg/cpp2a/nodiscard-constructor1.C
@@ -1,6 +1,6 @@
 /* nodiscard attribute tests  */
 /* { dg-do compile { target c++20 } } */
-/* { dg-options "-O -ftrack-macro-expansion=0" } */
+/* { dg-options "-O" } */
 
 struct A { [[nodiscard("bad constructor")]] A() {} };
 struct B { [[nodiscard]] B() {} };
@@ -8,6 +8,6 @@ struct B { [[nodiscard]] B() {} };
 void
 test (void)
 {
-  A{}; /* { dg-warning "(?n)nodiscard.*bad constructor" } */
-  B{}; /* { dg-warning "(?n)nodiscard" } */
+  A{}; /* { dg-warning "nodiscard\[^\n\r]*bad constructor" } */
+  B{}; /* { dg-warning "nodiscard" } */
 }
diff --git a/gcc/testsuite/g++.dg/cpp2a/nodiscard-constructor2.C b/gcc/testsuite/g++.dg/cpp2a/nodiscard-constructor2.C
new file mode 100644
index 0000000000000000000000000000000000000000..3abb11847d1097943928cbedfd6d4d3bbf075ce3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nodiscard-constructor2.C
@@ -0,0 +1,17 @@
+// PR c++/99362
+// { dg-do compile { target c++20 } }
+
+struct S {
+  [[nodiscard]] S() {}
+  S(int) {}
+};
+
+int main()
+{
+  S s;
+  S();		// { dg-warning "ignoring return value" }
+  (void)(S());
+  S t = 1;
+  S(1);
+  (void)(S(1));
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/nodiscard-once.C b/gcc/testsuite/g++.dg/cpp2a/nodiscard-once.C
index c95fa1b0741d24567fb7c7be68d42afcebc8fd79..c533f9cf7d0c3113af7cc9ef1e466a68c90cd6c1 100644
--- a/gcc/testsuite/g++.dg/cpp2a/nodiscard-once.C
+++ b/gcc/testsuite/g++.dg/cpp2a/nodiscard-once.C
@@ -1,6 +1,6 @@
 /* nodiscard attribute tests  */
 /* { dg-do compile { target c++20 } } */
-/* { dg-options "-O -ftrack-macro-expansion=0" } */
+/* { dg-options "-O" } */
 
 [[nodiscard, nodiscard]] int check1 (void); // { dg-warning "specified multiple times" }
 
diff --git a/gcc/testsuite/g++.dg/cpp2a/nodiscard-reason-nonstring.C b/gcc/testsuite/g++.dg/cpp2a/nodiscard-reason-nonstring.C
index d81baf0ebcdbcf72b2c0a859681b40e66476ff4c..091c3e56bd23c50953378acbc6428a4827d1bc1d 100644
--- a/gcc/testsuite/g++.dg/cpp2a/nodiscard-reason-nonstring.C
+++ b/gcc/testsuite/g++.dg/cpp2a/nodiscard-reason-nonstring.C
@@ -1,6 +1,6 @@
 /* nodiscard attribute tests  */
 /* { dg-do compile { target c++20 } } */
-/* { dg-options "-O -ftrack-macro-expansion=0" } */
+/* { dg-options "-O" } */
 
 [[nodiscard(123)]] int check1 (void); /* { dg-error "nodiscard\[^\n\r]*must be a string constant" } */
 
diff --git a/gcc/testsuite/g++.dg/cpp2a/nodiscard-reason-only-one.C b/gcc/testsuite/g++.dg/cpp2a/nodiscard-reason-only-one.C
index 6104a5ffa085bee433f8da872284bcd259143680..01fbb37436f62644ea889ab904866ce8c6447f72 100644
--- a/gcc/testsuite/g++.dg/cpp2a/nodiscard-reason-only-one.C
+++ b/gcc/testsuite/g++.dg/cpp2a/nodiscard-reason-only-one.C
@@ -1,6 +1,6 @@
 /* nodiscard attribute tests  */
 /* { dg-do compile { target c++20 } } */
-/* { dg-options "-O -ftrack-macro-expansion=0" } */
+/* { dg-options "-O" } */
 
 [[nodiscard("not", "allowed")]] int check1 (void); /* { dg-error "wrong number of arguments.\[^\n\r]*nodiscard" } */