Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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
24class SelectionRules;
26namespace ROOT {
27 namespace TMetaUtils {
28 class TNormalizedCtxt;
29 }
30}
31namespace cling {
32class Interpreter;
33}
34
35namespace 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:
64 * @c ROOT::Meta::Selection::NS::C.
65 *
66 * Examples:
67 *
68 * The DictSelectionReader is used to create selection rules starting from
69 * C++ the constructs of the @c ROOT::Meta::Selection namespace. All rules
70 * are matching by name.
71 * A brief description of the operations that lead to class selection:
72 * 1. If a class declaration is present in the selection namespace, a class
73 * with the same name is selected outside the selection namespace.
74 * 2. If a template class declaration and a template instantiation is present
75 * in the selection namespace, all the instances of the template are
76 * selected outside the namespace.
77 *
78 * For example:
79 * @code
80 * [...]
81 * class classVanilla{};
82 * template <class A> class classTemplateVanilla {};
83 * classTemplateVanilla<char> t0;
84 * namespace ROOT {
85 * namespace Meta {
86 * namespace Selection {
87 * class classVanilla {};
88 * template <typename A> class classTemplateVanilla {};
89 * classTemplateVanilla<char> st0;
90 * }
91 * }
92 * }
93 * @endcode
94 * would create two selection rules to select @c classVanilla and
95 * @c classTemplateVanilla<char>.
96 *
97 * A brief description of the properties that can be assigned to classes
98 * with the @c ROOT::Meta::Selection::ClassAttributes class.
99 * 1. @c kNonSplittable : Makes the class non splittable
100 *
101 * The class properties can be assigned via a traits mechanism. For example:
102 * @code
103 * [...]
104 * class classWithAttributes {};
105 * namespace ROOT {
106 * namespace Meta {
107 * namespace Selection {
108 * class classWithAttributes : ClassAttributes <kNonSplittable> {};
109 * }
110 * }
111 * }
112 * @endcode
113 * would create a selection rule which selects class @c classWithAttributes and
114 * assignes to it the property described by @c kNonSplittable. Multiple
115 * properties can be assigned to a single class with this syntax:
116 * @code
117 * [...]
118 * namespace ROOT {
119 * namespace Meta {
120 * namespace Selection {
121 * class classWithAttributes :
122 * ClassAttributes <kProperty1 + kProperty2 + ... + kPropertyN> {};
123 * }
124 * }
125 * }
126 * @endcode
127 *
128 * The @c ROOT::Meta::Selection syntax allows to alter the number of template
129 * parameters of a certain template class within the ROOT type system, TClass.
130 * Technically it allows to alter the way in which the "normalized name" (in
131 * other words, the "ROOT name") of the class is created. The key is the usage
132 * of the @c KeepFirstTemplateArguments traits class.
133 * It is possible to select the maximum number of template arguments considered
134 * if not different from the default. A concrete example can be more clear than
135 * a long explaination in this case:
136 * @code
137 * [...]
138 * template <class T, class U = int, int V = 3> class A {...};
139 * template <class T, class Alloc = myAllocator<T> > class myVector {...};
140 * A<char> a1;
141 * A<char, float> a2;
142 * myVector<float> v1;
143 * myVector<A<char>> v2;
144 *
145 * namespace ROOT {
146 * namespace Meta {
147 * namespace Selection {
148 * template <class T, class U = int, int V = 3> class A
149 * : KeepFirstTemplateArguments<1> {};
150 * A<double> a;
151 * template <class T, class Alloc = myAllocator<T> > class myVector
152 * : KeepFirstTemplateArguments<1> {};
153 * myVector<double> vd;
154 * }
155 * }
156 * }
157 * @endcode
158 *
159 * Consistently with what described above, all the instances of @c A and
160 * @c myvector will be selected. In addition, only the first template parameter
161 * will be kept.
162 * In absence of any @c KeepFirstTemplateArguments trait, the normalization
163 * would be:
164 * - @c A<char> &rarr; @c A<char,float,3>
165 * - @c A<char,float> &rarr; @c A<char,int,3>
166 * - @c myVector<float> &rarr; @c myVector<A<char,int,3>,myAllocator<A<char,int,3>>>
167 * - @c myVector<A<char>> &rarr; @c myVector<float,myAllocator<float>>
168 *
169 * Now, deciding to keep just one argument (@c KeepFirstTemplateArguments<1>):
170 * - @c A<char> &rarr; @c A<char,float>
171 * - @c A<char,float> &rarr; @c A<char>
172 * - @c myVector<float> &rarr; @c myVector<A<char>,myAllocator<A<char>>>
173 * - @c myVector<A<char>> &rarr; @c myVector<float,myAllocator<float>>
174 *
175 * And deciding to keep two arguments (@c KeepFirstTemplateArguments<2>):
176 * - @c A<char> &rarr; @c A<char,float>
177 * - @c A<char,float> &rarr; @c A<char,int>
178 * - @c myVector<float> &rarr; @c myVector<A<char,int>,myAllocator<A<char,int>>>
179 * - @c myVector<A<char>> &rarr; @c myVector<float,myAllocator<float>>
180 *
181 * A brief description of the properties that can be assigned to data members
182 * with the @c ROOT::Meta::Selection MemberAttributes class:
183 * 1. @c kTransient : the data member is transient, not persistified by the
184 * ROOT I/O.
185 * 2. @c kAutoSelected : the type of the data member is selected without the
186 * need of specifying its class explicitely.
187 *
188 * For example:
189 * @code
190 * [...]
191 * class classTransientMember {
192 * private:
193 * int transientMember;
194 * };
195 * class classAutoselected {};
196 * class classTestAutoselect {
197 * private:
198 * classAutoselected autoselected;
199 * };
200 *
201 * namespace ROOT {
202 * namespace Meta {
203 * namespace Selection {
204 * class classTestAutoselect {
205 * MemberAttributes<kAutoSelected> autoselected;
206 * };
207 * class classTransientMember {
208 * MemberAttributes<kTransient> transientMember;
209 * };
210 * }
211 * }
212 * }
213 * @endcode
214 * would lead to the creation of selection rules for @c classTransientMember
215 * specifying that @c transientMember is transient, @c classTestAutoselect and
216 * @c classAutoselected.
217 *
218 * Another trait class present in the @c ROOT::Meta::Selection is
219 * @c SelectNoInstance. If a template in the selection namespace inherits from
220 * this class, none of its instantiations will be automatically selected but
221 * all of the properties specified otherwise, like transient members or
222 * number of template arguments to keep, will be transmitted to all of the
223 * instantiations selected by other means.
224 * For example
225 * @code
226 * [...]
227 * template< class T, class BASE >
228 * class MyDataVector : KeepFirstTemplateArguments< 1 >, SelectNoInstance {
229 * MemberAttributes< kTransient + kAutoSelected > m_isMostDerived;
230 * MemberAttributes< kNonSplittable + kAutoSelected > m_isNonSplit;
231 * };
232 * [...]
233 * @endcode
234 **/
235namespace ROOT {
236namespace Internal {
237
238class DictSelectionReader : public clang::RecursiveASTVisitor<DictSelectionReader> {
239public:
240 /// Take the selection rules as input (for consistency w/ other selector
241 /// interfaces)
242 DictSelectionReader(cling::Interpreter &interp, SelectionRules &, const clang::ASTContext &,
244
245 /// Visit the entities that needs to be selected
246 bool VisitRecordDecl(clang::RecordDecl *);
247
249 return true;
250 }
251
252private:
253
254
255 struct TemplateInfo { /// < Class to store the information about templates upon parsing
256 TemplateInfo(int argsToKeep): fArgsToKeep(argsToKeep) {};
258 int fArgsToKeep = -1;
259 std::unordered_set<std::string> fTransientMembers {};
260 std::unordered_set<std::string> fUnsplittableMembers {};
261 };
262
263 inline bool
264 InSelectionNamespace(const clang::RecordDecl &,
265 const std::string &str =
266 ""); ///< Check if in the ROOT::Meta::Selection namespace
267 inline bool FirstPass(const clang::RecordDecl &); ///< First pass on the AST
268 inline bool SecondPass(const clang::RecordDecl &); ///< Second pass on the AST, using the information of the first one
269 inline void
270 ManageFields(const clang::RecordDecl &,
271 const std::string &,
273 bool); ///< Take care of the class fields
274 inline void
275 ManageBaseClasses(const clang::CXXRecordDecl &, const std::string &, bool &); ///< Take care of the class bases
276 template <class T>
277 inline unsigned int ExtractTemplateArgValue(
278 const T &,
279 const std::string &); ///< Extract the value of the template parameter
280 inline const clang::TemplateArgumentList *GetTmplArgList(
281 const clang::CXXRecordDecl &); ///< Get the template arguments list if any
282
283 std::string PatternifyName(const std::string &className); ///< Transform instance name in pattern for selection
284 void GetPointeeType(std::string &typeName); ///< Get name of the pointee type
285
286 SelectionRules &fSelectionRules; ///< The selection rules to be filled
287 std::set<const clang::RecordDecl *>
288 fSelectedRecordDecls; ///< The pointers of the selected RecordDecls
289 std::set<std::string>
290 fSpecialNames; ///< The names of the classes used for the selction syntax
291 llvm::StringMap<std::set<std::string> >
292 fAutoSelectedClassFieldNames; ///< Collect the autoselected classes
293 llvm::StringMap<std::set<std::string> >
294 fNoAutoSelectedClassFieldNames; ///< Collect the autoexcluded classes
295 std::unordered_map<std::string, TemplateInfo> fTemplateInfoMap; ///< List template name - properties map
296 llvm::StringMap<ClassSelectionRule>
297 fClassNameSelectionRuleMap; ///< Map of the already built sel rules
298 bool fIsFirstPass; ///< Keep trance of the number of passes through the AST
299 ROOT::TMetaUtils::TNormalizedCtxt &fNormCtxt; ///< The reference to the normalized context
300};
301}
302}
303
304#endif
bool fIsFirstPass
Keep trance of the number of passes through the AST.
llvm::StringMap< ClassSelectionRule > fClassNameSelectionRuleMap
Map of the already built sel rules.
void ManageFields(const clang::RecordDecl &, const std::string &, ClassSelectionRule &, bool)
Take care of the class fields.
ROOT::TMetaUtils::TNormalizedCtxt & fNormCtxt
The reference to the normalized context.
llvm::StringMap< std::set< std::string > > fNoAutoSelectedClassFieldNames
Collect the autoexcluded classes.
llvm::StringMap< std::set< std::string > > fAutoSelectedClassFieldNames
Collect the autoselected classes.
void ManageBaseClasses(const clang::CXXRecordDecl &, const std::string &, bool &)
Take care of the class bases.
bool VisitRecordDecl(clang::RecordDecl *)
Visit the entities that needs to be selected.
const clang::TemplateArgumentList * GetTmplArgList(const clang::CXXRecordDecl &)
Get the template arguments list if any.
std::set< const clang::RecordDecl * > fSelectedRecordDecls
The pointers of the selected RecordDecls.
std::string PatternifyName(const std::string &className)
Transform instance name in pattern for selection.
std::set< std::string > fSpecialNames
The names of the classes used for the selction syntax.
SelectionRules & fSelectionRules
The selection rules to be filled.
void GetPointeeType(std::string &typeName)
Get name of the pointee type.
unsigned int ExtractTemplateArgValue(const T &, const std::string &)
Extract the value of the template parameter.
bool InSelectionNamespace(const clang::RecordDecl &, const std::string &str="")
Check if in the ROOT::Meta::Selection namespace.
std::unordered_map< std::string, TemplateInfo > fTemplateInfoMap
List template name - properties map.
bool FirstPass(const clang::RecordDecl &)
First pass on the AST.
bool SecondPass(const clang::RecordDecl &)
Second pass on the AST, using the information of the first one.
The class representing the collection of selection rules.
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
std::unordered_set< std::string > fUnsplittableMembers
std::unordered_set< std::string > fTransientMembers
TemplateInfo(int argsToKeep)
< Class to store the information about templates upon parsing