Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 std::string, std::map, std::ostringstream, std::make_pair;
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
232static bool IsCopyConstructorDeleted(QualType QT)
233{
234 CXXRecordDecl *RD = QT->getAsCXXRecordDecl();
235 if (!RD) {
236 // For types that are not C++ records (such as PODs), we assume that they are copyable, ie their copy constructor
237 // is not deleted.
238 return false;
239 }
240
241 RD = RD->getDefinition();
242 assert(RD && "expecting a definition");
243
244 if (RD->hasSimpleCopyConstructor())
245 return false;
246
247 for (auto *Ctor : RD->ctors()) {
248 if (Ctor->isCopyConstructor()) {
249 return Ctor->isDeleted();
250 }
251 }
252
253 assert(0 && "did not find a copy constructor?");
254 // Should never happen and the return value is somewhat arbitrary, but we did not see a deleted copy ctor. The user
255 // will be told if the generated code doesn't compile.
256 return false;
257}
258
259void TClingCallFunc::make_narg_ctor(const unsigned N, ostringstream &typedefbuf,
260 ostringstream &callbuf, const string &class_name,
261 int indent_level)
262{
263 // Make a code string that follows this pattern:
264 //
265 // new ClassName(args...)
266 //
267 const FunctionDecl *FD = GetDecl();
268
269 callbuf << "new " << class_name << "(";
270
271 // IsCopyConstructorDeleted could trigger deserialization of decls.
272 cling::Interpreter::PushTransactionRAII RAII(fInterp);
273
274 for (unsigned i = 0U; i < N; ++i) {
275 const ParmVarDecl *PVD = FD->getParamDecl(i);
276 QualType Ty = PVD->getType();
277 QualType QT = Ty.getCanonicalType();
278 string type_name;
280 bool isPointer = false;
281 collect_type_info(QT, typedefbuf, callbuf, type_name,
282 refType, isPointer, indent_level, true);
283 if (i) {
284 callbuf << ',';
285 if (i % 2) {
286 callbuf << ' ';
287 } else {
288 callbuf << "\n";
289 for (int j = 0; j <= indent_level; ++j) {
290 callbuf << kIndentString;
291 }
292 }
293 }
294 if (refType != kNotReference) {
295 callbuf << "(" << type_name.c_str() <<
296 (refType == kLValueReference ? "&" : "&&") << ")*(" << type_name.c_str() << "*)args["
297 << i << "]";
298 } else if (isPointer) {
299 callbuf << "*(" << type_name.c_str() << "**)args["
300 << i << "]";
301 } else {
302 // By-value construction: Figure out if the type can be copy-constructed. This is tricky and cannot be done in
303 // a fully reliable way, also because std::vector<T> always defines a copy constructor, even if the type T is
304 // only moveable. As a heuristic, we only check if the copy constructor is deleted, or would be if implicit.
305 bool Move = IsCopyConstructorDeleted(QT);
306 if (Move) {
307 callbuf << "static_cast<" << type_name << "&&>(";
308 }
309 callbuf << "*(" << type_name.c_str() << "*)args[" << i << "]";
310 if (Move) {
311 callbuf << ")";
312 }
313 }
314 }
315 callbuf << ")";
316}
317
318void TClingCallFunc::make_narg_call(const std::string &return_type, const unsigned N, ostringstream &typedefbuf,
319 ostringstream &callbuf, const string &class_name, int indent_level)
320{
321 //
322 // Make a code string that follows this pattern:
323 //
324 // ((<class>*)obj)-><method>(*(<arg-i-type>*)args[i], ...)
325 //
326 const FunctionDecl *FD = GetDecl();
327
328 // Sometimes it's necessary that we cast the function we want to call first
329 // to its explicit function type before calling it. This is supposed to prevent
330 // that we accidentially ending up in a function that is not the one we're
331 // supposed to call here (e.g. because the C++ function lookup decides to take
332 // another function that better fits).
333 // This method has some problems, e.g. when we call a function with default
334 // arguments and we don't provide all arguments, we would fail with this pattern.
335 // Same applies with member methods which seem to cause parse failures even when
336 // we supply the object parameter.
337 // Therefore we only use it in cases where we know it works and set this variable
338 // to true when we do.
339 bool ShouldCastFunction = !isa<CXXMethodDecl>(FD) && N == FD->getNumParams();
340 if (ShouldCastFunction) {
341 callbuf << "(";
342 callbuf << "(";
343 callbuf << return_type << " (&)";
344 {
345 callbuf << "(";
346 for (unsigned i = 0U; i < N; ++i) {
347 if (i) {
348 callbuf << ',';
349 if (i % 2) {
350 callbuf << ' ';
351 } else {
352 callbuf << "\n";
353 for (int j = 0; j <= indent_level; ++j) {
354 callbuf << kIndentString;
355 }
356 }
357 }
358 const ParmVarDecl *PVD = FD->getParamDecl(i);
359 QualType Ty = PVD->getType();
360 QualType QT = Ty.getCanonicalType();
361 std::string arg_type;
362 ASTContext &C = FD->getASTContext();
363 GetTypeAsString(QT, arg_type, C, C.getPrintingPolicy());
364 callbuf << arg_type;
365 }
366 if (FD->isVariadic())
367 callbuf << ", ...";
368 callbuf << ")";
369 }
370
371 callbuf << ")";
372 }
373
374 if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
375 // This is a class, struct, or union member.
376 if (MD->isConst())
377 callbuf << "((const " << class_name << "*)obj)->";
378 else
379 callbuf << "((" << class_name << "*)obj)->";
380 } else if (const NamedDecl *ND =
381 dyn_cast<NamedDecl>(GetDeclContext())) {
382 // This is a namespace member.
383 (void) ND;
384 callbuf << class_name << "::";
385 }
386 // callbuf << fMethod->Name() << "(";
387 {
388 std::string name;
389 {
390 llvm::raw_string_ostream stream(name);
391 FD->getNameForDiagnostic(stream, FD->getASTContext().getPrintingPolicy(), /*Qualified=*/false);
392 }
393 callbuf << name;
394 }
395 if (ShouldCastFunction) callbuf << ")";
396
397 callbuf << "(";
398
399 // IsCopyConstructorDeleted could trigger deserialization of decls.
400 cling::Interpreter::PushTransactionRAII RAII(fInterp);
401
402 for (unsigned i = 0U; i < N; ++i) {
403 const ParmVarDecl *PVD = FD->getParamDecl(i);
404 QualType Ty = PVD->getType();
405 QualType QT = Ty.getCanonicalType();
406 string type_name;
408 bool isPointer = false;
409 collect_type_info(QT, typedefbuf, callbuf, type_name, refType, isPointer, indent_level, true);
410
411 if (i) {
412 callbuf << ',';
413 if (i % 2) {
414 callbuf << ' ';
415 } else {
416 callbuf << "\n";
417 for (int j = 0; j <= indent_level; ++j) {
418 callbuf << kIndentString;
419 }
420 }
421 }
422
423 if (refType != kNotReference) {
424 callbuf << "(" << type_name.c_str() <<
425 (refType == kLValueReference ? "&" : "&&") << ")*(" << type_name.c_str() << "*)args["
426 << i << "]";
427 } else if (isPointer) {
428 callbuf << "*(" << type_name.c_str() << "**)args["
429 << i << "]";
430 } else {
431 // By-value construction: Figure out if the type can be copy-constructed. This is tricky and cannot be done in
432 // a fully reliable way, also because std::vector<T> always defines a copy constructor, even if the type T is
433 // only moveable. As a heuristic, we only check if the copy constructor is deleted, or would be if implicit.
434 bool Move = IsCopyConstructorDeleted(QT);
435 if (Move) {
436 callbuf << "static_cast<" << type_name << "&&>(";
437 }
438 callbuf << "*(" << type_name.c_str() << "*)args[" << i << "]";
439 if (Move) {
440 callbuf << ")";
441 }
442 }
443 }
444 callbuf << ")";
445}
446
447void TClingCallFunc::make_narg_ctor_with_return(const unsigned N, const string &class_name,
448 ostringstream &buf, int indent_level)
449{
450 // Make a code string that follows this pattern:
451 //
452 // if (ret) {
453 // (*(ClassName**)ret) = new ClassName(args...);
454 // }
455 // else {
456 // new ClassName(args...);
457 // }
458 //
459 for (int i = 0; i < indent_level; ++i) {
460 buf << kIndentString;
461 }
462 buf << "if (ret) {\n";
463 ++indent_level;
464 {
465 ostringstream typedefbuf;
466 ostringstream callbuf;
467 //
468 // Write the return value assignment part.
469 //
470 for (int i = 0; i < indent_level; ++i) {
471 callbuf << kIndentString;
472 }
473 callbuf << "(*(" << class_name << "**)ret) = ";
474 //
475 // Write the actual new expression.
476 //
477 make_narg_ctor(N, typedefbuf, callbuf, class_name, indent_level);
478 //
479 // End the new expression statement.
480 //
481 callbuf << ";\n";
482 for (int i = 0; i < indent_level; ++i) {
483 callbuf << kIndentString;
484 }
485 callbuf << "return;\n";
486 //
487 // Output the whole new expression and return statement.
488 //
489 buf << typedefbuf.str() << callbuf.str();
490 }
491 --indent_level;
492 for (int i = 0; i < indent_level; ++i) {
493 buf << kIndentString;
494 }
495 buf << "}\n";
496 for (int i = 0; i < indent_level; ++i) {
497 buf << kIndentString;
498 }
499 buf << "else {\n";
500 ++indent_level;
501 {
502 ostringstream typedefbuf;
503 ostringstream callbuf;
504 for (int i = 0; i < indent_level; ++i) {
505 callbuf << kIndentString;
506 }
507 make_narg_ctor(N, typedefbuf, callbuf, class_name, indent_level);
508 callbuf << ";\n";
509 for (int i = 0; i < indent_level; ++i) {
510 callbuf << kIndentString;
511 }
512 callbuf << "return;\n";
513 buf << typedefbuf.str() << callbuf.str();
514 }
515 --indent_level;
516 for (int i = 0; i < indent_level; ++i) {
517 buf << kIndentString;
518 }
519 buf << "}\n";
520}
521
522///////////////////////////////////////////////////////////////////////////////
523// Returns the DeclContext corresponding to fMethod's Decl.
524// \Note that this might be a FunctionDecl or a UsingShadowDecl; we use the
525// DeclContext of the UsingShadowDecl e.g. for constructing a derived class
526// object, even if invoking a function made available by a using declaration
527// of a constructor of a base class (ROOT-11010).
528
529const clang::DeclContext *TClingCallFunc::GetDeclContext() const {
530 return fMethod->GetDecl()->getDeclContext();
531}
532
533int TClingCallFunc::get_wrapper_code(std::string &wrapper_name, std::string &wrapper)
534{
535 const FunctionDecl *FD = GetDecl();
536 assert(FD && "generate_wrapper called without a function decl!");
537 ASTContext &Context = FD->getASTContext();
538 PrintingPolicy Policy(Context.getPrintingPolicy());
539 //
540 // Get the class or namespace name.
541 //
542 string class_name;
543 const clang::DeclContext *DC = GetDeclContext();
544 if (const TypeDecl *TD = dyn_cast<TypeDecl>(DC)) {
545 // This is a class, struct, or union member.
546 QualType QT(TD->getTypeForDecl(), 0);
547 GetTypeAsString(QT, class_name, Context, Policy);
548 } else if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC)) {
549 // This is a namespace member.
550 raw_string_ostream stream(class_name);
551 ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/true);
552 stream.flush();
553 }
554 //
555 // Check to make sure that we can
556 // instantiate and codegen this function.
557 //
558 bool needInstantiation = false;
559 const FunctionDecl *Definition = nullptr;
560 if (!FD->isDefined(Definition)) {
561 FunctionDecl::TemplatedKind TK = FD->getTemplatedKind();
562 switch (TK) {
563 case FunctionDecl::TK_NonTemplate: {
564 // Ordinary function, not a template specialization.
565 // Note: This might be ok, the body might be defined
566 // in a library, and all we have seen is the
567 // header file.
568 //::Error("TClingCallFunc::make_wrapper",
569 // "Cannot make wrapper for a function which is "
570 // "declared but not defined!");
571 // return 0;
572 } break;
573 case FunctionDecl::TK_FunctionTemplate: {
574 // This decl is actually a function template,
575 // not a function at all.
576 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a function template!");
577 return 0;
578 } break;
579 case FunctionDecl::TK_MemberSpecialization: {
580 // This function is the result of instantiating an ordinary
581 // member function of a class template, or of instantiating
582 // an ordinary member function of a class member of a class
583 // template, or of specializing a member function template
584 // of a class template, or of specializing a member function
585 // template of a class member of a class template.
586 if (!FD->isTemplateInstantiation()) {
587 // We are either TSK_Undeclared or
588 // TSK_ExplicitSpecialization.
589 // Note: This might be ok, the body might be defined
590 // in a library, and all we have seen is the
591 // header file.
592 //::Error("TClingCallFunc::make_wrapper",
593 // "Cannot make wrapper for a function template "
594 // "explicit specialization which is declared "
595 // "but not defined!");
596 // return 0;
597 break;
598 }
599 const FunctionDecl *Pattern = FD->getTemplateInstantiationPattern();
600 if (!Pattern) {
601 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a member function "
602 "instantiation with no pattern!");
603 return 0;
604 }
605 FunctionDecl::TemplatedKind PTK = Pattern->getTemplatedKind();
606 TemplateSpecializationKind PTSK = Pattern->getTemplateSpecializationKind();
607 if (
608 // The pattern is an ordinary member function.
609 (PTK == FunctionDecl::TK_NonTemplate) ||
610 // The pattern is an explicit specialization, and
611 // so is not a template.
612 ((PTK != FunctionDecl::TK_FunctionTemplate) &&
613 ((PTSK == TSK_Undeclared) || (PTSK == TSK_ExplicitSpecialization)))) {
614 // Note: This might be ok, the body might be defined
615 // in a library, and all we have seen is the
616 // header file.
617 break;
618 } else if (!Pattern->hasBody()) {
619 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a member function "
620 "instantiation with no body!");
621 return 0;
622 }
623 if (FD->isImplicitlyInstantiable()) {
624 needInstantiation = true;
625 }
626 } break;
627 case FunctionDecl::TK_FunctionTemplateSpecialization: {
628 // This function is the result of instantiating a function
629 // template or possibly an explicit specialization of a
630 // function template. Could be a namespace scope function or a
631 // member function.
632 if (!FD->isTemplateInstantiation()) {
633 // We are either TSK_Undeclared or
634 // TSK_ExplicitSpecialization.
635 // Note: This might be ok, the body might be defined
636 // in a library, and all we have seen is the
637 // header file.
638 //::Error("TClingCallFunc::make_wrapper",
639 // "Cannot make wrapper for a function template "
640 // "explicit specialization which is declared "
641 // "but not defined!");
642 // return 0;
643 break;
644 }
645 const FunctionDecl *Pattern = FD->getTemplateInstantiationPattern();
646 if (!Pattern) {
647 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a function template"
648 "instantiation with no pattern!");
649 return 0;
650 }
651 FunctionDecl::TemplatedKind PTK = Pattern->getTemplatedKind();
652 TemplateSpecializationKind PTSK = Pattern->getTemplateSpecializationKind();
653 if (
654 // The pattern is an ordinary member function.
655 (PTK == FunctionDecl::TK_NonTemplate) ||
656 // The pattern is an explicit specialization, and
657 // so is not a template.
658 ((PTK != FunctionDecl::TK_FunctionTemplate) &&
659 ((PTSK == TSK_Undeclared) || (PTSK == TSK_ExplicitSpecialization)))) {
660 // Note: This might be ok, the body might be defined
661 // in a library, and all we have seen is the
662 // header file.
663 break;
664 }
665 if (!Pattern->hasBody()) {
666 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a function template"
667 "instantiation with no body!");
668 return 0;
669 }
670 if (FD->isImplicitlyInstantiable()) {
671 needInstantiation = true;
672 }
673 } break;
674 case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
675 // This function is the result of instantiating or
676 // specializing a member function of a class template,
677 // or a member function of a class member of a class template,
678 // or a member function template of a class template, or a
679 // member function template of a class member of a class
680 // template where at least some part of the function is
681 // dependent on a template argument.
682 if (!FD->isTemplateInstantiation()) {
683 // We are either TSK_Undeclared or
684 // TSK_ExplicitSpecialization.
685 // Note: This might be ok, the body might be defined
686 // in a library, and all we have seen is the
687 // header file.
688 //::Error("TClingCallFunc::make_wrapper",
689 // "Cannot make wrapper for a dependent function "
690 // "template explicit specialization which is declared "
691 // "but not defined!");
692 // return 0;
693 break;
694 }
695 const FunctionDecl *Pattern = FD->getTemplateInstantiationPattern();
696 if (!Pattern) {
697 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a dependent function template"
698 "instantiation with no pattern!");
699 return 0;
700 }
701 FunctionDecl::TemplatedKind PTK = Pattern->getTemplatedKind();
702 TemplateSpecializationKind PTSK = Pattern->getTemplateSpecializationKind();
703 if (
704 // The pattern is an ordinary member function.
705 (PTK == FunctionDecl::TK_NonTemplate) ||
706 // The pattern is an explicit specialization, and
707 // so is not a template.
708 ((PTK != FunctionDecl::TK_FunctionTemplate) &&
709 ((PTSK == TSK_Undeclared) || (PTSK == TSK_ExplicitSpecialization)))) {
710 // Note: This might be ok, the body might be defined
711 // in a library, and all we have seen is the
712 // header file.
713 break;
714 }
715 if (!Pattern->hasBody()) {
716 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a dependent function template"
717 "instantiation with no body!");
718 return 0;
719 }
720 if (FD->isImplicitlyInstantiable()) {
721 needInstantiation = true;
722 }
723 } break;
724 default: {
725 // Will only happen if clang implementation changes.
726 // Protect ourselves in case that happens.
727 ::Error("TClingCallFunc::make_wrapper", "Unhandled template kind!");
728 return 0;
729 } break;
730 }
731 // We do not set needInstantiation to true in these cases:
732 //
733 // isInvalidDecl()
734 // TSK_Undeclared
735 // TSK_ExplicitInstantiationDefinition
736 // TSK_ExplicitSpecialization && !getClassScopeSpecializationPattern()
737 // TSK_ExplicitInstantiationDeclaration &&
738 // getTemplateInstantiationPattern() &&
739 // PatternDecl->hasBody() &&
740 // !PatternDecl->isInlined()
741 //
742 // Set it true in these cases:
743 //
744 // TSK_ImplicitInstantiation
745 // TSK_ExplicitInstantiationDeclaration && (!getPatternDecl() ||
746 // !PatternDecl->hasBody() || PatternDecl->isInlined())
747 //
748 }
749 if (needInstantiation) {
750 clang::FunctionDecl *FDmod = const_cast<clang::FunctionDecl *>(FD);
751 clang::Sema &S = fInterp->getSema();
752 // Could trigger deserialization of decls.
753 cling::Interpreter::PushTransactionRAII RAII(fInterp);
754 S.InstantiateFunctionDefinition(SourceLocation(), FDmod,
755 /*Recursive=*/true,
756 /*DefinitionRequired=*/true);
757 if (!FD->isDefined(Definition)) {
758 ::Error("TClingCallFunc::make_wrapper", "Failed to force template instantiation!");
759 return 0;
760 }
761 }
762 if (Definition) {
763 FunctionDecl::TemplatedKind TK = Definition->getTemplatedKind();
764 switch (TK) {
765 case FunctionDecl::TK_NonTemplate: {
766 // Ordinary function, not a template specialization.
767 if (Definition->isDeleted()) {
768 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a deleted function!");
769 return 0;
770 } else if (Definition->isLateTemplateParsed()) {
771 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a late template parsed "
772 "function!");
773 return 0;
774 }
775 // else if (Definition->isDefaulted()) {
776 // // Might not have a body, but we can still use it.
777 //}
778 // else {
779 // // Has a body.
780 //}
781 } break;
782 case FunctionDecl::TK_FunctionTemplate: {
783 // This decl is actually a function template,
784 // not a function at all.
785 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a function template!");
786 return 0;
787 } break;
788 case FunctionDecl::TK_MemberSpecialization: {
789 // This function is the result of instantiating an ordinary
790 // member function of a class template or of a member class
791 // of a class template.
792 if (Definition->isDeleted()) {
793 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a deleted member function "
794 "of a specialization!");
795 return 0;
796 } else if (Definition->isLateTemplateParsed()) {
797 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a late template parsed "
798 "member function of a specialization!");
799 return 0;
800 }
801 // else if (Definition->isDefaulted()) {
802 // // Might not have a body, but we can still use it.
803 //}
804 // else {
805 // // Has a body.
806 //}
807 } break;
808 case FunctionDecl::TK_FunctionTemplateSpecialization: {
809 // This function is the result of instantiating a function
810 // template or possibly an explicit specialization of a
811 // function template. Could be a namespace scope function or a
812 // member function.
813 if (Definition->isDeleted()) {
814 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a deleted function "
815 "template specialization!");
816 return 0;
817 } else if (Definition->isLateTemplateParsed()) {
818 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a late template parsed "
819 "function template specialization!");
820 return 0;
821 }
822 // else if (Definition->isDefaulted()) {
823 // // Might not have a body, but we can still use it.
824 //}
825 // else {
826 // // Has a body.
827 //}
828 } break;
829 case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
830 // This function is the result of instantiating or
831 // specializing a member function of a class template,
832 // or a member function of a class member of a class template,
833 // or a member function template of a class template, or a
834 // member function template of a class member of a class
835 // template where at least some part of the function is
836 // dependent on a template argument.
837 if (Definition->isDeleted()) {
838 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a deleted dependent function "
839 "template specialization!");
840 return 0;
841 } else if (Definition->isLateTemplateParsed()) {
842 ::Error("TClingCallFunc::make_wrapper", "Cannot make wrapper for a late template parsed "
843 "dependent function template specialization!");
844 return 0;
845 }
846 // else if (Definition->isDefaulted()) {
847 // // Might not have a body, but we can still use it.
848 //}
849 // else {
850 // // Has a body.
851 //}
852 } break;
853 default: {
854 // Will only happen if clang implementation changes.
855 // Protect ourselves in case that happens.
856 ::Error("TClingCallFunc::make_wrapper", "Unhandled template kind!");
857 return 0;
858 } break;
859 }
860 }
861 unsigned min_args = GetMinRequiredArguments();
862 unsigned num_params = FD->getNumParams();
863 //
864 // Make the wrapper name.
865 //
866 {
867 ostringstream buf;
868 buf << "__cf";
869 // const NamedDecl* ND = dyn_cast<NamedDecl>(FD);
870 // string mn;
871 // fInterp->maybeMangleDeclName(ND, mn);
872 // buf << '_' << mn;
873 buf << '_' << gWrapperSerial++;
874 wrapper_name = buf.str();
875 }
876 //
877 // Write the wrapper code.
878 // FIXME: this should be synthesized into the AST!
879 //
880 int indent_level = 0;
881 ostringstream buf;
882 buf << "#pragma clang diagnostic push\n"
883 "#pragma clang diagnostic ignored \"-Wformat-security\"\n"
884 "__attribute__((used)) "
885 "__attribute__((annotate(\"__cling__ptrcheck(off)\")))\n"
886 "extern \"C\" void ";
887 buf << wrapper_name;
888 buf << "(void* obj, int nargs, void** args, void* ret)\n"
889 "{\n";
890 ++indent_level;
891 if (min_args == num_params) {
892 // No parameters with defaults.
893 make_narg_call_with_return(num_params, class_name, buf, indent_level);
894 } else {
895 // We need one function call clause compiled for every
896 // possible number of arguments per call.
897 for (unsigned N = min_args; N <= num_params; ++N) {
898 for (int i = 0; i < indent_level; ++i) {
899 buf << kIndentString;
900 }
901 buf << "if (nargs == " << N << ") {\n";
902 ++indent_level;
903 make_narg_call_with_return(N, class_name, buf, indent_level);
904 --indent_level;
905 for (int i = 0; i < indent_level; ++i) {
906 buf << kIndentString;
907 }
908 buf << "}\n";
909 }
910 }
911 --indent_level;
912 buf << "}\n"
913 "#pragma clang diagnostic pop";
914 wrapper = buf.str();
915 return 1;
916}
917
918void TClingCallFunc::make_narg_call_with_return(const unsigned N, const string &class_name,
919 ostringstream &buf, int indent_level)
920{
921 // Make a code string that follows this pattern:
922 //
923 // if (ret) {
924 // new (ret) (return_type) ((class_name*)obj)->func(args...);
925 // }
926 // else {
927 // (void)(((class_name*)obj)->func(args...));
928 // }
929 //
930 const FunctionDecl *FD = GetDecl();
931 if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
932 if (N <= 1 && llvm::isa<UsingShadowDecl>(GetFunctionOrShadowDecl())) {
933 auto SpecMemKind = fInterp->getSema().getSpecialMember(CD);
934 if ((N == 0 && SpecMemKind == clang::Sema::CXXDefaultConstructor) ||
935 (N == 1 &&
936 (SpecMemKind == clang::Sema::CXXCopyConstructor || SpecMemKind == clang::Sema::CXXMoveConstructor))) {
937 // Using declarations cannot inject special members; do not call them
938 // as such. This might happen by using `Base(Base&, int = 12)`, which
939 // is fine to be called as `Derived d(someBase, 42)` but not as
940 // copy constructor of `Derived`.
941 return;
942 }
943 }
944 make_narg_ctor_with_return(N, class_name, buf, indent_level);
945 return;
946 }
947 QualType QT = FD->getReturnType().getCanonicalType();
948 if (QT->isVoidType()) {
949 ostringstream typedefbuf;
950 ostringstream callbuf;
951 for (int i = 0; i < indent_level; ++i) {
952 callbuf << kIndentString;
953 }
954 make_narg_call("void", N, typedefbuf, callbuf, class_name, indent_level);
955 callbuf << ";\n";
956 for (int i = 0; i < indent_level; ++i) {
957 callbuf << kIndentString;
958 }
959 callbuf << "return;\n";
960 buf << typedefbuf.str() << callbuf.str();
961 } else {
962 for (int i = 0; i < indent_level; ++i) {
963 buf << kIndentString;
964 }
965
966 string type_name;
968 bool isPointer = false;
969
970 buf << "if (ret) {\n";
971 ++indent_level;
972 {
973 ostringstream typedefbuf;
974 ostringstream callbuf;
975 //
976 // Write the placement part of the placement new.
977 //
978 for (int i = 0; i < indent_level; ++i) {
979 callbuf << kIndentString;
980 }
981 callbuf << "new (ret) ";
982 collect_type_info(QT, typedefbuf, callbuf, type_name,
983 refType, isPointer, indent_level, false);
984 //
985 // Write the type part of the placement new.
986 //
987 callbuf << "(" << type_name.c_str();
988 if (refType != kNotReference) {
989 callbuf << "*) (&";
990 type_name += "&";
991 } else if (isPointer) {
992 callbuf << "*) (";
993 type_name += "*";
994 } else {
995 callbuf << ") (";
996 }
997 //
998 // Write the actual function call.
999 //
1000 make_narg_call(type_name, N, typedefbuf, callbuf, class_name, indent_level);
1001 //
1002 // End the placement new.
1003 //
1004 callbuf << ");\n";
1005 for (int i = 0; i < indent_level; ++i) {
1006 callbuf << kIndentString;
1007 }
1008 callbuf << "return;\n";
1009 //
1010 // Output the whole placement new expression and return statement.
1011 //
1012 buf << typedefbuf.str() << callbuf.str();
1013 }
1014 --indent_level;
1015 for (int i = 0; i < indent_level; ++i) {
1016 buf << kIndentString;
1017 }
1018 buf << "}\n";
1019 for (int i = 0; i < indent_level; ++i) {
1020 buf << kIndentString;
1021 }
1022 buf << "else {\n";
1023 ++indent_level;
1024 {
1025 ostringstream typedefbuf;
1026 ostringstream callbuf;
1027 for (int i = 0; i < indent_level; ++i) {
1028 callbuf << kIndentString;
1029 }
1030 callbuf << "(void)(";
1031 make_narg_call(type_name, N, typedefbuf, callbuf, class_name, indent_level);
1032 callbuf << ");\n";
1033 for (int i = 0; i < indent_level; ++i) {
1034 callbuf << kIndentString;
1035 }
1036 callbuf << "return;\n";
1037 buf << typedefbuf.str() << callbuf.str();
1038 }
1039 --indent_level;
1040 for (int i = 0; i < indent_level; ++i) {
1041 buf << kIndentString;
1042 }
1043 buf << "}\n";
1044 }
1045}
1046
1048{
1050
1051 const Decl *D = GetFunctionOrShadowDecl();
1052 string wrapper_name;
1053 string wrapper;
1054
1055 if (get_wrapper_code(wrapper_name, wrapper) == 0) return nullptr;
1056
1057 //fprintf(stderr, "%s\n", wrapper.c_str());
1058 //
1059 // Compile the wrapper code.
1060 //
1061 void *F = compile_wrapper(wrapper_name, wrapper);
1062 if (F) {
1063 gWrapperStore.insert(make_pair(D, F));
1064 } else {
1065 ::Error("TClingCallFunc::make_wrapper",
1066 "Failed to compile\n ==== SOURCE BEGIN ====\n%s\n ==== SOURCE END ====",
1067 wrapper.c_str());
1068 }
1070}
1071
1073 ROOT::TMetaUtils::EIOCtorCategory kind, const std::string &type_name)
1074{
1075 // Make a code string that follows this pattern:
1076 //
1077 // void
1078 // unique_wrapper_ddd(void** ret, void* arena, unsigned long nary)
1079 // {
1080 // if (!arena) {
1081 // if (!nary) {
1082 // *ret = new ClassName;
1083 // }
1084 // else {
1085 // *ret = new ClassName[nary];
1086 // }
1087 // }
1088 // else {
1089 // if (!nary) {
1090 // *ret = new (arena) ClassName;
1091 // }
1092 // else {
1093 // *ret = new (arena) ClassName[nary];
1094 // }
1095 // }
1096 // }
1097 //
1098 // When I/O constructor used:
1099 //
1100 // void
1101 // unique_wrapper_ddd(void** ret, void* arena, unsigned long nary)
1102 // {
1103 // if (!arena) {
1104 // if (!nary) {
1105 // *ret = new ClassName((TRootIOCtor*)nullptr);
1106 // }
1107 // else {
1108 // char *buf = malloc(nary * sizeof(ClassName));
1109 // for (int k=0;k<nary;++k)
1110 // new (buf + k * sizeof(ClassName)) ClassName((TRootIOCtor*)nullptr);
1111 // *ret = buf;
1112 // }
1113 // }
1114 // else {
1115 // if (!nary) {
1116 // *ret = new (arena) ClassName((TRootIOCtor*)nullptr);
1117 // }
1118 // else {
1119 // for (int k=0;k<nary;++k)
1120 // new ((char *) arena + k * sizeof(ClassName)) ClassName((TRootIOCtor*)nullptr);
1121 // *ret = arena;
1122 // }
1123 // }
1124 // }
1125 //
1126 //
1127 // Note:
1128 //
1129 // If the class is of POD type, the form:
1130 //
1131 // new ClassName;
1132 //
1133 // does not initialize the object at all, and the form:
1134 //
1135 // new ClassName();
1136 //
1137 // default-initializes the object.
1138 //
1139 // We are using the form without parentheses because that is what
1140 // CINT did.
1141 //
1142 //--
1143 ASTContext &Context = info->GetDecl()->getASTContext();
1144 PrintingPolicy Policy(Context.getPrintingPolicy());
1145 Policy.SuppressTagKeyword = true;
1146 Policy.SuppressUnwrittenScope = true;
1147 //
1148 // Get the class or namespace name.
1149 //
1150 string class_name;
1151 if (const TypeDecl *TD = dyn_cast<TypeDecl>(info->GetDecl())) {
1152 // This is a class, struct, or union member.
1153 QualType QT(TD->getTypeForDecl(), 0);
1154 GetTypeAsString(QT, class_name, Context, Policy);
1155 } else if (const NamedDecl *ND = dyn_cast<NamedDecl>(info->GetDecl())) {
1156 // This is a namespace member.
1157 raw_string_ostream stream(class_name);
1158 ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/true);
1159 stream.flush();
1160 }
1161
1162
1163 //
1164 // Make the wrapper name.
1165 //
1166 string wrapper_name;
1167 {
1168 ostringstream buf;
1169 buf << "__ctor";
1170 //const NamedDecl* ND = dyn_cast<NamedDecl>(FD);
1171 //string mn;
1172 //fInterp->maybeMangleDeclName(ND, mn);
1173 //buf << '_dtor_' << mn;
1174 buf << '_' << gWrapperSerial++;
1175 wrapper_name = buf.str();
1176 }
1177
1178 string constr_arg;
1180 constr_arg = string("((") + type_name + "*)nullptr)";
1182 constr_arg = string("(*((") + type_name + "*)arena))";
1183
1184 //
1185 // Write the wrapper code.
1186 //
1187 int indent_level = 0;
1188 ostringstream buf;
1189 buf << "__attribute__((used)) ";
1190 buf << "extern \"C\" void ";
1191 buf << wrapper_name;
1192 buf << "(void** ret, void* arena, unsigned long nary)\n";
1193 buf << "{\n";
1194
1195 // if (!arena) {
1196 // if (!nary) {
1197 // *ret = new ClassName;
1198 // }
1199 // else {
1200 // *ret = new ClassName[nary];
1201 // }
1202 // }
1203 indent(buf, ++indent_level);
1204 buf << "if (!arena) {\n";
1205 indent(buf, ++indent_level);
1206 buf << "if (!nary) {\n";
1207 indent(buf, ++indent_level);
1208 buf << "*ret = new " << class_name << constr_arg << ";\n";
1209 indent(buf, --indent_level);
1210 buf << "}\n";
1211 indent(buf, indent_level);
1212 buf << "else {\n";
1213 indent(buf, ++indent_level);
1214 if (constr_arg.empty()) {
1215 buf << "*ret = new " << class_name << "[nary];\n";
1216 } else {
1217 buf << "char *buf = (char *) malloc(nary * sizeof(" << class_name << "));\n";
1218 indent(buf, indent_level);
1219 buf << "for (int k=0;k<nary;++k)\n";
1220 indent(buf, ++indent_level);
1221 buf << "new (buf + k * sizeof(" << class_name << ")) " << class_name << constr_arg << ";\n";
1222 indent(buf, --indent_level);
1223 buf << "*ret = buf;\n";
1224 }
1225 indent(buf, --indent_level);
1226 buf << "}\n";
1227 indent(buf, --indent_level);
1228 buf << "}\n";
1229 // else {
1230 // if (!nary) {
1231 // *ret = new (arena) ClassName;
1232 // }
1233 // else {
1234 // *ret = new (arena) ClassName[nary];
1235 // }
1236 // }
1237 indent(buf, indent_level);
1238 buf << "else {\n";
1239 indent(buf, ++indent_level);
1240 buf << "if (!nary) {\n";
1241 indent(buf, ++indent_level);
1242 buf << "*ret = new (arena) " << class_name << constr_arg << ";\n";
1243 indent(buf, --indent_level);
1244 buf << "}\n";
1245 indent(buf, indent_level);
1246 buf << "else {\n";
1247 indent(buf, ++indent_level);
1248 if (constr_arg.empty()) {
1249 buf << "*ret = new (arena) " << class_name << "[nary];\n";
1250 } else {
1251 buf << "for (int k=0;k<nary;++k)\n";
1252 indent(buf, ++indent_level);
1253 buf << "new ((char *) arena + k * sizeof(" << class_name << ")) " << class_name << constr_arg << ";\n";
1254 indent(buf, --indent_level);
1255 buf << "*ret = arena;\n";
1256 }
1257 indent(buf, --indent_level);
1258 buf << "}\n";
1259 indent(buf, --indent_level);
1260 buf << "}\n";
1261 // End wrapper.
1262 --indent_level;
1263 buf << "}\n";
1264 // Done.
1265 string wrapper(buf.str());
1266 //fprintf(stderr, "%s\n", wrapper.c_str());
1267 //
1268 // Compile the wrapper code.
1269 //
1270 void *F = compile_wrapper(wrapper_name, wrapper,
1271 /*withAccessControl=*/false);
1272 if (F) {
1273 gCtorWrapperStore.insert(make_pair(info->GetDecl(), F));
1274 } else {
1275 ::Error("TClingCallFunc::make_ctor_wrapper",
1276 "Failed to compile\n ==== SOURCE BEGIN ====\n%s\n ==== SOURCE END ====",
1277 wrapper.c_str());
1278 }
1280}
1281
1284{
1285 // Make a code string that follows this pattern:
1286 //
1287 // void
1288 // unique_wrapper_ddd(void* obj, unsigned long nary, int withFree)
1289 // {
1290 // if (withFree) {
1291 // if (!nary) {
1292 // delete (ClassName*) obj;
1293 // }
1294 // else {
1295 // delete[] (ClassName*) obj;
1296 // }
1297 // }
1298 // else {
1299 // typedef ClassName DtorName;
1300 // if (!nary) {
1301 // ((ClassName*)obj)->~DtorName();
1302 // }
1303 // else {
1304 // for (unsigned long i = nary - 1; i > -1; --i) {
1305 // (((ClassName*)obj)+i)->~DtorName();
1306 // }
1307 // }
1308 // }
1309 // }
1310 //
1311 //--
1312 ASTContext &Context = info->GetDecl()->getASTContext();
1313 PrintingPolicy Policy(Context.getPrintingPolicy());
1314 Policy.SuppressTagKeyword = true;
1315 Policy.SuppressUnwrittenScope = true;
1316 //
1317 // Get the class or namespace name.
1318 //
1319 string class_name;
1320 if (const TypeDecl *TD = dyn_cast<TypeDecl>(info->GetDecl())) {
1321 // This is a class, struct, or union member.
1322 QualType QT(TD->getTypeForDecl(), 0);
1323 GetTypeAsString(QT, class_name, Context, Policy);
1324 } else if (const NamedDecl *ND = dyn_cast<NamedDecl>(info->GetDecl())) {
1325 // This is a namespace member.
1326 raw_string_ostream stream(class_name);
1327 ND->getNameForDiagnostic(stream, Policy, /*Qualified=*/true);
1328 stream.flush();
1329 }
1330 //
1331 // Make the wrapper name.
1332 //
1333 string wrapper_name;
1334 {
1335 ostringstream buf;
1336 buf << "__dtor";
1337 //const NamedDecl* ND = dyn_cast<NamedDecl>(FD);
1338 //string mn;
1339 //fInterp->maybeMangleDeclName(ND, mn);
1340 //buf << '_dtor_' << mn;
1341 buf << '_' << gWrapperSerial++;
1342 wrapper_name = buf.str();
1343 }
1344 //
1345 // Write the wrapper code.
1346 //
1347 int indent_level = 0;
1348 ostringstream buf;
1349 buf << "__attribute__((used)) ";
1350 buf << "extern \"C\" void ";
1351 buf << wrapper_name;
1352 buf << "(void* obj, unsigned long nary, int withFree)\n";
1353 buf << "{\n";
1354 // if (withFree) {
1355 // if (!nary) {
1356 // delete (ClassName*) obj;
1357 // }
1358 // else {
1359 // delete[] (ClassName*) obj;
1360 // }
1361 // }
1362 ++indent_level;
1363 indent(buf, indent_level);
1364 buf << "if (withFree) {\n";
1365 ++indent_level;
1366 indent(buf, indent_level);
1367 buf << "if (!nary) {\n";
1368 ++indent_level;
1369 indent(buf, indent_level);
1370 buf << "delete (" << class_name << "*) obj;\n";
1371 --indent_level;
1372 indent(buf, indent_level);
1373 buf << "}\n";
1374 indent(buf, indent_level);
1375 buf << "else {\n";
1376 ++indent_level;
1377 indent(buf, indent_level);
1378 buf << "delete[] (" << class_name << "*) obj;\n";
1379 --indent_level;
1380 indent(buf, indent_level);
1381 buf << "}\n";
1382 --indent_level;
1383 indent(buf, indent_level);
1384 buf << "}\n";
1385 // else {
1386 // typedef ClassName Nm;
1387 // if (!nary) {
1388 // ((Nm*)obj)->~Nm();
1389 // }
1390 // else {
1391 // for (unsigned long i = nary - 1; i > -1; --i) {
1392 // (((Nm*)obj)+i)->~Nm();
1393 // }
1394 // }
1395 // }
1396 indent(buf, indent_level);
1397 buf << "else {\n";
1398 ++indent_level;
1399 indent(buf, indent_level);
1400 buf << "typedef " << class_name << " Nm;\n";
1401 buf << "if (!nary) {\n";
1402 ++indent_level;
1403 indent(buf, indent_level);
1404 buf << "((Nm*)obj)->~Nm();\n";
1405 --indent_level;
1406 indent(buf, indent_level);
1407 buf << "}\n";
1408 indent(buf, indent_level);
1409 buf << "else {\n";
1410 ++indent_level;
1411 indent(buf, indent_level);
1412 buf << "do {\n";
1413 ++indent_level;
1414 indent(buf, indent_level);
1415 buf << "(((Nm*)obj)+(--nary))->~Nm();\n";
1416 --indent_level;
1417 indent(buf, indent_level);
1418 buf << "} while (nary);\n";
1419 --indent_level;
1420 indent(buf, indent_level);
1421 buf << "}\n";
1422 --indent_level;
1423 indent(buf, indent_level);
1424 buf << "}\n";
1425 // End wrapper.
1426 --indent_level;
1427 buf << "}\n";
1428 // Done.
1429 string wrapper(buf.str());
1430 //fprintf(stderr, "%s\n", wrapper.c_str());
1431 //
1432 // Compile the wrapper code.
1433 //
1434 void *F = compile_wrapper(wrapper_name, wrapper,
1435 /*withAccessControl=*/false);
1436 if (F) {
1437 gDtorWrapperStore.insert(make_pair(info->GetDecl(), F));
1438 } else {
1439 ::Error("TClingCallFunc::make_dtor_wrapper",
1440 "Failed to compile\n ==== SOURCE BEGIN ====\n%s\n ==== SOURCE END ====",
1441 wrapper.c_str());
1442 }
1443
1445}
1446
1447void TClingCallFunc::exec(void *address, void *ret)
1448{
1449 SmallVector<void *, 8> vp_ary;
1450 const unsigned num_args = fArgVals.size();
1451 {
1453 const FunctionDecl *FD = GetDecl();
1454
1455 // FIXME: Consider the implicit this which is sometimes not passed.
1456 if (num_args < GetMinRequiredArguments()) {
1457 ::Error("TClingCallFunc::exec",
1458 "Not enough arguments provided for %s (%d instead of the minimum %d)",
1459 fMethod->Name(),
1460 num_args, (int)GetMinRequiredArguments());
1461 return;
1462 } else if (!isa<CXXMethodDecl>(FD) && num_args > FD->getNumParams()) {
1463 ::Error("TClingCallFunc::exec",
1464 "Too many arguments provided for %s (%d instead of the minimum %d)",
1465 fMethod->Name(),
1466 num_args, (int)GetMinRequiredArguments());
1467 return;
1468 }
1469 if (auto CXXMD = dyn_cast<CXXMethodDecl>(FD))
1470 if (!address && CXXMD && !CXXMD->isStatic() && !isa<CXXConstructorDecl>(FD)) {
1471 ::Error("TClingCallFunc::exec",
1472 "The method %s is called without an object.",
1473 fMethod->Name());
1474 return;
1475 }
1476
1477 vp_ary.reserve(num_args);
1478 for (unsigned i = 0; i < num_args; ++i) {
1479 QualType QT;
1480 // Check if we provided a this parameter.
1481 // FIXME: Currently we do not provide consistently the this pointer at
1482 // index 0 of the call arguments passed to the wrapper.
1483 // In C++ we can still call member functions which do not use it. Eg:
1484 // struct S {int Print() { return printf("a");} }; auto r1 = ((S*)0)->Print();
1485 // This works just fine even though it might be UB...
1486 bool implicitThisPassed = i == 0 && isa<CXXMethodDecl>(FD) && num_args - FD->getNumParams() == 1;
1487 if (implicitThisPassed)
1488 QT = cast<CXXMethodDecl>(FD)->getThisType();
1489 else
1490 QT = FD->getParamDecl(i)->getType();
1491 QT = QT.getCanonicalType();
1492 if (QT->isReferenceType() || QT->isRecordType()) {
1493 // the argument is already a pointer value (points to the same thing
1494 // as the reference or pointing to object passed by value.
1495 vp_ary.push_back(fArgVals[i].getPtr());
1496 } else {
1497 // Check if arguments need readjusting. This can happen if we called
1498 // cling::Value::Create which instantiates to say double but the
1499 // function signature requires a float.
1500 ASTContext &C = FD->getASTContext();
1501 if (QT->isBuiltinType() && !C.hasSameType(QT, fArgVals[i].getType())) {
1502 switch(QT->getAs<BuiltinType>()->getKind()) {
1503 default:
1504 ROOT::TMetaUtils::Error("TClingCallFunc::exec", "Unknown builtin type!");
1505#ifndef NDEBUG
1506 QT->dump();
1507#endif // NDEBUG
1508 break;
1509#define X(type, name) \
1510 case BuiltinType::name: fArgVals[i] = cling::Value::Create(*fInterp, fArgVals[i].castAs<type>()); break;
1511 CLING_VALUE_BUILTIN_TYPES
1512#undef X
1513 }
1514 }
1515 vp_ary.push_back(fArgVals[i].getPtrAddress());
1516 }
1517 }
1518 } // End of scope holding the lock
1519 (*fWrapper)(address, (int)num_args, (void **)vp_ary.data(), ret);
1520}
1521
1522void TClingCallFunc::exec_with_valref_return(void *address, cling::Value &ret)
1523{
1524 const FunctionDecl *FD = GetDecl();
1525
1526 QualType QT;
1527 if (llvm::isa<CXXConstructorDecl>(FD)) {
1529 ASTContext &Context = FD->getASTContext();
1530 const TypeDecl *TD = dyn_cast<TypeDecl>(GetDeclContext());
1531 QualType ClassTy(TD->getTypeForDecl(), 0);
1532 QT = Context.getLValueReferenceType(ClassTy);
1533 ret = cling::Value(QT, *fInterp);
1534 } else {
1535 QT = FD->getReturnType().getCanonicalType();
1536 ret = cling::Value(QT, *fInterp);
1537
1538 if (QT->isRecordType() || QT->isMemberDataPointerType())
1539 return exec(address, ret.getPtr());
1540 }
1541 exec(address, ret.getPtrAddress());
1542}
1543
1544void TClingCallFunc::EvaluateArgList(const string &ArgList)
1545{
1547
1548 SmallVector<Expr *, 4> exprs;
1549 fInterp->getLookupHelper().findArgList(ArgList, exprs,
1550 gDebug > 5 ? cling::LookupHelper::WithDiagnostics
1551 : cling::LookupHelper::NoDiagnostics);
1552 for (SmallVectorImpl<Expr *>::const_iterator I = exprs.begin(),
1553 E = exprs.end(); I != E; ++I) {
1554 cling::Value val;
1555 EvaluateExpr(*fInterp, *I, val);
1556 if (!val.isValid()) {
1557 // Bad expression, all done.
1558 ::Error("TClingCallFunc::EvaluateArgList",
1559 "Bad expression in parameter %d of '%s'!",
1560 (int)(I - exprs.begin()),
1561 ArgList.c_str());
1562 return;
1563 }
1564 fArgVals.push_back(val);
1565 }
1566}
1567
1568void TClingCallFunc::Exec(void *address, TInterpreterValue *interpVal/*=0*/)
1569{
1570 IFacePtr();
1571 if (!fWrapper) {
1572 ::Error("TClingCallFunc::Exec(address, interpVal)",
1573 "Called with no wrapper, not implemented!");
1574 return;
1575 }
1576 if (!interpVal || !interpVal->GetValAddr()) {
1577 exec(address, nullptr);
1578 return;
1579 }
1580 cling::Value *val = reinterpret_cast<cling::Value *>(interpVal->GetValAddr());
1581 exec_with_valref_return(address, *val);
1582}
1583
1584template <typename T>
1586{
1587 IFacePtr();
1588 if (!fWrapper) {
1589 ::Error("TClingCallFunc::ExecT",
1590 "Called with no wrapper, not implemented!");
1591 return 0;
1592 }
1593 cling::Value ret;
1594 exec_with_valref_return(address, ret);
1595 if (ret.isVoid()) {
1596 return 0;
1597 }
1598
1599 if (ret.needsManagedAllocation())
1600 ((TCling *)gCling)->RegisterTemporary(ret);
1601
1602 return ret.castAs<T>();
1603}
1604
1606{
1607 return ExecT<Longptr_t>(address);
1608}
1609
1610long long TClingCallFunc::ExecInt64(void *address)
1611{
1612 return ExecT<long long>(address);
1613}
1614
1615double TClingCallFunc::ExecDouble(void *address)
1616{
1617 return ExecT<double>(address);
1618}
1619
1620void TClingCallFunc::ExecWithArgsAndReturn(void *address, const void *args[] /*= 0*/,
1621 int nargs /*= 0*/, void *ret/*= 0*/)
1622{
1623 IFacePtr();
1624 if (!fWrapper) {
1625 ::Error("TClingCallFunc::ExecWithArgsAndReturn(address, args, ret)",
1626 "Called with no wrapper, not implemented!");
1627 return;
1628 }
1629 (*fWrapper)(address, nargs, const_cast<void **>(args), ret);
1630}
1631
1632void TClingCallFunc::ExecWithReturn(void *address, void *ret/*= 0*/)
1633{
1634 IFacePtr();
1635 if (!fWrapper) {
1636 ::Error("TClingCallFunc::ExecWithReturn(address, ret)",
1637 "Called with no wrapper, not implemented!");
1638 return;
1639 }
1640 exec(address, ret);
1641}
1642
1645 const std::string &type_name,
1646 void *address /*=0*/, unsigned long nary /*= 0UL*/)
1647{
1648 if (!info->IsValid()) {
1649 ::Error("TClingCallFunc::ExecDefaultConstructor", "Invalid class info!");
1650 return nullptr;
1651 }
1652 tcling_callfunc_ctor_Wrapper_t wrapper = nullptr;
1653 {
1655 auto D = info->GetDecl();
1656 //if (!info->HasDefaultConstructor()) {
1657 // // FIXME: We might have a ROOT ioctor, we might
1658 // // have to check for that here.
1659 // ::Error("TClingCallFunc::ExecDefaultConstructor",
1660 // "Class has no default constructor: %s",
1661 // info->Name());
1662 // return 0;
1663 //}
1664 auto I = gCtorWrapperStore.find(D);
1665 if (I != gCtorWrapperStore.end()) {
1666 wrapper = (tcling_callfunc_ctor_Wrapper_t) I->second;
1667 } else {
1668 wrapper = make_ctor_wrapper(info, kind, type_name);
1669 }
1670 }
1671 if (!wrapper) {
1672 ::Error("TClingCallFunc::ExecDefaultConstructor",
1673 "Called with no wrapper, not implemented!");
1674 return nullptr;
1675 }
1676 void *obj = nullptr;
1677 (*wrapper)(&obj, address, nary);
1678 return obj;
1679}
1680
1681void TClingCallFunc::ExecDestructor(const TClingClassInfo *info, void *address /*=0*/,
1682 unsigned long nary /*= 0UL*/, bool withFree /*= true*/)
1683{
1684 if (!info->IsValid()) {
1685 ::Error("TClingCallFunc::ExecDestructor", "Invalid class info!");
1686 return;
1687 }
1688
1689 tcling_callfunc_dtor_Wrapper_t wrapper = nullptr;
1690 {
1692 const Decl *D = info->GetDecl();
1693 map<const Decl *, void *>::iterator I = gDtorWrapperStore.find(D);
1694 if (I != gDtorWrapperStore.end()) {
1695 wrapper = (tcling_callfunc_dtor_Wrapper_t) I->second;
1696 } else {
1697 wrapper = make_dtor_wrapper(info);
1698 }
1699 }
1700 if (!wrapper) {
1701 ::Error("TClingCallFunc::ExecDestructor",
1702 "Called with no wrapper, not implemented!");
1703 return;
1704 }
1705 (*wrapper)(address, nary, withFree);
1706}
1707
1710{
1711 return new TClingMethodInfo(*fMethod);
1712}
1713
1715{
1716 fMethod.reset();
1717 fWrapper = nullptr;
1718 fDecl = nullptr;
1720 ResetArg();
1721}
1722
1724{
1725 Init();
1726 fMethod = std::unique_ptr<TClingMethodInfo>(new TClingMethodInfo(minfo));
1727}
1728
1729void TClingCallFunc::Init(std::unique_ptr<TClingMethodInfo> minfo)
1730{
1731 Init();
1732 fMethod = std::move(minfo);
1733}
1734
1736{
1737 if (!IsValid()) {
1738 return nullptr;
1739 }
1740 if (!fWrapper) {
1741 const Decl *decl = GetFunctionOrShadowDecl();
1742
1744 // check if another thread already did it
1745 if (!fWrapper) {
1746 map<const Decl *, void *>::iterator I = gWrapperStore.find(decl);
1747 if (I != gWrapperStore.end()) {
1749 } else {
1751 }
1752 }
1753 }
1754 return (void *)fWrapper.load();
1755}
1756
1758{
1759 if (!fMethod) {
1760 return false;
1761 }
1762 return fMethod->IsValid();
1763}
1764
1766{
1767 if (!IsValid()) {
1768 ::Error("TClingCallFunc::IFacePtr(kind)",
1769 "Attempt to get interface while invalid.");
1771 }
1772 if (!fWrapper) {
1773 const Decl *decl = GetFunctionOrShadowDecl();
1774
1776 // check if another thread already did it
1777 if (!fWrapper) {
1778 map<const Decl *, void *>::iterator I = gWrapperStore.find(decl);
1779 if (I != gWrapperStore.end()) {
1781 } else {
1783 }
1784 }
1785 }
1787}
1788
1789
1791{
1792 fArgVals.clear();
1793}
1794
1795void TClingCallFunc::SetArgArray(Longptr_t *paramArr, int nparam)
1796{
1797 ResetArg();
1798 for (int i = 0; i < nparam; ++i) {
1799 SetArg(paramArr[i]);
1800 }
1801}
1802
1803void TClingCallFunc::SetArgs(const char *params)
1804{
1805 ResetArg();
1806 EvaluateArgList(params);
1807}
1808
1809void TClingCallFunc::SetFunc(const TClingClassInfo *info, const char *method, const char *arglist,
1810 Longptr_t *poffset)
1811{
1812 SetFunc(info, method, arglist, false, poffset);
1813}
1814
1815void TClingCallFunc::SetFunc(const TClingClassInfo *info, const char *method, const char *arglist,
1816 bool objectIsConst, Longptr_t *poffset)
1817{
1818 Init(std::unique_ptr<TClingMethodInfo>(new TClingMethodInfo(fInterp)));
1819 if (poffset) {
1820 *poffset = 0L;
1821 }
1822 ResetArg();
1823 if (!info->IsValid()) {
1824 ::Error("TClingCallFunc::SetFunc", "Class info is invalid!");
1825 return;
1826 }
1827 if (!strcmp(arglist, ")")) {
1828 // CINT accepted a single right paren as meaning no arguments.
1829 arglist = "";
1830 }
1831 *fMethod = info->GetMethodWithArgs(method, arglist, objectIsConst, poffset);
1832 if (!fMethod->IsValid()) {
1833 //::Error("TClingCallFunc::SetFunc", "Could not find method %s(%s)", method,
1834 // arglist);
1835 return;
1836 }
1837 // FIXME: The arglist was already parsed by the lookup, we should
1838 // enhance the lookup to return the resulting expression
1839 // list so we do not need to parse it again here.
1840 EvaluateArgList(arglist);
1841}
1842
1844{
1845 Init(std::unique_ptr<TClingMethodInfo>(new TClingMethodInfo(*info)));
1846 ResetArg();
1847 if (!fMethod->IsValid()) {
1848 return;
1849 }
1850}
1851
1852void TClingCallFunc::SetFuncProto(const TClingClassInfo *info, const char *method,
1853 const char *proto, Longptr_t *poffset,
1854 EFunctionMatchMode mode/*=kConversionMatch*/)
1855{
1856 SetFuncProto(info, method, proto, false, poffset, mode);
1857}
1858
1859void TClingCallFunc::SetFuncProto(const TClingClassInfo *info, const char *method,
1860 const char *proto, bool objectIsConst, Longptr_t *poffset,
1861 EFunctionMatchMode mode/*=kConversionMatch*/)
1862{
1863 Init(std::unique_ptr<TClingMethodInfo>(new TClingMethodInfo(fInterp)));
1864 if (poffset) {
1865 *poffset = 0L;
1866 }
1867 ResetArg();
1868 if (!info->IsValid()) {
1869 ::Error("TClingCallFunc::SetFuncProto", "Class info is invalid!");
1870 return;
1871 }
1872 *fMethod = info->GetMethod(method, proto, objectIsConst, poffset, mode);
1873 if (!fMethod->IsValid()) {
1874 //::Error("TClingCallFunc::SetFuncProto", "Could not find method %s(%s)",
1875 // method, proto);
1876 return;
1877 }
1878}
1879
1880void TClingCallFunc::SetFuncProto(const TClingClassInfo *info, const char *method,
1881 const llvm::SmallVectorImpl<clang::QualType> &proto, Longptr_t *poffset,
1882 EFunctionMatchMode mode/*=kConversionMatch*/)
1883{
1884 SetFuncProto(info, method, proto, false, poffset, mode);
1885}
1886
1887void TClingCallFunc::SetFuncProto(const TClingClassInfo *info, const char *method,
1888 const llvm::SmallVectorImpl<clang::QualType> &proto,
1889 bool objectIsConst, Longptr_t *poffset,
1890 EFunctionMatchMode mode/*=kConversionMatch*/)
1891{
1892 Init(std::unique_ptr<TClingMethodInfo>(new TClingMethodInfo(fInterp)));
1893 if (poffset) {
1894 *poffset = 0L;
1895 }
1896 ResetArg();
1897 if (!info->IsValid()) {
1898 ::Error("TClingCallFunc::SetFuncProto", "Class info is invalid!");
1899 return;
1900 }
1901 *fMethod = info->GetMethod(method, proto, objectIsConst, poffset, mode);
1902 if (!fMethod->IsValid()) {
1903 //::Error("TClingCallFunc::SetFuncProto", "Could not find method %s(%s)",
1904 // method, proto);
1905 return;
1906 }
1907}
1908
long Longptr_t
Definition RtypesCore.h:75
static void EvaluateExpr(cling::Interpreter &interp, const Expr *E, cling::Value &V)
static bool IsCopyConstructorDeleted(QualType QT)
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:597
const char * proto
Definition civetweb.c:17535
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)
void Error(const char *location, const char *fmt,...)
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
EFunctionMatchMode