2 * This file is part of the LibreOffice project.
6 * This file is distributed under the University of Illinois Open Source
7 * License. See LICENSE.TXT for details.
13 #include <clang/Lex/Preprocessor.h>
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
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
;
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
;
49 void checkMacro( const Token
& macroToken
, SourceLocation location
);
50 std::set
< string
> configMacros
;
53 CheckConfigMacros::CheckConfigMacros( CompilerInstance
& 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();
69 void CheckConfigMacros::MacroDefined( const Token
& macroToken
, const MacroDirective
* info
)
71 SourceLocation location
= info
->getLocation();
73 const char* filename
= compiler
.getSourceManager().getPresumedLoc( location
).getFilename();
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
* )
86 void CheckConfigMacros::MacroUndefined( const Token
& macroToken
, const MacroDirective
* )
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
)
95 void CheckConfigMacros::Ifdef( SourceLocation location
, const Token
& macroToken
, const MacroDirective
* )
98 checkMacro( macroToken
, location
);
101 #if __clang_major__ < 3 || __clang_major__ == 3 && __clang_minor__ < 3
102 void CheckConfigMacros::Ifndef( SourceLocation location
, const Token
& macroToken
)
104 void CheckConfigMacros::Ifndef( SourceLocation location
, const Token
& macroToken
, const MacroDirective
* )
107 checkMacro( macroToken
, location
);
110 #if __clang_major__ < 3 || __clang_major__ == 3 && __clang_minor__ < 3
111 void CheckConfigMacros::Defined( const Token
& macroToken
)
113 void CheckConfigMacros::Defined( const Token
& macroToken
, const MacroDirective
* )
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" );