ahatanak updated this revision to Diff 55453. ahatanak added a comment. Use ParseScopeFlags to clear the TemplateParamScope rather than calling setFlags directly.
I tried calling Init(AnyParent, F) is Scope::setFlags, but it caused a lot of test cases to fail, which I'm currently investigating. http://reviews.llvm.org/D19175 Files: lib/Parse/ParseTemplate.cpp lib/Sema/SemaLambda.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp test/SemaCXX/vartemplate-lambda.cpp Index: test/SemaCXX/vartemplate-lambda.cpp =================================================================== --- /dev/null +++ test/SemaCXX/vartemplate-lambda.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s +// expected-no-diagnostics + +template <class> auto fn0 = [] {}; +template <typename> void foo0() { fn0<char>(); } + +template<typename T> auto fn1 = [](auto a) { return a + T(1); }; + +template <typename X> +int foo2() { + X a = 0x61; + fn1<char>(a); + return 0; +} + +int main() { + foo2<int>(); +} Index: test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp =================================================================== --- test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp +++ test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp @@ -195,7 +195,7 @@ namespace default_args { #ifdef CPP11ONLY namespace lambdas { -template<int I = ([] { return 5; }())> //expected-error 2{{constant expression}} expected-note{{constant expression}} +template<int I = ([] { return 5; }())> //expected-error {{constant expression}} int f(); } #endif // CPP11ONLY Index: lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3907,9 +3907,14 @@ PushExpressionEvaluationContext(Sema::PotentiallyEvaluated, OldVar); // Instantiate the initializer. - ExprResult Init = - SubstInitializer(OldVar->getInit(), TemplateArgs, - OldVar->getInitStyle() == VarDecl::CallInit); + ExprResult Init; + + { + ContextRAII SwitchContext(*this, Var->getDeclContext()); + Init = SubstInitializer(OldVar->getInit(), TemplateArgs, + OldVar->getInitStyle() == VarDecl::CallInit); + } + if (!Init.isInvalid()) { bool TypeMayContainAuto = true; Expr *InitExpr = Init.get(); Index: lib/Sema/SemaLambda.cpp =================================================================== --- lib/Sema/SemaLambda.cpp +++ lib/Sema/SemaLambda.cpp @@ -814,8 +814,8 @@ // The lambda-expression's closure type might be dependent even if its // semantic context isn't, if it appears within a default argument of a // function template. - if (Scope *TmplScope = CurScope->getTemplateParamParent()) - if (!TmplScope->decl_empty()) + if (auto *TmplScope = CurScope->getTemplateParamParent()) + if (TmplScope->isTemplateParamScope()) KnownDependent = true; // Determine the signature of the call operator. Index: lib/Parse/ParseTemplate.cpp =================================================================== --- lib/Parse/ParseTemplate.cpp +++ lib/Parse/ParseTemplate.cpp @@ -147,6 +147,9 @@ } } while (Tok.isOneOf(tok::kw_export, tok::kw_template)); + unsigned NewFlags = getCurScope()->getFlags() & ~Scope::TemplateParamScope; + ParseScopeFlags TemplateScopeFlags(this, NewFlags, isSpecialization); + // Parse the actual template declaration. return ParseSingleDeclarationAfterTemplate(Context, ParsedTemplateInfo(&ParamLists,
Index: test/SemaCXX/vartemplate-lambda.cpp =================================================================== --- /dev/null +++ test/SemaCXX/vartemplate-lambda.cpp @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s +// expected-no-diagnostics + +template <class> auto fn0 = [] {}; +template <typename> void foo0() { fn0<char>(); } + +template<typename T> auto fn1 = [](auto a) { return a + T(1); }; + +template <typename X> +int foo2() { + X a = 0x61; + fn1<char>(a); + return 0; +} + +int main() { + foo2<int>(); +} Index: test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp =================================================================== --- test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp +++ test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp @@ -195,7 +195,7 @@ namespace default_args { #ifdef CPP11ONLY namespace lambdas { -template<int I = ([] { return 5; }())> //expected-error 2{{constant expression}} expected-note{{constant expression}} +template<int I = ([] { return 5; }())> //expected-error {{constant expression}} int f(); } #endif // CPP11ONLY Index: lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3907,9 +3907,14 @@ PushExpressionEvaluationContext(Sema::PotentiallyEvaluated, OldVar); // Instantiate the initializer. - ExprResult Init = - SubstInitializer(OldVar->getInit(), TemplateArgs, - OldVar->getInitStyle() == VarDecl::CallInit); + ExprResult Init; + + { + ContextRAII SwitchContext(*this, Var->getDeclContext()); + Init = SubstInitializer(OldVar->getInit(), TemplateArgs, + OldVar->getInitStyle() == VarDecl::CallInit); + } + if (!Init.isInvalid()) { bool TypeMayContainAuto = true; Expr *InitExpr = Init.get(); Index: lib/Sema/SemaLambda.cpp =================================================================== --- lib/Sema/SemaLambda.cpp +++ lib/Sema/SemaLambda.cpp @@ -814,8 +814,8 @@ // The lambda-expression's closure type might be dependent even if its // semantic context isn't, if it appears within a default argument of a // function template. - if (Scope *TmplScope = CurScope->getTemplateParamParent()) - if (!TmplScope->decl_empty()) + if (auto *TmplScope = CurScope->getTemplateParamParent()) + if (TmplScope->isTemplateParamScope()) KnownDependent = true; // Determine the signature of the call operator. Index: lib/Parse/ParseTemplate.cpp =================================================================== --- lib/Parse/ParseTemplate.cpp +++ lib/Parse/ParseTemplate.cpp @@ -147,6 +147,9 @@ } } while (Tok.isOneOf(tok::kw_export, tok::kw_template)); + unsigned NewFlags = getCurScope()->getFlags() & ~Scope::TemplateParamScope; + ParseScopeFlags TemplateScopeFlags(this, NewFlags, isSpecialization); + // Parse the actual template declaration. return ParseSingleDeclarationAfterTemplate(Context, ParsedTemplateInfo(&ParamLists,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits