Skip to content

Commit 98a75fe

Browse files
committed
Add array new in ctor codegen
1 parent 39ace33 commit 98a75fe

File tree

1 file changed

+93
-33
lines changed

1 file changed

+93
-33
lines changed

lib/CppInterOp/CppInterOp.cpp

Lines changed: 93 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1853,42 +1853,51 @@ void collect_type_info(const FunctionDecl* FD, QualType& QT,
18531853

18541854
void make_narg_ctor(const FunctionDecl* FD, const unsigned N,
18551855
std::ostringstream& typedefbuf, std::ostringstream& callbuf,
1856-
const std::string& class_name, int indent_level) {
1856+
const std::string& class_name, int indent_level,
1857+
bool array = false) {
18571858
// Make a code string that follows this pattern:
18581859
//
18591860
// ClassName(args...)
1861+
// OR
1862+
// ClassName[nary] // array of objects
18601863
//
18611864

1862-
callbuf << class_name << "(";
1863-
for (unsigned i = 0U; i < N; ++i) {
1864-
const ParmVarDecl* PVD = FD->getParamDecl(i);
1865-
QualType Ty = PVD->getType();
1866-
QualType QT = Ty.getCanonicalType();
1867-
std::string type_name;
1868-
EReferenceType refType = kNotReference;
1869-
bool isPointer = false;
1870-
collect_type_info(FD, QT, typedefbuf, callbuf, type_name, refType,
1871-
isPointer, indent_level, true);
1872-
if (i) {
1873-
callbuf << ',';
1874-
if (i % 2) {
1875-
callbuf << ' ';
1865+
if (array)
1866+
callbuf << class_name << "[nary]";
1867+
else
1868+
callbuf << class_name;
1869+
if (N) {
1870+
callbuf << "(";
1871+
for (unsigned i = 0U; i < N; ++i) {
1872+
const ParmVarDecl* PVD = FD->getParamDecl(i);
1873+
QualType Ty = PVD->getType();
1874+
QualType QT = Ty.getCanonicalType();
1875+
std::string type_name;
1876+
EReferenceType refType = kNotReference;
1877+
bool isPointer = false;
1878+
collect_type_info(FD, QT, typedefbuf, callbuf, type_name, refType,
1879+
isPointer, indent_level, true);
1880+
if (i) {
1881+
callbuf << ',';
1882+
if (i % 2) {
1883+
callbuf << ' ';
1884+
} else {
1885+
callbuf << "\n";
1886+
indent(callbuf, indent_level);
1887+
}
1888+
}
1889+
if (refType != kNotReference) {
1890+
callbuf << "(" << type_name.c_str()
1891+
<< (refType == kLValueReference ? "&" : "&&") << ")*("
1892+
<< type_name.c_str() << "*)args[" << i << "]";
1893+
} else if (isPointer) {
1894+
callbuf << "*(" << type_name.c_str() << "**)args[" << i << "]";
18761895
} else {
1877-
callbuf << "\n";
1878-
indent(callbuf, indent_level + 1);
1896+
callbuf << "*(" << type_name.c_str() << "*)args[" << i << "]";
18791897
}
18801898
}
1881-
if (refType != kNotReference) {
1882-
callbuf << "(" << type_name.c_str()
1883-
<< (refType == kLValueReference ? "&" : "&&") << ")*("
1884-
<< type_name.c_str() << "*)args[" << i << "]";
1885-
} else if (isPointer) {
1886-
callbuf << "*(" << type_name.c_str() << "**)args[" << i << "]";
1887-
} else {
1888-
callbuf << "*(" << type_name.c_str() << "*)args[" << i << "]";
1889-
}
1899+
callbuf << ")";
18901900
}
1891-
callbuf << ")";
18921901
}
18931902

18941903
const DeclContext* get_non_transparent_decl_context(const FunctionDecl* FD) {
@@ -2040,18 +2049,59 @@ void make_narg_ctor_with_return(const FunctionDecl* FD, const unsigned N,
20402049
std::ostringstream& buf, int indent_level) {
20412050
// Make a code string that follows this pattern:
20422051
//
2043-
// (*(ClassName**)ret) = (obj) ?
2044-
// new (*(ClassName**)ret) ClassName(args...) : new ClassName(args...);
2045-
//
2052+
// Array new if nary has been passed, and nargs is 0 (must be default ctor)
2053+
// if (nary) {
2054+
// (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName[nary] :
2055+
// new ClassName[nary];
2056+
// }
2057+
// else {
2058+
// (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName(args...)
2059+
// : new ClassName(args...);
2060+
// }
20462061
{
20472062
std::ostringstream typedefbuf;
20482063
std::ostringstream callbuf;
20492064
//
20502065
// Write the return value assignment part.
20512066
//
20522067
indent(callbuf, indent_level);
2068+
auto* CD = dyn_cast<CXXConstructorDecl>(FD);
2069+
2070+
// Activate this block only if array new is possible
2071+
// if (nary) {
2072+
// (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName[nary]
2073+
// : new ClassName[nary];
2074+
// }
2075+
// else {
2076+
if (!CD->isDefaultConstructor() and CD->getNumParams() == 0) {
2077+
callbuf << "if (nary > 1) {\n";
2078+
indent(callbuf, indent_level);
2079+
callbuf << "(*(" << class_name << "**)ret) = ";
2080+
callbuf << "(is_arena) ? new (*(" << class_name << "**)ret) ";
2081+
make_narg_ctor(FD, N, typedefbuf, callbuf, class_name, indent_level,
2082+
true);
2083+
2084+
callbuf << ": new ";
2085+
//
2086+
// Write the actual expression.
2087+
//
2088+
make_narg_ctor(FD, N, typedefbuf, callbuf, class_name, indent_level,
2089+
true);
2090+
//
2091+
// End the new expression statement.
2092+
//
2093+
callbuf << ";\n";
2094+
indent(callbuf, indent_level);
2095+
callbuf << "}\n";
2096+
callbuf << "else {\n";
2097+
}
2098+
2099+
// Standard branch:
2100+
// (*(ClassName**)ret) = (obj) ? new (*(ClassName**)ret) ClassName(args...)
2101+
// : new ClassName(args...);
2102+
indent(callbuf, indent_level);
20532103
callbuf << "(*(" << class_name << "**)ret) = ";
2054-
callbuf << "(obj) ? new (*(" << class_name << "**)ret) ";
2104+
callbuf << "(is_arena) ? new (*(" << class_name << "**)ret) ";
20552105
make_narg_ctor(FD, N, typedefbuf, callbuf, class_name, indent_level);
20562106

20572107
callbuf << ": new ";
@@ -2063,6 +2113,10 @@ void make_narg_ctor_with_return(const FunctionDecl* FD, const unsigned N,
20632113
// End the new expression statement.
20642114
//
20652115
callbuf << ";\n";
2116+
indent(callbuf, --indent_level);
2117+
if (!CD->isDefaultConstructor() and CD->getNumParams() == 0)
2118+
callbuf << "}\n";
2119+
20662120
//
20672121
// Output the whole new expression and return statement.
20682122
//
@@ -2575,8 +2629,14 @@ int get_wrapper_code(compat::Interpreter& I, const FunctionDecl* FD,
25752629
"__attribute__((annotate(\"__cling__ptrcheck(off)\")))\n"
25762630
"extern \"C\" void ";
25772631
buf << wrapper_name;
2578-
buf << "(void* obj, int nargs, void** args, void* ret)\n"
2579-
"{\n";
2632+
if (Cpp::IsConstructor(FD)) {
2633+
buf << "(void* ret, unsigned long nary, unsigned long nargs, void** args, "
2634+
"int is_arena)\n"
2635+
"{\n";
2636+
} else
2637+
buf << "(void* obj, unsigned long nargs, void** args, void* ret)\n"
2638+
"{\n";
2639+
25802640
++indent_level;
25812641
if (min_args == num_params) {
25822642
// No parameters with defaults.

0 commit comments

Comments
 (0)