Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
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->isDependentType() || DestTy->isDependentType()) {
return;
}

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

Expand Down
74 changes: 74 additions & 0 deletions clang/test/SemaCXX/reinterpret-cast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,3 +302,77 @@ 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>();
}

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

template<typename T, typename U>
void cast_template_dependent_member_type_noninstantiated(typename T::X x)
{
(void)*reinterpret_cast<typename U::Y>(x);
}

} // namespace templated