Summary:
Recursion is a powerful tool, but like any tool
without care it can be dangerous. For example,
if the recursion is unbounded, you will
eventually run out of stack and crash.
You can of course track the recursion depth
but if it is hardcoded, there can always be some
other environment when that depth is too large,
so said magic number would need to be env-dependent.
But then your program's behavior is suddenly more env-dependent.
Also, recursion, while it does not outright stop optimization,
recursive calls are less great than normal calls,
for example they hinder inlining.
Recursion is banned in some coding guidelines:
* SEI CERT DCL56-CPP. Avoid cycles during initialization of static objects
* JPL 2.4 Do not use direct or indirect recursion.
* I'd say it is frowned upon in LLVM, although not banned
And is plain unsupported in some cases:
* OpenCL 1.2, 6.9 Restrictions: i. Recursion is not supported.
So there's clearly a lot of reasons why one might want to
avoid recursion, and replace it with worklist handling.
It would be great to have a enforcement for it though.
This implements such a check.
Here we detect both direct and indirect recursive calls,
although since clang-tidy (unlike clang static analyzer)
is CTU-unaware, if the recursion transcends a single standalone TU,
we will naturally not find it :/
The algorithm is pretty straight-forward:
1. Build call-graph for the entire TU.
For that, the existing `clang::CallGraph` is re-used,
although it had to be modified to also track the location of the call.
2. Then, the hard problem: how do we detect recursion?
Since we have a graph, let's just do the sane thing,
and look for Strongly Connected Function Declarations - widely known as `SCC`.
For that LLVM provides `llvm::scc_iterator`,
which is internally an Tarjan's DFS algorithm, and is used throught LLVM,
so this should be as performant as possible.
3. Now that we've got SCC's, we discard those that don't contain loops.
Note that there may be more than one loop in SCC!
4. For each loopy SCC, we call out each function, and print a single example
call graph that shows recursion -- it didn't seem worthwhile enumerating
every possible loop in SCC, although i suppose it could be implemented.
* To come up with that call graph cycle example, we start at first SCC node,
see which callee of the node is within SCC (and is thus known to be in cycle),
and recurse into it until we hit the callee that is already in call stack.
Reviewers: JonasToth, aaron.ballman, ffrankies, Eugene.Zelenko, erichkeane, NoQ
Reviewed By: aaron.ballman
Subscribers: Charusso, Naghasan, bader, riccibruno, mgorny, Anastasia, xazax.hun, cfe-commits
Tags: #llvm, #clang
Differential Revision: https://reviews.llvm.org/D72362
This is how it should've been and brings it more in line with
std::string_view. There should be no functional change here.
This is mostly mechanical from a custom clang-tidy check, with a lot of
manual fixups. It uncovers a lot of minor inefficiencies.
This doesn't actually modify StringRef yet, I'll do that in a follow-up.
Do not warn for redundant conditional expressions when the true and false
branches are expanded from different macros even when they are defined by
one another.
Patch by Daniel Krupp.
The static analyzer is warning about potential null dereferences, but in these cases we should be able to use castAs<> directly and if not assert will fire for us.
llvm-svn: 375102
Summary:
The check was generating a fix without taking qualifiers in return type
into account. This patch changes the insertion location to be before qualifers.
Reviewers: gribozavr
Subscribers: xazax.hun, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D67213
llvm-svn: 371022
The previous matcher "hasAnyTemplateArgument(templateArgument())" only
matches the first template argument, but the check wants to iterate all
template arguments. This patch fixes this.
Also some refactorings in this patch (to make the code reusable).
llvm-svn: 370760
Summary:
We've been running doxygen with the autobrief option for a couple of
years now. This makes the \brief markers into our comments
redundant. Since they are a visual distraction and we don't want to
encourage more \brief markers in new code either, this patch removes
them all.
Patch produced by
for i in $(git grep -l '\\brief'); do perl -pi -e 's/\\brief //g' $i & done
[This is analogous to LLVM r331272 and CFE r331834]
Subscribers: srhines, nemanjai, javed.absar, kbarton, MaskRay, jkorous, arphaman, jfb, kadircet, jsji, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D66578
llvm-svn: 369643
Now that we've moved to C++14, we no longer need the llvm::make_unique
implementation from STLExtras.h. This patch is a mechanical replacement
of (hopefully) all the llvm::make_unique instances across the monorepo.
Differential revision: https://reviews.llvm.org/D66259
llvm-svn: 368944
Summary: The fixit `int square(int /*num*/)` yields `error: parameter name omitted` for C code. Enable it only for C++ code.
Reviewers: klimek, ilya-biryukov, lebedev.ri, aaron.ballman
Subscribers: xazax.hun, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D63088
llvm-svn: 364106
Summary: It was trying to pass a dependent expression into constant evaluator.
Reviewers: ilya-biryukov
Subscribers: cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D63188
llvm-svn: 363133
Summary:
The assertion "isIntegerConstantExpr" is triggered in the
isIntegerConstantExpr(), we should not call it if the expression is value
dependent.
Reviewers: gribozavr
Subscribers: xazax.hun, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D62947
llvm-svn: 362701
Catching trivial objects by value is not dangerous but may be
inefficient if they are too large. This patch adds an option
`WarnOnLargeObject` to the checker to also warn if such an object
is caught by value. An object is considered as "large" if its
size is greater than `MaxSize` which is another option. Default
value is the machine word of the architecture (size of the type
`size_t`).
Differential Revision: https://reviews.llvm.org/D61851
llvm-svn: 361225
Summary:
Motivation/Context: in the code review system integrating with clang-tidy,
clang-tidy doesn't provide a human-readable description of the fix. Usually
developers have to preview a code diff (before vs after apply the fix) to
understand what the fix does before applying a fix.
This patch proposes that each clang-tidy check provides a short and
actional fix description that can be shown in the UI, so that users can know
what the fix does without previewing diff.
This patch extends clang-tidy framework to support fix descriptions (will add implementations for
existing checks in the future). Fix descriptions and fixes are emitted via diagnostic::Note (rather than
attaching the main warning diagnostic).
Before this patch:
```
void MyCheck::check(...) {
...
diag(loc, "my check warning") << FixtItHint::CreateReplacement(...);
}
```
After:
```
void MyCheck::check(...) {
...
diag(loc, "my check warning"); // Emit a check warning
diag(loc, "fix description", DiagnosticIDs::Note) << FixtItHint::CreateReplacement(...); // Emit a diagnostic note and a fix
}
```
Reviewers: sammccall, alexfh
Reviewed By: alexfh
Subscribers: MyDeveloperDay, Eugene.Zelenko, aaron.ballman, JonasToth, xazax.hun, jdoerfert, cfe-commits
Tags: #clang-tools-extra, #clang
Differential Revision: https://reviews.llvm.org/D59932
llvm-svn: 358576
Requires making the llvm::MemoryBuffer* stored by SourceManager const,
which in turn requires making the accessors for that return const
llvm::MemoryBuffer*s and updating all call sites.
The original motivation for this was to use it and fix the TODO in
CodeGenAction.cpp's ConvertBackendLocation() by using the UnownedTag
version of createFileID, and since llvm::SourceMgr* hands out a const
llvm::MemoryBuffer* this is required. I'm not sure if fixing the TODO
this way actually works, but this seems like a good change on its own
anyways.
No intended behavior change.
Differential Revision: https://reviews.llvm.org/D60247
llvm-svn: 357724
Otherwise we don't warn on a struct containing a single public int, but
we warn on a struct containing a single public std::string, which is
inconsistent.
llvm-svn: 351686
to reflect the new license.
We understand that people may be surprised that we're moving the header
entirely to discuss the new license. We checked this carefully with the
Foundation's lawyer and we believe this is the correct approach.
Essentially, all code in the project is now made available by the LLVM
project under our new license, so you will see that the license headers
include that license only. Some of our contributors have contributed
code under our old license, and accordingly, we have retained a copy of
our old license notice in the top-level files in each project and
repository.
llvm-svn: 351636
Removed the uses of the allOf() matcher inside node matchers that are implicit
allOf(). Replaced uses of allOf() with the explicit node matcher where it makes
matchers more readable. Replace anyOf(hasName(), hasName(), ...) with the more
efficient and readable hasAnyName().
llvm-svn: 347520