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:
Eli Friedman 2011-12-21 00:43:02 +00:00
parent c5af54ec89
commit 13ec75ba42
2 changed files with 24 additions and 10 deletions

View File

@ -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;
} }

View File

@ -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