Hi rsmith,
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.
http://reviews.llvm.org/D6665
Files:
include/clang/Sema/Sema.h
lib/Sema/TreeTransform.h
test/SemaCXX/lambda-expressions.cpp
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -3101,6 +3101,18 @@
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);
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -9121,6 +9121,8 @@
}
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 @@
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 @@
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);
}
Index: test/SemaCXX/lambda-expressions.cpp
===================================================================
--- test/SemaCXX/lambda-expressions.cpp
+++ test/SemaCXX/lambda-expressions.cpp
@@ -425,3 +425,17 @@
}
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}}
+ }
+}
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -3101,6 +3101,18 @@
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);
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -9121,6 +9121,8 @@
}
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 @@
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 @@
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);
}
Index: test/SemaCXX/lambda-expressions.cpp
===================================================================
--- test/SemaCXX/lambda-expressions.cpp
+++ test/SemaCXX/lambda-expressions.cpp
@@ -425,3 +425,17 @@
}
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}}
+ }
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits