Skip to content

Commit 1c3b617

Browse files
ahatanakazygoloid
andauthored
Use builtin recognition to detect std::move / std::forward. (#4668)
Replaces some prior ad-hoc detection strategies and generally cleans up a little. No functional change intended. (cherry picked from commit f6a5ab6) Co-authored-by: Richard Smith <[email protected]>
1 parent c313aed commit 1c3b617

File tree

7 files changed

+34
-36
lines changed

7 files changed

+34
-36
lines changed

clang/include/clang/AST/Expr.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3128,11 +3128,7 @@ class CallExpr : public Expr {
31283128
setDependence(getDependence() | ExprDependence::TypeValueInstantiation);
31293129
}
31303130

3131-
bool isCallToStdMove() const {
3132-
const FunctionDecl *FD = getDirectCallee();
3133-
return getNumArgs() == 1 && FD && FD->isInStdNamespace() &&
3134-
FD->getIdentifier() && FD->getIdentifier()->isStr("move");
3135-
}
3131+
bool isCallToStdMove() const;
31363132

31373133
static bool classof(const Stmt *T) {
31383134
return T->getStmtClass() >= firstCallExprConstant &&

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4924,7 +4924,7 @@ def ext_adl_only_template_id : ExtWarn<
49244924
"with explicit template arguments is a C++20 extension">, InGroup<CXX20>;
49254925

49264926
def warn_unqualified_call_to_std_cast_function : Warning<
4927-
"unqualified call to %0">, InGroup<DiagGroup<"unqualified-std-cast-call">>;
4927+
"unqualified call to '%0'">, InGroup<DiagGroup<"unqualified-std-cast-call">>;
49284928

49294929
// C++ Template Argument Lists
49304930
def err_template_missing_args : Error<

clang/lib/AST/Expr.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,8 +1478,7 @@ Decl *Expr::getReferencedDeclOfCallee() {
14781478

14791479
/// If this is a call to a builtin, return the builtin ID. If not, return 0.
14801480
unsigned CallExpr::getBuiltinCallee() const {
1481-
auto *FDecl =
1482-
dyn_cast_or_null<FunctionDecl>(getCallee()->getReferencedDeclOfCallee());
1481+
auto *FDecl = getDirectCallee();
14831482
return FDecl ? FDecl->getBuiltinID() : 0;
14841483
}
14851484

@@ -3337,9 +3336,9 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
33373336
}
33383337

33393338
bool CallExpr::isBuiltinAssumeFalse(const ASTContext &Ctx) const {
3340-
const FunctionDecl* FD = getDirectCallee();
3341-
if (!FD || (FD->getBuiltinID() != Builtin::BI__assume &&
3342-
FD->getBuiltinID() != Builtin::BI__builtin_assume))
3339+
unsigned BuiltinID = getBuiltinCallee();
3340+
if (BuiltinID != Builtin::BI__assume &&
3341+
BuiltinID != Builtin::BI__builtin_assume)
33433342
return false;
33443343

33453344
const Expr* Arg = getArg(0);
@@ -3348,6 +3347,10 @@ bool CallExpr::isBuiltinAssumeFalse(const ASTContext &Ctx) const {
33483347
Arg->EvaluateAsBooleanCondition(ArgVal, Ctx) && !ArgVal;
33493348
}
33503349

3350+
bool CallExpr::isCallToStdMove() const {
3351+
return getBuiltinCallee() == Builtin::BImove;
3352+
}
3353+
33513354
namespace {
33523355
/// Look for any side effects within a Stmt.
33533356
class SideEffectFinder : public ConstEvaluatedExprVisitor<SideEffectFinder> {

clang/lib/Sema/SemaExpr.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6570,18 +6570,17 @@ static void DiagnosedUnqualifiedCallsToStdFunctions(Sema &S, CallExpr *Call) {
65706570
if (DRE->getQualifier())
65716571
return;
65726572

6573-
NamedDecl *D = dyn_cast_or_null<NamedDecl>(Call->getCalleeDecl());
6574-
if (!D || !D->isInStdNamespace())
6573+
const FunctionDecl *FD = Call->getDirectCallee();
6574+
if (!FD)
65756575
return;
65766576

65776577
// Only warn for some functions deemed more frequent or problematic.
6578-
static constexpr llvm::StringRef SpecialFunctions[] = {"move", "forward"};
6579-
auto it = llvm::find(SpecialFunctions, D->getName());
6580-
if (it == std::end(SpecialFunctions))
6578+
unsigned BuiltinID = FD->getBuiltinID();
6579+
if (BuiltinID != Builtin::BImove && BuiltinID != Builtin::BIforward)
65816580
return;
65826581

65836582
S.Diag(DRE->getLocation(), diag::warn_unqualified_call_to_std_cast_function)
6584-
<< D->getQualifiedNameAsString()
6583+
<< FD->getQualifiedNameAsString()
65856584
<< FixItHint::CreateInsertion(DRE->getLocation(), "std::");
65866585
}
65876586

clang/test/SemaCXX/unqualified-std-call-fixits.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ using namespace std;
1616

1717
void f() {
1818
int i = 0;
19-
(void)move(i); // expected-warning {{unqualified call to std::move}}
19+
(void)move(i); // expected-warning {{unqualified call to 'std::move}}
2020
// CHECK: {{^}} (void)std::move
21-
(void)forward(i); // expected-warning {{unqualified call to std::forward}}
21+
(void)forward(i); // expected-warning {{unqualified call to 'std::forward}}
2222
// CHECK: {{^}} (void)std::forward
2323
}

clang/test/SemaCXX/unqualified-std-call.cpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,23 @@ using namespace std;
2525
void f() {
2626
int i = 0;
2727
std::move(i);
28-
move(i); // expected-warning{{unqualified call to std::move}}
29-
(move)(i); // expected-warning{{unqualified call to std::move}}
28+
move(i); // expected-warning{{unqualified call to 'std::move'}}
29+
(move)(i); // expected-warning{{unqualified call to 'std::move'}}
3030
std::dummy(1);
3131
dummy(1);
3232
std::move(1, 2);
3333
move(1, 2);
34-
forward<int>(i); // expected-warning{{unqualified call to std::forward}}
34+
forward<int>(i); // expected-warning{{unqualified call to 'std::forward'}}
3535
std::forward<int>(i);
3636
}
3737

3838
template <typename T>
3939
void g(T &&foo) {
4040
std::move(foo);
41-
move(foo); // expected-warning{{unqualified call to std::move}}
41+
move(foo); // expected-warning{{unqualified call to 'std::move}}
4242

4343
std::forward<decltype(foo)>(foo);
44-
forward<decltype(foo)>(foo); // expected-warning{{unqualified call to std::forward}}
44+
forward<decltype(foo)>(foo); // expected-warning{{unqualified call to 'std::forward}}
4545
move(1, 2);
4646
dummy(foo);
4747
}
@@ -59,16 +59,16 @@ using std::move;
5959

6060
void f() {
6161
int i = 0;
62-
move(i); // expected-warning{{unqualified call to std::move}}
62+
move(i); // expected-warning{{unqualified call to 'std::move}}
6363
move(1, 2);
64-
forward<int>(i); // expected-warning{{unqualified call to std::forward}}
64+
forward<int>(i); // expected-warning{{unqualified call to 'std::forward}}
6565
}
6666

6767
template <typename T>
6868
void g(T &&foo) {
69-
move(foo); // expected-warning{{unqualified call to std::move}}
70-
forward<decltype(foo)>(foo); // expected-warning{{unqualified call to std::forward}}
71-
(forward<decltype(foo)>)(foo); // expected-warning{{unqualified call to std::forward}}
69+
move(foo); // expected-warning{{unqualified call to 'std::move}}
70+
forward<decltype(foo)>(foo); // expected-warning{{unqualified call to 'std::forward}}
71+
(forward<decltype(foo)>)(foo); // expected-warning{{unqualified call to 'std::forward}}
7272
move(1, 2);
7373
}
7474

@@ -90,7 +90,7 @@ void f() {
9090

9191
namespace adl {
9292
void f() {
93-
move(std::foo{}); // expected-warning{{unqualified call to std::move}}
93+
move(std::foo{}); // expected-warning{{unqualified call to 'std::move}}
9494
}
9595

9696
} // namespace adl
@@ -99,8 +99,8 @@ namespace std {
9999

100100
void f() {
101101
int i = 0;
102-
move(i); // expected-warning{{unqualified call to std::move}}
103-
forward<int>(i); // expected-warning{{unqualified call to std::forward}}
102+
move(i); // expected-warning{{unqualified call to 'std::move}}
103+
forward<int>(i); // expected-warning{{unqualified call to 'std::forward}}
104104
}
105105

106106
} // namespace std
@@ -110,9 +110,9 @@ namespace alias = std;
110110
using namespace alias;
111111
void f() {
112112
int i = 0;
113-
move(i); // expected-warning{{unqualified call to std::move}}
113+
move(i); // expected-warning{{unqualified call to 'std::move}}
114114
move(1, 2);
115-
forward<int>(i); // expected-warning{{unqualified call to std::forward}}
115+
forward<int>(i); // expected-warning{{unqualified call to 'std::forward}}
116116
}
117117

118118
} // namespace test_alias

clang/test/SemaCXX/warn-self-move.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ void int_test() {
1818

1919
using std::move;
2020
x = move(x); // expected-warning{{explicitly moving}} \
21-
expected-warning {{unqualified call to std::move}}
21+
expected-warning {{unqualified call to 'std::move}}
2222
}
2323

2424
int global;
@@ -28,7 +28,7 @@ void global_int_test() {
2828

2929
using std::move;
3030
global = move(global); // expected-warning{{explicitly moving}} \
31-
expected-warning {{unqualified call to std::move}}
31+
expected-warning {{unqualified call to 'std::move}}
3232
}
3333

3434
class field_test {

0 commit comments

Comments
 (0)