================
@@ -2700,6 +2702,210 @@ StmtResult 
Parser::ParseOpenMPDeclarativeOrExecutableDirective(
     // A single match is returned for OpenMP 5.0
     int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
 
+    // Check if we have user conditions with non-constant expressions that
+    // require runtime selection.
+    bool HasUserCondition = false;
+    for (const VariantMatchInfo &VMI : VMIs) {
+      if (VMI.HasNonConstantUserCondition) {
+        HasUserCondition = true;
+        break;
+      }
+    }
+
+    // Different directives have different data-sharing attributes, so each
+    // variant needs its own CapturedStmt with proper DSA context.
+    // We manually cache body tokens and inject them for each variant parse.
+    if (HasUserCondition) {
+      SmallVector<OpenMPClauseKind, 4> ClauseKinds;
+      SmallVector<OpenMPDirectiveKind, 4> DirectiveKinds;
+      SmallVector<SmallVector<OMPClause *, 5>, 4> DirectiveClauses;
+
+      BalancedDelimiterTracker T(*this, tok::l_paren,
+                                 tok::annot_pragma_openmp_end);
+      while (Tok.isNot(tok::annot_pragma_openmp_end)) {
+        OpenMPClauseKind CKind =
+            Tok.isAnnotation() ? OMPC_unknown
+                               : getOpenMPClauseKind(PP.getSpelling(Tok));
+        SourceLocation ClauseLoc = ConsumeToken();
+
+        // Parse '('.
+        T.consumeOpen();
+
+        if (CKind == OMPC_when) {
+          OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();
+          parseOMPContextSelectors(ClauseLoc, TI);
+
+          // Parse ':'.
+          if (Tok.is(tok::colon))
+            ConsumeAnyToken();
+        }
+
+        // Parse the directive kind and clauses manually.
+        OpenMPDirectiveKind DKind = OMPD_unknown;
+        SmallVector<OMPClause *, 5> Clauses;
+
+        if (!Tok.is(tok::r_paren)) {
+          // Parse directive kind (handles combined directives like
+          // 'parallel for simd').
+          DKind = parseOpenMPDirectiveKind(*this);
+
+          // Consume the last token of the directive name.
+          if (Tok.isNot(tok::annot_pragma_openmp_end) &&
+              Tok.isNot(tok::r_paren))
+            ConsumeAnyToken();
+
+          // Parse clauses for this directive if any exist.
+          // We stop at ')' which ends the metadirective variant.
+          while (Tok.isNot(tok::r_paren) &&
+                 Tok.isNot(tok::annot_pragma_openmp_end)) {
+            // Check if current token is a clause keyword.
+            OpenMPClauseKind ClauseKind =
+                Tok.isAnnotation()
+                    ? OMPC_unknown
+                    : getOpenMPClauseKind(PP.getSpelling(Tok));
+
+            // If not a clause keyword, we've parsed all clauses.
+            if (ClauseKind == OMPC_unknown)
+              break;
+
+            Actions.OpenMP().StartOpenMPClause(ClauseKind);
+            OMPClause *Clause =
+                ParseOpenMPClause(DKind, ClauseKind,
+                                  /* FirstClause */ Clauses.empty());
+            Actions.OpenMP().EndOpenMPClause();
+
+            if (Clause)
+              Clauses.push_back(Clause);
+
+            // Check for comma separator between clauses.
+            if (Tok.is(tok::comma))
+              ConsumeAnyToken();
+            else if (Tok.isNot(tok::r_paren) &&
+                     Tok.isNot(tok::annot_pragma_openmp_end)) {
+              // Unexpected token - not comma, not closing paren.
+              break;
+            }
+          }
+        }
+
+        // Parse ')'.
+        if (Tok.is(tok::r_paren))
+          T.consumeClose();
+
+        ClauseKinds.push_back(CKind);
+        DirectiveKinds.push_back(DKind);
+        DirectiveClauses.push_back(Clauses);
+      }
+
+      SourceLocation EndLoc = Tok.getLocation();
+      ConsumeAnnotationToken();
+
+      // Manually cache all body tokens for unlimited replay.
+      SmallVector<Token, 64> BodyTokens;
+
+      // Cache the current token before enabling backtracking.
+      BodyTokens.push_back(Tok);
+
+      // Parse the statement once and cache remaining tokens.
+      PP.EnableBacktrackAtThisPos();
+      {
+        ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
+        StmtResult BodyStmt = ParseStatement();
----------------
alexey-bataev wrote:

N+1 errors/messages. Need to try to emit errors/messages only once

https://github.com/llvm/llvm-project/pull/192455
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to