For a fix-it that inserts the `[[clang::unsafe_buffer_usage]]`
attribute, it will lookup existing macros defined for the attribute
and use the (last defined such) macro directly. Fix-its will use raw
`[[clang::unsafe_buffer_usage]]` if no such macro is defined.
The implementation mimics how a similar machine for the
`[[fallthrough]]` attribute was implemented.
Reviewed by: NoQ (Artem Dergachev)
Differential revision: https://reviews.llvm.org/D150338
This patch implements a new clang driver flag -fsafe-buffer-usage-suggestions
which allows turning the smart suggestion machine on and off (defaults to off).
This is valuable for stability reasons, as the machine is being rapidly improved\
and we don't want accidental breakages to ruin the build for innocent users.
It is also arguably useful in general because it enables separation of concerns
between project contributors: some users will actively update the code to
conform to the programming model, while others simply want to make sure that
they aren't regressing it. Finally, there could be other valid reasons to
opt out of suggestions entirely on some codebases (while continuing to enforce
-Wunsafe-buffer-usage warnings), such as lack of access to hardened libc++
(or even to the C++ standard library in general) on the target platform.
When the flag is disabled, the unsafe buffer usage analysis is reduced to
an extremely minimal mode of operation that contains virtually no smarts:
not only it doesn't offer automatic fixits, but also textual suggestions
such as "change the type of this variable to std::span to preserve bounds
information" are not displayed, and in fact the machine doesn't even try
to blame specific variables in the first place, it simply warns on
the operations and leaves everything else to the user. So this flag turns off
a lot more of our complex machinery than what we already turn off in presence
of say -fno-diagnostic-fixit-info.
The flag is discoverable: when it's off, the warnings are accompanied by a note:
telling the user that there's a flag they can use.
Differential Revision: https://reviews.llvm.org/D146669
A follow-up change for 6d861d498de1320d22771c329ec69f9419ef06b7:
remove an unnecessary const-qualifier so that the code doesn't have to
remove the qualifier explicitly using `std::remove_const_t`, which
triggers a warning at some bots (e.g.,
https://lab.llvm.org/buildbot/#/builders/247/builds/4442).
The unsafe-buffer analysis requires a complete view of the translation
unit (TU) to be conservative. So the analysis is moved to the end of a
TU.
A summary of changes made: add a new `IssueWarnings` function in
`AnalysisBasedWarnings.cpp` for TU-based analyses. So far
[-Wunsafe-buffer-usage] is the only analysis using it but there could
be more. `Sema` will call the new `IssueWarnings` function at the end
of parsing a TU.
Reviewed by: NoQ (Artem Dergachev)
Differential revision: https://reviews.llvm.org/D146342
This patch checks whether -Wunreachable-code-fallthrough is enabled
when clang encounters unreachable fallthrough attributes and, if so,
suppresses code will never be executed warning to avoid duplicate
warnings.
Fixes https://github.com/llvm/llvm-project/issues/60416
Differential Revision: https://reviews.llvm.org/D145842
All exceptions thrown in coroutine bodies are caught and
unhandled_exception member of the coroutine promise type is called.
In accordance with the existing rules of diagnostics related to
exceptions thrown in functions marked noexcept, even if the promise
type's constructor, get_return_object, or unhandled_exception
throws, diagnostics should not be emitted.
Fixes#48797.
Differential Revision: https://reviews.llvm.org/D144352
The transformation strategy we are bringing up heavily relies on std::span which was introduced as part of C++20.
Differential Revision: https://reviews.llvm.org/D143455
Add a pair of clang pragmas:
- `#pragma clang unsafe_buffer_usage begin` and
- `#pragma clang unsafe_buffer_usage end`,
which specify the start and end of an (unsafe buffer checking) opt-out
region, respectively.
Behaviors of opt-out regions conform to the following rules:
- No nested nor overlapped opt-out regions are allowed. One cannot
start an opt-out region with `... unsafe_buffer_usage begin` but never
close it with `... unsafe_buffer_usage end`. Mis-use of the pragmas
will be warned.
- Warnings raised from unsafe buffer operations inside such an opt-out
region will always be suppressed. This behavior CANNOT be changed by
`clang diagnostic` pragmas or command-line flags.
- Warnings raised from unsafe operations outside of such opt-out
regions may be reported on declarations inside opt-out
regions. These warnings are NOT suppressed.
- An un-suppressed unsafe operation warning may be attached with
notes. These notes are NOT suppressed as well regardless of whether
they are in opt-out regions.
The implementation maintains a separate sequence of location pairs
representing opt-out regions in `Preprocessor`. The `UnsafeBufferUsage`
analyzer reads the region sequence to check if an unsafe operation is
in an opt-out region. If it is, discard the warning raised from the
operation immediately.
This is a re-land after I reverting it at 9aa00c8a306561c4e3ddb09058e66bae322a0769.
The compilation error should be resolved.
Reviewed by: NoQ
Differential revision: https://reviews.llvm.org/D140179
Add a pair of clang pragmas:
- `#pragma clang unsafe_buffer_usage begin` and
- `#pragma clang unsafe_buffer_usage end`,
which specify the start and end of an (unsafe buffer checking) opt-out
region, respectively.
Behaviors of opt-out regions conform to the following rules:
- No nested nor overlapped opt-out regions are allowed. One cannot
start an opt-out region with `... unsafe_buffer_usage begin` but never
close it with `... unsafe_buffer_usage end`. Mis-use of the pragmas
will be warned.
- Warnings raised from unsafe buffer operations inside such an opt-out
region will always be suppressed. This behavior CANNOT be changed by
`clang diagnostic` pragmas or command-line flags.
- Warnings raised from unsafe operations outside of such opt-out
regions may be reported on declarations inside opt-out
regions. These warnings are NOT suppressed.
- An un-suppressed unsafe operation warning may be attached with
notes. These notes are NOT suppressed as well regardless of whether
they are in opt-out regions.
The implementation maintains a separate sequence of location pairs
representing opt-out regions in `Preprocessor`. The `UnsafeBufferUsage`
analyzer reads the region sequence to check if an unsafe operation is
in an opt-out region. If it is, discard the warning raised from the
operation immediately.
Reviewed by: NoQ
Differential revision: https://reviews.llvm.org/D140179
Use clang fix-its to transform declarations of local variables, which
are used for buffer access , to be of std::span type.
We placed a few limitations to keep the solution simple:
- it only transforms local variable declarations (no parameter declaration);
- it only considers single level pointers, i.e., pointers of type T * regardless of whether T is again a pointer;
- it only transforms to std::span types (no std::array, or std::span::iterator, or ...);
- it can only transform a VarDecl that belongs to a DeclStmt whose has a single child.
One of the purposes of keeping this patch simple enough is to first
evaluate if fix-it is an appropriate approach to do the
transformation.
This commit was reverted by 622be09c815266632e204eaf1c7a35f050220459
for a compilation warning and now it is fixed.
Reviewed by: NoQ, jkorous
Differential revision: https://reviews.llvm.org/D139737
Use clang fix-its to transform declarations of local variables, which are used for buffer access , to be of std::span type.
We placed a few limitations to keep the solution simple:
- it only transforms local variable declarations (no parameter declaration);
- it only considers single level pointers, i.e., pointers of type T * regardless of whether T is again a pointer;
- it only transforms to std::span types (no std::array, or std::span::iterator, or ...);
- it can only transform a VarDecl that belongs to a DeclStmt whose has a single child.
One of the purposes of keeping this patch simple enough is to first
evaluate if fix-it is an appropriate approach to do the
transformation.
Reviewed by: NoQ, jkorous
Differential revision: https://reviews.llvm.org/D139737
This way we highlight a particular unsafe subexpression by providing more accurate
source location than begin of an entire statement.
Differential Revision: https://reviews.llvm.org/D141340
This patch adds more abstractions that we'll need later for emitting
-Wunsafe-buffer-usage fixits. It doesn't emit any actual fixits,
so no change is observed behavior, but it introduces a way to emit fixits,
and existing tests now verify that the compiler still emits no fixits,
despite knowing how to do so.
The purpose of our code transformation analysis is to fix variable types
in the code from raw pointer types to C++ standard collection/view types.
The analysis has to decide on its own which specific type is
the most appropriate for every variable. This patch introduces
the Strategy class that maps variables to their most appropriate types.
In D137348 we've introduced the Gadget abstraction, which describes
a rigid AST pattern that the analysis "fully understands" and may need
to fix. Which specific fix is actually necessary for a given Gadget,
and whether it's necessary at all, and whether it's possible in the first place,
depends on the Strategy. So, this patch adds a virtual method which every
gadget can implement in order to teach the analysis how to fix that gadget:
Gadget->getFixits(Strategy)
However, even if the analysis knows how to fix every Gadget, doesn't
necessarily mean it can fix the variable. Some uses of the variable may have
never been covered by Gadgets, which corresponds to the situation that
the analysis doesn't fully understand how the variable is used. This patch
introduces a Tracker class that tracks all variable uses (i.e. DeclRefExprs)
in the function. Additionally, each Gadget now provides a new virtual method
Gadget->getClaimedVarUseSites()
that the Tracker can call to see which DeclRefExprs are "claimed" by the Gadget.
In order to fix the variable with a certain Strategy, the Tracker needs to
confirm that there are no unclaimed uses, and every Gadget has to provide
a fix for that Strategy.
This "conservative" behavior guarantees that fixes emitted by our analysis
are correct by construction. We can now be sure that the analysis won't
attempt to emit a fix if it doesn't understand the code. Later, as we implement
more getFixits() methods in individual Gadget classes, we'll start
progressively emitting more and more fixits.
Differential Revision: https://reviews.llvm.org/D138253
This is the initial commit for -Wunsafe-buffer-usage, a warning that helps
codebases (especially modern C++ codebases) transition away from raw buffer
pointers.
The warning is implemented in libAnalysis as it's going to become a non-trivial
analysis, mostly the fixit part where we try to figure out if we understand
a variable's use pattern well enough to suggest a safe container/view
as a replacement. Some parts of this analsysis may eventually prove useful
for any similar fixit machine that tries to change types of variables.
The warning is disabled by default.
RFC/discussion in https://discourse.llvm.org/t/rfc-c-buffer-hardening/65734
Differential Revision: https://reviews.llvm.org/D137346
If no capability is held, or the capability expression is invalid, there
is obviously no capability kind and so none would be reported.
Reviewed By: aaron.ballman
Differential Revision: https://reviews.llvm.org/D124132
After 04f30795f16638, -Wreturn-type has an effect on functions that
contain @try/@catch statements. CheckFallThrough() was missing
a case for ObjCAtTryStmts, leading to a false positive.
(What about the other two places in CheckFallThrough() that handle
CXXTryStmt but not ObjCAtTryStmts?
- I think the last use of CXXTryStmt is dead in practice: 04c6851cd made it so
that calls never add edges to try bodies, and the CFG block for a try
statement is always an empty block containing just the try element itself as
terminator (the try body itself is part of the normal flow of the function
and not connected to the block for the try statement itself. The try statment
cfg block is only connected to the catch bodies, and only reachable from
throw expressions within the try body.)
- The first use of CXXTryStmt might be important. It looks similar to
the code that adds all cfg blocks for try statements as roots of
the reachability graph for the reachability warnings, but I can't
find a way to trigger it. So I'm omitting it for now. The CXXTryStmt
code path seems to only be hit by try statements that are function
bodies without a surrounding compound statements
(`f() try { ... } catch ...`), and those don't exist for ObjC
@try statements.
)
Fixes PR52473.
Differential Revfision: https://reviews.llvm.org/D114660
CFGBuilder::addStmt() implicitly passes AddStmtChoice::AlwaysAdd
to Visit() already, so this should have no behavior change.
Differential Revision: https://reviews.llvm.org/D111570
The Linux kernel has a macro called IS_ENABLED(), which evaluates to a
constant 1 or 0 based on Kconfig selections, allowing C code to be
unconditionally enabled or disabled at build time. For example:
int foo(struct *a, int b) {
switch (b) {
case 1:
if (a->flag || !IS_ENABLED(CONFIG_64BIT))
return 1;
__attribute__((fallthrough));
case 2:
return 2;
default:
return 3;
}
}
There is an unreachable warning about the fallthrough annotation in the
first case because !IS_ENABLED(CONFIG_64BIT) can be evaluated to 1,
which looks like
return 1;
__attribute__((fallthrough));
to clang.
This type of warning is pointless for the Linux kernel because it does
this trick all over the place due to the sheer number of configuration
options that it has.
Add -Wunreachable-code-fallthrough, enabled under -Wunreachable-code, so
that projects that want to warn on unreachable code get this warning but
projects that do not care about unreachable code can still use
-Wimplicit-fallthrough without having to make changes to their code
base.
Fixes PR51094.
Reviewed By: aaron.ballman, nickdesaulniers
Differential Revision: https://reviews.llvm.org/D107933
This patch introduces a very simple inter-procedural analysis
between blocks and enclosing functions.
We always analyze blocks first (analysis is done as part of semantic
analysis that goes side-by-side with the parsing process), and at the
moment of reporting we don't know how that block will be actually
used.
This patch introduces new logic delaying reports of the "never called"
warnings on blocks. If we are not sure that the block will be called
exactly once, we shouldn't warn our users about that. Double calls,
however, don't require such delays. While analyzing the enclosing
function, we can actually decide what we should do with those
warnings.
Additionally, as a side effect, we can be more confident about blocks
in such context and can treat them not as escapes, but as direct
calls.
rdar://74090107
Differential Revision: https://reviews.llvm.org/D98688
This commit introduces a new attribute `called_once`.
It can be applied to function-like parameters to signify that
this parameter should be called exactly once. This concept
is particularly widespread in asynchronous programs.
Additionally, this commit introduce a new group of dataflow
analysis-based warnings to check this property. It identifies
and reports the following situations:
* parameter is called twice
* parameter is never called
* parameter is not called on one of the paths
Current implementation can also automatically infer `called_once`
attribute for completion handler paramaters that should follow the
same principle by convention. This behavior is OFF by default and
can be turned on by using `-Wcompletion-handler`.
Differential Revision: https://reviews.llvm.org/D92039
rdar://72812043
This recommits 7f1f89ec8d9944559042bb6d3b1132eabe3409de and
40df06cdafc010002fc9cfe1dda73d689b7d27a6 with bug fixes for
memory sanitizer failure and Tensile build failure.