Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
DictSelectionReader.h
Go to the documentation of this file.
1 // @(#)root/utils/src:$Id$
2 // Author: Danilo Piparo January 2014
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2011, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/rootcint. *
10  *************************************************************************/
11 
12 #ifndef __DICTSELECTIONREADER__
13 #define __DICTSELECTIONREADER__
14 
15 #include "clang/AST/RecursiveASTVisitor.h"
16 
17 #include <llvm/ADT/StringMap.h>
18 
19 #include <set>
20 #include <unordered_set>
21 #include <string>
22 #include <unordered_map>
23 
24 class SelectionRules;
25 class ClassSelectionRule;
26 namespace ROOT {
27  namespace TMetaUtils {
28  class TNormalizedCtxt;
29  }
30 }
31 namespace cling {
32 class Interpreter;
33 }
34 
35 namespace clang {
36  class ASTContext;
37 // class DeclContext;
38  class NamespaceDecl;
39  class CXXRecordDecl;
40 }
41 
42 /**
43  * @file DictSelectionReader.h
44  * @author Danilo Piparo
45  * @date January 2014
46  * @brief Select classes and assign properties using C++ syntax.
47  *
48  * @details When generating dictionary information for a class,
49  * one sometimes wants to specify additional information
50  * beyond the class definition itself, for example, to specify
51  * that certain members are to be treated as transient by the persistency
52  * system. This can be done by associating a dictionary selection class
53  * with the class for which dictionary information is being generated.
54  * The contents of this selection class encode the additional information.
55  * Below, we first discuss how to associate a selection class
56  * with your class; then we list the current Set of information
57  * which may appear inside the selection class.
58  *
59  * The simplest case is for the case of a non-template class @c C.
60  * By default, the Name of the selection class is then
61  * @c ROOT::Meta::Selection::C. If you have such a class, it will be found
62  * automatically. If @c C is in a namespace, @c NS::C, then
63  * the selection class should be in the same namespace: @c
64 ROOT::Selection::NS::C.
65  * Examples:
66  *
67 
68 **/
69 
70 /**
71  * The DictSelectionReader is used to create selection rules starting from
72  * C++ the constructs of the @c ROOT::Meta::Selection namespace. All rules
73  * are matching by name.
74  * A brief description of the operations that lead to class selection:
75  * 1. If a class declaration is present in the selection namespace, a class
76  * with the same name is selected outside the selection namespace.
77  * 2. If a template class declaration and a template instantiation is present
78  * in the selection namespace, all the instances of the template are
79  * selected outside the namespace.
80  * For example:
81  * @code
82  * [...]
83  * class classVanilla{};
84  * template <class A> class classTemplateVanilla {};
85  * classTemplateVanilla<char> t0;
86  * namespace ROOT{
87  * namespace Meta {
88  * namespace Selection{
89  * class classVanilla{};
90  * template <typename A> class classTemplateVanilla{};
91  * classTemplateVanilla<char> st0;
92  * }
93  * }
94  * }
95  * @endcode
96  * would create two selection rules to select @c classVanilla and
97  * @c classTemplateVanilla<char>.
98  *
99  * A brief description of the properties that can be assigned to classes
100  * with the @c ROOT::Meta::Selection::ClassAttributes class.
101  * 1. @c kNonSplittable : Makes the class non splittable
102  * The class properties can be assigned via a traits mechanism. For example:
103  * @code
104  * [...]
105  * class classWithAttributes{};
106  * namespace ROOT{
107  * namespace Meta {
108  * namespace Selection{
109  * class classWithAttributes : ClassAttributes <kNonSplittable> {};
110  * }
111  * }
112  * }
113  * @endcode
114  * would create a selection rule which selects class @c classWithAttributes and
115  * assignes to it the property described by @c kNonSplittable. Multiple
116  * properties can be assigned to a single class with this syntax:
117  * @code
118  * [...]
119  * namespace ROOT{
120  * namespace Meta {
121  * namespace Selection{
122  * class classWithAttributes :
123  * ClassAttributes <kProperty1 + kProperty2 + ... + kPropertyN> {};
124  * }
125  * }
126  * }
127  * @endcode
128  *
129  *
130  * The @c ROOT::Meta::Selection syntax allows to alter the number of template
131  * parameters of a certain template class within the ROOT type system, TClass.
132  * Technically it allows to alter the way in which the "normalized name" (in
133  * other words, the "ROOT name") of the class is created. The key is the usage
134  * of the @c KeepFirstTemplateArguments traits class.
135  * It is possible to select the maximum number of template arguments considered
136  * if not different from the default. A concrete example can be more clear than
137  * a long explaination in this case:
138  * @code
139  * [...]
140  * template <class T, class U=int, int V=3> class A{...};
141  * template <class T, class Alloc= myAllocator<T> > class myVector{...};
142  * A<char> a1;
143  * A<char,float> a2;
144  * myVector<float> v1;
145  * myVector<A<char>> v2;
146  *
147  * namespace ROOT{
148  * namespace Meta {
149  * namespace Selection{
150  * template <class T, class U=int, int V=3> class A
151  * :KeepFirstTemplateArguments<1>{};
152  *
153  * A<double> ;
154  * template <class T, class Alloc= myAllocator<T> > class myVector
155  * :KeepFirstTemplateArguments<1>{};
156  *
157  * myVector<double> vd;
158  * }
159  * }
160  * }
161  * @endcode
162  *
163  * Consistently with what described above, all the instances of @c A and
164  * @c myvector will be selected. In addition, only the first template parameter
165  * will be kept.
166  * In absence of any @c KeepFirstTemplateArguments trait, the normalization
167  * would be:
168  * @c A<char> &rarr @c A<char,float,3>
169  * @c A<char,float> &rarr @c A<char,int,3>
170  * @c myVector<float> &rarr @c myVector<A<char,int,3>,myAllocator<A<char,int,3>>>
171  * @c myVector<A<char>> &rarr @c myVector<float,myAllocator<float>>
172  *
173  * Now, deciding to keep just one argument (@c KeepFirstTemplateArguments<1>):
174  * @c A<char> &rarr @c A<char,float>
175  * @c A<char,float> &rarr @c A<char>
176  * @c myVector<float> &rarr @c myVector<A<char>,myAllocator<A<char>>>
177  * @c myVector<A<char>> &rarr @c myVector<float,myAllocator<float>>
178  *
179  * And deciding to keep two arguments (@c KeepFirstTemplateArguments<2>):
180  * @c A<char> &rarr @c A<char,float>
181  * @c A<char,float> &rarr @c A<char,int>
182  * @c myVector<float> &rarr @c myVector<A<char,int>,myAllocator<A<char,int>>>
183  * @c myVector<A<char>> &rarr @c myVector<float,myAllocator<float>>
184  *
185  * A brief description of the properties that can be assigned to data members
186  * with the @c ROOT::Meta::Selection MemberAttributes class:
187  * 1. @c kTransient : the data member is transient, not persistified by the
188  * ROOT I/O.
189  * 2. @c kAutoSelected : the type of the data member is selected without the
190  * need of specifying its class explicitely.
191  * For example:
192  * @code
193  * [...]
194  * class classTransientMember{
195  * private:
196  * int transientMember;
197  * };
198  * class classAutoselected{};
199  * class classTestAutoselect{
200  * private:
201  * classAutoselected autoselected;
202  * };
203  *
204  * namespace ROOT{
205  * namespace Meta {
206  * namespace Selection{
207  * class classTestAutoselect{
208  * MemberAttributes<kAutoSelected> autoselected;
209  * };
210 
211  class classTransientMember{
212  MemberAttributes<kTransient> transientMember;
213  };
214  *
215  * @endcode
216  * would lead to the creation of selection rules for @c classTransientMember
217  * specifying that @c transientMember is transient, @c classTestAutoselect and
218  * @c classAutoselected.
219  *
220  * Another trait class present in the @c ROOT::Meta::Selection is
221  * @c SelectNoInstance. If a template in the selection namespace inherits from
222  * this class, none of its instantiations will be automatically selected but
223  * all of the properties specified otherwise, like transient members or
224  * number of template arguments to keep, will be transmitted to all of the
225  * instantiations selected by other means.
226  * For example
227  * @code
228  * [...]
229  * template< class T, class BASE >
230  * class MyDataVector : KeepFirstTemplateArguments< 1 >, SelectNoInstance {
231  * MemberAttributes< kTransient + kAutoSelected > m_isMostDerived;
232  * MemberAttributes< kNonSplittable+ kAutoSelected > m_isNonSplit;
233  * };
234  * [...]
235  *
236  **/
237 namespace ROOT {
238 namespace Internal {
239 
240 class DictSelectionReader : public clang::RecursiveASTVisitor<DictSelectionReader> {
241 public:
242  /// Take the selection rules as input (for consistency w/ other selector
243  /// interfaces)
244  DictSelectionReader(cling::Interpreter &interp, SelectionRules &, const clang::ASTContext &,
245  ROOT::TMetaUtils::TNormalizedCtxt &);
246 
247  /// Visit the entities that needs to be selected
248  bool VisitRecordDecl(clang::RecordDecl *);
249 
250  bool shouldVisitTemplateInstantiations() const {
251  return true;
252  }
253 
254 private:
255 
256 
257  struct TemplateInfo { /// < Class to store the information about templates upon parsing
258  TemplateInfo(int argsToKeep): fArgsToKeep(argsToKeep) {};
259  TemplateInfo() {};
260  int fArgsToKeep = -1;
261  std::unordered_set<std::string> fTransientMembers {};
262  std::unordered_set<std::string> fUnsplittableMembers {};
263  };
264 
265  inline bool
266  InSelectionNamespace(const clang::RecordDecl &,
267  const std::string &str =
268  ""); ///< Check if in the ROOT::Selection namespace
269  inline bool FirstPass(const clang::RecordDecl &); ///< First pass on the AST
270  inline bool SecondPass(const clang::RecordDecl &); ///< Second pass on the
271  ///AST, using the
272  ///information of the first
273  ///one
274  inline void
275  ManageFields(const clang::RecordDecl &,
276  const std::string &,
277  ClassSelectionRule &,
278  bool); ///< Take care of the class fields
279  inline void
280  ManageBaseClasses(const clang::CXXRecordDecl &, const std::string &, bool &); ///< Take care of the class bases
281  template <class T>
282  inline unsigned int ExtractTemplateArgValue(
283  const T &,
284  const std::string &); ///< Extract the value of the template parameter
285  inline const clang::TemplateArgumentList *GetTmplArgList(
286  const clang::CXXRecordDecl &); ///< Get the template arguments list if any
287 
288  std::string PatternifyName(const std::string &className); ///< Transform instance
289  ///< name in pattern for selection
290  void GetPointeeType(std::string &typeName); ///< Get name of the pointee type
291 
292  SelectionRules &fSelectionRules; ///< The selection rules to be filled
293  std::set<const clang::RecordDecl *>
294  fSelectedRecordDecls; ///< The pointers of the selected RecordDecls
295  std::set<std::string>
296  fSpecialNames; ///< The names of the classes used for the selction syntax
297  llvm::StringMap<std::set<std::string> >
298  fAutoSelectedClassFieldNames; ///< Collect the autoselected classes
299  llvm::StringMap<std::set<std::string> >
300  fNoAutoSelectedClassFieldNames; ///< Collect the autoexcluded classes
301  std::unordered_map<std::string, TemplateInfo> fTemplateInfoMap; ///< List template name - properties map
302  llvm::StringMap<ClassSelectionRule>
303  fClassNameSelectionRuleMap; /// < Map of the already built sel rules
304  bool fIsFirstPass; ///< Keep trance of the number of passes through the AST
305  ROOT::TMetaUtils::TNormalizedCtxt &fNormCtxt; /// < The reference to the normalized context
306 };
307 }
308 }
309 
310 #endif