[cfe-dev] Matching method defined outside a class declaration

Jesper Eskilson jesper.eskilson at iar.com
Tue Sep 17 06:27:39 PDT 2013


On 09/17/2013 03:20 PM, Manuel Klimek wrote:
> On Tue, Sep 17, 2013 at 3:17 PM, Jesper Eskilson 
> <jesper.eskilson at iar.com <mailto:jesper.eskilson at iar.com>> wrote:
>
>     On 09/17/2013 02:50 PM, Manuel Klimek wrote:
>
>         On Tue, Sep 17, 2013 at 2:24 PM, Jesper Eskilson
>         <jesper.eskilson at iar.com <mailto:jesper.eskilson at iar.com>
>         <mailto:jesper.eskilson at iar.com
>         <mailto:jesper.eskilson at iar.com>>> wrote:
>
>
>             Hello,
>
>             I'm trying to write an AST matcher rule which is able to match
>             method definitions. Given the following C++ source code:
>
>                 class B
>                 {
>                   void foo();
>                   void bar() {
>                     int a_local_variable_in_bar;
>                   }
>                 };
>
>                 void B::foo()
>                 {
>                   int a_local_variable_in_foo;
>                 }
>
>                 B b
>
>                 int main()
>                 {
>                 }
>
>
>             I would like a matcher which can tell me where instances
>         of B are
>             created and also give me the definitions of its methods
>         (in this
>             case "foo" and "bar").
>
>                   StatementMatcher m = constructExpr(
>                       hasType(
>                           recordDecl(isSameOrDerivedFrom("B"),
>                 hasMethod(methodDecl(isDefinition()).bind("method")))));
>
>
>             But it will only give me the definition of "bar", and not the
>             defintion of "foo" which is declared outside the class.
>
>
>         This is because hasMethod will not give you anything outside
>         of the class definition. The reason is that you often don't
>         see out-of-class method definitions of when you have a class
>         definition.
>
>         If you already know the name of the class (as you specify it
>         in your matcher), why do you want to write this matcher in the
>         first place? You'll not be able to match all constructor calls
>         and method definitions in general, as classes may be
>         instantiated in a translation unit where not all method
>         definitions are visible.
>
>         If you have more details on what you're actually trying to do
>         (on a higher level) we might be able to help more...
>
>             If I cannot do this with matchers, is there a way to get
>         to the
>             definition of "foo" given the declaration of the class B?
>
>
>         No, as you might see the class definition in a header where
>         foo is not visible. Usually you'll want to go the other way -
>         find all method definitions of class "B".
>
>
>     I have a bunch of class instantiations in a large codebase which
>     look like this
>
>     A a1("banana", new B1);
>     A a2("apple", new B2);
>     A a3("ananas", new B2);
>
>     B1, B2, B3, all inherit from B which defines a method "foo"
>     (outside the declaration of B). This definition may or may not be
>     overridden in B1/B2/B3.
>
>     I want to be able to generate output on the form:
>
>     banana:
>         void foo() { /* this is the foo implementation in class B1 */ }
>     apple:
>         void foo() { /* this is the foo implementation in class B2 */ }
>     ananas:
>         void foo() { /* this is the foo implementation in class B3 */ }
>
>     I was thinking about first matching out all the different
>     definitions of foo, and then in a separate matcher match the
>     construction expressions of a1-a3, but I'm not sure of the best
>     way to "share" information between matchers.
>
>
> Create intermediate output:
> - output all paremeter combinations ("banana", "B1"), ("apple, "B2")
> - output all method definitions ("B1", "void foo() { ... }"), ...
> store the intermediate results. After running over all translation 
> units, do a "reduce" step where you combine the information by using 
> the class as the key

How do construct the key so that I get unique names for B1-B3, for 
example if they are qualified by namespaces? Typically it will look like 
this

A a1("banana", new fruits::behavior);
A a1("tomato", new vegetables::behavior);

>
>
>     -- 
>     *Jesper Eskilson* /Development Engineer/
>     IAR Systems AB
>     Box 23051, Strandbodgatan 1
>     SE-750 23 Uppsala, SWEDEN
>     E-mail: jesper.eskilson at iar.com <mailto:jesper.eskilson at iar.com>
>     <mailto:jesper.eskilson at iar.com <mailto:jesper.eskilson at iar.com>>
>     Website: www.iar.com <http://www.iar.com>
>     <http://www.iar.com> Twitter: www.twitter.com/iarsystems
>     <http://www.twitter.com/iarsystems>
>     <http://www.twitter.com/iarsystems>
>
>


-- 
*Jesper Eskilson* /Development Engineer/
IAR Systems AB
Box 23051, Strandbodgatan 1
SE-750 23 Uppsala, SWEDEN
E-mail: jesper.eskilson at iar.com <mailto:jesper.eskilson at iar.com> 
Website: www.iar.com
<http://www.iar.com> Twitter: www.twitter.com/iarsystems 
<http://www.twitter.com/iarsystems>



More information about the cfe-dev mailing list