<div dir="ltr"><p>Hi!</p><p>I started working with Clang a couple of weeks ago with an aim to developing a<br>small project that would be useful to me (perhaps to others as well) and to get<br>involved with the clang project and community.  After a couple of weeks of<br>experimentation I've reached the point where it would be helpful to ask for<br>advice.</p><div>(By way of background I have had commercial development experience with compiler<br>development, which is somewhat dated but still relevant, but I have no experience</div><div>with using or modifying either LLVM or Clang.)</div><p>I'd like to briefly describe two versions of my project and then ask for your<br>advice on the best way to proceed.</p><p>I want to "break encapsulation" on C++ classes to better enable unit testing of<br>legacy code (or just plain poorly written code) that can't be refactored, for<br>which developing better tests is a higher priority (given the constraints I'm<br>subject to) than changing the design.</p><p>I have two approaches in mind:</p><p>The first (which I've tested by hand) is to build a C++ source-to-source<br>processor that given a source file and some class names will parse the<br>translation unit and then emit two files: first, a C++ header that will contain<br>the named classes (but renamed) with all methods and fields in the same order as<br>the original but where all access is public (and it will also have the<br>appropriate #includes), and second, an assembly language file of thunks that<br>will implement the methods of the new proxy class by jumping to the methods of<br>the original class (and this file needs the mangled names of original and proxy<br>class methods).  So that to write a unit test you create this proxy header and<br>use it (by a cast) on your objects-under-test and by linking with the assembly<br>thunks you can transparently access all public/protected/private methods and<br>fields of your instance in hand.  (As I've said, this works when I've done it<br>by hand.)</p><p>The second approach is to use Clang/LLVM as a C++ compiler (not just the front<br>end of a tool) by inventing a new statement which is like a reverse friend<br>declaration, with its own special keyword.  Placed in a method it will name a<br>class or method that you want to "break encapsulation" of.  And it will act is<br>if the class or method named has a friend declaration pointing back to the<br>method with the break declaration statement.  With its own keyword that can<br>easily be grepped for you can make sure this statement is used only in unit<br>tests and not production code.  (In fact, it could be enabled as any other<br>language extension only if a compiler switch is present, and so you could easily<br>ensure that only unit test projects have that compiler switch.)</p><p>Here are my questions about these approaches:</p><p>1.  What packaged Clang functionality do I need?</p><p>    a. Can approach 1 be done with strictly libclang (using the AST and the lexer<br>       to guide modification of the source and to identify methods that need<br>       assembly thunks)?  Or do I need to step up to LibTooling + LibASTMatchers<br>       (or LibAST).  Or does it need a plugin?  What is your recommendation?</p><p>    b. Can approach 2 be done with LibTooling + LibASTMatchers + minimal changes<br>       to clang so it accepts the new grammar with new AST nodes to match.  My<br>       idea there is, having parsed and traversed my new "break encapsulation"<br>       declarations, to go right to the definitions of the targeted class and<br>       modify the AST in-place to have an actual friend declaration pointing<br>       back, and then to finish the compilation of the modified AST.</p><p>2.  How much of this work can be done on the Windows platform with Clang?  And<br>    can it be done with Visual Studio or do I need to use an alternate native<br>    compiler for Windows?</p><p>    I've become aware of restrictions of developing on the Windows platform.<br>    Leave aside restrictions on what you can do with Clang/LLVM as a compiler<br>    on Windows (e.g., at this time no exceptions or anything else that requires<br>    compiler-rt) which would only affect my second approach.  Even so I've found<br>    things that make Windows/Visual Studio less than a perfect development<br>    environment for Clang.</p><p>    For example, I can't confirm my compiled Clang/LLVM is correct (using the VS<br>    12 Win64) platform because even though it compiles without error and the<br>    unit tests all pass I can't successfully run the "command line tests"<br>    (<a href="http://clang.llvm.org/hacking.html#testingCommands">http://clang.llvm.org/hacking.html#testingCommands</a>) as I reported here<br>    earlier (<a href="http://lists.cs.uiuc.edu/pipermail/cfe-dev/2015-March/042170.html">http://lists.cs.uiuc.edu/pipermail/cfe-dev/2015-March/042170.html</a>) - I<br>    got some help from the community there but the thread petered out and I've<br>    been unable to continue with them.  (Just for reference I've attached to<br>    this email my last log of running the tests, with 122 unexpected failures<br>    which are all some kind of lock error I don't understand.)</p><p>    Anyway, if I continue with the Windows platform can I be successful (or<br>    should I switch to Linux)?</p><p>This email has been quite long, and I apologize, but I'd really appreciate your<br>help.  I'd like to start my Clang/LLVM development with some chance of success<br>without getting greatly frustrated by not knowing some basic things that everyone<br>who is working in the code "just knows" from experience.  So thanks in advance!<br>And I hope to contribute back to the Clang/LLVM community in the future ...</p><p>-- David Bakin<br></p></div>