[cfe-commits] r91633 - in /cfe/trunk: lib/AST/DeclCXX.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaCXX/friend.cpp

John McCall rjmccall at apple.com
Thu Dec 17 15:21:11 PST 2009


Author: rjmccall
Date: Thu Dec 17 17:21:11 2009
New Revision: 91633

URL: http://llvm.org/viewvc/llvm-project?rev=91633&view=rev
Log:
Patch over yet more problems with friend declarations which were provoking
problems on LLVM-Code-Syntax.  This proved remarkably easy to "fix" once
I settled on how I was going to approach it.


Modified:
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/SemaCXX/friend.cpp

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=91633&r1=91632&r2=91633&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Thu Dec 17 17:21:11 2009
@@ -874,7 +874,11 @@
            isa<CXXRecordDecl>(D) ||
            isa<FunctionTemplateDecl>(D) ||
            isa<ClassTemplateDecl>(D));
-    assert(D->getFriendObjectKind());
+
+    // As a temporary hack, we permit template instantiation to point
+    // to the original declaration when instantiating members.
+    assert(D->getFriendObjectKind() ||
+           (cast<CXXRecordDecl>(DC)->getTemplateSpecializationKind()));
   }
 #endif
 

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Dec 17 17:21:11 2009
@@ -691,6 +691,26 @@
   if (Previous.begin() != Previous.end())
     PrevDecl = *Previous.begin();
 
+  // If there is a previous declaration with the same name, check
+  // whether this is a valid redeclaration.
+  ClassTemplateDecl *PrevClassTemplate
+    = dyn_cast_or_null<ClassTemplateDecl>(PrevDecl);
+
+  // We may have found the injected-class-name of a class template,
+  // class template partial specialization, or class template specialization. 
+  // In these cases, grab the template that is being defined or specialized.
+  if (!PrevClassTemplate && PrevDecl && isa<CXXRecordDecl>(PrevDecl) && 
+      cast<CXXRecordDecl>(PrevDecl)->isInjectedClassName()) {
+    PrevDecl = cast<CXXRecordDecl>(PrevDecl->getDeclContext());
+    PrevClassTemplate 
+      = cast<CXXRecordDecl>(PrevDecl)->getDescribedClassTemplate();
+    if (!PrevClassTemplate && isa<ClassTemplateSpecializationDecl>(PrevDecl)) {
+      PrevClassTemplate
+        = cast<ClassTemplateSpecializationDecl>(PrevDecl)
+            ->getSpecializedTemplate();
+    }
+  }
+
   if (PrevDecl && TUK == TUK_Friend) {
     // C++ [namespace.memdef]p3:
     //   [...] When looking for a prior declaration of a class or a function 
@@ -708,7 +728,7 @@
       // Declarations in outer scopes don't matter. However, the outermost
       // context we computed is the semantic context for our new 
       // declaration.
-      PrevDecl = 0;
+      PrevDecl = PrevClassTemplate = 0;
       SemanticContext = OutermostContext;
     }
     
@@ -717,30 +737,10 @@
       // class template to the template in scope, because that would perform
       // checking of the template parameter lists that can't be performed
       // until the outer context is instantiated.
-      PrevDecl = 0;
+      PrevDecl = PrevClassTemplate = 0;
     }
   } else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S))
-    PrevDecl = 0;
-
-  // If there is a previous declaration with the same name, check
-  // whether this is a valid redeclaration.
-  ClassTemplateDecl *PrevClassTemplate
-    = dyn_cast_or_null<ClassTemplateDecl>(PrevDecl);
-
-  // We may have found the injected-class-name of a class template,
-  // class template partial specialization, or class template specialization. 
-  // In these cases, grab the template that is being defined or specialized.
-  if (!PrevClassTemplate && PrevDecl && isa<CXXRecordDecl>(PrevDecl) && 
-      cast<CXXRecordDecl>(PrevDecl)->isInjectedClassName()) {
-    PrevDecl = cast<CXXRecordDecl>(PrevDecl->getDeclContext());
-    PrevClassTemplate 
-      = cast<CXXRecordDecl>(PrevDecl)->getDescribedClassTemplate();
-    if (!PrevClassTemplate && isa<ClassTemplateSpecializationDecl>(PrevDecl)) {
-      PrevClassTemplate
-        = cast<ClassTemplateSpecializationDecl>(PrevDecl)
-            ->getSpecializedTemplate();
-    }
-  }
+    PrevDecl = PrevClassTemplate = 0;
 
   if (PrevClassTemplate) {
     // Ensure that the template parameter lists are compatible.

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Dec 17 17:21:11 2009
@@ -396,7 +396,13 @@
     // FIXME: We have a problem here, because the nested call to Visit(ND)
     // will inject the thing that the friend references into the current
     // owner, which is wrong.
-    Decl *NewND = Visit(ND);
+    Decl *NewND;
+
+    // Hack to make this work almost well pending a rewrite.
+    if (ND->getDeclContext()->isRecord())
+      NewND = SemaRef.FindInstantiatedDecl(ND, TemplateArgs);
+    else
+      NewND = Visit(ND);
     if (!NewND) return 0;
 
     FU = cast<NamedDecl>(NewND);

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

==============================================================================
--- cfe/trunk/test/SemaCXX/friend.cpp (original)
+++ cfe/trunk/test/SemaCXX/friend.cpp Thu Dec 17 17:21:11 2009
@@ -15,3 +15,17 @@
     friend void ns::f(int a);
   };
 }
+
+// Test derived from LLVM's Registry.h
+namespace test1 {
+  template <class T> struct Outer {
+    void foo(T);
+    struct Inner {
+      friend void Outer::foo(T);
+    };
+  };
+
+  void test() {
+    (void) Outer<int>::Inner();
+  }
+}





More information about the cfe-commits mailing list