https://github.com/hnrklssn updated https://github.com/llvm/llvm-project/pull/226431
>From 35b514c318bb85e6f9d41e5bafaf27820ddfdd99 Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" <[email protected]> Date: Thu, 24 Sep 2026 16:14:32 +0200 Subject: [PATCH 1/3] clean up trailing whitespace --- clang/test/SemaObjCXX/blocks.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/test/SemaObjCXX/blocks.mm b/clang/test/SemaObjCXX/blocks.mm index f1b5b301087eb..0d63f9c9b1017 100644 --- a/clang/test/SemaObjCXX/blocks.mm +++ b/clang/test/SemaObjCXX/blocks.mm @@ -33,7 +33,7 @@ - (void)bar; @end namespace N { - class X { }; + class X { }; void foo(X); } @@ -45,7 +45,7 @@ - (void)bar { @end typedef signed char BOOL; -void foo6(void *block) { +void foo6(void *block) { void (^vb)(id obj, int idx, BOOL *stop) = (void (^)(id, int, BOOL *))block; BOOL (^bb)(id obj, int idx, BOOL *stop) = (BOOL (^)(id, int, BOOL *))block; } >From bae3926324a08dff3a577406141e5ce99029cd77 Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" <[email protected]> Date: Fri, 25 Sep 2026 12:39:44 +0200 Subject: [PATCH 2/3] [clang] preserve return type sourceloc when instantiating templated blocks When transforming a block expression we would transform the return type, but ignore the return type location. When using the `typename` keyword, this would result in an elaborated type with invalid source location, which would trigger the `(Keyword != ElaboratedTypeKeyword::None) == KeywordLoc.isValid()` assertion in `CheckTypenameType`. rdar://184773464 --- clang/lib/Sema/TreeTransform.h | 27 +++++++++++++++++++++++-- clang/test/SemaObjCXX/blocks.mm | 35 +++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index e482d15f31cc5..b9115da43bed2 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -17910,8 +17910,31 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { return ExprError(); } - QualType exprResultType = - getDerived().TransformType(exprFunctionType->getReturnType()); + TypeLoc resultTL; + if (TypeSourceInfo *SigTSI = oldBlock->getSignatureAsWritten()) { + resultTL = SigTSI->getTypeLoc(); + // If there's no FunctionProtoTypeLoc, the typeloc is just the return type. + if (auto FTL = resultTL.getAsAdjusted<FunctionProtoTypeLoc>()) + resultTL = FTL.getReturnLoc(); + } + QualType exprResultType; + if (resultTL && resultTL.getType() == exprFunctionType->getReturnType()) { + // Preserve the source location for any elaborated-type keywords + // (e.g. 'typename') + TypeSourceInfo *ResultTSI = SemaRef.Context.CreateTypeSourceInfo( + resultTL.getType(), resultTL.getFullDataSize()); + ResultTSI->getTypeLoc().initializeFullCopy(resultTL); + if (TypeSourceInfo *NewResultTSI = getDerived().TransformType(ResultTSI)) + exprResultType = NewResultTSI->getType(); + } else { + // Fallback for deduced return types, since they lack a source location. + exprResultType = + getDerived().TransformType(exprFunctionType->getReturnType()); + } + if (exprResultType.isNull()) { + getSema().ActOnBlockError(E->getCaretLocation(), /*Scope=*/nullptr); + return ExprError(); + } auto epi = exprFunctionType->getExtProtoInfo(); epi.ExtParameterInfos = extParamInfos.getPointerOrNull(paramTypes.size()); diff --git a/clang/test/SemaObjCXX/blocks.mm b/clang/test/SemaObjCXX/blocks.mm index 0d63f9c9b1017..c74a3e0ff8f37 100644 --- a/clang/test/SemaObjCXX/blocks.mm +++ b/clang/test/SemaObjCXX/blocks.mm @@ -147,6 +147,41 @@ void f(T t) { template void f<X>(X); } +namespace DependentTypenameReturnType { + // Success case + template <class T> struct S { typedef int type; }; + template <class T> void f() { + auto b = ^ typename S<T>::type () { return 0; }; + (void)b; + } + template void f<int>(); + + // Same as 'f' but with no parameter list. The written block signature is + // then stored as just the return-type loc (there is no FunctionProtoTypeLoc + // to look through). + template <class T> void g() { + auto b = ^ typename S<T>::type { return 0; }; + (void)b; + } + template void g<int>(); + + // A block with no explicit return type has no return-type source location, so + // it takes the deduced-return fallback in TransformBlockExpr. + template <class T> T h() { + auto b = ^ { T x{}; return x; }; + return b(); + } + template int h<int>(); + + // Failure case + template <class T> struct NoType {}; + template <class T> void i() { + auto b = ^ typename NoType<T>::type () { return 0; }; // expected-error{{no type named 'type' in 'DependentTypenameReturnType::NoType<int>'}} + (void)b; + } + template void i<int>(); // expected-note{{in instantiation of function template specialization 'DependentTypenameReturnType::i<int>' requested here}} +} + namespace GenericLambdaCapture { int test(int outerp) { auto lambda =[&](auto p) { >From 62641d5b7e57cb506bc22e2a70b7132f631ced9f Mon Sep 17 00:00:00 2001 From: "Henrik G. Olsson" <[email protected]> Date: Mon, 28 Sep 2026 15:08:11 +0200 Subject: [PATCH 3/3] add trailing return type test case --- clang/test/SemaObjCXX/blocks.mm | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/clang/test/SemaObjCXX/blocks.mm b/clang/test/SemaObjCXX/blocks.mm index c74a3e0ff8f37..9620fd2489097 100644 --- a/clang/test/SemaObjCXX/blocks.mm +++ b/clang/test/SemaObjCXX/blocks.mm @@ -173,13 +173,19 @@ void f(T t) { } template int h<int>(); + template <class T> T i() { + auto b = ^auto()->typename S<T>::type { return 0; }; + (void)b(); + } + template int i<int>(); + // Failure case template <class T> struct NoType {}; - template <class T> void i() { + template <class T> void j() { auto b = ^ typename NoType<T>::type () { return 0; }; // expected-error{{no type named 'type' in 'DependentTypenameReturnType::NoType<int>'}} (void)b; } - template void i<int>(); // expected-note{{in instantiation of function template specialization 'DependentTypenameReturnType::i<int>' requested here}} + template void j<int>(); // expected-note{{in instantiation of function template specialization 'DependentTypenameReturnType::j<int>' requested here}} } namespace GenericLambdaCapture { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
