================
@@ -4529,6 +4529,191 @@ void CodeGenFunction::EmitOMPMasterDirective(const 
OMPMasterDirective &S) {
   emitMaster(*this, S);
 }
 
+static Expr *replaceWithNewTraitsOrDirectCall(CapturedDecl *CDecl,
+                                              Expr *NewExpr) {
+  Expr *CurrentCallExpr = nullptr;
+  Stmt *CallExprStmt = CDecl->getBody();
+
+  if (BinaryOperator *BinaryCopyOpr = dyn_cast<BinaryOperator>(CallExprStmt)) {
+    CurrentCallExpr = BinaryCopyOpr->getRHS();
+    BinaryCopyOpr->setRHS(NewExpr);
+  } else {
+    CurrentCallExpr = dyn_cast<Expr>(CallExprStmt);
+    CDecl->setBody(NewExpr);
+  }
+
+  return CurrentCallExpr;
+}
+
+static Expr *transformCallInStmt(Stmt *StmtP, bool NoContext = false) {
+  Expr *CurrentExpr = nullptr;
+  if (auto *CptStmt = dyn_cast<CapturedStmt>(StmtP)) {
+    CapturedDecl *CDecl = CptStmt->getCapturedDecl();
+
+    CallExpr *NewCallExpr = nullptr;
+    for (const auto *attr : CDecl->attrs()) {
+      if (NoContext) {
+        if (const auto *annotateAttr =
+                llvm::dyn_cast<clang::AnnotateAttr>(attr);
+            annotateAttr && annotateAttr->getAnnotation() == "NoContextAttr") {
+          NewCallExpr = llvm::dyn_cast<CallExpr>(*annotateAttr->args_begin());
+        }
+      } else {
+        if (const auto *annotateAttr =
+                llvm::dyn_cast<clang::AnnotateAttr>(attr);
+            annotateAttr && annotateAttr->getAnnotation() == "NoVariantsAttr") 
{
+          NewCallExpr = llvm::dyn_cast<CallExpr>(*annotateAttr->args_begin());
+        }
+      }
+    }
+
+    CurrentExpr = replaceWithNewTraitsOrDirectCall(CDecl, NewCallExpr);
+  }
+  return CurrentExpr;
+}
+
+// emitIfElse is used for the following conditions:
+//
+// NoVariants = 0 && NoContext = 1
+//   if (Condition_NoContext) {
+//     foo_variant2(); // Present in AnnotationAttr
+//   } else {
+//     foo_variant();
+//   }
+//
+// NoVariants = 1 && NoContext = 0
+//   if (Condition_NoVariants) {
+//     foo();
+//   } else {
+//     foo_variant();
+//   }
+//
+// NoVariants = 1 && NoContext = 1
+//   if (Condition_NoVariants) {   // ==> label if.then.NoVariants
+//     foo();
+//   } else {  // ==> label else.NoVariants
+//     if (Condition_NoContext) {   // ==> label if.then.NoContext
+//       foo_variant2(); // Present in AnnotationAttr
+//     } else {   // ==> label else
+//       foo_variant();
+//     }
+//   }
+//
+static void emitIfElse(CodeGenFunction *CGF, Stmt *AssociatedStmt,
----------------
dreachem wrote:

Thanks for the clarification. So something like this?

```c++
#include <iostream>                                                             
                                                                                
                                                                                
                             
int main()
{
    class IsPositive {
public:
    IsPositive(int x) : _x(x) {
        std::cout << "constructing IsPositive(" << x << ") object\n";
    }
    ~IsPositive() {
        std::cout << "destructing IsPositive(" << _x << ") object\n";
    }
    operator bool() const { return _x > 0; }
private:
        int _x;
    };

  // case 1
#pragma omp parallel if(IsPositive(10))
    {
        std::cout << "[1] in parallel\n";
    }

  // case 2
    auto cond1 = IsPositive(5);
#pragma omp parallel if(cond1)
    {
        std::cout << "[2] in parallel\n";
    }

  // case 3
#pragma omp parallel if(IsPositive(-10))
    {
        std::cout << "[3] in parallel\n";
    }

  // case 4
    auto cond2 = IsPositive(-5);
#pragma omp parallel if(cond2)
    {
        std::cout << "[4] in parallel\n";
    }

  
```

The output for the above with `OMP_NUM_THREADS=2` is:

```
constructing IsPositive(10) object
[1] in parallel
[1] in parallel
destructing IsPositive(10) object
constructing IsPositive(5) object
[2] in parallel
[2] in parallel
constructing IsPositive(-10) object
[3] in parallel
destructing IsPositive(-10) object
constructing IsPositive(-5) object
[4] in parallel
destructing IsPositive(-5) object
destructing IsPositive(5) object
```

So, the destructor for the instantiated class object used in the `if` condition 
is called upon completing each `parallel` region. On the other hand, if I move 
the condition expression outside the directive (as for cases 2 and 4), then the 
destructor for the instantiated class is called at the end of the function.

Does this match the expected behavior?

https://github.com/llvm/llvm-project/pull/131838
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to