3#include "clang/AST/AST.h"
5#include "cling/Interpreter/Interpreter.h"
9#include "TClingUtils.h"
22DictSelectionReader::DictSelectionReader(cling::Interpreter &interp,
SelectionRules &selectionRules,
23 const clang::ASTContext &
C, ROOT::TMetaUtils::TNormalizedCtxt &normCtxt)
24 : fSelectionRules(selectionRules), fIsFirstPass(true), fNormCtxt(normCtxt)
26 clang::TranslationUnitDecl *translUnitDecl =
C.getTranslationUnitDecl();
30 cling::Interpreter::PushTransactionRAII RAII(&interp);
32 TraverseDecl(translUnitDecl);
37 if (!fTemplateInfoMap.empty() ||
38 !fAutoSelectedClassFieldNames.empty() ||
39 !fNoAutoSelectedClassFieldNames.empty())
40 TraverseDecl(translUnitDecl);
43 for (llvm::StringMap<ClassSelectionRule>::iterator it =
44 fClassNameSelectionRuleMap.begin();
45 it != fClassNameSelectionRuleMap.end();
47 fSelectionRules.AddClassSelectionRule(it->second);
63DictSelectionReader::InSelectionNamespace(
const clang::RecordDecl &recordDecl,
64 const std::string &className)
66 std::list<std::pair<std::string, bool> > enclosingNamespaces;
67 ROOT::TMetaUtils::ExtractEnclosingNameSpaces(recordDecl,
70 const unsigned int nNs = enclosingNamespaces.size();
71 if (nNs < 3)
return false;
73 if (enclosingNamespaces.back().second ||
74 enclosingNamespaces.back().first !=
"ROOT")
77 enclosingNamespaces.pop_back();
78 if (enclosingNamespaces.back().second ||
79 enclosingNamespaces.back().first !=
"Meta")
82 enclosingNamespaces.pop_back();
83 if (enclosingNamespaces.back().second ||
84 enclosingNamespaces.back().first !=
"Selection")
88 if (className !=
"" &&
89 (className.find(
"MemberAttributes") == 0 ||
90 className.find(
"ClassAttributes") == 0 || className.find(
"Keep") == 0))
101const clang::TemplateArgumentList *
102DictSelectionReader::GetTmplArgList(
const clang::CXXRecordDecl &cxxRcrdDecl)
104 const clang::ClassTemplateSpecializationDecl *tmplSpecDecl =
105 llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&cxxRcrdDecl);
107 if (!tmplSpecDecl)
return 0;
109 return &tmplSpecDecl->getTemplateArgs();
121DictSelectionReader::ExtractTemplateArgValue(
const T &myClass,
122 const std::string &pattern)
124 const clang::RecordDecl *rcrdDecl =
125 ROOT::TMetaUtils::GetUnderlyingRecordDecl(myClass.getType());
126 const clang::CXXRecordDecl *cxxRcrdDecl =
127 llvm::dyn_cast<clang::CXXRecordDecl>(rcrdDecl);
129 if (!cxxRcrdDecl)
return 0;
131 const clang::TemplateArgumentList *tmplArgs = GetTmplArgList(*cxxRcrdDecl);
132 if (!tmplArgs)
return 0;
134 if (std::string::npos == cxxRcrdDecl->getNameAsString().find(pattern))
137 return tmplArgs->get(0).getAsIntegral().getLimitedValue();
152void DictSelectionReader::ManageFields(
const clang::RecordDecl &recordDecl,
153 const std::string &className,
157 std::string pattern = className.substr(0, className.find_first_of(
"<"));
159 for (
auto fieldPtr : recordDecl.fields()) {
161 unsigned int attrCode =
162 ExtractTemplateArgValue(*fieldPtr,
"MemberAttributes");
166 const char *fieldName = fieldPtr->getName().data();
170 fTemplateInfoMap[pattern].fUnsplittableMembers.insert(fieldName);
174 vsr.SetAttributeValue(ROOT::TMetaUtils::propNames::comment,
"||");
181 fTemplateInfoMap[pattern].fTransientMembers.insert(fieldName);
185 vsr.SetAttributeValue(ROOT::TMetaUtils::propNames::comment,
"!");
191 fAutoSelectedClassFieldNames[className].insert(fieldName);
193 fNoAutoSelectedClassFieldNames[className].insert(fieldName);
217DictSelectionReader::ManageBaseClasses(
const clang::CXXRecordDecl &cxxRcrdDecl,
218 const std::string &className,
221 std::string baseName;
222 clang::ASTContext &
C = cxxRcrdDecl.getASTContext();
223 for (
auto & base : cxxRcrdDecl.bases()) {
225 if (
unsigned int nArgsToKeep = ExtractTemplateArgValue(base,
"Keep")) {
226 std::string pattern =
227 className.substr(0, className.find_first_of(
"<"));
230 fTemplateInfoMap[pattern] = TemplateInfo(nArgsToKeep);
235 auto qt = base.getType();
236 ROOT::TMetaUtils::GetFullyQualifiedTypeName(baseName, qt,
C);
237 if (baseName ==
"ROOT::Meta::Selection::SelectNoInstance") autoselect =
false;
250bool DictSelectionReader::FirstPass(
const clang::RecordDecl &recordDecl)
252 std::string className;
253 ROOT::TMetaUtils::GetQualifiedName(
254 className, *recordDecl.getTypeForDecl(), recordDecl);
257 className.replace(0, 23,
"");
259 if (!InSelectionNamespace(recordDecl, className))
return true;
261 if (!fSelectedRecordDecls.insert(&recordDecl).second)
return true;
263 bool autoselect =
true;
264 if (
auto cxxRcrdDecl = llvm::dyn_cast<clang::CXXRecordDecl>(&recordDecl)) {
265 ManageBaseClasses(*cxxRcrdDecl, className, autoselect);
269 const size_t lWedgePos(className.find_first_of(
"<"));
270 std::string patternName(
"");
271 if (lWedgePos != std::string::npos &&
272 llvm::isa<clang::ClassTemplateSpecializationDecl>(recordDecl)) {
273 patternName = PatternifyName(className);
280 ManageFields(recordDecl, className, csr, autoselect);
282 if (!autoselect)
return true;
285 fClassNameSelectionRuleMap[patternName.empty() ? className : patternName] =
307bool DictSelectionReader::SecondPass(
const clang::RecordDecl &recordDecl)
312 if (InSelectionNamespace(recordDecl))
return true;
314 std::string className;
315 GetQualifiedName(className, *recordDecl.getTypeForDecl(), recordDecl);
319 if (0 != fAutoSelectedClassFieldNames.count(className) ||
320 0 != fNoAutoSelectedClassFieldNames.count(className)) {
323 std::string typeName;
324 clang::ASTContext &
C = recordDecl.getASTContext();
325 for (clang::RecordDecl::field_iterator filedsIt =
326 recordDecl.field_begin();
327 filedsIt != recordDecl.field_end();
329 const std::string fieldName(filedsIt->getNameAsString());
330 bool excluded = 1 == fNoAutoSelectedClassFieldNames[className].count(fieldName);
331 bool selected = 1 == fAutoSelectedClassFieldNames[className].count(fieldName);
332 if (!selected && !excluded)
335 GetFullyQualifiedTypeName(typeName, filedsIt->getType(),
C);
336 GetPointeeType(typeName);
338 fSelectionRules.AddClassSelectionRule(aSelCsr);
346 if (
auto tmplSpecDecl = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(&recordDecl)) {
347 for (
auto & patternInfoPair : fTemplateInfoMap) {
348 const std::string &pattern = patternInfoPair.first;
349 const TemplateInfo &tInfo = patternInfoPair.second;
351 if (className.find(pattern) != 0)
continue;
354 auto ctd = tmplSpecDecl->getSpecializedTemplate();
355 if (tInfo.fArgsToKeep != -1 && ctd) {
356 fNormCtxt.AddTemplAndNargsToKeep(ctd->getCanonicalDecl(), tInfo.fArgsToKeep);
360 if (tInfo.fTransientMembers.empty() && tInfo.fUnsplittableMembers.empty())
continue;
361 clang::ASTContext &
C = recordDecl.getASTContext();
362 clang::SourceRange commentRange;
363 std::string userDefinedProperty;
364 userDefinedProperty.reserve(100);
365 for (
auto fieldPtr : recordDecl.fields()) {
366 const auto fieldName = fieldPtr->getName().data();
367 if (tInfo.fTransientMembers.count(fieldName) == 1) {
368 userDefinedProperty =
"!";
369 }
else if (tInfo.fUnsplittableMembers.count(fieldName) == 1) {
370 userDefinedProperty = propNames::comment + propNames::separator +
"||";
372 if (!userDefinedProperty.empty()) {
373 fieldPtr->addAttr(
new(
C) clang::AnnotateAttr(commentRange,
C, userDefinedProperty, 0));
374 userDefinedProperty =
"";
385bool DictSelectionReader::VisitRecordDecl(clang::RecordDecl *recordDecl)
388 return FirstPass(*recordDecl);
390 return SecondPass(*recordDecl);
400inline std::string DictSelectionReader::PatternifyName(
const std::string &className)
402 return className.substr(0, className.find_first_of(
"<")) +
"<*>";
411inline void DictSelectionReader::GetPointeeType(std::string &typeName)
413 while (typeName[typeName.size() - 1] ==
'*' ||
414 typeName[typeName.size() - 1] ==
'&') {
415 typeName = typeName.substr(0, typeName.size() - 1);
Select classes and assign properties using C++ syntax.
void SetAttributeValue(const std::string &attributeName, const std::string &attributeValue)
void AddFieldSelectionRule(const VariableSelectionRule &field)
The class representing the collection of selection rules.