5353
5454#include < algorithm>
5555#include < cassert>
56+ #include < cstddef>
5657#include < deque>
5758#include < iterator>
5859#include < map>
@@ -1914,42 +1915,58 @@ void collect_type_info(const FunctionDecl* FD, QualType& QT,
19141915
19151916void make_narg_ctor (const FunctionDecl* FD, const unsigned N,
19161917 std::ostringstream& typedefbuf, std::ostringstream& callbuf,
1917- const std::string& class_name, int indent_level) {
1918+ const std::string& class_name, int indent_level,
1919+ bool array = false ) {
19181920 // Make a code string that follows this pattern:
19191921 //
19201922 // ClassName(args...)
1923+ // OR
1924+ // ClassName[nary] // array of objects
19211925 //
19221926
1923- callbuf << class_name << " (" ;
1924- for (unsigned i = 0U ; i < N; ++i) {
1925- const ParmVarDecl* PVD = FD->getParamDecl (i);
1926- QualType Ty = PVD->getType ();
1927- QualType QT = Ty.getCanonicalType ();
1928- std::string type_name;
1929- EReferenceType refType = kNotReference ;
1930- bool isPointer = false ;
1931- collect_type_info (FD, QT, typedefbuf, callbuf, type_name, refType,
1932- isPointer, indent_level, true );
1933- if (i) {
1934- callbuf << ' ,' ;
1935- if (i % 2 ) {
1936- callbuf << ' ' ;
1927+ if (array)
1928+ callbuf << class_name << " [nary]" ;
1929+ else
1930+ callbuf << class_name;
1931+
1932+ // We cannot pass initialization parameters if we call array new
1933+ if (N && !array) {
1934+ callbuf << " (" ;
1935+ for (unsigned i = 0U ; i < N; ++i) {
1936+ const ParmVarDecl* PVD = FD->getParamDecl (i);
1937+ QualType Ty = PVD->getType ();
1938+ QualType QT = Ty.getCanonicalType ();
1939+ std::string type_name;
1940+ EReferenceType refType = kNotReference ;
1941+ bool isPointer = false ;
1942+ collect_type_info (FD, QT, typedefbuf, callbuf, type_name, refType,
1943+ isPointer, indent_level, true );
1944+ if (i) {
1945+ callbuf << ' ,' ;
1946+ if (i % 2 ) {
1947+ callbuf << ' ' ;
1948+ } else {
1949+ callbuf << " \n " ;
1950+ indent (callbuf, indent_level);
1951+ }
1952+ }
1953+ if (refType != kNotReference ) {
1954+ callbuf << " (" << type_name.c_str ()
1955+ << (refType == kLValueReference ? " &" : " &&" ) << " )*("
1956+ << type_name.c_str () << " *)args[" << i << " ]" ;
1957+ } else if (isPointer) {
1958+ callbuf << " *(" << type_name.c_str () << " **)args[" << i << " ]" ;
19371959 } else {
1938- callbuf << " \n " ;
1939- indent (callbuf, indent_level + 1 );
1960+ callbuf << " *(" << type_name.c_str () << " *)args[" << i << " ]" ;
19401961 }
19411962 }
1942- if (refType != kNotReference ) {
1943- callbuf << " (" << type_name.c_str ()
1944- << (refType == kLValueReference ? " &" : " &&" ) << " )*("
1945- << type_name.c_str () << " *)args[" << i << " ]" ;
1946- } else if (isPointer) {
1947- callbuf << " *(" << type_name.c_str () << " **)args[" << i << " ]" ;
1948- } else {
1949- callbuf << " *(" << type_name.c_str () << " *)args[" << i << " ]" ;
1950- }
1963+ callbuf << " )" ;
1964+ }
1965+ // This can be zero or default-initialized
1966+ else if (const auto * CD = dyn_cast<CXXConstructorDecl>(FD);
1967+ CD && CD->isDefaultConstructor () && !array) {
1968+ callbuf << " ()" ;
19511969 }
1952- callbuf << " )" ;
19531970}
19541971
19551972const DeclContext* get_non_transparent_decl_context (const FunctionDecl* FD) {
@@ -2108,18 +2125,59 @@ void make_narg_ctor_with_return(const FunctionDecl* FD, const unsigned N,
21082125 std::ostringstream& buf, int indent_level) {
21092126 // Make a code string that follows this pattern:
21102127 //
2111- // (*(ClassName**)ret) = (obj) ?
2112- // new (*(ClassName**)ret) ClassName(args...) : new ClassName(args...);
2113- //
2128+ // Array new if nary has been passed, and nargs is 0 (must be default ctor)
2129+ // if (nary) {
2130+ // (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName[nary] :
2131+ // new ClassName[nary];
2132+ // }
2133+ // else {
2134+ // (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName(args...)
2135+ // : new ClassName(args...);
2136+ // }
21142137 {
21152138 std::ostringstream typedefbuf;
21162139 std::ostringstream callbuf;
21172140 //
21182141 // Write the return value assignment part.
21192142 //
21202143 indent (callbuf, indent_level);
2144+ const auto * CD = dyn_cast<CXXConstructorDecl>(FD);
2145+
2146+ // Activate this block only if array new is possible
2147+ // if (nary) {
2148+ // (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName[nary]
2149+ // : new ClassName[nary];
2150+ // }
2151+ // else {
2152+ if (CD->isDefaultConstructor ()) {
2153+ callbuf << " if (nary > 1) {\n " ;
2154+ indent (callbuf, indent_level);
2155+ callbuf << " (*(" << class_name << " **)ret) = " ;
2156+ callbuf << " (is_arena) ? new (*(" << class_name << " **)ret) " ;
2157+ make_narg_ctor (FD, N, typedefbuf, callbuf, class_name, indent_level,
2158+ true );
2159+
2160+ callbuf << " : new " ;
2161+ //
2162+ // Write the actual expression.
2163+ //
2164+ make_narg_ctor (FD, N, typedefbuf, callbuf, class_name, indent_level,
2165+ true );
2166+ //
2167+ // End the new expression statement.
2168+ //
2169+ callbuf << " ;\n " ;
2170+ indent (callbuf, indent_level);
2171+ callbuf << " }\n " ;
2172+ callbuf << " else {\n " ;
2173+ }
2174+
2175+ // Standard branch:
2176+ // (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName(args...)
2177+ // : new ClassName(args...);
2178+ indent (callbuf, indent_level);
21212179 callbuf << " (*(" << class_name << " **)ret) = " ;
2122- callbuf << " (obj ) ? new (*(" << class_name << " **)ret) " ;
2180+ callbuf << " (is_arena ) ? new (*(" << class_name << " **)ret) " ;
21232181 make_narg_ctor (FD, N, typedefbuf, callbuf, class_name, indent_level);
21242182
21252183 callbuf << " : new " ;
@@ -2131,6 +2189,10 @@ void make_narg_ctor_with_return(const FunctionDecl* FD, const unsigned N,
21312189 // End the new expression statement.
21322190 //
21332191 callbuf << " ;\n " ;
2192+ indent (callbuf, --indent_level);
2193+ if (CD->isDefaultConstructor ())
2194+ callbuf << " }\n " ;
2195+
21342196 //
21352197 // Output the whole new expression and return statement.
21362198 //
@@ -2643,8 +2705,14 @@ int get_wrapper_code(compat::Interpreter& I, const FunctionDecl* FD,
26432705 " __attribute__((annotate(\" __cling__ptrcheck(off)\" )))\n "
26442706 " extern \" C\" void " ;
26452707 buf << wrapper_name;
2646- buf << " (void* obj, int nargs, void** args, void* ret)\n "
2647- " {\n " ;
2708+ if (Cpp::IsConstructor (FD)) {
2709+ buf << " (void* ret, unsigned long nary, unsigned long nargs, void** args, "
2710+ " void* is_arena)\n "
2711+ " {\n " ;
2712+ } else
2713+ buf << " (void* obj, unsigned long nargs, void** args, void* ret)\n "
2714+ " {\n " ;
2715+
26482716 ++indent_level;
26492717 if (min_args == num_params) {
26502718 // No parameters with defaults.
0 commit comments