[cfe-commits] r159895 - in /cfe/trunk: lib/Sema/SemaDeclCXX.cpp test/CodeGenCXX/virt-template-vtable.cpp test/SemaTemplate/instantiate-exception-spec-cxx11.cpp

Richard Smith richard-llvm at metafoo.co.uk
Fri Jul 6 23:59:51 PDT 2012


Author: rsmith
Date: Sat Jul  7 01:59:51 2012
New Revision: 159895

URL: http://llvm.org/viewvc/llvm-project?rev=159895&view=rev
Log:
When marking virtual functions as used for a class' vtable, mark all functions
which will appear in the vtable as used, not just those ones which were
declared within the class itself. Fixes an issue reported as comment#3 in
PR12763 -- we sometimes assert in codegen if we try to emit a reference to a
function declaration which we've not marked as referenced. This also matches
gcc's observed behavior.

Modified:
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/CodeGenCXX/virt-template-vtable.cpp
    cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=159895&r1=159894&r2=159895&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sat Jul  7 01:59:51 2012
@@ -10795,14 +10795,23 @@
 
 void Sema::MarkVirtualMembersReferenced(SourceLocation Loc,
                                         const CXXRecordDecl *RD) {
-  for (CXXRecordDecl::method_iterator i = RD->method_begin(), 
-       e = RD->method_end(); i != e; ++i) {
-    CXXMethodDecl *MD = *i;
-
-    // C++ [basic.def.odr]p2:
-    //   [...] A virtual member function is used if it is not pure. [...]
-    if (MD->isVirtual() && !MD->isPure())
-      MarkFunctionReferenced(Loc, MD);
+  // Mark all functions which will appear in RD's vtable as used.
+  CXXFinalOverriderMap FinalOverriders;
+  RD->getFinalOverriders(FinalOverriders);
+  for (CXXFinalOverriderMap::const_iterator I = FinalOverriders.begin(),
+                                            E = FinalOverriders.end();
+       I != E; ++I) {
+    for (OverridingMethods::const_iterator OI = I->second.begin(),
+                                           OE = I->second.end();
+         OI != OE; ++OI) {
+      assert(OI->second.size() > 0 && "no final overrider");
+      CXXMethodDecl *Overrider = OI->second.front().Method;
+
+      // C++ [basic.def.odr]p2:
+      //   [...] A virtual member function is used if it is not pure. [...]
+      if (!Overrider->isPure())
+        MarkFunctionReferenced(Loc, Overrider);
+    }
   }
 
   // Only classes that have virtual bases need a VTT.

Modified: cfe/trunk/test/CodeGenCXX/virt-template-vtable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/virt-template-vtable.cpp?rev=159895&r1=159894&r2=159895&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/virt-template-vtable.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/virt-template-vtable.cpp Sat Jul  7 01:59:51 2012
@@ -20,3 +20,13 @@
 // CHECK: @_ZTV1AIlE = weak_odr unnamed_addr constant
 // CHECK: @_ZTV1AIsE = weak_odr unnamed_addr constant
 // CHECK: @_ZTV1AIiE = linkonce_odr unnamed_addr constant
+
+template<class T> struct C {
+  virtual void c() {}
+};
+struct D : C<int> {
+  virtual void d();
+};
+void D::d() {}
+
+// CHECK: define {{.*}}@_ZN1CIiE1cEv(

Modified: cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp?rev=159895&r1=159894&r2=159895&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp Sat Jul  7 01:59:51 2012
@@ -131,3 +131,17 @@
 
 Derived<Exc1> d1; // ok
 Derived<Exc2> d2; // expected-note {{in instantiation of}}
+
+// If the vtable for a derived class is used, the exception specification of
+// any member function which ends up in that vtable is needed, even if it was
+// declared in a base class.
+namespace PR12763 {
+  template<bool *B> struct T {
+    virtual void f() noexcept (*B); // expected-error {{constant expression}} expected-note {{read of non-const}}
+  };
+  bool b; // expected-note {{here}}
+  struct X : public T<&b> {
+    virtual void g();
+  };
+  void X::g() {} // expected-note {{in instantiation of}}
+}





More information about the cfe-commits mailing list