Hi rsmith,

This affects this test case:
  void foo();
  template <typename T> class C {
    friend void foo();
  };
  inline void foo() {}
  C<int> c;

Here, we instantiate the foo friend decl and add it to foo's redecl
chain. However, our previous decl pointer happens to reference the first
declaration of foo, which is not marked inline. When we check to see if
foo was already defined, we implicitly search all previous decls. We
should do the same for the inline check, instead of just checking this
particular previous decl.

http://reviews.llvm.org/D8872

Files:
  lib/Sema/SemaDeclCXX.cpp
  test/SemaTemplate/friend.cpp

Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -615,7 +615,8 @@
       << New << New->isConstexpr();
     Diag(Old->getLocation(), diag::note_previous_declaration);
     Invalid = true;
-  } else if (!Old->isInlined() && New->isInlined() && Old->isDefined(Def)) {
+  } else if (!Old->getMostRecentDecl()->isInlined() && New->isInlined() &&
+             Old->isDefined(Def)) {
     // C++11 [dcl.fcn.spec]p4:
     //   If the definition of a function appears in a translation unit before 
its
     //   first declaration as inline, the program is ill-formed.
Index: test/SemaTemplate/friend.cpp
===================================================================
--- test/SemaTemplate/friend.cpp
+++ test/SemaTemplate/friend.cpp
@@ -31,3 +31,16 @@
     friend class f1; // expected-error{{'friend' used outside of class}}
   }
 }
+
+namespace friend_redecl_inline {
+// We had a bug where instantiating the foo friend declaration would check the
+// defined-ness of the most recent decl while checking if the canonical decl 
was
+// inlined.
+void foo();
+template <typename T>
+class C {
+  friend void foo();
+};
+inline void foo() {}
+C<int> c;
+}

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -615,7 +615,8 @@
       << New << New->isConstexpr();
     Diag(Old->getLocation(), diag::note_previous_declaration);
     Invalid = true;
-  } else if (!Old->isInlined() && New->isInlined() && Old->isDefined(Def)) {
+  } else if (!Old->getMostRecentDecl()->isInlined() && New->isInlined() &&
+             Old->isDefined(Def)) {
     // C++11 [dcl.fcn.spec]p4:
     //   If the definition of a function appears in a translation unit before its
     //   first declaration as inline, the program is ill-formed.
Index: test/SemaTemplate/friend.cpp
===================================================================
--- test/SemaTemplate/friend.cpp
+++ test/SemaTemplate/friend.cpp
@@ -31,3 +31,16 @@
     friend class f1; // expected-error{{'friend' used outside of class}}
   }
 }
+
+namespace friend_redecl_inline {
+// We had a bug where instantiating the foo friend declaration would check the
+// defined-ness of the most recent decl while checking if the canonical decl was
+// inlined.
+void foo();
+template <typename T>
+class C {
+  friend void foo();
+};
+inline void foo() {}
+C<int> c;
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to