5353
5454#include < algorithm>
5555#include < cassert>
56+ #include < cstddef>
5657#include < deque>
5758#include < iterator>
5859#include < map>
@@ -1902,42 +1903,58 @@ void collect_type_info(const FunctionDecl* FD, QualType& QT,
19021903
19031904void make_narg_ctor (const FunctionDecl* FD, const unsigned N,
19041905 std::ostringstream& typedefbuf, std::ostringstream& callbuf,
1905- const std::string& class_name, int indent_level) {
1906+ const std::string& class_name, int indent_level,
1907+ bool array = false ) {
19061908 // Make a code string that follows this pattern:
19071909 //
19081910 // ClassName(args...)
1911+ // OR
1912+ // ClassName[nary] // array of objects
19091913 //
19101914
1911- callbuf << class_name << " (" ;
1912- for (unsigned i = 0U ; i < N; ++i) {
1913- const ParmVarDecl* PVD = FD->getParamDecl (i);
1914- QualType Ty = PVD->getType ();
1915- QualType QT = Ty.getCanonicalType ();
1916- std::string type_name;
1917- EReferenceType refType = kNotReference ;
1918- bool isPointer = false ;
1919- collect_type_info (FD, QT, typedefbuf, callbuf, type_name, refType,
1920- isPointer, indent_level, true );
1921- if (i) {
1922- callbuf << ' ,' ;
1923- if (i % 2 ) {
1924- callbuf << ' ' ;
1915+ if (array)
1916+ callbuf << class_name << " [nary]" ;
1917+ else
1918+ callbuf << class_name;
1919+
1920+ // We cannot pass initialization parameters if we call array new
1921+ if (N && !array) {
1922+ callbuf << " (" ;
1923+ for (unsigned i = 0U ; i < N; ++i) {
1924+ const ParmVarDecl* PVD = FD->getParamDecl (i);
1925+ QualType Ty = PVD->getType ();
1926+ QualType QT = Ty.getCanonicalType ();
1927+ std::string type_name;
1928+ EReferenceType refType = kNotReference ;
1929+ bool isPointer = false ;
1930+ collect_type_info (FD, QT, typedefbuf, callbuf, type_name, refType,
1931+ isPointer, indent_level, true );
1932+ if (i) {
1933+ callbuf << ' ,' ;
1934+ if (i % 2 ) {
1935+ callbuf << ' ' ;
1936+ } else {
1937+ callbuf << " \n " ;
1938+ indent (callbuf, indent_level);
1939+ }
1940+ }
1941+ if (refType != kNotReference ) {
1942+ callbuf << " (" << type_name.c_str ()
1943+ << (refType == kLValueReference ? " &" : " &&" ) << " )*("
1944+ << type_name.c_str () << " *)args[" << i << " ]" ;
1945+ } else if (isPointer) {
1946+ callbuf << " *(" << type_name.c_str () << " **)args[" << i << " ]" ;
19251947 } else {
1926- callbuf << " \n " ;
1927- indent (callbuf, indent_level + 1 );
1948+ callbuf << " *(" << type_name.c_str () << " *)args[" << i << " ]" ;
19281949 }
19291950 }
1930- if (refType != kNotReference ) {
1931- callbuf << " (" << type_name.c_str ()
1932- << (refType == kLValueReference ? " &" : " &&" ) << " )*("
1933- << type_name.c_str () << " *)args[" << i << " ]" ;
1934- } else if (isPointer) {
1935- callbuf << " *(" << type_name.c_str () << " **)args[" << i << " ]" ;
1936- } else {
1937- callbuf << " *(" << type_name.c_str () << " *)args[" << i << " ]" ;
1938- }
1951+ callbuf << " )" ;
1952+ }
1953+ // This can be zero or default-initialized
1954+ else if (const auto * CD = dyn_cast<CXXConstructorDecl>(FD);
1955+ CD && CD->isDefaultConstructor () && !array) {
1956+ callbuf << " ()" ;
19391957 }
1940- callbuf << " )" ;
19411958}
19421959
19431960const DeclContext* get_non_transparent_decl_context (const FunctionDecl* FD) {
@@ -2095,18 +2112,59 @@ void make_narg_ctor_with_return(const FunctionDecl* FD, const unsigned N,
20952112 std::ostringstream& buf, int indent_level) {
20962113 // Make a code string that follows this pattern:
20972114 //
2098- // (*(ClassName**)ret) = (obj) ?
2099- // new (*(ClassName**)ret) ClassName(args...) : new ClassName(args...);
2100- //
2115+ // Array new if nary has been passed, and nargs is 0 (must be default ctor)
2116+ // if (nary) {
2117+ // (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName[nary] :
2118+ // new ClassName[nary];
2119+ // }
2120+ // else {
2121+ // (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName(args...)
2122+ // : new ClassName(args...);
2123+ // }
21012124 {
21022125 std::ostringstream typedefbuf;
21032126 std::ostringstream callbuf;
21042127 //
21052128 // Write the return value assignment part.
21062129 //
21072130 indent (callbuf, indent_level);
2131+ const auto * CD = dyn_cast<CXXConstructorDecl>(FD);
2132+
2133+ // Activate this block only if array new is possible
2134+ // if (nary) {
2135+ // (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName[nary]
2136+ // : new ClassName[nary];
2137+ // }
2138+ // else {
2139+ if (CD->isDefaultConstructor ()) {
2140+ callbuf << " if (nary > 1) {\n " ;
2141+ indent (callbuf, indent_level);
2142+ callbuf << " (*(" << class_name << " **)ret) = " ;
2143+ callbuf << " (is_arena) ? new (*(" << class_name << " **)ret) " ;
2144+ make_narg_ctor (FD, N, typedefbuf, callbuf, class_name, indent_level,
2145+ true );
2146+
2147+ callbuf << " : new " ;
2148+ //
2149+ // Write the actual expression.
2150+ //
2151+ make_narg_ctor (FD, N, typedefbuf, callbuf, class_name, indent_level,
2152+ true );
2153+ //
2154+ // End the new expression statement.
2155+ //
2156+ callbuf << " ;\n " ;
2157+ indent (callbuf, indent_level);
2158+ callbuf << " }\n " ;
2159+ callbuf << " else {\n " ;
2160+ }
2161+
2162+ // Standard branch:
2163+ // (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName(args...)
2164+ // : new ClassName(args...);
2165+ indent (callbuf, indent_level);
21082166 callbuf << " (*(" << class_name << " **)ret) = " ;
2109- callbuf << " (obj ) ? new (*(" << class_name << " **)ret) " ;
2167+ callbuf << " (is_arena ) ? new (*(" << class_name << " **)ret) " ;
21102168 make_narg_ctor (FD, N, typedefbuf, callbuf, class_name, indent_level);
21112169
21122170 callbuf << " : new " ;
@@ -2118,6 +2176,10 @@ void make_narg_ctor_with_return(const FunctionDecl* FD, const unsigned N,
21182176 // End the new expression statement.
21192177 //
21202178 callbuf << " ;\n " ;
2179+ indent (callbuf, --indent_level);
2180+ if (CD->isDefaultConstructor ())
2181+ callbuf << " }\n " ;
2182+
21212183 //
21222184 // Output the whole new expression and return statement.
21232185 //
@@ -2630,8 +2692,14 @@ int get_wrapper_code(compat::Interpreter& I, const FunctionDecl* FD,
26302692 " __attribute__((annotate(\" __cling__ptrcheck(off)\" )))\n "
26312693 " extern \" C\" void " ;
26322694 buf << wrapper_name;
2633- buf << " (void* obj, int nargs, void** args, void* ret)\n "
2634- " {\n " ;
2695+ if (Cpp::IsConstructor (FD)) {
2696+ buf << " (void* ret, unsigned long nary, unsigned long nargs, void** args, "
2697+ " void* is_arena)\n "
2698+ " {\n " ;
2699+ } else
2700+ buf << " (void* obj, unsigned long nargs, void** args, void* ret)\n "
2701+ " {\n " ;
2702+
26352703 ++indent_level;
26362704 if (min_args == num_params) {
26372705 // No parameters with defaults.
0 commit comments