Bug 469079 - Kdevelop clang parser fails with GCC 13.1
Summary: Kdevelop clang parser fails with GCC 13.1
Status: RESOLVED FIXED
Alias: None
Product: kdevelop
Classification: Applications
Component: Language Support: CPP (Clang-based) (show other bugs)
Version: git master
Platform: Other Linux
: NOR normal
Target Milestone: ---
Assignee: kdevelop-bugs-null
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-04-27 21:40 UTC by Eugene Shalygin
Modified: 2023-09-15 08:57 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In: 5.13.231200
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Eugene Shalygin 2023-04-27 21:40:05 UTC
Parsing fails with clang 16 and GCC 13 when GCC is selected as "Compiler for path". clang complains on these types being undefined: _Float32, _Float64, _Float128, _Float32x, _Float64x, _Float128x. This is with the C++20 mode set by CMake, haven't tried other standards.
Comment 1 Igor Kushnir 2023-04-28 06:40:42 UTC
This is probably the same issue as the one detected by recent test_duchain_clang failures on the CI. From https://invent.kde.org/kdevelop/kdevelop/-/pipelines/381087/test_report:
/usr/include/stdlib.h:141:8: error: unknown type name '_Float32'
/usr/include/stdlib.h:147:8: error: unknown type name '_Float64'
/usr/include/stdlib.h:153:8: error: unknown type name '_Float128'
/usr/include/stdlib.h:159:8: error: unknown type name '_Float32x'
/usr/include/stdlib.h:165:8: error: unknown type name '_Float64x'
/usr/include/stdlib.h:234:10: error: unknown type name '_Float32'
/usr/include/stdlib.h:240:10: error: unknown type name '_Float64'
/usr/include/stdlib.h:246:4: error: unknown type name '_Float128'
/usr/include/stdlib.h:252:4: error: unknown type name '_Float32x'
/usr/include/stdlib.h:258:4: error: unknown type name '_Float64x'
/usr/include/stdlib.h:317:8: error: unknown type name '_Float32'
/usr/include/stdlib.h:324:8: error: unknown type name '_Float64'
/usr/include/stdlib.h:331:8: error: unknown type name '_Float128'
/usr/include/stdlib.h:338:8: error: unknown type name '_Float32x'
/usr/include/stdlib.h:345:8: error: unknown type name '_Float64x'
FAIL!  : TestDUChain::testGccCompatibility(x86intrin) parse error detected
   Loc: [/builds/kdevelop/kdevelop/plugins/clang/tests/test_duchain.cpp(1996)]
/usr/include/wchar.h:397:8: error: unknown type name '_Float32'
/usr/include/wchar.h:402:8: error: unknown type name '_Float64'
/usr/include/wchar.h:407:8: error: unknown type name '_Float128'
/usr/include/wchar.h:412:8: error: unknown type name '_Float32x'
/usr/include/wchar.h:417:8: error: unknown type name '_Float64x'
/usr/include/wchar.h:512:8: error: unknown type name '_Float32'
/usr/include/wchar.h:518:8: error: unknown type name '_Float64'
/usr/include/wchar.h:524:8: error: unknown type name '_Float128'
/usr/include/wchar.h:530:8: error: unknown type name '_Float32x'
/usr/include/wchar.h:536:8: error: unknown type name '_Float64x'
FAIL!  : TestDUChain::testGccCompatibility(sized-dealloc) parse error detected
   Loc: [/builds/kdevelop/kdevelop/plugins/clang/tests/test_duchain.cpp(1996)]
Comment 2 Igor Kushnir 2023-07-25 17:58:00 UTC
(In reply to Eugene Shalygin from comment #0)
> Parsing fails with clang 16 and GCC 13 when GCC is selected as "Compiler for
> path". clang complains on these types being undefined: _Float32, _Float64,
> _Float128, _Float32x, _Float64x, _Float128x. This is with the C++20 mode set
> by CMake, haven't tried other standards.
What are the practical consequences/problems? What workaround do you employ for this bug?

Does anyone know how to fix this issue properly? Milian fixed similar issues in two different ways:
https://commits.kde.org/kdevelop/ce41c99ba3cc67acd931b784e1c029f16cb1641e 
https://commits.kde.org/kdevelop/35ea746ddd49e872998152cc157152c2cb5b86ea

Is there a Clang command-line argument that enables these _Float* types? Or do we have to resort to injecting a preprocessor definition of each unknown type to its alternative spelling, or even to some other similar type if no such alternative spelling is supported by Clang?
Comment 3 Eugene Shalygin 2023-07-27 18:33:38 UTC
(In reply to Igor Kushnir from comment #2)

> What are the practical consequences/problems? What workaround do you employ
> for this bug?

Well, the IDE ceases to work as soon as you turn the C++20 mode on. As a workaround I provide those types as typedefs in the Language support/Defines page of the project settings dialog.

> Does anyone know how to fix this issue properly? 

I'd supply a header file that defines those types basing on Clang version, which can be force included.
Comment 4 Igor Kushnir 2023-07-27 19:01:01 UTC
(In reply to Eugene Shalygin from comment #3)
> Well, the IDE ceases to work as soon as you turn the C++20 mode on. As a
> workaround I provide those types as typedefs in the Language support/Defines
> page of the project settings dialog.
The failing KDevelop's tests use a default standard and C++14, so the issue isn't limited to C++20. Does the standard version make a difference in your case?
What do you typedef these types to?

> I'd supply a header file that defines those types basing on Clang version,
> which can be force included.
I agree that injecting type aliases would be safer than macros. Do you mean this option https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-include-file ?
Does the Clang version make a difference or only GCC's? If only GCC's, then I think the header should be included `if (isCpp)`, similarly to https://invent.kde.org/kdevelop/kdevelop/-/commit/35ea746ddd49e872998152cc157152c2cb5b86ea .

The header file can be installed with KDevelop, but then the exact path to the installed header would have to be found at run-time... Alternatively the header file can be stored in resources and copied into a temporary file at run-time (similarly to how the define files are stored in /tmp/kdevelop.*).
Comment 5 Eugene Shalygin 2023-07-27 19:10:54 UTC
(In reply to Igor Kushnir from comment #4)
> The failing KDevelop's tests use a default standard and C++14, so the issue
> isn't limited to C++20. Does the standard version make a difference in your
> case?

Yes, definitely. Everything works fine in the C++17 mode.

> What do you typedef these types to?
float, double, and __float128.
 
> I agree that injecting type aliases would be safer than macros. Do you mean
> this option
> https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-
> include-file ?

Yes, the force-include option.

> Does the Clang version make a difference or only GCC's? If only GCC's, then
> I think the header should be included `if (isCpp)`, similarly to
> https://invent.kde.org/kdevelop/kdevelop/-/commit/
> 35ea746ddd49e872998152cc157152c2cb5b86ea .

I haven't tried clang-15, but why would it work if the newer version still has no these types? https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html says they are a new addition in C.

> The header file can be installed with KDevelop, but then the exact path to
> the installed header would have to be found at run-time... Alternatively the
> header file can be stored in resources and copied into a temporary file at
> run-time (similarly to how the define files are stored in /tmp/kdevelop.*).

I see no big difference from the user point of view, and I guess it is not a big deal to find out own installation prefix at run-time?
Comment 6 Eugene Shalygin 2023-07-27 19:13:55 UTC
Although the same GCC page states "These types are not supported when compiling C++." I don't understand what's going on then.
Comment 7 Igor Kushnir 2023-07-27 19:27:39 UTC
(In reply to Eugene Shalygin from comment #5)
> Yes, definitely. Everything works fine in the C++17 mode.
Strange. Will have to investigate this.

> I haven't tried clang-15, but why would it work if the newer version still
> has no these types? https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html
> says they are a new addition in C.
I thought so. Did "basing on Clang version" in your previous comment refer to a future Clang version that will contain these types too?

OK, so no limiting to isCpp, because the kdevclang plugin supports only C and C++, both of which contain these types.

(In reply to Eugene Shalygin from comment #6)
> Although the same GCC page states "These types are not supported when
> compiling C++." I don't understand what's going on then.
Yes, I also noticed that sentence. Maybe C++20 and later (but not C++ 17 or earlier) includes the C standard version that contains these types?
Comment 8 Igor Kushnir 2023-07-27 19:42:57 UTC
From https://codebrowser.dev/gcc/include/x86_64-linux-gnu/bits/floatn-common.h.html:
> No configurations support _Float128x or, as of GCC 7, have compiler
> support for a type meeting the requirements for _Float128x.

> #   if !__GNUC_PREREQ (7, 0) || defined __cplusplus
> typedef _Float128 _Float64x;
> #   endif
KDevelop should probably typedef _Float128 to double, not __float128, to match GCC's defines.

It appears that these types are always defined in C++, not limited to C++20. Maybe the C++ standard version affects something else. After all, GCC's floatn-common.h header should be parsed by libclang too, but maybe it is parsed wrongly for some reason. Will have to investigate this.
Comment 9 Igor Kushnir 2023-07-27 19:44:34 UTC
(In reply to Igor Kushnir from comment #8)
> KDevelop should probably typedef _Float128 to double, not __float128, to
> match GCC's defines.
Or rather to "long double":
> typedef long double _Float64x;
Comment 10 Igor Kushnir 2023-07-28 18:36:05 UTC
(In reply to Eugene Shalygin from comment #0)
> Parsing fails with clang 16 and GCC 13 when GCC is selected as "Compiler for
> path". clang complains on these types being undefined: _Float32, _Float64,
> _Float128, _Float32x, _Float64x, _Float128x. This is with the C++20 mode set
> by CMake, haven't tried other standards.
I cannot reproduce this bug with a single-file CMake project created from Standard=>Terminal=>CMake C++ KDevelop project template:
* Clang version 15.0.7 and GCC version 13.1.1;
* `set(CMAKE_CXX_STANDARD 20)` in CMakeLists.txt;
* C++ profile: c++2a;
* Compiler for path: GCC.
Could you attach a small example project that manifests the bug on your system?
Comment 11 Eugene Shalygin 2023-07-28 18:46:42 UTC
I'm building GCC 13.2, once it's ready I create an MWE, or maybe the update resolves the issue.
Comment 12 Eugene Shalygin 2023-07-30 11:12:41 UTC
The issue has not went away with update to GCC 13.2, so I sat down to create an MWE only to discover that the problem is not directly controlled by the C++20 mode.

There is the following block for each _Float type in the /usr/include/bits/floatn-common.h file:
#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
typedef float _Float16 __attribute__ ((__mode__ (__HF__)));
#  endif

When the "Compiler for path" is set to "GCC" in the project options dialog, and GCC version is  >= 13, the Clang parser then runs into "fatal error: too many errors emitted, stopping now [-ferror-limit=]". My guess is __GNUC__ is defined somewhere to the actual GCC version, which prevents glibc to define those typedefs itself.

Maybe the C++20 mode changed the list of includes so that the error state is triggered quicker.
Comment 13 Igor Kushnir 2023-07-30 13:58:12 UTC
> There is the following block for each _Float type in the
> /usr/include/bits/floatn-common.h file:
> #  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13,
> 0))
> typedef float _Float16 __attribute__ ((__mode__ (__HF__)));
> #  endif
Same on my system.
> When the "Compiler for path" is set to "GCC" in the project options dialog,
> and GCC version is  >= 13, the Clang parser then runs into "fatal error: too
> many errors emitted, stopping now [-ferror-limit=]". 
So there is no fatal error in a single-file project? Are the "unknown type name" errors printed somewhere?
> /usr/include/stdlib.h:141:8: error: unknown type name '_Float32'
Comment 14 Eugene Shalygin 2023-08-01 06:45:17 UTC
> So there is no fatal error in a single-file project? Are the "unknown type
> name" errors printed somewhere?
> > /usr/include/stdlib.h:141:8: error: unknown type name '_Float32'

I see errors in the terminal when run KDEV_CLANG_DISPLAY_DIAGS=1 CLEAR_DUCHAIN_DIR=1 kdevelop, and the IDE shows error when I open those glibc headers.
Comment 15 Bug Janitor Service 2023-08-19 18:28:49 UTC
A possibly relevant merge request was started @ https://invent.kde.org/kdevelop/kdevelop/-/merge_requests/476
Comment 16 Igor Kushnir 2023-09-15 08:57:15 UTC
Git commit 6c44e08795219bf14e30d2384d6ac06aa3b59517 by Igor Kushnir.
Committed on 15/09/2023 at 10:55.
Pushed by igorkushnir into branch 'master'.

Improve GCC compatibility by including floating typedefs

The included _FloatX typedefs eliminate the following parse errors when
GCC 13 is selected as "Compiler for path":
    /usr/include/stdlib.h:141:8: error: unknown type name '_Float32'
    /usr/include/stdlib.h:147:8: error: unknown type name '_Float64'
    /usr/include/stdlib.h:153:8: error: unknown type name '_Float128'
    /usr/include/stdlib.h:159:8: error: unknown type name '_Float32x'
    /usr/include/stdlib.h:165:8: error: unknown type name '_Float64x'

There are so many such errors that parsing sometimes fails altogether:
    fatal error: too many errors emitted, stopping now [-ferror-limit=]
This fatal error can be reproduced by including <bits/stdc++.h> in
main.cpp and inserting `set(CMAKE_CXX_STANDARD 20)` in CMakeLists.txt of
a single-file hello-world C++ project; selecting "c++2a" C++ profile and
"GCC" as Compiler for path on the project's Language Support
configuration page and restarting KDevelop as
    KDEV_CLANG_DISPLAY_DIAGS=1 CLEAR_DUCHAIN_DIR=1 kdevelop

This change also fixes the testGccCompatibility test (both data rows) in
test_duchain-clang.

The included _FloatX typedefs introduce type aliases instead of GCC's
separate types. This causes the following parse errors:
    /usr/include/math.h:1396:19: error: redefinition of '__iseqsig_type<float>'
    /usr/include/math.h:1406:19: error: redefinition of '__iseqsig_type<double>'
    /usr/include/math.h:1432:19: error: redefinition of '__iseqsig_type<double>'
    /usr/include/math.h:1442:19: error: redefinition of '__iseqsig_type<long double>'
because of template specializations like this:
    template<> struct __iseqsig_type<_Float32>
Fortunately, these new redefinition errors are much fewer and don't
cause the "too many errors" fatal error.

The _FloatX typedefs are included in C programs only when GCC version is
7 or later and in C++ programs only when GCC version is 13 or later,
because earlier GCC versions don't provide these types and glibc
provides their substitutes for earlier GCC versions in its
bits/floatn-common.h header:
    #  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
    typedef float _Float32;
    #  endif

Include also a __float80 typedef to eliminate the following parse error:
    /usr/include/c++/13.2.1/compare:715:33: error: unknown type name '__float80'
According to the documentation, GCC provides __float80 since at least
version 7:
https://gcc.gnu.org/onlinedocs/gcc-7.5.0/gcc/Floating-Types.html#Floating-Types

The changes in ClangCodeCompletionContext::completionItems() prevent
unwanted _FloatX TypedefDecl completions, which would otherwise make
TestCodeCompletion::testIgnoreGccBuiltins() fail.

Note: c791359763cd862f93ad9f91fa628d20e1e630f2 removed a similarly
included workaround header gcc_compat.h.
FIXED-IN: 5.13.231200

M  +2    -1    plugins/clang/CMakeLists.txt
M  +49   -3    plugins/clang/codecompletion/context.cpp
A  +35   -0    plugins/clang/duchain/gccCompatibility/additional_floating_types.h     [License: LGPL(v2.0+)]
M  +18   -1    plugins/clang/duchain/parsesession.cpp

https://invent.kde.org/kdevelop/kdevelop/-/commit/6c44e08795219bf14e30d2384d6ac06aa3b59517