aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2014-04-26 18:29:13 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2014-04-26 18:29:13 +0000
commitc117f224c622bac377d7fcf102ef6f29598099d8 (patch)
tree55e1f6c5fd3008e5c5096f5d5f99766b42468566
parentdbc6d63bd5ffb866033822536d90ab57974cb224 (diff)
downloadclang_35a-c117f224c622bac377d7fcf102ef6f29598099d8.tar.gz
[Sema] Adjust Sema::getCurBlock()/getCurLambda() to take into account that we may have
switch CurContext due to class template instantiation. Fixes crash of the included test case. rdar://16527205 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@207325 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/Sema.cpp20
-rw-r--r--lib/Sema/SemaExpr.cpp2
-rw-r--r--lib/Sema/SemaLambda.cpp3
-rw-r--r--test/SemaCXX/decltype.cpp21
4 files changed, 42 insertions, 4 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index a0d64ac2af..8faf29556e 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -1114,14 +1114,30 @@ BlockScopeInfo *Sema::getCurBlock() {
if (FunctionScopes.empty())
return 0;
- return dyn_cast<BlockScopeInfo>(FunctionScopes.back());
+ auto CurBSI = dyn_cast<BlockScopeInfo>(FunctionScopes.back());
+ if (CurBSI && CurBSI->TheDecl &&
+ !CurBSI->TheDecl->Encloses(CurContext)) {
+ // We have switched contexts due to template instantiation.
+ assert(!ActiveTemplateInstantiations.empty());
+ return nullptr;
+ }
+
+ return CurBSI;
}
LambdaScopeInfo *Sema::getCurLambda() {
if (FunctionScopes.empty())
return 0;
- return dyn_cast<LambdaScopeInfo>(FunctionScopes.back());
+ auto CurLSI = dyn_cast<LambdaScopeInfo>(FunctionScopes.back());
+ if (CurLSI && CurLSI->Lambda &&
+ !CurLSI->Lambda->Encloses(CurContext)) {
+ // We have switched contexts due to template instantiation.
+ assert(!ActiveTemplateInstantiations.empty());
+ return nullptr;
+ }
+
+ return CurLSI;
}
// We have a generic lambda if we parsed auto parameters, or we have
// an associated template parameter list.
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 1c6cfb8484..6d624adc4e 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -10557,7 +10557,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
// to deduce an implicit return type.
if (getLangOpts().CPlusPlus && RetTy->isRecordType() &&
!BSI->TheDecl->isDependentContext())
- computeNRVO(Body, getCurBlock());
+ computeNRVO(Body, BSI);
BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy);
AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index 0d287f7210..537f1ec8ab 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -1139,6 +1139,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
bool IsInstantiation) {
+ LambdaScopeInfo *LSI = getCurLambda();
+
// Leave the expression-evaluation context.
DiscardCleanupsInEvaluationContext();
PopExpressionEvaluationContext();
@@ -1148,7 +1150,6 @@ void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope,
PopDeclContext();
// Finalize the lambda.
- LambdaScopeInfo *LSI = getCurLambda();
CXXRecordDecl *Class = LSI->Lambda;
Class->setInvalidDecl();
SmallVector<Decl*, 4> Fields(Class->fields());
diff --git a/test/SemaCXX/decltype.cpp b/test/SemaCXX/decltype.cpp
index 8de5a9c3ba..f1900b2b83 100644
--- a/test/SemaCXX/decltype.cpp
+++ b/test/SemaCXX/decltype.cpp
@@ -16,6 +16,27 @@ void test_f2() {
float &fr = f2(AC().a);
}
+template <class T>
+struct Future {
+ explicit Future(T v);
+
+ template <class F>
+ auto call(F&& fn) -> decltype(fn(T())) {
+ return fn(T());
+ }
+
+ template <class B, class F>
+ auto then(F&& fn) -> decltype(call(fn))
+ {
+ return fn(T());
+ }
+};
+
+void rdar16527205() {
+ Future<int> f1(42);
+ f1.call([](int){ return Future<float>(0); });
+}
+
namespace pr10154 {
class A{
A(decltype(nullptr) param);