Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TClingCallFunc.cxx
Go to the documentation of this file.
1// root/core/meta
2// vim: sw=3
3// Author: Paul Russo 30/07/2012
4// Author: Vassil Vassilev 9/02/2013
5
6/*************************************************************************
7 * Copyright (C) 1995-2023, Rene Brun and Fons Rademakers. *
8 * All rights reserved. *
9 * *
10 * For the licensing terms see $ROOTSYS/LICENSE. *
11 * For the list of contributors see $ROOTSYS/README/CREDITS. *
12 *************************************************************************/
13
14/** \class TClingCallFunc
15Emulation of the CINT CallFunc class.
16
17The CINT C++ interpreter provides an interface for calling
18functions through the generated wrappers in dictionaries with
19the CallFunc class. This class provides the same functionality,
20using an interface as close as possible to CallFunc but the
21function metadata and calling service comes from the Cling
22C++ interpreter and the Clang C++ compiler, not CINT.
23*/
24
25#include "TClingCallFunc.h"
26
27#include "TClingClassInfo.h"
28#include "TClingMethodInfo.h"
29#include "TClingUtils.h"
30
31#include "TError.h"
32#include "TCling.h"
33
34#include "TInterpreter.h"
35
36#include "cling/Interpreter/CompilationOptions.h"
37#include "cling/Interpreter/Interpreter.h"
38#include "cling/Interpreter/LookupHelper.h"
39#include "cling/Interpreter/Transaction.h"
40#include "cling/Interpreter/Value.h"
41#include "cling/Utils/AST.h"
42
43#include "clang/AST/ASTContext.h"
44#include "clang/AST/Decl.h"
45#include "clang/AST/DeclCXX.h"
46#include "clang/AST/GlobalDecl.h"
47#include "clang/AST/PrettyPrinter.h"
48#include "clang/AST/QualTypeNames.h"
49#include "clang/AST/RecordLayout.h"
50#include "clang/AST/Type.h"
51#include "clang/Frontend/CompilerInstance.h"
52#include "clang/Lex/Preprocessor.h"
53#include "clang/Sema/Sema.h"
54#include "clang/Sema/Lookup.h"
55
56#include "llvm/ADT/APInt.h"
57#include "llvm/ExecutionEngine/ExecutionEngine.h"
58#include "llvm/ExecutionEngine/GenericValue.h"
59#include "llvm/Support/Casting.h"
60#include "llvm/Support/raw_ostream.h"
61#include "llvm/IR/LLVMContext.h"
62#include "llvm/IR/DerivedTypes.h"
63#include "llvm/IR/Function.h"
64#include "llvm/IR/GlobalValue.h"
65#include "llvm/IR/Module.h"
66#include "llvm/IR/Type.h"
67
68#include "clang/Sema/SemaInternal.h"
69
70#include <map>
71#include <string>
72#include <sstream>
73
74using namespace ROOT;
75using namespace llvm;
76using namespace clang;
77using namespace std;
78
79static unsigned long long gWrapperSerial = 0LL;
80static const string kIndentString(" ");
81
82static map<const Decl *, void *> gWrapperStore;
83static map<const Decl *, void *> gCtorWrapperStore;
84static map<const Decl *, void *> gDtorWrapperStore;
85
86static
87inline
88void
89indent(ostringstream &buf, int indent_level)
90{
91 for (int i = 0; i < indent_level; ++i) {
92 buf << kIndentString;
93 }
94}
95
96static
97void
98EvaluateExpr(cling::Interpreter &interp, const Expr *E, cling::Value &V)
99{
100 // Evaluate an Expr* and return its cling::Value
101 ASTContext &C = interp.getCI()->getASTContext();
102 clang::Expr::EvalResult evalRes;
103 if (E->EvaluateAsInt(evalRes, C, /*AllowSideEffects*/Expr::SE_NoSideEffects)) {
104 // FIXME: Find the right type or make sure we have an interface to update
105 // the clang::Type in the cling::Value
106 APSInt res = evalRes.Val.getInt();
107 // IntTy or maybe better E->getType()?
108 V = cling::Value(C.IntTy, interp);
109 // We must use the correct signedness otherwise the zero extension
110 // fails if the actual type is strictly less than long long.
111 if (res.isSigned())
112 V.setLongLong(res.getSExtValue());
113 else
114 V.setULongLong(res.getZExtValue());
115 return;
116 }
117 // TODO: Build a wrapper around the expression to avoid decompilation and
118 // compilation and other string operations.
119 PrintingPolicy Policy(C.getPrintingPolicy());
120 Policy.SuppressTagKeyword = true;
121 Policy.SuppressUnwrittenScope = false;
122 Policy.SuppressInitializers = false;
123 Policy.AnonymousTagLocations = false;
124 string buf;
125 raw_string_ostream out(buf);
126 E->printPretty(out, /*Helper=*/nullptr, Policy, /*Indentation=*/0);
127 out << ';'; // no value printing
128 out.flush();
129 // Evaluate() will set V to invalid if evaluation fails.
130 interp.evaluate(buf, V);
131}
132
134{
135 // This function is non-const to use caching overload of GetDecl()!
136 return GetDecl()->getMinRequiredArguments();
137}
138
139void *TClingCallFunc::compile_wrapper(const string &wrapper_name, const string &wrapper,
140 bool withAccessControl/*=true*/)
141{
142 return fInterp->compileFunction(wrapper_name, wrapper, false /*ifUnique*/,
143 withAccessControl);
144}
145
146static void GetTypeAsString(QualType QT, string& type_name, ASTContext &C,
147 PrintingPolicy Policy) {
148
149 // FIXME: Take the code here https://github.com/root-project/root/blob/550fb2644f3c07d1db72b9b4ddc4eba5a99ddc12/interpreter/cling/lib/Utils/AST.cpp#L316-L350
150 // to make hist/histdrawv7/test/histhistdrawv7testUnit work into
151 // QualTypeNames.h in clang
152 //type_name = clang::TypeName::getFullyQualifiedName(QT, C, Policy);
153 cling::utils::Transform::Config Config;
154 QT = cling::utils::Transform::GetPartiallyDesugaredType(C, QT, Config, /*fullyQualify=*/true);
155 QT.getAsStringInternal(type_name, Policy);
156}
157
158void TClingCallFunc::collect_type_info(QualType &QT, ostringstream &typedefbuf, std::ostringstream &callbuf,
159 string &type_name, EReferenceType &refType, bool &isPointer, int indent_level,
160 bool forArgument)
161{
162 //
163 // Collect information about type type of a function parameter
164 // needed for building the wrapper function.
165 //
166 const FunctionDecl *FD = GetDecl();
167 ASTContext &C = FD->getASTContext();
168 PrintingPolicy Policy(C.getPrintingPolicy());
169 refType = kNotReference;
170 if (QT->isRecordType() && forArgument) {
171 GetTypeAsString(QT, type_name, C, Policy);
172 return;
173 }
174 if (QT->isFunctionPointerType()) {
175 string fp_typedef_name;
176 {
177 ostringstream nm;
178 nm << "FP" << gWrapperSerial++;
179 type_name = nm.str();
180 raw_string_ostream OS(fp_typedef_name);
181 QT.print(OS, Policy, type_name);
182 OS.flush();
183 }
184 for (int i = 0; i < indent_level; ++i) {
185 typedefbuf << kIndentString;
186 }
187 typedefbuf << "typedef " << fp_typedef_name << ";\n";
188 return;
189 } else if (QT->isMemberPointerType()) {
190 string mp_typedef_name;
191 {
192 ostringstream nm;
193 nm << "MP" << gWrapperSerial++;
194 type_name = nm.str();
195 raw_string_ostream OS(mp_typedef_name);
196 QT.print(OS, Policy, type_name);
197 OS.flush();
198 }
199 for (int i = 0; i < indent_level; ++i) {
200 typedefbuf << kIndentString;
201 }
202 typedefbuf << "typedef " << mp_typedef_name << ";\n";
203 return;
204 } else if (QT->isPointerType()) {
205 isPointer = true;
206 QT = cast<clang::PointerType>(QT)->getPointeeType();
207 } else if (QT->isReferenceType()) {
208 if (QT->isRValueReferenceType()) refType = kRValueReference;
209 else refType = kLValueReference;
210 QT = cast<ReferenceType>(QT)->getPointeeType();
211 }
212 // Fall through for the array type to deal with reference/pointer ro array type.
213 if (QT->isArrayType()) {
214 string ar_typedef_name;
215 {
216 ostringstream ar;
217 ar << "AR" << gWrapperSerial++;
218 type_name = ar.str();
219 raw_string_ostream OS(ar_typedef_name);
220 QT.print(OS, Policy, type_name);
221 OS.flush();
222 }
223 for (int i = 0; i < indent_level; ++i) {
224 typedefbuf << kIndentString;
225 }
226 typedefbuf << "typedef " << ar_typedef_name << ";\n";
227 return;
228 }
229 GetTypeAsString(QT, type_name, C, Policy);
230}
231
232void TClingCallFunc::make_narg_ctor(const unsigned N, ostringstream &typedefbuf,
233 ostringstream &callbuf, const string &class_name,
234 int indent_level)
235{
236 // Make a code string that follows this pattern:
237 //
238 // new ClassName(args...)
239 //
240 const FunctionDecl *FD = GetDecl();
241
242 callbuf << "new " << class_name << "(";
243 for (unsigned i = 0U; i < N; ++i) {
244 const ParmVarDecl *PVD = FD->getParamDecl(i);
245 QualType Ty = PVD->getType();
246 QualType QT = Ty.getCanonicalType();
247 string type_name;
249 bool isPointer = false;
250 collect_type_info(QT, typedefbuf, callbuf, type_name,
251 refType, isPointer, indent_level, true);
252 if (i) {
253 callbuf << ',';
254 if (i % 2) {
255 callbuf << ' ';
256 } else {
257 callbuf << "\n";
258 for (int j = 0; j <= indent_level; ++j) {
259 callbuf << kIndentString;
260 }
261 }
262 }
263 if (refType != kNotReference) {
264 callbuf << "(" << type_name.c_str() <<
265 (refType == kLValueReference ? "&" : "&&") << ")*(" << type_name.c_str() << "*)args["
266 << i << "]";
267 } else if (isPointer) {
268 callbuf << "*(" << type_name.c_str() << "**)args["
269 << i << "]";
270 } else {
271 callbuf << "*(" << type_name.c_str() << "*)args[" << i << "]";
272 }
273 }
274 callbuf << ")";
275}
276
277void TClingCallFunc::make_narg_call(const std::string &return_type, const unsigned N, ostringstream &typedefbuf,
278 ostringstream &callbuf, const string &class_name, int indent_level)
279{
280 //
281 // Make a code string that follows this pattern:
282 //
283 // ((<class>*)obj)-><method>(*(<arg-i-type>*)args[i], ...)
284 //
285 const FunctionDecl *FD = GetDecl();
286
287 // Sometimes it's necessary that we cast the function we want to call first
288 // to its explicit function type before calling it. This is supposed to prevent
289 // that we accidentially ending up in a function that is not the one we're
290 // supposed to call here (e.g. because the C++ function lookup decides to take
291 // another function that better fits).
292 // This method has some problems, e.g. when we call a function with default
293 // arguments and we don't provide all arguments, we would fail with this pattern.
294 // Same applies with member methods which seem to cause parse failures even when
295 // we supply the object parameter.
296 // Therefore we only use it in cases where we know it works and set this variable
297 // to true when we do.
298 bool ShouldCastFunction = !isa<CXXMethodDecl>(FD) && N == FD->getNumParams();
299 if (ShouldCastFunction) {
300 callbuf << "(";
301 callbuf << "(";
302 callbuf << return_type << " (&)";
303 {
304 callbuf << "(";
305 for (unsigned i = 0U; i < N; ++i) {
306 if (i) {
307 callbuf << ',';
308 if (i % 2) {
309 callbuf << ' ';
310 } else {
311 callbuf << "\n";
312 for (int j = 0; j <= indent_level; ++j) {
313 callbuf << kIndentString;
314 }
315 }
316 }
317 const ParmVarDecl *PVD = FD->getParamDecl(i);
318 QualType Ty = PVD->getType();
319 QualType QT = Ty.getCanonicalType();
320 std::string arg_type;
321 ASTContext &C = FD->getASTContext();
322 GetTypeAsString(QT, arg_type, C, C.getPrintingPolicy());
323 callbuf << arg_type;
324 }
325 if (FD->isVariadic())
326 callbuf << ", ...";
327 callbuf << ")";
328 }
329
330 callbuf << ")";
331 }
332
333 if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
334 // This is a class, struct, or union member.
335 if (MD->isConst())
336 callbuf << "((const " << class_name << "*)obj)->";
337 else
338 callbuf << "((" << class_name << "*)obj)->";
339 } else if (const NamedDecl *ND =
340 dyn_cast<NamedDecl>(GetDeclContext())) {
341 // This is a namespace member.
342 (void) ND;
343 callbuf << class_name << "::";
344 }
345 // callbuf << fMethod->Name() << "(";
346 {
347 std::string name;
348 {
349 llvm::raw_string_ostream stream(name);
350 FD->getNameForDiagnostic(stream, FD->getASTContext().getPrintingPolicy(), /*Qualified=*/false);
351 }
352 callbuf << name;
353 }
354 if (ShouldCastFunction) callbuf << ")";
355
356 callbuf << "(";
357 for (unsigned i = 0U; i < N; ++i) {
358 const ParmVarDecl *PVD = FD->getParamDecl(i);
359 QualType Ty = PVD->getType();
360 QualType QT = Ty.getCanonicalType();
361 string type_name;
363 bool isPointer = false;
364 collect_type_info(QT, typedefbuf, callbuf, type_name, refType, isPointer, indent_level, true);
365
366 if (i) {
367 callbuf << ',';
368 if (i % 2) {
369 callbuf << ' ';
370 } else {
371 callbuf << "\n";
372 for (int j = 0; j <= indent_level; ++j) {
373 callbuf << kIndentString;
374 }
375 }
376 }
377
378 if (refType != kNotReference) {
379 callbuf << "(" << type_name.c_str() <<
380 (refType == kLValueReference ? "&" : "&&") << ")*(" << type_name.c_str() << "*)args["
381 << i << "]";
382 } else if (isPointer) {
383 callbuf << "*(" << type_name.c_str() << "**)args["
384 << i << "]";
385 } else {
386 // pointer falls back to non-pointer case; the argument preserves
387 // the "pointerness" (i.e. doesn't reference the value).
388 callbuf << "*(" << type_name.c_str() << "*)args[" << i << "]";
389 }
390 }
391 callbuf << ")";
392}
393
394void TClingCallFunc::make_narg_ctor_with_return(const unsigned N, const string &class_name,
395 ostringstream &buf, int indent_level)
396{
397 // Make a code string that follows this pattern:
398 //
399 // if (ret) {
400 // (*(ClassName**)ret) = new ClassName(args...);
401 // }
402 // else {
403 // new ClassName(args...);
404 // }
405 //
406 for (int i = 0; i < indent_level; ++i) {
407 buf << kIndentString;
408 }
409 buf << "if (ret) {\n";
410 ++indent_level;
411 {
412 ostringstream typedefbuf;
413 ostringstream callbuf;
414 //
415 // Write the return value assignment part.
416 //
417 for (int i = 0; i < indent_level; ++i) {
418 callbuf << kIndentString;
419 }
420 callbuf << "(*(" << class_name << "**)ret) = ";
421 //
422 // Write the actual new expression.
423 //
424 make_narg_ctor(N, typedefbuf, callbuf, class_name, indent_level);
425 //
426 // End the new expression statement.
427 //
428 callbuf << ";\n";
429 for (int i = 0; i < indent_level; ++i) {
430 callbuf << kIndentString;
431 }
432 callbuf << "return;\n";
433 //
434 // Output the whole new expression and return statement.
435 //
436 buf << typedefbuf.str() << callbuf.str();
437 }
438 --indent_level;
439 for (int i = 0; i < indent_level; ++i) {
440 buf << kIndentString;
441 }
442 buf << "}\n";
443 for (int i = 0; i < indent_level; ++i) {
444 buf << kIndentString;
445 }
446 buf << "else {\n";
447 ++indent_level;
448 {
449 ostringstream typedefbuf;
450 ostringstream callbuf;
451 for (int i = 0; i < indent_level; ++i) {
452 callbuf << kIndentString;
453 }
454 make_narg_ctor(N, typedefbuf, callbuf, class_name, indent_level);
455 callbuf << ";\n";
456 for (int i = 0; i < indent_level; ++i) {
457 callbuf << kIndentString;
458 }
459 callbuf << "return;\n";
460 buf << typedefbuf.str() << callbuf.str();
461 }
462 --indent_level;
463 for (int i = 0; i < indent_level; ++i) {
464 buf << kIndentString;
465 }
466 buf << "}\n";
467}
468
469///////////////////////////////////////////////////////////////////////////////
470// Returns the DeclContext corresponding to fMethod's Decl.
471// \Note that this might be a FunctionDecl or a UsingShadowDecl; we use the
472// DeclContext of the UsingShadowDecl e.g. for constructing a derived class
473// object, even if invoking a function made available by a using declaration
474// of a constructor of a base class (ROOT-11010).
475
476const clang::DeclContext *TClingCallFunc::GetDeclContext() const {
477 return fMethod->GetDecl()->getDeclContext();
478}
479
480int TClingCallFunc::get_wrapper_code(std::string &wrapper_name, std::string &wrapper)
481{
482 const FunctionDecl *FD = GetDecl();
483 assert(FD && "generate_wrapper called without a function decl!");
484 ASTContext &Context = FD->getASTContext();
485 PrintingPolicy Policy(Context.getPrintingPolicy());
486 //
487 // Get the class or namespace name.
488 //
489 string class_name;
490 const clang::DeclContext *DC = GetDeclContext();
491 if (const TypeDecl *TD = dyn_cast<TypeDecl>(DC)) {
492 // This is a class, struct, or union member.
493 QualType QT(TD->getTypeForDecl(), 0);
494 GetTypeAsString(QT, class_name, Context, Policy);
495 } else if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC)) {
496 // This is a namespace member.
497 raw_string_ostream stream(class_name);
498 ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/true);
499 stream.flush();
500 }
501 //
502 // Check to make sure that we can
503 // instantiate and codegen this function.
504 //
505 bool needInstantiation = false;
506 const FunctionDecl *Definition = nullptr;
507 if (!FD->isDefined(Definition)) {
508 FunctionDecl::TemplatedKind TK = FD->getTemplatedKind();
509 switch (TK) {
510 case FunctionDecl::TK_NonTemplate: {
511 // Ordinary function, not a template specialization.
512 // Note: This might be ok, the body might be defined
513 // in a library, and all we have seen is the
514 // header file.
515 //::Error("TClingCallFunc::make_wrapper",
516 // "Cannot make wrapper for a function which is "
517 // "declared but not defined!");
518 // return 0;
519 } break;
520 case FunctionDecl::TK_FunctionTemplate: {
521 // This decl is actually a function template,
522 // not a function at all.
523 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a function template!");
524 return 0;
525 } break;
526 case FunctionDecl::TK_MemberSpecialization: {
527 // This function is the result of instantiating an ordinary
528 // member function of a class template, or of instantiating
529 // an ordinary member function of a class member of a class
530 // template, or of specializing a member function template
531 // of a class template, or of specializing a member function
532 // template of a class member of a class template.
533 if (!FD->isTemplateInstantiation()) {
534 // We are either TSK_Undeclared or
535 // TSK_ExplicitSpecialization.
536 // Note: This might be ok, the body might be defined
537 // in a library, and all we have seen is the
538 // header file.
539 //::Error("TClingCallFunc::make_wrapper",
540 // "Cannot make wrapper for a function template "
541 // "explicit specialization which is declared "
542 // "but not defined!");
543 // return 0;
544 break;
545 }
546 const FunctionDecl *Pattern = FD->getTemplateInstantiationPattern();
547 if (!Pattern) {
548 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a member function "
549 "instantiation with no pattern!");
550 return 0;
551 }
552 FunctionDecl::TemplatedKind PTK = Pattern->getTemplatedKind();
553 TemplateSpecializationKind PTSK = Pattern->getTemplateSpecializationKind();
554 if (
555 // The pattern is an ordinary member function.
556 (PTK == FunctionDecl::TK_NonTemplate) ||
557 // The pattern is an explicit specialization, and
558 // so is not a template.
559 ((PTK != FunctionDecl::TK_FunctionTemplate) &&
560 ((PTSK == TSK_Undeclared) || (PTSK == TSK_ExplicitSpecialization)))) {
561 // Note: This might be ok, the body might be defined
562 // in a library, and all we have seen is the
563 // header file.
564 break;
565 } else if (!Pattern->hasBody()) {
566 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a member function "
567 "instantiation with no body!");
568 return 0;
569 }
570 if (FD->isImplicitlyInstantiable()) {
571 needInstantiation = true;
572 }
573 } break;
574 case FunctionDecl::TK_FunctionTemplateSpecialization: {
575 // This function is the result of instantiating a function
576 // template or possibly an explicit specialization of a
577 // function template. Could be a namespace scope function or a
578 // member function.
579 if (!FD->isTemplateInstantiation()) {
580 // We are either TSK_Undeclared or
581 // TSK_ExplicitSpecialization.
582 // Note: This might be ok, the body might be defined
583 // in a library, and all we have seen is the
584 // header file.
585 //::Error("TClingCallFunc::make_wrapper",
586 // "Cannot make wrapper for a function template "
587 // "explicit specialization which is declared "
588 // "but not defined!");
589 // return 0;
590 break;
591 }
592 const FunctionDecl *Pattern = FD->getTemplateInstantiationPattern();
593 if (!Pattern) {
594 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a function template"
595 "instantiation with no pattern!");
596 return 0;
597 }
598 FunctionDecl::TemplatedKind PTK = Pattern->getTemplatedKind();
599 TemplateSpecializationKind PTSK = Pattern->getTemplateSpecializationKind();
600 if (
601 // The pattern is an ordinary member function.
602 (PTK == FunctionDecl::TK_NonTemplate) ||
603 // The pattern is an explicit specialization, and
604 // so is not a template.
605 ((PTK != FunctionDecl::TK_FunctionTemplate) &&
606 ((PTSK == TSK_Undeclared) || (PTSK == TSK_ExplicitSpecialization)))) {
607 // Note: This might be ok, the body might be defined
608 // in a library, and all we have seen is the
609 // header file.
610 break;
611 }
612 if (!Pattern->hasBody()) {
613 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a function template"
614 "instantiation with no body!");
615 return 0;
616 }
617 if (FD->isImplicitlyInstantiable()) {
618 needInstantiation = true;
619 }
620 } break;
621 case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
622 // This function is the result of instantiating or
623 // specializing a member function of a class template,
624 // or a member function of a class member of a class template,
625 // or a member function template of a class template, or a
626 // member function template of a class member of a class
627 // template where at least some part of the function is
628 // dependent on a template argument.
629 if (!FD->isTemplateInstantiation()) {
630 // We are either TSK_Undeclared or
631 // TSK_ExplicitSpecialization.
632 // Note: This might be ok, the body might be defined
633 // in a library, and all we have seen is the
634 // header file.
635 //::Error("TClingCallFunc::make_wrapper",
636 // "Cannot make wrapper for a dependent function "
637 // "template explicit specialization which is declared "
638 // "but not defined!");
639 // return 0;
640 break;
641 }
642 const FunctionDecl *Pattern = FD->getTemplateInstantiationPattern();
643 if (!Pattern) {
644 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a dependent function template"
645 "instantiation with no pattern!");
646 return 0;
647 }
648 FunctionDecl::TemplatedKind PTK = Pattern->getTemplatedKind();
649 TemplateSpecializationKind PTSK = Pattern->getTemplateSpecializationKind();
650 if (
651 // The pattern is an ordinary member function.
652 (PTK == FunctionDecl::TK_NonTemplate) ||
653 // The pattern is an explicit specialization, and
654 // so is not a template.
655 ((PTK != FunctionDecl::TK_FunctionTemplate) &&
656 ((PTSK == TSK_Undeclared) || (PTSK == TSK_ExplicitSpecialization)))) {
657 // Note: This might be ok, the body might be defined
658 // in a library, and all we have seen is the
659 // header file.
660 break;
661 }
662 if (!Pattern->hasBody()) {
663 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a dependent function template"
664 "instantiation with no body!");
665 return 0;
666 }
667 if (FD->isImplicitlyInstantiable()) {
668 needInstantiation = true;
669 }
670 } break;
671 default: {
672 // Will only happen if clang implementation changes.
673 // Protect ourselves in case that happens.
674 ::Error("TClingCallFunc::make_wrapper", "Unhandled template kind!");
675 return 0;
676 } break;
677 }
678 // We do not set needInstantiation to true in these cases:
679 //
680 // isInvalidDecl()
681 // TSK_Undeclared
682 // TSK_ExplicitInstantiationDefinition
683 // TSK_ExplicitSpecialization && !getClassScopeSpecializationPattern()
684 // TSK_ExplicitInstantiationDeclaration &&
685 // getTemplateInstantiationPattern() &&
686 // PatternDecl->hasBody() &&
687 // !PatternDecl->isInlined()
688 //
689 // Set it true in these cases:
690 //
691 // TSK_ImplicitInstantiation
692 // TSK_ExplicitInstantiationDeclaration && (!getPatternDecl() ||
693 // !PatternDecl->hasBody() || PatternDecl->isInlined())
694 //
695 }
696 if (needInstantiation) {
697 clang::FunctionDecl *FDmod = const_cast<clang::FunctionDecl *>(FD);
698 clang::Sema &S = fInterp->getSema();
699 // Could trigger deserialization of decls.
700 cling::Interpreter::PushTransactionRAII RAII(fInterp);
701 S.InstantiateFunctionDefinition(SourceLocation(), FDmod,
702 /*Recursive=*/true,
703 /*DefinitionRequired=*/true);
704 if (!FD->isDefined(Definition)) {
705 ::Error("TClingCallFunc::make_wrapper", "Failed to force template instantiation!");
706 return 0;
707 }
708 }
709 if (Definition) {
710 FunctionDecl::TemplatedKind TK = Definition->getTemplatedKind();
711 switch (TK) {
712 case FunctionDecl::TK_NonTemplate: {
713 // Ordinary function, not a template specialization.
714 if (Definition->isDeleted()) {
715 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a deleted function!");
716 return 0;
717 } else if (Definition->isLateTemplateParsed()) {
718 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a late template parsed "
719 "function!");
720 return 0;
721 }
722 // else if (Definition->isDefaulted()) {
723 // // Might not have a body, but we can still use it.
724 //}
725 // else {
726 // // Has a body.
727 //}
728 } break;
729 case FunctionDecl::TK_FunctionTemplate: {
730 // This decl is actually a function template,
731 // not a function at all.
732 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a function template!");
733 return 0;
734 } break;
735 case FunctionDecl::TK_MemberSpecialization: {
736 // This function is the result of instantiating an ordinary
737 // member function of a class template or of a member class
738 // of a class template.
739 if (Definition->isDeleted()) {
740 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a deleted member function "
741 "of a specialization!");
742 return 0;
743 } else if (Definition->isLateTemplateParsed()) {
744 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a late template parsed "
745 "member function of a specialization!");
746 return 0;
747 }
748 // else if (Definition->isDefaulted()) {
749 // // Might not have a body, but we can still use it.
750 //}
751 // else {
752 // // Has a body.
753 //}
754 } break;
755 case FunctionDecl::TK_FunctionTemplateSpecialization: {
756 // This function is the result of instantiating a function
757 // template or possibly an explicit specialization of a
758 // function template. Could be a namespace scope function or a
759 // member function.
760 if (Definition->isDeleted()) {
761 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a deleted function "
762 "template specialization!");
763 return 0;
764 } else if (Definition->isLateTemplateParsed()) {
765 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a late template parsed "
766 "function template specialization!");
767 return 0;
768 }
769 // else if (Definition->isDefaulted()) {
770 // // Might not have a body, but we can still use it.
771 //}
772 // else {
773 // // Has a body.
774 //}
775 } break;
776 case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
777 // This function is the result of instantiating or
778 // specializing a member function of a class template,
779 // or a member function of a class member of a class template,
780 // or a member function template of a class template, or a
781 // member function template of a class member of a class
782 // template where at least some part of the function is
783 // dependent on a template argument.
784 if (Definition->isDeleted()) {
785 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a deleted dependent function "
786 "template specialization!");
787 return 0;
788 } else if (Definition->isLateTemplateParsed()) {
789 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a late template parsed "
790 "dependent function template specialization!");
791 return 0;
792 }
793 // else if (Definition->isDefaulted()) {
794 // // Might not have a body, but we can still use it.
795 //}
796 // else {
797 // // Has a body.
798 //}
799 } break;
800 default: {
801 // Will only happen if clang implementation changes.
802 // Protect ourselves in case that happens.
803 ::Error("TClingCallFunc::make_wrapper", "Unhandled template kind!");
804 return 0;
805 } break;
806 }
807 }
808 unsigned min_args = GetMinRequiredArguments();
809 unsigned num_params = FD->getNumParams();
810 //
811 // Make the wrapper name.
812 //
813 {
814 ostringstream buf;
815 buf << "__cf";
816 // const NamedDecl* ND = dyn_cast<NamedDecl>(FD);
817 // string mn;
818 // fInterp->maybeMangleDeclName(ND, mn);
819 // buf << '_' << mn;
820 buf << '_' << gWrapperSerial++;
821 wrapper_name = buf.str();
822 }
823 //
824 // Write the wrapper code.
825 // FIXME: this should be synthesized into the AST!
826 //
827 int indent_level = 0;
828 ostringstream buf;
829 buf << "#pragma clang diagnostic push\n"
830 "#pragma clang diagnostic ignored \"-Wformat-security\"\n"
831 "__attribute__((used)) "
832 "__attribute__((annotate(\"__cling__ptrcheck(off)\")))\n"
833 "extern \"C\" void ";
834 buf << wrapper_name;
835 buf << "(void* obj, int nargs, void** args, void* ret)\n"
836 "{\n";
837 ++indent_level;
838 if (min_args == num_params) {
839 // No parameters with defaults.
840 make_narg_call_with_return(num_params, class_name, buf, indent_level);
841 } else {
842 // We need one function call clause compiled for every
843 // possible number of arguments per call.
844 for (unsigned N = min_args; N <= num_params; ++N) {
845 for (int i = 0; i < indent_level; ++i) {
846 buf << kIndentString;
847 }
848 buf << "if (nargs == " << N << ") {\n";
849 ++indent_level;
850 make_narg_call_with_return(N, class_name, buf, indent_level);
851 --indent_level;
852 for (int i = 0; i < indent_level; ++i) {
853 buf << kIndentString;
854 }
855 buf << "}\n";
856 }
857 }
858 --indent_level;
859 buf << "}\n"
860 "#pragma clang diagnostic pop";
861 wrapper = buf.str();
862 return 1;
863}
864
865void TClingCallFunc::make_narg_call_with_return(const unsigned N, const string &class_name,
866 ostringstream &buf, int indent_level)
867{
868 // Make a code string that follows this pattern:
869 //
870 // if (ret) {
871 // new (ret) (return_type) ((class_name*)obj)->func(args...);
872 // }
873 // else {
874 // (void)(((class_name*)obj)->func(args...));
875 // }
876 //
877 const FunctionDecl *FD = GetDecl();
878 if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
879 if (N <= 1 && llvm::isa<UsingShadowDecl>(GetFunctionOrShadowDecl())) {
880 auto SpecMemKind = fInterp->getSema().getSpecialMember(CD);
881 if ((N == 0 && SpecMemKind == clang::Sema::CXXDefaultConstructor) ||
882 (N == 1 &&
883 (SpecMemKind == clang::Sema::CXXCopyConstructor || SpecMemKind == clang::Sema::CXXMoveConstructor))) {
884 // Using declarations cannot inject special members; do not call them
885 // as such. This might happen by using `Base(Base&, int = 12)`, which
886 // is fine to be called as `Derived d(someBase, 42)` but not as
887 // copy constructor of `Derived`.
888 return;
889 }
890 }
891 make_narg_ctor_with_return(N, class_name, buf, indent_level);
892 return;
893 }
894 QualType QT = FD->getReturnType().getCanonicalType();
895 if (QT->isVoidType()) {
896 ostringstream typedefbuf;
897 ostringstream callbuf;
898 for (int i = 0; i < indent_level; ++i) {
899 callbuf << kIndentString;
900 }
901 make_narg_call("void", N, typedefbuf, callbuf, class_name, indent_level);
902 callbuf << ";\n";
903 for (int i = 0; i < indent_level; ++i) {
904 callbuf << kIndentString;
905 }
906 callbuf << "return;\n";
907 buf << typedefbuf.str() << callbuf.str();
908 } else {
909 for (int i = 0; i < indent_level; ++i) {
910 buf << kIndentString;
911 }
912
913 string type_name;
915 bool isPointer = false;
916
917 buf << "if (ret) {\n";
918 ++indent_level;
919 {
920 ostringstream typedefbuf;
921 ostringstream callbuf;
922 //
923 // Write the placement part of the placement new.
924 //
925 for (int i = 0; i < indent_level; ++i) {
926 callbuf << kIndentString;
927 }
928 callbuf << "new (ret) ";
929 collect_type_info(QT, typedefbuf, callbuf, type_name,
930 refType, isPointer, indent_level, false);
931 //
932 // Write the type part of the placement new.
933 //
934 callbuf << "(" << type_name.c_str();
935 if (refType != kNotReference) {
936 callbuf << "*) (&";
937 type_name += "&";
938 } else if (isPointer) {
939 callbuf << "*) (";
940 type_name += "*";
941 } else {
942 callbuf << ") (";
943 }
944 //
945 // Write the actual function call.
946 //
947 make_narg_call(type_name, N, typedefbuf, callbuf, class_name, indent_level);
948 //
949 // End the placement new.
950 //
951 callbuf << ");\n";
952 for (int i = 0; i < indent_level; ++i) {
953 callbuf << kIndentString;
954 }
955 callbuf << "return;\n";
956 //
957 // Output the whole placement new expression and return statement.
958 //
959 buf << typedefbuf.str() << callbuf.str();
960 }
961 --indent_level;
962 for (int i = 0; i < indent_level; ++i) {
963 buf << kIndentString;
964 }
965 buf << "}\n";
966 for (int i = 0; i < indent_level; ++i) {
967 buf << kIndentString;
968 }
969 buf << "else {\n";
970 ++indent_level;
971 {
972 ostringstream typedefbuf;
973 ostringstream callbuf;
974 for (int i = 0; i < indent_level; ++i) {
975 callbuf << kIndentString;
976 }
977 callbuf << "(void)(";
978 make_narg_call(type_name, N, typedefbuf, callbuf, class_name, indent_level);
979 callbuf << ");\n";
980 for (int i = 0; i < indent_level; ++i) {
981 callbuf << kIndentString;
982 }
983 callbuf << "return;\n";
984 buf << typedefbuf.str() << callbuf.str();
985 }
986 --indent_level;
987 for (int i = 0; i < indent_level; ++i) {
988 buf << kIndentString;
989 }
990 buf << "}\n";
991 }
992}
993
995{
997
998 const Decl *D = GetFunctionOrShadowDecl();
999 string wrapper_name;
1000 string wrapper;
1001
1002 if (get_wrapper_code(wrapper_name, wrapper) == 0) return nullptr;
1003
1004 //fprintf(stderr, "%s\n", wrapper.c_str());
1005 //
1006 // Compile the wrapper code.
1007 //
1008 void *F = compile_wrapper(wrapper_name, wrapper);
1009 if (F) {
1010 gWrapperStore.insert(make_pair(D, F));
1011 } else {
1012 ::Error("TClingCallFunc::make_wrapper",
1013 "Failed to compile\n ==== SOURCE BEGIN ====\n%s\n ==== SOURCE END ====",
1014 wrapper.c_str());
1015 }
1017}
1018
1020 ROOT::TMetaUtils::EIOCtorCategory kind, const std::string &type_name)
1021{
1022 // Make a code string that follows this pattern:
1023 //
1024 // void
1025 // unique_wrapper_ddd(void** ret, void* arena, unsigned long nary)
1026 // {
1027 // if (!arena) {
1028 // if (!nary) {
1029 // *ret = new ClassName;
1030 // }
1031 // else {
1032 // *ret = new ClassName[nary];
1033 // }
1034 // }
1035 // else {
1036 // if (!nary) {
1037 // *ret = new (arena) ClassName;
1038 // }
1039 // else {
1040 // *ret = new (arena) ClassName[nary];
1041 // }
1042 // }
1043 // }
1044 //
1045 // When I/O constructor used:
1046 //
1047 // void
1048 // unique_wrapper_ddd(void** ret, void* arena, unsigned long nary)
1049 // {
1050 // if (!arena) {
1051 // if (!nary) {
1052 // *ret = new ClassName((TRootIOCtor*)nullptr);
1053 // }
1054 // else {
1055 // char *buf = malloc(nary * sizeof(ClassName));
1056 // for (int k=0;k<nary;++k)
1057 // new (buf + k * sizeof(ClassName)) ClassName((TRootIOCtor*)nullptr);
1058 // *ret = buf;
1059 // }
1060 // }
1061 // else {
1062 // if (!nary) {
1063 // *ret = new (arena) ClassName((TRootIOCtor*)nullptr);
1064 // }
1065 // else {
1066 // for (int k=0;k<nary;++k)
1067 // new ((char *) arena + k * sizeof(ClassName)) ClassName((TRootIOCtor*)nullptr);
1068 // *ret = arena;
1069 // }
1070 // }
1071 // }
1072 //
1073 //
1074 // Note:
1075 //
1076 // If the class is of POD type, the form:
1077 //
1078 // new ClassName;
1079 //
1080 // does not initialize the object at all, and the form:
1081 //
1082 // new ClassName();
1083 //
1084 // default-initializes the object.
1085 //
1086 // We are using the form without parentheses because that is what
1087 // CINT did.
1088 //
1089 //--
1090 ASTContext &Context = info->GetDecl()->getASTContext();
1091 PrintingPolicy Policy(Context.getPrintingPolicy());
1092 Policy.SuppressTagKeyword = true;
1093 Policy.SuppressUnwrittenScope = true;
1094 //
1095 // Get the class or namespace name.
1096 //
1097 string class_name;
1098 if (const TypeDecl *TD = dyn_cast<TypeDecl>(info->GetDecl())) {
1099 // This is a class, struct, or union member.
1100 QualType QT(TD->getTypeForDecl(), 0);
1101 GetTypeAsString(QT, class_name, Context, Policy);
1102 } else if (const NamedDecl *ND = dyn_cast<NamedDecl>(info->GetDecl())) {
1103 // This is a namespace member.
1104 raw_string_ostream stream(class_name);
1105 ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/true);
1106 stream.flush();
1107 }
1108
1109
1110 //
1111 // Make the wrapper name.
1112 //
1113 string wrapper_name;
1114 {
1115 ostringstream buf;
1116 buf << "__ctor";
1117 //const NamedDecl* ND = dyn_cast<NamedDecl>(FD);
1118 //string mn;
1119 //fInterp->maybeMangleDeclName(ND, mn);
1120 //buf << '_dtor_' << mn;
1121 buf << '_' << gWrapperSerial++;
1122 wrapper_name = buf.str();
1123 }
1124
1125 string constr_arg;
1127 constr_arg = string("((") + type_name + "*)nullptr)";
1129 constr_arg = string("(*((") + type_name + "*)arena))";
1130
1131 //
1132 // Write the wrapper code.
1133 //
1134 int indent_level = 0;
1135 ostringstream buf;
1136 buf << "__attribute__((used)) ";
1137 buf << "extern \"C\" void ";
1138 buf << wrapper_name;
1139 buf << "(void** ret, void* arena, unsigned long nary)\n";
1140 buf << "{\n";
1141
1142 // if (!arena) {
1143 // if (!nary) {
1144 // *ret = new ClassName;
1145 // }
1146 // else {
1147 // *ret = new ClassName[nary];
1148 // }
1149 // }
1150 indent(buf, ++indent_level);
1151 buf << "if (!arena) {\n";
1152 indent(buf, ++indent_level);
1153 buf << "if (!nary) {\n";
1154 indent(buf, ++indent_level);
1155 buf << "*ret = new " << class_name << constr_arg << ";\n";
1156 indent(buf, --indent_level);
1157 buf << "}\n";
1158 indent(buf, indent_level);
1159 buf << "else {\n";
1160 indent(buf, ++indent_level);
1161 if (constr_arg.empty()) {
1162 buf << "*ret = new " << class_name << "[nary];\n";
1163 } else {
1164 buf << "char *buf = (char *) malloc(nary * sizeof(" << class_name << "));\n";
1165 indent(buf, indent_level);
1166 buf << "for (int k=0;k<nary;++k)\n";
1167 indent(buf, ++indent_level);
1168 buf << "new (buf + k * sizeof(" << class_name << ")) " << class_name << constr_arg << ";\n";
1169 indent(buf, --indent_level);
1170 buf << "*ret = buf;\n";
1171 }
1172 indent(buf, --indent_level);
1173 buf << "}\n";
1174 indent(buf, --indent_level);
1175 buf << "}\n";
1176 // else {
1177 // if (!nary) {
1178 // *ret = new (arena) ClassName;
1179 // }
1180 // else {
1181 // *ret = new (arena) ClassName[nary];
1182 // }
1183 // }
1184 indent(buf, indent_level);
1185 buf << "else {\n";
1186 indent(buf, ++indent_level);
1187 buf << "if (!nary) {\n";
1188 indent(buf, ++indent_level);
1189 buf << "*ret = new (arena) " << class_name << constr_arg << ";\n";
1190 indent(buf, --indent_level);
1191 buf << "}\n";
1192 indent(buf, indent_level);
1193 buf << "else {\n";
1194 indent(buf, ++indent_level);
1195 if (constr_arg.empty()) {
1196 buf << "*ret = new (arena) " << class_name << "[nary];\n";
1197 } else {
1198 buf << "for (int k=0;k<nary;++k)\n";
1199 indent(buf, ++indent_level);
1200 buf << "new ((char *) arena + k * sizeof(" << class_name << ")) " << class_name << constr_arg << ";\n";
1201 indent(buf, --indent_level);
1202 buf << "*ret = arena;\n";
1203 }
1204 indent(buf, --indent_level);
1205 buf << "}\n";
1206 indent(buf, --indent_level);
1207 buf << "}\n";
1208 // End wrapper.
1209 --indent_level;
1210 buf << "}\n";
1211 // Done.
1212 string wrapper(buf.str());
1213 //fprintf(stderr, "%s\n", wrapper.c_str());
1214 //
1215 // Compile the wrapper code.
1216 //
1217 void *F = compile_wrapper(wrapper_name, wrapper,
1218 /*withAccessControl=*/false);
1219 if (F) {
1220 gCtorWrapperStore.insert(make_pair(info->GetDecl(), F));
1221 } else {
1222 ::Error("TClingCallFunc::make_ctor_wrapper",
1223 "Failed to compile\n ==== SOURCE BEGIN ====\n%s\n ==== SOURCE END ====",
1224 wrapper.c_str());
1225 }
1227}
1228
1231{
1232 // Make a code string that follows this pattern:
1233 //
1234 // void
1235 // unique_wrapper_ddd(void* obj, unsigned long nary, int withFree)
1236 // {
1237 // if (withFree) {
1238 // if (!nary) {
1239 // delete (ClassName*) obj;
1240 // }
1241 // else {
1242 // delete[] (ClassName*) obj;
1243 // }
1244 // }
1245 // else {
1246 // typedef ClassName DtorName;
1247 // if (!nary) {
1248 // ((ClassName*)obj)->~DtorName();
1249 // }
1250 // else {
1251 // for (unsigned long i = nary - 1; i > -1; --i) {
1252 // (((ClassName*)obj)+i)->~DtorName();
1253 // }
1254 // }
1255 // }
1256 // }
1257 //
1258 //--
1259 ASTContext &Context = info->GetDecl()->getASTContext();
1260 PrintingPolicy Policy(Context.getPrintingPolicy());
1261 Policy.SuppressTagKeyword = true;
1262 Policy.SuppressUnwrittenScope = true;
1263 //
1264 // Get the class or namespace name.
1265 //
1266 string class_name;
1267 if (const TypeDecl *TD = dyn_cast<TypeDecl>(info->GetDecl())) {
1268 // This is a class, struct, or union member.
1269 QualType QT(TD->getTypeForDecl(), 0);
1270 GetTypeAsString(QT, class_name, Context, Policy);
1271 } else if (const NamedDecl *ND = dyn_cast<NamedDecl>(info->GetDecl())) {
1272 // This is a namespace member.
1273 raw_string_ostream stream(class_name);
1274 ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/true);
1275 stream.flush();
1276 }
1277 //
1278 // Make the wrapper name.
1279 //
1280 string wrapper_name;
1281 {
1282 ostringstream buf;
1283 buf << "__dtor";
1284 //const NamedDecl* ND = dyn_cast<NamedDecl>(FD);
1285 //string mn;
1286 //fInterp->maybeMangleDeclName(ND, mn);
1287 //buf << '_dtor_' << mn;
1288 buf << '_' << gWrapperSerial++;
1289 wrapper_name = buf.str();
1290 }
1291 //
1292 // Write the wrapper code.
1293 //
1294 int indent_level = 0;
1295 ostringstream buf;
1296 buf << "__attribute__((used)) ";
1297 buf << "extern \"C\" void ";
1298 buf << wrapper_name;
1299 buf << "(void* obj, unsigned long nary, int withFree)\n";
1300 buf << "{\n";
1301 // if (withFree) {
1302 // if (!nary) {
1303 // delete (ClassName*) obj;
1304 // }
1305 // else {
1306 // delete[] (ClassName*) obj;
1307 // }
1308 // }
1309 ++indent_level;
1310 indent(buf, indent_level);
1311 buf << "if (withFree) {\n";
1312 ++indent_level;
1313 indent(buf, indent_level);
1314 buf << "if (!nary) {\n";
1315 ++indent_level;
1316 indent(buf, indent_level);
1317 buf << "delete (" << class_name << "*) obj;\n";
1318 --indent_level;
1319 indent(buf, indent_level);
1320 buf << "}\n";
1321 indent(buf, indent_level);
1322 buf << "else {\n";
1323 ++indent_level;
1324 indent(buf, indent_level);
1325 buf << "delete[] (" << class_name << "*) obj;\n";
1326 --indent_level;
1327 indent(buf, indent_level);
1328 buf << "}\n";
1329 --indent_level;
1330 indent(buf, indent_level);
1331 buf << "}\n";
1332 // else {
1333 // typedef ClassName Nm;
1334 // if (!nary) {
1335 // ((Nm*)obj)->~Nm();
1336 // }
1337 // else {
1338 // for (unsigned long i = nary - 1; i > -1; --i) {
1339 // (((Nm*)obj)+i)->~Nm();
1340 // }
1341 // }
1342 // }
1343 indent(buf, indent_level);
1344 buf << "else {\n";
1345 ++indent_level;
1346 indent(buf, indent_level);
1347 buf << "typedef " << class_name << " Nm;\n";
1348 buf << "if (!nary) {\n";
1349 ++indent_level;
1350 indent(buf, indent_level);
1351 buf << "((Nm*)obj)->~Nm();\n";
1352 --indent_level;
1353 indent(buf, indent_level);
1354 buf << "}\n";
1355 indent(buf, indent_level);
1356 buf << "else {\n";
1357 ++indent_level;
1358 indent(buf, indent_level);
1359 buf << "do {\n";
1360 ++indent_level;
1361 indent(buf, indent_level);
1362 buf << "(((Nm*)obj)+(--nary))->~Nm();\n";
1363 --indent_level;
1364 indent(buf, indent_level);
1365 buf << "} while (nary);\n";
1366 --indent_level;
1367 indent(buf, indent_level);
1368 buf << "}\n";
1369 --indent_level;
1370 indent(buf, indent_level);
1371 buf << "}\n";
1372 // End wrapper.
1373 --indent_level;
1374 buf << "}\n";
1375 // Done.
1376 string wrapper(buf.str());
1377 //fprintf(stderr, "%s\n", wrapper.c_str());
1378 //
1379 // Compile the wrapper code.
1380 //
1381 void *F = compile_wrapper(wrapper_name, wrapper,
1382 /*withAccessControl=*/false);
1383 if (F) {
1384 gDtorWrapperStore.insert(make_pair(info->GetDecl(), F));
1385 } else {
1386 ::Error("TClingCallFunc::make_dtor_wrapper",
1387 "Failed to compile\n ==== SOURCE BEGIN ====\n%s\n ==== SOURCE END ====",
1388 wrapper.c_str());
1389 }
1390
1392}
1393
1394void TClingCallFunc::exec(void *address, void *ret)
1395{
1396 SmallVector<void *, 8> vp_ary;
1397 const unsigned num_args = fArgVals.size();
1398 {
1400 const FunctionDecl *FD = GetDecl();
1401
1402 // FIXME: Consider the implicit this which is sometimes not passed.
1403 if (num_args < GetMinRequiredArguments()) {
1404 ::Error("TClingCallFunc::exec",
1405 "Not enough arguments provided for %s (%d instead of the minimum %d)",
1406 fMethod->Name(),
1407 num_args, (int)GetMinRequiredArguments());
1408 return;
1409 } else if (!isa<CXXMethodDecl>(FD) && num_args > FD->getNumParams()) {
1410 ::Error("TClingCallFunc::exec",
1411 "Too many arguments provided for %s (%d instead of the minimum %d)",
1412 fMethod->Name(),
1413 num_args, (int)GetMinRequiredArguments());
1414 return;
1415 }
1416 if (auto CXXMD = dyn_cast<CXXMethodDecl>(FD))
1417 if (!address && CXXMD && !CXXMD->isStatic() && !isa<CXXConstructorDecl>(FD)) {
1418 ::Error("TClingCallFunc::exec",
1419 "The method %s is called without an object.",
1420 fMethod->Name());
1421 return;
1422 }
1423
1424
1425 //
1426 // Convert the arguments from cling::Value to their
1427 // actual type and store them in a holder for passing to the
1428 // wrapper function by pointer to value.
1429 //
1430 vp_ary.reserve(num_args);
1431 for (unsigned i = 0; i < num_args; ++i) {
1432 QualType QT;
1433 // Check if we provided a this parameter.
1434 // FIXME: Currently we do not provide consistently the this pointer at
1435 // index 0 of the call arguments passed to the wrapper.
1436 // In C++ we can still call member functions which do not use it. Eg:
1437 // struct S {int Print() { return printf("a");} }; auto r1 = ((S*)0)->Print();
1438 // This works just fine even though it might be UB...
1439 bool implicitThisPassed = i == 0 && isa<CXXMethodDecl>(FD) && num_args - FD->getNumParams() == 1;
1440 if (implicitThisPassed)
1441 QT = cast<CXXMethodDecl>(FD)->getThisType();
1442 else
1443 QT = FD->getParamDecl(i)->getType();
1444 QT = QT.getCanonicalType();
1445 if (QT->isReferenceType() || QT->isRecordType()) {
1446 // the argument is already a pointer value (points to the same thing
1447 // as the reference or pointing to object passed by value.
1448 vp_ary.push_back(fArgVals[i].getPtr());
1449 } else
1450 vp_ary.push_back(fArgVals[i].getPtrAddress());
1451 }
1452 } // End of scope holding the lock
1453 (*fWrapper)(address, (int)num_args, (void **)vp_ary.data(), ret);
1454}
1455
1456void TClingCallFunc::exec_with_valref_return(void *address, cling::Value &ret)
1457{
1458 const FunctionDecl *FD = GetDecl();
1459
1460 QualType QT;
1461 if (llvm::isa<CXXConstructorDecl>(FD)) {
1463 ASTContext &Context = FD->getASTContext();
1464 const TypeDecl *TD = dyn_cast<TypeDecl>(GetDeclContext());
1465 QualType ClassTy(TD->getTypeForDecl(), 0);
1466 QT = Context.getLValueReferenceType(ClassTy);
1467 ret = cling::Value(QT, *fInterp);
1468 } else {
1469 QT = FD->getReturnType().getCanonicalType();
1470 ret = cling::Value(QT, *fInterp);
1471
1472 if (QT->isRecordType() || QT->isMemberDataPointerType())
1473 return exec(address, ret.getPtr());
1474 }
1475 exec(address, ret.getPtrAddress());
1476}
1477
1478void TClingCallFunc::EvaluateArgList(const string &ArgList)
1479{
1481
1482 SmallVector<Expr *, 4> exprs;
1483 fInterp->getLookupHelper().findArgList(ArgList, exprs,
1484 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
1485 : cling::LookupHelper::NoDiagnostics);
1486 for (SmallVectorImpl<Expr *>::const_iterator I = exprs.begin(),
1487 E = exprs.end(); I != E; ++I) {
1488 cling::Value val;
1489 EvaluateExpr(*fInterp, *I, val);
1490 if (!val.isValid()) {
1491 // Bad expression, all done.
1492 ::Error("TClingCallFunc::EvaluateArgList",
1493 "Bad expression in parameter %d of '%s'!",
1494 (int)(I - exprs.begin()),
1495 ArgList.c_str());
1496 return;
1497 }
1498 fArgVals.push_back(val);
1499 }
1500}
1501
1502void TClingCallFunc::Exec(void *address, TInterpreterValue *interpVal/*=0*/)
1503{
1504 IFacePtr();
1505 if (!fWrapper) {
1506 ::Error("TClingCallFunc::Exec(address, interpVal)",
1507 "Called with no wrapper, not implemented!");
1508 return;
1509 }
1510 if (!interpVal || !interpVal->GetValAddr()) {
1511 exec(address, nullptr);
1512 return;
1513 }
1514 cling::Value *val = reinterpret_cast<cling::Value *>(interpVal->GetValAddr());
1515 exec_with_valref_return(address, *val);
1516}
1517
1518template <typename T>
1520{
1521 IFacePtr();
1522 if (!fWrapper) {
1523 ::Error("TClingCallFunc::ExecT",
1524 "Called with no wrapper, not implemented!");
1525 return 0;
1526 }
1527 cling::Value ret;
1528 exec_with_valref_return(address, ret);
1529 if (ret.isVoid()) {
1530 return 0;
1531 }
1532
1533 if (ret.needsManagedAllocation())
1534 ((TCling *)gCling)->RegisterTemporary(ret);
1535
1536 return ret.castAs<T>();
1537}
1538
1540{
1541 return ExecT<Longptr_t>(address);
1542}
1543
1544long long TClingCallFunc::ExecInt64(void *address)
1545{
1546 return ExecT<long long>(address);
1547}
1548
1549double TClingCallFunc::ExecDouble(void *address)
1550{
1551 return ExecT<double>(address);
1552}
1553
1554void TClingCallFunc::ExecWithArgsAndReturn(void *address, const void *args[] /*= 0*/,
1555 int nargs /*= 0*/, void *ret/*= 0*/)
1556{
1557 IFacePtr();
1558 if (!fWrapper) {
1559 ::Error("TClingCallFunc::ExecWithArgsAndReturn(address, args, ret)",
1560 "Called with no wrapper, not implemented!");
1561 return;
1562 }
1563 (*fWrapper)(address, nargs, const_cast<void **>(args), ret);
1564}
1565
1566void TClingCallFunc::ExecWithReturn(void *address, void *ret/*= 0*/)
1567{
1568 IFacePtr();
1569 if (!fWrapper) {
1570 ::Error("TClingCallFunc::ExecWithReturn(address, ret)",
1571 "Called with no wrapper, not implemented!");
1572 return;
1573 }
1574 exec(address, ret);
1575}
1576
1579 const std::string &type_name,
1580 void *address /*=0*/, unsigned long nary /*= 0UL*/)
1581{
1582 if (!info->IsValid()) {
1583 ::Error("TClingCallFunc::ExecDefaultConstructor", "Invalid class info!");
1584 return nullptr;
1585 }
1586 tcling_callfunc_ctor_Wrapper_t wrapper = nullptr;
1587 {
1589 auto D = info->GetDecl();
1590 //if (!info->HasDefaultConstructor()) {
1591 // // FIXME: We might have a ROOT ioctor, we might
1592 // // have to check for that here.
1593 // ::Error("TClingCallFunc::ExecDefaultConstructor",
1594 // "Class has no default constructor: %s",
1595 // info->Name());
1596 // return 0;
1597 //}
1598 auto I = gCtorWrapperStore.find(D);
1599 if (I != gCtorWrapperStore.end()) {
1600 wrapper = (tcling_callfunc_ctor_Wrapper_t) I->second;
1601 } else {
1602 wrapper = make_ctor_wrapper(info, kind, type_name);
1603 }
1604 }
1605 if (!wrapper) {
1606 ::Error("TClingCallFunc::ExecDefaultConstructor",
1607 "Called with no wrapper, not implemented!");
1608 return nullptr;
1609 }
1610 void *obj = nullptr;
1611 (*wrapper)(&obj, address, nary);
1612 return obj;
1613}
1614
1615void TClingCallFunc::ExecDestructor(const TClingClassInfo *info, void *address /*=0*/,
1616 unsigned long nary /*= 0UL*/, bool withFree /*= true*/)
1617{
1618 if (!info->IsValid()) {
1619 ::Error("TClingCallFunc::ExecDestructor", "Invalid class info!");
1620 return;
1621 }
1622
1623 tcling_callfunc_dtor_Wrapper_t wrapper = nullptr;
1624 {
1626 const Decl *D = info->GetDecl();
1627 map<const Decl *, void *>::iterator I = gDtorWrapperStore.find(D);
1628 if (I != gDtorWrapperStore.end()) {
1629 wrapper = (tcling_callfunc_dtor_Wrapper_t) I->second;
1630 } else {
1631 wrapper = make_dtor_wrapper(info);
1632 }
1633 }
1634 if (!wrapper) {
1635 ::Error("TClingCallFunc::ExecDestructor",
1636 "Called with no wrapper, not implemented!");
1637 return;
1638 }
1639 (*wrapper)(address, nary, withFree);
1640}
1641
1644{
1645 return new TClingMethodInfo(*fMethod);
1646}
1647
1649{
1650 fMethod.reset();
1651 fWrapper = nullptr;
1652 fDecl = nullptr;
1654 ResetArg();
1655}
1656
1658{
1659 Init();
1660 fMethod = std::unique_ptr<TClingMethodInfo>(new TClingMethodInfo(minfo));
1661}
1662
1663void TClingCallFunc::Init(std::unique_ptr<TClingMethodInfo> minfo)
1664{
1665 Init();
1666 fMethod = std::move(minfo);
1667}
1668
1670{
1671 if (!IsValid()) {
1672 return nullptr;
1673 }
1674 if (!fWrapper) {
1675 const Decl *decl = GetFunctionOrShadowDecl();
1676
1678 // check if another thread already did it
1679 if (!fWrapper) {
1680 map<const Decl *, void *>::iterator I = gWrapperStore.find(decl);
1681 if (I != gWrapperStore.end()) {
1683 } else {
1685 }
1686 }
1687 }
1688 return (void *)fWrapper.load();
1689}
1690
1692{
1693 if (!fMethod) {
1694 return false;
1695 }
1696 return fMethod->IsValid();
1697}
1698
1700{
1701 if (!IsValid()) {
1702 ::Error("TClingCallFunc::IFacePtr(kind)",
1703 "Attempt to get interface while invalid.");
1705 }
1706 if (!fWrapper) {
1707 const Decl *decl = GetFunctionOrShadowDecl();
1708
1710 // check if another thread already did it
1711 if (!fWrapper) {
1712 map<const Decl *, void *>::iterator I = gWrapperStore.find(decl);
1713 if (I != gWrapperStore.end()) {
1715 } else {
1717 }
1718 }
1719 }
1721}
1722
1723
1725{
1726 fArgVals.clear();
1727}
1728
1729void TClingCallFunc::SetArgArray(Longptr_t *paramArr, int nparam)
1730{
1731 ResetArg();
1732 for (int i = 0; i < nparam; ++i) {
1733 SetArg(paramArr[i]);
1734 }
1735}
1736
1737void TClingCallFunc::SetArgs(const char *params)
1738{
1739 ResetArg();
1740 EvaluateArgList(params);
1741}
1742
1743void TClingCallFunc::SetFunc(const TClingClassInfo *info, const char *method, const char *arglist,
1744 Longptr_t *poffset)
1745{
1746 SetFunc(info, method, arglist, false, poffset);
1747}
1748
1749void TClingCallFunc::SetFunc(const TClingClassInfo *info, const char *method, const char *arglist,
1750 bool objectIsConst, Longptr_t *poffset)
1751{
1752 Init(std::unique_ptr<TClingMethodInfo>(new TClingMethodInfo(fInterp)));
1753 if (poffset) {
1754 *poffset = 0L;
1755 }
1756 ResetArg();
1757 if (!info->IsValid()) {
1758 ::Error("TClingCallFunc::SetFunc", "Class info is invalid!");
1759 return;
1760 }
1761 if (!strcmp(arglist, ")")) {
1762 // CINT accepted a single right paren as meaning no arguments.
1763 arglist = "";
1764 }
1765 *fMethod = info->GetMethodWithArgs(method, arglist, objectIsConst, poffset);
1766 if (!fMethod->IsValid()) {
1767 //::Error("TClingCallFunc::SetFunc", "Could not find method %s(%s)", method,
1768 // arglist);
1769 return;
1770 }
1771 // FIXME: The arglist was already parsed by the lookup, we should
1772 // enhance the lookup to return the resulting expression
1773 // list so we do not need to parse it again here.
1774 EvaluateArgList(arglist);
1775}
1776
1778{
1779 Init(std::unique_ptr<TClingMethodInfo>(new TClingMethodInfo(*info)));
1780 ResetArg();
1781 if (!fMethod->IsValid()) {
1782 return;
1783 }
1784}
1785
1786void TClingCallFunc::SetFuncProto(const TClingClassInfo *info, const char *method,
1787 const char *proto, Longptr_t *poffset,
1788 EFunctionMatchMode mode/*=kConversionMatch*/)
1789{
1790 SetFuncProto(info, method, proto, false, poffset, mode);
1791}
1792
1793void TClingCallFunc::SetFuncProto(const TClingClassInfo *info, const char *method,
1794 const char *proto, bool objectIsConst, Longptr_t *poffset,
1795 EFunctionMatchMode mode/*=kConversionMatch*/)
1796{
1797 Init(std::unique_ptr<TClingMethodInfo>(new TClingMethodInfo(fInterp)));
1798 if (poffset) {
1799 *poffset = 0L;
1800 }
1801 ResetArg();
1802 if (!info->IsValid()) {
1803 ::Error("TClingCallFunc::SetFuncProto", "Class info is invalid!");
1804 return;
1805 }
1806 *fMethod = info->GetMethod(method, proto, objectIsConst, poffset, mode);
1807 if (!fMethod->IsValid()) {
1808 //::Error("TClingCallFunc::SetFuncProto", "Could not find method %s(%s)",
1809 // method, proto);
1810 return;
1811 }
1812}
1813
1814void TClingCallFunc::SetFuncProto(const TClingClassInfo *info, const char *method,
1815 const llvm::SmallVectorImpl<clang::QualType> &proto, Longptr_t *poffset,
1816 EFunctionMatchMode mode/*=kConversionMatch*/)
1817{
1818 SetFuncProto(info, method, proto, false, poffset, mode);
1819}
1820
1821void TClingCallFunc::SetFuncProto(const TClingClassInfo *info, const char *method,
1822 const llvm::SmallVectorImpl<clang::QualType> &proto,
1823 bool objectIsConst, Longptr_t *poffset,
1824 EFunctionMatchMode mode/*=kConversionMatch*/)
1825{
1826 Init(std::unique_ptr<TClingMethodInfo>(new TClingMethodInfo(fInterp)));
1827 if (poffset) {
1828 *poffset = 0L;
1829 }
1830 ResetArg();
1831 if (!info->IsValid()) {
1832 ::Error("TClingCallFunc::SetFuncProto", "Class info is invalid!");
1833 return;
1834 }
1835 *fMethod = info->GetMethod(method, proto, objectIsConst, poffset, mode);
1836 if (!fMethod->IsValid()) {
1837 //::Error("TClingCallFunc::SetFuncProto", "Could not find method %s(%s)",
1838 // method, proto);
1839 return;
1840 }
1841}
1842
long Longptr_t
Definition RtypesCore.h:82
static void EvaluateExpr(cling::Interpreter &interp, const Expr *E, cling::Value &V)
static void GetTypeAsString(QualType QT, string &type_name, ASTContext &C, PrintingPolicy Policy)
static unsigned long long gWrapperSerial
static map< const Decl *, void * > gCtorWrapperStore
static const string kIndentString(" ")
static void indent(ostringstream &buf, int indent_level)
static map< const Decl *, void * > gDtorWrapperStore
static map< const Decl *, void * > gWrapperStore
void(* tcling_callfunc_ctor_Wrapper_t)(void **, void *, unsigned long)
void(* tcling_callfunc_Wrapper_t)(void *, int, void **, void *)
void(* tcling_callfunc_dtor_Wrapper_t)(void *, unsigned long, int)
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:185
#define N
Option_t Option_t TPoint TPoint const char mode
char name[80]
Definition TGX11.cxx:110
R__EXTERN TVirtualMutex * gInterpreterMutex
#define R__LOCKGUARD_CLING(mutex)
R__EXTERN TInterpreter * gCling
Int_t gDebug
Definition TROOT.cxx:595
const char * proto
Definition civetweb.c:17536
void * ExecDefaultConstructor(const TClingClassInfo *info, ROOT::TMetaUtils::EIOCtorCategory kind, const std::string &type_name, void *address=nullptr, unsigned long nary=0UL)
void ExecWithReturn(void *address, void *ret=nullptr)
void exec_with_valref_return(void *address, cling::Value &ret)
std::unique_ptr< TClingMethodInfo > fMethod
Current method, we own.
void collect_type_info(clang::QualType &QT, std::ostringstream &typedefbuf, std::ostringstream &callbuf, std::string &type_name, EReferenceType &refType, bool &isPointer, int indent_level, bool forArgument)
void SetArgs(const char *args)
size_t fMinRequiredArguments
Number of required arguments.
T ExecT(void *address)
size_t CalculateMinRequiredArguments()
double ExecDouble(void *address)
void SetArgArray(Longptr_t *argArr, int narg)
tcling_callfunc_Wrapper_t make_wrapper()
bool IsValid() const
tcling_callfunc_dtor_Wrapper_t make_dtor_wrapper(const TClingClassInfo *info)
void ExecDestructor(const TClingClassInfo *info, void *address=nullptr, unsigned long nary=0UL, bool withFree=true)
Longptr_t ExecInt(void *address)
const clang::DeclContext * GetDeclContext() const
void * compile_wrapper(const std::string &wrapper_name, const std::string &wrapper, bool withAccessControl=true)
void SetFuncProto(const TClingClassInfo *info, const char *method, const char *proto, Longptr_t *poffset, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch)
TInterpreter::CallFuncIFacePtr_t IFacePtr()
void exec(void *address, void *ret)
std::atomic< tcling_callfunc_Wrapper_t > fWrapper
Pointer to compiled wrapper, we do not own.
void make_narg_ctor(const unsigned N, std::ostringstream &typedefbuf, std::ostringstream &callbuf, const std::string &class_name, int indent_level)
void SetFunc(const TClingClassInfo *info, const char *method, const char *arglist, Longptr_t *poffset)
const clang::FunctionDecl * GetDecl()
void EvaluateArgList(const std::string &ArgList)
const clang::Decl * GetFunctionOrShadowDecl() const
void ExecWithArgsAndReturn(void *address, const void *args[]=0, int nargs=0, void *ret=0)
void Exec(void *address, TInterpreterValue *interpVal=0)
TClingMethodInfo * FactoryMethod() const
int get_wrapper_code(std::string &wrapper_name, std::string &wrapper)
size_t GetMinRequiredArguments()
tcling_callfunc_ctor_Wrapper_t make_ctor_wrapper(const TClingClassInfo *, ROOT::TMetaUtils::EIOCtorCategory, const std::string &)
void SetArg(T arg)
long long ExecInt64(void *address)
cling::Interpreter * fInterp
Cling interpreter, we do not own.
void make_narg_call(const std::string &return_type, const unsigned N, std::ostringstream &typedefbuf, std::ostringstream &callbuf, const std::string &class_name, int indent_level)
const clang::FunctionDecl * fDecl
Decl for the method.
void make_narg_call_with_return(const unsigned N, const std::string &class_name, std::ostringstream &buf, int indent_level)
llvm::SmallVector< cling::Value, 8 > fArgVals
Stored function arguments, we own.
void make_narg_ctor_with_return(const unsigned N, const std::string &class_name, std::ostringstream &buf, int indent_level)
Emulation of the CINT ClassInfo class.
TClingMethodInfo GetMethodWithArgs(const char *fname, const char *arglist, Longptr_t *poffset, ROOT::EFunctionMatchMode mode=ROOT::kConversionMatch, EInheritanceMode imode=kWithInheritance) const
TClingMethodInfo GetMethod(const char *fname) const
virtual bool IsValid() const
virtual const clang::Decl * GetDecl() const
Emulation of the CINT MethodInfo class.
This class defines an interface to the cling C++ interpreter.
Definition TCling.h:102
virtual const void * GetValAddr() const =0
#define F(x, y, z)
#define I(x, y, z)
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
EFunctionMatchMode