When checking whether a reference to a variable is an ICE, look at the type of

the declaration, not at the type of the DeclRefExpr, since within a lambda the
DeclRefExpr can be more const than the declaration is.

llvm-svn: 151399
This commit is contained in:
Richard Smith 2012-02-24 22:12:32 +00:00
parent 9fceb90175
commit 6365c9138e
2 changed files with 32 additions and 4 deletions

View File

@ -6379,12 +6379,12 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
return CheckEvalInICE(E, Ctx);
return ICEDiag(2, E->getLocStart());
}
case Expr::DeclRefExprClass:
case Expr::DeclRefExprClass: {
if (isa<EnumConstantDecl>(cast<DeclRefExpr>(E)->getDecl()))
return NoDiag();
if (Ctx.getLangOptions().CPlusPlus && IsConstNonVolatile(E->getType())) {
const NamedDecl *D = cast<DeclRefExpr>(E)->getDecl();
const ValueDecl *D = dyn_cast<ValueDecl>(cast<DeclRefExpr>(E)->getDecl());
if (Ctx.getLangOptions().CPlusPlus &&
D && IsConstNonVolatile(D->getType())) {
// Parameter variables are never constants. Without this check,
// getAnyInitializer() can find a default argument, which leads
// to chaos.
@ -6408,6 +6408,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
}
}
return ICEDiag(2, E->getLocStart());
}
case Expr::UnaryOperatorClass: {
const UnaryOperator *Exp = cast<UnaryOperator>(E);
switch (Exp->getOpcode()) {

View File

@ -101,3 +101,30 @@ namespace PR12031 {
f(v, [](){});
}
}
namespace NullPtr {
int &f(int *p);
char &f(...);
void g() {
int n = 0;
[=] {
char &k = f(n); // not a null pointer constant
} ();
const int m = 0;
[=] {
int &k = f(m); // a null pointer constant
} ();
// FIXME: At least the second of these cases should probably not be
// considered to be a null pointer constant.
[=] () -> bool {
int &k = f(m); // a null pointer constant?
return &m == 0; // no, captured!
} ();
[m] {
int &k = f(m); // a null pointer constant?
} ();
}
}