Skip to content

Commit d049db8

Browse files
authored
[clang] Fix false warning on reinterpret_casting unknown template type (#109430)
After 1595988 diag::warn_undefined_reinterpret_cast started raising on non-instantiated template functions without sufficient knowledge whether the reinterpret_cast is indeed UB.
1 parent 6f0a627 commit d049db8

File tree

3 files changed

+80
-0
lines changed

3 files changed

+80
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,8 @@ Improvements to Clang's diagnostics
660660

661661
- Don't emit bogus dangling diagnostics when ``[[gsl::Owner]]`` and `[[clang::lifetimebound]]` are used together (#GH108272).
662662

663+
- Don't emit bogus dignostic about an undefined behavior on ``reinterpret_cast<T>`` for non-instantiated template functions without sufficient knowledge whether it can actually lead to undefined behavior for ``T`` (#GH109430).
664+
663665
- The ``-Wreturn-stack-address`` warning now also warns about addresses of
664666
local variables passed to function calls using the ``[[clang::musttail]]``
665667
attribute.

clang/lib/Sema/SemaCast.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2094,6 +2094,10 @@ void Sema::CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType,
20942094
}
20952095
}
20962096

2097+
if (SrcTy->isDependentType() || DestTy->isDependentType()) {
2098+
return;
2099+
}
2100+
20972101
Diag(Range.getBegin(), DiagID) << SrcType << DestType << Range;
20982102
}
20992103

clang/test/SemaCXX/reinterpret-cast.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,3 +302,77 @@ void reinterpret_cast_allowlist () {
302302
(void)reinterpret_cast<unsigned char&>(b);
303303
(void)*reinterpret_cast<unsigned char*>(&b);
304304
}
305+
306+
namespace templated {
307+
template <typename TARGETTYPE, typename UATYPE>
308+
void cast_uninstantiated() {
309+
const UATYPE* data;
310+
(void)*reinterpret_cast<const TARGETTYPE*>(data); // no warning
311+
}
312+
313+
314+
template <typename TARGETTYPE, typename UATYPE>
315+
void cast_instantiated_badly() {
316+
const UATYPE* data;
317+
(void)*reinterpret_cast<const TARGETTYPE*>(data); // expected-warning {{dereference of type 'const int *' that was reinterpret_cast from type 'const float *' has undefined behavior}}
318+
}
319+
320+
template <typename TARGETTYPE, typename UATYPE>
321+
void cast_instantiated_well() {
322+
const UATYPE* data;
323+
(void)*reinterpret_cast<const TARGETTYPE*>(data); // no warning
324+
}
325+
326+
template <typename TARGETTYPE>
327+
void cast_one_tmpl_arg_uninstantiated() {
328+
const int* data;
329+
(void)*reinterpret_cast<const TARGETTYPE*>(data); // no warning
330+
}
331+
332+
template <typename TARGETTYPE>
333+
void cast_one_tmpl_arg_instantiated_badly() {
334+
const float* data;
335+
(void)*reinterpret_cast<const TARGETTYPE*>(data); // expected-warning {{dereference of type 'const int *' that was reinterpret_cast from type 'const float *' has undefined behavior}}
336+
}
337+
338+
template <typename TARGETTYPE>
339+
void cast_one_tmpl_arg_instantiated_well() {
340+
const float* data;
341+
(void)*reinterpret_cast<const TARGETTYPE*>(data); // no warning
342+
}
343+
344+
template <int size>
345+
void cast_nontype_template_true_positive_noninstantiated() {
346+
const float *data;
347+
const int arr[size];
348+
(void)*reinterpret_cast<const int*>(data); // expected-warning {{dereference of type 'const int *' that was reinterpret_cast from type 'const float *' has undefined behavior}}
349+
}
350+
351+
template <int size>
352+
void cast_nontype_template_true_negative_noninstantiated() {
353+
const int data[size];
354+
(void)*reinterpret_cast<const int*>(data); // no warning
355+
}
356+
357+
void top() {
358+
cast_instantiated_badly<int, float>();
359+
// expected-note@-1 {{in instantiation of function template specialization 'templated::cast_instantiated_badly<int, float>' requested here}}
360+
cast_instantiated_well<int, int>();
361+
cast_one_tmpl_arg_instantiated_badly<int>();
362+
// expected-note@-1 {{in instantiation of function template specialization 'templated::cast_one_tmpl_arg_instantiated_badly<int>' requested here}}
363+
cast_one_tmpl_arg_instantiated_well<float>();
364+
}
365+
366+
template<typename T, typename U>
367+
void cast_template_dependent_type_noninstantiated(T** x)
368+
{
369+
(void)*reinterpret_cast<U**>(x);
370+
}
371+
372+
template<typename T, typename U>
373+
void cast_template_dependent_member_type_noninstantiated(typename T::X x)
374+
{
375+
(void)*reinterpret_cast<typename U::Y>(x);
376+
}
377+
378+
} // namespace templated

0 commit comments

Comments
 (0)