================
@@ -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();
+ if (BodyStmt.isInvalid()) {
+ PP.Backtrack();
+ return StmtError();
+ }
+ }
+
+ // Get cached tokens and commit (keeps stream advanced).
+ ArrayRef<Token> CachedRange = PP.GetAndCommitBacktrackedTokens();
+ BodyTokens.append(CachedRange.begin(), CachedRange.end());
+
+ if (BodyTokens.empty()) {
+ Diag(Tok, diag::err_expected_statement);
+ return StmtError();
+ }
+
+ // Add an EOF token with marker to end the injected stream.
+ Token EofToken;
+ EofToken.startToken();
+ EofToken.setKind(tok::eof);
+ EofToken.setLocation(Tok.getLocation());
+ EofToken.setEofData(this);
+ BodyTokens.push_back(EofToken);
+
+ // Parse the body separately for each variant to get correct DSA.
+ SmallVector<Stmt *, 4> VariantBodies;
+ for (unsigned i = 0; i < DirectiveKinds.size(); ++i) {
----------------
alexey-bataev wrote:
```suggestion
for (unsigned I : llvm::seq<unsigned>(DirectiveKinds.size())) {
```
https://github.com/llvm/llvm-project/pull/192455
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits