Age | Commit message (Collapse) | Author | Files | Lines |
|
Fix a false positive in thread safety alias analysis caused by incorrect
late resolution of aliases. The analysis previously failed to
distinguish between an alias and its defining expression; reassigning a
variable within that expression (e.g., `ptr` in `alias = ptr->field`)
would incorrectly change the dependent alias as well.
The fix is to properly use LocalVariableMap::lookupExpr's updated
context in a recursive lookup.
Reported-by: Christoph Hellwig <hch@lst.de>
Link: https://lkml.kernel.org/r/20250919140803.GA23745@lst.de
|
|
Add basic alias analysis for capabilities by reusing LocalVariableMap,
which tracks currently valid definitions of variables. Aliases created
through complex control flow are not tracked. This implementation would
satisfy the basic needs of addressing the concerns for Linux kernel
application [1].
For example, the analysis will no longer generate false positives for
cases such as (and many others):
void testNestedAccess(Container *c) {
Foo *ptr = &c->foo;
ptr->mu.Lock();
c->foo.data = 42; // OK - no false positive
ptr->mu.Unlock();
}
void testNestedAcquire(Container *c) EXCLUSIVE_LOCK_FUNCTION(&c->foo.mu)
{
Foo *buf = &c->foo;
buf->mu.Lock(); // OK - no false positive
}
Given the analysis is now able to identify potentially unsafe patterns
it was not able to identify previously (see added FIXME test case for an
example), mark alias resolution as a "beta" feature behind the flag
`-Wthread-safety-beta`.
**Fixing LocalVariableMap:** It was found that LocalVariableMap was not
properly tracking loop-invariant aliases: the old implementation failed
because the merge logic compared raw VarDefinition IDs. The algorithm
for handling back-edges (in createReferenceContext()) generates new
'reference' definitions for loop-scoped variables. Later ID comparison
caused alias invalidation at back-edge merges (in intersectBackEdge())
and at subsequent forward-merges with non-loop paths (in
intersectContexts()).
Fix LocalVariableMap by adding the getCanonicalDefinitionID() helper
that resolves any definition ID down to its non-reference base. As a
result, a variable's definition is preserved across control-flow merges
as long as its underlying canonical definition remains the same.
Link:
https://lore.kernel.org/all/CANpmjNPquO=W1JAh1FNQb8pMQjgeZAKCPQUAd7qUg=5pjJ6x=Q@mail.gmail.com/
[1]
|
|
This reintroduces `Type.h`, having earlier been renamed to `TypeBase.h`,
as a redirection to `TypeBase.h`, and redirects most users to include
the former instead.
This is a preparatory patch for being able to provide inline definitions
for `Type` methods which would otherwise cause a circular dependency
with `Decl{,CXX}.h`.
Doing these operations into their own NFC patch helps the git rename
detection logic work, preserving the history.
This patch makes clang just a little slower to build (~0.17%), just
because it makes more code indirectly include `DeclCXX.h`.
|
|
This is a preparatory patch, to be able to provide inline definitions
for `Type` functions which depend on `Decl{,CXX}.h`. As the latter also
depends on `Type.h`, this would not be possible without some
reorganizing.
Splitting this rename into its own patch allows git to track this as a
rename, and preserve all git history, and not force any code
reformatting.
A later NFC patch will reintroduce `Type.h` as redirection to
`TypeBase.h`, rewriting most places back to directly including `Type.h`
instead of `TypeBase.h`, leaving only a handful of places where this is
necessary.
Then yet a later patch will exploit this by making more stuff inline.
|
|
This changes a bunch of places which use getAs<TagType>, including
derived types, just to obtain the tag definition.
This is preparation for #155028, offloading all the changes that PR used
to introduce which don't depend on any new helpers.
|
|
This is a major change on how we represent nested name qualifications in
the AST.
* The nested name specifier itself and how it's stored is changed. The
prefixes for types are handled within the type hierarchy, which makes
canonicalization for them super cheap, no memory allocation required.
Also translating a type into nested name specifier form becomes a no-op.
An identifier is stored as a DependentNameType. The nested name
specifier gains a lightweight handle class, to be used instead of
passing around pointers, which is similar to what is implemented for
TemplateName. There is still one free bit available, and this handle can
be used within a PointerUnion and PointerIntPair, which should keep
bit-packing aficionados happy.
* The ElaboratedType node is removed, all type nodes in which it could
previously apply to can now store the elaborated keyword and name
qualifier, tail allocating when present.
* TagTypes can now point to the exact declaration found when producing
these, as opposed to the previous situation of there only existing one
TagType per entity. This increases the amount of type sugar retained,
and can have several applications, for example in tracking module
ownership, and other tools which care about source file origins, such as
IWYU. These TagTypes are lazily allocated, in order to limit the
increase in AST size.
This patch offers a great performance benefit.
It greatly improves compilation time for
[stdexec](https://github.com/NVIDIA/stdexec). For one datapoint, for
`test_on2.cpp` in that project, which is the slowest compiling test,
this patch improves `-c` compilation time by about 7.2%, with the
`-fsyntax-only` improvement being at ~12%.
This has great results on compile-time-tracker as well:

This patch also further enables other optimziations in the future, and
will reduce the performance impact of template specialization resugaring
when that lands.
It has some other miscelaneous drive-by fixes.
About the review: Yes the patch is huge, sorry about that. Part of the
reason is that I started by the nested name specifier part, before the
ElaboratedType part, but that had a huge performance downside, as
ElaboratedType is a big performance hog. I didn't have the steam to go
back and change the patch after the fact.
There is also a lot of internal API changes, and it made sense to remove
ElaboratedType in one go, versus removing it from one type at a time, as
that would present much more churn to the users. Also, the nested name
specifier having a different API avoids missing changes related to how
prefixes work now, which could make existing code compile but not work.
How to review: The important changes are all in
`clang/include/clang/AST` and `clang/lib/AST`, with also important
changes in `clang/lib/Sema/TreeTransform.h`.
The rest and bulk of the changes are mostly consequences of the changes
in API.
PS: TagType::getDecl is renamed to `getOriginalDecl` in this patch, just
for easier to rebasing. I plan to rename it back after this lands.
Fixes #136624
Fixes https://github.com/llvm/llvm-project/issues/43179
Fixes https://github.com/llvm/llvm-project/issues/68670
Fixes https://github.com/llvm/llvm-project/issues/92757
|
|
These are identified by misc-include-cleaner. I've filtered out those
that break builds. Also, I'm staying away from llvm-config.h,
config.h, and Compiler.h, which likely cause platform- or
compiler-specific build failures.
|
|
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.
|
|
Note that PointerUnion::dyn_cast has been soft deprecated in
PointerUnion.h:
// FIXME: Replace the uses of is(), get() and dyn_cast() with
// isa<T>, cast<T> and the llvm::dyn_cast<T>
Literal migration would result in dyn_cast_if_present (see the
definition of PointerUnion::dyn_cast), but this patch uses dyn_cast
because we expect Ctx->FunArgs to be nonnull.
|
|
For operator calls that go to methods we need to substitute the first
parameter for "this" and the following parameters into the function
parameters, instead of substituting all of them into the parameters.
This revealed an issue about lambdas. An existing test accidentally
worked because the substitution bug was covered by a speciality of
lambdas: a CXXThisExpr in a lambda CXXMethodDecl does not refer to the
implicit this argument of the method, but to a captured "this" from the
context the lambda was created in. This can happen for operator calls,
where it worked due to the substitution bug (we treated the implicit
this argument incorrectly as parameter), and for regular calls (i.e.
obj.operator()(args) instead of obj(args)), where it didn't work.
The correct fix seems to be to clear the self-argument on a lambda call.
Lambdas can only capture "this" inside methods, and calls to the lambda
in that scope cannot substitute anything for "this".
|
|
Note that PointerUnion::{is,get} have been soft deprecated in
PointerUnion.h:
// FIXME: Replace the uses of is(), get() and dyn_cast() with
// isa<T>, cast<T> and the llvm::dyn_cast<T>
I'm not touching PointerUnion::dyn_cast for now because it's a bit
complicated; we could blindly migrate it to dyn_cast_if_present, but
we should probably use dyn_cast when the operand is known to be
non-null.
|
|
Seems to be a common pattern.
|
|
Ignore `ImplicitCastExpr` when building `AttrExp` for capability
attribute diagnostics.
Fixes: https://github.com/llvm/llvm-project/issues/92118.
|
|
We routinely rely on implicit conversions of string literals to
StringRef so that we can use operator==(StringRef, StringRef).
The LHS here are all known to be of StringRef.
|
|
I called this function when investigating the issue
(https://github.com/llvm/llvm-project/issues/78131), and I was surprised
to see the definition is commented out.
I think it makes sense to provide the definition even though the
implementation is not stable.
|
|
This patch implements P0847R7 (partially),
CWG2561 and CWG2653.
Reviewed By: aaron.ballman, #clang-language-wg
Differential Revision: https://reviews.llvm.org/D140828
|
|
Consider cleanup functions in thread safety analysis.
Differential Revision: https://reviews.llvm.org/D152504
|
|
|
|
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
|
|
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.
|
|
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
|
|
|
|
This should make us print the right capability kind in many more cases,
especially when attributes name multiple capabilities of different kinds.
Previously we were trying to deduce the capability kind from the
original attribute, but most attributes can name multiple capabilities,
which could be of different kinds. So instead we derive the kind when
translating the attribute expression, and then store it in the returned
CapabilityExpr. Then we can extract the corresponding capability name
when we need it, which saves us lots of plumbing and almost guarantees
that the name is right.
I didn't bother adding any tests for this because it's just a usability
improvement and it's pretty much evident from the code that we don't
fall back to "mutex" anymore (save for a few cases that I'll address in
a separate change).
Reviewed By: aaron.ballman
Differential Revision: https://reviews.llvm.org/D124131
|
|
<string> is currently the highest impact header in a clang+llvm build:
https://commondatastorage.googleapis.com/chromium-browser-clang/llvm-include-analysis.html
One of the most common places this is being included is the APInt.h header, which needs it for an old toString() implementation that returns std::string - an inefficient method compared to the SmallString versions that it actually wraps.
This patch replaces these APInt/APSInt methods with a pair of llvm::toString() helpers inside StringExtras.h, adjusts users accordingly and removes the <string> from APInt.h - I was hoping that more of these users could be converted to use the SmallString methods, but it appears that most end up creating a std::string anyhow. I avoided trying to use the raw_ostream << operators as well as I didn't want to lose having the integer radix explicit in the code.
Differential Revision: https://reviews.llvm.org/D103888
|
|
The constructor of Project asserts that the contained ValueDecl is not
null, use that in the ThreadSafetyAnalyzer. In the case of LiteralPtr
it's the other way around.
Also dyn_cast<> is sufficient if we know something isn't null.
|
|
scope" & followup
This appears to cause false-positives because it started to warn on local non-global variables.
Repro posted to https://reviews.llvm.org/D84604#2262745
This reverts commit 9dcc82f34ea9b623d82d2577b93aaf67d36dabd2.
This reverts commit b2ce79ef66157dd752e3864ece57915e23a73f5d.
|
|
The constructor asserts that, use it in the ThreadSafetyAnalyzer.
Also note that the result of a cast<> cannot be null.
|
|
Summary:
this patch refactor representation of materialized temporaries to prevent an issue raised by rsmith in https://reviews.llvm.org/D63640#inline-612718
Reviewers: rsmith, martong, shafik
Reviewed By: rsmith
Subscribers: thakis, sammccall, ilya-biryukov, rnkovacs, arphaman, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D69360
|
|
This reverts commit 08ea1ee2db5f9d6460fef1d79d0d1d1a5eb78982.
It broke ./ClangdTests/FindExplicitReferencesTest.All
on the bots, see comments on https://reviews.llvm.org/D69360
|
|
Summary:
this patch refactor representation of materialized temporaries to prevent an issue raised by rsmith in https://reviews.llvm.org/D63640#inline-612718
Reviewers: rsmith, martong, shafik
Reviewed By: rsmith
Subscribers: rnkovacs, arphaman, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D69360
|
|
Summary:
SExprBuilder::translateDeclRefExpr was only looking at FunctionDecl and not also looking at ObjCMethodDecl. It should consider both because the attributes can be used on Objective-C as well.
<rdar://problem/48941331>
Reviewers: dexonsmith, erik.pilkington
Subscribers: jkorous, jdoerfert, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D59523
llvm-svn: 356940
|
|
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
|
|
All of the other constructors already take a reference to the AST context.
This avoids calling Decl::getASTContext in most cases. Additionally move
the definition of the constructor from Expr.h to Expr.cpp since it is calling
DeclRefExpr::computeDependence. NFC.
llvm-svn: 349901
|
|
A ConstantExpr class represents a full expression that's in a context where a
constant expression is required. This class reflects the path the evaluator
took to reach the expression rather than the syntactic context in which the
expression occurs.
In the future, the class will be expanded to cache the result of the evaluated
expression so that it's not needlessly re-evaluated
Reviewed By: rsmith
Differential Revision: https://reviews.llvm.org/D53475
llvm-svn: 345692
|
|
Not used productively, so no observable functional change.
Note that printSCFG doesn't yet work reliably, it seems to crash
sometimes.
llvm-svn: 342790
|
|
Summary:
This imitates the code for MemberExpr.
Fixes PR38896.
Reviewers: aaron.ballman, delesley, lukasza, rjmccall
Reviewed By: delesley
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D52200
llvm-svn: 342600
|
|
For function pointers, the FunctionDecl of the callee is unknown, so
getDirectCallee will return nullptr. We have to catch that case to avoid
crashing. We assume there is no attribute then.
llvm-svn: 342519
|
|
This is similar to the LLVM change https://reviews.llvm.org/D46290.
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
for i in $(git grep -l '\\brief'); do perl -pi -e 's/\\brief //g' $i & done
Differential Revision: https://reviews.llvm.org/D46320
llvm-svn: 331834
|
|
Found via codespell -q 3 -I ../clang-whitelist.txt
Where whitelist consists of:
archtype
cas
classs
checkk
compres
definit
frome
iff
inteval
ith
lod
methode
nd
optin
ot
pres
statics
te
thru
Patch by luzpaz! (This is a subset of D44188 that applies cleanly with a few
files that have dubious fixes reverted.)
Differential revision: https://reviews.llvm.org/D44188
llvm-svn: 329399
|
|
other minor fixes (NFC).
llvm-svn: 327453
|
|
Convert most uses to range-for loops. No functionality change intended.
llvm-svn: 320954
|
|
Adding the new enumerator forced a bunch more changes into this patch than I
would have liked. The -Wtautological-compare warning was extended to properly
check the new comparison operator, clang-format needed updating because it uses
precedence levels as weights for determining where to break lines (and several
operators increased their precedence levels with this change), thread-safety
analysis needed changes to build its own IL properly for the new operator.
All "real" semantic checking for this operator has been deferred to a future
patch. For now, we use the relational comparison rules and arbitrarily give
the builtin form of the operator a return type of 'void'.
llvm-svn: 320707
|
|
The implementation is in AnalysisDeclContext.cpp and the class is called
AnalysisDeclContext.
Making those match up has numerous benefits, including:
- Easier jump from header to/from implementation.
- Easily identify filename from class.
Differential Revision: https://reviews.llvm.org/D37500
llvm-svn: 312671
|
|
temporary produces an xvalue, not a prvalue. Support this by materializing the
temporary prior to performing the member access.
llvm-svn: 288563
|
|
Summary: Removed unused headers, replaced some headers with forward class declarations
Patch by: Eugene <claprix@yandex.ru>
Differential Revision: https://reviews.llvm.org/D20100
llvm-svn: 275882
|
|
of await_* calls, and AST representation for same.
llvm-svn: 251387
|
|
minor cleanups
Patch by Eugene Zelenko!
Differential Revision: http://reviews.llvm.org/D13406
llvm-svn: 249484
|
|
variables as well member variables.
llvm-svn: 248803
|
|
across modules.
llvm-svn: 244714
|
|
namespaces
NFC.
llvm-svn: 231653
|