Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions clang/lib/Sema/SemaCast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2092,6 +2092,10 @@ void Sema::CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType,
}
}

if (SrcTy->isTemplateTypeParmType() || DestTy->isTemplateTypeParmType()) {
Copy link
Member

@sdkrystian sdkrystian Sep 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably beif (SrcTy->isDependentType() || DestTy->isDependentType()). Otherwise we will continue to warn for the following:

template<typename T, typename U>
void f(T** x) 
{
    *reinterpret_cast<U**>(x);
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point
Fixed in 541e0af

return;
}

Diag(Range.getBegin(), DiagID) << SrcType << DestType << Range;
}

Expand Down
62 changes: 62 additions & 0 deletions clang/test/SemaCXX/reinterpret-cast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,3 +302,65 @@ void reinterpret_cast_allowlist () {
(void)reinterpret_cast<unsigned char&>(b);
(void)*reinterpret_cast<unsigned char*>(&b);
}

namespace templated {
template <typename TARGETTYPE, typename UATYPE>
void cast_uninstantiated() {
const UATYPE* data;
(void)*reinterpret_cast<const TARGETTYPE*>(data); // no warning
}


template <typename TARGETTYPE, typename UATYPE>
void cast_instantiated_badly() {
const UATYPE* data;
(void)*reinterpret_cast<const TARGETTYPE*>(data); // expected-warning {{dereference of type 'const int *' that was reinterpret_cast from type 'const float *' has undefined behavior}}
}

template <typename TARGETTYPE, typename UATYPE>
void cast_instantiated_well() {
const UATYPE* data;
(void)*reinterpret_cast<const TARGETTYPE*>(data); // no warning
}

template <typename TARGETTYPE>
void cast_one_tmpl_arg_uninstantiated() {
const int* data;
(void)*reinterpret_cast<const TARGETTYPE*>(data); // no warning
}

template <typename TARGETTYPE>
void cast_one_tmpl_arg_instantiated_badly() {
const float* data;
(void)*reinterpret_cast<const TARGETTYPE*>(data); // expected-warning {{dereference of type 'const int *' that was reinterpret_cast from type 'const float *' has undefined behavior}}
}

template <typename TARGETTYPE>
void cast_one_tmpl_arg_instantiated_well() {
const float* data;
(void)*reinterpret_cast<const TARGETTYPE*>(data); // no warning
}

template <int size>
void cast_nontype_template_true_positive_noninstantiated() {
const float *data;
const int arr[size];
(void)*reinterpret_cast<const int*>(data); // expected-warning {{dereference of type 'const int *' that was reinterpret_cast from type 'const float *' has undefined behavior}}
}

template <int size>
void cast_nontype_template_true_negative_noninstantiated() {
const int data[size];
(void)*reinterpret_cast<const int*>(data); // no warning
}

void top() {
cast_instantiated_badly<int, float>();
// expected-note@-1 {{in instantiation of function template specialization 'templated::cast_instantiated_badly<int, float>' requested here}}
cast_instantiated_well<int, int>();
cast_one_tmpl_arg_instantiated_badly<int>();
// expected-note@-1 {{in instantiation of function template specialization 'templated::cast_one_tmpl_arg_instantiated_badly<int>' requested here}}
cast_one_tmpl_arg_instantiated_well<float>();
}

} // namespace templated