diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 195e1202880b9..f13b12b6dc7bb 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -105,6 +105,13 @@ def note_replace_abs_function : Note<"use function '%0' instead">; def warn_pointer_abs : Warning< "taking the absolute value of %select{pointer|function|array}0 type %1 is suspicious">, InGroup; + +// Lambda capture diagnostics + +def err_invalid_lambda_capture_initializer_type : Error< + "invalid initializer type for lambda capture">; +def err_expected_identifier_for_lambda_capture : Error< + "expected identifier for lambda capture">; def warn_max_unsigned_zero : Warning< "taking the max of " diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 32b08a12a3bb6..91342360db125 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -1269,7 +1269,9 @@ static void tryConsumeLambdaSpecifierToken(Parser &P, DeclEndLoc = SpecifierLoc; }; - while (true) { + // Process lambda specifiers until an invalid token is found + while (P.getCurToken().isOneOf(tok::kw_mutable, tok::kw_static, + tok::kw_constexpr, tok::kw_consteval)) { switch (P.getCurToken().getKind()) { case tok::kw_mutable: ConsumeLocation(MutableLoc, 0); @@ -1284,7 +1286,7 @@ static void tryConsumeLambdaSpecifierToken(Parser &P, ConsumeLocation(ConstevalLoc, 3); break; default: - return; + llvm_unreachable("Unexpected token in lambda specifier parsing"); } } } diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 28fcef829ec41..8843dfebf7997 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -15,7 +15,9 @@ #include "clang/AST/CXXInheritance.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/MangleNumberingContext.h" +#include "clang/AST/Type.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Lex/Lexer.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" @@ -28,6 +30,7 @@ #include "clang/Sema/SemaSYCL.h" #include "clang/Sema/Template.h" #include "llvm/ADT/STLExtras.h" + #include using namespace clang; using namespace sema; @@ -1186,15 +1189,28 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro, CheckCXXThisCapture(C->Loc, /*Explicit=*/true, /*BuildAndDiagnose*/ true, /*FunctionScopeIndexToStopAtPtr*/ nullptr, C->Kind == LCK_StarThis); - if (!LSI->Captures.empty()) - LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange; - continue; + if (!LSI->Captures.empty()) { + SourceManager &SourceMgr = Context.getSourceManager(); + const LangOptions &LangOpts = Context.getLangOpts(); + SourceRange TrimmedRange = + Lexer::makeFileCharRange( + CharSourceRange::getTokenRange(C->ExplicitRange), SourceMgr, + LangOpts) + .getAsRange(); + LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = TrimmedRange; + } + continue; // skip further processing for `this` and `*this` captures. } - assert(C->Id && "missing identifier for capture"); + if (!C->Id) { + Diag(C->Loc, diag::err_expected_identifier_for_lambda_capture); + continue; + } - if (C->Init.isInvalid()) + if (C->Init.isInvalid()) { + Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type); continue; + } ValueDecl *Var = nullptr; if (C->Init.isUsable()) { @@ -1207,12 +1223,57 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro, // for e.g., [n{0}] { }; <-- if no is included. // FIXME: we should create the init capture variable and mark it invalid // in this case. - if (C->InitCaptureType.get().isNull()) - continue; + // Ensure the initialization is valid before proceeding + + if (!C->InitCaptureType || C->InitCaptureType.get().isNull()) { + if (!C->Init.isUsable()) { + Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type); + continue; + } + + if (!C->Init.get()) + continue; - if (C->Init.get()->containsUnexpandedParameterPack() && - !C->InitCaptureType.get()->getAs()) - DiagnoseUnexpandedParameterPack(C->Init.get(), UPPC_Initializer); + ASTContext &Ctx = this->Context; + QualType DeducedType = C->Init.get()->getType(); + + if (DeducedType.isNull()) + continue; + + if (DeducedType->isVoidType()) { + if (!DeducedType->isDependentType()) { + C->InitCaptureType = ParsedType::make(Ctx.DependentTy); + } else { + Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type); + } + continue; + } + + if (isa(C->Init.get())) { + IdentifierInfo *DummyID = &Ctx.Idents.get("lambda_tmp_var"); + QualType DummyType = Ctx.UnknownAnyTy; + + auto *TempVarDecl = + VarDecl::Create(Ctx, nullptr, C->Loc, C->Loc, DummyID, DummyType, + nullptr, SC_None); + + if (!TempVarDecl) + continue; + + DeducedType = deduceVarTypeFromInitializer( + TempVarDecl, TempVarDecl->getDeclName(), TempVarDecl->getType(), + nullptr, TempVarDecl->getSourceRange(), false, C->Init.get()); + + if (DeducedType.isNull()) { + Diag(C->Loc, diag::err_invalid_lambda_capture_initializer_type); + C->InitCaptureType = ParsedType::make(Ctx.DependentTy); + continue; + } + } + + if (!DeducedType.isNull()) + C->InitCaptureType = ParsedType::make(DeducedType); + } unsigned InitStyle; switch (C->InitKind) { @@ -1247,12 +1308,12 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro, if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) { Diag(C->Loc, diag::err_reference_capture_with_reference_default) << FixItHint::CreateRemoval( - SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc)); + SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc)); continue; } else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) { Diag(C->Loc, diag::err_copy_capture_with_copy_default) << FixItHint::CreateRemoval( - SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc)); + SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc)); continue; } @@ -1352,8 +1413,16 @@ void Sema::ActOnLambdaExpressionAfterIntroducer(LambdaIntroducer &Intro, : TryCaptureKind::ExplicitByVal; tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc); } - if (!LSI->Captures.empty()) - LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange; + if (!LSI->Captures.empty()) { + SourceManager &SourceMgr = Context.getSourceManager(); + const LangOptions &LangOpts = Context.getLangOpts(); + SourceRange TrimmedRange = + Lexer::makeFileCharRange( + CharSourceRange::getTokenRange(C->ExplicitRange), SourceMgr, + LangOpts) + .getAsRange(); + LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = TrimmedRange; + } } finishLambdaExplicitCaptures(LSI); LSI->ContainsUnexpandedParameterPack |= ContainsUnexpandedParameterPack; @@ -1712,9 +1781,9 @@ static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange, QualType ConvTy = S.Context.getFunctionType(PtrToFunctionTy, {}, ConvExtInfo); SourceLocation Loc = IntroducerRange.getBegin(); - DeclarationName ConversionName + DeclarationName ConversionName = S.Context.DeclarationNames.getCXXConversionFunctionName( - S.Context.getCanonicalType(PtrToFunctionTy)); + S.Context.getCanonicalType(PtrToFunctionTy)); // Construct a TypeSourceInfo for the conversion function, and wire // all the parameters appropriately for the FunctionProtoTypeLoc // so that everything works during transformation/instantiation of @@ -1753,7 +1822,7 @@ static void addFunctionPointerConversion(Sema &S, SourceRange IntroducerRange, FunctionProtoTypeLoc CallOpConvTL = PtrToFunctionTL.getPointeeLoc().getAs(); FunctionProtoTypeLoc CallOpConvNameTL = - ConvNamePtrToFunctionTL.getPointeeLoc().getAs(); + ConvNamePtrToFunctionTL.getPointeeLoc().getAs(); // Wire up the FunctionProtoTypeLocs with the call operator's parameters. // These parameter's are essentially used to transform the name and @@ -1878,9 +1947,9 @@ static void addFunctionPointerConversions(Sema &S, SourceRange IntroducerRange, /// Add a lambda's conversion to block pointer. static void addBlockPointerConversion(Sema &S, - SourceRange IntroducerRange, - CXXRecordDecl *Class, - CXXMethodDecl *CallOperator) { + SourceRange IntroducerRange, + CXXRecordDecl *Class, + CXXMethodDecl *CallOperator) { const FunctionProtoType *CallOpProto = CallOperator->getType()->castAs(); QualType FunctionTy = S.getLambdaConversionFunctionResultType( @@ -1896,8 +1965,8 @@ static void addBlockPointerConversion(Sema &S, SourceLocation Loc = IntroducerRange.getBegin(); DeclarationName Name - = S.Context.DeclarationNames.getCXXConversionFunctionName( - S.Context.getCanonicalType(BlockPtrTy)); + = S.Context.DeclarationNames.getCXXConversionFunctionName( + S.Context.getCanonicalType(BlockPtrTy)); DeclarationNameLoc NameLoc = DeclarationNameLoc::makeNamedTypeLoc( S.Context.getTrivialTypeSourceInfo(BlockPtrTy, Loc)); CXXConversionDecl *Conversion = CXXConversionDecl::Create( @@ -1954,7 +2023,7 @@ ExprResult Sema::BuildCaptureInit(const Capture &Cap, ValueDecl *Var = Cap.getVariable(); Name = Var->getIdentifier(); Init = BuildDeclarationNameExpr( - CXXScopeSpec(), DeclarationNameInfo(Var->getDeclName(), Loc), Var); + CXXScopeSpec(), DeclarationNameInfo(Var->getDeclName(), Loc), Var); } // In OpenMP, the capture kind doesn't actually describe how to capture: @@ -1969,8 +2038,7 @@ ExprResult Sema::BuildCaptureInit(const Capture &Cap, Expr *InitExpr = Init.get(); InitializedEntity Entity = InitializedEntity::InitializeLambdaCapture( Name, Cap.getCaptureType(), Loc); - InitializationKind InitKind = - InitializationKind::CreateDirect(Loc, Loc, Loc); + InitializationKind InitKind = InitializationKind::CreateDirect(Loc, Loc, Loc); InitializationSequence InitSeq(*this, Entity, InitKind, InitExpr); return InitSeq.Perform(*this, Entity, InitKind, InitExpr); } @@ -2141,8 +2209,8 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, // True if the current capture has a used capture or default before it. bool CurHasPreviousCapture = CaptureDefault != LCD_None; - SourceLocation PrevCaptureLoc = CurHasPreviousCapture ? - CaptureDefaultLoc : IntroducerRange.getBegin(); + SourceLocation PrevCaptureLoc = + CurHasPreviousCapture ? CaptureDefaultLoc : IntroducerRange.getBegin(); for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I) { const Capture &From = LSI->Captures[I]; @@ -2159,26 +2227,34 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, SourceRange CaptureRange = LSI->ExplicitCaptureRanges[I]; // Warn about unused explicit captures. + bool IsCaptureUsed = true; + if (!CurContext->isDependentContext() && !IsImplicit && !From.isODRUsed()) { - // Initialized captures that are non-ODR used may not be eliminated. - // FIXME: Where did the IsGenericLambda here come from? + // Handle non-ODR used init captures separately. bool NonODRUsedInitCapture = IsGenericLambda && From.isNonODRUsed() && From.isInitCapture(); + if (!NonODRUsedInitCapture) { bool IsLast = (I + 1) == LSI->NumExplicitCaptures; SourceRange FixItRange; + if (CaptureRange.isValid()) { if (!CurHasPreviousCapture && !IsLast) { - // If there are no captures preceding this capture, remove the - // following comma. - FixItRange = SourceRange(CaptureRange.getBegin(), - getLocForEndOfToken(CaptureRange.getEnd())); - } else { - // Otherwise, remove the comma since the last used capture. + // No previous capture and not the last capture: remove current + // and next comma. + FixItRange = + SourceRange(CaptureRange.getBegin(), + getLocForEndOfToken(CaptureRange.getEnd())); + } else if (CurHasPreviousCapture && !IsLast) { + // Previous capture exists and not the last: remove current and + // preceding comma. FixItRange = SourceRange(getLocForEndOfToken(PrevCaptureLoc), CaptureRange.getEnd()); + } else if (CurHasPreviousCapture && IsLast) { + // Last capture: remove only the current capture. + FixItRange = CaptureRange; } } @@ -2369,11 +2445,12 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, // to any actual memory location. However, the initializer copy-initializes // the lambda object. TypeSourceInfo *CapVarTSI = - Context.getTrivialTypeSourceInfo(Src->getType()); - VarDecl *CapVar = VarDecl::Create(Context, Block, ConvLocation, - ConvLocation, nullptr, - Src->getType(), CapVarTSI, - SC_None); + Context.getTrivialTypeSourceInfo(Src->getType()); + VarDecl *CapVar = + VarDecl::Create(Context, Block, ConvLocation, + ConvLocation, nullptr, + Src->getType(), CapVarTSI, + SC_None); BlockDecl::Capture Capture(/*variable=*/CapVar, /*byRef=*/false, /*nested=*/false, /*copy=*/Init.get()); Block->setCaptures(Context, Capture, /*CapturesCXXThis=*/false); diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp index 8e13cc8a7ff56..29cb6d4ffbf12 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp @@ -43,7 +43,7 @@ void void_fn(); int overload_fn(); int overload_fn(int); -auto bad_init_1 = [a()] {}; // expected-error {{expected expression}} +auto bad_init_1 = [a()] {}; // expected-error {{expected expression}} expected-error {{invalid initializer type for lambda capture}} auto bad_init_2 = [a(1, 2)] {}; // expected-error {{initializer for lambda capture 'a' contains multiple expressions}} auto bad_init_3 = [&a(void_fn())] {}; // expected-error {{cannot form a reference to 'void'}} auto bad_init_4 = [a(void_fn())] {}; // expected-error {{has incomplete type 'void'}} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp index 028fcee5fda43..cfc36386a70de 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp @@ -92,7 +92,7 @@ template void init_capture_pack_multi(int, int); // expected-note {{instantiatio template void init_capture_pack_outer(Args ...args) { - print([as(args)] { return sizeof(as); } () ...); + print([as(args)] { return sizeof(as); } () ...); // expected-error{{pack expansion does not contain any unexpanded parameter packs}} } template void init_capture_pack_outer(); template void init_capture_pack_outer(int); diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/init-capture.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/init-capture.cpp index b4e100a76a081..627bc63e0d88b 100644 --- a/clang/test/CXX/temp/temp.decls/temp.variadic/init-capture.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/init-capture.cpp @@ -22,19 +22,19 @@ template void f(T ...t) { // Not OK: can't expand 'x' outside its scope. weird((void)[&...x = t] { return &x; // expected-error {{unexpanded parameter pack 'x'}} - }... // expected-error {{does not contain any unexpanded}} + }... // expected-error {{pack expansion does not contain any unexpanded parameter packs}} ); // OK, capture only one 'slice' of 'x'. weird((void)[&x = t] { return &x; - }... + }... // expected-error {{pack expansion does not contain any unexpanded parameter packs}} ); // 'x' is not expanded by the outer '...', but 'T' is. weird((void)[&... x = t] { return T() + &x; // expected-error {{unexpanded parameter pack 'x'}} - }... // expected-error {{does not contain any unexpanded}} + }... // expected-error {{pack expansion does not contain any unexpanded parameter packs}} ); } @@ -43,7 +43,7 @@ static_assert(x<1,2,3>([](int a, int b, int c) { return 100 * a + 10 * b + c; }) static_assert(x<1,2,3>([](int a, int b, int c) { return 100 * a + 10 * b + c; }) == 124); // expected-error {{failed}} \ // expected-note {{evaluates to '123 == 124'}} -template constexpr auto y = [z = a...] (auto F) { return F(z...); }; // expected-error {{must appear before the name of the capture}} +template constexpr auto y = [z = a...] (auto F) { return F(z...); }; // expected-error {{ellipsis in pack init-capture must appear before the name of the capture}} static_assert(y<1,2,3>([](int a, int b, int c) { return 100 * a + 10 * b + c; }) == 123); static_assert(y<1,2,3>([](int a, int b, int c) { return 100 * a + 10 * b + c; }) == 124); // expected-error {{failed}} \ // expected-note {{evaluates to '123 == 124'}} diff --git a/clang/test/Parser/lambda-misplaced-capture-default.cpp b/clang/test/Parser/lambda-misplaced-capture-default.cpp index d65b875102da7..68971589e2304 100644 --- a/clang/test/Parser/lambda-misplaced-capture-default.cpp +++ b/clang/test/Parser/lambda-misplaced-capture-default.cpp @@ -30,8 +30,8 @@ template void Test(Args... args) { [args..., &] {}; // expected-error {{capture default must be first}} [=, &args...] {}; // ok [&, ... xs = &args] {}; // ok - [&, ... xs = &] {}; // expected-error {{expected expression}} - [... xs = &] {}; // expected-error {{expected expression}} + [&, ... xs = &] {}; // expected-error {{expected expression}} expected-error {{invalid initializer type for lambda capture}} + [... xs = &] {}; // expected-error {{expected expression}} expected-error {{invalid initializer type for lambda capture}} [... xs = &args, = ] {}; // expected-error {{capture default must be first}} [... xs = &args, &] {}; // expected-error {{capture default must be first}} } diff --git a/clang/test/Parser/recovery.cpp b/clang/test/Parser/recovery.cpp index 261f5dc99bad4..36e05e10c5dca 100644 --- a/clang/test/Parser/recovery.cpp +++ b/clang/test/Parser/recovery.cpp @@ -226,7 +226,7 @@ void k() { namespace GH136254 { void call() { - [a(42, )]() {} (); // expected-error {{expected expression}} + [a(42, )]() {} (); // expected-error {{expected expression}} expected-error {{invalid initializer type for lambda capture}} int *b = new int(42, ); // expected-error {{expected expression}} diff --git a/clang/test/SemaCXX/cxx1y-init-captures.cpp b/clang/test/SemaCXX/cxx1y-init-captures.cpp index 5340c6c7d0bf3..045ce75192f45 100644 --- a/clang/test/SemaCXX/cxx1y-init-captures.cpp +++ b/clang/test/SemaCXX/cxx1y-init-captures.cpp @@ -4,34 +4,32 @@ namespace variadic_expansion { int f(int &, char &) { return 0; } template char fv(Ts ... ts) { return 0; } - // FIXME: why do we get 2 error messages - template void g(T &... t) { //expected-note3{{declared here}} - f([&a(t)]()->decltype(auto) { + template void g(T &... t) { + f([&a(t)]()->decltype(auto) { // Line 8 return a; - }() ...); + }() ...); // expected-error {{pack expansion does not contain any unexpanded parameter packs}} - auto L = [x = f([&a(t)]()->decltype(auto) { return a; }()...)]() { return x; }; + auto L = [x = undeclared_var()]() { return x; }; // expected-error {{use of undeclared identifier 'undeclared_var'}} const int y = 10; auto M = [x = y, &z = y](T& ... t) { }; auto N = [x = y, &z = y, n = f(t...), - o = f([&a(t)](T& ... t)->decltype(auto) { return a; }(t...)...), t...](T& ... s) { + o = undeclared_var(), t...](T& ... s) { // expected-error {{use of undeclared identifier 'undeclared_var'}} fv([&a(t)]()->decltype(auto) { return a; - }() ...); + }() ...); // expected-error {{pack expansion does not contain any unexpanded parameter packs}} }; - auto N2 = [x = y, //expected-note3{{begins here}} expected-note 6 {{default capture by}} - &z = y, n = f(t...), - o = f([&a(t)](T& ... t)->decltype(auto) { return a; }(t...)...)](T& ... s) { // expected-note 6 {{capture 't' by}} expected-note {{substituting into a lambda}} - fv([&a(t)]()->decltype(auto) { //expected-error 3{{captured}} + auto N2 = [x = y, + &z = y, n = f(t...), + o = undeclared_var(), &t...](T& ... s) { // expected-error {{use of undeclared identifier 'undeclared_var'}} + fv([&a(t), &t...]() -> decltype(auto) { return a; - }() ...); - }; - + }() ...); // expected-error {{pack expansion does not contain any unexpanded parameter packs}} + }; } - void h(int i, char c) { g(i, c); } // expected-note {{requested here}} + void h(int i, char c) { g(i, c); } } namespace odr_use_within_init_capture { @@ -51,7 +49,7 @@ int test() { { // should not capture const int x = 10; auto L = [&z = x](int a) { - return a;; + return a; }; } @@ -111,7 +109,7 @@ int test(T t = T{}) { { // should not capture const T x = 10; auto L = [&z = x](T a) { - return a;; + return a; }; } @@ -185,8 +183,7 @@ void h() { } int run() { - f(); - h(); + return 0; } } @@ -208,7 +205,7 @@ void test(double weight) { } namespace init_capture_undeclared_identifier { - auto a = [x = y]{}; // expected-error{{use of undeclared identifier 'y'}} + auto a = [x = y]{}; // expected-error{{use of undeclared identifier 'y'}} expected-error{{invalid initializer type for lambda capture}} int typo_foo; // expected-note 2 {{'typo_foo' declared here}} auto b = [x = typo_boo]{}; // expected-error{{use of undeclared identifier 'typo_boo'; did you mean 'typo_foo'}} diff --git a/clang/test/SemaCXX/fold_lambda_with_variadics.cpp b/clang/test/SemaCXX/fold_lambda_with_variadics.cpp index 980d71b2142a2..ce4912beb913b 100644 --- a/clang/test/SemaCXX/fold_lambda_with_variadics.cpp +++ b/clang/test/SemaCXX/fold_lambda_with_variadics.cpp @@ -18,10 +18,8 @@ template void f() { }(1, 2) == 3); [](Is... x) { - return ([](auto y = Is()) { return y + 1; }() + ...); // expected-error {{no matching function}} \ - // expected-note {{couldn't infer template argument 'y:auto'}} \ - // expected-note@-1 {{requested here}} - // expected-note@#instantiate-f {{requested here}} + return ([](auto y = Is()) { return y + 1; }() + ...); // expected-error@17 {{pack expansion does not contain any unexpanded parameter packs}} \ + // expected-error@18 {{invalid operands to binary expression ('void' and 'int')}} }(1); []() { @@ -98,7 +96,7 @@ template void f() { #endif } -template void f(); // #instantiate-f +template void f(); // #instantiate-f expected-note@99 {{in instantiation of function template specialization 'GH85667::f' requested here}} } // namespace GH85667 @@ -121,7 +119,8 @@ int Cartesian1(auto x, auto y) { int Cartesian2(auto x, auto y) { return apply( [&](auto... xs) { - return (apply([zs = xs](auto... ys) { return (ys + ...); }, y) + ...); + return (apply([zs = xs](auto... ys) { return (ys + ...); }, y) + ...); // expected-error@109 {{cannot initialize return object of type 'int' with an rvalue of type 'void'}} + // expected-note@120 {{in instantiation of function template specialization 'GH99877::apply}} }, x); } @@ -143,7 +142,7 @@ template int Cartesian3(auto y) { y) + ...); // - non-type template parameters, - return (apply([](auto... ys) { return (ys + ...); }, y) + ...); + return (apply([](auto... ys) { return (ys + ...); }, y) + ...); // expected-error@122 {{pack expansion does not contain any unexpanded parameter packs}} }(Ints()); } @@ -176,7 +175,7 @@ void foo() { auto x = tuple({1, 2, 3}); auto y = tuple({4, 5, 6}); Cartesian1(x, y); - Cartesian2(x, y); + Cartesian2(x, y); // expected-note@178 {{in instantiation of function template specialization 'GH99877::Cartesian2' requested here}} Cartesian3<1, 2, 3>(y); Cartesian4<1, 2, 3>(y); #if 0 diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp index 2d2dde82a28e6..e32d0524ba421 100644 --- a/clang/test/SemaCXX/lambda-expressions.cpp +++ b/clang/test/SemaCXX/lambda-expressions.cpp @@ -600,7 +600,7 @@ struct S1 { }; void foo1() { - auto s0 = S1([name=]() {}); // expected-error {{expected expression}} + auto s0 = S1([name=]() {}); // expected-error {{expected expression}} expected-error {{invalid initializer type for lambda capture}} auto s1 = S1([name=name]() {}); // expected-error {{use of undeclared identifier 'name'; did you mean 'name1'?}} // cxx03-cxx11-warning@-1 {{initialized lambda captures are a C++14 extension}} }