]> granicus.if.org Git - clang/commitdiff
In -fdelayed-template-parsing mode, reenter every scope when late parsing a templated...
authorFrancois Pichet <pichet2000@gmail.com>
Wed, 22 Feb 2012 08:25:53 +0000 (08:25 +0000)
committerFrancois Pichet <pichet2000@gmail.com>
Wed, 22 Feb 2012 08:25:53 +0000 (08:25 +0000)
Otherwise this breaks some invariant during name lookup especially when dealing with shadowed declaration

Fix PR11931.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151140 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Parse/ParseTemplate.cpp
test/Parser/DelayedTemplateParsing.cpp

index d4a0502859def352026ea1afc71617934dceb71b..84b967e213bed9380e6f7d36713c71b45e61911a 100644 (file)
@@ -1157,109 +1157,113 @@ void Parser::LateTemplateParser(const FunctionDecl *FD) {
 
   llvm_unreachable("Late templated function without associated lexed tokens");
 }
-
-/// \brief Late parse a C++ function template in Microsoft mode.
-void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) {
-  if(!LMT.D)
-     return;
-
-  // If this is a member template, introduce the template parameter scope.
-  ParseScope TemplateScope(this, Scope::TemplateParamScope);
-
-  // Get the FunctionDecl.
-  FunctionDecl *FD = 0;
-  if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(LMT.D))
-    FD = FunTmpl->getTemplatedDecl();
-  else
-    FD = cast<FunctionDecl>(LMT.D);
-  
-  // Reinject the template parameters.
-  SmallVector<ParseScope*, 4> TemplateParamScopeStack;
-  DeclaratorDecl* Declarator = dyn_cast<DeclaratorDecl>(FD);
-  if (Declarator && Declarator->getNumTemplateParameterLists() != 0) {
-    Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator);
-    Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D);
-  } else {
-    Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D);
-
-    // Get the list of DeclContext to reenter.
-    SmallVector<DeclContext*, 4> DeclContextToReenter;
-    DeclContext *DD = FD->getLexicalParent();
-    while (DD && DD->isRecord()) {
-      DeclContextToReenter.push_back(DD);
-      DD = DD->getLexicalParent();
-    }
-
-    // Reenter template scopes from outmost to innermost.
-    SmallVector<DeclContext*, 4>::reverse_iterator II =
-    DeclContextToReenter.rbegin();
-    for (; II != DeclContextToReenter.rend(); ++II) {
-      if (ClassTemplatePartialSpecializationDecl* MD =
-                dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(*II)) {
-       TemplateParamScopeStack.push_back(new ParseScope(this,
-                                                   Scope::TemplateParamScope));
-        Actions.ActOnReenterTemplateScope(getCurScope(), MD);
-      } else if (CXXRecordDecl* MD = dyn_cast_or_null<CXXRecordDecl>(*II)) {
-        TemplateParamScopeStack.push_back(new ParseScope(this,
-                                                    Scope::TemplateParamScope,
-                                       MD->getDescribedClassTemplate() != 0 ));
-        Actions.ActOnReenterTemplateScope(getCurScope(),
-                                          MD->getDescribedClassTemplate());
-      }
-    }
-  }
-  assert(!LMT.Toks.empty() && "Empty body!");
-
-  // Append the current token at the end of the new token stream so that it
-  // doesn't get lost.
-  LMT.Toks.push_back(Tok);
-  PP.EnterTokenStream(LMT.Toks.data(), LMT.Toks.size(), true, false);
-
-  // Consume the previously pushed token.
-  ConsumeAnyToken();
-  assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))
-         && "Inline method not starting with '{', ':' or 'try'");
-
-  // Parse the method body. Function body parsing code is similar enough
-  // to be re-used for method bodies as well.
-  ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
-
-  // Recreate the DeclContext.
-  Sema::ContextRAII SavedContext(Actions, Actions.getContainingDC(FD));
-
-  if (FunctionTemplateDecl *FunctionTemplate
-        = dyn_cast_or_null<FunctionTemplateDecl>(LMT.D))
-    Actions.ActOnStartOfFunctionDef(getCurScope(),
-                                   FunctionTemplate->getTemplatedDecl());
-  if (FunctionDecl *Function = dyn_cast_or_null<FunctionDecl>(LMT.D))
-    Actions.ActOnStartOfFunctionDef(getCurScope(), Function);
-  
-
-  if (Tok.is(tok::kw_try)) {
-    ParseFunctionTryBlock(LMT.D, FnScope);
-  } else {
-    if (Tok.is(tok::colon))
-      ParseConstructorInitializer(LMT.D);
-    else
-      Actions.ActOnDefaultCtorInitializers(LMT.D);
-
-    if (Tok.is(tok::l_brace)) {
-      ParseFunctionStatementBody(LMT.D, FnScope);
-      Actions.MarkAsLateParsedTemplate(FD, false);
-    } else
-      Actions.ActOnFinishFunctionBody(LMT.D, 0);
-  }
-
-  // Exit scopes.
+\r
+/// \brief Late parse a C++ function template in Microsoft mode.\r
+void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) {\r
+  if(!LMT.D)\r
+     return;\r
+\r
+  // Get the FunctionDecl.\r
+  FunctionDecl *FD = 0;\r
+  if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(LMT.D))\r
+    FD = FunTmpl->getTemplatedDecl();\r
+  else\r
+    FD = cast<FunctionDecl>(LMT.D);\r
+  \r
+  // To restore the context after late parsing.
+  Sema::ContextRAII GlobalSavedContext(Actions, Actions.CurContext);\r
+\r
+  SmallVector<ParseScope*, 4> TemplateParamScopeStack;\r
+  DeclaratorDecl* Declarator = dyn_cast<DeclaratorDecl>(FD);\r
+  if (Declarator && Declarator->getNumTemplateParameterLists() != 0) {\r
+    TemplateParamScopeStack.push_back(new ParseScope(this, Scope::TemplateParamScope));\r
+    Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator);\r
+    Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D);\r
+  } else {\r
+    // Get the list of DeclContext to reenter.\r
+    SmallVector<DeclContext*, 4> DeclContextToReenter;\r
+    DeclContext *DD = FD->getLexicalParent();\r
+    while (DD && !DD->isTranslationUnit()) {\r
+      DeclContextToReenter.push_back(DD);\r
+      DD = DD->getLexicalParent();\r
+    }\r
+\r
+    // Reenter template scopes from outmost to innermost.\r
+    SmallVector<DeclContext*, 4>::reverse_iterator II =\r
+    DeclContextToReenter.rbegin();\r
+    for (; II != DeclContextToReenter.rend(); ++II) {\r
+      if (ClassTemplatePartialSpecializationDecl* MD =\r
+                dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(*II)) {\r
+        TemplateParamScopeStack.push_back(new ParseScope(this,\r
+                                                   Scope::TemplateParamScope));\r
+        Actions.ActOnReenterTemplateScope(getCurScope(), MD);\r
+      } else if (CXXRecordDecl* MD = dyn_cast_or_null<CXXRecordDecl>(*II)) {\r
+        TemplateParamScopeStack.push_back(new ParseScope(this,\r
+                                                    Scope::TemplateParamScope,\r
+                                       MD->getDescribedClassTemplate() != 0 ));\r
+        Actions.ActOnReenterTemplateScope(getCurScope(),\r
+                                          MD->getDescribedClassTemplate());\r
+      }\r
+      TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope));\r
+      Actions.PushDeclContext(Actions.getCurScope(), *II);\r
+    }\r
+    TemplateParamScopeStack.push_back(new ParseScope(this,\r
+                                      Scope::TemplateParamScope));\r
+    Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D);\r
+  }\r
+\r
+  assert(!LMT.Toks.empty() && "Empty body!");\r
+\r
+  // Append the current token at the end of the new token stream so that it\r
+  // doesn't get lost.\r
+  LMT.Toks.push_back(Tok);\r
+  PP.EnterTokenStream(LMT.Toks.data(), LMT.Toks.size(), true, false);\r
+\r
+  // Consume the previously pushed token.\r
+  ConsumeAnyToken();\r
+  assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))\r
+         && "Inline method not starting with '{', ':' or 'try'");\r
+\r
+  // Parse the method body. Function body parsing code is similar enough\r
+  // to be re-used for method bodies as well.\r
+  ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);\r
+\r
+  // Recreate the containing function DeclContext.\r
+  Sema::ContextRAII FunctionSavedContext(Actions, Actions.getContainingDC(FD));\r
+\r
+  if (FunctionTemplateDecl *FunctionTemplate\r
+        = dyn_cast_or_null<FunctionTemplateDecl>(LMT.D))\r
+    Actions.ActOnStartOfFunctionDef(getCurScope(),\r
+                                   FunctionTemplate->getTemplatedDecl());\r
+  if (FunctionDecl *Function = dyn_cast_or_null<FunctionDecl>(LMT.D))\r
+    Actions.ActOnStartOfFunctionDef(getCurScope(), Function);\r
+  \r
+\r
+  if (Tok.is(tok::kw_try)) {\r
+    ParseFunctionTryBlock(LMT.D, FnScope);\r
+  } else {\r
+    if (Tok.is(tok::colon))\r
+      ParseConstructorInitializer(LMT.D);\r
+    else\r
+      Actions.ActOnDefaultCtorInitializers(LMT.D);\r
+\r
+    if (Tok.is(tok::l_brace)) {\r
+      ParseFunctionStatementBody(LMT.D, FnScope);\r
+      Actions.MarkAsLateParsedTemplate(FD, false);\r
+    } else\r
+      Actions.ActOnFinishFunctionBody(LMT.D, 0);\r
+  }\r
+\r
+  // Exit scopes.\r
   FnScope.Exit();
-  SmallVector<ParseScope*, 4>::reverse_iterator I =
-   TemplateParamScopeStack.rbegin();
-  for (; I != TemplateParamScopeStack.rend(); ++I)
-    delete *I;
-
-  DeclGroupPtrTy grp = Actions.ConvertDeclToDeclGroup(LMT.D);
-  if (grp)
-    Actions.getASTConsumer().HandleTopLevelDecl(grp.get());
+  SmallVector<ParseScope*, 4>::reverse_iterator I =\r
+   TemplateParamScopeStack.rbegin();\r
+  for (; I != TemplateParamScopeStack.rend(); ++I)\r
+    delete *I;\r
+\r
+  DeclGroupPtrTy grp = Actions.ConvertDeclToDeclGroup(LMT.D);\r
+  if (grp)\r
+    Actions.getASTConsumer().HandleTopLevelDecl(grp.get());\r
 }
 
 /// \brief Lex a delayed template function for late parsing.
index 7fa87d98e55f210aa061e05a33a8558bd395cbdd..9737c731bd170cbdf3616d9e44523a9deea5545b 100644 (file)
@@ -63,3 +63,30 @@ public:
 
 }
 
+
+namespace PR11931 {
+
+template <typename RunType>
+struct BindState;
+
+  template<>
+struct BindState<void(void*)> {
+  static void Run() { }
+};
+
+class Callback {
+public:
+  typedef void RunType();
+
+  template <typename RunType>
+  Callback(BindState<RunType> bind_state) {
+    BindState<RunType>::Run();
+  }
+};
+
+
+Callback Bind() {
+  return Callback(BindState<void(void*)>());
+}
+
+}