Best way to determine if preprocessor directives live in a source range?

I'm enhancing clang-tidy to replace:

    if (expr)
      return true;
    return false;

with

    return expr;

I am running the transformation on the LLVM/clang code as a test bed.
In the course of examining the results it turned up this one in
llvm/lib/Analysis/ConstantFolding.cpp:

with

/// Test if a floating-point exception was raised.
static inline bool llvm_fenv_testexcept() {
   int errno_val = errno;
- if (errno_val == ERANGE || errno_val == EDOM)
- return true;
-#if defined(HAVE_FENV_H) && HAVE_DECL_FE_ALL_EXCEPT && HAVE_DECL_FE_INEXACT
- if (fetestexcept(FE_ALL_EXCEPT & ~FE_INEXACT))
- return true;
-#endif
- return false;
+ return errno_val == ERANGE || errno_val == EDOM;
}
} // End namespace

Clearly, this is not behavior preserving. According to the AST, the
part that is #if'ed out doesn't exist.

What's the best way to identify such things so that the tool's default
behavior would be to leave these alone?

PS: Mail filters are blocking my messages, so ignore this, its
only for them. Lorem ipsum dolor sit amet, consectetur adipiscing
elit. Phasellus consequat ullamcorper mollis. Sed blandit semper tortor
ultricies dictum. Proin hendrerit et quam in sagittis. Maecenas vel
blandit ante, in auctor sem. Phasellus condimentum leo vel finibus
viverra. Duis fermentum sollicitudin est, ac iaculis lectus auctor vel.
Nam condimentum nulla feugiat, venenatis nibh a, elementum nulla. Nulla
vitae malesuada eros. Nulla cursus maximus ligula non hendrerit.

Curabitur lobortis nulla vel sapien posuere, id aliquam orci
bibendum. Vestibulum at vulputate risus. Proin in purus commodo,
tempus lectus vitae, faucibus nunc. Aenean congue faucibus elit, sit
amet facilisis nibh ultrices eget. Nam pulvinar leo ac nunc ultricies,
nec tincidunt nulla tincidunt. Etiam placerat felis tellus, ut ultricies
nunc ultricies quis. In placerat sapien nec ultricies mattis. Integer
sed tempor orci, ac imperdiet orci. Integer ac augue et augue convallis
faucibus.

This problem is relevant to comments as well.

I’m not sure if there’s an easy solution, but some hand-rolled options are available. One way is to re-lex the range and try to find preprocessor directives (and comments) by analyzing token sequences. Another approach would be to subscribe to PPCallbacks, gather all locations of #if/#else/… into a set and then look up any values in this set that fall between the bounds of your range.

– Alex

In article <CAOweq9+4kdBKeiKBg+SXzKs3SN-RNE7NQG7ysv4N4tsBCcWiCA@mail.gmail.com>,
    Alexander Kornienko <alexfh@google.com> writes:

This problem is relevant to comments as well.

I'm not sure if there's an easy solution, but some hand-rolled options are
available. One way is to re-lex the range and try to find preprocessor
directives (and comments) by analyzing token sequences. Another approach
would be to subscribe to PPCallbacks, gather all locations of #if/#else/...
into a set and then look up any values in this set that fall between the
bounds of your range.

Yeah, I think with PPCallbacks you could build a function that would
tell you something about preprocessor blocks based on source location.

For comments, I thought there was something about sprinkling comment
nodes into the AST? Isn't this how the doxygen thing works?

I think getting the PreprocessingRecord (http://clang.llvm.org/doxygen/classclang_1_1PreprocessingRecord.html) from the Preprocessor would also work; a PreprocessedEntity seems to contain source information that you can use: http://clang.llvm.org/doxygen/classclang_1_1PreprocessedEntity.html

Nice, didn’t know about that. PreprocessingRecord::getPreprocessedEntitiesInRange() seems to be what Richard is looking for.