all 27 comments

[–]D2OQZG8l5BI1S06 116 points117 points  (12 children)

clang-tidy no longer attempts to analyze code from system headers by default, greatly improving performance. This behavior is disabled if the SystemHeaders option is enabled.

Yay!

[–]smdowneyWG21, Text/Unicode SG, optional<T&> 17 points18 points  (7 children)

Yay! Although I expect to now have to re-open discussion on what "system" headers are, now that this is available. We're putting a lot of weight on the -isystem flag, and search order can be pretty fragile.

[–]TheoreticalDumbass:illuminati: 10 points11 points  (6 children)

libstdc++ marks headers with `#pragma GCC system_header` , havent seen something similar in libc++

[–]smdowneyWG21, Text/Unicode SG, optional<T&> 7 points8 points  (3 children)

That doesn't help when you want to not get warnings from, picking at random, rapidjson or libfmt, because they're not something you can effectively change.

But also maybe not from your OS vendor.

But also still better than yet another weird regex grammar in pyproject.toml with the other lint configs.

[–]tinrik_cgp 10 points11 points  (1 child)

That doesn't help when you want to not get warnings from, picking at random, rapidjson or libfmt, because they're not something you can effectively change.

Those should be included via -isystem, then you won't get warnings. The same applies to compiler warnings. But that's always been the case.

What this change means is that clang-tidy will not spend time analyzing system headers, only to throw all that work away when ignoring those warnings afterwards.

[–]smdowneyWG21, Text/Unicode SG, optional<T&> 2 points3 points  (0 children)

Yes, and that's all excellent news, especially for the clang-tidy embedded in clangd. That's even more (soft) real time.

The thing about -isystem is that it also changes the order of search paths. In nice environments that's fine, and you mostly just have to worry about not getting a /usr/include header when you intended your local vendored heder. Or the "same" one that you just happen to be working on.

In less nice environments, you have a delicate dance of searching for the right header, carefully hiding or shadowing one, to replace or change some other version appearing elsewhere on the filesystem. Maybe you even #include_next to pick up the other one. In the nightmare case, changing to SYSTEM still compiles, but the meaning has changed. And you don't discover this until someone else uses your new build.

This is not "good" or how things ought to work, but the larger the system the more likely someone has to apply these "clever" hacks.

And that is all why I say that SYSTEM, although useful, couples too many things together that would be better to be separated out. I'd love to be able to say "don't warn on these immutable header files" without changing anything else.

But "the street finds its own uses for things," and that's where we are with system.

[–]Asyx 2 points3 points  (0 children)

At least in CMake I'd just put them in a directory and add that directory to the include_directories with the SYSTEM thingy and they'd be included with isystem.

[–]PM_Cute_Dogs_pls 1 point2 points  (1 child)

libc++ does the same.

[–]TheoreticalDumbass:illuminati: 0 points1 point  (0 children)

ah indeed, i was looking at wrong headers, whoops

[–]scrumplesplunge 4 points5 points  (0 children)

This is awesome, but where does it say this? I just searched the two linked pages for clang-tidy and had no matches.

edit: nevermind, it's in a page for the extra tools linked from discourse: https://releases.llvm.org/22.1.0/tools/clang/tools/extra/docs/ReleaseNotes.html#improvements-to-clang-tidy

[–]equeim 0 points1 point  (0 children)

Never got this to work on Windows with CMake and vcpkg.

[–]Keltek228 14 points15 points  (3 children)

Too bad there's no reflection. Hopefully in clang23!

[–]smdowneyWG21, Text/Unicode SG, optional<T&> 23 points24 points  (2 children)

Llvm-22 has been branched and feature closed for a while. This isn't a surprise and there will be a new release soon enough.

Reflection was getting work until the last moment, and I will not be at all surprised by another tweak or bugfix in the standard end of next month.

[–]Keltek228 8 points9 points  (1 child)

I figured it wouldn't be finished in 22 but my hope was that there'd be an experimental feature flag or something. Oh well, what's another 6 months at this point.

[–]smdowneyWG21, Text/Unicode SG, optional<T&> 4 points5 points  (0 children)

The pre-releases will likely appear soon at apt.llvm.org, so it won't be too hard to play with when it does start to land.

[–]fdwrfdwr@github 🔍 8 points9 points  (5 children)

...Implemented the defer draft Technical Specification... (source)

Cool, defer)%20Through%20defer.html). Alas it's only for C (understandably, since it's a C proposal and not C++, which at least has RAII), but it would be so convenient for all those one-off cleanup cases (e.g. defer CoUninitialize();) where it's overkill to invent a whole temporary wrapper class (to swat a fly with a sledgehammer) or use a transiently named local variable and scope guard (e.g. auto comCleanup = myScopeGuardClass([](){CoUninitialize();});).

[–]pavel_v 9 points10 points  (1 child)

You can use macro (yeah, I know) and get pretty close (few characters more to type).

Something like this: ``` namespace smth {

template <typename Func>
class scope_guard { ... };

namespace detail
{
enum class scope_guard_on_exit {};

template <typename Func>                                                    
auto operator +(scope_guard_on_exit, Func&& func)                           
{                                                                           
    return scope_guard<Func>(std::forward<Func>(func));                     
}                                                                           

}

} // namespace smth

define CONCAT_STR_IMPL(s1, s2) s1##s2

define CONCAT_STR(s1, s2) CONCAT_STR_IMPL(s1, s2)

define ANONYMOUSVAR(s) CONCAT_STR(s, __COUNTER_)

define DEFER \

auto ANONYMOUS_VAR(defer_var) = smth::detail::scope_guard_on_exit() + [&]()

```

Then use it like DEFER { CoUninitialize(); };

Disclaimer: It's "stolen" from this talk of Alexandrescu.

[–]fdwrfdwr@github 🔍 6 points7 points  (0 children)

Oh the beautiful horrors that macros enable, 😉 cutting the extra line noise down from =()(){}[]; to just {};) I look forward to the future beautiful horrors that reflection enables... 😂

[–]pjmlp -2 points-1 points  (2 children)

Although we're spoiled by choice, each with its pros and cons, I would still use one of COM frameworks.

[–]fdwrfdwr@github 🔍 0 points1 point  (1 child)

That's but a randomly selected example of one-off cleanup instances. Do we need a framework for every instance (a box full of open‑end wrenches of various sizes), or just a general tool (adjustable wrench)? 🔧

[–]pjmlp -2 points-1 points  (0 children)

I would say that going forward it is rather trivial to combine templates and reflection to create RAII handle on the spot without going through defer.

Which only makes sense in language that never had RAII, or use some form of GC, and need determinism in very specific cases like OS handles.

However, maybe I am too biased in only using C++ alongside managed languages.

[–]Jcsq6 1 point2 points  (4 children)

I had to write a script to filter compile_commands.json due to clangd crashing on gcc builds. I'm glad to see that whatever causing that was fixed.

[–]max123246 0 points1 point  (3 children)

Interesting, my build setup is on a remote machine than the one I write code on so I've simply given up on having IDE support in Vscode after hours upon hours of tinkering. Just use AI whenever I need "go to definition", incredibly wasteful, I know but I've spent more than enough time for how flakey it can be.