Matching method defined outside a class declaration

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.

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?

Thanks,

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".

Cheers,
/Manuel

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.

    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

            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);

        On Tue, Sep 17, 2013 at 2:24 PM, Jesper Eskilson
        <jesper.eskilson@iar.com <mailto:jesper.eskilson@iar.**com<jesper.eskilson@iar.com>
>
        <mailto:jesper.eskilson@iar.**com <jesper.eskilson@iar.com>

        <mailto:jesper.eskilson@iar.**com <jesper.eskilson@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);

Sorry for the late answer, I was on vacation.

The solution we're using is to use a combination of the file name and the
fully qualified name as key.