]> granicus.if.org Git - clang/commitdiff
[modules] When emitting an update record containing the body of a destructor,
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 7 Aug 2014 18:53:08 +0000 (18:53 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 7 Aug 2014 18:53:08 +0000 (18:53 +0000)
also emit the updated 'operator delete' looked up for that destructor. Switch
from UpdateDecl to an actual update record when this happens due to implicitly
defining a special member function and unify this code path and the one for
instantiating a function definition.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@215132 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Serialization/ASTCommon.h
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTWriter.cpp
test/Modules/Inputs/cxx-irgen-left.h
test/Modules/Inputs/cxx-irgen-top.h
test/Modules/cxx-irgen.cpp

index c7669749260bf62d3d0eecd4ae88ae56b366305b..6090a13439ddcc839a7866503a57684c491fecc9 100644 (file)
@@ -25,8 +25,8 @@ enum DeclUpdateKind {
   UPD_CXX_ADDED_IMPLICIT_MEMBER,
   UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
   UPD_CXX_ADDED_ANONYMOUS_NAMESPACE,
+  UPD_CXX_ADDED_FUNCTION_DEFINITION,
   UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
-  UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION,
   UPD_CXX_INSTANTIATED_CLASS_DEFINITION,
   UPD_CXX_RESOLVED_EXCEPTION_SPEC,
   UPD_CXX_DEDUCED_RETURN_TYPE,
index 441427cc5687edf968f514e9f0fbc23a9e0782f6..078e9c86f2ee9599c957a04a7a34a4f4990f3b6f 100644 (file)
@@ -3273,7 +3273,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
           Reader.ReadSourceLocation(ModuleFile, Record, Idx));
       break;
 
-    case UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION: {
+    case UPD_CXX_ADDED_FUNCTION_DEFINITION: {
       FunctionDecl *FD = cast<FunctionDecl>(D);
       if (Reader.PendingBodies[FD]) {
         // FIXME: Maybe check for ODR violations.
@@ -3296,6 +3296,10 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile,
       if (auto *CD = dyn_cast<CXXConstructorDecl>(FD))
         std::tie(CD->CtorInitializers, CD->NumCtorInitializers) =
             Reader.ReadCXXCtorInitializers(ModuleFile, Record, Idx);
+      if (auto *DD = dyn_cast<CXXDestructorDecl>(FD))
+        // FIXME: Check consistency.
+        DD->setOperatorDelete(Reader.ReadDeclAs<FunctionDecl>(ModuleFile,
+                                                              Record, Idx));
       // Store the offset of the body so we can lazily load it later.
       Reader.PendingBodies[FD] = GetCurrentCursorOffset();
       HasPendingBody = true;
index 8de1fca05f4e6f32e344f0163a7470bf25bd4fb2..baed95ebf84513b0afc0ba0ab2dc5b02aaf8aa11 100644 (file)
@@ -4629,17 +4629,17 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
         Record.push_back(GetDeclRef(Update.getDecl()));
         break;
 
-      case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER:
-        AddSourceLocation(Update.getLoc(), Record);
-        break;
-
-      case UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION:
+      case UPD_CXX_ADDED_FUNCTION_DEFINITION:
         // An updated body is emitted last, so that the reader doesn't need
         // to skip over the lazy body to reach statements for other records.
         Record.pop_back();
         HasUpdatedBody = true;
         break;
 
+      case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER:
+        AddSourceLocation(Update.getLoc(), Record);
+        break;
+
       case UPD_CXX_INSTANTIATED_CLASS_DEFINITION: {
         auto *RD = cast<CXXRecordDecl>(D);
         AddUpdatedDeclContext(RD->getPrimaryContext());
@@ -4709,10 +4709,12 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
 
     if (HasUpdatedBody) {
       const FunctionDecl *Def = cast<FunctionDecl>(D);
-      Record.push_back(UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION);
+      Record.push_back(UPD_CXX_ADDED_FUNCTION_DEFINITION);
       Record.push_back(Def->isInlined());
       AddSourceLocation(Def->getInnerLocStart(), Record);
       AddFunctionDefinition(Def, Record);
+      if (auto *DD = dyn_cast<CXXDestructorDecl>(Def))
+        Record.push_back(GetDeclRef(DD->getOperatorDelete()));
     }
 
     OffsetsRecord.push_back(GetDeclRef(D));
@@ -5704,9 +5706,8 @@ void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) {
   if (!D->isFromASTFile())
     return; // Declaration not imported from PCH.
 
-  // Implicit decl from a PCH was defined.
-  // FIXME: Should implicit definition be a separate FunctionDecl?
-  RewriteDecl(D);
+  // Implicit function decl from a PCH was defined.
+  DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION));
 }
 
 void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) {
@@ -5714,10 +5715,8 @@ void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) {
   if (!D->isFromASTFile())
     return;
 
-  // Since the actual instantiation is delayed, this really means that we need
-  // to update the instantiation location.
   DeclUpdates[D].push_back(
-      DeclUpdate(UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION));
+      DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION));
 }
 
 void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) {
index fb36b218a49d59d194bb0c35d512dc5334883960..31ae805c9a19bff60610dc60fb19b906d5cbfa1f 100644 (file)
@@ -18,3 +18,9 @@ namespace ImplicitSpecialMembers {
     C c2(c); D d2(d);
   }
 }
+
+namespace OperatorDeleteLookup {
+  // Trigger definition of A::~A() and lookup of operator delete.
+  // Likewise for B<int>::~B().
+  inline void f() { A a; B<int> b; }
+}
index 0ab586f7ae16bc9bc5ff2b19619374c291282278..43c0b18c775f947697086ae3dca4a49d925b9610 100644 (file)
@@ -32,3 +32,9 @@ namespace ImplicitSpecialMembers {
     D(int);
   };
 }
+
+namespace OperatorDeleteLookup {
+  struct A { void operator delete(void*); virtual ~A() = default; };
+  template<typename T> struct B { void operator delete(void*); virtual ~B() {} typedef int t; };
+  typedef B<int>::t b_int_instantated;
+}
index 9fb38cedacf144a10bd7e2b9d386b6ea1092fb13..7bb128716221ea80d50dbb744f2643468ab9ac9b 100644 (file)
@@ -18,6 +18,9 @@ int b = h();
 // CHECK-DAG: define linkonce_odr {{signext i32|i32}} @_Z3minIiET_S0_S0_(i32
 int c = min(1, 2);
 
+// CHECK-LABEL: define {{.*}} @_ZN20OperatorDeleteLookup1AD0Ev(
+// CHECK: call void @_ZN20OperatorDeleteLookup1AdlEPv(
+
 namespace ImplicitSpecialMembers {
   // CHECK-LABEL: define {{.*}} @_ZN22ImplicitSpecialMembers1DC2EOS0_(
   // CHECK: call {{.*}} @_ZN22ImplicitSpecialMembers1AC1ERKS0_(
@@ -45,6 +48,12 @@ namespace ImplicitSpecialMembers {
   D d3(static_cast<D&&>(d1));
 }
 
+namespace OperatorDeleteLookup {
+  // Trigger emission of B's vtable and deleting dtor.
+  // This requires us to know what operator delete was selected.
+  void g() { f(); }
+}
+
 // CHECK: define available_externally {{signext i32|i32}} @_ZN1SIiE1fEv({{.*}} #[[ALWAYS_INLINE]] align
 
 // CHECK: attributes #[[ALWAYS_INLINE]] = {{.*}} alwaysinline