Skip to content

Commit 0dd5685

Browse files
[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.
1 parent 94a98cf commit 0dd5685

File tree

3 files changed

+34
-1
lines changed

3 files changed

+34
-1
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,8 @@ Bug Fixes to C++ Support
397397
- Fixed a crash when clang tries to subtitute parameter pack while retaining the parameter
398398
pack. #GH63819, #GH107560
399399
- Fix a crash when a static assert declaration has an invalid close location. (#GH108687)
400+
- Fixed an assertion failure in debug mode, and potential crashes in release mode, when
401+
diagnosing a failed cast caused indirectly by a failed implicit conversion to the type of the constructor parameter.
400402

401403
Bug Fixes to AST Handling
402404
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaCast.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,12 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT,
446446
: InitializationKind::CreateCast(/*type range?*/ range);
447447
InitializationSequence sequence(S, entity, initKind, src);
448448

449-
assert(sequence.Failed() && "initialization succeeded on second try?");
449+
// It could happen that a constructor failed to be used because
450+
// it requires a temporary of a broken type. Still, it will be found when
451+
// looking for a match.
452+
if (!sequence.Failed())
453+
return false;
454+
450455
switch (sequence.getFailureKind()) {
451456
default: return false;
452457

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s
2+
3+
template<typename>
4+
struct StringTrait {};
5+
6+
template< int N >
7+
struct StringTrait< const char[ N ] > {
8+
typedef char CharType;
9+
static const MissingIntT length = N - 1; // expected-error {{unknown type name 'MissingIntT'}}
10+
};
11+
12+
class String {
13+
public:
14+
template <typename T>
15+
String(T& str, typename StringTrait<T>::CharType = 0);
16+
};
17+
18+
19+
class Exception {
20+
public:
21+
Exception(String const&);
22+
};
23+
24+
void foo() {
25+
throw Exception("some error"); // expected-error {{functional-style cast from 'const char[11]' to 'Exception' is not allowed}}
26+
}

0 commit comments

Comments
 (0)