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>
@@ -1902,42 +1903,58 @@ void collect_type_info(const FunctionDecl* FD, QualType& QT,
1902
1903
1903
1904
void make_narg_ctor (const FunctionDecl* FD, const unsigned N,
1904
1905
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 ) {
1906
1908
// Make a code string that follows this pattern:
1907
1909
//
1908
1910
// ClassName(args...)
1911
+ // OR
1912
+ // ClassName[nary] // array of objects
1909
1913
//
1910
1914
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 << " ]" ;
1925
1947
} else {
1926
- callbuf << " \n " ;
1927
- indent (callbuf, indent_level + 1 );
1948
+ callbuf << " *(" << type_name.c_str () << " *)args[" << i << " ]" ;
1928
1949
}
1929
1950
}
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 (auto * CD = dyn_cast<CXXConstructorDecl>(FD);
1955
+ CD && CD->isDefaultConstructor () && !array) {
1956
+ callbuf << " ()" ;
1939
1957
}
1940
- callbuf << " )" ;
1941
1958
}
1942
1959
1943
1960
const 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,
2095
2112
std::ostringstream& buf, int indent_level) {
2096
2113
// Make a code string that follows this pattern:
2097
2114
//
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
+ // }
2101
2124
{
2102
2125
std::ostringstream typedefbuf;
2103
2126
std::ostringstream callbuf;
2104
2127
//
2105
2128
// Write the return value assignment part.
2106
2129
//
2107
2130
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);
2108
2166
callbuf << " (*(" << class_name << " **)ret) = " ;
2109
- callbuf << " (obj ) ? new (*(" << class_name << " **)ret) " ;
2167
+ callbuf << " (is_arena ) ? new (*(" << class_name << " **)ret) " ;
2110
2168
make_narg_ctor (FD, N, typedefbuf, callbuf, class_name, indent_level);
2111
2169
2112
2170
callbuf << " : new " ;
@@ -2118,6 +2176,10 @@ void make_narg_ctor_with_return(const FunctionDecl* FD, const unsigned N,
2118
2176
// End the new expression statement.
2119
2177
//
2120
2178
callbuf << " ;\n " ;
2179
+ indent (callbuf, --indent_level);
2180
+ if (CD->isDefaultConstructor ())
2181
+ callbuf << " }\n " ;
2182
+
2121
2183
//
2122
2184
// Output the whole new expression and return statement.
2123
2185
//
@@ -2630,8 +2692,14 @@ int get_wrapper_code(compat::Interpreter& I, const FunctionDecl* FD,
2630
2692
" __attribute__((annotate(\" __cling__ptrcheck(off)\" )))\n "
2631
2693
" extern \" C\" void " ;
2632
2694
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
+
2635
2703
++indent_level;
2636
2704
if (min_args == num_params) {
2637
2705
// No parameters with defaults.
0 commit comments