diff options
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 20 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 3 | ||||
-rw-r--r-- | clang/test/SemaCXX/decltype.cpp | 21 |
4 files changed, 42 insertions, 4 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index a0d64ac2afd..8faf29556e1 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/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/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 1c6cfb8484e..6d624adc4eb 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/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/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 0d287f7210c..537f1ec8ab5 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/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/clang/test/SemaCXX/decltype.cpp b/clang/test/SemaCXX/decltype.cpp index 8de5a9c3bae..f1900b2b830 100644 --- a/clang/test/SemaCXX/decltype.cpp +++ b/clang/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); |