efriedma updated this revision to Diff 467601. efriedma added a comment. Add dedicated error message.
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D134928/new/ https://reviews.llvm.org/D134928 Files: clang/docs/ReleaseNotes.rst clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaTemplate.cpp clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp
Index: clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp =================================================================== --- clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp +++ clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp @@ -176,7 +176,7 @@ // -- a pointer to member expressed as described in 5.3.1. namespace bad_args { - template <int* N> struct X0 { }; // precxx17-note 2{{template parameter is declared here}} + template <int* N> struct X0 { }; // precxx17-note 4{{template parameter is declared here}} int i = 42; X0<&i + 2> x0a; // precxx17-error{{non-type template argument does not refer to any declaration}} \ cxx17-error {{non-type template argument is not a constant expression}} \ @@ -194,6 +194,13 @@ // cxx17-error@-5 {{non-type template argument is not a constant expression}} // expected-note@-6 {{read of non-constexpr variable 'iptr' is not allowed in a constant expression}} #endif + X0<(int*)1> x0c; + // precxx17-error@-1 {{non-type template argument '(int *)1' is invalid}} + // cxx17-error@-2 {{non-type template argument is not a constant expression}} + // cxx17-note@-3 {{reinterpret_cast}} + X0<__builtin_constant_p(0) ? (int*)1 : (int*)1> x0d; + // precxx17-error@-1 {{non-type template argument '(int *)1' is invalid}} + // cxx17-error@-2 {{non-type template argument refers to subobject '(int *)1'}} } #endif // CPP11ONLY Index: clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp =================================================================== --- clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp +++ clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp @@ -4,7 +4,7 @@ typedef decltype(nullptr) nullptr_t; } -template<int *ip> struct IP { // expected-note 5 {{template parameter is declared here}} +template<int *ip> struct IP { // expected-note 6 {{template parameter is declared here}} IP<ip> *ip2; }; @@ -28,6 +28,7 @@ // expected-note{{read of non-constexpr variable 'nonconst_np' is not allowed in a constant expression}} IP<(float*)0> ip6; // expected-error{{null non-type template argument of type 'float *' does not match template parameter of type 'int *'}} IP<&tl> ip7; // expected-error{{non-type template argument of type 'int *' is not a constant expression}} +IP<(int*)1> ip8; // expected-error {{non-type template argument '(int *)1' is invalid}} IR<tl> ir1; // expected-error{{non-type template argument refers to thread-local object}} Index: clang/lib/Sema/SemaTemplate.cpp =================================================================== --- clang/lib/Sema/SemaTemplate.cpp +++ clang/lib/Sema/SemaTemplate.cpp @@ -6514,7 +6514,7 @@ // - a constant expression that evaluates to a null pointer value (4.10); or // - a constant expression that evaluates to a null member pointer value // (4.11); or - if ((EvalResult.Val.isLValue() && !EvalResult.Val.getLValueBase()) || + if ((EvalResult.Val.isLValue() && EvalResult.Val.isNullPointer()) || (EvalResult.Val.isMemberPointer() && !EvalResult.Val.getMemberPointerDecl())) { // If our expression has an appropriate type, we've succeeded. @@ -6532,6 +6532,16 @@ return NPV_NullPointer; } + if (EvalResult.Val.isLValue() && !EvalResult.Val.getLValueBase()) { + // We found a pointer that isn't null, but doesn't refer to an object. + // We could just return NPV_NotNullPointer, but we can print a better + // message with the information we have here. + S.Diag(Arg->getExprLoc(), diag::err_template_arg_invalid) + << EvalResult.Val.getAsString(S.Context, ParamType); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return NPV_Error; + } + // If we don't have a null pointer value, but we do have a NULL pointer // constant, suggest a cast to the appropriate type. if (Arg->isNullPointerConstant(S.Context, Expr::NPC_NeverValueDependent)) { Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5027,6 +5027,8 @@ def err_template_arg_member_ptr_base_derived_not_supported : Error< "sorry, non-type template argument of pointer-to-member type %1 that refers " "to member %q0 of a different class is not supported yet">; +def err_template_arg_invalid : Error< + "non-type template argument '%0' is invalid">; def ext_template_arg_extra_parens : ExtWarn< "address non-type template argument cannot be surrounded by parentheses">; def warn_cxx98_compat_template_arg_extra_parens : Warning< Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -248,6 +248,9 @@ not satisfied in the event of an instantiation failures in a requires expression's parameter list. We previously handled this correctly in a constraint evaluation context, but not in a requires clause evaluated as a boolean. +- Reject non-type template arguments formed by casting a non-zero integer + to a pointer in pre-C++17 modes, instead of treating them as null + pointers. Improvements to Clang's diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits