forked from OSchip/llvm-project
[Sema] Mark GNU compound literal array init as an rvalue.
Basically the same issue as string init, except it didn't really have any visible consequences before I removed the implicit lvalue-to-rvalue conversion from CodeGen. While I'm here, a couple minor drive-by cleanups: IgnoreParens never returns a ConstantExpr, and there was a potential crash with string init involving a ChooseExpr. The analyzer test change maybe indicates we could simplify the analyzer code a little with this fix? Apparently a hack was added to support lvalues in initializers in r315750, but I'm not really familiar with the relevant code. Fixes regression reported in the kernel build at https://bugs.llvm.org/show_bug.cgi?id=40430#c6 . Differential Revision: https://reviews.llvm.org/D58069 llvm-svn: 353762
This commit is contained in:
parent
9d5a089bf5
commit
88fccbdea7
|
@ -145,16 +145,42 @@ static void updateStringLiteralType(Expr *E, QualType Ty) {
|
|||
while (true) {
|
||||
E->setType(Ty);
|
||||
E->setValueKind(VK_RValue);
|
||||
if (isa<StringLiteral>(E) || isa<ObjCEncodeExpr>(E))
|
||||
if (isa<StringLiteral>(E) || isa<ObjCEncodeExpr>(E)) {
|
||||
break;
|
||||
else if (ParenExpr *PE = dyn_cast<ParenExpr>(E))
|
||||
} else if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
|
||||
E = PE->getSubExpr();
|
||||
else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E))
|
||||
} else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
|
||||
assert(UO->getOpcode() == UO_Extension);
|
||||
E = UO->getSubExpr();
|
||||
else if (GenericSelectionExpr *GSE = dyn_cast<GenericSelectionExpr>(E))
|
||||
} else if (GenericSelectionExpr *GSE = dyn_cast<GenericSelectionExpr>(E)) {
|
||||
E = GSE->getResultExpr();
|
||||
else
|
||||
} else if (ChooseExpr *CE = dyn_cast<ChooseExpr>(E)) {
|
||||
E = CE->getChosenSubExpr();
|
||||
} else {
|
||||
llvm_unreachable("unexpected expr in string literal init");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Fix a compound literal initializing an array so it's correctly marked
|
||||
/// as an rvalue.
|
||||
static void updateGNUCompoundLiteralRValue(Expr *E) {
|
||||
while (true) {
|
||||
E->setValueKind(VK_RValue);
|
||||
if (isa<CompoundLiteralExpr>(E)) {
|
||||
break;
|
||||
} else if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
|
||||
E = PE->getSubExpr();
|
||||
} else if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
|
||||
assert(UO->getOpcode() == UO_Extension);
|
||||
E = UO->getSubExpr();
|
||||
} else if (GenericSelectionExpr *GSE = dyn_cast<GenericSelectionExpr>(E)) {
|
||||
E = GSE->getResultExpr();
|
||||
} else if (ChooseExpr *CE = dyn_cast<ChooseExpr>(E)) {
|
||||
E = CE->getChosenSubExpr();
|
||||
} else {
|
||||
llvm_unreachable("unexpected expr in array compound literal init");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5542,8 +5568,7 @@ void InitializationSequence::InitializeFrom(Sema &S,
|
|||
// array from a compound literal that creates an array of the same
|
||||
// type, so long as the initializer has no side effects.
|
||||
if (!S.getLangOpts().CPlusPlus && Initializer &&
|
||||
(isa<ConstantExpr>(Initializer->IgnoreParens()) ||
|
||||
isa<CompoundLiteralExpr>(Initializer->IgnoreParens())) &&
|
||||
isa<CompoundLiteralExpr>(Initializer->IgnoreParens()) &&
|
||||
Initializer->getType()->isArrayType()) {
|
||||
const ArrayType *SourceAT
|
||||
= Context.getAsArrayType(Initializer->getType());
|
||||
|
@ -7956,6 +7981,7 @@ ExprResult InitializationSequence::Perform(Sema &S,
|
|||
S.Diag(Kind.getLocation(), diag::ext_array_init_copy)
|
||||
<< Step->Type << CurInit.get()->getType()
|
||||
<< CurInit.get()->getSourceRange();
|
||||
updateGNUCompoundLiteralRValue(CurInit.get());
|
||||
LLVM_FALLTHROUGH;
|
||||
case SK_ArrayInit:
|
||||
// If the destination type is an incomplete array type, update the
|
||||
|
|
|
@ -4,6 +4,5 @@ void clang_analyzer_eval(int);
|
|||
// pr28449: Used to crash.
|
||||
void foo(void) {
|
||||
static const unsigned short array[] = (const unsigned short[]){0x0F00};
|
||||
// FIXME: Should be true.
|
||||
clang_analyzer_eval(array[0] == 0x0F00); // expected-warning{{UNKNOWN}}
|
||||
clang_analyzer_eval(array[0] == 0x0F00); // expected-warning{{TRUE}}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,11 @@ _Complex double * x = &(_Complex double){1.0f};
|
|||
typedef int v4i32 __attribute((vector_size(16)));
|
||||
v4i32 *y = &(v4i32){1,2,3,4};
|
||||
|
||||
// Check generated code for GNU constant array init from compound literal,
|
||||
// for a global variable.
|
||||
// CHECK: @compound_array = global [8 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8]
|
||||
int compound_array[] = __extension__(__builtin_choose_expr(0, 0, _Generic(1, int: (int[]){1, 2, 3, 4, 5, 6, 7, 8})));
|
||||
|
||||
void xxx() {
|
||||
int* a = &(int){1};
|
||||
struct s {int a, b, c;} * b = &(struct s) {1, 2, 3};
|
||||
|
@ -82,3 +87,13 @@ int compareMyCLH() {
|
|||
const void *b = MyCLH;
|
||||
return a == b;
|
||||
}
|
||||
|
||||
// Check generated code for GNU constant array init from compound literal,
|
||||
// for a local variable.
|
||||
// CHECK-LABEL: define i32 @compound_array_fn()
|
||||
// CHECK: [[COMPOUND_ARRAY:%.*]] = alloca [8 x i32]
|
||||
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}, i64 32, i1 false)
|
||||
int compound_array_fn() {
|
||||
int compound_array[] = (int[]){1,2,3,4,5,6,7,8};
|
||||
return compound_array[0];
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue