Skip to content

Commit 29785cc

Browse files
committed
[Clang] Don't retain template FoundDecl for conversion function calls
In consteval calls rewriting, we expect an instantiated AST to remain untouched. However, this was not true when rebuilding a MemberExpr in TreeTransform, as it relies on FoundDecl to build a resolved member call expression. This is due to the fact that the instantiated CXXMemberCallExpr still holds a template declaration as FoundDecl, leading to a non-dependent-to-dependent transform. I don't think it makes much sense to preserve a template in FoundDecl. FoundDecl should primarily distinguish declarations whose getUnderlyingDecl() points elsewhere, like UsingShadowDecl.
1 parent 91edbe2 commit 29785cc

File tree

3 files changed

+36
-1
lines changed

3 files changed

+36
-1
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ Bug Fixes to C++ Support
545545
- Clang no longer crashes when establishing subsumption between some constraint expressions. (#GH122581)
546546
- Clang now issues an error when placement new is used to modify a const-qualified variable
547547
in a ``constexpr`` function. (#GH131432)
548+
- Fixed an incorrect TreeTransform for calls to ``consteval`` functions if a conversion template is present. (#GH137885)
548549
- Clang now emits a warning when class template argument deduction for alias templates is used in C++17. (#GH133806)
549550

550551
Bug Fixes to AST Handling

clang/lib/Sema/SemaOverload.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3977,7 +3977,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
39773977
// phase of [over.match.list] when the initializer list has exactly
39783978
// one element that is itself an initializer list, [...] and the
39793979
// conversion is to X or reference to cv X, user-defined conversion
3980-
// sequences are not cnosidered.
3980+
// sequences are not considered.
39813981
if (SuppressUserConversions && ListInitializing) {
39823982
SuppressUserConversions =
39833983
NumArgs == 1 && isa<InitListExpr>(Args[0]) &&
@@ -14750,6 +14750,12 @@ ExprResult Sema::CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass,
1475014750
ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
1475114751
CXXConversionDecl *Method,
1475214752
bool HadMultipleCandidates) {
14753+
// FoundDecl can be the TemplateDecl of Method. Don't retain a template in
14754+
// the FoundDecl as it impedes TransformMemberExpr.
14755+
// We go a bit further here: if there's no difference in UnderlyingDecl,
14756+
// then using FoundDecl vs Method shouldn't make a difference either.
14757+
if (FoundDecl->getUnderlyingDecl() == FoundDecl)
14758+
FoundDecl = Method;
1475314759
// Convert the expression to match the conversion function's implicit object
1475414760
// parameter.
1475514761
ExprResult Exp;

clang/test/SemaCXX/cxx2a-consteval.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,3 +1272,31 @@ int main() {
12721272
}
12731273

12741274
} // namespace GH107175
1275+
1276+
namespace GH137885 {
1277+
1278+
template <typename... P> struct A {};
1279+
1280+
template <int N>
1281+
struct B {
1282+
consteval B() {}
1283+
1284+
template <typename... P> consteval operator A<P...>() const {
1285+
static_assert(sizeof...(P) == N);
1286+
return {};
1287+
}
1288+
};
1289+
1290+
template <typename T> struct type_identity {
1291+
using type = T;
1292+
};
1293+
1294+
template <typename... P>
1295+
void foo(typename type_identity<A<P...>>::type a, P...) {}
1296+
1297+
void foo() {
1298+
foo(B<0>());
1299+
foo(B<5>(), 1, 2, 3, 4, 5);
1300+
}
1301+
1302+
}

0 commit comments

Comments
 (0)