From: Akira Hatanaka Date: Fri, 29 Apr 2016 02:24:14 +0000 (+0000) Subject: [Parser] Clear the TemplateParamScope bit of the current scope's flag X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dc80ac434c06547fdc596b83ef531e0ca3fd3464;p=clang [Parser] Clear the TemplateParamScope bit of the current scope's flag if we are parsing a template specialization. This commit makes changes to clear the TemplateParamScope bit and set the TemplateParamParent field of the current scope to null if a template specialization is being parsed. Before this commit, Sema::ActOnStartOfLambdaDefinition would check whether the parent template scope had any decls to determine whether or not a template specialization was being parsed. This wasn't correct since it couldn't distinguish between a real template specialization and a template defintion with an unnamed template parameter (only template parameters with names are added to the scope's decl list). To fix the bug, this commit changes the code to check the pointer to the parent template scope rather than the decl list. rdar://problem/23440346 Differential Revision: http://reviews.llvm.org/D19175 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@267975 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Scope.h b/include/clang/Sema/Scope.h index 4e96b7553d..d0b006b82e 100644 --- a/include/clang/Sema/Scope.h +++ b/include/clang/Sema/Scope.h @@ -197,6 +197,8 @@ private: /// this scope, or over-defined. The bit is true when over-defined. llvm::PointerIntPair NRVO; + void setFlags(Scope *Parent, unsigned F); + public: Scope(Scope *Parent, unsigned ScopeFlags, DiagnosticsEngine &Diag) : ErrorTrap(Diag) { @@ -206,7 +208,7 @@ public: /// getFlags - Return the flags for this scope. /// unsigned getFlags() const { return Flags; } - void setFlags(unsigned F) { Flags = F; } + void setFlags(unsigned F) { setFlags(getParent(), F); } /// isBlockScope - Return true if this scope correspond to a closure. bool isBlockScope() const { return Flags & BlockScope; } diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 185497a8be..61da159ae0 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -147,6 +147,9 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, } } 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, diff --git a/lib/Sema/Scope.cpp b/lib/Sema/Scope.cpp index c9c7dea5d8..ae5b181c67 100644 --- a/lib/Sema/Scope.cpp +++ b/lib/Sema/Scope.cpp @@ -18,7 +18,7 @@ using namespace clang; -void Scope::Init(Scope *parent, unsigned flags) { +void Scope::setFlags(Scope *parent, unsigned flags) { AnyParent = parent; Flags = flags; @@ -83,6 +83,10 @@ void Scope::Init(Scope *parent, unsigned flags) { else incrementMSManglingNumber(); } +} + +void Scope::Init(Scope *parent, unsigned flags) { + setFlags(parent, flags); DeclsInScope.clear(); UsingDirectives.clear(); diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 88754e2597..d1d002b5d4 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -814,9 +814,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, // 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()) - KnownDependent = true; + if (CurScope->getTemplateParamParent()) + KnownDependent = true; // Determine the signature of the call operator. TypeSourceInfo *MethodTyInfo; diff --git a/test/CXX/drs/dr1xx.cpp b/test/CXX/drs/dr1xx.cpp index 47d1494ec7..8d368a5a54 100644 --- a/test/CXX/drs/dr1xx.cpp +++ b/test/CXX/drs/dr1xx.cpp @@ -902,7 +902,11 @@ namespace dr183 { // dr183: sup 382 typedef int X; }; template<> struct A { +#if __cplusplus <= 199711 + typename B::X x; // expected-error {{'typename' occurs outside of a template}} +#else typename B::X x; +#endif }; } diff --git a/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp b/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp index 6b87c6688a..58290ac40f 100644 --- a/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp +++ b/test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp @@ -195,7 +195,7 @@ namespace bad_args { namespace default_args { #ifdef CPP11ONLY namespace lambdas { -template //expected-error 2{{constant expression}} expected-note{{constant expression}} +template //expected-error {{constant expression}} int f(); } #endif // CPP11ONLY diff --git a/test/SemaCXX/vartemplate-lambda.cpp b/test/SemaCXX/vartemplate-lambda.cpp index d5ad155d0e..9dab6da3d1 100644 --- a/test/SemaCXX/vartemplate-lambda.cpp +++ b/test/SemaCXX/vartemplate-lambda.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s // expected-no-diagnostics +template auto fn0 = [] {}; +template void foo0() { fn0(); } + template auto fn1 = [](auto a) { return a + T(1); }; template