diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2014-04-26 18:29:13 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2014-04-26 18:29:13 +0000 |
commit | c117f224c622bac377d7fcf102ef6f29598099d8 (patch) | |
tree | 55e1f6c5fd3008e5c5096f5d5f99766b42468566 | |
parent | dbc6d63bd5ffb866033822536d90ab57974cb224 (diff) | |
download | clang_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.cpp | 20 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaLambda.cpp | 3 | ||||
-rw-r--r-- | test/SemaCXX/decltype.cpp | 21 |
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); |