]> granicus.if.org Git - clang/commitdiff
[Parser] Clear the TemplateParamScope bit of the current scope's flag
authorAkira Hatanaka <ahatanaka@apple.com>
Fri, 29 Apr 2016 02:24:14 +0000 (02:24 +0000)
committerAkira Hatanaka <ahatanaka@apple.com>
Fri, 29 Apr 2016 02:24:14 +0000 (02:24 +0000)
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

include/clang/Sema/Scope.h
lib/Parse/ParseTemplate.cpp
lib/Sema/Scope.cpp
lib/Sema/SemaLambda.cpp
test/CXX/drs/dr1xx.cpp
test/CXX/temp/temp.arg/temp.arg.nontype/p1.cpp
test/SemaCXX/vartemplate-lambda.cpp

index 4e96b7553d0f31621c4418549f9c6084b71ff8a5..d0b006b82ec6e310fad57b67f50e6fca8dcbf28e 100644 (file)
@@ -197,6 +197,8 @@ private:
   /// this scope, or over-defined. The bit is true when over-defined.
   llvm::PointerIntPair<VarDecl *, 1, bool> 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; }
index 185497a8be44aa005c990ef518b363ab09a4dde5..61da159ae02179d5600984d5b32d884435e6dd11 100644 (file)
@@ -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,
index c9c7dea5d865b3585e13894c3d0cb528a871a8e5..ae5b181c6728815073e9e8e79d41e3994ef363f5 100644 (file)
@@ -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();
index 88754e259758fe0abe4b32e36963eea45886508b..d1d002b5d41e9838b356d54fd255a4f17e0d60b8 100644 (file)
@@ -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;
index 47d1494ec7a3c41f7f14c8cb19d16407fbb06852..8d368a5a54e8546edd6ad27cb0c3594c4a05e2f1 100644 (file)
@@ -902,7 +902,11 @@ namespace dr183 { // dr183: sup 382
     typedef int X;
   };
   template<> struct A<int> {
+#if __cplusplus <= 199711
+    typename B<int>::X x; // expected-error {{'typename' occurs outside of a template}}
+#else
     typename B<int>::X x;
+#endif
   };
 }
 
index 6b87c6688a8a20d85dc05069a6b1be5fd2c5f4ee..58290ac40fdb0a21433ceae85aa78ab7ec4cf84b 100644 (file)
@@ -195,7 +195,7 @@ namespace bad_args {
 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 d5ad155d0e32c36dccebebdde2039d49096c811b..9dab6da3d1e3d44dea40ec285f3dc9779b735e06 100644 (file)
@@ -1,6 +1,9 @@
 // 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>