[cfe-commits] r140344 - in /cfe/trunk: lib/Parse/ParseTemplate.cpp test/Parser/DelayedTemplateParsing.cpp

Francois Pichet pichet2000 at gmail.com
Thu Sep 22 15:14:56 PDT 2011


Author: fpichet
Date: Thu Sep 22 17:14:56 2011
New Revision: 140344

URL: http://llvm.org/viewvc/llvm-project?rev=140344&view=rev
Log:
[microsoft] Fix a bug in -fdelayed-template-parsing mode where we were not reentering the delayed function context correctly. The problem was that all template params were reintroduced inside the same scope. So if we had a situation where we had 2 template params with the same name at different scope then clang would generate an error about ambiguous name.

The solution is to create a new ParseScope(Scope::TemplateParamScope) for each template scope that we want to reenter. (from the outmost to the innermost scope)

This fixes some errors when parsing MFC code with clang.

Modified:
    cfe/trunk/lib/Parse/ParseTemplate.cpp
    cfe/trunk/test/Parser/DelayedTemplateParsing.cpp

Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=140344&r1=140343&r2=140344&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Thu Sep 22 17:14:56 2011
@@ -1159,6 +1159,7 @@
     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);
@@ -1166,17 +1167,31 @@
   } 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()) {
-      if (ClassTemplatePartialSpecializationDecl* MD =
-                  dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(DD))
-          Actions.ActOnReenterTemplateScope(getCurScope(), MD);
-      else if (CXXRecordDecl* MD = dyn_cast_or_null<CXXRecordDecl>(DD))
-          Actions.ActOnReenterTemplateScope(getCurScope(),
-                                            MD->getDescribedClassTemplate());
-
+      DeclContextToReenter.push_back(DD);
       DD = DD->getLexicalParent();
     }
+
+    // Reenter the DeclContext 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!");
 
@@ -1207,21 +1222,25 @@
 
   if (Tok.is(tok::kw_try)) {
     ParseFunctionTryBlock(LMT.D, FnScope);
-    return;
-  }
-  if (Tok.is(tok::colon)) {
-    ParseConstructorInitializer(LMT.D);
-
-    // Error recovery.
-    if (!Tok.is(tok::l_brace)) {
+  } 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);
-      return;
-    }
-  } else
-    Actions.ActOnDefaultCtorInitializers(LMT.D);
+  }
 
-  ParseFunctionStatementBody(LMT.D, FnScope);
-  Actions.MarkAsLateParsedTemplate(FD, false);
+  // Exit scopes.
+  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)

Modified: cfe/trunk/test/Parser/DelayedTemplateParsing.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/DelayedTemplateParsing.cpp?rev=140344&r1=140343&r2=140344&view=diff
==============================================================================
--- cfe/trunk/test/Parser/DelayedTemplateParsing.cpp (original)
+++ cfe/trunk/test/Parser/DelayedTemplateParsing.cpp Thu Sep 22 17:14:56 2011
@@ -1,11 +1,11 @@
-// RUN: %clang_cc1 -fdelayed-template-parsing -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fms-extensions -fdelayed-template-parsing -fsyntax-only -verify %s
 
 template <class T>
 class A {
    void foo() {
        undeclared();
    }
-      void foo2();
+   void foo2();
 };
 
 template <class T>
@@ -40,3 +40,22 @@
 
 template <class T> void foo5() {} //expected-note {{previous definition is here}} 
 template <class T> void foo5() {} // expected-error {{redefinition of 'foo5'}}
+
+              
+
+namespace Inner_Outer_same_template_param_name {              
+
+template <class T>
+class Outmost {
+public:
+    template <class T>
+    class Inner {
+    public:
+        void f() {
+            T* var;
+        }
+   };
+};
+
+}
+





More information about the cfe-commits mailing list