diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -11,8 +11,9 @@ // Constant expression diagnostics. These (and their users) belong in Sema. def note_expr_divide_by_zero : Note<"division by zero">; def note_constexpr_invalid_cast : Note< - "%select{reinterpret_cast|dynamic_cast|cast that performs the conversions of" - " a reinterpret_cast|cast from %1}0 is not allowed in a constant expression" + "%select{reinterpret_cast|dynamic_cast|%select{this conversion|cast that" + " performs the conversions of a reinterpret_cast}1|cast from %1}0" + " is not allowed in a constant expression" "%select{| in C++ standards before C++20||}0">; def note_constexpr_invalid_downcast : Note< "cannot cast object of dynamic type %0 to type %1">; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -8179,7 +8179,8 @@ return LValueExprEvaluatorBaseTy::VisitCastExpr(E); case CK_LValueBitCast: - this->CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; + this->CCEDiag(E, diag::note_constexpr_invalid_cast) + << 2 << Info.Ctx.getLangOpts().CPlusPlus; if (!Visit(E->getSubExpr())) return false; Result.Designator.setInvalid(); @@ -8890,9 +8891,10 @@ Result.Designator.setInvalid(); if (SubExpr->getType()->isVoidPointerType()) CCEDiag(E, diag::note_constexpr_invalid_cast) - << 3 << SubExpr->getType(); + << 3 << SubExpr->getType(); else - CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; + CCEDiag(E, diag::note_constexpr_invalid_cast) + << 2 << Info.Ctx.getLangOpts().CPlusPlus; } } if (E->getCastKind() == CK_AddressSpaceConversion && Result.IsNullPtr) @@ -8929,7 +8931,8 @@ return ZeroInitialization(E); case CK_IntegralToPointer: { - CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; + CCEDiag(E, diag::note_constexpr_invalid_cast) + << 2 << Info.Ctx.getLangOpts().CPlusPlus; APValue Value; if (!EvaluateIntegerOrLValue(SubExpr, Value, Info)) @@ -13566,7 +13569,8 @@ } case CK_PointerToIntegral: { - CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; + CCEDiag(E, diag::note_constexpr_invalid_cast) + << 2 << Info.Ctx.getLangOpts().CPlusPlus; LValue LV; if (!EvaluatePointer(SubExpr, LV, Info)) diff --git a/clang/test/Sema/cast.c b/clang/test/Sema/cast.c --- a/clang/test/Sema/cast.c +++ b/clang/test/Sema/cast.c @@ -1,4 +1,8 @@ -// RUN: %clang_cc1 -fsyntax-only -triple x86_64-unknown-unknown %s -verify +// RUN: %clang_cc1 -fsyntax-only -triple x86_64-unknown-unknown %s -verify -Wvla + +int array[(long)(char *)0]; // expected-warning {{variable length array used}} \ + // expected-warning {{variable length array folded to constant array as an extension}} \ + // expected-note {{this conversion is not allowed in a constant expression}} typedef struct { unsigned long bits[(((1) + (64) - 1) / (64))]; } cpumask_t; cpumask_t x; diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -2,6 +2,7 @@ // RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx11_20,cxx20_2b -triple x86_64-linux -Wno-string-plus-int -Wno-pointer-arith -Wno-zero-length-array -Wno-c99-designator -fcxx-exceptions -pedantic %s -Wno-comment -Wno-tautological-pointer-compare -Wno-bool-conversion // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify=expected,cxx11_20,cxx11 -triple x86_64-linux -Wno-string-plus-int -Wno-pointer-arith -Wno-zero-length-array -Wno-c99-designator -fcxx-exceptions -pedantic %s -Wno-comment -Wno-tautological-pointer-compare -Wno-bool-conversion + namespace StaticAssertFoldTest { int x; @@ -11,6 +12,10 @@ } +int array[(long)(char *)0]; // expected-warning {{variable length arrays are a C99 feature}} \ + // expected-warning {{variable length array folded to constant array as an extension}} \ + // expected-note {{cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression}} + typedef decltype(sizeof(char)) size_t; template constexpr T id(const T &t) { return t; } @@ -2449,6 +2454,6 @@ constexpr EMaxInt x19 = static_cast(__INT_MAX__-1); constexpr EMaxInt x20 = static_cast((long)__INT_MAX__+1); // expected-error {{must be initialized by a constant expression}} - // expected-note@-1 {{integer value 2147483648 is outside the valid range of values [-2147483648, 2147483647] for this enumeration type}} + // expected-note@-1 {{integer value 2147483648 is outside the valid range of values [-2147483648, 2147483647] for this enumeration type}} } }