[clang] disable implicit moves when not in CPlusPLus

See PR51842.

This fixes an assert firing in the static analyzer, triggered by implicit moves
in blocks in C mode:

This also simplifies the AST a little bit when compiling non C++ code,
as the xvalue implicit casts are not inserted.

We keep and test that the nrvo flag is still being set on the VarDecls,
as that is still a bit beneficial while not really making anything
more complicated.

Signed-off-by: Matheus Izvekov <mizvekov@gmail.com>

Reviewed By: NoQ

Differential Revision: https://reviews.llvm.org/D109654
This commit is contained in:
Matheus Izvekov
2021-09-12 01:11:02 +02:00
parent f287405419
commit 2d6829bbbe
3 changed files with 45 additions and 1 deletions

View File

@@ -3481,7 +3481,8 @@ VerifyInitializationSequenceCXX98(const Sema &S,
ExprResult Sema::PerformMoveOrCopyInitialization(
const InitializedEntity &Entity, const NamedReturnInfo &NRInfo, Expr *Value,
bool SupressSimplerImplicitMoves) {
if ((!getLangOpts().CPlusPlus2b || SupressSimplerImplicitMoves) &&
if (getLangOpts().CPlusPlus &&
(!getLangOpts().CPlusPlus2b || SupressSimplerImplicitMoves) &&
NRInfo.isMoveEligible()) {
ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, Value->getType(),
CK_NoOp, Value, VK_XValue, FPOptionsOverride());

29
clang/test/AST/nrvo.c Normal file
View File

@@ -0,0 +1,29 @@
// RUN: %clang_cc1 -ast-dump -fblocks %s | FileCheck -strict-whitespace %s
struct A {};
struct A f1() {
// CHECK: FunctionDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:1, line:{{[^:]*}}:1> line:[[@LINE-1]]:10 f1 'struct A ()'
// CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:15, line:{{[^:]*}}:1>
struct A a;
// CHECK-NEXT: DeclStmt 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:13>
// CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:3, col:12> col:12 used a 'struct A':'struct A' nrvo
return a;
// CHECK-NEXT: ReturnStmt 0x{{[^ ]*}} <line:[[@LINE-1]]:3, col:10>
// CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} <col:10> 'struct A':'struct A' <LValueToRValue>
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:10> 'struct A':'struct A' lvalue Var 0x{{[^ ]*}} 'a' 'struct A':'struct A'
}
void f2() {
(void)^{
// CHECK: BlockDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:9, line:{{[^:]*}}:3> line:[[@LINE-1]]:9
// CHECK-NEXT: CompoundStmt 0x{{[^ ]*}} <col:10, line:{{[^:]*}}:3>
struct A a;
// CHECK-NEXT: DeclStmt 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:15>
// CHECK-NEXT: VarDecl 0x{{[^ ]*}} <col:5, col:14> col:14 used a 'struct A':'struct A' nrvo
return a;
// CHECK-NEXT: ReturnStmt 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:12>
// CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} <col:12> 'struct A':'struct A' <LValueToRValue>
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:12> 'struct A':'struct A' lvalue Var 0x{{[^ ]*}} 'a' 'struct A':'struct A'
}();
}

View File

@@ -0,0 +1,14 @@
// RUN: %clang_analyze_cc1 -w -analyzer-checker=core -fblocks -verify %s
// expected-no-diagnostics
typedef struct {
int x;
} S;
void foo() {
^{
S s;
return s; // no-crash
};
}