[cfe-commits] r91771 - in /cfe/trunk: include/clang/Parse/Action.h include/clang/Parse/Parser.h lib/Parse/ParseCXXInlineMethods.cpp lib/Sema/Sema.h lib/Sema/SemaCXXScopeSpec.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/CXX/temp/temp.spec/temp.explicit/p3.cpp

John McCall rjmccall at apple.com
Sat Dec 19 02:49:30 PST 2009


Author: rjmccall
Date: Sat Dec 19 04:49:29 2009
New Revision: 91771

URL: http://llvm.org/viewvc/llvm-project?rev=91771&view=rev
Log:
Refactor to remove more dependencies on PreDeclaratorDC.  I seem to have made
the redeclaration problems in the [temp.explicit]p3 testcase worse, but I can
live with that;  they'll need to be fixed more holistically anyhow.


Modified:
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p3.cpp

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=91771&r1=91770&r2=91771&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Sat Dec 19 04:49:29 2009
@@ -1351,6 +1351,14 @@
   virtual void ActOnReenterTemplateScope(Scope *S, DeclPtrTy Template) {
   }
 
+  /// ActOnStartDelayedMemberDeclarations - We have completed parsing
+  /// a C++ class, and we are about to start parsing any parts of
+  /// member declarations that could not be parsed earlier.  Enter
+  /// the appropriate record scope.
+  virtual void ActOnStartDelayedMemberDeclarations(Scope *S,
+                                                   DeclPtrTy Record) {
+  }
+
   /// ActOnStartDelayedCXXMethodDeclaration - We have completed
   /// parsing a top-level (non-nested) C++ class, and we are now
   /// parsing those parts of the given Method declaration that could
@@ -1381,6 +1389,14 @@
                                                       DeclPtrTy Method) {
   }
 
+  /// ActOnFinishDelayedMemberDeclarations - We have finished parsing
+  /// a C++ class, and we are about to start parsing any parts of
+  /// member declarations that could not be parsed earlier.  Enter the
+  /// appropriate record scope.
+  virtual void ActOnFinishDelayedMemberDeclarations(Scope *S,
+                                                    DeclPtrTy Record) {
+  }
+
   /// ActOnStaticAssertDeclaration - Parse a C++0x static_assert declaration.
   virtual DeclPtrTy ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
                                                  ExprArg AssertExpr,

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=91771&r1=91770&r2=91771&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Sat Dec 19 04:49:29 2009
@@ -1243,10 +1243,7 @@
       CreatedScope = true;
       P.EnterScope(0); // Not a decl scope.
 
-      if (P.Actions.ActOnCXXEnterDeclaratorScope(P.CurScope, SS))
-        SS.setScopeRep(0);
-      
-      if (!SS.isInvalid())
+      if (!P.Actions.ActOnCXXEnterDeclaratorScope(P.CurScope, SS))
         EnteredScope = true;
     }
 

Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=91771&r1=91770&r2=91771&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Sat Dec 19 04:49:29 2009
@@ -95,9 +95,12 @@
   if (HasTemplateScope)
     Actions.ActOnReenterTemplateScope(CurScope, Class.TagOrTemplate);
 
+  // The current scope is still active if we're the top-level class.
+  // Otherwise we'll need to push and enter a new scope.
   bool HasClassScope = !Class.TopLevelClass;
-  ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope,
-                        HasClassScope);
+  ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope, HasClassScope);
+  if (HasClassScope)
+    Actions.ActOnStartDelayedMemberDeclarations(CurScope, Class.TagOrTemplate);
 
   for (; !Class.MethodDecls.empty(); Class.MethodDecls.pop_front()) {
     LateParsedMethodDeclaration &LM = Class.MethodDecls.front();
@@ -148,6 +151,9 @@
 
   for (unsigned I = 0, N = Class.NestedClasses.size(); I != N; ++I)
     ParseLexedMethodDeclarations(*Class.NestedClasses[I]);
+
+  if (HasClassScope)
+    Actions.ActOnFinishDelayedMemberDeclarations(CurScope, Class.TagOrTemplate);
 }
 
 /// ParseLexedMethodDefs - We finished parsing the member specification of a top

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=91771&r1=91770&r2=91771&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sat Dec 19 04:49:29 2009
@@ -2193,11 +2193,15 @@
                                                  SourceLocation RBrac);
 
   virtual void ActOnReenterTemplateScope(Scope *S, DeclPtrTy Template);
+  virtual void ActOnStartDelayedMemberDeclarations(Scope *S,
+                                                   DeclPtrTy Record);
   virtual void ActOnStartDelayedCXXMethodDeclaration(Scope *S,
                                                      DeclPtrTy Method);
   virtual void ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy Param);
   virtual void ActOnFinishDelayedCXXMethodDeclaration(Scope *S,
                                                       DeclPtrTy Method);
+  virtual void ActOnFinishDelayedMemberDeclarations(Scope *S,
+                                                    DeclPtrTy Record);
 
   virtual DeclPtrTy ActOnStaticAssertDeclaration(SourceLocation AssertLoc,
                                                  ExprArg AssertExpr,

Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=91771&r1=91770&r2=91771&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Sat Dec 19 04:49:29 2009
@@ -605,15 +605,18 @@
 /// The 'SS' should be a non-empty valid CXXScopeSpec.
 bool Sema::ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
   assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
-  if (DeclContext *DC = computeDeclContext(SS, true)) {
-    // Before we enter a declarator's context, we need to make sure that
-    // it is a complete declaration context.
-    if (!DC->isDependentContext() && RequireCompleteDeclContext(SS))
-      return true;
-      
-    EnterDeclaratorContext(S, DC);
-  }
-  
+
+  if (SS.isInvalid()) return true;
+
+  DeclContext *DC = computeDeclContext(SS, true);
+  if (!DC) return true;
+
+  // Before we enter a declarator's context, we need to make sure that
+  // it is a complete declaration context.
+  if (!DC->isDependentContext() && RequireCompleteDeclContext(SS))
+    return true;
+    
+  EnterDeclaratorContext(S, DC);
   return false;
 }
 
@@ -626,6 +629,7 @@
   assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
   if (SS.isInvalid())
     return;
-  if (computeDeclContext(SS, true))
-    ExitDeclaratorContext(S);
+  assert(!SS.isInvalid() && computeDeclContext(SS, true) &&
+         "exiting declarator scope we never really entered");
+  ExitDeclaratorContext(S);
 }

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=91771&r1=91770&r2=91771&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Dec 19 04:49:29 2009
@@ -321,23 +321,47 @@
 
 /// EnterDeclaratorContext - Used when we must lookup names in the context
 /// of a declarator's nested name specifier.
+///
 void Sema::EnterDeclaratorContext(Scope *S, DeclContext *DC) {
-  assert(PreDeclaratorDC == 0 && "Previous declarator context not popped?");
-  PreDeclaratorDC = static_cast<DeclContext*>(S->getEntity());
+  // C++0x [basic.lookup.unqual]p13:
+  //   A name used in the definition of a static data member of class
+  //   X (after the qualified-id of the static member) is looked up as
+  //   if the name was used in a member function of X.
+  // C++0x [basic.lookup.unqual]p14:
+  //   If a variable member of a namespace is defined outside of the
+  //   scope of its namespace then any name used in the definition of
+  //   the variable member (after the declarator-id) is looked up as
+  //   if the definition of the variable member occurred in its
+  //   namespace.
+  // Both of these imply that we should push a scope whose context
+  // is the semantic context of the declaration.  We can't use
+  // PushDeclContext here because that context is not necessarily
+  // lexically contained in the current context.  Fortunately,
+  // the containing scope should have the appropriate information.
+
+  assert(!S->getEntity() && "scope already has entity");
+
+#ifndef NDEBUG
+  Scope *Ancestor = S->getParent();
+  while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent();
+  assert(Ancestor->getEntity() == CurContext && "ancestor context mismatch");
+#endif
+
   CurContext = DC;
-  assert(CurContext && "No context?");
-  S->setEntity(CurContext);
+  S->setEntity(DC);
 }
 
 void Sema::ExitDeclaratorContext(Scope *S) {
-  S->setEntity(PreDeclaratorDC);
-  PreDeclaratorDC = 0;
+  assert(S->getEntity() == CurContext && "Context imbalance!");
 
-  // Reset CurContext to the nearest enclosing context.
-  while (!S->getEntity() && S->getParent())
-    S = S->getParent();
-  CurContext = static_cast<DeclContext*>(S->getEntity());
-  assert(CurContext && "No context?");
+  // Switch back to the lexical context.  The safety of this is
+  // enforced by an assert in EnterDeclaratorContext.
+  Scope *Ancestor = S->getParent();
+  while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent();
+  CurContext = (DeclContext*) Ancestor->getEntity();
+
+  // We don't need to do anything with the scope, which is going to
+  // disappear.
 }
 
 /// \brief Determine whether we allow overloading of the function

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=91771&r1=91770&r2=91771&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sat Dec 19 04:49:29 2009
@@ -2266,6 +2266,18 @@
   }
 }
 
+void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, DeclPtrTy RecordD) {
+  if (!RecordD) return;
+  AdjustDeclIfTemplate(RecordD);
+  CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordD.getAs<Decl>());
+  PushDeclContext(S, Record);
+}
+
+void Sema::ActOnFinishDelayedMemberDeclarations(Scope *S, DeclPtrTy RecordD) {
+  if (!RecordD) return;
+  PopDeclContext();
+}
+
 /// ActOnStartDelayedCXXMethodDeclaration - We have completed
 /// parsing a top-level (non-nested) C++ class, and we are now
 /// parsing those parts of the given Method declaration that could
@@ -2275,18 +2287,6 @@
 /// name. However, it should not bring the parameters into scope;
 /// that will be performed by ActOnDelayedCXXMethodParameter.
 void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) {
-  if (!MethodD)
-    return;
-
-  AdjustDeclIfTemplate(MethodD);
-
-  CXXScopeSpec SS;
-  FunctionDecl *Method = cast<FunctionDecl>(MethodD.getAs<Decl>());
-  QualType ClassTy
-    = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
-  SS.setScopeRep(
-    NestedNameSpecifier::Create(Context, 0, false, ClassTy.getTypePtr()));
-  ActOnCXXEnterDeclaratorScope(S, SS);
 }
 
 /// ActOnDelayedCXXMethodParameter - We've already started a delayed
@@ -2323,12 +2323,6 @@
   AdjustDeclIfTemplate(MethodD);
 
   FunctionDecl *Method = cast<FunctionDecl>(MethodD.getAs<Decl>());
-  CXXScopeSpec SS;
-  QualType ClassTy
-    = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
-  SS.setScopeRep(
-    NestedNameSpecifier::Create(Context, 0, false, ClassTy.getTypePtr()));
-  ActOnCXXExitDeclaratorScope(S, SS);
 
   // Now that we have our default arguments, check the constructor
   // again. It could produce additional diagnostics or affect whether
@@ -5544,31 +5538,7 @@
   // We should only get called for declarations with scope specifiers, like:
   //   int foo::bar;
   assert(D->isOutOfLine());
-
-  // C++0x [basic.lookup.unqual]p13:
-  //   A name used in the definition of a static data member of class
-  //   X (after the qualified-id of the static member) is looked up as
-  //   if the name was used in a member function of X.
-  // C++0x [basic.lookup.unqual]p14:
-  //   If a variable member of a namespace is defined outside of the
-  //   scope of its namespace then any name used in the definition of
-  //   the variable member (after the declarator-id) is looked up as
-  //   if the definition of the variable member occurred in its
-  //   namespace.
-  // Both of these imply that we should push a scope whose context
-  // is the semantic context of the declaration.  We can't use
-  // PushDeclContext here because that context is not necessarily
-  // lexically contained in the current context.  Fortunately,
-  // scopes should work.
-
-#ifndef NDEBUG
-  Scope *Ancestor = S->getParent();
-  while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent();
-  assert(Ancestor->getEntity() == CurContext && "ancestor context mismatch");
-#endif
-
-  CurContext = D->getDeclContext();
-  S->setEntity(CurContext);
+  EnterDeclaratorContext(S, D->getDeclContext());
 }
 
 /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
@@ -5579,11 +5549,7 @@
   if (D == 0) return;
 
   assert(D->isOutOfLine());
-  assert(S->getEntity() == D->getDeclContext() && "Context imbalance!");
-  
-  Scope *Ancestor = S->getParent();
-  while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent();
-  CurContext = (DeclContext*) Ancestor->getEntity();
+  ExitDeclaratorContext(S);
 }
 
 /// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a

Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p3.cpp?rev=91771&r1=91770&r2=91771&view=diff

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p3.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p3.cpp Sat Dec 19 04:49:29 2009
@@ -8,14 +8,12 @@
 // A definition of the class or class template containing a member function 
 // template shall be in scope at the point of the explicit instantiation of 
 // the member function template.
-struct X0; // expected-note 2{{forward declaration}}
-template<typename> struct X1; // expected-note 5{{declared here}}
+struct X0; // expected-note 3{{forward declaration}}
+template<typename> struct X1; // expected-note 8{{declared here}}
 
 // FIXME: Repeated diagnostics here!
-template void X0::f0<int>(int); // expected-error 2{{incomplete type}} \
-  // expected-error{{does not refer}}
-template void X1<int>::f0<int>(int); // expected-error 2{{implicit instantiation of undefined template}} \
-  // expected-error{{does not refer}}
+template void X0::f0<int>(int); // expected-error 3{{incomplete type}} // expected-error{{invalid token after top level declarator}}
+template void X1<int>::f0<int>(int); // expected-error 3{{implicit instantiation of undefined template}} // expected-error{{invalid token after top level declarator}}
 
 // A definition of a class template or class member template shall be in scope 
 // at the point of the explicit instantiation of the class template or class 
@@ -35,10 +33,10 @@
 // A definition of a class template shall be in scope at the point of an 
 // explicit instantiation of a member function or a static data member of the
 // class template.
-template void X1<int>::f1(int); // expected-error{{undefined template}} \
+template void X1<int>::f1(int); // expected-error 2{{undefined template}} \
                                 // expected-error{{does not refer}}
 
-template int X1<int>::member; // expected-error{{undefined template}} \
+template int X1<int>::member; // expected-error 2{{undefined template}} \
                               // expected-error{{does not refer}}
 
 // A definition of a member class of a class template shall be in scope at the 





More information about the cfe-commits mailing list