26 Commits

Author SHA1 Message Date
Marco Elver
de10e44b6f Thread Safety Analysis: Support warning on passing/returning pointers to 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
2025-02-26 16:34:33 +01:00
Malek Ben Slimane
c1e7e4500c Thread Safety Analysis: Support passing scoped locks between functions with 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.
2024-12-20 23:49:03 +01:00
Aaron Puchert
30fad6a976 Thread safety analysis: Implement MutexLocker factory functions in documentation
We skipped adding definitions in 54bfd0484615 because we'd emit false
positive warnings on the closing braces. But these have been fixed in
commit e64ef634bbd9.
2024-11-19 17:19:35 +01:00
Pierre d'Herbemont
c8ba5562e5
Support guarded_by attribute and related attributes inside C structs and support late parsing them (#95455)
This fixes #20777. This replaces #94216 which was reverted after being
merged.

Previously the `guarded_by`, `pt_guarded_by`, `acquired_after`, and
`acquired_before` attributes were only supported inside C++ classes or
top level C/C++ declaration.

This patch allows these attributes to be added to struct members in C.
These attributes have also now support experimental late parsing. This
is off by default but can be enabled by passing
`-fexperimental-late-parse-attributes`. This is useful for referring to
a struct member after the annotated member. E.g.

```
struct Example {
  int a_value_defined_before __attribute__ ((guarded_by(a_mutex)));
  struct Mutex *a_mutex;
};
```
2024-07-09 15:08:11 +01:00
Dan McArdle
d698760687
[clang][ThreadSafety] Revert stricter typing on trylock attributes (#97293)
This PR reverts #95290 and the one-liner followup PR #96494.

I received some substantial feedback on #95290, which I plan to address
in a future PR.

I've also received feedback that because the change emits errors where
they were not emitted before, we should at least have a flag to disable
the stricter warnings.
2024-07-01 09:47:09 -04:00
Dan McArdle
34026207c8
[clang][ThreadSafety] Fix code block syntax in ThreadSafetyAnalysis.rst (#96494)
Without a newline, documentation was failing to build with this error:

    Warning, treated as error:

/home/runner/work/llvm-project/llvm-project/clang-build/tools/clang/docs/ThreadSafetyAnalysis.rst:466:Error
in "code-block" directive:
    maximum 1 argument(s) allowed, 10 supplied.

Issue #92408
2024-06-24 10:48:51 -04:00
Dan McArdle
c1bde0a2cb
[clang][ThreadSafety] Check trylock function success and return types (#95290)
With this change, Clang will generate errors when trylock functions have
improper return types. Today, it silently fails to apply the trylock
attribute to these functions which may incorrectly lead users to believe
they have correctly acquired locks before accessing guarded data.

As a side effect of explicitly checking the success argument type, I
seem to have fixed a false negative in the analysis that could occur
when a trylock's success argument is an enumerator. I've added a
regression test to warn-thread-safety-analysis.cpp named
`TrylockSuccessEnumFalseNegative`.

This change also improves the documentation with descriptions of of the
subtle gotchas that arise from the analysis interpreting the success arg
as a boolean.

Issue #92408
2024-06-24 09:29:13 -04:00
Dan Liew
c9d580033f Revert "Support guarded_by attribute and related attributes inside C structs and support late parsing them (#94216)"
This reverts commit af0d7128c8fd053d3de8af208d7d1682bc7a525a.

Reverting due to likely regression:

https://github.com/llvm/llvm-project/pull/94216#issuecomment-2164013300
2024-06-12 15:43:12 -07:00
Pierre d'Herbemont
af0d7128c8
Support guarded_by attribute and related attributes inside C structs and support late parsing them (#94216)
This fixes #20777.

Previously the `guarded_by`, `pt_guarded_by`, `acquired_after`, and `acquired_before` attributes were only supported inside C++ classes or top level C/C++ declaration.

This patch allows these attributes to be added to struct members in C. These attributes have also now support experimental late parsing. This is off by default but can be enabled by passing `-fexperimental-late-parse-attributes`. This is useful for referring to a struct member after the annotated member. E.g.

```
struct Example {
  int a_value_defined_before __attribute__ ((guarded_by(a_mutex)));
  struct Mutex *a_mutex;
};
```

Patch by  Pierre d'Herbemont (@pdherbemont)
2024-06-12 11:20:05 -07:00
Aaron Puchert
54bfd04846 Thread safety analysis: Support copy-elided production of scoped capabilities through arbitrary calls
When support for copy elision was initially added in e97654b2f2807, it
was taking attributes from a constructor call, although that constructor
call is actually not involved. It seems more natural to use attributes
on the function returning the scoped capability, which is where it's
actually coming from. This would also support a number of interesting
use cases, like producing different scope kinds without the need for tag
types, or producing scopes from a private mutex.

Changing the behavior was surprisingly difficult: we were not handling
CXXConstructorExpr calls like regular calls but instead handled them
through the DeclStmt they're contained in. This was based on the
assumption that constructors are basically only called in variable
declarations (not true because of temporaries), and that variable
declarations necessitate constructors (not true with C++17 anymore).

Untangling this required separating construction from assigning a
variable name. When a call produces an object, we use a placeholder
til::LiteralPtr for `this`, and we collect the call expression and
placeholder in a map. Later when going through a DeclStmt, we look up
the call expression and set the placeholder to the new VarDecl.

The change has a couple of nice side effects:
* We don't miss constructor calls not contained in DeclStmts anymore,
  allowing patterns like
    MutexLock{&mu}, requiresMutex();
  The scoped lock temporary will be destructed at the end of the full
  statement, so it protects the following call without the need for a
  scope, but with the ability to unlock in case of an exception.
* We support lifetime extension of temporaries. While unusual, one can
  now write
    const MutexLock &scope = MutexLock(&mu);
  and have it behave as expected.
* Destructors used to be handled in a weird way: since there is no
  expression in the AST for implicit destructor calls, we instead
  provided a made-up DeclRefExpr to the variable being destructed, and
  passed that instead of a CallExpr. Then later in translateAttrExpr
  there was special code that knew that destructor expressions worked a
  bit different.
* We were producing dummy DeclRefExprs in a number of places, this has
  been eliminated. We now use til::SExprs instead.

Technically this could break existing code, but the current handling
seems unexpected enough to justify this change.

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D129755
2022-10-13 19:36:15 +02:00
Hans Wennborg
a4afa2bde6 Revert "Thread safety analysis: Support copy-elided production of scoped capabilities through arbitrary calls"
This caused false positives, see comment on the code review.

> When support for copy elision was initially added in e97654b2f2807, it
> was taking attributes from a constructor call, although that constructor
> call is actually not involved. It seems more natural to use attributes
> on the function returning the scoped capability, which is where it's
> actually coming from. This would also support a number of interesting
> use cases, like producing different scope kinds without the need for tag
> types, or producing scopes from a private mutex.
>
> Changing the behavior was surprisingly difficult: we were not handling
> CXXConstructorExpr calls like regular calls but instead handled them
> through the DeclStmt they're contained in. This was based on the
> assumption that constructors are basically only called in variable
> declarations (not true because of temporaries), and that variable
> declarations necessitate constructors (not true with C++17 anymore).
>
> Untangling this required separating construction from assigning a
> variable name. When a call produces an object, we use a placeholder
> til::LiteralPtr for `this`, and we collect the call expression and
> placeholder in a map. Later when going through a DeclStmt, we look up
> the call expression and set the placeholder to the new VarDecl.
>
> The change has a couple of nice side effects:
> * We don't miss constructor calls not contained in DeclStmts anymore,
>   allowing patterns like
>     MutexLock{&mu}, requiresMutex();
>   The scoped lock temporary will be destructed at the end of the full
>   statement, so it protects the following call without the need for a
>   scope, but with the ability to unlock in case of an exception.
> * We support lifetime extension of temporaries. While unusual, one can
>   now write
>     const MutexLock &scope = MutexLock(&mu);
>   and have it behave as expected.
> * Destructors used to be handled in a weird way: since there is no
>   expression in the AST for implicit destructor calls, we instead
>   provided a made-up DeclRefExpr to the variable being destructed, and
>   passed that instead of a CallExpr. Then later in translateAttrExpr
>   there was special code that knew that destructor expressions worked a
>   bit different.
> * We were producing dummy DeclRefExprs in a number of places, this has
>   been eliminated. We now use til::SExprs instead.
>
> Technically this could break existing code, but the current handling
> seems unexpected enough to justify this change.
>
> Reviewed By: aaron.ballman
>
> Differential Revision: https://reviews.llvm.org/D129755

This reverts commit 0041a69495f828f6732803cfb0f1e3fddd7fbf2a and the follow-up
warning fix in 83d93d3c11ac9727bf3d4c5c956de44233cc7f87.
2022-10-07 14:30:36 +02:00
Aaron Puchert
0041a69495 Thread safety analysis: Support copy-elided production of scoped capabilities through arbitrary calls
When support for copy elision was initially added in e97654b2f2807, it
was taking attributes from a constructor call, although that constructor
call is actually not involved. It seems more natural to use attributes
on the function returning the scoped capability, which is where it's
actually coming from. This would also support a number of interesting
use cases, like producing different scope kinds without the need for tag
types, or producing scopes from a private mutex.

Changing the behavior was surprisingly difficult: we were not handling
CXXConstructorExpr calls like regular calls but instead handled them
through the DeclStmt they're contained in. This was based on the
assumption that constructors are basically only called in variable
declarations (not true because of temporaries), and that variable
declarations necessitate constructors (not true with C++17 anymore).

Untangling this required separating construction from assigning a
variable name. When a call produces an object, we use a placeholder
til::LiteralPtr for `this`, and we collect the call expression and
placeholder in a map. Later when going through a DeclStmt, we look up
the call expression and set the placeholder to the new VarDecl.

The change has a couple of nice side effects:
* We don't miss constructor calls not contained in DeclStmts anymore,
  allowing patterns like
    MutexLock{&mu}, requiresMutex();
  The scoped lock temporary will be destructed at the end of the full
  statement, so it protects the following call without the need for a
  scope, but with the ability to unlock in case of an exception.
* We support lifetime extension of temporaries. While unusual, one can
  now write
    const MutexLock &scope = MutexLock(&mu);
  and have it behave as expected.
* Destructors used to be handled in a weird way: since there is no
  expression in the AST for implicit destructor calls, we instead
  provided a made-up DeclRefExpr to the variable being destructed, and
  passed that instead of a CallExpr. Then later in translateAttrExpr
  there was special code that knew that destructor expressions worked a
  bit different.
* We were producing dummy DeclRefExprs in a number of places, this has
  been eliminated. We now use til::SExprs instead.

Technically this could break existing code, but the current handling
seems unexpected enough to justify this change.

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D129755
2022-10-06 22:19:09 +02:00
Zarko Todorovski
f5ad6fa279 [clang][docs] Inclusive language: remove use of sanity check in option description
Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D114562
2021-11-30 15:07:43 -05:00
Shao-Ce SUN
0c660256eb [NFC] Trim trailing whitespace in *.rst 2021-11-15 09:17:08 +08:00
Aaron Puchert
0e64a525c1 Thread safety analysis: Mock getter for private mutexes can be undefined
Usage in an annotation is no odr-use, so I think there needs to be no
definition. Upside is that in practice one will get linker errors if it
is actually odr-used instead of calling a function that returns 0.

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D106375
2021-07-23 14:46:02 +02:00
Russell Yanofsky
f702a6fa7c Thread safety analysis: Improve documentation for ASSERT_CAPABILITY
Previous description didn't actually state the effect the attribute has on
thread safety analysis (causing analysis to assume the capability is held).

Previous description was also ambiguous about (or slightly overstated) the
noreturn assumption made by thread safety analysis, implying the assumption had
to be true about the function's behavior in general, and not just its behavior
in places where it's used. Stating the assumption specifically should avoid a
perceived need to disable thread safety analysis in places where only asserting
that a specific capability is held would be better.

Reviewed By: aaronpuchert, vasild

Differential Revision: https://reviews.llvm.org/D87629
2020-09-26 22:16:50 +02:00
Aaron Puchert
bbb3baf620 Thread safety analysis: Improve documentation for scoped capabilities
They are for more powerful than the current documentation implies, this
adds

* adopting a lock,
* deferring a lock,
* manually unlocking the scoped capability,
* relocking the scoped capability, possibly in a different mode,
* try-relocking the scoped capability.

Also there is now a generic explanation how attributes on scoped
capabilities work. There has been confusion in the past about how to
annotate them (see e.g. PR33504), hopefully this clears things up.

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D87066
2020-09-06 20:37:42 +02:00
Aaron Puchert
cc6713a2c3 Thread safety analysis: Test and document release_generic_capability
The old locking attributes had a generic release, but as it turns out
the capability-based attributes have it as well.

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D87064
2020-09-06 20:37:41 +02:00
Aaron Puchert
8544defdcb Thread safety analysis: Document how try-acquire is handled
I don't think this is obvious, since try-acquire seemingly contradicts
our usual requirements of "no conditional locking".

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D87065
2020-09-05 14:26:43 +02:00
Aaron Ballman
b6d8070205 Correct the attribute spelling for guarded_var and pt_guarded_var.
Patch by Roman Lebedev.

llvm-svn: 302419
2017-05-08 12:39:17 +00:00
Aaron Ballman
05fd05ac52 Do not redefine the THREAD_ANNOTATION_ATTRIBUTE__ macro in the documentation.
Patch by Roman Lebedev.

llvm-svn: 302275
2017-05-05 19:56:09 +00:00
Aaron Ballman
8afcd0a71a Updating the documentation to include an operator! for negative capability support.
llvm-svn: 238020
2015-05-22 13:36:48 +00:00
Aaron Ballman
eb1e2f213a Correcting some grammar and typos, and adding CERT as a collaborator.
llvm-svn: 221992
2014-11-14 13:48:34 +00:00
DeLesley Hutchins
0d1ce2f199 Thread Safety Analysis: Update to documentation.
The attribute documentation now conforms to Aaron Ballman's renaming of the
thread safety attributes, as well as the new paper that is due to be published
in the conference on Source Code Analysis and Manipulation (SCAM 2014) later
this week.  In addition, recent changes to the analysis, such as checking
of references and negative capabilities, are now documented.

llvm-svn: 218420
2014-09-24 22:13:34 +00:00
Aaron Ballman
0580cd4ff5 Some of these headings had the incorrect number of "underlines" and so would get warnings when generating the content from Sphinx. No functional changes intended.
llvm-svn: 201713
2014-02-19 20:43:58 +00:00
DeLesley Hutchins
c51e08c7ea Updated documentation for Thread Safety Analysis.
llvm-svn: 201598
2014-02-18 19:42:01 +00:00