5353
5454#include < algorithm>
5555#include < cassert>
56+ #include < cstddef>
5657#include < deque>
5758#include < iterator>
5859#include < map>
@@ -1920,42 +1921,58 @@ void collect_type_info(const FunctionDecl* FD, QualType& QT,
19201921
19211922void make_narg_ctor (const FunctionDecl* FD, const unsigned N,
19221923 std::ostringstream& typedefbuf, std::ostringstream& callbuf,
1923- const std::string& class_name, int indent_level) {
1924+ const std::string& class_name, int indent_level,
1925+ bool array = false ) {
19241926 // Make a code string that follows this pattern:
19251927 //
19261928 // ClassName(args...)
1929+ // OR
1930+ // ClassName[nary] // array of objects
19271931 //
19281932
1929- callbuf << class_name << " (" ;
1930- for (unsigned i = 0U ; i < N; ++i) {
1931- const ParmVarDecl* PVD = FD->getParamDecl (i);
1932- QualType Ty = PVD->getType ();
1933- QualType QT = Ty.getCanonicalType ();
1934- std::string type_name;
1935- EReferenceType refType = kNotReference ;
1936- bool isPointer = false ;
1937- collect_type_info (FD, QT, typedefbuf, callbuf, type_name, refType,
1938- isPointer, indent_level, true );
1939- if (i) {
1940- callbuf << ' ,' ;
1941- if (i % 2 ) {
1942- callbuf << ' ' ;
1933+ if (array)
1934+ callbuf << class_name << " [nary]" ;
1935+ else
1936+ callbuf << class_name;
1937+
1938+ // We cannot pass initialization parameters if we call array new
1939+ if (N && !array) {
1940+ callbuf << " (" ;
1941+ for (unsigned i = 0U ; i < N; ++i) {
1942+ const ParmVarDecl* PVD = FD->getParamDecl (i);
1943+ QualType Ty = PVD->getType ();
1944+ QualType QT = Ty.getCanonicalType ();
1945+ std::string type_name;
1946+ EReferenceType refType = kNotReference ;
1947+ bool isPointer = false ;
1948+ collect_type_info (FD, QT, typedefbuf, callbuf, type_name, refType,
1949+ isPointer, indent_level, true );
1950+ if (i) {
1951+ callbuf << ' ,' ;
1952+ if (i % 2 ) {
1953+ callbuf << ' ' ;
1954+ } else {
1955+ callbuf << " \n " ;
1956+ indent (callbuf, indent_level);
1957+ }
1958+ }
1959+ if (refType != kNotReference ) {
1960+ callbuf << " (" << type_name.c_str ()
1961+ << (refType == kLValueReference ? " &" : " &&" ) << " )*("
1962+ << type_name.c_str () << " *)args[" << i << " ]" ;
1963+ } else if (isPointer) {
1964+ callbuf << " *(" << type_name.c_str () << " **)args[" << i << " ]" ;
19431965 } else {
1944- callbuf << " \n " ;
1945- indent (callbuf, indent_level + 1 );
1966+ callbuf << " *(" << type_name.c_str () << " *)args[" << i << " ]" ;
19461967 }
19471968 }
1948- if (refType != kNotReference ) {
1949- callbuf << " (" << type_name.c_str ()
1950- << (refType == kLValueReference ? " &" : " &&" ) << " )*("
1951- << type_name.c_str () << " *)args[" << i << " ]" ;
1952- } else if (isPointer) {
1953- callbuf << " *(" << type_name.c_str () << " **)args[" << i << " ]" ;
1954- } else {
1955- callbuf << " *(" << type_name.c_str () << " *)args[" << i << " ]" ;
1956- }
1969+ callbuf << " )" ;
1970+ }
1971+ // This can be zero or default-initialized
1972+ else if (const auto * CD = dyn_cast<CXXConstructorDecl>(FD);
1973+ CD && CD->isDefaultConstructor () && !array) {
1974+ callbuf << " ()" ;
19571975 }
1958- callbuf << " )" ;
19591976}
19601977
19611978const DeclContext* get_non_transparent_decl_context (const FunctionDecl* FD) {
@@ -2114,18 +2131,59 @@ void make_narg_ctor_with_return(const FunctionDecl* FD, const unsigned N,
21142131 std::ostringstream& buf, int indent_level) {
21152132 // Make a code string that follows this pattern:
21162133 //
2117- // (*(ClassName**)ret) = (obj) ?
2118- // new (*(ClassName**)ret) ClassName(args...) : new ClassName(args...);
2119- //
2134+ // Array new if nary has been passed, and nargs is 0 (must be default ctor)
2135+ // if (nary) {
2136+ // (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName[nary] :
2137+ // new ClassName[nary];
2138+ // }
2139+ // else {
2140+ // (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName(args...)
2141+ // : new ClassName(args...);
2142+ // }
21202143 {
21212144 std::ostringstream typedefbuf;
21222145 std::ostringstream callbuf;
21232146 //
21242147 // Write the return value assignment part.
21252148 //
21262149 indent (callbuf, indent_level);
2150+ const auto * CD = dyn_cast<CXXConstructorDecl>(FD);
2151+
2152+ // Activate this block only if array new is possible
2153+ // if (nary) {
2154+ // (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName[nary]
2155+ // : new ClassName[nary];
2156+ // }
2157+ // else {
2158+ if (CD->isDefaultConstructor ()) {
2159+ callbuf << " if (nary > 1) {\n " ;
2160+ indent (callbuf, indent_level);
2161+ callbuf << " (*(" << class_name << " **)ret) = " ;
2162+ callbuf << " (is_arena) ? new (*(" << class_name << " **)ret) " ;
2163+ make_narg_ctor (FD, N, typedefbuf, callbuf, class_name, indent_level,
2164+ true );
2165+
2166+ callbuf << " : new " ;
2167+ //
2168+ // Write the actual expression.
2169+ //
2170+ make_narg_ctor (FD, N, typedefbuf, callbuf, class_name, indent_level,
2171+ true );
2172+ //
2173+ // End the new expression statement.
2174+ //
2175+ callbuf << " ;\n " ;
2176+ indent (callbuf, indent_level);
2177+ callbuf << " }\n " ;
2178+ callbuf << " else {\n " ;
2179+ }
2180+
2181+ // Standard branch:
2182+ // (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName(args...)
2183+ // : new ClassName(args...);
2184+ indent (callbuf, indent_level);
21272185 callbuf << " (*(" << class_name << " **)ret) = " ;
2128- callbuf << " (obj ) ? new (*(" << class_name << " **)ret) " ;
2186+ callbuf << " (is_arena ) ? new (*(" << class_name << " **)ret) " ;
21292187 make_narg_ctor (FD, N, typedefbuf, callbuf, class_name, indent_level);
21302188
21312189 callbuf << " : new " ;
@@ -2137,6 +2195,10 @@ void make_narg_ctor_with_return(const FunctionDecl* FD, const unsigned N,
21372195 // End the new expression statement.
21382196 //
21392197 callbuf << " ;\n " ;
2198+ indent (callbuf, --indent_level);
2199+ if (CD->isDefaultConstructor ())
2200+ callbuf << " }\n " ;
2201+
21402202 //
21412203 // Output the whole new expression and return statement.
21422204 //
@@ -2651,8 +2713,14 @@ int get_wrapper_code(compat::Interpreter& I, const FunctionDecl* FD,
26512713 " __attribute__((annotate(\" __cling__ptrcheck(off)\" )))\n "
26522714 " extern \" C\" void " ;
26532715 buf << wrapper_name;
2654- buf << " (void* obj, int nargs, void** args, void* ret)\n "
2655- " {\n " ;
2716+ if (Cpp::IsConstructor (FD)) {
2717+ buf << " (void* ret, unsigned long nary, unsigned long nargs, void** args, "
2718+ " void* is_arena)\n "
2719+ " {\n " ;
2720+ } else
2721+ buf << " (void* obj, unsigned long nargs, void** args, void* ret)\n "
2722+ " {\n " ;
2723+
26562724 ++indent_level;
26572725 if (min_args == num_params) {
26582726 // No parameters with defaults.
0 commit comments