[PATCH] D42731: [IR] - Make User construction exception safe

Klaus Kretzschmar via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 31 04:14:23 PST 2018


kkretzsch created this revision.
kkretzsch added reviewers: pete, MatzeB.

There are many instruction ctors that call the setName method of the Value base class, which can throw a bad_alloc exception in OOM situations.  In such situations special  User delete operators are called  which are not implemented yet.

Note that some User subclasses change the information which is required to calculate the storage pointer of a User object (e.g.NumUserOperands). Those subclasses need an operator delete that restores the changed information to its original value. Example: GlobalVariable.h


Repository:
  rL LLVM

https://reviews.llvm.org/D42731

Files:
  include/llvm/IR/GlobalVariable.h
  include/llvm/IR/User.h


Index: include/llvm/IR/User.h
===================================================================
--- include/llvm/IR/User.h
+++ include/llvm/IR/User.h
@@ -99,13 +99,31 @@
 
   /// \brief Free memory allocated for User and Use objects.
   void operator delete(void *Usr);
-  /// \brief Placement delete - required by std, but never called.
-  void operator delete(void*, unsigned) {
+  /// \brief Placement delete - required by std, called if the ctor throws.
+  void operator delete(void* Usr, unsigned) {
+    // called when constructor throws.
+    // Note: If a subclass manipulates the information which is required to calculate the 
+    // Usr memory pointer, e.g. NumUserOperands, the operator delete of that subclass has 
+    // to restore the changed information to the original value, since the dtor of that class
+    // is not called if the ctor fails.  
+    User::operator delete(Usr);
+
+#ifndef LLVM_ENABLE_EXCEPTIONS
     llvm_unreachable("Constructor throws?");
+#endif
   }
-  /// \brief Placement delete - required by std, but never called.
-  void operator delete(void*, unsigned, bool) {
+  /// \brief Placement delete - required by std, called if the ctor throws.
+  void operator delete(void* Usr, unsigned, bool) {
+    // called when constructor throws.
+    // Note: If a subclass manipulates the information which is required to calculate the 
+    // Usr memory pointer, e.g. NumUserOperands, the operator delete of that subclass has 
+    // to restore the changed information to the original value, since the dtor of that class
+    // is not called if the ctor fails.  
+    User::operator delete(Usr);
+
+#ifndef LLVM_ENABLE_EXCEPTIONS
     llvm_unreachable("Constructor throws?");
+#endif
   }
 
 protected:
Index: include/llvm/IR/GlobalVariable.h
===================================================================
--- include/llvm/IR/GlobalVariable.h
+++ include/llvm/IR/GlobalVariable.h
@@ -68,9 +68,6 @@
 
   ~GlobalVariable() {
     dropAllReferences();
-
-    // FIXME: needed by operator delete
-    setGlobalVariableNumOperands(1);
   }
 
   // allocate space for exactly one operand
@@ -78,6 +75,16 @@
     return User::operator new(s, 1);
   }
 
+  // delete space for exactly one operand as created in the corresponding new operator
+  void operator delete(void* ptr){
+    assert(ptr != nullptr && "must not be nullptr");
+    User *Obj = static_cast<User *>(ptr);
+    // Number of operands can be set to 0 after construction and initialization. Make sure
+    // that number of operands is reset to 1, as this is needed in User::operator delete
+    Obj->setGlobalVariableNumOperands(1);
+    User::operator delete(Obj);
+  }
+
   /// Provide fast operand accessors
   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D42731.132124.patch
Type: text/x-patch
Size: 2767 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180131/460c1f56/attachment.bin>


More information about the llvm-commits mailing list