Logo ROOT   6.08/07
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 
39 //
40 // ROOT::Internal::RStl is the rootcint STL handling class.
41 //
42 
43 static int fgCount = 0;
44 
46 {
47  // Return the singleton ROOT::Internal::RStl.
48 
49  static ROOT::Internal::RStl instance;
50  return instance;
51 
52 }
53 
54 void ROOT::Internal::RStl::GenerateTClassFor(const clang::QualType &type, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt)
55 {
56  // Force the generation of the TClass for the given class.
57 
58  clang::QualType thisType = type;
59 
60  auto typePtr = thisType.getTypePtr();
61  const clang::CXXRecordDecl *stlclass = typePtr->getAsCXXRecordDecl();
62  if (!stlclass) {
63  return;
64  }
65 
66  // Transform the type to the corresponding one for IO
67  auto typeForIO = ROOT::TMetaUtils::GetTypeForIO(thisType, interp, normCtxt);
68  if (typeForIO.getTypePtr() != typePtr)
69  stlclass = typeForIO->getAsCXXRecordDecl();
70  if (!stlclass) {
71  return;
72  }
73  thisType = typeForIO;
74 
75  const clang::ClassTemplateSpecializationDecl *templateCl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(stlclass);
76 
77  if (!templateCl) {
78  ROOT::TMetaUtils::Error("RStl::GenerateTClassFor","%s not in a template",
79  ROOT::TMetaUtils::GetQualifiedName(*stlclass).c_str());
80  }
81 
82  if ( TClassEdit::STLKind( stlclass->getName().str().c_str() ) == ROOT::kSTLvector ) {
83  const clang::TemplateArgument &arg( templateCl->getTemplateArgs().get(0) );
84  if (arg.getKind() == clang::TemplateArgument::Type) {
85  const clang::NamedDecl *decl = arg.getAsType().getTypePtr()->getAsCXXRecordDecl();
86  if (decl) {
87  // NOTE: we should just compare the decl to the bool builtin!
88  llvm::StringRef argname = decl->getName();
89  if ( (argname.str() == "bool") || (argname.str() == "Bool_t") ) {
90  ROOT::TMetaUtils::Warning("std::vector<bool>", " is not fully supported yet!\nUse std::vector<char> or std::deque<bool> instead.\n");
91  }
92  }
93  }
94  }
95 
97  thisType.getTypePtr(),
98  stlclass,
99  "",
100  false /* for backward compatibility rather than 'true' .. neither really make a difference */,
101  false,
102  false,
103  false,
104  -1,
105  interp,
106  normCtxt) );
107 
108  // fprintf(stderr,"Registered the STL class %s as needing a dictionary\n",R__GetQualifiedName(*stlclass).c_str());
109 
110  for(unsigned int i=0; i < templateCl->getTemplateArgs().size(); ++i) {
111  const clang::TemplateArgument &arg( templateCl->getTemplateArgs().get(i) );
112  if (arg.getKind() == clang::TemplateArgument::Type) {
113  const clang::NamedDecl *decl = arg.getAsType().getTypePtr()->getAsCXXRecordDecl();
114 
115  if (decl && TClassEdit::STLKind( decl->getName().str().c_str() ) != 0 )
116  {
117  const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(decl);
118  if (clxx) {
119  if (!clxx->isCompleteDefinition()) {
120  /* bool result = */ ROOT::TMetaUtils::RequireCompleteType(interp, clxx->getLocation(), arg.getAsType());
121  }
122  // Do we need to strip the qualifier?
123  GenerateTClassFor(arg.getAsType(),interp,normCtxt);
124  }
125  }
126  }
127  }
128 }
129 
130 void ROOT::Internal::RStl::GenerateTClassFor(const char *requestedName, const clang::CXXRecordDecl *stlclass, const cling::Interpreter &interp, const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt)
131 {
132  // Force the generation of the TClass for the given class.
133  const clang::ClassTemplateSpecializationDecl *templateCl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(stlclass);
134 
135  if (templateCl == 0) {
136  ROOT::TMetaUtils::Error("RStl::GenerateTClassFor","%s not in a template",
137  ROOT::TMetaUtils::GetQualifiedName(*stlclass).c_str());
138  }
139 
140 
141  if ( TClassEdit::STLKind( stlclass->getName().str().c_str() ) == ROOT::kSTLvector ) {
142  const clang::TemplateArgument &arg( templateCl->getTemplateArgs().get(0) );
143  if (arg.getKind() == clang::TemplateArgument::Type) {
144  const clang::NamedDecl *decl = arg.getAsType().getTypePtr()->getAsCXXRecordDecl();
145  if (decl) {
146  // NOTE: we should just compare the decl to the bool builtin!
147  llvm::StringRef argname = decl->getName();
148  if ( (argname.str() == "bool") || (argname.str() == "Bool_t") ) {
149  ROOT::TMetaUtils::Warning("std::vector<bool>", " is not fully supported yet!\nUse std::vector<char> or std::deque<bool> instead.\n");
150  }
151  }
152  }
153  }
154 
155  fList.insert( ROOT::TMetaUtils::AnnotatedRecordDecl(++fgCount,stlclass,requestedName,true,false,false,false,-1, interp,normCtxt) );
156 
158  for(unsigned int i=0; i < templateCl->getTemplateArgs().size(); ++i) {
159  const clang::TemplateArgument &arg( templateCl->getTemplateArgs().get(i) );
160  if (arg.getKind() == clang::TemplateArgument::Type) {
161  const clang::NamedDecl *decl = arg.getAsType().getTypePtr()->getAsCXXRecordDecl();
162 
163  if (decl && TClassEdit::STLKind( decl->getName().str().c_str() ) != 0 )
164  {
165  const clang::CXXRecordDecl *clxx = llvm::dyn_cast<clang::CXXRecordDecl>(decl);
166  if (clxx) {
167  if (!clxx->isCompleteDefinition()) {
168  /* bool result = */ ROOT::TMetaUtils::RequireCompleteType(interp, clxx->getLocation (), arg.getAsType());
169  clxx = arg.getAsType().getTypePtr()->getAsCXXRecordDecl();
170  }
171  if (!splitType.fElements.empty()) {
172  GenerateTClassFor( splitType.fElements[i+1].c_str(), clxx, interp, normCtxt);
173  } else {
174  GenerateTClassFor( "", clxx, interp, normCtxt );
175  }
176  }
177  }
178  }
179  }
180 
181 }
182 
184 {
185  // Print the content of the object
186  fprintf(stderr,"ROOT::Internal::RStl singleton\n");
187  list_t::iterator iter;
188  for(iter = fList.begin(); iter != fList.end(); ++iter) {
189  fprintf(stderr, "need TClass for %s\n", ROOT::TMetaUtils::GetQualifiedName(*(*iter)).c_str());
190  }
191 }
192 
193 void ROOT::Internal::RStl::WriteClassInit(std::ostream &ostr,
194  const cling::Interpreter &interp,
195  const ROOT::TMetaUtils::TNormalizedCtxt &normCtxt,
196  const ROOT::TMetaUtils::RConstructorTypes& ctorTypes,
197  bool &needCollectionProxy,
198  void (*emitStreamerInfo)(const char*) )
199 {
200  // This function writes the TGeneraticClassInfo initialiser
201  // and the auxiliary functions (new and delete wrappers) for
202  // each of the STL containers that have been registered
203 
204  list_t::iterator iter;
205  for(iter = fList.begin(); iter != fList.end(); ++iter) {
206  const clang::CXXRecordDecl* result;
207 
208  if (!iter->GetRecordDecl()->getDefinition()) {
209 
210  // We do not have a complete definition, we need to force the instantiation
211  // and findScope can do that.
212  const cling::LookupHelper& lh = interp.getLookupHelper();
213  result = llvm::dyn_cast_or_null<clang::CXXRecordDecl>(lh.findScope(iter->GetNormalizedName(),
214  cling::LookupHelper::NoDiagnostics,
215  0)
216  );
217 
218  if (!result || !iter->GetRecordDecl()->getDefinition()) {
219  fprintf(stderr,"Error: incomplete definition for %s\n",iter->GetNormalizedName());
220  continue;
221  }
222  }
223  else
224  {
225  result = llvm::dyn_cast<clang::CXXRecordDecl>(iter->GetRecordDecl());
226  }
227 
228  ROOT::TMetaUtils::WriteClassInit(ostr, *iter, result, interp, normCtxt, ctorTypes, needCollectionProxy);
229  ROOT::TMetaUtils::WriteAuxFunctions(ostr, *iter, result, interp, ctorTypes, normCtxt);
230 
231  if (emitStreamerInfo) emitStreamerInfo(iter->GetNormalizedName());
232  }
233 }
clang::QualType GetTypeForIO(const clang::QualType &templateInstanceType, const cling::Interpreter &interpreter, const TNormalizedCtxt &normCtxt, TClassEdit::EModType mode=TClassEdit::kNone)
void Error(const char *location, const char *va_(fmt),...)
Definition: TMetaUtils.h:767
void GetQualifiedName(std::string &qual_name, const clang::QualType &type, const clang::NamedDecl &forcontext)
Main implementation relying on GetFullyQualifiedTypeName All other GetQualifiedName functions leverag...
ROOT::ESTLType STLKind(std::string_view type)
Converts STL container name to number.
Definition: TClassEdit.cxx:468
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:299
std::vector< std::string > fElements
Definition: TClassEdit.h:140
bool RequireCompleteType(const cling::Interpreter &interp, const clang::CXXRecordDecl *cl)
Definition: TMetaUtils.cxx:723
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:130
static RStl & Instance()
Definition: RStl.cxx:45
int type
Definition: TGX11.cxx:120
void Warning(const char *location, const char *va_(fmt),...)
Definition: TMetaUtils.h:797
static int fgCount
Definition: RStl.cxx:43
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:193