# [cfe-users] How to find the physical end of an expression?

Richard Smith via cfe-users cfe-users at lists.llvm.org
Wed May 5 11:52:45 PDT 2021

```On Wed, 28 Apr 2021 at 13:53, Taylor, Max via cfe-users <
cfe-users at lists.llvm.org> wrote:

> Greetings.
>
>
>
> I’m building a source-to-source tool with clang. What I want to do is
> instrument stores made with the binary = operator. Currently, I’m running
> into problems with rewriting expressions that contain macro invocations.
> I’ve done some digging around, and I found some info  that helped with my
> understanding (e.g.
> https://stackoverflow.com/questions/24062989/clang-fails-replacing-a-statement-if-it-contains-a-macro).
> But I’m still not sure how to solve this problem.
>
>
>
> Concretely, suppose you have:
>
> #define a(x) ((x) * 10 + 1)
>
>
>
> class my_class {
>
>     int x;
>
>
>
> public:
>
>     int my_function() {
>
>         x = a(0);
>
>         return x;
>
>     }
>
> };
>
>
>
> I want to rewrite this into something like this:
>
> #ifndef _instrument_noclash
>
> #define _instrument_noclash(name, expr, instance_no)
>          \
>
>     (*({
>                                                        \
>
>         typeof(expr) *_t_instrument_no_clash##instance_no = &(expr);
>   \
>
>         _t_instrument_no_clash##instance_no;
>                       \
>
>         }))
>
> #endif
>
>
>
> #define a(x) ((x) * 10 + 1)
>
>
>
> class my_class {
>
>         int x;
>
> public:
>
>         int my_function() {
>
>                 _instrument_noclash("x",(this->x=((0) * 10 + 1)),0);
>
>                 return x;
>
>         }
>
> };
>
>
>
> The problem (to me) is simple: *how do I determine the physical location
> of the ending of the expression on the right hand sign of the = operator? *Without
> this knowledge, I end up overwriting the end of the statement. Scanning the
> APIs, it seems like there isn’t a simple way to do this. I’ve tried several
> ways to get the ending source location:
>
>    1. op->getEndLoc(), where op is an instance of BinaryOperator. This
>    doesn’t work, because the ending location in the AST is not the same as the
>    physical end location of the expression, due to macro expansion.
>    2. sm.getSpellingLoc(op->getEndLoc()), where sm is the source manager.
>    This just returns op->getEndLoc().
>    3. sm.getExpansionLoc(op->getEndLoc()). This is close, but the
>    location returned is the end of the macro name, so the macro arguments are
>    not removed.
>
> sm.getExpansionRange(op->getEndLoc()).getEnd() should work in this case.
In general what you're trying to do is not possible, because the assignment
expression might end in the middle of the macro expansion, though;
depending on exactly what your goal is, it might be easiest to first
preprocess the source file and then run your transform.

> Any suggestions (or easier way to achieve this same goal) are appreciated.
>
>
>
> -Max
> _______________________________________________
> cfe-users mailing list
> cfe-users at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-users/attachments/20210505/3105914e/attachment.html>
```