diff --git a/lib/Interpreter/CIFactory.cpp b/lib/Interpreter/CIFactory.cpp index 0368a116..a18eea5b 100644 --- a/lib/Interpreter/CIFactory.cpp +++ b/lib/Interpreter/CIFactory.cpp @@ -726,6 +726,7 @@ namespace cling { stateCollector = new DeclCollector(); // Set up the ASTConsumers CI->setASTConsumer(stateCollector); + CI->getASTContext().setASTMutationListener(stateCollector); // Set up Sema CodeCompleteConsumer* CCC = 0; diff --git a/lib/Interpreter/DeclCollector.cpp b/lib/Interpreter/DeclCollector.cpp index 0f064969..41cd7a1c 100644 --- a/lib/Interpreter/DeclCollector.cpp +++ b/lib/Interpreter/DeclCollector.cpp @@ -31,9 +31,25 @@ namespace cling { return D->isFromASTFile(); } + bool DeclCollector::comesFromASTReader(const Decl* D) const { + // The operation is const but clang::DeclGroupRef doesn't allow us to + // express it. + return comesFromASTReader(DeclGroupRef(const_cast(D))); + } + // pin the vtable here. DeclCollector::~DeclCollector() { } + void DeclCollector::AddedCXXImplicitMember(const CXXRecordDecl *RD, + const Decl *D) { + assert(D->isImplicit()); + // We need to mark the decls coming from the modules + if (comesFromASTReader(RD) || comesFromASTReader(D)) { + Decl* implicitD = const_cast(D); + implicitD->addAttr(UsedAttr::CreateImplicit(implicitD->getASTContext())); + } + } + bool DeclCollector::HandleTopLevelDecl(DeclGroupRef DGR) { Transaction::DelayCallInfo DCI(DGR, Transaction::kCCIHandleTopLevelDecl); m_CurTransaction->append(DCI); diff --git a/lib/Interpreter/DeclCollector.h b/lib/Interpreter/DeclCollector.h index 504e6b09..23c4d349 100644 --- a/lib/Interpreter/DeclCollector.h +++ b/lib/Interpreter/DeclCollector.h @@ -11,6 +11,7 @@ #define CLING_DECL_COLLECTOR_H #include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTMutationListener.h" #include "clang/Lex/PPCallbacks.h" namespace clang { @@ -32,7 +33,9 @@ namespace cling { /// cling::DeclCollector is responsible for appending all the declarations /// seen by clang. /// - class DeclCollector: public clang::PPCallbacks, public clang::ASTConsumer { + class DeclCollector: public clang::PPCallbacks, + public clang::ASTMutationListener, + public clang::ASTConsumer { private: Transaction* m_CurTransaction; @@ -40,11 +43,23 @@ namespace cling { /// file. /// bool comesFromASTReader(clang::DeclGroupRef DGR) const; + bool comesFromASTReader(const clang::Decl* D) const; public: DeclCollector() : m_CurTransaction(0){} virtual ~DeclCollector(); + /// \name PPCallbacks overrides + /// Macro support + virtual void MacroDefined(const clang::Token &MacroNameTok, + const clang::MacroDirective *MD); + /// \} + + /// \name ASTMutationListeners overrides + virtual void AddedCXXImplicitMember(const clang::CXXRecordDecl *RD, + const clang::Decl *D); + /// \} + /// \{ /// \name ASTConsumer overrides @@ -71,9 +86,6 @@ namespace cling { /// \} - /// Macro support - virtual void MacroDefined (const clang::Token &MacroNameTok, - const clang::MacroDirective *MD); // dyn_cast/isa support static bool classof(const clang::ASTConsumer*) { return true; } }; diff --git a/lib/Interpreter/TransactionUnloader.cpp b/lib/Interpreter/TransactionUnloader.cpp index 8ed09280..c369695e 100644 --- a/lib/Interpreter/TransactionUnloader.cpp +++ b/lib/Interpreter/TransactionUnloader.cpp @@ -64,6 +64,7 @@ namespace clang { Changed |= RemoveUnusedGlobalValue(*GV); // Collect all uses of globals by GV CollectAllUsesOfGlobals(GV); + FindUsedValues(*GV->getParent()); // The first pass is to drop initializers of global vars which are dead. for (Globals::iterator I = VisitedGlobals.begin(), @@ -108,6 +109,24 @@ namespace clang { } private: + + /// Find values that are marked as llvm.used. + void FindUsedValues(const llvm::Module& m) { + for (const llvm::GlobalVariable& GV : m.globals()) { + if (!GV.getName().startswith("llvm.used")) + continue; + + const llvm::ConstantArray* Inits + = cast(GV.getInitializer()); + + for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i) { + llvm::Value *Operand + = Inits->getOperand(i)->stripPointerCastsNoFollowAliases(); + VisitedGlobals.erase(cast(Operand)); + } + + } + } /// CollectAllUsesOfGlobals - collects recursively all referenced globals by /// GV. void CollectAllUsesOfGlobals(llvm::GlobalValue *G) {