-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature Request: Option to not check included files in clang-tidy #52959
Comments
clang-tidy needs to build the entire AST for a translation unit so it has to parse all the includes. For editor integrations, have you tried clangd. This builds a preamble saving the need to reparse all your header files and then when clang-tidy checks get ran on the AST, they ignore all Declarations that aren't in the main file. |
Yes, it's clear that the preprocessor directives need to all be evaluated, which includes
I have not. I'm actually building with |
It should be configurable for your needs. You can set it up with additional include folders if there are any issues with them not being found. |
I was looking if this issue was reported and I am glad to find it here. Of course, I guess this is not trivial to implement. I just made some tests and for a simple file c++ file, just In the general case, I doubt most C++ developers would care anyway about reports of defects in the STL or any 3rd part library, so that's a big waste of time to spend time for that in my opinion. clang-tidy is so widely used today, that I believe that if you address this, you would reduce a significant part of the carbon footprint of humanity. 🤣 Well that being said, that's always simpler to request something than to do it, so thank you for all your hard work. I just wanted to motivate the need a bit, if that was even necessary... If there is anything else I can do to help please let me know. |
Not parsing headers that aren't part of your project would be great. clang-tidy is a fantastic tool, but it is very problematic to run it in a script (e.g. on CI) and for it to take ~6x longer. I see there was an attempt to add an option to skip parsing header files, https://reviews.llvm.org/D98710, in 2021. Anyone know why that got abandoned -- looks like some non-trivial work went into it? And whether that work could reasonably be used as a basis for implementing the feature? |
Just adding a +1 to the need for this feature. Here is the output from a clang-tidy run I'm staring at right now (very typical output):
It would nice for those 132155 checks to have been skipped entirely. On the bright side, it's nice that clang-tidy is at least honest about how much work it's doing for no reason. ;) |
It would also be highly apreciated by us if this could be fixed. It feels very inefficient to take so much time for "skipping" 99.99% of all checks because they are not in the current scope. |
I see that some checks use If this fixes the problem, can't we apply this to all/most existing checks? |
Currently, clang-tidy processes the entire TranslationUnit, including declarations in system headers. However, the work done in system headers is discarded at the very end when presenting results, unless the SystemHeaders option is active. This is a lot of wasted work, and makes clang-tidy very slow. In comparison, clangd only processes declarations in the main file, and it's claimed to be 10x faster than clang-tidy: https://github.com/lljbash/clangd-tidy To solve this problem, we can apply a similar solution done in clangd into clang-tidy. We do this by changing the traversal scope from the default TranslationUnitDecl, to only contain the top-level declarations that are _not_ part of system headers. We do this by prepending a new ASTConsumer to the list of consumers: this new consumer sets the traversal scope in the ASTContext, which is later used by the MatchASTConsumer. Note: this behavior is not active if the user requests warnings from system headers via the SystemHeaders option. Note2: out of all the unit tests, only one of them fails: readability/identifier-naming-anon-record-fields.cpp This is because the limited traversal scope no longer includes the "IndirectFieldDecl" that appears in the AST when having a global scope anonymous union. I have not found a way to make this one work. However, it does seem like a very niche use case, and the benefits of a 10x faster clang-tidy largely outweigh the false negative now introduced by this patch. This use case is therefore removed from the unit test to make it pass. Note3: I have purposely decided to make this new feature enabled by default, instead of adding a new "opt-in/opt-out" flag. Having a new flag would mean duplicating all our tests to ensure they work in both modes, which would be infeasible. Having it enabled by default allow people to get the benefits immediately. Given that all unit tests pass, the risk for regressions is low. Even if that's the case, the only issue would be false negatives (fewer things are detected), which are much more tolerable than false positives. Credits: original implementation by @njames93, here: https://reviews.llvm.org/D150126 This implementation is simpler in the sense that it does not consider HeaderFilterRegex to filter even further. A follow-up patch could include the functionality if wanted. Fixes llvm#52959
Currently, clang-tidy processes the entire TranslationUnit, including declarations in system headers. However, the work done in system headers is discarded at the very end when presenting results, unless the SystemHeaders option is active. This is a lot of wasted work, and makes clang-tidy very slow. In comparison, clangd only processes declarations in the main file, and it's claimed to be 10x faster than clang-tidy: https://github.com/lljbash/clangd-tidy To solve this problem, we can apply a similar solution done in clangd into clang-tidy. We do this by changing the traversal scope from the default TranslationUnitDecl, to only contain the top-level declarations that are _not_ part of system headers. We do this by prepending a new ASTConsumer to the list of consumers: this new consumer sets the traversal scope in the ASTContext, which is later used by the MatchASTConsumer. Note: this behavior is not active if the user requests warnings from system headers via the SystemHeaders option. Note2: out of all the unit tests, only one of them fails: readability/identifier-naming-anon-record-fields.cpp This is because the limited traversal scope no longer includes the "IndirectFieldDecl" that appears in the AST when having a global scope anonymous union. I have not found a way to make this one work. However, it does seem like a very niche use case, and the benefits of a 10x faster clang-tidy largely outweigh the false negative now introduced by this patch. This use case is therefore removed from the unit test to make it pass. Note3: I have purposely decided to make this new feature enabled by default, instead of adding a new "opt-in/opt-out" flag. Having a new flag would mean duplicating all our tests to ensure they work in both modes, which would be infeasible. Having it enabled by default allow people to get the benefits immediately. Given that all unit tests pass, the risk for regressions is low. Even if that's the case, the only issue would be false negatives (fewer things are detected), which are much more tolerable than false positives. Credits: original implementation by @njames93, here: https://reviews.llvm.org/D150126 This implementation is simpler in the sense that it does not consider HeaderFilterRegex to filter even further. A follow-up patch could include the functionality if wanted. Fixes llvm#52959
Currently, clang-tidy processes the entire TranslationUnit, including declarations in system headers. However, the work done in system headers is discarded at the very end when presenting results, unless the SystemHeaders option is active. This is a lot of wasted work, and makes clang-tidy very slow. In comparison, clangd only processes declarations in the main file, and it's claimed to be 10x faster than clang-tidy: https://github.com/lljbash/clangd-tidy To solve this problem, we can apply a similar solution done in clangd into clang-tidy. We do this by changing the traversal scope from the default TranslationUnitDecl, to only contain the top-level declarations that are _not_ part of system headers. We do this by prepending a new ASTConsumer to the list of consumers: this new consumer sets the traversal scope in the ASTContext, which is later used by the MatchASTConsumer. Note: this behavior is not active if the user requests warnings from system headers via the SystemHeaders option. Note2: out of all the unit tests, only one of them fails: readability/identifier-naming-anon-record-fields.cpp This is because the limited traversal scope no longer includes the "IndirectFieldDecl" that appears in the AST when having a global scope anonymous union. I have not found a way to make this one work. However, it does seem like a very niche use case, and the benefits of a 10x faster clang-tidy largely outweigh the false negative now introduced by this patch. This use case is therefore removed from the unit test to make it pass. Note3: I have purposely decided to make this new feature enabled by default, instead of adding a new "opt-in/opt-out" flag. Having a new flag would mean duplicating all our tests to ensure they work in both modes, which would be infeasible. Having it enabled by default allow people to get the benefits immediately. Given that all unit tests pass, the risk for regressions is low. Even if that's the case, the only issue would be false negatives (fewer things are detected), which are much more tolerable than false positives. Credits: original implementation by @njames93, here: https://reviews.llvm.org/D150126 This implementation is simpler in the sense that it does not consider HeaderFilterRegex to filter even further. A follow-up patch could include the functionality if wanted. Fixes llvm#52959
Currently, clang-tidy processes the entire TranslationUnit, including declarations in system headers. However, the work done in system headers is discarded at the very end when presenting results, unless the SystemHeaders option is active. This is a lot of wasted work, and makes clang-tidy very slow. In comparison, clangd only processes declarations in the main file, and it's claimed to be 10x faster than clang-tidy: https://github.com/lljbash/clangd-tidy To solve this problem, we can apply a similar solution done in clangd into clang-tidy. We do this by changing the traversal scope from the default TranslationUnitDecl, to only contain the top-level declarations that are _not_ part of system headers. We do this by prepending a new ASTConsumer to the list of consumers: this new consumer sets the traversal scope in the ASTContext, which is later used by the MatchASTConsumer. Note: this behavior is not active if the user requests warnings from system headers via the SystemHeaders option. Note2: out of all the unit tests, only one of them fails: readability/identifier-naming-anon-record-fields.cpp This is because the limited traversal scope no longer includes the "IndirectFieldDecl" that appears in the AST when having a global scope anonymous union. I have not found a way to make this one work. However, it does seem like a very niche use case, and the benefits of a 10x faster clang-tidy largely outweigh the false negative now introduced by this patch. This use case is therefore removed from the unit test to make it pass. Note3: I have purposely decided to make this new feature enabled by default, instead of adding a new "opt-in/opt-out" flag. Having a new flag would mean duplicating all our tests to ensure they work in both modes, which would be infeasible. Having it enabled by default allow people to get the benefits immediately. Given that all unit tests pass, the risk for regressions is low. Even if that's the case, the only issue would be false negatives (fewer things are detected), which are much more tolerable than false positives. Credits: original implementation by @njames93, here: https://reviews.llvm.org/D150126 This implementation is simpler in the sense that it does not consider HeaderFilterRegex to filter even further. A follow-up patch could include the functionality if wanted. Fixes llvm#52959
Currently, clang-tidy processes the entire TranslationUnit, including declarations in system headers. However, the work done in system headers is discarded at the very end when presenting results, unless the SystemHeaders option is active. This is a lot of wasted work, and makes clang-tidy very slow. In comparison, clangd only processes declarations in the main file, and it's claimed to be 10x faster than clang-tidy: https://github.com/lljbash/clangd-tidy To solve this problem, we can apply a similar solution done in clangd into clang-tidy. We do this by changing the traversal scope from the default TranslationUnitDecl, to only contain the top-level declarations that are _not_ part of system headers. We do this in the MatchASTConsumer class, so the logic can be reused by other tools. This behavior is currently off by default, and only clang-tidy enables skipping system headers. If wanted, this behavior can be activated by other tools in follow-up patches. I had to move MatchFinderOptions out of the MatchFinder class, because otherwise I could not set a default value for the "bool SkipSystemHeaders" member otherwise. The compiler error message was "default member initializer required before the end of its enclosing class". Note: this behavior is not active if the user requests warnings from system headers via the SystemHeaders option. Note2: out of all the unit tests, only one of them fails: readability/identifier-naming-anon-record-fields.cpp This is because the limited traversal scope no longer includes the "CXXRecordDecl" of the global anonymous union, see: llvm#130618 I have not found a way to make this work. For now, document the technical debt introduced. Note3: I have purposely decided to make this new feature enabled by default, instead of adding a new "opt-in/opt-out" flag. Having a new flag would mean duplicating all our tests to ensure they work in both modes, which would be infeasible. Having it enabled by default allow people to get the benefits immediately. Given that all unit tests pass, the risk for regressions is low. Even if that's the case, the only issue would be false negatives (fewer things are detected), which are much more tolerable than false positives. Credits: original implementation by @njames93, here: https://reviews.llvm.org/D150126 This implementation is simpler in the sense that it does not consider HeaderFilterRegex to filter even further. A follow-up patch could include the functionality if wanted. Fixes llvm#52959
Currently, clang-tidy processes the entire TranslationUnit, including declarations in system headers. However, the work done in system headers is discarded at the very end when presenting results, unless the SystemHeaders option is active. This is a lot of wasted work, and makes clang-tidy very slow. In comparison, clangd only processes declarations in the main file, and it's claimed to be 10x faster than clang-tidy: https://github.com/lljbash/clangd-tidy To solve this problem, we can apply a similar solution done in clangd into clang-tidy. We do this by changing the traversal scope from the default TranslationUnitDecl, to only contain the top-level declarations that are _not_ part of system headers. We do this in the MatchASTConsumer class, so the logic can be reused by other tools. This behavior is currently off by default, and only clang-tidy enables skipping system headers. If wanted, this behavior can be activated by other tools in follow-up patches. I had to move MatchFinderOptions out of the MatchFinder class, because otherwise I could not set a default value for the "bool SkipSystemHeaders" member otherwise. The compiler error message was "default member initializer required before the end of its enclosing class". Note: this behavior is not active if the user requests warnings from system headers via the SystemHeaders option. Note2: out of all the unit tests, only one of them fails: readability/identifier-naming-anon-record-fields.cpp This is because the limited traversal scope no longer includes the "CXXRecordDecl" of the global anonymous union, see: llvm#130618 I have not found a way to make this work. For now, document the technical debt introduced. Note3: I have purposely decided to make this new feature enabled by default, instead of adding a new "opt-in/opt-out" flag. Having a new flag would mean duplicating all our tests to ensure they work in both modes, which would be infeasible. Having it enabled by default allow people to get the benefits immediately. Given that all unit tests pass, the risk for regressions is low. Even if that's the case, the only issue would be false negatives (fewer things are detected), which are much more tolerable than false positives. Credits: original implementation by @njames93, here: https://reviews.llvm.org/D150126 This implementation is simpler in the sense that it does not consider HeaderFilterRegex to filter even further. A follow-up patch could include the functionality if wanted. Fixes llvm#52959
Currently, clang-tidy processes the entire TranslationUnit, including declarations in system headers. However, the work done in system headers is discarded at the very end when presenting results, unless the SystemHeaders option is active. This is a lot of wasted work, and makes clang-tidy very slow. In comparison, clangd only processes declarations in the main file, and it's claimed to be 10x faster than clang-tidy: https://github.com/lljbash/clangd-tidy To solve this problem, we can apply a similar solution done in clangd into clang-tidy. We do this by changing the traversal scope from the default TranslationUnitDecl, to only contain the top-level declarations that are _not_ part of system headers. We do this in the MatchASTConsumer class, so the logic can be reused by other tools. This behavior is currently off by default, and only clang-tidy enables skipping system headers. If wanted, this behavior can be activated by other tools in follow-up patches. I had to move MatchFinderOptions out of the MatchFinder class, because otherwise I could not set a default value for the "bool SkipSystemHeaders" member otherwise. The compiler error message was "default member initializer required before the end of its enclosing class". Note: this behavior is not active if the user requests warnings from system headers via the SystemHeaders option. Note2: out of all the unit tests, only one of them fails: readability/identifier-naming-anon-record-fields.cpp This is because the limited traversal scope no longer includes the "CXXRecordDecl" of the global anonymous union, see: llvm#130618 I have not found a way to make this work. For now, document the technical debt introduced. Note3: I have purposely decided to make this new feature enabled by default, instead of adding a new "opt-in/opt-out" flag. Having a new flag would mean duplicating all our tests to ensure they work in both modes, which would be infeasible. Having it enabled by default allow people to get the benefits immediately. Given that all unit tests pass, the risk for regressions is low. Even if that's the case, the only issue would be false negatives (fewer things are detected), which are much more tolerable than false positives. Credits: original implementation by @njames93, here: https://reviews.llvm.org/D150126 This implementation is simpler in the sense that it does not consider HeaderFilterRegex to filter even further. A follow-up patch could include the functionality if wanted. Fixes llvm#52959
Currently, clang-tidy processes the entire TranslationUnit, including declarations in system headers. However, the work done in system headers is discarded at the very end when presenting results, unless the SystemHeaders option is active. This is a lot of wasted work, and makes clang-tidy very slow. In comparison, clangd only processes declarations in the main file, and it's claimed to be 10x faster than clang-tidy: https://github.com/lljbash/clangd-tidy To solve this problem, we can apply a similar solution done in clangd into clang-tidy. We do this by changing the traversal scope from the default TranslationUnitDecl, to only contain the top-level declarations that are _not_ part of system headers. We do this in the MatchASTConsumer class, so the logic can be reused by other tools. This behavior is currently off by default, and only clang-tidy enables skipping system headers. If wanted, this behavior can be activated by other tools in follow-up patches. I had to move MatchFinderOptions out of the MatchFinder class, because otherwise I could not set a default value for the "bool SkipSystemHeaders" member otherwise. The compiler error message was "default member initializer required before the end of its enclosing class". Note: this behavior is not active if the user requests warnings from system headers via the SystemHeaders option. Note2: out of all the unit tests, only one of them fails: readability/identifier-naming-anon-record-fields.cpp This is because the limited traversal scope no longer includes the "CXXRecordDecl" of the global anonymous union, see: llvm#130618 I have not found a way to make this work. For now, document the technical debt introduced. Note3: I have purposely decided to make this new feature enabled by default, instead of adding a new "opt-in/opt-out" flag. Having a new flag would mean duplicating all our tests to ensure they work in both modes, which would be infeasible. Having it enabled by default allow people to get the benefits immediately. Given that all unit tests pass, the risk for regressions is low. Even if that's the case, the only issue would be false negatives (fewer things are detected), which are much more tolerable than false positives. Credits: original implementation by @njames93, here: https://reviews.llvm.org/D150126 This implementation is simpler in the sense that it does not consider HeaderFilterRegex to filter even further. A follow-up patch could include the functionality if wanted. Fixes llvm#52959
…8150) [clang-tidy] Avoid processing declarations in system headers Currently, clang-tidy processes the entire TranslationUnit, including declarations in system headers. However, the work done in system headers is discarded at the very end when presenting results, unless the SystemHeaders option is active. This is a lot of wasted work, and makes clang-tidy very slow. In comparison, clangd only processes declarations in the main file, and it's claimed to be 10x faster than clang-tidy: https://github.com/lljbash/clangd-tidy To solve this problem, we can apply a similar solution done in clangd into clang-tidy. We do this by changing the traversal scope from the default TranslationUnitDecl, to only contain the top-level declarations that are _not_ part of system headers. We do this in the MatchASTConsumer class, so the logic can be reused by other tools. This behavior is currently off by default, and only clang-tidy enables skipping system headers. If wanted, this behavior can be activated by other tools in follow-up patches. I had to move MatchFinderOptions out of the MatchFinder class, because otherwise I could not set a default value for the "bool SkipSystemHeaders" member otherwise. The compiler error message was "default member initializer required before the end of its enclosing class". Note: this behavior is not active if the user requests warnings from system headers via the SystemHeaders option. Note2: out of all the unit tests, only one of them fails: readability/identifier-naming-anon-record-fields.cpp This is because the limited traversal scope no longer includes the "CXXRecordDecl" of the global anonymous union, see: llvm#130618 I have not found a way to make this work. For now, document the technical debt introduced. Note3: I have purposely decided to make this new feature enabled by default, instead of adding a new "opt-in/opt-out" flag. Having a new flag would mean duplicating all our tests to ensure they work in both modes, which would be infeasible. Having it enabled by default allow people to get the benefits immediately. Given that all unit tests pass, the risk for regressions is low. Even if that's the case, the only issue would be false negatives (fewer things are detected), which are much more tolerable than false positives. Credits: original implementation by @njames93, here: https://reviews.llvm.org/D150126 This implementation is simpler in the sense that it does not consider HeaderFilterRegex to filter even further. A follow-up patch could include the functionality if wanted. Fixes llvm#52959 Co-authored-by: Carlos Gálvez <[email protected]>
When using
clang-tidy
to lint files, it needs to#include
the dependencies. More often than not, however, dependencies are much larger and out of control of the consumer that is runningclang-tidy
.clang-tidy
, by default, currently does the correct thing and does not report errors/warnings from the#include
d files. However, from watching it run, it's clearly still actually checking those files for errors (52k+ warnings suppressed!). This dramatically increases the time it takes forclang-tidy
to run from nearly instant to ~3 seconds for a large header file like<napi.h>
(and this is a rather fast desktop). This really gets in the way of tools that integrate linters into code editors as every change requires that 3 second delay.I see options about filtering headers or even lines but, at best, it looks like I'd need to list out every single range of my included header files which is actually a rather large number of files which could also change outside of my control. I have tried a variety of these options and not noticed a significant change in behavior in ways I care about.
Is there a way to do what I'd like? Or is there some fundamental reason why this wouldn't work? Frankly, if feels like this should even be the default.
The text was updated successfully, but these errors were encountered: