Hi, C++ constructors return void, even though the D front-end semantic treats them as implicitly returning `this'. To handle this correctly, the object reference is cached and used as the result of the expression.
Bootstrapped and regression tested on x86_64-linux-gnu/-mx32/-m32, committed to mainline, and backported to the gcc-11 release branch. Regards, Iain --- gcc/d/ChangeLog: PR d/101664 * expr.cc (ExprVisitor::visit (CallExp *)): Use object expression as result for C++ constructor calls. gcc/testsuite/ChangeLog: PR d/101664 * gdc.dg/extern-c++/extern-c++.exp: New. * gdc.dg/extern-c++/pr101664.d: New test. * gdc.dg/extern-c++/pr101664_1.cc: New test. --- gcc/d/expr.cc | 13 +++++++ .../gdc.dg/extern-c++/extern-c++.exp | 39 +++++++++++++++++++ gcc/testsuite/gdc.dg/extern-c++/pr101664.d | 15 +++++++ gcc/testsuite/gdc.dg/extern-c++/pr101664_1.cc | 10 +++++ 4 files changed, 77 insertions(+) create mode 100644 gcc/testsuite/gdc.dg/extern-c++/extern-c++.exp create mode 100644 gcc/testsuite/gdc.dg/extern-c++/pr101664.d create mode 100644 gcc/testsuite/gdc.dg/extern-c++/pr101664_1.cc diff --git a/gcc/d/expr.cc b/gcc/d/expr.cc index 99ca958c7c4..85269c6b2be 100644 --- a/gcc/d/expr.cc +++ b/gcc/d/expr.cc @@ -1751,6 +1751,7 @@ public: tree callee = NULL_TREE; tree object = NULL_TREE; tree cleanup = NULL_TREE; + tree returnvalue = NULL_TREE; TypeFunction *tf = NULL; /* Calls to delegates can sometimes look like this. */ @@ -1819,6 +1820,15 @@ public: else fndecl = build_address (fndecl); + /* C++ constructors return void, even though front-end semantic + treats them as implicitly returning `this'. Set returnvalue + to override the result of this expression. */ + if (fd->isCtorDeclaration () && fd->linkage == LINKcpp) + { + thisexp = d_save_expr (thisexp); + returnvalue = thisexp; + } + callee = build_method_call (fndecl, thisexp, fd->type); } } @@ -1885,6 +1895,9 @@ public: build the call expression. */ tree exp = d_build_call (tf, callee, object, e->arguments); + if (returnvalue != NULL_TREE) + exp = compound_expr (exp, returnvalue); + if (tf->isref) exp = build_deref (exp); diff --git a/gcc/testsuite/gdc.dg/extern-c++/extern-c++.exp b/gcc/testsuite/gdc.dg/extern-c++/extern-c++.exp new file mode 100644 index 00000000000..d38f993faaf --- /dev/null +++ b/gcc/testsuite/gdc.dg/extern-c++/extern-c++.exp @@ -0,0 +1,39 @@ +# Copyright (C) 2021 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +# Load support procs. +load_lib gdc-dg.exp + +# We are mixing D and C++ code, need to pull in libstdc++ +global GDC_INCLUDE_CXX_FLAGS +set GDC_INCLUDE_CXX_FLAGS 1 + +# Initialize `dg'. +dg-init + +# Main loop. +if [check_no_compiler_messages extern_c++_tests assembly { + // C++ + int main() { return 0; } +}] { + gdc-dg-runtest [lsort \ + [glob -nocomplain $srcdir/$subdir/*.d ] ] "" "" +} + +set GDC_INCLUDE_CXX_FLAGS 0 + +# All done. +dg-finish diff --git a/gcc/testsuite/gdc.dg/extern-c++/pr101664.d b/gcc/testsuite/gdc.dg/extern-c++/pr101664.d new file mode 100644 index 00000000000..57b3d903582 --- /dev/null +++ b/gcc/testsuite/gdc.dg/extern-c++/pr101664.d @@ -0,0 +1,15 @@ +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101664 +// { dg-do run } +// { dg-options "-O2" } +// { dg-additional-sources "pr101664_1.cc" } + +extern(C++) struct S101664 +{ + int i; + this(int); +} + +void main() +{ + assert(S101664(1).i == 1); +} diff --git a/gcc/testsuite/gdc.dg/extern-c++/pr101664_1.cc b/gcc/testsuite/gdc.dg/extern-c++/pr101664_1.cc new file mode 100644 index 00000000000..066e784293d --- /dev/null +++ b/gcc/testsuite/gdc.dg/extern-c++/pr101664_1.cc @@ -0,0 +1,10 @@ +struct S101664 +{ + int i; + S101664 (int n); +}; + +S101664::S101664 (int n) + : i(n) +{ +} -- 2.30.2