compilerplugins/clang/checkconfigmacros.cxx | 100 ++++++++++++++++++++++++++++ compilerplugins/clang/pluginhandler.cxx | 7 + 2 files changed, 106 insertions(+), 1 deletion(-)
New commits: commit c3ffd741b207774be787896dfd305db89aca0e42 Author: LuboÅ¡ LuÅák <[email protected]> Date: Thu Apr 4 13:02:34 2013 +0200 compiler plugin to check incorrect #ifdef for config_XXX.h macros http://lists.freedesktop.org/archives/libreoffice/2013-March/047769.html Change-Id: Ibba9d3dcc87d6d6eee58ab3690a8f87339d00956 diff --git a/compilerplugins/clang/checkconfigmacros.cxx b/compilerplugins/clang/checkconfigmacros.cxx new file mode 100644 index 0000000..3ffaff8 --- /dev/null +++ b/compilerplugins/clang/checkconfigmacros.cxx @@ -0,0 +1,100 @@ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#include "plugin.hxx" + +#include <clang/Lex/Preprocessor.h> + +namespace loplugin +{ + +/* +This is a compile check. + +Feature macros from config_XXX.h headers are always #defined (to 1 or 0 in case of yes/no +settings). It is a mistake to use #ifdef/#ifndef/defined to check them. + +Using 1/0 instead of defined/undefined avoids undetected problems when e.g. the necessary +#include of the config_XXX.h file is missing. +*/ + +class CheckConfigMacros + : public PPCallbacks + , public Plugin + { + public: + explicit CheckConfigMacros( CompilerInstance& compiler ); + virtual void run(); + virtual void MacroDefined( const Token& macroToken, const MacroInfo* info ); + virtual void MacroUndefined( const Token& macroToken , const MacroInfo* info ); + virtual void Ifdef( SourceLocation location, const Token& macroToken ); + virtual void Ifndef( SourceLocation location, const Token& macroToken ); + virtual void Defined( const Token& macroToken ); + private: + void checkMacro( const Token& macroToken, SourceLocation location ); + std::set< string > configMacros; + }; + +CheckConfigMacros::CheckConfigMacros( CompilerInstance& compiler ) + : Plugin( compiler ) + { + compiler.getPreprocessor().addPPCallbacks( this ); + } + +void CheckConfigMacros::run() + { + // nothing, only check preprocessor usage + } + +void CheckConfigMacros::MacroDefined( const Token& macroToken, const MacroInfo* info ) + { + const char* filename = compiler.getSourceManager().getPresumedLoc( info->getDefinitionLoc()).getFilename(); + if( filename != NULL + && ( strncmp( filename, BUILDDIR "/config_host/", strlen( BUILDDIR "/config_host/" )) == 0 + || strncmp( filename, BUILDDIR "/config_build/", strlen( BUILDDIR "/config_build/" )) == 0 )) + { +// fprintf(stderr,"DEF: %s %s\n", macroToken.getIdentifierInfo()->getName().data(), filename ); + configMacros.insert( macroToken.getIdentifierInfo()->getName()); + } + } + +void CheckConfigMacros::MacroUndefined( const Token& macroToken, const MacroInfo* ) + { + configMacros.erase( macroToken.getIdentifierInfo()->getName()); + } + +void CheckConfigMacros::Ifdef( SourceLocation location, const Token& macroToken ) + { + checkMacro( macroToken, location ); + } + +void CheckConfigMacros::Ifndef( SourceLocation location, const Token& macroToken ) + { + checkMacro( macroToken, location ); + } + +void CheckConfigMacros::Defined( const Token& macroToken ) + { + checkMacro( macroToken, macroToken.getLocation()); + } + +void CheckConfigMacros::checkMacro( const Token& macroToken, SourceLocation location ) + { + if( configMacros.find( macroToken.getIdentifierInfo()->getName()) != configMacros.end()) + { + report( DiagnosticsEngine::Error, "checking whether a config macro %0 is defined", + location ) << macroToken.getIdentifierInfo()->getName(); + report( DiagnosticsEngine::Note, "use #if instead of #ifdef/#ifndef/defined", location ); + } + } + +static Plugin::Registration< CheckConfigMacros > X( "bodynotinblock" ); + +} // namespace commit 996b6fc92b847f70f73cda58f64e5cf438585127 Author: LuboÅ¡ LuÅák <[email protected]> Date: Thu Apr 4 12:52:04 2013 +0200 don't explicitly delete PPCallbacks-based compiler plugin actions If the class is based on PPCallbacks too, Clang internals will delete the instance. Change-Id: I6dd83d800e6cca17eb0b5de23c8994f11c087fd5 diff --git a/compilerplugins/clang/pluginhandler.cxx b/compilerplugins/clang/pluginhandler.cxx index 69b8c04..cd554aa 100644 --- a/compilerplugins/clang/pluginhandler.cxx +++ b/compilerplugins/clang/pluginhandler.cxx @@ -12,6 +12,7 @@ #include <clang/Frontend/CompilerInstance.h> #include <clang/Frontend/FrontendPluginRegistry.h> +#include <clang/Lex/PPCallbacks.h> #include <stdio.h> #include <sys/stat.h> #include <unistd.h> @@ -65,7 +66,11 @@ PluginHandler::~PluginHandler() i < pluginCount; ++i ) if( plugins[ i ].object != NULL ) - delete plugins[ i ].object; + { + // PPCallbacks is owned by preprocessor object, don't delete those + if( dynamic_cast< PPCallbacks* >( plugins[ i ].object ) == NULL ) + delete plugins[ i ].object; + } } void PluginHandler::handleOption( const string& option )
_______________________________________________ Libreoffice-commits mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
