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

llvm-svn: 224271
This commit is contained in:
Reid Kleckner 2014-12-15 21:07:16 +00:00
parent 42be29f748
commit aac43c6a77
3 changed files with 34 additions and 2 deletions

View File

@ -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);

View File

@ -9121,6 +9121,8 @@ TreeTransform<Derived>::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<Derived>::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<Derived>::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);
}

View File

@ -425,3 +425,17 @@ namespace lambda_in_default_mem_init {
}
template void g<int>();
}
namespace error_in_transform_prototype {
template<class T>
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}}
}
}