Logo ROOT  
Reference Guide
TClingMemberIter.cxx
Go to the documentation of this file.
1// @(#)root/core/meta:$Id$
2// Author: Axel Naumann 2020-08-25
3
4/*************************************************************************
5 * Copyright (C) 1995-2020, 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/CREDITS. *
10 *************************************************************************/
11
12#include "TClingMemberIter.h"
13
14#include "cling/Interpreter/Interpreter.h"
15#include "cling/Interpreter/LookupHelper.h"
16
17#include "clang/AST/DeclTemplate.h"
18
19ClingMemberIterInternal::DCIter::DCIter(clang::DeclContext *DC, cling::Interpreter *interp) : fInterp(interp)
20{
21 cling::Interpreter::PushTransactionRAII RAII(fInterp);
22 DC->collectAllContexts(fContexts);
23 fDeclIter = fContexts[0]->decls_begin();
24 // Skip initial empty decl contexts.
25 while (IsValid() && fDeclIter == fContexts[fDCIdx]->decls_end()) {
26 ++fDCIdx;
27 if (fDCIdx < fContexts.size())
28 fDeclIter = fContexts[fDCIdx]->decls_begin();
29 else
30 fDeclIter = fContexts.back()->decls_end();
31 }
33}
34
36{
37 if (auto *NSD = llvm::dyn_cast<clang::NamespaceDecl>(*fDeclIter)) {
38 if (NSD->isInlineNamespace() || NSD->isAnonymousNamespace()) {
39 // Collect e.g. internal `__cling_N5xxx' inline namespaces; they will be traversed later
40 // Top-most inline namespaces are folded into the iteration:
41 fContexts.push_back(NSD);
42 return true;
43 }
44 } else if (auto *ED = llvm::dyn_cast<clang::EnumDecl>(*fDeclIter)) {
45 if (!ED->isScoped()) {
46 // Inline enums folded into the iteration:
47 fContexts.push_back(ED);
48 return true;
49 }
50 } else if (auto *RD = llvm::dyn_cast<clang::RecordDecl>(*fDeclIter)) {
51 if (RD->isAnonymousStructOrUnion()) {
52 // Anonymous unions are folded into the iteration:
53 fContexts.push_back(RD);
54 return true;
55 }
56 }
57 return false;
58}
59
61{
62 if (!IsValid())
63 return false;
64
65 while (HandleInlineDeclContext())
66 if (!IterNext())
67 return false;
68
69 return true;
70}
71
73{
74 ++fDeclIter;
75 while (fDeclIter == fContexts[fDCIdx]->decls_end()) {
76 ++fDCIdx;
77 if (fDCIdx == fContexts.size())
78 return false;
79 cling::Interpreter::PushTransactionRAII RAII(fInterp);
80 fDeclIter = fContexts[fDCIdx]->decls_begin();
81 }
82 return true;
83}
84
86{
87 IterNext();
88 return AdvanceToFirstValidDecl();
89}
90
91ClingMemberIterInternal::UsingDeclIter::UsingDeclIter(const clang::UsingDecl *UD, cling::Interpreter *interp)
92 : fInterp(interp)
93{
94 cling::Interpreter::PushTransactionRAII RAII(interp);
95 fUsingIterStack.push({UD});
96}
97
99{
100 ++Iter();
101 while (true) {
102 if (Iter() == End()) {
103 // End of this UD's loop; continue iteration with parent.
104 fUsingIterStack.pop();
105 if (fUsingIterStack.empty())
106 return false;
107 ++Iter(); // parent was the UsingDecl we just finished, move to next.
108 continue;
109 }
110 if (auto *UD = llvm::dyn_cast<clang::UsingDecl>(Iter()->getTargetDecl())) {
111 if (UD->shadow_size()) {
112 cling::Interpreter::PushTransactionRAII RAII(fInterp);
113 fUsingIterStack.push({UD});
114 // Continue with child.
115 }
116 } else {
117 break;
118 }
119 };
120 return true;
121}
122
124{
125 fTemplateSpec = nullptr;
126 do {
127 const clang::Decl *D = Get();
128 if (auto *UD = llvm::dyn_cast<clang::UsingDecl>(D)) {
129 if (UD->shadow_size()) {
130 assert(!fUsingDeclIter.IsValid() && "Expected UsingDecl to be already handled by UsingDeclIter!");
131 AdvanceUnfiltered();
132 fUsingDeclIter = ClingMemberIterInternal::UsingDeclIter(UD, fInterp);
133 continue;
134 }
135 }
136 if (auto *USD = llvm::dyn_cast<clang::UsingShadowDecl>(D)) {
137 if (!ShouldSkip(USD))
138 return true;
139 } else if (auto *RTD = llvm::dyn_cast<clang::RedeclarableTemplateDecl>(D)) {
140 if (const clang::Decl *DInst = InstantiateTemplateWithDefaults(RTD)) {
141 fTemplateSpec = DInst;
142 return true;
143 }
144 } else if (!ShouldSkip(D))
145 return true;
146
147 // Not interested in this one, continue.
148 if (!AdvanceUnfiltered())
149 break;
150 } while (true);
151 return false;
152}
llvm::SmallVector< clang::DeclContext *, 2 > fContexts
bool AdvanceToFirstValidDecl()
Do not return inline namespaces etc.
bool IterNext()
Increment the iterator, possibly moving to the next context.
clang::DeclContext::decl_iterator fDeclIter
bool HandleInlineDeclContext()
Return true if fDeclIter has triggered an inline or anonymous namespace / ... to be appended to fCont...
std::stack< UsingDeclFrame > fUsingIterStack
Handle nested UsingDecls:
void End()