Fix the `.g' metacommand: take as global anything reachable from the TU

This commit is contained in:
Javier Lopez-Gomez 2019-08-15 11:05:42 +02:00 committed by SFT
parent d02353c10b
commit 84d2e4fbd4

View File

@ -1084,6 +1084,8 @@ public:
void DisplayGlobal(const std::string& name)const;
private:
template <typename T, typename... Args>
unsigned DisplayDCDecls(const DeclContext *DC, T filter_func, Args... args) const;
void DisplayVarDecl(const VarDecl* varDecl)const;
void DisplayEnumeratorDecl(const EnumConstantDecl* enumerator)const;
@ -1103,10 +1105,33 @@ GlobalsPrinter::GlobalsPrinter(llvm::raw_ostream& stream, const cling::Interpret
assert(interpreter != 0 && "GlobalsPrinter, 'compiler' parameter is null");
}
//______________________________________________________________________________
template <typename T, typename... Args>
unsigned GlobalsPrinter::DisplayDCDecls(const DeclContext *DC, T filter_func, Args... args) const
{
unsigned count = 0;
for (auto decl = DC->decls_begin(); decl != DC->decls_end(); ++decl) {
if (const auto NS = dyn_cast<NamespaceDecl>(*decl)) {
if (NS->isInlineNamespace()) // Recursively visit inline namespaces
count += DisplayDCDecls(NS, filter_func, args...);
} else if (const auto VD = dyn_cast<VarDecl>(*decl)) {
if (filter_func(VD, args...))
DisplayVarDecl(VD), count++;
} else if (auto ED = dyn_cast<EnumDecl>(*decl)) {
// Timur.Pocheptsov: it's not really clear, if I should really check this:
if (ED->isComplete() && (ED = ED->getDefinition())) {
for (auto I = ED->enumerator_begin(); I != ED->enumerator_end(); ++I)
if (filter_func(*I, args...))
DisplayEnumeratorDecl(*I), count++;
}
}
}
return count;
}
//______________________________________________________________________________
void GlobalsPrinter::DisplayGlobals()const
{
typedef EnumDecl::enumerator_iterator enumerator_iterator;
typedef Preprocessor::macro_iterator macro_iterator;
assert(fInterpreter != 0 && "DisplayGlobals, fInterpreter is null");
@ -1135,24 +1160,12 @@ void GlobalsPrinter::DisplayGlobals()const
//It's obviously that for objects we can have one definition and any number
//of declarations, should I print them?
for (decl_iterator decl = tuDecl->decls_begin(); decl != tuDecl->decls_end(); ++decl) {
if (const VarDecl* const varDecl = dyn_cast<VarDecl>(*decl))
DisplayVarDecl(varDecl);
else if (const EnumDecl* enumDecl = dyn_cast<EnumDecl>(*decl)) {
//it's not really clear, if I should really check this:
if (enumDecl->isComplete() && (enumDecl = enumDecl->getDefinition())) {
for (enumerator_iterator enumerator = enumDecl->enumerator_begin();
enumerator != enumDecl->enumerator_end(); ++enumerator)
DisplayEnumeratorDecl(*enumerator);
}
}
}
DisplayDCDecls(tuDecl, [] (NamedDecl *D) { return true; });
}
//______________________________________________________________________________
void GlobalsPrinter::DisplayGlobal(const std::string& name)const
{
typedef EnumDecl::enumerator_iterator enumerator_iterator;
typedef Preprocessor::macro_iterator macro_iterator;
//TODO: is it ok to compare 'name' with decl->getNameAsString() ??
@ -1165,7 +1178,7 @@ void GlobalsPrinter::DisplayGlobal(const std::string& name)const
const TranslationUnitDecl* const tuDecl = compiler->getASTContext().getTranslationUnitDecl();
assert(tuDecl != 0 && "DisplayGlobal, translation unit is empty");
bool found = false;
unsigned count = 0;
// Could trigger deserialization of decls.
Interpreter::PushTransactionRAII RAII(const_cast<Interpreter*>(fInterpreter));
@ -1176,35 +1189,16 @@ void GlobalsPrinter::DisplayGlobal(const std::string& name)const
continue;
auto MI = MD->getMacroInfo();
if (MI && MI->isObjectLike()) {
if (name == macro->first->getName().data()) {
DisplayObjectLikeMacro(macro->first, MI);
found = true;
}
if (name == macro->first->getName().data())
DisplayObjectLikeMacro(macro->first, MI), count++;
}
}
for (decl_iterator decl = tuDecl->decls_begin(); decl != tuDecl->decls_end(); ++decl) {
if (const VarDecl* const varDecl = dyn_cast<VarDecl>(*decl)) {
if (varDecl->getNameAsString() == name) {
DisplayVarDecl(varDecl);
found = true;
}
} else if (const EnumDecl* enumDecl = dyn_cast<EnumDecl>(*decl)) {
//it's not really clear, if I should really check this:
if (enumDecl->isComplete() && (enumDecl = enumDecl->getDefinition())) {
for (enumerator_iterator enumerator = enumDecl->enumerator_begin();
enumerator != enumDecl->enumerator_end(); ++enumerator) {
if (enumerator->getNameAsString() == name) {
DisplayEnumeratorDecl(*enumerator);
found = true;
}
}
}
}
}
count += DisplayDCDecls(tuDecl, [&name] (NamedDecl *D)
{ return D->getNameAsString() == name; });
//Do as CINT does:
if (!found)
if (!count)
fOut.Print(("Variable " + name + " not found\n").c_str());
}