Skip to content

Commit bc9dded

Browse files
SC llvm teamSC llvm team
authored andcommitted
Merged main:be6ccc98f382 into origin/amd-gfx:943bd63b166f
Local branch origin/amd-gfx 943bd63 Merged main:146ad71bc71a into origin/amd-gfx:b969d463888c Remote branch main be6ccc9 [VPlan] Split out VPBlendRecipe simplifications from simplifyRecipes. NFC (llvm#134073)
2 parents 943bd63 + be6ccc9 commit bc9dded

File tree

48 files changed

+577
-189
lines changed

Some content is hidden

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

48 files changed

+577
-189
lines changed

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

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,23 @@ AST_MATCHER(CXXRecordDecl, correctHandleCaptureThisLambda) {
6464

6565
constexpr const char *DefaultFunctionWrapperTypes =
6666
"::std::function;::std::move_only_function;::boost::function";
67+
constexpr const char *DefaultBindFunctions =
68+
"::std::bind;::boost::bind;::std::bind_front;::std::bind_back;"
69+
"::boost::compat::bind_front;::boost::compat::bind_back";
6770

6871
CapturingThisInMemberVariableCheck::CapturingThisInMemberVariableCheck(
6972
StringRef Name, ClangTidyContext *Context)
7073
: ClangTidyCheck(Name, Context),
7174
FunctionWrapperTypes(utils::options::parseStringList(
72-
Options.get("FunctionWrapperTypes", DefaultFunctionWrapperTypes))) {}
75+
Options.get("FunctionWrapperTypes", DefaultFunctionWrapperTypes))),
76+
BindFunctions(utils::options::parseStringList(
77+
Options.get("BindFunctions", DefaultBindFunctions))) {}
7378
void CapturingThisInMemberVariableCheck::storeOptions(
7479
ClangTidyOptions::OptionMap &Opts) {
7580
Options.store(Opts, "FunctionWrapperTypes",
7681
utils::options::serializeStringList(FunctionWrapperTypes));
82+
Options.store(Opts, "BindFunctions",
83+
utils::options::serializeStringList(BindFunctions));
7784
}
7885

7986
void CapturingThisInMemberVariableCheck::registerMatchers(MatchFinder *Finder) {
@@ -87,33 +94,52 @@ void CapturingThisInMemberVariableCheck::registerMatchers(MatchFinder *Finder) {
8794
// [self = this]
8895
capturesVar(varDecl(hasInitializer(cxxThisExpr())))));
8996
auto IsLambdaCapturingThis =
90-
lambdaExpr(hasAnyCapture(CaptureThis.bind("capture"))).bind("lambda");
91-
auto IsInitWithLambda =
92-
anyOf(IsLambdaCapturingThis,
93-
cxxConstructExpr(hasArgument(0, IsLambdaCapturingThis)));
97+
lambdaExpr(hasAnyCapture(CaptureThis)).bind("lambda");
98+
99+
auto IsBindCapturingThis =
100+
callExpr(
101+
callee(functionDecl(matchers::matchesAnyListedName(BindFunctions))
102+
.bind("callee")),
103+
hasAnyArgument(cxxThisExpr()))
104+
.bind("bind");
105+
106+
auto IsInitWithLambdaOrBind =
107+
anyOf(IsLambdaCapturingThis, IsBindCapturingThis,
108+
cxxConstructExpr(hasArgument(
109+
0, anyOf(IsLambdaCapturingThis, IsBindCapturingThis))));
110+
94111
Finder->addMatcher(
95112
cxxRecordDecl(
96113
anyOf(has(cxxConstructorDecl(
97114
unless(isCopyConstructor()), unless(isMoveConstructor()),
98115
hasAnyConstructorInitializer(cxxCtorInitializer(
99116
isMemberInitializer(), forField(IsStdFunctionField),
100-
withInitializer(IsInitWithLambda))))),
117+
withInitializer(IsInitWithLambdaOrBind))))),
101118
has(fieldDecl(IsStdFunctionField,
102-
hasInClassInitializer(IsInitWithLambda)))),
119+
hasInClassInitializer(IsInitWithLambdaOrBind)))),
103120
unless(correctHandleCaptureThisLambda())),
104121
this);
105122
}
106-
107123
void CapturingThisInMemberVariableCheck::check(
108124
const MatchFinder::MatchResult &Result) {
109-
const auto *Capture = Result.Nodes.getNodeAs<LambdaCapture>("capture");
110-
const auto *Lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda");
125+
if (const auto *Lambda = Result.Nodes.getNodeAs<LambdaExpr>("lambda")) {
126+
diag(Lambda->getBeginLoc(),
127+
"'this' captured by a lambda and stored in a class member variable; "
128+
"disable implicit class copying/moving to prevent potential "
129+
"use-after-free");
130+
} else if (const auto *Bind = Result.Nodes.getNodeAs<CallExpr>("bind")) {
131+
const auto *Callee = Result.Nodes.getNodeAs<FunctionDecl>("callee");
132+
assert(Callee);
133+
diag(Bind->getBeginLoc(),
134+
"'this' captured by a '%0' call and stored in a class member "
135+
"variable; disable implicit class copying/moving to prevent potential "
136+
"use-after-free")
137+
<< Callee->getQualifiedNameAsString();
138+
}
139+
111140
const auto *Field = Result.Nodes.getNodeAs<FieldDecl>("field");
112-
diag(Lambda->getBeginLoc(),
113-
"'this' captured by a lambda and stored in a class member variable; "
114-
"disable implicit class copying/moving to prevent potential "
115-
"use-after-free")
116-
<< Capture->getLocation();
141+
assert(Field);
142+
117143
diag(Field->getLocation(),
118144
"class member of type '%0' that stores captured 'this'",
119145
DiagnosticIDs::Note)

clang-tools-extra/clang-tidy/bugprone/CapturingThisInMemberVariableCheck.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class CapturingThisInMemberVariableCheck : public ClangTidyCheck {
3737
private:
3838
///< store the function wrapper types
3939
const std::vector<StringRef> FunctionWrapperTypes;
40+
const std::vector<StringRef> BindFunctions;
4041
};
4142

4243
} // namespace clang::tidy::bugprone

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,9 @@ New checks
103103
- New :doc:`bugprone-capturing-this-in-member-variable
104104
<clang-tidy/checks/bugprone/capturing-this-in-member-variable>` check.
105105

106-
Finds lambda captures that capture the ``this`` pointer and store it as class
107-
members without handle the copy and move constructors and the assignments.
106+
Finds lambda captures and ``bind`` function calls that capture the ``this``
107+
pointer and store it as class members without handle the copy and move
108+
constructors and the assignments.
108109

109110
- New :doc:`bugprone-unintended-char-ostream-output
110111
<clang-tidy/checks/bugprone/unintended-char-ostream-output>` check.

clang-tools-extra/docs/clang-tidy/checks/bugprone/capturing-this-in-member-variable.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,10 @@ Options
4040
A semicolon-separated list of names of types. Used to specify function
4141
wrapper that can hold lambda expressions.
4242
Default is `::std::function;::std::move_only_function;::boost::function`.
43+
44+
.. option:: BindFunctions
45+
46+
A semicolon-separated list of fully qualified names of functions that can
47+
capture ``this`` pointer.
48+
Default is `::std::bind;::boost::bind;::std::bind_front;::std::bind_back;
49+
::boost::compat::bind_front;::boost::compat::bind_back`.

clang-tools-extra/test/clang-tidy/checkers/bugprone/capturing-this-in-member-variable.cpp

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %check_clang_tidy -std=c++11-or-later %s bugprone-capturing-this-in-member-variable %t -- -config="{CheckOptions: {bugprone-capturing-this-in-member-variable.FunctionWrapperTypes: '::std::function;::Fn'}}" --
1+
// RUN: %check_clang_tidy -std=c++11-or-later %s bugprone-capturing-this-in-member-variable %t -- -config="{CheckOptions: {bugprone-capturing-this-in-member-variable.FunctionWrapperTypes: '::std::function;::Fn', bugprone-capturing-this-in-member-variable.BindFunctions: '::std::bind;::Bind'}}" --
22

33
namespace std {
44

@@ -12,12 +12,22 @@ class function<R(Args...)> {
1212
template<class F> function(F &&);
1313
};
1414

15+
template <typename F, typename... Args>
16+
function<F(Args...)> bind(F&&, Args&&...) {
17+
return {};
18+
}
19+
1520
} // namespace std
1621

1722
struct Fn {
1823
template<class F> Fn(F &&);
1924
};
2025

26+
template <typename F, typename... Args>
27+
std::function<F(Args...)> Bind(F&&, Args&&...) {
28+
return {};
29+
}
30+
2131
struct BasicConstructor {
2232
BasicConstructor() : Captured([this]() { static_cast<void>(this); }) {}
2333
// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: 'this' captured by a lambda and stored in a class member variable;
@@ -208,3 +218,49 @@ struct CustomFunctionWrapper {
208218
Fn Captured;
209219
// CHECK-MESSAGES: :[[@LINE-1]]:6: note: class member of type 'Fn' that stores captured 'this'
210220
};
221+
222+
struct BindConstructor {
223+
BindConstructor() : Captured(std::bind(&BindConstructor::method, this)) {}
224+
// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: 'this' captured by a 'std::bind' call and stored in a class member variable;
225+
void method() {}
226+
std::function<void()> Captured;
227+
// CHECK-MESSAGES: :[[@LINE-1]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
228+
};
229+
230+
struct BindField1 {
231+
void method() {}
232+
std::function<void()> Captured = std::bind(&BindField1::method, this);
233+
// CHECK-MESSAGES: :[[@LINE-1]]:36: warning: 'this' captured by a 'std::bind' call and stored in a class member variable;
234+
// CHECK-MESSAGES: :[[@LINE-2]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
235+
};
236+
237+
struct BindField2 {
238+
void method() {}
239+
std::function<void()> Captured{std::bind(&BindField2::method, this)};
240+
// CHECK-MESSAGES: :[[@LINE-1]]:34: warning: 'this' captured by a 'std::bind' call and stored in a class member variable;
241+
// CHECK-MESSAGES: :[[@LINE-2]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
242+
};
243+
244+
struct BindCustom {
245+
BindCustom() : Captured(Bind(&BindCustom::method, this)) {}
246+
// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: 'this' captured by a 'Bind' call and stored in a class member variable;
247+
void method() {}
248+
std::function<void()> Captured;
249+
// CHECK-MESSAGES: :[[@LINE-1]]:25: note: class member of type 'std::function<void (void)>' that stores captured 'this'
250+
};
251+
252+
struct BindNotCapturingThis {
253+
void method(int) {}
254+
BindNotCapturingThis(int V) : Captured(std::bind(&BindNotCapturingThis::method, V)) {}
255+
std::function<void()> Captured;
256+
};
257+
258+
struct DeletedCopyMoveWithBind {
259+
DeletedCopyMoveWithBind() : Captured(std::bind(&DeletedCopyMoveWithBind::method, this)) {}
260+
DeletedCopyMoveWithBind(DeletedCopyMoveWithBind const&) = delete;
261+
DeletedCopyMoveWithBind(DeletedCopyMoveWithBind &&) = delete;
262+
DeletedCopyMoveWithBind& operator=(DeletedCopyMoveWithBind const&) = delete;
263+
DeletedCopyMoveWithBind& operator=(DeletedCopyMoveWithBind &&) = delete;
264+
void method() {}
265+
std::function<void()> Captured;
266+
};

clang/include/clang/Basic/DiagnosticFrontendKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,8 @@ def err_ast_action_on_llvm_ir : Error<
379379
"cannot apply AST actions to LLVM IR file '%0'">,
380380
DefaultFatal;
381381

382+
def err_invalid_llvm_ir : Error<"invalid LLVM IR input: %0">;
383+
382384
def err_os_unsupport_riscv_fmv : Error<
383385
"function multiversioning is currently only supported on Linux">;
384386

clang/lib/AST/ASTContext.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7011,7 +7011,7 @@ TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name,
70117011
getCanonicalTemplateArgument(subst->getArgumentPack());
70127012
return getSubstTemplateTemplateParmPack(
70137013
canonArgPack, subst->getAssociatedDecl()->getCanonicalDecl(),
7014-
subst->getFinal(), subst->getIndex());
7014+
subst->getIndex(), subst->getFinal());
70157015
}
70167016
case TemplateName::DeducedTemplate: {
70177017
assert(IgnoreDeduced == false);

clang/lib/CodeGen/CodeGenAction.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "llvm/IR/LLVMContext.h"
4040
#include "llvm/IR/LLVMRemarkStreamer.h"
4141
#include "llvm/IR/Module.h"
42+
#include "llvm/IR/Verifier.h"
4243
#include "llvm/IRReader/IRReader.h"
4344
#include "llvm/LTO/LTOBackend.h"
4445
#include "llvm/Linker/Linker.h"
@@ -1048,8 +1049,17 @@ CodeGenAction::loadModule(MemoryBufferRef MBRef) {
10481049

10491050
// Handle textual IR and bitcode file with one single module.
10501051
llvm::SMDiagnostic Err;
1051-
if (std::unique_ptr<llvm::Module> M = parseIR(MBRef, Err, *VMContext))
1052+
if (std::unique_ptr<llvm::Module> M = parseIR(MBRef, Err, *VMContext)) {
1053+
// For LLVM IR files, always verify the input and report the error in a way
1054+
// that does not ask people to report an issue for it.
1055+
std::string VerifierErr;
1056+
raw_string_ostream VerifierErrStream(VerifierErr);
1057+
if (llvm::verifyModule(*M, &VerifierErrStream)) {
1058+
CI.getDiagnostics().Report(diag::err_invalid_llvm_ir) << VerifierErr;
1059+
return {};
1060+
}
10521061
return M;
1062+
}
10531063

10541064
// If MBRef is a bitcode with multiple modules (e.g., -fsplit-lto-unit
10551065
// output), place the extra modules (actually only one, a regular LTO module)

clang/lib/Driver/ToolChains/Arch/X86.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,9 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
252252
D.Diag(diag::warn_drv_deprecated_arg) << Name << 1 << Name.drop_back(4);
253253
else if (Width == "256")
254254
D.Diag(diag::warn_drv_deprecated_custom)
255-
<< Name << "because AVX10/256 is not supported and will be removed";
255+
<< Name
256+
<< "no alternative argument provided because "
257+
"AVX10/256 is not supported and will be removed";
256258
else
257259
assert((Width == "256" || Width == "512") && "Invalid vector length.");
258260
Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
@@ -286,7 +288,9 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
286288
if (A->getOption().matches(options::OPT_mevex512) ||
287289
A->getOption().matches(options::OPT_mno_evex512))
288290
D.Diag(diag::warn_drv_deprecated_custom)
289-
<< Name << "because AVX10/256 is not supported and will be removed";
291+
<< Name
292+
<< "no alternative argument provided because "
293+
"AVX10/256 is not supported and will be removed";
290294

291295
if (A->getOption().matches(options::OPT_mapx_features_EQ) ||
292296
A->getOption().matches(options::OPT_mno_apx_features_EQ)) {

clang/lib/Sema/OpenCLBuiltins.td

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -958,13 +958,25 @@ foreach name = ["async_work_group_strided_copy"] in {
958958
def : Builtin<name, [Event, PointerType<AGenTypeN, LocalAS>, PointerType<ConstType<AGenTypeN>, GlobalAS>, Size, Size, Event]>;
959959
def : Builtin<name, [Event, PointerType<AGenTypeN, GlobalAS>, PointerType<ConstType<AGenTypeN>, LocalAS>, Size, Size, Event]>;
960960
}
961-
foreach name = ["wait_group_events"] in {
962-
def : Builtin<name, [Void, Int, PointerType<Event, GenericAS>]>;
963-
}
964961
foreach name = ["prefetch"] in {
965962
def : Builtin<name, [Void, PointerType<ConstType<AGenTypeN>, GlobalAS>, Size]>;
966963
}
967964

965+
// The wait_group_events is declared with an argument of type event_t*.
966+
// The address-space of the pointer parameter is different if the generic address space is available.
967+
multiclass BuiltinWithDefaultPointerArg<AddressSpace AS> {
968+
foreach name = ["wait_group_events"] in {
969+
def : Builtin<name, [Void, Int, PointerType<Event, AS>]>;
970+
}
971+
}
972+
973+
let Extension = FuncExtOpenCLCNamedAddressSpaceBuiltins in {
974+
defm : BuiltinWithDefaultPointerArg<PrivateAS>;
975+
}
976+
let Extension = FuncExtOpenCLCGenericAddressSpace in {
977+
defm : BuiltinWithDefaultPointerArg<GenericAS>;
978+
}
979+
968980
//--------------------------------------------------------------------
969981
// OpenCL v2.0 s6.13.11 - Atomics Functions.
970982
// Functions that use memory_order and cl_mem_fence_flags enums are not

0 commit comments

Comments
 (0)