forked from OSchip/llvm-project
Fix a case where Expr::isConstantInitializer would return true for an expression we can't support. In a slightly amusing twist, the case in question was already in the clang regression tests marked as a valid construct. <rdar://problem/10020074>
llvm-svn: 147026
This commit is contained in:
parent
c5af54ec89
commit
13ec75ba42
|
@ -2550,17 +2550,30 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const {
|
||||||
if (getType()->isVectorType() && CE->getCastKind() == CK_BitCast)
|
if (getType()->isVectorType() && CE->getCastKind() == CK_BitCast)
|
||||||
return CE->getSubExpr()->isConstantInitializer(Ctx, false);
|
return CE->getSubExpr()->isConstantInitializer(Ctx, false);
|
||||||
|
|
||||||
// Handle casts with a destination that's a struct or union; this
|
// Handle misc casts we want to ignore.
|
||||||
// deals with both the gcc no-op struct cast extension and the
|
// FIXME: Is it really safe to ignore all these?
|
||||||
// cast-to-union extension.
|
if (CE->getCastKind() == CK_NoOp ||
|
||||||
if (getType()->isRecordType())
|
CE->getCastKind() == CK_LValueToRValue ||
|
||||||
|
CE->getCastKind() == CK_ToUnion ||
|
||||||
|
CE->getCastKind() == CK_ConstructorConversion)
|
||||||
return CE->getSubExpr()->isConstantInitializer(Ctx, false);
|
return CE->getSubExpr()->isConstantInitializer(Ctx, false);
|
||||||
|
|
||||||
// Integer->integer casts can be handled here, which is important for
|
// Handle things like (int)(&&x-&&y). It's a bit nasty, but we support it.
|
||||||
// things like (int)(&&x-&&y). Scary but true.
|
if (CE->getCastKind() == CK_IntegralCast) {
|
||||||
if (getType()->isIntegerType() &&
|
const Expr *E = CE->getSubExpr()->IgnoreParenNoopCasts(Ctx);
|
||||||
CE->getSubExpr()->getType()->isIntegerType())
|
while (const CastExpr *InnerCE = dyn_cast<CastExpr>(E)) {
|
||||||
return CE->getSubExpr()->isConstantInitializer(Ctx, false);
|
if (InnerCE->getCastKind() != CK_IntegralCast)
|
||||||
|
break;
|
||||||
|
E = InnerCE->getSubExpr()->IgnoreParenNoopCasts(Ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
|
||||||
|
if (BO->getOpcode() == BO_Sub &&
|
||||||
|
isa<AddrLabelExpr>(BO->getLHS()->IgnoreParenNoopCasts(Ctx)) &&
|
||||||
|
isa<AddrLabelExpr>(BO->getRHS()->IgnoreParenNoopCasts(Ctx)))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,5 +19,6 @@ struct foo {
|
||||||
};
|
};
|
||||||
|
|
||||||
union bar u[1];
|
union bar u[1];
|
||||||
struct foo x = {(intptr_t) u}; // no-error
|
struct foo x = {(intptr_t) u}; // expected-error {{initializer element is not a compile-time constant}}
|
||||||
struct foo y = {(char) u}; // expected-error {{initializer element is not a compile-time constant}}
|
struct foo y = {(char) u}; // expected-error {{initializer element is not a compile-time constant}}
|
||||||
|
intptr_t z = (intptr_t) u; // no-error
|
||||||
|
|
Loading…
Reference in New Issue