From: Reid Kleckner Date: Mon, 15 Dec 2014 21:07:16 +0000 (+0000) Subject: Handle errors in lambda prototype instantiation correctly X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cbfd7a0d4454b17c11c73cdd483c5b5c059f567b;p=clang Handle errors in lambda prototype instantiation correctly Previously we would attempt to build a TypeSourceInfo for a null type, and then we would forget to pop the function scope before returning an error. Reviewers: rsmith Differential Revision: http://reviews.llvm.org/D6665 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@224271 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index b0d9be449a..a6010944aa 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -3107,6 +3107,18 @@ public: Sema &S; }; + /// An RAII helper that pops function a function scope on exit. + struct FunctionScopeRAII { + Sema &S; + bool Active; + FunctionScopeRAII(Sema &S) : Active(true), S(S) {} + ~FunctionScopeRAII() { + if (Active) + S.PopFunctionScopeInfo(); + } + void disable() { Active = false; } + }; + StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 295d208edf..36abbb624a 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -9121,6 +9121,8 @@ TreeTransform::TransformLambdaExpr(LambdaExpr *E) { } LambdaScopeInfo *LSI = getSema().PushLambdaScope(); + Sema::FunctionScopeRAII FuncScopeCleanup(getSema()); + // Transform the template parameters, and add them to the current // instantiation scope. The null case is handled correctly. LSI->GLTemplateParameterList = getDerived().TransformTemplateParameterList( @@ -9145,10 +9147,10 @@ TreeTransform::TransformLambdaExpr(LambdaExpr *E) { return This->TransformExceptionSpec(OldCallOpFPTL.getBeginLoc(), ESI, ExceptionStorage, Changed); }); + if (NewCallOpType.isNull()) + return ExprError(); NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, NewCallOpType); - if (!NewCallOpTSI) - return ExprError(); } // Create the local class that will describe the lambda. @@ -9168,6 +9170,10 @@ TreeTransform::TransformLambdaExpr(LambdaExpr *E) { getDerived().transformAttrs(E->getCallOperator(), NewCallOperator); + // TransformLambdaScope will manage the function scope, so we can disable the + // cleanup. + FuncScopeCleanup.disable(); + return getDerived().TransformLambdaScope(E, NewCallOperator, InitCaptureExprsAndTypes); } diff --git a/test/SemaCXX/lambda-expressions.cpp b/test/SemaCXX/lambda-expressions.cpp index 1346c3da91..62208959ae 100644 --- a/test/SemaCXX/lambda-expressions.cpp +++ b/test/SemaCXX/lambda-expressions.cpp @@ -425,3 +425,17 @@ namespace lambda_in_default_mem_init { } template void g(); } + +namespace error_in_transform_prototype { + template + void f(T t) { + // expected-error@+2 {{type 'int' cannot be used prior to '::' because it has no members}} + // expected-error@+1 {{no member named 'ns' in 'error_in_transform_prototype::S'}} + auto x = [](typename T::ns::type &k) {}; + } + class S {}; + void foo() { + f(5); // expected-note {{requested here}} + f(S()); // expected-note {{requested here}} + } +}