2016-06-26 10:06:18 +02:00
//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author: Vassil Vassilev <vvasilev@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------
# ifndef CLING_DECL_UNLOADER
# define CLING_DECL_UNLOADER
# include "cling/Interpreter/Transaction.h"
# include "clang/AST/DeclVisitor.h"
2016-09-09 17:23:32 -04:00
namespace clang {
2016-06-26 10:06:18 +02:00
class CodeGenerator ;
class GlobalDecl ;
2016-09-09 17:23:32 -04:00
}
2016-06-26 10:06:18 +02:00
2016-09-09 17:23:32 -04:00
namespace cling {
2016-06-26 10:06:18 +02:00
///\brief The class does the actual work of removing a declaration and
/// resetting the internal structures of the compiler
///
2016-09-09 17:23:32 -04:00
class DeclUnloader : public clang : : DeclVisitor < cling : : DeclUnloader , bool > {
2016-06-26 10:06:18 +02:00
private :
2016-09-09 17:23:32 -04:00
typedef llvm : : DenseSet < clang : : FileID > FileIDs ;
2016-06-26 10:06:18 +02:00
///\brief The Sema object being unloaded (contains the AST as well).
///
2016-09-09 17:23:32 -04:00
clang : : Sema * m_Sema ;
2016-06-26 10:06:18 +02:00
///\brief The clang code generator, being recovered.
///
clang : : CodeGenerator * m_CodeGen ;
///\brief The current transaction being unloaded.
///
const Transaction * m_CurTransaction ;
///\brief Unloaded declaration contains a SourceLocation, representing a
/// place in the file where it was seen. Clang caches that file and even if
/// a declaration is removed and the file is edited we hit the cached entry.
/// This ADT keeps track of the files from which the unloaded declarations
/// came from so that in the end they could be removed from clang's cache.
///
FileIDs m_FilesToUncache ;
public :
2016-09-09 17:23:32 -04:00
DeclUnloader ( clang : : Sema * S , clang : : CodeGenerator * CG , const Transaction * T )
2016-06-26 10:06:18 +02:00
: m_Sema ( S ) , m_CodeGen ( CG ) , m_CurTransaction ( T ) { }
~ DeclUnloader ( ) ;
2019-09-29 21:12:16 +02:00
///\brief Forwards to Visit(), excluding PCH declarations (known to cause
/// problems). If unsure, call this function instead of plain `Visit()'.
///\param[in] D - The declaration to unload
2016-06-26 10:06:18 +02:00
///\returns true on success.
///
2017-03-31 10:08:07 +02:00
bool UnloadDecl ( clang : : Decl * D ) {
2023-11-24 14:39:34 +01:00
if ( D - > isFromASTFile ( ) )
2017-03-31 10:08:07 +02:00
return true ;
return Visit ( D ) ;
}
2016-06-26 10:06:18 +02:00
///\brief If it falls back in the base class just remove the declaration
/// only from the declaration context.
/// @param[in] D - The declaration to be removed.
///
///\returns true on success.
///
2016-09-09 17:23:32 -04:00
bool VisitDecl ( clang : : Decl * D ) ;
2016-06-26 10:06:18 +02:00
///\brief Removes the declaration from the lookup chains and from the
/// declaration context.
/// @param[in] ND - The declaration to be removed.
///
///\returns true on success.
///
2016-09-09 17:23:32 -04:00
bool VisitNamedDecl ( clang : : NamedDecl * ND ) ;
2016-06-26 10:06:18 +02:00
///\brief Removes the declaration from Sema's unused decl registry
/// @param[in] DD - The declaration to be removed.
///
///\returns true on success.
///
2016-09-09 17:23:32 -04:00
bool VisitDeclaratorDecl ( clang : : DeclaratorDecl * DD ) ;
2016-06-26 10:06:18 +02:00
///\brief Removes a using shadow declaration, created in the cases:
///\code
/// namespace A {
/// void foo();
/// }
/// namespace B {
/// using A::foo; // <- a UsingDecl
/// // Also creates a UsingShadowDecl for A::foo() in B
/// }
///\endcode
///\param[in] USD - The declaration to be removed.
///
///\returns true on success.
///
2016-09-09 17:23:32 -04:00
bool VisitUsingShadowDecl ( clang : : UsingShadowDecl * USD ) ;
2016-06-26 10:06:18 +02:00
///\brief Removes a typedef name decls. A base class for TypedefDecls and
/// TypeAliasDecls.
///\param[in] TND - The declaration to be removed.
///
///\returns true on success.
///
2016-09-09 17:23:32 -04:00
bool VisitTypedefNameDecl ( clang : : TypedefNameDecl * TND ) ;
2016-06-26 10:06:18 +02:00
///\brief Removes the declaration from the lookup chains and from the
/// declaration context and it rebuilds the redeclaration chain.
/// @param[in] VD - The declaration to be removed.
///
///\returns true on success.
///
2016-09-09 17:23:32 -04:00
bool VisitVarDecl ( clang : : VarDecl * VD ) ;
2016-06-26 10:06:18 +02:00
2023-11-26 14:14:44 +01:00
///\brief Removes the declaration from the lookup chains and from the
/// declaration context and it rebuilds the redeclaration chain.
/// @param[in] FD - The declaration to be removed.
/// @param[in] RemoveSpec - If a template specialization, whether to remove
/// it from the parent.
///
///\returns true on success.
///
bool VisitFunctionDecl ( clang : : FunctionDecl * FD , bool RemoveSpec ) ;
2016-06-26 10:06:18 +02:00
///\brief Removes the declaration from the lookup chains and from the
/// declaration context and it rebuilds the redeclaration chain.
/// @param[in] FD - The declaration to be removed.
///
///\returns true on success.
///
2016-09-09 17:23:32 -04:00
bool VisitFunctionDecl ( clang : : FunctionDecl * FD ) ;
2016-06-26 10:06:18 +02:00
///\brief Specialize the removal of constructors due to the fact the we need
/// the constructor type (aka CXXCtorType). The information is located in
/// the CXXConstructExpr of usually VarDecls.
/// See clang::CodeGen::CodeGenFunction::EmitCXXConstructExpr.
///
/// What we will do instead is to brute-force and try to remove from the
/// llvm::Module all ctors of this class with all the types.
///
///\param[in] CXXCtor - The declaration to be removed.
///
///\returns true on success.
///
2016-09-09 17:23:32 -04:00
bool VisitCXXConstructorDecl ( clang : : CXXConstructorDecl * CXXCtor ) ;
2016-06-26 10:06:18 +02:00
///\brief Specialize the removal of destructors due to the fact the we need
/// the to erase the dtor decl and the deleting operator.
///
/// We will brute-force and try to remove from the llvm::Module all dtors of
/// this class with all the types.
///
///\param[in] CXXDtor - The declaration to be removed.
///
///\returns true on success.
///
2016-09-09 17:23:32 -04:00
bool VisitCXXDestructorDecl ( clang : : CXXDestructorDecl * CXXDtor ) ;
2016-06-26 10:06:18 +02:00
///\brief Removes the DeclCotnext and its decls.
/// @param[in] DC - The declaration to be removed.
///
///\returns true on success.
///
2016-09-09 17:23:32 -04:00
bool VisitDeclContext ( clang : : DeclContext * DC ) ;
2016-06-26 10:06:18 +02:00
///\brief Removes the namespace.
/// @param[in] NSD - The declaration to be removed.
///
///\returns true on success.
///
2016-09-09 17:23:32 -04:00
bool VisitNamespaceDecl ( clang : : NamespaceDecl * NSD ) ;
2016-06-26 10:06:18 +02:00
2016-06-13 10:56:42 -04:00
///\brief Removes all extern "C" declarations.
/// @param[in] LSD - The declaration context to be removed.
///
///\returns true on success.
///
bool VisitLinkageSpecDecl ( clang : : LinkageSpecDecl * LSD ) ;
2016-06-26 10:06:18 +02:00
///\brief Removes a Tag (class/union/struct/enum). Most of the other
/// containers fall back into that case.
/// @param[in] TD - The declaration to be removed.
///
///\returns true on success.
///
2016-09-09 17:23:32 -04:00
bool VisitTagDecl ( clang : : TagDecl * TD ) ;
2016-06-26 10:06:18 +02:00
///\brief Removes a RecordDecl. We shouldn't remove the implicit class
/// declaration.
///\param[in] RD - The declaration to be removed.
///
///\returns true on success.
///
2016-09-09 17:23:32 -04:00
bool VisitRecordDecl ( clang : : RecordDecl * RD ) ;
2016-06-26 10:06:18 +02:00
///\brief Remove the macro from the Preprocessor.
/// @param[in] MD - The MacroDirectiveInfo containing the IdentifierInfo and
/// MacroDirective to forward.
///
///\returns true on success.
///
bool VisitMacro ( const Transaction : : MacroDirectiveInfo MD ) ;
///@name Templates
///@{
///\brief Removes template from the redecl chain. Templates are
/// redeclarables also.
/// @param[in] R - The declaration to be removed.
///
///\returns true on success.
///
2016-09-09 17:23:32 -04:00
bool VisitRedeclarableTemplateDecl ( clang : : RedeclarableTemplateDecl * R ) ;
2016-06-26 10:06:18 +02:00
///\brief Removes the declaration clang's internal structures. This case
/// looks very much to VisitFunctionDecl, but FunctionTemplateDecl doesn't
/// derive from FunctionDecl and thus we need to handle it 'by hand'.
/// @param[in] FTD - The declaration to be removed.
///
///\returns true on success.
///
2016-09-09 17:23:32 -04:00
bool VisitFunctionTemplateDecl ( clang : : FunctionTemplateDecl * FTD ) ;
2016-06-26 10:06:18 +02:00
///\brief Removes a class template declaration from clang's internal
/// structures.
/// @param[in] CTD - The declaration to be removed.
///
///\returns true on success.
///
2016-09-09 17:23:32 -04:00
bool VisitClassTemplateDecl ( clang : : ClassTemplateDecl * CTD ) ;
2016-06-26 10:06:18 +02:00
2023-11-26 14:14:44 +01:00
///\brief Removes a class template specialization declaration from clang's
/// internal structures.
/// @param[in] CTSD - The declaration to be removed.
/// @param[in] RemoveSpec - Whether to remove the specialization from its
/// parent.
///
///\returns true on success.
///
bool VisitClassTemplateSpecializationDecl (
clang : : ClassTemplateSpecializationDecl * CTSD , bool RemoveSpec ) ;
2016-06-26 10:06:18 +02:00
///\brief Removes a class template specialization declaration from clang's
/// internal structures.
/// @param[in] CTSD - The declaration to be removed.
///
///\returns true on success.
///
2016-09-09 17:23:32 -04:00
bool VisitClassTemplateSpecializationDecl (
2023-11-26 14:14:44 +01:00
clang : : ClassTemplateSpecializationDecl * CTSD ) ;
2016-06-26 10:06:18 +02:00
2023-11-24 22:15:41 +01:00
///\brief Removes a var template declaration from clang's internal
/// structures.
/// @param[in] VTD - The declaration to be removed.
///
///\returns true on success.
///
bool VisitVarTemplateDecl ( clang : : VarTemplateDecl * VTD ) ;
///\brief Removes a var template specialization declaration from clang's
/// internal structures.
/// @param[in] CTSD - The declaration to be removed.
/// @param[in] RemoveSpec - Whether to remove the specialization from its
/// parent.
///
///\returns true on success.
///
bool VisitVarTemplateSpecializationDecl (
clang : : VarTemplateSpecializationDecl * VTSD , bool RemoveSpec ) ;
///\brief Removes a var template specialization declaration from clang's
/// internal structures.
/// @param[in] CTSD - The declaration to be removed.
///
///\returns true on success.
///
bool VisitVarTemplateSpecializationDecl (
clang : : VarTemplateSpecializationDecl * VTSD ) ;
2016-06-26 10:06:18 +02:00
///@}
2016-12-01 12:30:25 -05:00
void MaybeRemoveDeclFromModule ( clang : : GlobalDecl & GD ) const ;
2016-06-26 10:06:18 +02:00
/// @name Helpers
/// @{
///\brief Interface with nice name, forwarding to Visit.
///
///\param[in] MD - The MacroDirectiveInfo containing the IdentifierInfo and
/// MacroDirective to forward.
///\returns true on success.
///
bool UnloadMacro ( Transaction : : MacroDirectiveInfo MD ) {
return VisitMacro ( MD ) ;
}
2016-06-26 18:09:16 +03:00
/// @}
2016-06-26 10:06:18 +02:00
2021-02-12 17:15:42 +00:00
static void resetDefinitionData ( void * ) {
llvm_unreachable ( " resetDefinitionData on non-cxx record declaration " ) ;
}
static void resetDefinitionData ( clang : : TagDecl * decl ) ;
2016-06-26 18:09:16 +03:00
private :
///\brief Function that collects the files which we must reread from disk.
///
/// For example: We must uncache the cached include, which brought a
2016-06-26 18:15:39 +03:00
/// declaration or a macro directive definition in the AST.
2016-06-26 18:09:16 +03:00
///\param[in] Loc - The source location of the unloaded declaration.
///
2016-09-09 17:23:32 -04:00
void CollectFilesToUncache ( clang : : SourceLocation Loc ) ;
2016-06-26 17:54:52 +03:00
2016-06-26 10:06:18 +02:00
template < typename T >
2016-09-09 17:23:32 -04:00
bool VisitRedeclarable ( clang : : Redeclarable < T > * R , clang : : DeclContext * DC ) ;
2016-06-26 10:06:18 +02:00
} ;
2016-06-26 18:26:35 +03:00
/// \brief Unload a Decl from the AST, but not from CodeGen or Module.
inline bool UnloadDecl ( clang : : Sema * S , clang : : Decl * D ) {
DeclUnloader Unloader ( S , nullptr , nullptr ) ;
return Unloader . UnloadDecl ( D ) ;
}
/// \brief Unload a Decl from the AST and CodeGen, but not from the Module.
inline bool UnloadDecl ( clang : : Sema * S , clang : : CodeGenerator * CG , clang : : Decl * D ) {
DeclUnloader Unloader ( S , CG , nullptr ) ;
return Unloader . UnloadDecl ( D ) ;
}
2016-09-09 17:23:32 -04:00
2016-06-26 10:06:18 +02:00
} // namespace cling
# endif // CLING_DECL_UNLOADER