From 84d2e4fbd4b518c45d5b088ded3d09a11ed03d94 Mon Sep 17 00:00:00 2001 From: Javier Lopez-Gomez Date: Thu, 15 Aug 2019 11:05:42 +0200 Subject: [PATCH] Fix the `.g' metacommand: take as global anything reachable from the TU --- lib/MetaProcessor/Display.cpp | 72 ++++++++++++++++------------------- 1 file changed, 33 insertions(+), 39 deletions(-) diff --git a/lib/MetaProcessor/Display.cpp b/lib/MetaProcessor/Display.cpp index 9267bb8c..0d4e21a4 100644 --- a/lib/MetaProcessor/Display.cpp +++ b/lib/MetaProcessor/Display.cpp @@ -1084,6 +1084,8 @@ public: void DisplayGlobal(const std::string& name)const; private: + template + 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 +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(*decl)) { + if (NS->isInlineNamespace()) // Recursively visit inline namespaces + count += DisplayDCDecls(NS, filter_func, args...); + } else if (const auto VD = dyn_cast(*decl)) { + if (filter_func(VD, args...)) + DisplayVarDecl(VD), count++; + } else if (auto ED = dyn_cast(*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(*decl)) - DisplayVarDecl(varDecl); - else if (const EnumDecl* enumDecl = dyn_cast(*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(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(*decl)) { - if (varDecl->getNameAsString() == name) { - DisplayVarDecl(varDecl); - found = true; - } - } else if (const EnumDecl* enumDecl = dyn_cast(*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()); }