53
53
54
54
#include < algorithm>
55
55
#include < cassert>
56
+ #include < cstddef>
56
57
#include < deque>
57
58
#include < iterator>
58
59
#include < map>
@@ -1914,42 +1915,58 @@ void collect_type_info(const FunctionDecl* FD, QualType& QT,
1914
1915
1915
1916
void make_narg_ctor (const FunctionDecl* FD, const unsigned N,
1916
1917
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 ) {
1918
1920
// Make a code string that follows this pattern:
1919
1921
//
1920
1922
// ClassName(args...)
1923
+ // OR
1924
+ // ClassName[nary] // array of objects
1921
1925
//
1922
1926
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 << " ]" ;
1937
1959
} else {
1938
- callbuf << " \n " ;
1939
- indent (callbuf, indent_level + 1 );
1960
+ callbuf << " *(" << type_name.c_str () << " *)args[" << i << " ]" ;
1940
1961
}
1941
1962
}
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 << " ()" ;
1951
1969
}
1952
- callbuf << " )" ;
1953
1970
}
1954
1971
1955
1972
const 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,
2108
2125
std::ostringstream& buf, int indent_level) {
2109
2126
// Make a code string that follows this pattern:
2110
2127
//
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
+ // }
2114
2137
{
2115
2138
std::ostringstream typedefbuf;
2116
2139
std::ostringstream callbuf;
2117
2140
//
2118
2141
// Write the return value assignment part.
2119
2142
//
2120
2143
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);
2121
2179
callbuf << " (*(" << class_name << " **)ret) = " ;
2122
- callbuf << " (obj ) ? new (*(" << class_name << " **)ret) " ;
2180
+ callbuf << " (is_arena ) ? new (*(" << class_name << " **)ret) " ;
2123
2181
make_narg_ctor (FD, N, typedefbuf, callbuf, class_name, indent_level);
2124
2182
2125
2183
callbuf << " : new " ;
@@ -2131,6 +2189,10 @@ void make_narg_ctor_with_return(const FunctionDecl* FD, const unsigned N,
2131
2189
// End the new expression statement.
2132
2190
//
2133
2191
callbuf << " ;\n " ;
2192
+ indent (callbuf, --indent_level);
2193
+ if (CD->isDefaultConstructor ())
2194
+ callbuf << " }\n " ;
2195
+
2134
2196
//
2135
2197
// Output the whole new expression and return statement.
2136
2198
//
@@ -2643,8 +2705,14 @@ int get_wrapper_code(compat::Interpreter& I, const FunctionDecl* FD,
2643
2705
" __attribute__((annotate(\" __cling__ptrcheck(off)\" )))\n "
2644
2706
" extern \" C\" void " ;
2645
2707
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
+
2648
2716
++indent_level;
2649
2717
if (min_args == num_params) {
2650
2718
// No parameters with defaults.
0 commit comments