Age | Commit message (Collapse) | Author | Files | Lines |
|
Add a language option flag for experimental lifetime safety analysis in C++.
This change provides a language option to control the experimental lifetime safety analysis feature, making it more explicit and easier to enable/disable. Previously, the feature was controlled indirectly through a diagnostic warning flag, which we do not want to accidentally enable with `-Weverything` (atm)!
### Changes:
- Added a new language option `EnableLifetimeSafety` in `LangOptions.def` for experimental lifetime safety analysis in C++
- Added corresponding driver options `-fexperimental-lifetime-safety` and `-fno-experimental-lifetime-safety` in `Options.td`
- Modified `AnalysisBasedWarnings.cpp` to use the new language option flag instead of checking if a specific diagnostic is ignored
- Updated a test case to use the new flag instead of relying on the warning flag alone
|
|
This reverts commit 54b50681ca0fd1c0c6ddb059c88981a45e2f1b19.
|
|
This reverts commit 688ea048affe8e79221ea1a8c376bcf20ef8f3bb.
|
|
Refactor the Lifetime Safety Analysis infrastructure to support unit testing.
- Created a public API class `LifetimeSafetyAnalysis` that encapsulates the analysis functionality
- Added support for test points via a special `TestPointFact` that can be used to mark specific program points
- Added unit tests that verify loan propagation in various code patterns
|
|
We can pass a range to llvm::all_of.
|
|
attributes (#148974)
de10e44b6fe7 ("Thread Safety Analysis: Support warning on
passing/returning pointers to guarded variables") added checks for
passing pointer to guarded variables. While new features do not
necessarily need to support the deprecated attributes (`guarded_var`,
and `pt_guarded_var`), we need to ensure that such features do not cause
the compiler to crash.
As such, code such as this:
struct {
int v __attribute__((guarded_var));
} p;
int *g() {
return &p.v; // handleNoMutexHeld() with POK_ReturnPointer
}
Would crash in debug builds with the assertion in handleNoMutexHeld()
triggering. The assertion is meant to capture the fact that this helper
should only be used for warnings on variables (which the deprecated
attributes only applied to).
To fix, the function handleNoMutexHeld() should handle all POK cases
that apply to variables explicitly, and produce a best-effort warning.
We refrain from introducing new warnings to avoid unnecessary code bloat
for deprecated features.
Fixes: https://github.com/llvm/llvm-project/issues/140330
|
|
Compiler sometimes issues warnings on exit from 'noreturn' functions, in
the code like:
[[noreturn]] extern void nonreturnable();
void (*func_ptr)();
[[noreturn]] void foo() {
func_ptr = nonreturnable;
(*func_ptr)();
}
where exit cannot take place because the function pointer is actually a
pointer to noreturn function.
This change introduces small data analysis that can remove some of the
warnings in the cases when compiler can prove that the set of reaching
definitions consists of noreturn functions only.
|
|
This option is similar to -Wuninitialized-const-reference, but diagnoses
the passing of an uninitialized value via a const pointer, like in the
following code:
```
void foo(const int *);
void test() {
int v;
foo(&v);
}
```
This is an extract from #147221 as suggested in [this
comment](https://github.com/llvm/llvm-project/pull/147221#discussion_r2190998730).
|
|
When one kind of diagnostics is disabled, this should not preclude other
diagnostics from displaying, even if they have lower priority. For
example, this should print a warning about passing an uninitialized
variable as a const reference:
```
> cat test.cpp
void foo(const int &);
int f(bool a) {
int v;
if (a) {
foo(v);
v = 5;
}
return v;
}
> clang test.cpp -fsyntax-only -Wuninitialized -Wno-sometimes-uninitialized
```
|
|
(#147898)
This helps to avoid duplicating warnings in cases like:
```
> cat test.cpp
void bar(int);
void foo(const int &);
void test(bool a) {
int v = v;
if (a)
bar(v);
else
foo(v);
}
> clang++.exe test.cpp -fsyntax-only -Wuninitialized
test.cpp:4:11: warning: variable 'v' is uninitialized when used within its own initialization [-Wuninitialized]
4 | int v = v;
| ~ ^
test.cpp:4:11: warning: variable 'v' is uninitialized when used within its own initialization [-Wuninitialized]
4 | int v = v;
| ~ ^
2 warnings generated.
```
|
|
This patch introduces the initial implementation of the
intra-procedural, flow-sensitive lifetime analysis for Clang, as
proposed in the recent RFC:
https://discourse.llvm.org/t/rfc-intra-procedural-lifetime-analysis-in-clang/86291
The primary goal of this initial submission is to establish the core
dataflow framework and gather feedback on the overall design, fact
representation, and testing strategy. The focus is on the dataflow
mechanism itself rather than exhaustively covering all C++ AST edge
cases, which will be addressed in subsequent patches.
#### Key Components
* **Conceptual Model:** Introduces the fundamental concepts of `Loan`,
`Origin`, and `Path` to model memory borrows and the lifetime of
pointers.
* **Fact Generation:** A frontend pass traverses the Clang CFG to
generate a representation of lifetime-relevant events, such as pointer
assignments, taking an address, and variables going out of scope.
* **Testing:** `llvm-lit` tests validate the analysis by checking the
generated facts.
### Next Steps
*(Not covered in this PR but planned for subsequent patches)*
The following functionality is planned for the upcoming patches to build
upon this foundation and make the analysis usable in practice:
* **Dataflow Lattice:** A dataflow lattice used to map each pointer's
symbolic `Origin` to the set of `Loans` it may contain at any given
program point.
* **Fixed-Point Analysis:** A worklist-based, flow-sensitive analysis
that propagates the lattice state across the CFG to a fixed point.
* **Placeholder Loans:** Introduce placeholder loans to represent the
lifetimes of function parameters, forming the basis for analysis
involving function calls.
* **Annotation and Opaque Call Handling:** Use placeholder loans to
correctly model **function calls**, both by respecting
`[[clang::lifetimebound]]` annotations and by conservatively handling
opaque/un-annotated functions.
* **Error Reporting:** Implement the final analysis phase that consumes
the dataflow results to generate user-facing diagnostics. This will
likely require liveness analysis to identify live origins holding
expired loans.
* **Strict vs. Permissive Modes:** Add the logic to support both
high-confidence (permissive) and more comprehensive (strict) warning
levels.
* **Expanded C++ Coverage:** Broaden support for common patterns,
including the lifetimes of temporary objects and pointers within
aggregate types (structs/containers).
* Performance benchmarking
* Capping number of iterations or number of times a CFGBlock is
processed.
---------
Co-authored-by: Baranov Victor <bar.victor.2002@gmail.com>
|
|
This patch fixes:
clang/lib/Sema/AnalysisBasedWarnings.cpp:686:23: error: variable
'FD' set but not used [-Werror,-Wunused-but-set-variable]
|
|
(#145166)
Fixes https://github.com/llvm/llvm-project/issues/144952
|
|
Introduce the `reentrant_capability` attribute, which may be specified
alongside the `capability(..)` attribute to denote that the defined
capability type is reentrant. Marking a capability as reentrant means
that acquiring the same capability multiple times is safe, and does not
produce warnings on attempted re-acquisition.
The most significant changes required are plumbing to propagate if the
attribute is present to a CapabilityExpr, and introducing
ReentrancyDepth to the LockableFactEntry class.
|
|
This PR attempts to improve the diagnostics flag
`-Wtautological-overlap-compare` (#13473). I have added code to warn
about float-point literals and character literals. I have also changed
the warning message for the non-overlapping case to provide a more
correct hint to the user.
Fixes #13473.
|
|
|
|
Previously, analysis-based diagnostics (like -Wconsumed) had to be
enabled at file scope in order to be run at the end of each function
body. This meant that they did not respect #pragma clang diagnostic
enabling or disabling the diagnostic.
Now, these pragmas can control the diagnostic emission.
Fixes #42199
|
|
|
|
Each piece of code should have analysis run on it precisely once.
However, if you build a module, and then build another module depending
on it, the header file of the module you depend on will have
`-Wunsafe-buffer-usage` run on it twice. This normally isn't a huge
issue, but in the case of using the standard library as a module, simply
adding the line `#include <cstddef>` increases compile times by 900ms
(from 100ms to 1 second) on my machine. I believe this is because the
standard library has massive modules, of which only a small part is used
(the AST is ~700k lines), and because if what I've been told is correct,
the AST is lazily generated, and `-Wunsafe-buffer-usage` forces it to be
evaluated every time.
See https://issues.chromium.org/issues/351909443 for details and
benchmarks.
|
|
Fixes #21650
---
Clang currently inserts an implicit `return 0;` in `main()` when
compiling in `C89` mode, even though the `C89` standard doesn't require
this behavior. This patch changes that behavior by emitting a warning
instead of silently inserting the implicit return under `-pedantic`.
|
|
guarded variables
Introduce `-Wthread-safety-pointer` to warn when passing or returning
pointers to guarded variables or guarded data. This is is analogous to
`-Wthread-safety-reference`, which performs similar checks for C++
references.
Adding checks for pointer passing is required to avoid false negatives
in large C codebases, where data structures are typically implemented
through helpers that take pointers to instances of a data structure.
The feature is planned to be enabled by default under `-Wthread-safety`
in the next release cycle. This gives time for early adopters to address
new findings.
Pull Request: https://github.com/llvm/llvm-project/pull/127396
|
|
with clang::unsafe_buffer_usage attribute (#125671)
Unsafe operation in methods that are already annotated with
clang::unsafe_buffer_usage attribute, should not trigger a warning. This
is because, the developer has already identified the method as unsafe
and warning at every unsafe operation is redundant.
rdar://138644831
---------
Co-authored-by: MalavikaSamak <malavika2@apple.com>
|
|
This merges several falloff and noreturn-related warnings and
removes unused diagnostic arguments.
Changes:
- `warn_maybe_falloff_nonvoid_function` and
`warn_falloff_nonvoid_function`, `warn_maybe_falloff_nonvoid_coroutine`
and `warn_falloff_nonvoid_coroutine`,
`warn_maybe_falloff_nonvoid_lambda` and `warn_falloff_nonvoid_lambda`
were combined into `warn_falloff_nonvoid`,
- `err_maybe_falloff_nonvoid_block` and `err_falloff_nonvoid_block` were
combined into `err_falloff_nonvoid`
- `err_noreturn_block_has_return_expr` and
`err_noreturn_lambda_has_return_expr` were merged into
`err_noreturn_has_return_expr` with the same semantics as
`warn_falloff_nonvoid` or `err_falloff_nonvoid`.
- Removed some diagnostic args that weren’t being used by the diagnostics.
|
|
Declaring a coroutine `[[noreturn]]` doesn't make sense, because it will
always return its handle. Clang previously crashed when trying to warn
about this (diagnostic ID was 0).
Fixes #127327.
|
|
appropriate annotations (#110523)
This is helpful when multiple functions operate on the same
capabilities, but we still want to use scoped lockable types for
readability and exception safety.
- Introduce support for thread safety annotations on function parameters
marked with the 'scoped_lockable' attribute.
- Add semantic checks for annotated function parameters, ensuring
correct usage.
- Enhance the analysis to recognize and handle parameters annotated for
thread safety, extending the scope of analysis to track these across
function boundries.
- Verify that the underlying mutexes of function arguments match the
expectations set by the annotations.
Limitation: This does not work when the attribute arguments are class
members, because attributes on function parameters are parsed
differently from attributes on functions.
|
|
This commit addresses several Static Analyzer issues related to
potential null dereference by replacing dyn_cast<> with cast<> and
getAs<> with castAs<> in various parts of the codes.
The cast function asserts that the cast is valid, ensuring that the
pointer is not null and preventing null dereference errors.
The changes are made in the following files:
CGBuiltin.cpp: Ensure vector types have exactly 3 elements.
CGExpr.cpp: Ensure member declarations are field declarations.
AnalysisBasedWarnings.cpp: Ensure operations are member expressions.
SemaExprMember.cpp: Ensure base types are extended vector types.
These changes ensure that the types are correctly cast and prevent
potential null dereference issues, improving the robustness and safety
of the code.
|
|
Fixed the crash coming from attempting to get size of incomplete types.
Casting `span.data()` to a pointer-to-incomplete-type should be
immediately considered unsafe.
Solving issue #116286.
Co-authored-by: Ziqing Luo <ziqing_luo@apple.com>
|
|
Identified with misc-include-cleaner.
|
|
DynamicRecursiveASTVisitor (#115144)
This pr refactors all recursive AST visitors in `Sema`, `Analyze`, and
`StaticAnalysis` to inherit from DRAV instead. This is over half of the
visitors that inherit from RAV directly.
See also #115132, #110040, #93462
LLVM Compile-Time Tracker link for this branch:
https://llvm-compile-time-tracker.com/compare.php?from=5adb5c05a2e9f31385fbba8b0436cbc07d91a44d&to=b58e589a86c06ba28d4d90613864d10be29aa5ba&stat=instructions%3Au
|
|
and array::data is cast to larger type (#111910)
Emit a warning when the raw pointer retrieved from std::vector and
std::array instances are cast to a larger type. Such a cast followed by
a field dereference to the resulting pointer could cause an OOB access.
This is similar to the existing span::data warning.
(rdar://136704278)
Co-authored-by: MalavikaSamak <malavika2@apple.com>
|
|
(#109496)
- Fix a bug in UnsafeBufferUsage.cpp related to casting to PointerType
- Suppress -Wunsafe-buffer-usage-in-libc-call for C files
(rdar://117182250)
|
|
Revert commit 23457964392d00fc872fa6021763859024fb38da, and re-land
with a new flag "-Wunsafe-buffer-usage-in-libc-call" for the new
warning.
(rdar://117182250)
|
|
This reverts commit 0fffdeb5f46078ddcc61e112cd38856b1165f050.
Will re-land this commit soon with a way to opt-out
|
|
[-Wunsafe-buffer-usage] Add warn on unsafe calls to libc functions
Warning about calls to libc functions involving buffer access. Warned
functions are hardcoded by names.
(rdar://117182250)
|
|
attribute to struct fields (#101585)
Extend the unsafe_buffer_usage attribute, so they can also be added to
struct fields. This will cause the compiler to warn about the unsafe
field at their access sites.
Co-authored-by: MalavikaSamak <malavika2@apple.com>
|
|
This addresses a clang-tidy suggestion.
|
|
The -Wunsafe-buffer-usage warning should fire on any call to a function
annotated with [[clang::unsafe_buffer_usage]], however it omitted calls
to constructors, since the expression is a CXXConstructExpr which does
not subclass CallExpr. Thus the matcher on callExpr() does not find
these expressions.
Add a new WarningGadget that matches cxxConstructExpr that are calling a
CXXConstructDecl annotated by [[clang::unsafe_buffer_usage]] and fires
the warning. The new UnsafeBufferUsageCtorAttrGadget gadget explicitly
avoids matching against the std::span(ptr, size) constructor because
that is handled by SpanTwoParamConstructorGadget and we never want two
gadgets to match the same thing (and this is guarded by asserts).
The gadgets themselves do not report the warnings, instead each gadget's
Stmt is passed to the UnsafeBufferUsageHandler (implemented by
UnsafeBufferUsageReporter). The Reporter is previously hardcoded that a
CXXConstructExpr statement must be a match for std::span(ptr, size), but
that is no longer the case. We want the Reporter to generate different
warnings (in the -Wunsafe-buffer-usage-in-container subgroup) for the
span contructor. And we will want it to report more warnings for other
std-container-specific gadgets in the future. To handle this we allow
the gadget to control if the warning is general (it calls
handleUnsafeBufferUsage()) or is a std-container-specific warning (it
calls handleUnsafeOperationInContainer()).
Then the WarningGadget grows a virtual method to dispatch to the
appropriate path in the UnsafeBufferUsageHandler. By doing so, we no
longer need getBaseStmt in the Gadget interface. The only use of it for
FixableGadgets was to get the SourceLocation, so we make an explicit
virtual method for that on Gadget. Then the handleUnsafeOperation()
dispatcher can be a virtual method that is only in WarningGadget.
The SpanTwoParamConstructorGadget gadget dispatches to
handleUnsafeOperationInContainer() while the other WarningGadgets all
dispatch to the original handleUnsafeBufferUsage().
Tests are added for annotated constructors, conversion operattors, call
operators, fold expressions, and regular methods.
Issue #80482
|
|
clang-format would format these headers poorly by splitting it into
multiple lines.
|
|
Array subscript on a const size array is not bounds-checked. The idiomatic
replacement is std::array which is bounds-safe in hardened mode of libc++.
This commit extends the fixit-producing machine to consider std::array as a
transformation target type and teaches it to handle the array subscript on const
size arrays with a trivial (empty) fixit.
|
|
two-parameter constructors (#77148)
Constructing `std::span` objects with the two parameter constructors
could introduce mismatched bounds information, which defeats the
purpose of using `std::span`. Therefore, we warn every use of such
constructors.
rdar://115817781
|
|
This patch fixes:
clang/lib/Sema/AnalysisBasedWarnings.cpp:2269:21: error: unused
variable 'subExpr' [-Werror,-Wunused-variable]
|
|
span::data warning (#78815)
The patch fixes the crash introduced by the DataInvocation warning
gadget designed to warn against unsafe invocations of span::data method.
It also now considers the invocation of span::data method inside
parenthesis.
Radar: 121223051
---------
Co-authored-by: MalavikaSamak <malavika2@apple.com>
|
|
…-Wunsafe-buffer-usage,
there maybe accidental re-introduction of new OutOfBound accesses into
the code bases. One such case is invoking span::data() method on a span
variable to retrieve a pointer, which is then cast to a larger type and
dereferenced. Such dereferences can introduce OutOfBound accesses.
To address this, a new WarningGadget is being introduced to warn against
such invocations.
---------
Co-authored-by: MalavikaSamak <malavika2@apple.com>
|
|
(#68572)
…… (#68394)"
The new warnings are now under a separate flag
`-Wthread-safety-reference-return`, which is on by default under
`-Wthread-safety-reference`.
- People can opt out via `-Wthread-safety-reference
-Wnothread-safety-reference-return`.
This reverts commit 859f2d032386632562521a99db20923217d98988.
|
|
return-by-reference..… (#68394)"
This reverts commit cd184c866e0aad1f957910b8c7a94f98a2b21ceb.
|
|
(#68394)
…. (#67776)"
Now that `scudo` issues have been fixed (#68273).
This reverts commit 462bdd5bf0861a27f451f7917802a954e2046bc7.
|
|
(#67795)
… (#67776)"
This detects issues in `scudo`. Reverting until these are fixed.
```
/b/sanitizer-x86_64-linux-autoconf/build/llvm-project/compiler-rt/lib/scudo/standalone/tsd.h:74:12: error: returning variable 'QuarantineCache' by reference requires holding mutex 'Mutex' exclusively [-Werror,-Wthread-safety-reference]
74 | return QuarantineCache;
| ^
/b/sanitizer-x86_64-linux-autoconf/build/llvm-project/compiler-rt/lib/scudo/standalone/combined.h:248:28: note: in instantiation of member function 'scudo::TSD<scudo::Allocator<scudo::DefaultConfig, &malloc_postinit>>::getQuarantineCache' requested here
248 | Quarantine.drain(&TSD->getQuarantineCache(),
| ^
/b/sanitizer-x86_64-linux-autoconf/build/llvm-project/compiler-rt/lib/scudo/standalone/tsd.h:57:15: note: in instantiation of member function 'scudo::Allocator<scudo::DefaultConfig, &malloc_postinit>::commitBack' requested here
57 | Instance->commitBack(this);
| ^
/b/sanitizer-x86_64-linux-autoconf/build/llvm-project/compiler-rt/lib/scudo/standalone/tsd_exclusive.h:172:27: note: in instantiation of member function 'scudo::TSD<scudo::Allocator<scudo::DefaultConfig, &malloc_postinit>>::commitBack' requested here
172 | TSDRegistryT::ThreadTSD.commitBack(Instance);
| ^
/b/sanitizer-x86_64-linux-autoconf/build/llvm-project/compiler-rt/lib/scudo/standalone/tsd_exclusive.h:33:46: note: in instantiation of function template specialization 'scudo::teardownThread<scudo::Allocator<scudo::DefaultConfig, &malloc_postinit>>' requested here
33 | CHECK_EQ(pthread_key_create(&PThreadKey, teardownThread<Allocator>), 0);
| ^
/b/sanitizer-x86_64-linux-autoconf/build/llvm-project/compiler-rt/lib/scudo/standalone/tsd_exclusive.h:42:5: note: in instantiation of member function 'scudo::TSDRegistryExT<scudo::Allocator<scudo::DefaultConfig, &malloc_postinit>>::init' requested here
42 | init(Instance); // Sets Initialized.
| ^
/b/sanitizer-x86_64-linux-autoconf/build/llvm-project/compiler-rt/lib/scudo/standalone/tsd_exclusive.h:130:5: note: in instantiation of member function 'scudo::TSDRegistryExT<scudo::Allocator<scudo::DefaultConfig, &malloc_postinit>>::initOnceMaybe' requested here
130 | initOnceMaybe(Instance);
| ^
/b/sanitizer-x86_64-linux-autoconf/build/llvm-project/compiler-rt/lib/scudo/standalone/tsd_exclusive.h:74:5: note: in instantiation of member function 'scudo::TSDRegistryExT<scudo::Allocator<scudo::DefaultConfig, &malloc_postinit>>::initThread' requested here
74 | initThread(Instance, MinimalInit);
| ^
/b/sanitizer-x86_64-linux-autoconf/build/llvm-project/compiler-rt/lib/scudo/standalone/combined.h:221:17: note: in instantiation of member function 'scudo::TSDRegistryExT<scudo::Allocator<scudo::DefaultConfig, &malloc_postinit>>::initThreadMaybe' requested here
221 | TSDRegistry.initThreadMaybe(this, MinimalInit);
| ^
/b/sanitizer-x86_64-linux-autoconf/build/llvm-project/compiler-rt/lib/scudo/standalone/combined.h:790:5: note: in instantiation of member function 'scudo::Allocator<scudo::DefaultConfig, &malloc_postinit>::initThreadMaybe' requested here
790 | initThreadMaybe();
| ^
/b/sanitizer-x86_64-linux-autoconf/build/llvm-project/compiler-rt/lib/scudo/standalone/wrappers_c.inc:36:25: note: in instantiation of member function 'scudo::Allocator<scudo::DefaultConfig, &malloc_postinit>::canReturnNull' requested here
36 | if (SCUDO_ALLOCATOR.canReturnNull()) {
```
This reverts commit 6dd96d6e80e9b3679a6161c590c60e0e99549b89.
|
|
...of guarded variables, when the function is not marked as requiring
locks:
```
class Return {
Mutex mu;
Foo foo GUARDED_BY(mu);
Foo &returns_ref_locked() {
MutexLock lock(&mu);
return foo; // BAD
}
Foo &returns_ref_locks_required() SHARED_LOCKS_REQUIRED(mu) {
return foo; // OK
}
};
```
Review on Phabricator: https://reviews.llvm.org/D153131
|
|
For a function `F` whose parameters need to be fixed, we group fix-its
of F's parameters together so that either all of the parameters get
fixed or none of them gets fixed.
Reviewed by: NoQ (Artem Dergachev), t-rasmud (Rashmi Mudduluru), jkorous (Jan Korous)
Differential revision: https://reviews.llvm.org/D153059
|
|
This reverts commit ac9a76d7487b9af1ace626eb90064194cb12c53d.
Previously an abstract class has no pure virtual function. It causes build error on some bots.
|