LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 37990 - -frewrite-includes doesn't handle __has_include in macro expansion
Summary: -frewrite-includes doesn't handle __has_include in macro expansion
Status: NEW
Alias: None
Product: clang
Classification: Unclassified
Component: C++ (show other bugs)
Version: trunk
Hardware: All All
: P enhancement
Assignee: Unassigned Clang Bugs
URL:
Keywords:
: 43982 (view as bug list)
Depends on:
Blocks:
 
Reported: 2018-06-29 09:37 PDT by Alexander Richardson
Modified: 2019-12-09 03:37 PST (History)
6 users (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Alexander Richardson 2018-06-29 09:37:09 PDT
I was trying to get a reduced test case for a crash in libc++ and QtBase but I couldn't use clang -cc1 on the preprocessed source. It would fail with compilation errors instead of the assertion I was trying to track down.
It turns out that both of these projects have a custom macro wrapping __has_include()
and -frewrite-includes does not rewrite that to 0 or 1 so the invocation fails on the rewritten source.

I have added a local hack to handle the Qt and libc++ macro names in https://github.com/CTSRD-CHERI/clang/commit/05aafbf0c6cd7099b7d53466b58a8b8214d29f33 but I guess a real fix is needed instead. If people are interested I'm happy to put it up for review. Especially the libc++ macro is probably used in lots of crash reproducers so it might help with getting a reduced test case from C++-specific crashes.
Comment 1 Richard Smith 2018-07-08 12:50:42 PDT
The existence of QT_HAS_INCLUDE is a mistake; that fundamentally doesn't work. Instead of trying to work around this mistake in the compiler, you should get Qt to fix their macro. And we should do the same for libc++ where we made the same mistake.

The characters after '__has_include(' have special lexing rules that can't possibly be applied when __has_include is generated by a macro. And this kind of usage will lead to problems such as the one you're seeing here. Per Clang's documentation / SD-6, the correct way to deal with this is:

#ifndef __has_include
#define __has_include(...) 0
#endif

not to define your own wrapper macro.

The C++ standard appears to be missing a rule that says that a __has_include token produced by macro expansion results in undefined behavior (matching the corresponding rule for a 'defined' token produced by macro expansion), but that seems to just be a wording oversight. You should not expect this to work.
Comment 2 Alexander Richardson 2018-07-08 14:55:19 PDT
Thanks for the explanation! I have no idea why Qt or libc++ added another macro so 
I will try to submit a patch to Qt remove those uses. I'll also try to do it for libc++.

Should I also open another bug that we should be diagnosing use of __has_include in a macro?
Comment 3 Richard Smith 2018-07-09 16:56:40 PDT
We can repurpose this bug to cover Clang's failure to diagnose __has_include misuse if you prefer. It was pointed out on the C++ core reflector that the code in question is ill-formed per:

http://eel.is/c++draft/cpp.cond#7.sentence-2

(because the __has_include token is not permitted to appear in a #define directive at all.) I've started a discussion in the reflector over exactly which cases should be ill-formed.
Comment 4 Emilio Cobos Álvarez (:emilio) 2019-11-12 10:20:11 PST
*** Bug 43982 has been marked as a duplicate of this bug. ***
Comment 5 Tor Arne Vestbø 2019-12-08 04:23:47 PST
(In reply to Richard Smith from comment #3)

> (because the __has_include token is not permitted to appear in a #define
> directive at all.) I've started a discussion in the reflector over exactly
> which cases should be ill-formed.

I'm going to remove the QT_HAS_INCLUDE macro from Qt and replace it with fallback #define __has_include(...) 0 suggested above.

In Qt we also have similar macro wrappers for:

 * __has_builtin
 * __has_attribute
 * __has_cpp_attribute
 * __has_include_next

Are these okey to replace with the same fallback #define?

http://eel.is/c++draft/cpp.cond#7.sentence-2 only mentions __has_cpp_attribute explicitly, but based on https://clang.llvm.org/docs/LanguageExtensions.html it looks like the fallback #define is recommended for them all?

(AFAIK the choice in Qt of a wrapper macro was due to not being sure if it was okey to #define internal/reserved identifiers such as __has_include).
Comment 6 Tor Arne Vestbø 2019-12-09 03:37:12 PST
Qt fix in https://codereview.qt-project.org/c/qt/qtbase/+/284037