Skip to content

Commit deedf7a

Browse files
committed
Merge "merge main into amd-staging" into amd-staging
2 parents 43e0b73 + 2c82c4c commit deedf7a

File tree

79 files changed

+1978
-1385
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+1978
-1385
lines changed

clang-tools-extra/clang-tidy/bugprone/UnusedLocalNonTrivialVariableCheck.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ static constexpr StringRef DefaultIncludeTypeRegex =
2929

3030
AST_MATCHER(VarDecl, isLocalVarDecl) { return Node.isLocalVarDecl(); }
3131
AST_MATCHER(VarDecl, isReferenced) { return Node.isReferenced(); }
32+
AST_MATCHER_P(VarDecl, explicitMarkUnused, LangOptions, LangOpts) {
33+
// Implementations should not emit a warning that a name-independent
34+
// declaration is used or unused.
35+
return Node.hasAttr<UnusedAttr>() ||
36+
(LangOpts.CPlusPlus26 && Node.isPlaceholderVar(LangOpts));
37+
}
3238
AST_MATCHER(Type, isReferenceType) { return Node.isReferenceType(); }
3339
AST_MATCHER(QualType, isTrivial) {
3440
return Node.isTrivialType(Finder->getASTContext()) ||
@@ -60,7 +66,7 @@ void UnusedLocalNonTrivialVariableCheck::registerMatchers(MatchFinder *Finder) {
6066
varDecl(isLocalVarDecl(), unless(isReferenced()),
6167
unless(isExceptionVariable()), hasLocalStorage(), isDefinition(),
6268
unless(hasType(isReferenceType())), unless(hasType(isTrivial())),
63-
unless(hasAttr(attr::Kind::Unused)),
69+
unless(explicitMarkUnused(getLangOpts())),
6470
hasType(hasUnqualifiedDesugaredType(
6571
anyOf(recordType(hasDeclaration(namedDecl(
6672
matchesAnyListedName(IncludeTypes),

clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,12 +208,13 @@ TEST_F(LSPTest, ClangTidyRename) {
208208
Annotations Source(R"cpp(
209209
void [[foo]]() {}
210210
)cpp");
211-
Opts.ClangTidyProvider = [](tidy::ClangTidyOptions &ClangTidyOpts,
212-
llvm::StringRef) {
211+
constexpr auto ClangTidyProvider = [](tidy::ClangTidyOptions &ClangTidyOpts,
212+
llvm::StringRef) {
213213
ClangTidyOpts.Checks = {"-*,readability-identifier-naming"};
214214
ClangTidyOpts.CheckOptions["readability-identifier-naming.FunctionCase"] =
215215
"CamelCase";
216216
};
217+
Opts.ClangTidyProvider = ClangTidyProvider;
217218
auto &Client = start();
218219
Client.didOpen("foo.hpp", Header.code());
219220
Client.didOpen("foo.cpp", Source.code());
@@ -266,10 +267,11 @@ TEST_F(LSPTest, ClangTidyCrash_Issue109367) {
266267
// This test requires clang-tidy checks to be linked in.
267268
if (!CLANGD_TIDY_CHECKS)
268269
return;
269-
Opts.ClangTidyProvider = [](tidy::ClangTidyOptions &ClangTidyOpts,
270-
llvm::StringRef) {
270+
constexpr auto ClangTidyProvider = [](tidy::ClangTidyOptions &ClangTidyOpts,
271+
llvm::StringRef) {
271272
ClangTidyOpts.Checks = {"-*,boost-use-ranges"};
272273
};
274+
Opts.ClangTidyProvider = ClangTidyProvider;
273275
// Check that registering the boost-use-ranges checker's matchers
274276
// on two different threads does not cause a crash.
275277
auto &Client = start();

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,10 @@ Changes in existing checks
241241
<clang-tidy/checks/bugprone/unsafe-functions>` check to allow specifying
242242
additional functions to match.
243243

244+
- Improved :doc:`bugprone-unused-local-non-trivial-variable
245+
<clang-tidy/checks/bugprone/unused-local-non-trivial-variable>` check to avoid
246+
false positives when using name-independent variables after C++26.
247+
244248
- Improved :doc:`bugprone-use-after-move
245249
<clang-tidy/checks/bugprone/use-after-move>` to avoid triggering on
246250
``reset()`` calls on moved-from ``std::optional`` and ``std::any`` objects,

clang-tools-extra/docs/clang-tidy/checks/bugprone/unused-local-non-trivial-variable.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ The following types of variables are excluded from this check:
1212
* static or thread local
1313
* structured bindings
1414
* variables with ``[[maybe_unused]]`` attribute
15+
* name-independent variables
1516

1617
This check can be configured to warn on all non-trivial variables by setting
1718
`IncludeTypes` to `.*`, and excluding specific types using `ExcludeTypes`.

clang-tools-extra/include-cleaner/lib/Analysis.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,9 @@ analyze(llvm::ArrayRef<Decl *> ASTRoots,
8585
const auto MainFile = *SM.getFileEntryRefForID(SM.getMainFileID());
8686
llvm::DenseSet<const Include *> Used;
8787
llvm::StringMap<Header> Missing;
88+
constexpr auto DefaultHeaderFilter = [](llvm::StringRef) { return false; };
8889
if (!HeaderFilter)
89-
HeaderFilter = [](llvm::StringRef) { return false; };
90+
HeaderFilter = DefaultHeaderFilter;
9091
OptionalDirectoryEntryRef ResourceDir =
9192
PP.getHeaderSearchInfo().getModuleMap().getBuiltinDir();
9293
walkUsed(ASTRoots, MacroRefs, PI, PP,
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %check_clang_tidy -std=c++23 -check-suffixes=,CXX23 %s bugprone-unused-local-non-trivial-variable %t -- \
2+
// RUN: -config="{CheckOptions: {bugprone-unused-local-non-trivial-variable.IncludeTypes: '::async::Foo'}}" \
3+
// RUN: --
4+
// RUN: %check_clang_tidy -std=c++26 %s bugprone-unused-local-non-trivial-variable %t -- \
5+
// RUN: -config="{CheckOptions: {bugprone-unused-local-non-trivial-variable.IncludeTypes: '::async::Foo'}}" \
6+
// RUN: --
7+
8+
namespace async {
9+
class Foo {
10+
public:
11+
~Foo();
12+
private:
13+
};
14+
} // namespace async
15+
16+
void check() {
17+
async::Foo C;
18+
// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: unused local variable 'C' of type 'async::Foo' [bugprone-unused-local-non-trivial-variable]
19+
async::Foo _;
20+
// CHECK-MESSAGES-CXX23: :[[@LINE-1]]:14: warning: unused local variable '_' of type 'async::Foo' [bugprone-unused-local-non-trivial-variable]
21+
}

clang/include/clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CACHED_CONST_ACCESSORS_LATTICE_H
1414
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CACHED_CONST_ACCESSORS_LATTICE_H
1515

16+
#include "clang/AST/Decl.h"
1617
#include "clang/AST/Expr.h"
18+
#include "clang/AST/Type.h"
1719
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
1820
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
1921
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
@@ -71,10 +73,27 @@ template <typename Base> class CachedConstAccessorsLattice : public Base {
7173
/// Requirements:
7274
///
7375
/// - `CE` should return a location (GLValue or a record type).
76+
///
77+
/// DEPRECATED: switch users to the below overload which takes Callee and Type
78+
/// directly.
7479
StorageLocation *getOrCreateConstMethodReturnStorageLocation(
7580
const RecordStorageLocation &RecordLoc, const CallExpr *CE,
7681
Environment &Env, llvm::function_ref<void(StorageLocation &)> Initialize);
7782

83+
/// Creates or returns a previously created `StorageLocation` associated with
84+
/// a const method call `obj.getFoo()` where `RecordLoc` is the
85+
/// `RecordStorageLocation` of `obj`, `Callee` is the decl for `getFoo`.
86+
///
87+
/// The callback `Initialize` runs on the storage location if newly created.
88+
///
89+
/// Requirements:
90+
///
91+
/// - `Callee` should return a location (return type is a reference type or a
92+
/// record type).
93+
StorageLocation &getOrCreateConstMethodReturnStorageLocation(
94+
const RecordStorageLocation &RecordLoc, const FunctionDecl *Callee,
95+
Environment &Env, llvm::function_ref<void(StorageLocation &)> Initialize);
96+
7897
void clearConstMethodReturnValues(const RecordStorageLocation &RecordLoc) {
7998
ConstMethodReturnValues.erase(&RecordLoc);
8099
}
@@ -212,6 +231,27 @@ CachedConstAccessorsLattice<Base>::getOrCreateConstMethodReturnStorageLocation(
212231
return &Loc;
213232
}
214233

234+
template <typename Base>
235+
StorageLocation &
236+
CachedConstAccessorsLattice<Base>::getOrCreateConstMethodReturnStorageLocation(
237+
const RecordStorageLocation &RecordLoc, const FunctionDecl *Callee,
238+
Environment &Env, llvm::function_ref<void(StorageLocation &)> Initialize) {
239+
assert(Callee != nullptr);
240+
QualType Type = Callee->getReturnType();
241+
assert(!Type.isNull());
242+
assert(Type->isReferenceType() || Type->isRecordType());
243+
auto &ObjMap = ConstMethodReturnStorageLocations[&RecordLoc];
244+
auto it = ObjMap.find(Callee);
245+
if (it != ObjMap.end())
246+
return *it->second;
247+
248+
StorageLocation &Loc = Env.createStorageLocation(Type.getNonReferenceType());
249+
Initialize(Loc);
250+
251+
ObjMap.insert({Callee, &Loc});
252+
return Loc;
253+
}
254+
215255
} // namespace dataflow
216256
} // namespace clang
217257

clang/include/clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,13 @@ struct UncheckedOptionalAccessModelOptions {
3737
/// can't identify when their results are used safely (across calls),
3838
/// resulting in false positives in all such cases. Note: this option does not
3939
/// cover access through `operator[]`.
40-
/// FIXME: we currently cache and equate the result of const accessors
41-
/// returning pointers, so cover the case of operator-> followed by
42-
/// operator->, which covers the common case of smart pointers. We also cover
43-
/// some limited cases of returning references (if return type is an optional
44-
/// type), so cover some cases of operator* followed by operator*. We don't
45-
/// cover mixing operator-> and operator*. Once we are confident in this const
46-
/// accessor caching, we shouldn't need the IgnoreSmartPointerDereference
47-
/// option anymore.
40+
///
41+
/// FIXME: we now cache and equate the result of const accessors
42+
/// that look like unique_ptr, have both `->` (returning a pointer type) and
43+
/// `*` (returning a reference type). This includes mixing `->` and
44+
/// `*` in a sequence of calls as long as the object is not modified. Once we
45+
/// are confident in this const accessor caching, we shouldn't need the
46+
/// IgnoreSmartPointerDereference option anymore.
4847
bool IgnoreSmartPointerDereference = false;
4948
};
5049

clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,13 @@
2727
#include <cassert>
2828

2929
#include "clang/AST/Decl.h"
30+
#include "clang/AST/Expr.h"
3031
#include "clang/AST/Stmt.h"
3132
#include "clang/ASTMatchers/ASTMatchers.h"
33+
#include "clang/Analysis/FlowSensitive/MatchSwitch.h"
34+
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
35+
#include "clang/Analysis/FlowSensitive/Value.h"
36+
#include "llvm/ADT/STLFunctionalExtras.h"
3237

3338
namespace clang::dataflow {
3439

@@ -58,6 +63,107 @@ ast_matchers::StatementMatcher isSmartPointerLikeOperatorArrow();
5863
ast_matchers::StatementMatcher isSmartPointerLikeValueMethodCall();
5964
ast_matchers::StatementMatcher isSmartPointerLikeGetMethodCall();
6065

66+
// Common transfer functions.
67+
68+
/// Returns the "canonical" callee for smart pointer operators (`*` and `->`)
69+
/// as a key for caching.
70+
///
71+
/// We choose `*` as the canonical one, since it needs a
72+
/// StorageLocation anyway.
73+
///
74+
/// Note: there may be multiple `operator*` (one const, one non-const).
75+
/// We pick the const one, which the above provided matchers require to exist.
76+
const FunctionDecl *
77+
getCanonicalSmartPointerLikeOperatorCallee(const CallExpr *CE);
78+
79+
/// A transfer function for `operator*` (and `value`) calls that can be
80+
/// cached. Runs the `InitializeLoc` callback to initialize any new
81+
/// StorageLocations.
82+
///
83+
/// Requirements:
84+
///
85+
/// - LatticeT should use the `CachedConstAccessorsLattice` mixin.
86+
template <typename LatticeT>
87+
void transferSmartPointerLikeCachedDeref(
88+
const CallExpr *DerefExpr, RecordStorageLocation *SmartPointerLoc,
89+
TransferState<LatticeT> &State,
90+
llvm::function_ref<void(StorageLocation &)> InitializeLoc);
91+
92+
/// A transfer function for `operator->` (and `get`) calls that can be cached.
93+
/// Runs the `InitializeLoc` callback to initialize any new StorageLocations.
94+
///
95+
/// Requirements:
96+
///
97+
/// - LatticeT should use the `CachedConstAccessorsLattice` mixin.
98+
template <typename LatticeT>
99+
void transferSmartPointerLikeCachedGet(
100+
const CallExpr *GetExpr, RecordStorageLocation *SmartPointerLoc,
101+
TransferState<LatticeT> &State,
102+
llvm::function_ref<void(StorageLocation &)> InitializeLoc);
103+
104+
template <typename LatticeT>
105+
void transferSmartPointerLikeCachedDeref(
106+
const CallExpr *DerefExpr, RecordStorageLocation *SmartPointerLoc,
107+
TransferState<LatticeT> &State,
108+
llvm::function_ref<void(StorageLocation &)> InitializeLoc) {
109+
if (State.Env.getStorageLocation(*DerefExpr) != nullptr)
110+
return;
111+
if (SmartPointerLoc == nullptr)
112+
return;
113+
114+
const FunctionDecl *Callee = DerefExpr->getDirectCallee();
115+
if (Callee == nullptr)
116+
return;
117+
const FunctionDecl *CanonicalCallee =
118+
getCanonicalSmartPointerLikeOperatorCallee(DerefExpr);
119+
// This shouldn't happen, as we should at least find `Callee` itself.
120+
assert(CanonicalCallee != nullptr);
121+
if (CanonicalCallee != Callee) {
122+
// When using the provided matchers, we should always get a reference to
123+
// the same type.
124+
assert(CanonicalCallee->getReturnType()->isReferenceType() &&
125+
Callee->getReturnType()->isReferenceType());
126+
assert(CanonicalCallee->getReturnType()
127+
.getNonReferenceType()
128+
->getCanonicalTypeUnqualified() ==
129+
Callee->getReturnType()
130+
.getNonReferenceType()
131+
->getCanonicalTypeUnqualified());
132+
}
133+
134+
StorageLocation &LocForValue =
135+
State.Lattice.getOrCreateConstMethodReturnStorageLocation(
136+
*SmartPointerLoc, CanonicalCallee, State.Env, InitializeLoc);
137+
State.Env.setStorageLocation(*DerefExpr, LocForValue);
138+
}
139+
140+
template <typename LatticeT>
141+
void transferSmartPointerLikeCachedGet(
142+
const CallExpr *GetExpr, RecordStorageLocation *SmartPointerLoc,
143+
TransferState<LatticeT> &State,
144+
llvm::function_ref<void(StorageLocation &)> InitializeLoc) {
145+
if (SmartPointerLoc == nullptr)
146+
return;
147+
148+
const FunctionDecl *CanonicalCallee =
149+
getCanonicalSmartPointerLikeOperatorCallee(GetExpr);
150+
151+
if (CanonicalCallee != nullptr) {
152+
auto &LocForValue =
153+
State.Lattice.getOrCreateConstMethodReturnStorageLocation(
154+
*SmartPointerLoc, CanonicalCallee, State.Env, InitializeLoc);
155+
State.Env.setValue(*GetExpr,
156+
State.Env.template create<PointerValue>(LocForValue));
157+
} else {
158+
// Otherwise, just cache the pointer value as if it was a const accessor.
159+
Value *Val = State.Lattice.getOrCreateConstMethodReturnValue(
160+
*SmartPointerLoc, GetExpr, State.Env);
161+
if (Val == nullptr)
162+
return;
163+
State.Env.setValue(*GetExpr, *Val);
164+
}
165+
}
166+
61167
} // namespace clang::dataflow
62168

63169
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_SMARTPOINTERACCESSORCACHING_H

clang/include/clang/Basic/Attr.td

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4335,16 +4335,6 @@ def HLSLLoopHint: StmtAttr {
43354335
let Documentation = [HLSLLoopHintDocs, HLSLUnrollHintDocs];
43364336
}
43374337

4338-
def HLSLControlFlowHint: StmtAttr {
4339-
/// [branch]
4340-
/// [flatten]
4341-
let Spellings = [Microsoft<"branch">, Microsoft<"flatten">];
4342-
let Subjects = SubjectList<[IfStmt],
4343-
ErrorDiag, "'if' statements">;
4344-
let LangOpts = [HLSL];
4345-
let Documentation = [InternalOnly];
4346-
}
4347-
43484338
def CapturedRecord : InheritableAttr {
43494339
// This attribute has no spellings as it is only ever created implicitly.
43504340
let Spellings = [];

0 commit comments

Comments
 (0)