最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - How do I match builtin -> usages? - Stack Overflow

programmeradmin3浏览0评论

Take this silly C++ source file:

#include <optional>

struct Foo {
    int hello() const;
};

struct P1 {
    P1* another() const;
    int give() const;
};

auto fun() {
    return std::make_optional(std::make_optional(Foo{}));
}

int main()
{
    int * x = new int{3};
    P1 * p{};
    (*p->another()).another()->another();
    p->another()->give();
    p->give();
    return *x + (*fun())->hello() + p->give();
}

If I execute the following command on it,

clang-query -c "match expr(
    anyOf(
        unaryOperator(
            hasOperatorName(\"*\")
        ),
        unaryOperator(
            hasOperatorName(\"->\")
        ),
        cxxOperatorCallExpr(
            hasOverloadedOperatorName(\"*\")
        ),
        cxxOperatorCallExpr(
            hasOverloadedOperatorName(\"->\")
        )
    ), isExpansionInMainFile()
)" debugging.cpp | less

I get an output that ends like this (I've filtered out all matches happening in included headers):

/home/enrico/debugging.cpp:20:6: note: "root" binds here
   20 |     (*p->another()).another()->another();
      |      ^~~~~~~~~~~~~

Match #55:

/home/enrico/debugging.cpp:23:12: note: "root" binds here
   23 |     return *x + (*fun())->hello() + p->give();
      |            ^~

Match #56:

/home/enrico/debugging.cpp:23:17: note: "root" binds here
   23 |     return *x + (*fun())->hello() + p->give();
      |                 ^~~~~~~~~~

Match #57:

/home/enrico/debugging.cpp:23:18: note: "root" binds here
   23 |     return *x + (*fun())->hello() + p->give();
      |                  ^~~~~~
57 matches.

Which shows that the built-in -> has not been matched, whereas both the built-in and overloaded *s were matched.

What am I doing wrong?

Take this silly C++ source file:

#include <optional>

struct Foo {
    int hello() const;
};

struct P1 {
    P1* another() const;
    int give() const;
};

auto fun() {
    return std::make_optional(std::make_optional(Foo{}));
}

int main()
{
    int * x = new int{3};
    P1 * p{};
    (*p->another()).another()->another();
    p->another()->give();
    p->give();
    return *x + (*fun())->hello() + p->give();
}

If I execute the following command on it,

clang-query -c "match expr(
    anyOf(
        unaryOperator(
            hasOperatorName(\"*\")
        ),
        unaryOperator(
            hasOperatorName(\"->\")
        ),
        cxxOperatorCallExpr(
            hasOverloadedOperatorName(\"*\")
        ),
        cxxOperatorCallExpr(
            hasOverloadedOperatorName(\"->\")
        )
    ), isExpansionInMainFile()
)" debugging.cpp | less

I get an output that ends like this (I've filtered out all matches happening in included headers):

/home/enrico/debugging.cpp:20:6: note: "root" binds here
   20 |     (*p->another()).another()->another();
      |      ^~~~~~~~~~~~~

Match #55:

/home/enrico/debugging.cpp:23:12: note: "root" binds here
   23 |     return *x + (*fun())->hello() + p->give();
      |            ^~

Match #56:

/home/enrico/debugging.cpp:23:17: note: "root" binds here
   23 |     return *x + (*fun())->hello() + p->give();
      |                 ^~~~~~~~~~

Match #57:

/home/enrico/debugging.cpp:23:18: note: "root" binds here
   23 |     return *x + (*fun())->hello() + p->give();
      |                  ^~~~~~
57 matches.

Which shows that the built-in -> has not been matched, whereas both the built-in and overloaded *s were matched.

What am I doing wrong?

Share Improve this question asked Feb 17 at 14:22 EnlicoEnlico 28.5k8 gold badges67 silver badges149 bronze badges 3
  • I’m less familiar with clang-query, is it like clang-format in that it doesn’t utilize the AST? Or should you be trying this on code that actually compiles? I’d recommend the latter, even for clang-format. – sweenish Commented Feb 17 at 14:45
  • 1 @sweenish the code compiles, but doesn't link. There is std::optional::operator* – Caleth Commented Feb 17 at 14:52
  • Have you dumped AST of above code? – Jarod42 Commented Feb 17 at 16:00
Add a comment  | 

1 Answer 1

Reset to default 2

Clang's AST labels unary * as a unary operator, but doesn't label -> as an operator at all.

I don't see a clean way of finding every use of ->, without cases of implicit this, but if that is acceptable then you'd need

anyOf(
    unaryOperator(
        hasOperatorName(\"*\")
    ),
    cxxOperatorCallExpr(
        hasOverloadedOperatorName(\"*\")
    ),
    memberExpr(
        isArrow()
    ), 
    cxxDependentScopeMemberExpr(
        isArrow()
    ),
    unresolvedMemberExpr(
        isArrow()
    )
)

which, for the file in the question would produce

Match #172:

/path/to/file.cpp:20:5: note: "root" binds here
   20 |     (*p->another()).another()->another();
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Match #173:

/path/to/file.cpp:20:6: note: "root" binds here
   20 |     (*p->another()).another()->another();
      |      ^~~~~~~~~~~~~

Match #174:

/path/to/file.cpp:20:7: note: "root" binds here
   20 |     (*p->another()).another()->another();
      |       ^~~~~~~~~~

Match #175:

/path/to/file.cpp:21:5: note: "root" binds here
   21 |     p->another()->give();
      |     ^~~~~~~~~~~~~~~~~~

Match #176:

/path/to/file.cpp:21:5: note: "root" binds here
   21 |     p->another()->give();
      |     ^~~~~~~~~~

Match #177:

/path/to/file.cpp:22:5: note: "root" binds here
   22 |     p->give();
      |     ^~~~~~~

Match #178:

/path/to/file.cpp:23:12: note: "root" binds here
   23 |     return *x + (*fun())->hello() + p->give();
      |            ^~

Match #179:

/path/to/file.cpp:23:17: note: "root" binds here
   23 |     return *x + (*fun())->hello() + p->give();
      |                 ^~~~~~~~~~~~~~~

Match #180:

/path/to/file.cpp:23:18: note: "root" binds here
   23 |     return *x + (*fun())->hello() + p->give();
      |                  ^~~~~~

Match #181:

/path/to/file.cpp:23:37: note: "root" binds here
   23 |     return *x + (*fun())->hello() + p->give();
      |                                     ^~~~~~~
181 matches.

(having excluded all the matches happening in library code rather than in your file).

发布评论

评论列表(0)

  1. 暂无评论