[cfe-commits] r91769 - in /cfe/trunk: lib/Parse/ParseDecl.cpp lib/Sema/SemaDeclCXX.cpp test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp test/SemaCXX/nested-name-spec.cpp test/SemaCXX/qual-id-test.cpp

John McCall rjmccall at apple.com
Sat Dec 19 01:28:59 PST 2009


Author: rjmccall
Date: Sat Dec 19 03:28:58 2009
New Revision: 91769

URL: http://llvm.org/viewvc/llvm-project?rev=91769&view=rev
Log:
Just push a new scope when parsing an out-of-line variable definition.
Magically fixes all the terrible lookup problems associated with not pushing
a new scope.  Resolves an ancient xfail and an LLVM misparse.


Modified:
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp
    cfe/trunk/test/SemaCXX/nested-name-spec.cpp
    cfe/trunk/test/SemaCXX/qual-id-test.cpp

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Sat Dec 19 03:28:58 2009
@@ -550,13 +550,17 @@
       SourceLocation DelLoc = ConsumeToken();
       Actions.SetDeclDeleted(ThisDecl, DelLoc);
     } else {
-      if (getLang().CPlusPlus)
+      if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
+        EnterScope(0);
         Actions.ActOnCXXEnterDeclInitializer(CurScope, ThisDecl);
+      }
 
       OwningExprResult Init(ParseInitializer());
 
-      if (getLang().CPlusPlus)
+      if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
         Actions.ActOnCXXExitDeclInitializer(CurScope, ThisDecl);
+        ExitScope();
+      }
 
       if (Init.isInvalid()) {
         SkipUntil(tok::semi, true, true);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sat Dec 19 03:28:58 2009
@@ -5529,51 +5529,61 @@
   return true;
 }
 
-/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an
-/// initializer for the declaration 'Dcl'.
+/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse
+/// an initializer for the out-of-line declaration 'Dcl'.  The scope
+/// is a fresh scope pushed for just this purpose.
+///
 /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
 /// static data member of class X, names should be looked up in the scope of
 /// class X.
 void Sema::ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) {
-  AdjustDeclIfTemplate(Dcl);
-
-  Decl *D = Dcl.getAs<Decl>();
   // If there is no declaration, there was an error parsing it.
-  if (D == 0)
-    return;
-
-  // Check whether it is a declaration with a nested name specifier like
-  // int foo::bar;
-  if (!D->isOutOfLine())
-    return;
+  Decl *D = Dcl.getAs<Decl>();
+  if (D == 0) return;
 
-  // C++ [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.
+  // 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
 
-  // Change current context into the context of the initializing declaration.
-  EnterDeclaratorContext(S, D->getDeclContext());
+  CurContext = D->getDeclContext();
+  S->setEntity(CurContext);
 }
 
 /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
-/// initializer for the declaration 'Dcl'.
+/// initializer for the out-of-line declaration 'Dcl'.
 void Sema::ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) {
-  AdjustDeclIfTemplate(Dcl);
-
-  Decl *D = Dcl.getAs<Decl>();
   // If there is no declaration, there was an error parsing it.
-  if (D == 0)
-    return;
-
-  // Check whether it is a declaration with a nested name specifier like
-  // int foo::bar;
-  if (!D->isOutOfLine())
-    return;
+  Decl *D = Dcl.getAs<Decl>();
+  if (D == 0) return;
 
+  assert(D->isOutOfLine());
   assert(S->getEntity() == D->getDeclContext() && "Context imbalance!");
-  ExitDeclaratorContext(S);
+  
+  Scope *Ancestor = S->getParent();
+  while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent();
+  CurContext = (DeclContext*) Ancestor->getEntity();
 }
 
 /// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a

Modified: cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp?rev=91769&r1=91768&r2=91769&view=diff

==============================================================================
--- cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp (original)
+++ cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.unqual/p14.cpp Sat Dec 19 03:28:58 2009
@@ -1,5 +1,10 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
-// XFAIL: *
+
+// 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.
 
 namespace N { 
   struct S {};

Modified: cfe/trunk/test/SemaCXX/nested-name-spec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/nested-name-spec.cpp?rev=91769&r1=91768&r2=91769&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/nested-name-spec.cpp (original)
+++ cfe/trunk/test/SemaCXX/nested-name-spec.cpp Sat Dec 19 03:28:58 2009
@@ -207,3 +207,16 @@
     }
   };
 }
+
+// We still need to do lookup in the lexical scope, even if we push a
+// non-lexical scope.
+namespace test2 {
+  namespace ns {
+    int *count_ptr;
+  }
+  namespace {
+    int count = 0;
+  }
+
+  int *ns::count_ptr = &count;
+}

Modified: cfe/trunk/test/SemaCXX/qual-id-test.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/qual-id-test.cpp?rev=91769&r1=91768&r2=91769&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/qual-id-test.cpp (original)
+++ cfe/trunk/test/SemaCXX/qual-id-test.cpp Sat Dec 19 03:28:58 2009
@@ -137,4 +137,4 @@
 
 a a;
 
-int a::sa = a.a;
+int a::sa = a.a; // expected-error {{invalid use of nonstatic data member 'a'}}





More information about the cfe-commits mailing list