54
54
55
55
#include < algorithm>
56
56
#include < cassert>
57
+ #include < cstddef>
57
58
#include < deque>
58
59
#include < iterator>
59
60
#include < map>
@@ -1926,42 +1927,58 @@ void collect_type_info(const FunctionDecl* FD, QualType& QT,
1926
1927
1927
1928
void make_narg_ctor (const FunctionDecl* FD, const unsigned N,
1928
1929
std::ostringstream& typedefbuf, std::ostringstream& callbuf,
1929
- const std::string& class_name, int indent_level) {
1930
+ const std::string& class_name, int indent_level,
1931
+ bool array = false ) {
1930
1932
// Make a code string that follows this pattern:
1931
1933
//
1932
1934
// ClassName(args...)
1935
+ // OR
1936
+ // ClassName[nary] // array of objects
1933
1937
//
1934
1938
1935
- callbuf << class_name << " (" ;
1936
- for (unsigned i = 0U ; i < N; ++i) {
1937
- const ParmVarDecl* PVD = FD->getParamDecl (i);
1938
- QualType Ty = PVD->getType ();
1939
- QualType QT = Ty.getCanonicalType ();
1940
- std::string type_name;
1941
- EReferenceType refType = kNotReference ;
1942
- bool isPointer = false ;
1943
- collect_type_info (FD, QT, typedefbuf, callbuf, type_name, refType,
1944
- isPointer, indent_level, true );
1945
- if (i) {
1946
- callbuf << ' ,' ;
1947
- if (i % 2 ) {
1948
- callbuf << ' ' ;
1939
+ if (array)
1940
+ callbuf << class_name << " [nary]" ;
1941
+ else
1942
+ callbuf << class_name;
1943
+
1944
+ // We cannot pass initialization parameters if we call array new
1945
+ if (N && !array) {
1946
+ callbuf << " (" ;
1947
+ for (unsigned i = 0U ; i < N; ++i) {
1948
+ const ParmVarDecl* PVD = FD->getParamDecl (i);
1949
+ QualType Ty = PVD->getType ();
1950
+ QualType QT = Ty.getCanonicalType ();
1951
+ std::string type_name;
1952
+ EReferenceType refType = kNotReference ;
1953
+ bool isPointer = false ;
1954
+ collect_type_info (FD, QT, typedefbuf, callbuf, type_name, refType,
1955
+ isPointer, indent_level, true );
1956
+ if (i) {
1957
+ callbuf << ' ,' ;
1958
+ if (i % 2 ) {
1959
+ callbuf << ' ' ;
1960
+ } else {
1961
+ callbuf << " \n " ;
1962
+ indent (callbuf, indent_level);
1963
+ }
1964
+ }
1965
+ if (refType != kNotReference ) {
1966
+ callbuf << " (" << type_name.c_str ()
1967
+ << (refType == kLValueReference ? " &" : " &&" ) << " )*("
1968
+ << type_name.c_str () << " *)args[" << i << " ]" ;
1969
+ } else if (isPointer) {
1970
+ callbuf << " *(" << type_name.c_str () << " **)args[" << i << " ]" ;
1949
1971
} else {
1950
- callbuf << " \n " ;
1951
- indent (callbuf, indent_level + 1 );
1972
+ callbuf << " *(" << type_name.c_str () << " *)args[" << i << " ]" ;
1952
1973
}
1953
1974
}
1954
- if (refType != kNotReference ) {
1955
- callbuf << " (" << type_name.c_str ()
1956
- << (refType == kLValueReference ? " &" : " &&" ) << " )*("
1957
- << type_name.c_str () << " *)args[" << i << " ]" ;
1958
- } else if (isPointer) {
1959
- callbuf << " *(" << type_name.c_str () << " **)args[" << i << " ]" ;
1960
- } else {
1961
- callbuf << " *(" << type_name.c_str () << " *)args[" << i << " ]" ;
1962
- }
1975
+ callbuf << " )" ;
1976
+ }
1977
+ // This can be zero or default-initialized
1978
+ else if (const auto * CD = dyn_cast<CXXConstructorDecl>(FD);
1979
+ CD && CD->isDefaultConstructor () && !array) {
1980
+ callbuf << " ()" ;
1963
1981
}
1964
- callbuf << " )" ;
1965
1982
}
1966
1983
1967
1984
const DeclContext* get_non_transparent_decl_context (const FunctionDecl* FD) {
@@ -2121,18 +2138,59 @@ void make_narg_ctor_with_return(const FunctionDecl* FD, const unsigned N,
2121
2138
std::ostringstream& buf, int indent_level) {
2122
2139
// Make a code string that follows this pattern:
2123
2140
//
2124
- // (*(ClassName**)ret) = (obj) ?
2125
- // new (*(ClassName**)ret) ClassName(args...) : new ClassName(args...);
2126
- //
2141
+ // Array new if nary has been passed, and nargs is 0 (must be default ctor)
2142
+ // if (nary) {
2143
+ // (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName[nary] :
2144
+ // new ClassName[nary];
2145
+ // }
2146
+ // else {
2147
+ // (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName(args...)
2148
+ // : new ClassName(args...);
2149
+ // }
2127
2150
{
2128
2151
std::ostringstream typedefbuf;
2129
2152
std::ostringstream callbuf;
2130
2153
//
2131
2154
// Write the return value assignment part.
2132
2155
//
2133
2156
indent (callbuf, indent_level);
2157
+ const auto * CD = dyn_cast<CXXConstructorDecl>(FD);
2158
+
2159
+ // Activate this block only if array new is possible
2160
+ // if (nary) {
2161
+ // (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName[nary]
2162
+ // : new ClassName[nary];
2163
+ // }
2164
+ // else {
2165
+ if (CD->isDefaultConstructor ()) {
2166
+ callbuf << " if (nary > 1) {\n " ;
2167
+ indent (callbuf, indent_level);
2168
+ callbuf << " (*(" << class_name << " **)ret) = " ;
2169
+ callbuf << " (is_arena) ? new (*(" << class_name << " **)ret) " ;
2170
+ make_narg_ctor (FD, N, typedefbuf, callbuf, class_name, indent_level,
2171
+ true );
2172
+
2173
+ callbuf << " : new " ;
2174
+ //
2175
+ // Write the actual expression.
2176
+ //
2177
+ make_narg_ctor (FD, N, typedefbuf, callbuf, class_name, indent_level,
2178
+ true );
2179
+ //
2180
+ // End the new expression statement.
2181
+ //
2182
+ callbuf << " ;\n " ;
2183
+ indent (callbuf, indent_level);
2184
+ callbuf << " }\n " ;
2185
+ callbuf << " else {\n " ;
2186
+ }
2187
+
2188
+ // Standard branch:
2189
+ // (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName(args...)
2190
+ // : new ClassName(args...);
2191
+ indent (callbuf, indent_level);
2134
2192
callbuf << " (*(" << class_name << " **)ret) = " ;
2135
- callbuf << " (obj ) ? new (*(" << class_name << " **)ret) " ;
2193
+ callbuf << " (is_arena ) ? new (*(" << class_name << " **)ret) " ;
2136
2194
make_narg_ctor (FD, N, typedefbuf, callbuf, class_name, indent_level);
2137
2195
2138
2196
callbuf << " : new " ;
@@ -2144,6 +2202,10 @@ void make_narg_ctor_with_return(const FunctionDecl* FD, const unsigned N,
2144
2202
// End the new expression statement.
2145
2203
//
2146
2204
callbuf << " ;\n " ;
2205
+ indent (callbuf, --indent_level);
2206
+ if (CD->isDefaultConstructor ())
2207
+ callbuf << " }\n " ;
2208
+
2147
2209
//
2148
2210
// Output the whole new expression and return statement.
2149
2211
//
@@ -2652,8 +2714,14 @@ int get_wrapper_code(compat::Interpreter& I, const FunctionDecl* FD,
2652
2714
" __attribute__((annotate(\" __cling__ptrcheck(off)\" )))\n "
2653
2715
" extern \" C\" void " ;
2654
2716
buf << wrapper_name;
2655
- buf << " (void* obj, int nargs, void** args, void* ret)\n "
2656
- " {\n " ;
2717
+ if (Cpp::IsConstructor (FD)) {
2718
+ buf << " (void* ret, unsigned long nary, unsigned long nargs, void** args, "
2719
+ " void* is_arena)\n "
2720
+ " {\n " ;
2721
+ } else
2722
+ buf << " (void* obj, unsigned long nargs, void** args, void* ret)\n "
2723
+ " {\n " ;
2724
+
2657
2725
++indent_level;
2658
2726
if (min_args == num_params) {
2659
2727
// No parameters with defaults.
0 commit comments