[cfe-dev] Can you give me advice on the proper strategy for a Clang-using tool I'm writing?

David Bakin davidbak at gmail.com
Thu Apr 2 00:51:10 PDT 2015


Hi!

I started working with Clang a couple of weeks ago with an aim to
developing a
small project that would be useful to me (perhaps to others as well) and to
get
involved with the clang project and community.  After a couple of weeks of
experimentation I've reached the point where it would be helpful to ask for
advice.
(By way of background I have had commercial development experience with
compiler
development, which is somewhat dated but still relevant, but I have no
experience
with using or modifying either LLVM or Clang.)

I'd like to briefly describe two versions of my project and then ask for
your
advice on the best way to proceed.

I want to "break encapsulation" on C++ classes to better enable unit
testing of
legacy code (or just plain poorly written code) that can't be refactored,
for
which developing better tests is a higher priority (given the constraints
I'm
subject to) than changing the design.

I have two approaches in mind:

The first (which I've tested by hand) is to build a C++ source-to-source
processor that given a source file and some class names will parse the
translation unit and then emit two files: first, a C++ header that will
contain
the named classes (but renamed) with all methods and fields in the same
order as
the original but where all access is public (and it will also have the
appropriate #includes), and second, an assembly language file of thunks that
will implement the methods of the new proxy class by jumping to the methods
of
the original class (and this file needs the mangled names of original and
proxy
class methods).  So that to write a unit test you create this proxy header
and
use it (by a cast) on your objects-under-test and by linking with the
assembly
thunks you can transparently access all public/protected/private methods and
fields of your instance in hand.  (As I've said, this works when I've done
it
by hand.)

The second approach is to use Clang/LLVM as a C++ compiler (not just the
front
end of a tool) by inventing a new statement which is like a reverse friend
declaration, with its own special keyword.  Placed in a method it will name
a
class or method that you want to "break encapsulation" of.  And it will act
is
if the class or method named has a friend declaration pointing back to the
method with the break declaration statement.  With its own keyword that can
easily be grepped for you can make sure this statement is used only in unit
tests and not production code.  (In fact, it could be enabled as any other
language extension only if a compiler switch is present, and so you could
easily
ensure that only unit test projects have that compiler switch.)

Here are my questions about these approaches:

1.  What packaged Clang functionality do I need?

    a. Can approach 1 be done with strictly libclang (using the AST and the
lexer
       to guide modification of the source and to identify methods that need
       assembly thunks)?  Or do I need to step up to LibTooling +
LibASTMatchers
       (or LibAST).  Or does it need a plugin?  What is your recommendation?

    b. Can approach 2 be done with LibTooling + LibASTMatchers + minimal
changes
       to clang so it accepts the new grammar with new AST nodes to match.
My
       idea there is, having parsed and traversed my new "break
encapsulation"
       declarations, to go right to the definitions of the targeted class
and
       modify the AST in-place to have an actual friend declaration pointing
       back, and then to finish the compilation of the modified AST.

2.  How much of this work can be done on the Windows platform with Clang?
And
    can it be done with Visual Studio or do I need to use an alternate
native
    compiler for Windows?

    I've become aware of restrictions of developing on the Windows platform.
    Leave aside restrictions on what you can do with Clang/LLVM as a
compiler
    on Windows (e.g., at this time no exceptions or anything else that
requires
    compiler-rt) which would only affect my second approach.  Even so I've
found
    things that make Windows/Visual Studio less than a perfect development
    environment for Clang.

    For example, I can't confirm my compiled Clang/LLVM is correct (using
the VS
    12 Win64) platform because even though it compiles without error and the
    unit tests all pass I can't successfully run the "command line tests"
    (http://clang.llvm.org/hacking.html#testingCommands) as I reported here
    earlier (
http://lists.cs.uiuc.edu/pipermail/cfe-dev/2015-March/042170.html) - I
    got some help from the community there but the thread petered out and
I've
    been unable to continue with them.  (Just for reference I've attached to
    this email my last log of running the tests, with 122 unexpected
failures
    which are all some kind of lock error I don't understand.)

    Anyway, if I continue with the Windows platform can I be successful (or
    should I switch to Linux)?

This email has been quite long, and I apologize, but I'd really appreciate
your
help.  I'd like to start my Clang/LLVM development with some chance of
success
without getting greatly frustrated by not knowing some basic things that
everyone
who is working in the code "just knows" from experience.  So thanks in
advance!
And I hope to contribute back to the Clang/LLVM community in the future ...

-- David Bakin
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20150402/4b312673/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: command-line-tests.zip
Type: application/zip
Size: 26514 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20150402/4b312673/attachment.zip>


More information about the cfe-dev mailing list