1 #include "AssertCheck.h"
2 
3 #include <unordered_set>
4 
5 #include "clang/Frontend/CompilerInstance.h"
6 
7 using namespace clang::ast_matchers;
8 
9 namespace clang
10 {
11 namespace tidy
12 {
13 namespace cata
14 {
15 
16 class AssertMacroCallbacks : public PPCallbacks
17 {
18     public:
AssertMacroCallbacks(Preprocessor * PP,AssertCheck * Check)19         AssertMacroCallbacks( Preprocessor *PP, AssertCheck *Check ) :
20             PP( PP ), Check( Check ) {}
21 
MacroExpands(const Token & MacroNameTok,const MacroDefinition &,SourceRange Range,const MacroArgs *)22         void MacroExpands( const Token &MacroNameTok,
23                            const MacroDefinition &,
24                            SourceRange Range,
25                            const MacroArgs * ) override {
26             StringRef MacroName = MacroNameTok.getIdentifierInfo()->getName();
27             SourceLocation Begin = Range.getBegin();
28             SourceManager &SM = PP->getSourceManager();
29             // When using assert inside cata_assert, this fetches the location
30             // of the cata_assert from that of the assert.
31             SourceLocation ExpansionBegin = SM.getFileLoc( Begin );
32             if( MacroName == "cata_assert" ) {
33                 CataAssertLocations.insert( ExpansionBegin );
34             } else if( MacroName == "assert" ) {
35                 if( !CataAssertLocations.count( ExpansionBegin ) ) {
36                     SourceRange RangeToReplace(
37                         Begin, Begin.getLocWithOffset( MacroName.size() - 1 ) );
38                     Check->diag( Begin, "Prefer cata_assert to assert." ) <<
39                             FixItHint::CreateReplacement( RangeToReplace, "cata_assert" );
40                 }
41             }
42         }
43     private:
44         Preprocessor *PP;
45         AssertCheck *Check;
46         llvm::SmallPtrSet<SourceLocation, 10> CataAssertLocations;
47 };
48 
registerPPCallbacks(CompilerInstance & Compiler)49 void AssertCheck::registerPPCallbacks( CompilerInstance &Compiler )
50 {
51     Compiler.getPreprocessor().addPPCallbacks(
52         llvm::make_unique<AssertMacroCallbacks>( &Compiler.getPreprocessor(), this ) );
53 }
54 
registerMatchers(MatchFinder *)55 void AssertCheck::registerMatchers( MatchFinder * /*Finder*/ )
56 {
57 }
58 
check(const MatchFinder::MatchResult &)59 void AssertCheck::check( const MatchFinder::MatchResult &/*Result*/ )
60 {
61 }
62 
63 } // namespace cata
64 } // namespace tidy
65 } // namespace clang
66