From ed8574ce3b466ebf5af4656750fcb06b8ff607bf Mon Sep 17 00:00:00 2001
From: Virgile Prevosto <virgile.prevosto@m4x.org>
Date: Mon, 7 Feb 2022 17:00:23 +0100
Subject: [PATCH] [clang] use NRVO information at ReturnStmt level

isElidable at ConstructorExpr is not used in this case in clang-13
---
 ClangVisitor.cpp | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/ClangVisitor.cpp b/ClangVisitor.cpp
index 1fcd7ff6..452446f6 100644
--- a/ClangVisitor.cpp
+++ b/ClangVisitor.cpp
@@ -24,7 +24,12 @@
 // Description:
 //   Definition of a translator clang -> intermediate_format (-> cabs -> cil).
 //
-
+extern "C" {
+#include "intermediate_format.h"
+};
+#include <clang/AST/Expr.h>
+#include <clang/AST/ExprCXX.h>
+#include <llvm/Support/Casting.h>
 #ifdef __GNUC__
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wclass-memaccess"
@@ -3910,9 +3915,23 @@ statement FramacVisitor::makeReturnStmt(
   bool* shouldDelay) {
   // implicit precondition: commentLocation != NULL => stmts != NULL
   // the reverse is not true any more thanks to cleanups
-  const clang::Expr* re = returnStmt->getRetValue();
-  expression result = re ? makeLocExpression(re, shouldDelay) : NULL;
-  option e = re ? opt_some_container(result) : opt_none();
+  option e = opt_none();
+  expression result = NULL;
+  const clang::VarDecl* v = returnStmt->getNRVOCandidate();
+  if (v && v->isNRVOVariable()) {
+    // The returned expression should be a CXXConstructorExpr, which
+    // is not marked as elidable since clang 13.0. Hence, do the elision here
+    const clang::CXXConstructExpr* ce =
+        llvm::dyn_cast<clang::CXXConstructExpr>(returnStmt->getRetValue());
+    assert(ce && ce->getNumArgs() == 1);
+    const clang::Expr *re = ce->getArg(0);
+    result = makeLocExpression(re,shouldDelay);
+  }
+  else {
+    const clang::Expr* re = returnStmt->getRetValue();
+    if (re) result = makeLocExpression(re, shouldDelay);
+  }
+  if (result) e = opt_some_container(result);
   if (stmts || !_cleanups.empty()) {
     /* statement */ list* cursor = forwardStmts.getBack()
       ? &forwardStmts.getBack()->next : &forwardStmts.getFront();
-- 
GitLab