I am trying to write a clang-tidy check to rename struct members.
For this, I need to match MemberExpr nodes that access a certain member, from certain structs.
In the following code, it should only match all uses of member on types S1 and S2 (8 matches in total).
typedef struct S1 { int member; int v; } S1; typedef struct MS1 {S1 s1; } MS1;
typedef struct S2 { int member; int v; } S2; typedef struct MS2 {S2 s2; } MS2;
typedef struct S3 { int member; int v; } S3; typedef struct MS3 {S2 s3; } MS3;
void f() {
S1 *s1a, s1b; MS1 *ms1a, ms1b;
S2 *s2a, s2b; MS2 *ms2a, ms2b;
S3 *s3a, s3b; MS3 *ms3a, ms3b;
(void)s1a->member; (void)s1b.member; (void)ms1a->s1.member; (void)ms1b.s1.member;
(void)s2a->member; (void)s2b.member; (void)ms2a->s2.member; (void)ms2b.s2.member;
(void)s3a->member; (void)s3b.member; (void)ms3a->s3.member; (void)ms3b.s3.member;
(void)s1a->v; (void)s1b.v; (void)ms1a->s1.v; (void)ms1b.s1.v;
(void)s2a->v; (void)s2b.v; (void)ms2a->s2.v; (void)ms2b.s2.v;
(void)s3a->v; (void)s3b.v; (void)ms3a->s3.v; (void)ms3b.s3.v;
}
The matcher memberExpr(member(hasName("member"))) is too broad and also includes type S3.
How can I limit the matcher to only return those member accesses of S1 and S2?
Thanks.
Perhaps surprisingly, the
hasNameselector can be used to restrict the member's containing class or namespace as well as its simple identifier name. Quoting the linked documentation:This means we can match
S1::memberandS2::memberlike this:We can also use
matchesNameto express the conditionality using a regular expression:With either of the above, I get eight matches on your testcase, but only after fixing the apparent typo in this line:
which I think should be: