24 #include "TClingUtils.h"
30 #include "clang/Basic/SourceLocation.h"
31 #include "clang/Basic/SourceManager.h"
32 #include "clang/AST/DeclCXX.h"
33 #include "clang/AST/ASTContext.h"
34 #include "clang/AST/DeclTemplate.h"
41 static const char *R__GetDeclSourceFileName(
const clang::Decl* D)
43 clang::ASTContext& ctx = D->getASTContext();
44 clang::SourceManager& SM = ctx.getSourceManager();
45 clang::SourceLocation SL = D->getLocation();
50 SL = SM.getExpansionLoc(SL);
52 if (SL.isValid() && SL.isFileID()) {
53 clang::PresumedLoc PLoc = SM.getPresumedLoc(SL);
54 return PLoc.getFilename();
61 static bool R__match_filename(
const char *srcname,
const char *filename)
66 if((strcmp(srcname,filename)==0)) {
71 char i1name[_MAX_PATH];
72 char fullfile[_MAX_PATH];
73 _fullpath( i1name, srcname, _MAX_PATH );
74 _fullpath( fullfile, filename, _MAX_PATH );
75 if((stricmp(i1name, fullfile)==0))
return 1;
77 struct stat statBufItem;
79 if ( ( 0 == stat( filename, & statBufItem ) )
80 && ( 0 == stat( srcname, & statBuf ) )
81 && ( statBufItem.st_dev == statBuf.st_dev )
82 && ( statBufItem.st_ino == statBuf.st_ino )
83 && ( statBufItem.st_size == statBuf.st_size )
84 && ( statBufItem.st_mtime == statBuf.st_mtime )
92 BaseSelectionRule::BaseSelectionRule(
long index, BaseSelectionRule::ESelect sel,
const std::string& attributeName,
const std::string& attributeValue, cling::Interpreter &interp,
const char* selFileName,
long lineno)
93 : fIndex(index),fLineNumber(lineno),fSelFileName(selFileName),fIsSelected(sel),fMatchFound(false),fCXXRecordDecl(0),fRequestedType(0),fInterp(&interp)
95 fAttributes.insert(AttributesMap_t::value_type(attributeName, attributeValue));
98 void BaseSelectionRule::SetSelected(BaseSelectionRule::ESelect sel)
103 BaseSelectionRule::ESelect BaseSelectionRule::GetSelected()
const
108 bool BaseSelectionRule::HasAttributeWithName(
const std::string& attributeName)
const
110 AttributesMap_t::const_iterator iter = fAttributes.find(attributeName);
112 if(iter!=fAttributes.end())
return true;
116 bool BaseSelectionRule::GetAttributeValue(
const std::string& attributeName, std::string& returnValue)
const
118 AttributesMap_t::const_iterator iter = fAttributes.find(attributeName);
120 bool retVal = iter!=fAttributes.end();
121 returnValue = retVal ? iter->second :
"";
125 void BaseSelectionRule::SetAttributeValue(
const std::string& attributeName,
const std::string& attributeValue)
128 std::string localAttributeValue(attributeValue);
130 int pos = attributeName.find(
"pattern");
131 int pos_file = attributeName.find(
"file_pattern");
134 if (attributeName ==
"name" || pos> -1){
135 while(std::isspace(*localAttributeValue.begin())) localAttributeValue.erase(localAttributeValue.begin());
136 while(std::isspace(*localAttributeValue.rbegin()))localAttributeValue.erase(localAttributeValue.length()-1);
138 fAttributes.insert(AttributesMap_t::value_type(attributeName, localAttributeValue));
142 ProcessPattern(localAttributeValue, fFileSubPatterns);
143 else ProcessPattern(localAttributeValue, fSubPatterns);
150 const BaseSelectionRule::AttributesMap_t& BaseSelectionRule::GetAttributes()
const
155 void BaseSelectionRule::DebugPrint()
const
160 void BaseSelectionRule::PrintAttributes(std::ostream &out,
int level)
const
163 for (
int i = 0; i < level; ++i) {
167 if (!fAttributes.empty()) {
168 std::map<std::string,std::string> orderedAttributes(fAttributes.begin(),fAttributes.end());
169 for (
auto&& attr : orderedAttributes) {
170 out<<tabs<<attr.first<<
" = "<<attr.second<<std::endl;
174 out<<tabs<<
"No attributes"<<std::endl;
178 void BaseSelectionRule::PrintAttributes(
int level)
const
180 PrintAttributes(std::cout, level);
185 BaseSelectionRule::EMatchType BaseSelectionRule::Match(
const clang::NamedDecl *decl,
186 const std::string& name,
187 const std::string& prototype,
188 bool isLinkdef)
const
207 const std::string& name_value = fName;
208 const std::string& pattern_value = fPattern;
211 const clang::CXXRecordDecl *D = llvm::dyn_cast<clang::CXXRecordDecl>(decl);
212 bool isTypedefNametoRecordDecl =
false;
216 const clang::TypedefNameDecl* typedefNameDecl = llvm::dyn_cast<clang::TypedefNameDecl> (decl);
217 isTypedefNametoRecordDecl = typedefNameDecl &&
218 ROOT::TMetaUtils::GetUnderlyingRecordDecl(typedefNameDecl->getUnderlyingType());
221 if (! isTypedefNametoRecordDecl && fCXXRecordDecl !=0 && fCXXRecordDecl != (
void*)-1) {
222 const clang::CXXRecordDecl *target = fCXXRecordDecl;
223 if ( target && D && target == D ) {
225 const_cast<BaseSelectionRule*
>(
this)->SetMatchFound(
true);
228 }
else if (fHasNameAttribute) {
229 if (name_value == name) {
230 const_cast<BaseSelectionRule*
>(
this)->SetMatchFound(
true);
232 }
else if (fCXXRecordDecl ==
nullptr ||
233 (fCXXRecordDecl != (
void*)-1 && isTypedefNametoRecordDecl && !decl->hasOwningModule())){
236 const clang::CXXRecordDecl *target
237 = fHasFromTypedefAttribute ?
nullptr : ROOT::TMetaUtils::ScopeSearch(name_value.c_str(), *fInterp,
241 const_cast<BaseSelectionRule*
>(
this)->fCXXRecordDecl = target;
244 const_cast<BaseSelectionRule*
>(
this)->fCXXRecordDecl = (clang::CXXRecordDecl*)-1;
246 if ( target && D && target == D ) {
247 const_cast<BaseSelectionRule*
>(
this)->SetMatchFound(
true);
254 const std::string& file_name_value = fFileName;
255 const std::string& file_pattern_value = fFilePattern;
257 if ((fHasFileNameAttribute||fHasFilePatternAttribute)) {
258 const char *file_name = R__GetDeclSourceFileName(decl);
259 bool hasFileMatch = ((fHasFileNameAttribute &&
261 (R__match_filename(file_name_value.c_str(),file_name))) ||
262 (fHasFilePatternAttribute && CheckPattern(file_name, file_pattern_value, fFileSubPatterns, isLinkdef)));
267 if (!strncmp(name.c_str(),
"R__Init", 7) ||
268 strstr(name.c_str(),
"::R__Init")) {
271 if (!name.compare(0, 24,
"ROOT::R__dummyintdefault")) {
274 if (!name.compare(0, 27,
"ROOT::R__dummyVersionNumber")) {
277 if (!name.compare(0, 22,
"ROOT::R__dummyStreamer")) {
280 if (name.find(
"(anonymous namespace)") != std::string::npos) {
284 if (fHasPatternAttribute) {
285 if (CheckPattern(name, pattern_value, fSubPatterns, isLinkdef)) {
286 const_cast<BaseSelectionRule*
>(
this)->SetMatchFound(
true);
290 const_cast<BaseSelectionRule*
>(
this)->SetMatchFound(
true);
300 if (fHasPatternAttribute)
302 bool patternMatched = CheckPattern(name, pattern_value, fSubPatterns, isLinkdef);
303 if (!patternMatched && !isLinkdef) {
304 std::string auxName(name);
305 std::string &nameNoSpaces = auxName;
306 nameNoSpaces.erase(std::remove_if(nameNoSpaces.begin(), nameNoSpaces.end(), isspace),
308 if (name.size() != nameNoSpaces.size()) {
309 patternMatched = CheckPattern(nameNoSpaces, pattern_value, fSubPatterns, isLinkdef);
319 if (!patternMatched &&
322 0 != TClassEdit::IsSTLCont(name)) {
323 TClassEdit::GetNormalizedName(auxName, name);
324 if (name.size() != auxName.size()) {
325 auxName = TClassEdit::InsertStd(auxName.c_str());
326 patternMatched = CheckPattern(auxName, pattern_value, fSubPatterns, isLinkdef);
331 if (patternMatched) {
332 const_cast<BaseSelectionRule *
>(
this)->SetMatchFound(
true);
351 if (!prototype.empty()) {
352 if (fHasProtoNameAttribute && fProtoName==prototype) {
353 const_cast<BaseSelectionRule*
>(
this)->SetMatchFound(
true);
356 if (fHasProtoPatternAttribute && CheckPattern(prototype, fProtoPattern, fSubPatterns, isLinkdef)) {
357 const_cast<BaseSelectionRule*
>(
this)->SetMatchFound(
true);
373 void BaseSelectionRule::ProcessPattern(
const std::string& pattern, std::list<std::string>& out)
const
375 std::string temp = pattern;
380 if (pattern.size()==1 && pattern ==
"*"){
385 while (!temp.empty()){
386 pos = temp.find(
"*");
394 out.push_back(split);
400 temp = temp.substr(1);
402 else if (pos == (
int)(temp.length()-1)) {
403 if (pos > 0 && temp.at(pos-1) ==
'\\') {
404 split += temp.substr(0, temp.length()-2);
405 split += temp.at(pos);
406 out.push_back(split);
410 temp = temp.substr(0, (temp.length()-1));
413 if (pos > 0 && temp.at(pos-1) ==
'\\') {
414 split += temp.substr(0, pos-1);
415 split += temp.at(pos);
419 temp = temp.substr(pos);
424 split += temp.substr(0, pos);
427 split = temp.substr(0, pos);
430 temp = temp.substr(pos);
431 out.push_back(split);
445 bool BaseSelectionRule::CheckPattern(
const std::string& test,
const std::string& pattern,
const std::list<std::string>& patterns_list,
bool isLinkdef)
const
447 bool begin = pattern.front() ==
'*';
448 if (pattern.size() == 1 && begin) {
453 std::list<std::string>::const_iterator it = patterns_list.begin();
454 size_t pos1, pos2, pos3;
455 pos1= pos2= pos3= std::string::npos;
456 bool end = pattern.back() ==
'*';
459 const std::string& last = patterns_list.back();
460 size_t pos_end = test.rfind(last);
462 if (pos_end == std::string::npos) {
468 int len = last.length();
469 if ((pos_end+len) < test.length()) {
475 pos1 = test.find(*it);
478 if (pos1 == std::string::npos || (!begin && pos1 != 0)) {
486 int len = (*it).length();
487 int pos_colon = test.find(
"::", pos1+len);
489 if (pos_colon > -1) {
495 if (patterns_list.size() > 1) {
496 if (((*it).length())+pos1 > pos_end) {
505 for (; it != patterns_list.end(); ++it) {
507 pos2 = test.find(*it);
518 void BaseSelectionRule::SetMatchFound(
bool match)
523 bool BaseSelectionRule::GetMatchFound()
const
528 const clang::Type *BaseSelectionRule::GetRequestedType()
const
530 return fRequestedType;
533 void BaseSelectionRule::SetCXXRecordDecl(
const clang::CXXRecordDecl *decl,
const clang::Type *typeptr)
535 fCXXRecordDecl = decl;
536 fRequestedType = typeptr;
539 void BaseSelectionRule::FillCache()
542 fHasNameAttribute = GetAttributeValue(
"name",fName);
543 fHasProtoNameAttribute = GetAttributeValue(
"proto_name",fProtoName);
544 fHasPatternAttribute = GetAttributeValue(
"pattern",fPattern);
545 fHasProtoPatternAttribute = GetAttributeValue(
"proto_pattern",fProtoPattern);
546 fHasFileNameAttribute = GetAttributeValue(
"file_name",fFileName);
547 fHasFilePatternAttribute = GetAttributeValue(
"file_pattern",fFilePattern);
548 fHasFromTypedefAttribute = GetAttributeValue(
"fromTypedef",value);
549 fIsFromTypedef = (value ==
"true");
551 GetAttributeValue(ROOT::TMetaUtils::propNames::nArgsToKeep,fNArgsToKeep);
554 if (fHasPatternAttribute || fHasProtoPatternAttribute) {
555 if (fSubPatterns.empty()) {
556 std::cout<<
"Error - A pattern selection without sub patterns." <<std::endl;