1 #include "PointInitializationCheck.h"
2 
3 #include <clang/AST/Decl.h>
4 #include <clang/AST/DeclCXX.h>
5 #include <clang/AST/Expr.h>
6 #include <clang/AST/Type.h>
7 #include <clang/ASTMatchers/ASTMatchFinder.h>
8 #include <clang/ASTMatchers/ASTMatchers.h>
9 #include <clang/ASTMatchers/ASTMatchersInternal.h>
10 #include <clang/Basic/Diagnostic.h>
11 
12 #include "Utils.h"
13 
14 using namespace clang::ast_matchers;
15 
16 namespace clang
17 {
18 namespace tidy
19 {
20 namespace cata
21 {
registerMatchers(MatchFinder * Finder)22 void PointInitializationCheck::registerMatchers( MatchFinder *Finder )
23 {
24     using CxxConstructorMatcher = clang::ast_matchers::internal::Matcher<Expr>;
25     const CxxConstructorMatcher ZeroConstructor = cxxConstructExpr( anyOf(
26                 allOf(
27                     argumentCountIs( 1 ),
28                     hasArgument( 0, declRefExpr( to( varDecl(
29                                      anyOf( hasName( "point_zero" ), hasName( "tripoint_zero" ) )
30                                  ) ) ) ) ),
31                 allOf(
32                     hasArgument( 0, integerLiteral( equals( 0 ) ) ),
33                     hasArgument( 1, integerLiteral( equals( 0 ) ) ),
34                     anyOf(
35                         argumentCountIs( 2 ),
36                         allOf(
37                             hasArgument( 2, integerLiteral( equals( 0 ) ) ),
38                             argumentCountIs( 3 )
39                         )
40                     )
41                 )
42             ) ).bind( "expr" );
43     Finder->addMatcher( varDecl(
44                             unless( parmVarDecl() ),
45                             hasType( isPointType() ),
46                             hasInitializer( ZeroConstructor )
47                         ).bind( "decl" ), this );
48     Finder->addMatcher( cxxCtorInitializer(
49                             forField( hasType( isPointType() ) ),
50                             withInitializer( ZeroConstructor )
51                         ).bind( "init" ), this );
52 }
53 
CheckDecl(PointInitializationCheck & Check,const MatchFinder::MatchResult & Result)54 static void CheckDecl( PointInitializationCheck &Check, const MatchFinder::MatchResult &Result )
55 {
56     const VarDecl *MatchedDecl = Result.Nodes.getNodeAs<VarDecl>( "decl" );
57     if( !MatchedDecl ) {
58         return;
59     }
60     const Expr *MatchedExpr = Result.Nodes.getNodeAs<Expr>( "expr" );
61     if( !MatchedExpr ) {
62         return;
63     }
64     QualType Type = MatchedDecl->getType();
65     PrintingPolicy Policy( LangOptions{} );
66     Policy.adjustForCPlusPlus();
67     Type.removeLocalConst();
68     std::string Replacement = Type.getAsString( Policy ) + " " + MatchedDecl->getNameAsString();
69     SourceRange ToReplace( MatchedDecl->getTypeSpecStartLoc(),  MatchedDecl->getEndLoc() );
70     Check.diag(
71         MatchedExpr->getBeginLoc(),
72         "Unnecessary initialization of %0. %1 is zero-initialized by default." )
73             << MatchedDecl << Type
74             << FixItHint::CreateReplacement( ToReplace, Replacement );
75 }
76 
CheckInit(PointInitializationCheck & Check,const MatchFinder::MatchResult & Result)77 static void CheckInit( PointInitializationCheck &Check, const MatchFinder::MatchResult &Result )
78 {
79     const CXXCtorInitializer *MatchedInit = Result.Nodes.getNodeAs<CXXCtorInitializer>( "init" );
80     if( !MatchedInit ) {
81         return;
82     }
83     FieldDecl *Member = MatchedInit->getMember();
84     if( !Member ) {
85         return;
86     }
87     QualType Type = Member->getType();
88     Check.diag(
89         MatchedInit->getInit()->getBeginLoc(),
90         "Unnecessary initialization of %0. %1 is zero-initialized by default." ) <<
91                 Member << Type;
92 }
93 
check(const MatchFinder::MatchResult & Result)94 void PointInitializationCheck::check( const MatchFinder::MatchResult &Result )
95 {
96     CheckDecl( *this, Result );
97     CheckInit( *this, Result );
98 }
99 
100 } // namespace cata
101 } // namespace tidy
102 } // namespace clang
103