[clang][Sema] Fix assertion in tryDiagnoseOverloadedCast
(#108021)
Fixed an assertion failure in debug mode, and potential crashes in release mode, when diagnosing a failed cast caused indirectly by a failed implicit conversion to the type of the constructor parameter. For instance ``` template<typename> struct StringTrait {}; template< int N > struct StringTrait< const char[ N ] > { typedef char CharType; static const MissingIntT length = N - 1; }; class String { public: template <typename T> String(T& str, typename StringTrait<T>::CharType = 0); }; class Exception { public: Exception(String const&); }; void foo() { throw Exception("some error"); } ``` `Exception(String const&)` is a matching constructor for `Exception` from a `const char*`, via an implicit conversion to `String`. However, the instantiation of the `String` constructor will fail because of the missing type `MissingIntT` inside the specialization of `StringTrait`. When trying to emit a diagnosis, `tryDiagnoseOverloadedCast` expects not to have a matching constructor, but there is; it just could not be instantiated.
This commit is contained in:
parent
94a98cf5dc
commit
0dd56858fe
@ -397,6 +397,8 @@ Bug Fixes to C++ Support
|
||||
- Fixed a crash when clang tries to subtitute parameter pack while retaining the parameter
|
||||
pack. #GH63819, #GH107560
|
||||
- Fix a crash when a static assert declaration has an invalid close location. (#GH108687)
|
||||
- Fixed an assertion failure in debug mode, and potential crashes in release mode, when
|
||||
diagnosing a failed cast caused indirectly by a failed implicit conversion to the type of the constructor parameter.
|
||||
|
||||
Bug Fixes to AST Handling
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -446,7 +446,12 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT,
|
||||
: InitializationKind::CreateCast(/*type range?*/ range);
|
||||
InitializationSequence sequence(S, entity, initKind, src);
|
||||
|
||||
assert(sequence.Failed() && "initialization succeeded on second try?");
|
||||
// It could happen that a constructor failed to be used because
|
||||
// it requires a temporary of a broken type. Still, it will be found when
|
||||
// looking for a match.
|
||||
if (!sequence.Failed())
|
||||
return false;
|
||||
|
||||
switch (sequence.getFailureKind()) {
|
||||
default: return false;
|
||||
|
||||
|
26
clang/test/Parser/cxx-bad-cast-diagnose-broken-template.cpp
Normal file
26
clang/test/Parser/cxx-bad-cast-diagnose-broken-template.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s
|
||||
|
||||
template<typename>
|
||||
struct StringTrait {};
|
||||
|
||||
template< int N >
|
||||
struct StringTrait< const char[ N ] > {
|
||||
typedef char CharType;
|
||||
static const MissingIntT length = N - 1; // expected-error {{unknown type name 'MissingIntT'}}
|
||||
};
|
||||
|
||||
class String {
|
||||
public:
|
||||
template <typename T>
|
||||
String(T& str, typename StringTrait<T>::CharType = 0);
|
||||
};
|
||||
|
||||
|
||||
class Exception {
|
||||
public:
|
||||
Exception(String const&);
|
||||
};
|
||||
|
||||
void foo() {
|
||||
throw Exception("some error"); // expected-error {{functional-style cast from 'const char[11]' to 'Exception' is not allowed}}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user