ROOT  6.06/09
Reference Guide
RStl.cxx
Go to the documentation of this file.
1 // @(#)root/utils:$Id$
2 // Author: Philippe Canal 27/08/2003
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2003, Rene Brun, Fons Rademakers, and al. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS *
10  *************************************************************************/
11 
12 #include "RConfigure.h"
13 #include "RConfig.h"
14 
15 #include "RStl.h"
16 #include "TClassEdit.h"
17 #include "TMetaUtils.h"
18 using namespace TClassEdit;
19 
20 #include <stdio.h>
21 
22 #include "clang/AST/Decl.h"
23 #include "clang/AST/DeclTemplate.h"
24 
25 #include "Scanner.h"
26 
27 #include "cling/Interpreter/Interpreter.h"
28 #include "cling/Interpreter/LookupHelper.h"
29 
30 #include "clang/Sema/Sema.h"
31 #include "clang/Sema/Template.h"
32 #include "clang/Frontend/CompilerInstance.h"
33 #include "clang/AST/DeclTemplate.h"
34 
35 #ifndef ROOT_Varargs
36 #include "Varargs.h"
37 #endif
38 // void Error(const char *location, const char *va_(fmt), ...);
39 // void Warning(const char *location, const char *va_(fmt), ...);
40 
41 //
42 // ROOT::Internal::RStl is the rootcint STL handling class.
43 //
44 
45 static int fgCount = 0;
46 
48 {
49  // Return the singleton ROOT::Internal::RStl.
50 
51  static ROOT::Internal::RStl instance;
52  return instance;
53 
54 }
55 
56 void ROOT::Internal::RStl::GenerateTClassFor(const clang::QualType &type, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt)
57 {
58  // Force the generation of the TClass for the given class.
59 
60  const clang::CXXRecordDecl *stlclass = type.getTypePtr()->getAsCXXRecordDecl();
61  if (stlclass == 0) {
62  return;
63  }
64  const clang::ClassTemplateSpecializationDecl *templateCl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(stlclass);
65 
66  if (templateCl == 0) {
67  ROOT::TMetaUtils::Error("RStl::GenerateTClassFor","%s not in a template",
68  ROOT::TMetaUtils::GetQualifiedName(*stlclass).c_str());
69  }
70 
71  if ( TClassEdit::STLKind( stlclass->getName().str().c_str() ) == ROOT::kSTLvector ) {
72  const clang::TemplateArgument &arg( templateCl->getTemplateArgs().get(0) );
73  if (arg.getKind() == clang::TemplateArgument::Type) {
74  const clang::NamedDecl *decl = arg.getAsType().getTypePtr()->getAsCXXRecordDecl();
75  if (decl) {
76  // NOTE: we should just compare the decl to the bool builtin!
77  llvm::StringRef argname = decl->getName();
78  if ( (argname.str() == "bool") || (argname.str() == "Bool_t") ) {
79  ROOT::TMetaUtils::Warning("std::vector<bool>", " is not fully supported yet!\nUse std::vector<char> or std::deque<bool> instead.\n");
80  }
81  }
82  }
83  }
84 
85  fList.insert( ROOT::TMetaUtils::AnnotatedRecordDecl(++fgCount,type.getTypePtr(),stlclass,"",false /* for backward compatibility rather than 'true' .. neither really make a difference */,false,false,false,-1, interp, normCtxt) );
86 
87  // fprintf(stderr,"Registered the STL class %s as needing a dictionary\n",R__GetQualifiedName(*stlclass).c_str());
88 
89  for(unsigned int i=0; i < templateCl->getTemplateArgs().size(); ++i) {
90  const clang::TemplateArgument &arg( templateCl->getTemplateArgs().get(i) );
91  if (arg.getKind() == clang::TemplateArgument::Type) {
92  const clang::NamedDecl *decl = arg.getAsType().getTypePtr()->getAsCXXRecordDecl();
93 
94  if (decl && TClassEdit::STLKind( decl->getName().str().c_str() ) != 0 )
95  {
96  const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(decl);
97  if (clxx) {
98  if (!clxx->isCompleteDefinition()) {
99  /* bool result = */ ROOT::TMetaUtils::RequireCompleteType(interp, clxx->getLocation(), arg.getAsType());
100  }
101  // Do we need to strip the qualifier?
102  GenerateTClassFor(arg.getAsType(),interp,normCtxt);
103  }
104  }
105  }
106  }
107 }
108 
109 void ROOT::Internal::RStl::GenerateTClassFor(const char *requestedName, const clang::CXXRecordDecl *stlclass, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt)
110 {
111  // Force the generation of the TClass for the given class.
112 
113  const clang::ClassTemplateSpecializationDecl *templateCl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(stlclass);
114 
115  if (templateCl == 0) {
116  ROOT::TMetaUtils::Error("RStl::GenerateTClassFor","%s not in a template",
117  ROOT::TMetaUtils::GetQualifiedName(*stlclass).c_str());
118  }
119 
120 
121  if ( TClassEdit::STLKind( stlclass->getName().str().c_str() ) == ROOT::kSTLvector ) {
122  const clang::TemplateArgument &arg( templateCl->getTemplateArgs().get(0) );
123  if (arg.getKind() == clang::TemplateArgument::Type) {
124  const clang::NamedDecl *decl = arg.getAsType().getTypePtr()->getAsCXXRecordDecl();
125  if (decl) {
126  // NOTE: we should just compare the decl to the bool builtin!
127  llvm::StringRef argname = decl->getName();
128  if ( (argname.str() == "bool") || (argname.str() == "Bool_t") ) {
129  ROOT::TMetaUtils::Warning("std::vector<bool>", " is not fully supported yet!\nUse std::vector<char> or std::deque<bool> instead.\n");
130  }
131  }
132  }
133  }
134 
135  fList.insert( ROOT::TMetaUtils::AnnotatedRecordDecl(++fgCount,stlclass,requestedName,true,false,false,false,-1, interp,normCtxt) );
136 
138  for(unsigned int i=0; i < templateCl->getTemplateArgs().size(); ++i) {
139  const clang::TemplateArgument &arg( templateCl->getTemplateArgs().get(i) );
140  if (arg.getKind() == clang::TemplateArgument::Type) {
141  const clang::NamedDecl *decl = arg.getAsType().getTypePtr()->getAsCXXRecordDecl();
142 
143  if (decl && TClassEdit::STLKind( decl->getName().str().c_str() ) != 0 )
144  {
145  const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(decl);
146  if (clxx) {
147  if (!clxx->isCompleteDefinition()) {
148  /* bool result = */ ROOT::TMetaUtils::RequireCompleteType(interp, clxx->getLocation (), arg.getAsType());
149  clxx = arg.getAsType().getTypePtr()->getAsCXXRecordDecl();
150  }
151  if (!splitType.fElements.empty()) {
152  GenerateTClassFor( splitType.fElements[i+1].c_str(), clxx, interp, normCtxt);
153  } else {
154  GenerateTClassFor( "", clxx, interp, normCtxt );
155  }
156  }
157  }
158  }
159  }
160 
161  // fprintf(stderr,"ROOT::Internal::RStl registered %s as %s\n",stlclassname.c_str(),registername.c_str());
162 }
163 
165 {
166  // Print the content of the object
167  fprintf(stderr,"ROOT::Internal::RStl singleton\n");
168  list_t::iterator iter;
169  for(iter = fList.begin(); iter != fList.end(); ++iter) {
170  fprintf(stderr, "need TClass for %s\n", ROOT::TMetaUtils::GetQualifiedName(*(*iter)).c_str());
171  }
172 }
173 
174 void ROOT::Internal::RStl::WriteClassInit(std::ostream &ostr,
175  const cling::Interpreter &interp,
176  const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt,
177  const ROOT::TMetaUtils::RConstructorTypes& ctorTypes,
178  bool &needCollectionProxy,
179  void (*emitStreamerInfo)(const char*) )
180 {
181  // This function writes the TGeneraticClassInfo initialiser
182  // and the auxiliary functions (new and delete wrappers) for
183  // each of the STL containers that have been registered
184 
185  list_t::iterator iter;
186  for(iter = fList.begin(); iter != fList.end(); ++iter) {
187  const clang::CXXRecordDecl* result;
188 
189  if (!iter->GetRecordDecl()->getDefinition()) {
190 
191  // We do not have a complete definition, we need to force the instantiation
192  // and findScope can do that.
193  const cling::LookupHelper& lh = interp.getLookupHelper();
194  result = llvm::dyn_cast_or_null<clang::CXXRecordDecl>(lh.findScope(iter->GetNormalizedName(),
195  cling::LookupHelper::NoDiagnostics,
196  0)
197  );
198 
199  if (!result || !iter->GetRecordDecl()->getDefinition()) {
200  fprintf(stderr,"Error: incomplete definition for %s\n",iter->GetNormalizedName());
201  continue;
202  }
203  }
204  else
205  {
206  result = llvm::dyn_cast<clang::CXXRecordDecl>(iter->GetRecordDecl());
207  }
208 
209 // std::string fullname = TMetaUtils::GetQualifiedName(*iter->GetRecordDecl());
210 // fprintf(stderr,"RStl is generating TClass for %ld %s %s %s\n",iter->GetRuleIndex(),iter->GetRequestedName(),iter->GetNormalizedName(),fullname.c_str());
211 
212  ROOT::TMetaUtils::WriteClassInit(ostr, *iter, result, interp, normCtxt, ctorTypes, needCollectionProxy);
213  ROOT::TMetaUtils::WriteAuxFunctions(ostr, *iter, result, interp, ctorTypes, normCtxt);
214 
215  if (emitStreamerInfo) emitStreamerInfo(iter->GetNormalizedName());
216  }
217 }
218 
219 // void ROOT::Internal::RStl::WriteStreamer(FILE *file, const clang::CXXRecordDecl *stlcl)
220 // {
221 // // Write the free standing streamer function for the given
222 // // STL container class.
223 
224 // std::string streamerName = "stl_streamer_";
225 
226 // std::string shortTypeName = GetLong64_Name( TClassEdit::ShortType(ROOT::TMetaUtils::GetQualifiedName(*stlcl).c_str(),TClassEdit::kDropStlDefault) );
227 // std::string noConstTypeName( TClassEdit::CleanType(shortTypeName.c_str(),2) );
228 
229 // std::string typedefName;
230 // ROOT::TMetaUtils::GetCppName(typedefName, shortTypeName.c_str());
231 // streamerName += typedefName;
232 
233 // const clang::ClassTemplateSpecializationDecl *tmplt_specialization = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl> (stlcl);
234 // if (!tmplt_specialization) return;
235 
236 // int stltype = TClassEdit::STLKind(tmplt_specialization->getName().str().c_str());
237 
238 // const clang::TemplateArgument &arg0( tmplt_specialization->getTemplateArgs().get(0) );
239 
240 // clang::QualType firstType = arg0.getAsType();
241 // clang::QualType secondType;
242 
243 // const char *tclFirst=0,*tclSecond=0;
244 // std::string firstFullName, secondFullName;
245 
246 // if (ROOT::TMetaUtils::ElementStreamer(*stlcl, firstType,0,0)) {
247 // tclFirst = "R__tcl1";
248 // firstFullName = firstType.getAsString();
249 // }
250 // if (stltype==kMap || stltype==kMultiMap) {
251 // const clang::TemplateArgument &arg1( tmplt_specialization->getTemplateArgs().get(1) );
252 // secondType = arg1.getAsType();
253 
254 // if (ROOT::TMetaUtils::ElementStreamer(*stlcl, secondType,0,0)) {
255 // tclSecond="R__tcl2";
256 // secondFullName = secondType.getAsString();
257 // }
258 // }
259 
260 // fprintf(file, "//___________________________________________________________");
261 // fprintf(file, "_____________________________________________________________\n");
262 // fprintf(file, "namespace ROOT {\n");
263 // fprintf(file, " typedef %s %s;\n",shortTypeName.c_str(), typedefName.c_str());
264 // fprintf(file, " static void %s(TBuffer &R__b, void *R__p)\n",streamerName.c_str());
265 // fprintf(file, " {\n");
266 // fprintf(file, " if (gDebug>1) Info(__FILE__,\"Running compiled streamer for %s at %%p\",R__p);\n",shortTypeName.c_str());
267 // fprintf(file, " %s &R__stl = *(%s *)R__p;\n",shortTypeName.c_str(),shortTypeName.c_str());
268 // fprintf(file, " if (R__b.IsReading()) {\n");
269 // fprintf(file, " R__stl.clear();\n");
270 
271 // if (tclFirst)
272 // fprintf(file, " TClass *R__tcl1 = TBuffer::GetClass(typeid(%s));\n",
273 // firstFullName.c_str());
274 // if (tclSecond)
275 // fprintf(file, " TClass *R__tcl2 = TBuffer::GetClass(typeid(%s));\n",
276 // secondFullName.c_str());
277 
278 // fprintf(file, " int R__i, R__n;\n");
279 // fprintf(file, " R__b >> R__n;\n");
280 
281 // if (stltype==kVector) {
282 // fprintf(file," R__stl.reserve(R__n);\n");
283 // }
284 // fprintf(file, " for (R__i = 0; R__i < R__n; R__i++) {\n");
285 
286 // ROOT::TMetaUtils::ElementStreamer(*stlcl, firstType,"R__t",0,tclFirst);
287 // if (stltype == kMap || stltype == kMultiMap) { //Second Arg
288 // ROOT::TMetaUtils::ElementStreamer(*stlcl, secondType,"R__t2",0,tclSecond);
289 // }
290 // switch (stltype) {
291 
292 // case kMap:
293 // case kMultiMap:
294 // fprintf(file, " R__stl.insert(make_pair(R__t,R__t2));\n");
295 // break;
296 // case kSet:
297 // case kMultiSet:
298 // fprintf(file, " R__stl.insert(R__t);\n");
299 // break;
300 // case kVector:
301 // case kList:
302 // case kDeque:
303 // fprintf(file, " R__stl.push_back(R__t);\n");
304 // break;
305 
306 // default:
307 // assert(0);
308 // }
309 // fprintf(file, " }\n");
310 
311 // fprintf(file, " } else {\n");
312 
313 // fprintf(file, " int R__n=(&R__stl) ? int(R__stl.size()) : 0;\n");
314 // fprintf(file, " R__b << R__n;\n");
315 // fprintf(file, " if(R__n) {\n");
316 
317 // if (tclFirst) {
318 // fprintf(file, " TClass *R__tcl1 = TBuffer::GetClass(typeid(%s));\n",
319 // firstFullName.c_str());
320 // fprintf(file, " if (R__tcl1==0) {\n");
321 // fprintf(file, " Error(\"%s streamer\",\"Missing the TClass object for %s!\");\n",
322 // shortTypeName.c_str(), firstFullName.c_str());
323 // fprintf(file, " return;\n");
324 // fprintf(file, " }\n");
325 // }
326 // if (tclSecond) {
327 // fprintf(file, " TClass *R__tcl2 = TBuffer::GetClass(typeid(%s));\n",
328 // secondFullName.c_str());
329 // fprintf(file, " if (R__tcl2==0) {\n");
330 // fprintf(file, " Error(\"%s streamer\",\"Missing the TClass object for %s!\");\n",
331 // shortTypeName.c_str(), secondFullName.c_str());
332 // fprintf(file, " return;\n");
333 // fprintf(file, " }\n");
334 // }
335 // fprintf(file, " %s::iterator R__k;\n", shortTypeName.c_str());
336 // fprintf(file, " for (R__k = R__stl.begin(); R__k != R__stl.end(); ++R__k) {\n");
337 
338 // if (stltype == kMap || stltype == kMultiMap) {
339 // ROOT::TMetaUtils::ElementStreamer(*stlcl, firstType ,"((*R__k).first )",1,tclFirst);
340 // ROOT::TMetaUtils::ElementStreamer(*stlcl, secondType,"((*R__k).second)",1,tclSecond);
341 // } else {
342 // ROOT::TMetaUtils::ElementStreamer(*stlcl, firstType ,"(*R__k)" ,1,tclFirst);
343 // }
344 
345 // fprintf(file, " }\n");
346 // fprintf(file, " }\n");
347 
348 // fprintf(file, " }\n");
349 // fprintf(file, " } // end of %s streamer\n",ROOT::TMetaUtils::GetQualifiedName(*stlcl).c_str());
350 // fprintf(file, "} // close namespace ROOT\n\n");
351 
352 // fprintf(file, "// Register the streamer (a typedef is used to avoid problem with macro parameters\n");
353 
354 // //if ( 0 != ::getenv("MY_ROOT") && ::getenv("MY_ROOT")[0]>'1' ) {
355 // // fprintf(file, "// Disabled due customized build:\n// ");
356 // //}
357 // fprintf(file, "RootStlStreamer(%s,%s)\n", typedefName.c_str(), streamerName.c_str());
358 // fprintf(file, "\n");
359 
360 // }
361 
362 // void ROOT::Internal::RStl::WriteStreamer(FILE *file)
363 // {
364 // // Write the free standing streamer function for the registereed
365 // // STL container classes
366 
367 // list_t::iterator iter;
368 // for(iter = fList.begin(); iter != fList.end(); ++iter) {
369 // WriteStreamer(file,llvm::dyn_cast<clang::CXXRecordDecl>(iter->GetRecordDecl()));
370 // }
371 // }
void Error(const char *location, const char *va_(fmt),...)
Use this function in case an error occured.
void GetQualifiedName(std::string &qual_name, const clang::QualType &type, const clang::NamedDecl &forcontext)
Main implementation relying on GetFullyQualifiedTypeName All other GetQualifiedName functions leverag...
std::map< std::string, std::string >::const_iterator iter
Definition: TAlienJob.cxx:54
ROOT::ESTLType STLKind(std::string_view type)
Converts STL container name to number.
Definition: TClassEdit.cxx:467
void WriteClassInit(std::ostream &finalString, const AnnotatedRecordDecl &cl, const clang::CXXRecordDecl *decl, const cling::Interpreter &interp, const TNormalizedCtxt &normCtxt, const RConstructorTypes &ctorTypes, bool &needCollectionProxy)
FIXME: a function of ~300 lines!
void WriteAuxFunctions(std::ostream &finalString, const AnnotatedRecordDecl &cl, const clang::CXXRecordDecl *decl, const cling::Interpreter &interp, const RConstructorTypes &ctorTypes, const TNormalizedCtxt &normCtxt)
std::string NormalizedName; GetNormalizedName(NormalizedName, decl->getASTContext().getTypeDeclType(decl), interp, normCtxt);
std::list< RConstructorType > RConstructorTypes
Definition: TMetaUtils.h:301
std::vector< std::string > fElements
Definition: TClassEdit.h:139
bool RequireCompleteType(const cling::Interpreter &interp, const clang::CXXRecordDecl *cl)
Definition: TMetaUtils.cxx:733
Type
enumeration specifying the integration types.
void GenerateTClassFor(const char *requestedName, const clang::CXXRecordDecl *stlClass, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt)
Definition: RStl.cxx:109
static RStl & Instance()
Definition: RStl.cxx:47
int type
Definition: TGX11.cxx:120
void Warning(const char *location, const char *va_(fmt),...)
Use this function in warning situations.
static int fgCount
Definition: RStl.cxx:45
double result[121]
void WriteClassInit(std::ostream &strm, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt, const ROOT::TMetaUtils::RConstructorTypes &, bool &needCollectionProxy, void(*emitStreamerInfo)(const char *))
Definition: RStl.cxx:174