update credits
[LibreOffice.git] / compilerplugins / clang / checkconfigmacros.cxx
blob86b7e4378f9d84fa807e31593709de6c7a57bf48
1 /*
2 * This file is part of the LibreOffice project.
4 * Based on LLVM/Clang.
6 * This file is distributed under the University of Illinois Open Source
7 * License. See LICENSE.TXT for details.
9 */
11 #include "plugin.hxx"
13 #include <clang/Lex/Preprocessor.h>
15 namespace loplugin
19 This is a compile check.
21 Feature macros from config_XXX.h headers are always #defined (to 1 or 0 in case of yes/no
22 settings). It is a mistake to use #ifdef/#ifndef/defined to check them.
24 Using 1/0 instead of defined/undefined avoids undetected problems when e.g. the necessary
25 #include of the config_XXX.h file is missing.
28 class CheckConfigMacros
29 : public PPCallbacks
30 , public Plugin
32 public:
33 explicit CheckConfigMacros( CompilerInstance& compiler );
34 virtual void run() override;
35 #if __clang_major__ < 3 || __clang_major__ == 3 && __clang_minor__ < 3
36 virtual void MacroDefined( const Token& macroToken, const MacroInfo* info ) override;
37 virtual void MacroUndefined( const Token& macroToken, const MacroInfo* info ) override;
38 virtual void Ifdef( SourceLocation location, const Token& macroToken ) override;
39 virtual void Ifndef( SourceLocation location, const Token& macroToken ) override;
40 virtual void Defined( const Token& macroToken ) override;
41 #else
42 virtual void MacroDefined( const Token& macroToken, const MacroDirective* info ) override;
43 virtual void MacroUndefined( const Token& macroToken, const MacroDirective* info ) override;
44 virtual void Ifdef( SourceLocation location, const Token& macroToken, const MacroDirective* info ) override;
45 virtual void Ifndef( SourceLocation location, const Token& macroToken, const MacroDirective* info ) override;
46 virtual void Defined( const Token& macroToken, const MacroDirective* info ) override;
47 #endif
48 private:
49 void checkMacro( const Token& macroToken, SourceLocation location );
50 std::set< string > configMacros;
53 CheckConfigMacros::CheckConfigMacros( CompilerInstance& compiler )
54 : Plugin( compiler )
56 compiler.getPreprocessor().addPPCallbacks( this );
59 void CheckConfigMacros::run()
61 // nothing, only check preprocessor usage
64 #if __clang_major__ < 3 || __clang_major__ == 3 && __clang_minor__ < 3
65 void CheckConfigMacros::MacroDefined( const Token& macroToken, const MacroInfo* info )
67 SourceLocation location = info->getDefinitionLoc();
68 #else
69 void CheckConfigMacros::MacroDefined( const Token& macroToken, const MacroDirective* info )
71 SourceLocation location = info->getLocation();
72 #endif
73 const char* filename = compiler.getSourceManager().getPresumedLoc( location ).getFilename();
74 if( filename != NULL
75 && ( strncmp( filename, BUILDDIR "/config_host/", strlen( BUILDDIR "/config_host/" )) == 0
76 || strncmp( filename, BUILDDIR "/config_build/", strlen( BUILDDIR "/config_build/" )) == 0 ))
78 // fprintf(stderr,"DEF: %s %s\n", macroToken.getIdentifierInfo()->getName().data(), filename );
79 configMacros.insert( macroToken.getIdentifierInfo()->getName());
83 #if __clang_major__ < 3 || __clang_major__ == 3 && __clang_minor__ < 3
84 void CheckConfigMacros::MacroUndefined( const Token& macroToken, const MacroInfo* )
85 #else
86 void CheckConfigMacros::MacroUndefined( const Token& macroToken, const MacroDirective* )
87 #endif
89 configMacros.erase( macroToken.getIdentifierInfo()->getName());
92 #if __clang_major__ < 3 || __clang_major__ == 3 && __clang_minor__ < 3
93 void CheckConfigMacros::Ifdef( SourceLocation location, const Token& macroToken )
94 #else
95 void CheckConfigMacros::Ifdef( SourceLocation location, const Token& macroToken, const MacroDirective* )
96 #endif
98 checkMacro( macroToken, location );
101 #if __clang_major__ < 3 || __clang_major__ == 3 && __clang_minor__ < 3
102 void CheckConfigMacros::Ifndef( SourceLocation location, const Token& macroToken )
103 #else
104 void CheckConfigMacros::Ifndef( SourceLocation location, const Token& macroToken, const MacroDirective* )
105 #endif
107 checkMacro( macroToken, location );
110 #if __clang_major__ < 3 || __clang_major__ == 3 && __clang_minor__ < 3
111 void CheckConfigMacros::Defined( const Token& macroToken )
112 #else
113 void CheckConfigMacros::Defined( const Token& macroToken, const MacroDirective* )
114 #endif
116 checkMacro( macroToken, macroToken.getLocation());
119 void CheckConfigMacros::checkMacro( const Token& macroToken, SourceLocation location )
121 if( configMacros.find( macroToken.getIdentifierInfo()->getName()) != configMacros.end())
123 report( DiagnosticsEngine::Error, "checking whether a config macro %0 is defined",
124 location ) << macroToken.getIdentifierInfo()->getName();
125 report( DiagnosticsEngine::Note, "use #if instead of #ifdef/#ifndef/defined", location );
129 static Plugin::Registration< CheckConfigMacros > X( "bodynotinblock" );
131 } // namespace