From: Richard Smith Date: Fri, 24 Feb 2012 22:12:32 +0000 (+0000) Subject: When checking whether a reference to a variable is an ICE, look at the type of X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=359c89df5479810c9d4784fc0b6ab592eb136777;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151399 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index b69a805f78..44e41864f0 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -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(cast(E)->getDecl())) return NoDiag(); - if (Ctx.getLangOptions().CPlusPlus && IsConstNonVolatile(E->getType())) { - const NamedDecl *D = cast(E)->getDecl(); - + const ValueDecl *D = dyn_cast(cast(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(E); switch (Exp->getOpcode()) { diff --git a/test/SemaCXX/lambda-expressions.cpp b/test/SemaCXX/lambda-expressions.cpp index 1358d9e2a3..e1b0f49cc8 100644 --- a/test/SemaCXX/lambda-expressions.cpp +++ b/test/SemaCXX/lambda-expressions.cpp @@ -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? + } (); + } +}