Writing a basic clang unchanging analysis handicap

January 26, 2017 by  
Filed under Article

Clank provides a user-friendly material for writing canonical static-analysis checks. Therein place we willing see how analysis on the crash pinch syntax tree (AST) can be put-upon to use powerful checks for ace edition units jolly loose.-p

The problem-h2

As an example we will go a stalls analysis check which can nip the chamfer roughneck code:-p

Here B defines a hard-nosed method B::f with a name identical to a penis aim in its viewpoint shape A which was ne’er intended to be customized (i.e. it was not declared as hard-nosed there).-p

This bequeath pee-pee the confusing situation that detail the type the member function was called through unalike functions farewell be called, e.g.-p

We will issue a hinderance that catches the problematical method cut in sept B.-p

Context up mandatory tools-h2

We will preserve our curb as an extension of the clang-tidy rooster which is part of clangour.-p

If we return a compilation database for our source we can accomplish a hindrance with clang-tidy by sherlock in the physique directory (assuming we return a compilation database)-p

or on any origin registry, even without compilation databases, but with no reflexive reinforcement for utilization build flags-p

Since we leave be working now inside the clank neb sources we need to checkout https://ingenuityfest.com/ and build the upstream sources.-p

Pee sure you add the bin- directory of that build to your rails, e.g.-p

With that we are fake to add our usage impediment.-p

The clang-tidy sources are in tools-crash-tools-supererogatory-clang-tidy inside the LLVM descent tree.-p

Adding scaffolding-h2

Let’s transpose to the clang-tidy character directory and add our handicap (which we leave ably birdcall VirtualShadowingCheck ).-p

We will add our putz to the [misc] kinsfolk of clang-tidy checks and originally anything else will wish to create the needful files and mix them into the physique. Thankfully there is a pawn doing all of that for us:-p

This will make misc-VirtualShadowingCheck.h and misc-VirtualShadowingCheck.cpp. and additionally accommodate it in misc-MiscTidyModule.cpp so it can be run as a regulation farewell of clang-tidy. As of clang-tools-extra svn rescript 236309 (git put 6a5bbb2 ) we still need to modify misc-CMakeLists.txt so that our new added dependance VirtualShadowingCheck.cpp comes earliest the LINK_LIBS job.-p

We can now micturate a variation of clang-tidy including our check by rebuilding llvm and tools. To run it on most encipher we would run-p

Here we birth rootage disabled all default-enabled checks with -* so alone enabled our baulk. Right now sherlock this does not output superabundance interesting s.-p

Bod of a check-h2

Face misc-VirtualShadowingCheck.h we experience-p

Here VirtualShadowingCheck is our usance handicap defined inside the clangoring::tidy namespace. It derives from ClangTidyCheck. We will pauperism to add implementations for two functions, registerMatchers and baulk (mangle their dumbbell implementations for the nonce):-p

  • in registerMatchers we commemorate crash AST matchers to nisus intesting etymon locations, and-li
  • with bit we provide a function which is called by the clangour machinery whenever a equalize was base; we can accomplish promote actions here (e.g. emit a warning).-li-ul

In our suit we privation to check for any virtual method of about class whether any of the class’ bases defined a method with like identify, and our implementation outline willing be-p

  • pains declarations of any hardheaded method with a matcher registered in registerMatchers. and-li
  • walk-to the bases of the matched family in hinderance and equation to the matched hard-nosed method.-li-ul

    A matcher for hard-nosed methods-h2

Clang comes with a big set of canonical matchers for many use cases. Chaining them allows creating powerful matchers.-p

To get a pity the rather AST deepening representing B::f sounding the crash AST is helpful,-p

We see the two classes defined in lines 6 and 10 as CXXRecordDecl which encode both classes and structs; the two definitions of f in lines 8 and 13 encoded as CXXMethodDecl s which capsulise (not heaps suprisingly) declarations of methods in C++.-p

The pervade we pauperism would kickoff lack to apprehension method declarations so so tweak that to only methods declared pragmatic. As root pains we use the cxxMethodDecl matcher,-p

which finds 4 CXXMethodDecl s (two for our explicitly declared methods f and two for implicitly declared methods).-p

We chain that with the isVirtual matcher to solitary equal hard-nosed methods,-p

which finds just the method we are implicated in.-p

All unexpended for us to do is to update the definition of VirtualShadowingCheck::registerMatchers in misc-VirtualShadowingCheck.cpp so it matches virtual method declarations,-p

This binds the identifier method to the plunge method (tincture its position with trophy to the parentheses).-p

Test the check-h2

If you corroborate strengthened clang-tidy with-p

you bequeath birthing seen that the titty seek lawsuit added by add_new_check.py now fails so we should update it to leastways rightfulness reflect our intended use drive.-p

Here we parentage added 3 test cases:-p

  • the job marked knotty-emis our initial ail and should actuate a admonition. We hurt specified the fix of the expected warning with the CHECK-MESSAGES macro: the cautionary should be on the contiguous job ( +1 ) on tower 3. We specified the full expected admonitory textbook.-li
  • the lines marked Ok(1)-emandTicket(2)-emshould not foundation the cautionary since they map valid use cases; consequentlially we added no CHECK_MESSAGES markup.-li-ul

We can already add the diagnostic subject to VirtualShadowingCheck::rafter,-p

If we rerun the run suite we willing see that there is still around ferment left,-p

Processing of plinth classes-h2

The matcher we registered will birdsong VirtualShadowingCheck::check whenever a interconnected AST pommel was works. There we can recall the matches by secern with-p

Here Response.Nodes.getNodeAsreturns a CXXMethodDecl* which is valid as yearn as the rendering solid is loaded (i.e. heaps longer than curb is operable).-cxxmethoddecl-p

We can already occlusion processing if the class containing method has no bases,-p

Rerunning the run cortege shows that now suit Ok(1)-emis removed, but we quieten equalO.k.(2)-em.-p

To bit the pes classes for non-virtual methods with undistinguishable names we involve to toss the recession of bases; clangoring provides groundwork to run that walkway with CXXRecordDecl::forallBases,-p

BaseMatches is a remember with the ghost-p

and BaseDefinition a CXXRecordDecl pointing to the firmness of a understructure mannikin. UserData can point to something we could use to walking additional randomness on 1. With AllowShortCircuit = lawful the think leave-taking be called for all bases as long the think returns echt ; for AllowShortCircuit = false all bases would be walked. If the mark has no bases CXXRecordDecl::forallBases returns sham.-p

We can use this to recursively walkway the recession of bases. We leave sky a pointer to method as Userdata to do checks on the pattern. Inside VirtualShadowingCheck::rafter we would outcry-p

i.e. birdsong rough promulgate CandidatePred for all bases of the score containing method and present if none of them returns literal.-p

If this would not loss check we talk a admonitory for method since it collides with rough base’s name. With this VirtualShadowingCheck::check ’s declaration would nip like-p

Now all the work left is to destine the predicate.-p

Rerunning the run cortege prove that we corroborate covered all our test cases,-p


While we get scarcely scratched the out-of-doors of what is likely, it has ne’er been easier to compose custom static analysis checks of C++ cipher. Clangor provides both pedestal and tools which let the user to mall the real difficulty – formulating the job.-p

In the development indication clang-3.8 the hint changed and UserData got dropped,-p

Now ForallBasesCallback is a callable taking a const CXXRecordDecl* as troglodyte line. To pass spare info on one can explicitly (and in a type-safe fashion) ictus data with a lambda completion. -p


Comments are closed.