================
@@ -7938,46 +7985,107 @@ void SemaOpenMP::ActOnOpenMPDeclareVariantDirective(
}
}
- // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
- // Each argument can only appear in a single adjust_args clause for each
- // declare variant directive.
- llvm::SmallPtrSet<const VarDecl *, 4> AdjustVars;
+ // OpenMP 6.0 [5.2.1]: each parameter list item may be specified only once
+ // per directive. The subject is the item, so a range is exempt and a name
+ // does not collide with a position that resolves to the same parameter.
+ llvm::SmallPtrSet<const VarDecl *, 4> AdjustVars; // named items
+ llvm::SmallSet<uint64_t, 4> AdjustPositions; // literal positional items
- for (Expr *E : AllAdjustArgs) {
- E = E->IgnoreParenImpCasts();
- if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
- if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
- const VarDecl *CanonPVD = PVD->getCanonicalDecl();
- if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
- FD->getParamDecl(PVD->getFunctionScopeIndex())
- ->getCanonicalDecl() == CanonPVD) {
- // It's a parameter of the function, check duplicates.
- if (!AdjustVars.insert(CanonPVD).second) {
- Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
- << PVD;
+ for (const OMPAdjustArgsClause *Clause : AdjustArgs) {
+ for (const OMPAdjustArgsItem &ItemInfo : Clause->items()) {
+ // OpenMP 6.0 [5.2.1]: a parameter range 'lb:ub'. A range is
+ // exempt from the duplicate restriction above — it is one item
+ // identifying one or more parameters — so nothing is recorded for
+ // dedup.
+ if (ItemInfo.Kind == OMPAdjustArgsItem::Range) {
+ if (!checkOMPAdjustArgsRange(*this, ItemInfo))
+ return;
+ continue;
+ }
+
+ assert(ItemInfo.E && "expected an adjust_args expression");
+ Expr *Item = ItemInfo.E->IgnoreParenImpCasts();
+
+ // A named parameter list item — unchanged from OpenMP 5.1.
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(Item)) {
+ if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
+ const VarDecl *CanonPVD = PVD->getCanonicalDecl();
+ if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
+ FD->getParamDecl(PVD->getFunctionScopeIndex())
+ ->getCanonicalDecl() == CanonPVD) {
+ if (!AdjustVars.insert(CanonPVD).second) {
+ Diag(DRE->getLocation(),
+ diag::err_omp_adjust_arg_multiple_clauses)
+ << PVD;
+ return;
+ }
+ continue;
+ }
+ }
+ }
+
+ if (getLangOpts().OpenMP < 60) {
+ // Anything that is not a function parameter is an error before 6.0.
+ Diag(Item->getExprLoc(), diag::err_omp_param_or_this_in_clause)
+ << FD << 0;
+ return;
+ }
+
+ // OpenMP 6.0 [5.2.1]: the position of a parameter, given as a
+ // positive constant integer expression. A dependent item is skipped
+ // here and rechecked when the template is instantiated.
+ if (Item->isTypeDependent() || Item->getType()->isIntegerType()) {
+ llvm::APSInt Pos;
+ switch (checkOMPAdjustArgsValue(*this, Item,
+ /*StrictlyPositive=*/true, Pos)) {
+ case OMPAdjustArgsVal::Invalid:
+ return;
+ case OMPAdjustArgsVal::Dependent:
+ continue;
+ case OMPAdjustArgsVal::Known:
+ if (!AdjustPositions.insert(Pos.getZExtValue()).second) {
+ Diag(Item->getExprLoc(), diag::err_omp_adjust_arg_multiple_clauses)
+ << Pos;
return;
}
continue;
}
}
+
+ // Not a name or a position: neither form OpenMP 6.0 allows for a
+ // non-range item.
+ Diag(Item->getExprLoc(), diag::err_omp_adjust_args_invalid_item);
+ return;
}
- // Anything that is not a function parameter is an error.
- Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
- return;
}
- // OpenMP 6.0 [9.6.2 (page 332, line 31-33, adjust_args clause, Restrictions]
- // If the `need_device_addr` adjust-op modifier is present, each list item
- // that appears in the clause must refer to an argument in the declaration of
- // the function variant that has a reference type
+ // OpenMP 6.0 [9.6.2]: if the need_device_addr adjust-op modifier
+ // is present, each list item that appears in the clause must refer to an
+ // argument in the declaration of the function variant that has a reference
+ // type. Unlike the need_device_ptr restriction, this one is not scoped to
+ // named items ("that refers to a specific named argument" is absent here),
+ // so positions and ranges are checked too, via the shared item-to-positions
+ // resolver.
if (getLangOpts().OpenMP >= 60) {
- for (Expr *E : AdjustArgsNeedDeviceAddr) {
- E = E->IgnoreParenImpCasts();
- if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
- if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
- if (!VD->getType()->isReferenceType())
- Diag(E->getExprLoc(),
+ for (const OMPAdjustArgsClause *Clause : AdjustArgs) {
+ if (Clause->AdjustOp != OMPC_ADJUST_ARGS_need_device_addr)
+ continue;
+ for (const OMPAdjustArgsItem &Item : Clause->items()) {
+ SmallVector<unsigned, 8> Positions;
+ // With no call site in hand, 'omp_num_args' is the declared parameter
+ // count (OpenMP 6.0 [20.1]). Positions past it denote variadic
+ // actuals, which have no declared parameter to check against, and are
+ // dropped by the resolver (OpenMP 6.0 [9.6.2]).
+ resolveOMPAdjustArgsItem(Item, FD, FD->getNumParams(), getASTContext(),
+ Positions);
+ for (unsigned Pos : Positions) {
+ if (!FD->getParamDecl(Pos - 1)->getType()->isReferenceType()) {
----------------
alexey-bataev wrote:
```suggestion
QualType ParamTy = FD->getParamDecl(Pos - 1)->getType();
if (ParamTy->isReferenceType() || ParamTy->isDependentType())
continue;
```
https://github.com/llvm/llvm-project/pull/225081
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits