]> granicus.if.org Git - clang/commitdiff
[Sema] Adjust Sema::getCurBlock()/getCurLambda() to take into account that we may...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sat, 26 Apr 2014 18:29:13 +0000 (18:29 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sat, 26 Apr 2014 18:29:13 +0000 (18:29 +0000)
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

lib/Sema/Sema.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaLambda.cpp
test/SemaCXX/decltype.cpp

index a0d64ac2afd551815c44250408262e4f5d7a3c81..8faf29556e1d356f15529dd6e3e68ab3cb1669ad 100644 (file)
@@ -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.
index 1c6cfb8484e6947bfa3136fd2cf8611823ced556..6d624adc4eb115de29eb4445e780b2a3b0a391f7 100644 (file)
@@ -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();
index 0d287f7210cf7955aaae5d6450b64a266f33bc04..537f1ec8ab5936d95b8521d5322fcb7993fcdacf 100644 (file)
@@ -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());
index 8de5a9c3baee283a974a5fb680ac6d0a6b0c2055..f1900b2b830f038e2b60bc427aa07c26ad38b788 100644 (file)
@@ -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);