Skip to content

Commit 795f679

Browse files
committed
[Sema] Don't treat a non-null template argument as if it were null.
The way this code checks whether a pointer is null is wrong for other reasons; it doesn't actually check whether a null pointer constant is a "constant" in the C++ standard sense. But this fix at least makes sure we don't treat a non-null pointer as if it were null. Fixes llvm#57883 Differential Revision: https://reviews.llvm.org/D134928
1 parent e5d9ab0 commit 795f679

File tree

5 files changed

+26
-3
lines changed

5 files changed

+26
-3
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,9 @@ Bug Fixes
252252
`Issue 47177 <https://github.com/llvm/llvm-project/issues/47177>`_
253253
`Issue 47179 <https://github.com/llvm/llvm-project/issues/47179>`_
254254
- Fix a crash upon stray coloncolon token in C2x mode.
255+
- Reject non-type template arguments formed by casting a non-zero integer
256+
to a pointer in pre-C++17 modes, instead of treating them as null
257+
pointers.
255258

256259
Improvements to Clang's diagnostics
257260
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5027,6 +5027,8 @@ def err_template_arg_not_pointer_to_member_form : Error<
50275027
def err_template_arg_member_ptr_base_derived_not_supported : Error<
50285028
"sorry, non-type template argument of pointer-to-member type %1 that refers "
50295029
"to member %q0 of a different class is not supported yet">;
5030+
def err_template_arg_invalid : Error<
5031+
"non-type template argument '%0' is invalid">;
50305032
def ext_template_arg_extra_parens : ExtWarn<
50315033
"address non-type template argument cannot be surrounded by parentheses">;
50325034
def warn_cxx98_compat_template_arg_extra_parens : Warning<

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6506,7 +6506,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
65066506
// - a constant expression that evaluates to a null pointer value (4.10); or
65076507
// - a constant expression that evaluates to a null member pointer value
65086508
// (4.11); or
6509-
if ((EvalResult.Val.isLValue() && !EvalResult.Val.getLValueBase()) ||
6509+
if ((EvalResult.Val.isLValue() && EvalResult.Val.isNullPointer()) ||
65106510
(EvalResult.Val.isMemberPointer() &&
65116511
!EvalResult.Val.getMemberPointerDecl())) {
65126512
// If our expression has an appropriate type, we've succeeded.
@@ -6524,6 +6524,16 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param,
65246524
return NPV_NullPointer;
65256525
}
65266526

6527+
if (EvalResult.Val.isLValue() && !EvalResult.Val.getLValueBase()) {
6528+
// We found a pointer that isn't null, but doesn't refer to an object.
6529+
// We could just return NPV_NotNullPointer, but we can print a better
6530+
// message with the information we have here.
6531+
S.Diag(Arg->getExprLoc(), diag::err_template_arg_invalid)
6532+
<< EvalResult.Val.getAsString(S.Context, ParamType);
6533+
S.Diag(Param->getLocation(), diag::note_template_param_here);
6534+
return NPV_Error;
6535+
}
6536+
65276537
// If we don't have a null pointer value, but we do have a NULL pointer
65286538
// constant, suggest a cast to the appropriate type.
65296539
if (Arg->isNullPointerConstant(S.Context, Expr::NPC_NeverValueDependent)) {

clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace std {
44
typedef decltype(nullptr) nullptr_t;
55
}
66

7-
template<int *ip> struct IP { // expected-note 5 {{template parameter is declared here}}
7+
template<int *ip> struct IP { // expected-note 6 {{template parameter is declared here}}
88
IP<ip> *ip2;
99
};
1010

@@ -28,6 +28,7 @@ IP<nonconst_np> ip5; // expected-error{{non-type template argument of type 'std:
2828
// expected-note{{read of non-constexpr variable 'nonconst_np' is not allowed in a constant expression}}
2929
IP<(float*)0> ip6; // expected-error{{null non-type template argument of type 'float *' does not match template parameter of type 'int *'}}
3030
IP<&tl> ip7; // expected-error{{non-type template argument of type 'int *' is not a constant expression}}
31+
IP<(int*)1> ip8; // expected-error {{non-type template argument '(int *)1' is invalid}}
3132

3233
IR<tl> ir1; // expected-error{{non-type template argument refers to thread-local object}}
3334

clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ namespace addr_of_obj_or_func {
176176
// -- a pointer to member expressed as described in 5.3.1.
177177

178178
namespace bad_args {
179-
template <int* N> struct X0 { }; // precxx17-note 2{{template parameter is declared here}}
179+
template <int* N> struct X0 { }; // precxx17-note 4{{template parameter is declared here}}
180180
int i = 42;
181181
X0<&i + 2> x0a; // precxx17-error{{non-type template argument does not refer to any declaration}} \
182182
cxx17-error {{non-type template argument is not a constant expression}} \
@@ -194,6 +194,13 @@ namespace bad_args {
194194
// cxx17-error@-5 {{non-type template argument is not a constant expression}}
195195
// expected-note@-6 {{read of non-constexpr variable 'iptr' is not allowed in a constant expression}}
196196
#endif
197+
X0<(int*)1> x0c;
198+
// precxx17-error@-1 {{non-type template argument '(int *)1' is invalid}}
199+
// cxx17-error@-2 {{non-type template argument is not a constant expression}}
200+
// cxx17-note@-3 {{reinterpret_cast}}
201+
X0<__builtin_constant_p(0) ? (int*)1 : (int*)1> x0d;
202+
// precxx17-error@-1 {{non-type template argument '(int *)1' is invalid}}
203+
// cxx17-error@-2 {{non-type template argument refers to subobject '(int *)1'}}
197204
}
198205
#endif // CPP11ONLY
199206

0 commit comments

Comments
 (0)