NoQ updated this revision to Diff 139389.
NoQ added a comment.

I'd rather keep the helper method within the class. This allows us to keep 
constructors private, which is something i forgot to do originally.


https://reviews.llvm.org/D44725

Files:
  include/clang/Analysis/ConstructionContext.h
  lib/Analysis/ConstructionContext.cpp

Index: lib/Analysis/ConstructionContext.cpp
===================================================================
--- lib/Analysis/ConstructionContext.cpp
+++ lib/Analysis/ConstructionContext.cpp
@@ -48,15 +48,13 @@
   if (const Stmt *S = TopLayer->getTriggerStmt()) {
     if (const auto *DS = dyn_cast<DeclStmt>(S)) {
       assert(TopLayer->isLast());
-      auto *CC =
-          C.getAllocator().Allocate<SimpleVariableConstructionContext>();
-      return new (CC) SimpleVariableConstructionContext(DS);
-    } else if (const auto *NE = dyn_cast<CXXNewExpr>(S)) {
+      return create<SimpleVariableConstructionContext>(C, DS);
+    }
+    if (const auto *NE = dyn_cast<CXXNewExpr>(S)) {
       assert(TopLayer->isLast());
-      auto *CC =
-          C.getAllocator().Allocate<NewAllocatedObjectConstructionContext>();
-      return new (CC) NewAllocatedObjectConstructionContext(NE);
-    } else if (const auto *BTE = dyn_cast<CXXBindTemporaryExpr>(S)) {
+      return create<NewAllocatedObjectConstructionContext>(C, NE);
+    }
+    if (const auto *BTE = dyn_cast<CXXBindTemporaryExpr>(S)) {
       const MaterializeTemporaryExpr *MTE = nullptr;
       assert(BTE->getType().getCanonicalType()
                 ->getAsCXXRecordDecl()->hasNonTrivialDestructor());
@@ -68,60 +66,45 @@
                  ParentLayer->getTriggerStmt()))) {
           // A temporary object which has both destruction and
           // materialization info.
-          auto *CC =
-              C.getAllocator().Allocate<TemporaryObjectConstructionContext>();
-          return new (CC) TemporaryObjectConstructionContext(BTE, MTE);
+          return create<TemporaryObjectConstructionContext>(C, BTE, MTE);
         }
         // C++17 *requires* elision of the constructor at the return site
         // and at variable initialization site, while previous standards
         // were allowing an optional elidable constructor.
         if (auto *RS = dyn_cast<ReturnStmt>(ParentLayer->getTriggerStmt())) {
           assert(!RS->getRetValue()->getType().getCanonicalType()
                     ->getAsCXXRecordDecl()->hasTrivialDestructor());
-          auto *CC =
-              C.getAllocator()
-                  .Allocate<
-                      CXX17ElidedCopyReturnedValueConstructionContext>();
-          return new (CC)
-              CXX17ElidedCopyReturnedValueConstructionContext(RS, BTE);
+          return create<CXX17ElidedCopyReturnedValueConstructionContext>(C,
+                                                                       RS, BTE);
         }
         if (auto *DS = dyn_cast<DeclStmt>(ParentLayer->getTriggerStmt())) {
           assert(!cast<VarDecl>(DS->getSingleDecl())->getType()
                       .getCanonicalType()->getAsCXXRecordDecl()
                       ->hasTrivialDestructor());
-          auto *CC =
-              C.getAllocator()
-                  .Allocate<CXX17ElidedCopyVariableConstructionContext>();
-          return new (CC) CXX17ElidedCopyVariableConstructionContext(DS, BTE);
+          return create<CXX17ElidedCopyVariableConstructionContext>(C, DS, BTE);
         }
         llvm_unreachable("Unexpected construction context with destructor!");
       }
       // A temporary object that doesn't require materialization.
-      auto *CC =
-          C.getAllocator().Allocate<TemporaryObjectConstructionContext>();
-      return new (CC)
-          TemporaryObjectConstructionContext(BTE, /*MTE=*/nullptr);
-    } else if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(S)) {
+      return create<TemporaryObjectConstructionContext>(C, BTE, /*MTE=*/nullptr);
+    }
+    if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(S)) {
       // If the object requires destruction and is not lifetime-extended,
       // then it must have a BTE within its MTE.
       assert(MTE->getType().getCanonicalType()
                 ->getAsCXXRecordDecl()->hasTrivialDestructor() ||
              MTE->getStorageDuration() != SD_FullExpression);
       assert(TopLayer->isLast());
-      auto *CC =
-          C.getAllocator().Allocate<TemporaryObjectConstructionContext>();
-      return new (CC) TemporaryObjectConstructionContext(nullptr, MTE);
-    } else if (const auto *RS = dyn_cast<ReturnStmt>(S)) {
+      return create<TemporaryObjectConstructionContext>(C, nullptr, MTE);
+    }
+    if (const auto *RS = dyn_cast<ReturnStmt>(S)) {
       assert(TopLayer->isLast());
-      auto *CC =
-          C.getAllocator().Allocate<SimpleReturnedValueConstructionContext>();
-      return new (CC) SimpleReturnedValueConstructionContext(RS);
+      return create<SimpleReturnedValueConstructionContext>(C, RS);
     }
+    llvm_unreachable("Unexpected construction context with statement!");
   } else if (const CXXCtorInitializer *I = TopLayer->getTriggerInit()) {
     assert(TopLayer->isLast());
-    auto *CC =
-        C.getAllocator().Allocate<ConstructorInitializerConstructionContext>();
-    return new (CC) ConstructorInitializerConstructionContext(I);
+    return create<ConstructorInitializerConstructionContext>(C, I);
   }
   llvm_unreachable("Unexpected construction context!");
 }
Index: include/clang/Analysis/ConstructionContext.h
===================================================================
--- include/clang/Analysis/ConstructionContext.h
+++ include/clang/Analysis/ConstructionContext.h
@@ -118,6 +118,14 @@
   // via createFromLayers().
   explicit ConstructionContext(Kind K) : K(K) {}
 
+private:
+  // A helper function for constructing an instance into a bump vector context.
+  template <typename T, typename... ArgTypes>
+  static T *create(BumpVectorContext &C, ArgTypes... Args) {
+    auto *CC = C.getAllocator().Allocate<T>();
+    return new (CC) T(Args...);
+  }
+
 public:
   /// Consume the construction context layer, together with its parent layers,
   /// and wrap it up into a complete construction context.
@@ -153,11 +161,13 @@
 /// elidable copy-constructor from makeT() into var would also be a simple
 /// variable constructor handled by this class.
 class SimpleVariableConstructionContext : public VariableConstructionContext {
-public:
+  friend class ConstructionContext; // Allows to create<>() itself.
+
   explicit SimpleVariableConstructionContext(const DeclStmt *DS)
       : VariableConstructionContext(ConstructionContext::SimpleVariableKind,
                                     DS) {}
 
+public:
   static bool classof(const ConstructionContext *CC) {
     return CC->getKind() == SimpleVariableKind;
   }
@@ -176,13 +186,15 @@
     : public VariableConstructionContext {
   const CXXBindTemporaryExpr *BTE;
 
-public:
+  friend class ConstructionContext; // Allows to create<>() itself.
+
   explicit CXX17ElidedCopyVariableConstructionContext(
       const DeclStmt *DS, const CXXBindTemporaryExpr *BTE)
       : VariableConstructionContext(CXX17ElidedCopyVariableKind, DS), BTE(BTE) {
     assert(BTE);
   }
 
+public:
   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
 
   static bool classof(const ConstructionContext *CC) {
@@ -195,14 +207,16 @@
 class ConstructorInitializerConstructionContext : public ConstructionContext {
   const CXXCtorInitializer *I;
 
-public:
+  friend class ConstructionContext; // Allows to create<>() itself.
+
   explicit ConstructorInitializerConstructionContext(
       const CXXCtorInitializer *I)
       : ConstructionContext(ConstructionContext::ConstructorInitializerKind),
         I(I) {
     assert(I);
   }
 
+public:
   const CXXCtorInitializer *getCXXCtorInitializer() const { return I; }
 
   static bool classof(const ConstructionContext *CC) {
@@ -215,13 +229,15 @@
 class NewAllocatedObjectConstructionContext : public ConstructionContext {
   const CXXNewExpr *NE;
 
-public:
+  friend class ConstructionContext; // Allows to create<>() itself.
+
   explicit NewAllocatedObjectConstructionContext(const CXXNewExpr *NE)
       : ConstructionContext(ConstructionContext::NewAllocatedObjectKind),
         NE(NE) {
     assert(NE);
   }
 
+public:
   const CXXNewExpr *getCXXNewExpr() const { return NE; }
 
   static bool classof(const ConstructionContext *CC) {
@@ -237,7 +253,8 @@
   const CXXBindTemporaryExpr *BTE;
   const MaterializeTemporaryExpr *MTE;
 
-public:
+  friend class ConstructionContext; // Allows to create<>() itself.
+
   explicit TemporaryObjectConstructionContext(
       const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE)
       : ConstructionContext(ConstructionContext::TemporaryObjectKind),
@@ -248,6 +265,7 @@
     // nowhere that doesn't have a non-trivial destructor).
   }
 
+public:
   /// CXXBindTemporaryExpr here is non-null as long as the temporary has
   /// a non-trivial destructor.
   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const {
@@ -295,11 +313,13 @@
 /// MaterializeTemporaryExpr) is normally located in the caller function's AST.
 class SimpleReturnedValueConstructionContext
     : public ReturnedValueConstructionContext {
-public:
+  friend class ConstructionContext; // Allows to create<>() itself.
+
   explicit SimpleReturnedValueConstructionContext(const ReturnStmt *RS)
       : ReturnedValueConstructionContext(
             ConstructionContext::SimpleReturnedValueKind, RS) {}
 
+public:
   static bool classof(const ConstructionContext *CC) {
     return CC->getKind() == SimpleReturnedValueKind;
   }
@@ -317,15 +337,17 @@
     : public ReturnedValueConstructionContext {
   const CXXBindTemporaryExpr *BTE;
 
-public:
+  friend class ConstructionContext; // Allows to create<>() itself.
+
   explicit CXX17ElidedCopyReturnedValueConstructionContext(
       const ReturnStmt *RS, const CXXBindTemporaryExpr *BTE)
       : ReturnedValueConstructionContext(
             ConstructionContext::CXX17ElidedCopyReturnedValueKind, RS),
         BTE(BTE) {
     assert(BTE);
   }
 
+public:
   const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
 
   static bool classof(const ConstructionContext *CC) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to