[cfe-commits] r91146 - in /cfe/trunk: include/clang/Parse/Action.h lib/Parse/ParseDecl.cpp lib/Sema/Sema.h lib/Sema/SemaCXXScopeSpec.cpp test/SemaCXX/friend.cpp

John McCall rjmccall at apple.com
Fri Dec 11 12:04:54 PST 2009


Author: rjmccall
Date: Fri Dec 11 14:04:54 2009
New Revision: 91146

URL: http://llvm.org/viewvc/llvm-project?rev=91146&view=rev
Log:
Don't enter a new scope for a namespace-qualified declarator unless we're
in a file context.  In well-formed code, only happens with friend functions.
Fixes PR 5760.


Modified:
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp
    cfe/trunk/test/SemaCXX/friend.cpp

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

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Fri Dec 11 14:04:54 2009
@@ -365,8 +365,19 @@
     return 0;
   }
 
+  /// ShouldEnterDeclaratorScope - Called when a C++ scope specifier
+  /// is parsed as part of a declarator-id to determine whether a scope
+  /// should be entered.
+  ///
+  /// \param S the current scope
+  /// \param SS the scope being entered
+  /// \param isFriendDeclaration whether this is a friend declaration
+  virtual bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
+    return false;
+  }
+
   /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
-  /// scope or nested-name-specifier) is parsed, part of a declarator-id.
+  /// scope or nested-name-specifier) is parsed as part of a declarator-id.
   /// After this method is called, according to [C++ 3.4.3p3], names should be
   /// looked up in the declarator-id's scope, until the declarator is parsed and
   /// ActOnCXXExitDeclaratorScope is called.

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Fri Dec 11 14:04:54 2009
@@ -2335,9 +2335,10 @@
       ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0,
                                      true);
     if (afterCXXScope) {
-      // Change the declaration context for name lookup, until this function
-      // is exited (and the declarator has been parsed).
-      DeclScopeObj.EnterDeclaratorScope();
+      if (Actions.ShouldEnterDeclaratorScope(CurScope, D.getCXXScopeSpec()))
+        // Change the declaration context for name lookup, until this function
+        // is exited (and the declarator has been parsed).
+        DeclScopeObj.EnterDeclaratorScope();
     } 
     
     if (Tok.is(tok::identifier) || Tok.is(tok::kw_operator) ||

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Dec 11 14:04:54 2009
@@ -2048,6 +2048,8 @@
                                                   SourceRange TypeRange,
                                                   SourceLocation CCLoc);
 
+  virtual bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS);
+
   /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
   /// scope or nested-name-specifier) is parsed, part of a declarator-id.
   /// After this method is called, according to [C++ 3.4.3p3], names should be

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Fri Dec 11 14:04:54 2009
@@ -559,6 +559,44 @@
                                      T.getTypePtr());
 }
 
+bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
+  assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
+
+  NestedNameSpecifier *Qualifier =
+    static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+
+  // There are only two places a well-formed program may qualify a
+  // declarator: first, when defining a namespace or class member
+  // out-of-line, and second, when naming an explicitly-qualified
+  // friend function.  The latter case is governed by
+  // C++03 [basic.lookup.unqual]p10:
+  //   In a friend declaration naming a member function, a name used
+  //   in the function declarator and not part of a template-argument
+  //   in a template-id is first looked up in the scope of the member
+  //   function's class. If it is not found, or if the name is part of
+  //   a template-argument in a template-id, the look up is as
+  //   described for unqualified names in the definition of the class
+  //   granting friendship.
+  // i.e. we don't push a scope unless it's a class member.
+
+  switch (Qualifier->getKind()) {
+  case NestedNameSpecifier::Global:
+  case NestedNameSpecifier::Namespace:
+    // These are always namespace scopes.  We never want to enter a
+    // namespace scope from anything but a file context.
+    return CurContext->getLookupContext()->isFileContext();
+
+  case NestedNameSpecifier::Identifier:
+  case NestedNameSpecifier::TypeSpec:
+  case NestedNameSpecifier::TypeSpecWithTemplate:
+    // These are never namespace scopes.
+    return true;
+  }
+
+  // Silence bogus warning.
+  return false;
+}
+
 /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
 /// scope or nested-name-specifier) is parsed, part of a declarator-id.
 /// After this method is called, according to [C++ 3.4.3p3], names should be

Modified: cfe/trunk/test/SemaCXX/friend.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/friend.cpp?rev=91146&r1=91145&r2=91146&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/friend.cpp (original)
+++ cfe/trunk/test/SemaCXX/friend.cpp Fri Dec 11 14:04:54 2009
@@ -4,3 +4,14 @@
 void f() { friend class A; } // expected-error {{'friend' used outside of class}}
 class C { friend class A; };
 class D { void f() { friend class A; } }; // expected-error {{'friend' used outside of class}}
+
+// PR5760
+namespace test0 {
+  namespace ns {
+    void f(int);
+  }
+
+  struct A {
+    friend void ns::f(int a);
+  };
+}





More information about the cfe-commits mailing list