diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index b69a805f785a..44e41864f0b3 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/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/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp index 1358d9e2a391..e1b0f49cc8dc 100644 --- a/clang/test/SemaCXX/lambda-expressions.cpp +++ b/clang/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? + } (); + } +}