]> granicus.if.org Git - clang/commitdiff
When we're checking a friend function template in an out-of-line class
authorDouglas Gregor <dgregor@apple.com>
Thu, 3 Nov 2011 16:37:14 +0000 (16:37 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 3 Nov 2011 16:37:14 +0000 (16:37 +0000)
definition, we may not have a scope corresponding to the namespace
where that friend function template actually lives. Work around this
issue by faking up a scope with the appropriate DeclContext.

This is a bit of a hack, but it fixes <rdar://problem/10204947>.

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

lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaTemplate.cpp
test/SemaCXX/friend-out-of-line.cpp [new file with mode: 0644]

index 7a423a73f05c66da661690f8e9b0b4cdea3ac1ec..a4e25231a73e5ce3339d3dbca6244057d1f3f198 100644 (file)
@@ -10050,7 +10050,7 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
              diag::err_friend_is_member);
 
     DCScope = getScopeForDeclContext(S, DC);
-
+    
     // C++ [class.friend]p6:
     //   A function can be defined in a friend declaration of a class if and 
     //   only if the class is a non-local class (9.8), the function name is
@@ -10142,6 +10142,15 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
     }
   }
 
+  // FIXME: This is an egregious hack to cope with cases where the scope stack
+  // does not contain the declaration context, i.e., in an out-of-line 
+  // definition of a class.
+  Scope FakeDCScope(S, Scope::DeclScope, Diags);
+  if (!DCScope) {
+    FakeDCScope.setEntity(DC);
+    DCScope = &FakeDCScope;
+  }
+  
   bool AddToScope = true;
   NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, TInfo, Previous,
                                           move(TemplateParams), AddToScope);
index 9c14976f0ae8f365604ed3f90e4763d406dba3b6..2d7e85094aa27de0037760f2f9785422c8f6a77a 100644 (file)
@@ -4455,6 +4455,9 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
 /// false. Otherwise, issues a diagnostic and returns true.
 bool
 Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) {
+  if (!S)
+    return false;
+
   // Find the nearest enclosing declaration scope.
   while ((S->getFlags() & Scope::DeclScope) == 0 ||
          (S->getFlags() & Scope::TemplateParamScope) != 0)
diff --git a/test/SemaCXX/friend-out-of-line.cpp b/test/SemaCXX/friend-out-of-line.cpp
new file mode 100644 (file)
index 0000000..56b2daa
--- /dev/null
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// <rdar://problem/10204947>
+namespace N {
+  class X;
+};
+
+class N::X {
+  template<typename T> friend const T& f(const X&);
+  friend const int& g(const X&);
+  friend class Y;
+};