1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
7 * This file is distributed under the University of Illinois Open Source
8 * License. See LICENSE.TXT for details.
14 #include <clang/Lex/Preprocessor.h>
20 This is a compile check.
22 Feature macros from config_XXX.h headers are always #defined (to 1 or 0 in case of yes/no
23 settings). It is a mistake to use #ifdef/#ifndef/defined to check them.
25 Using 1/0 instead of defined/undefined avoids undetected problems when e.g. the necessary
26 #include of the config_XXX.h file is missing.
29 class CheckConfigMacros
34 explicit CheckConfigMacros( CompilerInstance
& compiler
);
35 virtual void run() override
;
36 #if __clang_major__ < 3 || __clang_major__ == 3 && __clang_minor__ < 3
37 virtual void MacroDefined( const Token
& macroToken
, const MacroInfo
* info
) override
;
38 virtual void MacroUndefined( const Token
& macroToken
, const MacroInfo
* info
) override
;
39 virtual void Ifdef( SourceLocation location
, const Token
& macroToken
) override
;
40 virtual void Ifndef( SourceLocation location
, const Token
& macroToken
) override
;
41 virtual void Defined( const Token
& macroToken
) override
;
43 virtual void MacroDefined( const Token
& macroToken
, const MacroDirective
* info
) override
;
44 virtual void MacroUndefined( const Token
& macroToken
, const MacroDirective
* info
) override
;
45 virtual void Ifdef( SourceLocation location
, const Token
& macroToken
, const MacroDirective
* info
) override
;
46 virtual void Ifndef( SourceLocation location
, const Token
& macroToken
, const MacroDirective
* info
) override
;
47 #if __clang_major__ == 3 && __clang_minor__ < 4
48 virtual void Defined( const Token
& macroToken
, const MacroDirective
* info
) override
;
50 virtual void Defined( const Token
& macroToken
, const MacroDirective
* info
, SourceRange Range
) override
;
53 enum { isPPCallback
= true };
55 void checkMacro( const Token
& macroToken
, SourceLocation location
);
56 std::set
< string
> configMacros
;
59 CheckConfigMacros::CheckConfigMacros( CompilerInstance
& compiler
)
62 compiler
.getPreprocessor().addPPCallbacks( this );
65 void CheckConfigMacros::run()
67 // nothing, only check preprocessor usage
70 #if __clang_major__ < 3 || __clang_major__ == 3 && __clang_minor__ < 3
71 void CheckConfigMacros::MacroDefined( const Token
& macroToken
, const MacroInfo
* info
)
73 SourceLocation location
= info
->getDefinitionLoc();
75 void CheckConfigMacros::MacroDefined( const Token
& macroToken
, const MacroDirective
* info
)
77 SourceLocation location
= info
->getLocation();
79 const char* filename
= compiler
.getSourceManager().getPresumedLoc( location
).getFilename();
81 && ( strncmp( filename
, BUILDDIR
"/config_host/", strlen( BUILDDIR
"/config_host/" )) == 0
82 || strncmp( filename
, BUILDDIR
"/config_build/", strlen( BUILDDIR
"/config_build/" )) == 0 ))
84 // fprintf(stderr,"DEF: %s %s\n", macroToken.getIdentifierInfo()->getName().data(), filename );
85 configMacros
.insert( macroToken
.getIdentifierInfo()->getName());
89 #if __clang_major__ < 3 || __clang_major__ == 3 && __clang_minor__ < 3
90 void CheckConfigMacros::MacroUndefined( const Token
& macroToken
, const MacroInfo
* )
92 void CheckConfigMacros::MacroUndefined( const Token
& macroToken
, const MacroDirective
* )
95 configMacros
.erase( macroToken
.getIdentifierInfo()->getName());
98 #if __clang_major__ < 3 || __clang_major__ == 3 && __clang_minor__ < 3
99 void CheckConfigMacros::Ifdef( SourceLocation location
, const Token
& macroToken
)
101 void CheckConfigMacros::Ifdef( SourceLocation location
, const Token
& macroToken
, const MacroDirective
* )
104 checkMacro( macroToken
, location
);
107 #if __clang_major__ < 3 || __clang_major__ == 3 && __clang_minor__ < 3
108 void CheckConfigMacros::Ifndef( SourceLocation location
, const Token
& macroToken
)
110 void CheckConfigMacros::Ifndef( SourceLocation location
, const Token
& macroToken
, const MacroDirective
* )
113 checkMacro( macroToken
, location
);
116 #if __clang_major__ < 3 || __clang_major__ == 3 && __clang_minor__ < 3
117 void CheckConfigMacros::Defined( const Token
& macroToken
)
118 #elif __clang_major__ == 3 && __clang_minor__ < 4
119 void CheckConfigMacros::Defined( const Token
& macroToken
, const MacroDirective
* )
121 void CheckConfigMacros::Defined( const Token
& macroToken
, const MacroDirective
* , SourceRange
)
124 checkMacro( macroToken
, macroToken
.getLocation());
127 void CheckConfigMacros::checkMacro( const Token
& macroToken
, SourceLocation location
)
129 if( configMacros
.find( macroToken
.getIdentifierInfo()->getName()) != configMacros
.end())
131 report( DiagnosticsEngine::Error
, "checking whether a config macro %0 is defined",
132 location
) << macroToken
.getIdentifierInfo()->getName();
133 report( DiagnosticsEngine::Note
, "use #if instead of #ifdef/#ifndef/defined", location
);
137 static Plugin::Registration
< CheckConfigMacros
> X( "bodynotinblock" );
141 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */