[cfe-commits] r112524 - in /cfe/trunk: lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaTemplate/inject-templated-friend-post.cpp

Gabor Greif ggreif at gmail.com
Mon Aug 30 14:10:05 PDT 2010


Author: ggreif
Date: Mon Aug 30 16:10:05 2010
New Revision: 112524

URL: http://llvm.org/viewvc/llvm-project?rev=112524&view=rev
Log:
fix dual aspect of PR8007,
namely when the friend function prototype is already used
at the point of the template definition that is supposed
to inject the friend function. Testcase verifies four
scenarios.
I would like receive some code review for this.

Modified:
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/SemaTemplate/inject-templated-friend-post.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=112524&r1=112523&r2=112524&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Aug 30 16:10:05 2010
@@ -1166,7 +1166,9 @@
 
     PrincipalDecl->setObjectOfFriendDecl(PrevDecl != 0);
     DC->makeDeclVisibleInContext(PrincipalDecl, /*Recoverable=*/ false);
-    
+
+		bool queuedInstantiation = false;
+
     if (!SemaRef.getLangOptions().CPlusPlus0x &&
         D->isThisDeclarationADefinition()) {
       // Check for a function body.
@@ -1185,7 +1187,22 @@
                 R != REnd; ++R) {
         if (*R == Function)
           continue;
-        if (R->getFriendObjectKind() != Decl::FOK_None) {
+        switch (R->getFriendObjectKind()) {
+        case Decl::FOK_None:
+          if (!queuedInstantiation && R->isUsed(false)) {
+            if (MemberSpecializationInfo *MSInfo
+                = Function->getMemberSpecializationInfo()) {
+              if (MSInfo->getPointOfInstantiation().isInvalid()) {
+                SourceLocation Loc = R->getLocation(); // FIXME
+                MSInfo->setPointOfInstantiation(Loc);
+                SemaRef.PendingLocalImplicitInstantiations.push_back(
+                                                 std::make_pair(Function, Loc));
+                queuedInstantiation = true;
+              }
+            }
+          }
+          break;
+        default:
           if (const FunctionDecl *RPattern
               = R->getTemplateInstantiationPattern())
             if (RPattern->hasBody(RPattern)) {
@@ -1198,7 +1215,6 @@
         }
       }
     }
-      
   }
 
   if (Function->isOverloadedOperator() && !DC->isRecord() &&

Modified: cfe/trunk/test/SemaTemplate/inject-templated-friend-post.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/inject-templated-friend-post.cpp?rev=112524&r1=112523&r2=112524&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/inject-templated-friend-post.cpp (original)
+++ cfe/trunk/test/SemaTemplate/inject-templated-friend-post.cpp Mon Aug 30 16:10:05 2010
@@ -1,8 +1,9 @@
 // RUN: %clang %s -S -emit-llvm -o - | grep -e "define linkonce_odr.*_ZlsR11std_ostreamRK8StreamerI3FooE"
+// RUN: %clang %s -S -emit-llvm -o - -DPROTOTYPE | grep -e "define linkonce_odr.*_ZlsR11std_ostreamRK8StreamerI3FooE"
 // RUN: %clang -cc1 %s -DREDEFINE -verify
+// RUN: %clang -cc1 %s -DPROTOTYPE -DREDEFINE -verify
 // PR8007: friend function not instantiated, reordered version.
 // Corresponds to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38392
-// XFAIL: *
 
 struct std_ostream
 {
@@ -17,6 +18,7 @@
 typedef struct Foo {} Foo;
 
 std_ostream& operator << (std_ostream&, const Streamer<Foo>&);
+
 void test(const Streamer<Foo>& foo)
 {
     cout << foo;
@@ -38,6 +40,21 @@
     void operator () (std_ostream&) const;
 };
 
+#ifdef PROTOTYPE
+std_ostream& operator << (std_ostream&, const Streamer<Foo>&);
+#endif
+
+#ifdef INSTANTIATE
+template struct Streamer<Foo>;
+#endif
+
+#ifdef REDEFINE
+std_ostream& operator << (std_ostream& o, const Streamer<Foo>&) // expected-note{{is here}}
+{
+  return o;
+}
+#endif
+
 template <>
 void Streamer<Foo>::operator () (std_ostream& o) const // expected-note{{requested here}}
 {
@@ -49,10 +66,3 @@
     test(foo);
 }
 
-#ifdef REDEFINE
-std_ostream& operator << (std_ostream& o, const Streamer<Foo>&) // expected-note{{is here}}
-{
-  // Sema should flag this as a redefinition
-  return o;
-}
-#endif





More information about the cfe-commits mailing list