[cfe-commits] r82950 - in /cfe/trunk: lib/Sema/SemaDeclCXX.cpp test/SemaTemplate/friend-template.cpp

Douglas Gregor dgregor at apple.com
Sun Sep 27 17:08:27 PDT 2009


Author: dgregor
Date: Sun Sep 27 19:08:27 2009
New Revision: 82950

URL: http://llvm.org/viewvc/llvm-project?rev=82950&view=rev
Log:
Improve handling of friend function templates somewhat

Modified:
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/SemaTemplate/friend-template.cpp

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun Sep 27 19:08:27 2009
@@ -4220,9 +4220,6 @@
   DeclarationName Name = GetNameForDeclarator(D);
   assert(Name);
 
-  // The existing declaration we found.
-  FunctionDecl *FD = NULL;
-
   // The context we found the declaration in, or in which we should
   // create the declaration.
   DeclContext *DC;
@@ -4230,19 +4227,20 @@
   // FIXME: handle local classes
 
   // Recover from invalid scope qualifiers as if they just weren't there.
+  NamedDecl *PrevDecl = 0;
   if (!ScopeQual.isInvalid() && ScopeQual.isSet()) {
     DC = computeDeclContext(ScopeQual);
 
     // FIXME: handle dependent contexts
     if (!DC) return DeclPtrTy();
 
-    Decl *Dec = LookupQualifiedNameWithType(DC, Name, T);
+    PrevDecl = LookupQualifiedName(DC, Name, LookupOrdinaryName, true);
 
     // If searching in that context implicitly found a declaration in
     // a different context, treat it like it wasn't found at all.
     // TODO: better diagnostics for this case.  Suggesting the right
     // qualified scope would be nice...
-    if (!Dec || Dec->getDeclContext() != DC) {
+    if (!PrevDecl || !PrevDecl->getDeclContext()->Equals(DC)) {
       D.setInvalidType();
       Diag(Loc, diag::err_qualified_friend_not_found) << Name << T;
       return DeclPtrTy();
@@ -4250,11 +4248,9 @@
 
     // C++ [class.friend]p1: A friend of a class is a function or
     //   class that is not a member of the class . . .
-    if (DC == CurContext)
+    if (DC->Equals(CurContext))
       Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member);
 
-    FD = cast<FunctionDecl>(Dec);
-
   // Otherwise walk out to the nearest namespace scope looking for matches.
   } else {
     // TODO: handle local class contexts.
@@ -4268,15 +4264,15 @@
       // declarations should stop at the nearest enclosing namespace,
       // not that they should only consider the nearest enclosing
       // namespace.
-      while (DC->isRecord()) DC = DC->getParent();
+      while (DC->isRecord()) 
+        DC = DC->getParent();
 
-      Decl *Dec = LookupQualifiedNameWithType(DC, Name, T);
+      PrevDecl = LookupQualifiedName(DC, Name, LookupOrdinaryName, true);
 
       // TODO: decide what we think about using declarations.
-      if (Dec) {
-        FD = cast<FunctionDecl>(Dec);
+      if (PrevDecl)
         break;
-      }
+      
       if (DC->isFileContext()) break;
       DC = DC->getParent();
     }
@@ -4286,24 +4282,11 @@
     // C++0x changes this for both friend types and functions.
     // Most C++ 98 compilers do seem to give an error here, so
     // we do, too.
-    if (FD && DC == CurContext && !getLangOptions().CPlusPlus0x)
+    if (PrevDecl && DC->Equals(CurContext) && !getLangOptions().CPlusPlus0x)
       Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member);
   }
 
-  bool Redeclaration = (FD != 0);
-
-  // If we found a match, create a friend function declaration with
-  // that function as the previous declaration.
-  if (Redeclaration) {
-    // Create it in the semantic context of the original declaration.
-    DC = FD->getDeclContext();
-
-  // If we didn't find something matching the type exactly, create
-  // a declaration.  This declaration should only be findable via
-  // argument-dependent lookup.
-  } else {
-    assert(DC->isFileContext());
-
+  if (DC->isFileContext()) {
     // This implies that it has to be an operator or function.
     if (D.getKind() == Declarator::DK_Constructor ||
         D.getKind() == Declarator::DK_Destructor ||
@@ -4315,20 +4298,15 @@
     }
   }
 
-  NamedDecl *ND = ActOnFunctionDeclarator(S, D, DC, T, DInfo,
-                                          /* PrevDecl = */ FD,
+  bool Redeclaration = false;
+  NamedDecl *ND = ActOnFunctionDeclarator(S, D, DC, T, DInfo, PrevDecl,
                                           MultiTemplateParamsArg(*this),
                                           IsDefinition,
                                           Redeclaration);
   if (!ND) return DeclPtrTy();
 
-  assert(cast<FunctionDecl>(ND)->getPreviousDeclaration() == FD &&
-         "lost reference to previous declaration");
-
-  FD = cast<FunctionDecl>(ND);
-
-  assert(FD->getDeclContext() == DC);
-  assert(FD->getLexicalDeclContext() == CurContext);
+  assert(ND->getDeclContext() == DC);
+  assert(ND->getLexicalDeclContext() == CurContext);
 
   // Add the function declaration to the appropriate lookup tables,
   // adjusting the redeclarations list as necessary.  We don't
@@ -4338,18 +4316,18 @@
   // lookup context is in lexical scope.
   if (!CurContext->isDependentContext()) {
     DC = DC->getLookupContext();
-    DC->makeDeclVisibleInContext(FD, /* Recoverable=*/ false);
+    DC->makeDeclVisibleInContext(ND, /* Recoverable=*/ false);
     if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
-      PushOnScopeChains(FD, EnclosingScope, /*AddToContext=*/ false);
+      PushOnScopeChains(ND, EnclosingScope, /*AddToContext=*/ false);
   }
 
   FriendDecl *FrD = FriendDecl::Create(Context, CurContext,
-                                       D.getIdentifierLoc(), FD,
+                                       D.getIdentifierLoc(), ND,
                                        DS.getFriendSpecLoc());
   FrD->setAccess(AS_public);
   CurContext->addDecl(FrD);
 
-  return DeclPtrTy::make(FD);
+  return DeclPtrTy::make(ND);
 }
 
 void Sema::SetDeclDeleted(DeclPtrTy dcl, SourceLocation DelLoc) {

Modified: cfe/trunk/test/SemaTemplate/friend-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/friend-template.cpp?rev=82950&r1=82949&r2=82950&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/friend-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/friend-template.cpp Sun Sep 27 19:08:27 2009
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only %s
+// RUN: clang-cc -fsyntax-only -verify %s
 
 // PR5057
 namespace std {
@@ -15,3 +15,16 @@
   {
   };
 }
+
+
+namespace N {
+  template<typename T> void f1(T) { } // expected-note{{here}}
+
+  class X {
+    template<typename T> friend void f0(T);
+    template<typename T> friend void f1(T);
+  };
+
+  template<typename T> void f0(T) { }
+  template<typename T> void f1(T) { } // expected-error{{redefinition}}
+}





More information about the cfe-commits mailing list