"Only one %0 clause can appear on a requires directive in a single translation unit">;
def note_omp_requires_previous_clause : Note <
"%0 clause previously used here">;
+def err_omp_target_before_requires : Error <
+ "target region encountered before requires directive with '%0' clause">;
+def note_omp_requires_encountered_target : Note <
+ "target previously encountered here">;
def err_omp_invalid_scope : Error <
"'#pragma omp %0' directive must appear only in file scope">;
def note_omp_invalid_length_on_this_ptr_mapping : Note <
/// Expression for the predefined allocators.
Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
nullptr};
+ /// Vector of previously encountered target directives
+ SmallVector<SourceLocation, 2> TargetLocations;
public:
explicit DSAStackTy(Sema &S) : SemaRef(S) {}
return IsDuplicate;
}
+ /// Add location of previously encountered target to internal vector
+ void addTargetDirLocation(SourceLocation LocStart) {
+ TargetLocations.push_back(LocStart);
+ }
+
+ // Return previously encountered target region locations.
+ ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
+ return TargetLocations;
+ }
+
/// Set default data sharing attribute to none.
void setDefaultDSANone(SourceLocation Loc) {
assert(!isStackEmpty());
OMPRequiresDecl *Sema::CheckOMPRequiresDecl(SourceLocation Loc,
ArrayRef<OMPClause *> ClauseList) {
+ /// For target specific clauses, the requires directive cannot be
+ /// specified after the handling of any of the target regions in the
+ /// current compilation unit.
+ ArrayRef<SourceLocation> TargetLocations =
+ DSAStack->getEncounteredTargetLocs();
+ if (!TargetLocations.empty()) {
+ for (const OMPClause *CNew : ClauseList) {
+ // Check if any of the requires clauses affect target regions.
+ if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
+ isa<OMPUnifiedAddressClause>(CNew) ||
+ isa<OMPReverseOffloadClause>(CNew) ||
+ isa<OMPDynamicAllocatorsClause>(CNew)) {
+ Diag(Loc, diag::err_omp_target_before_requires)
+ << getOpenMPClauseName(CNew->getClauseKind());
+ for (SourceLocation TargetLoc : TargetLocations) {
+ Diag(TargetLoc, diag::note_omp_requires_encountered_target);
+ }
+ }
+ }
+ }
+
if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
return OMPRequiresDecl::Create(Context, getCurLexicalContext(), Loc,
ClauseList);
->setIsOMPStructuredBlock(true);
}
+ if (!CurContext->isDependentContext() &&
+ isOpenMPTargetExecutionDirective(Kind) &&
+ !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
+ DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
+ DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
+ DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
+ // Register target to DSA Stack.
+ DSAStack->addTargetDirLocation(StartLoc);
+ }
+
return Res;
}
#pragma omp requires unified_shared_memory, unified_shared_memory // expected-error {{Only one unified_shared_memory clause can appear on a requires directive in a single translation unit}} expected-error {{directive '#pragma omp requires' cannot contain more than one 'unified_shared_memory' clause}}
-#pragma omp requires unified_address // expected-error {{Only one unified_address clause can appear on a requires directive in a single translation unit}}
+#pragma omp requires unified_address // expected-error {{Only one unified_address clause can appear on a requires directive in a single translation unit}}
#pragma omp requires unified_address, unified_address // expected-error {{Only one unified_address clause can appear on a requires directive in a single translation unit}} expected-error {{directive '#pragma omp requires' cannot contain more than one 'unified_address' clause}}
#pragma omp requires atomic_default_mem_order( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected 'seq_cst', 'acq_rel' or 'relaxed' in OpenMP clause 'atomic_default_mem_order'}} expected-error {{expected at least one clause on '#pragma omp requires' directive}}
-#pragma omp requires atomic_default_mem_order(seq_cst // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{Only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}}
+#pragma omp requires atomic_default_mem_order(seq_cst // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{Only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}}
-#pragma omp requires atomic_default_mem_order(invalid_modifier) // expected-error {{expected 'seq_cst', 'acq_rel' or 'relaxed' in OpenMP clause 'atomic_default_mem_order'}} expected-error {{expected at least one clause on '#pragma omp requires' directive}}
+#pragma omp requires atomic_default_mem_order(invalid_modifier) // expected-error {{expected 'seq_cst', 'acq_rel' or 'relaxed' in OpenMP clause 'atomic_default_mem_order'}} expected-error {{expected at least one clause on '#pragma omp requires' directive}}
#pragma omp requires atomic_default_mem_order(shared) // expected-error {{expected 'seq_cst', 'acq_rel' or 'relaxed' in OpenMP clause 'atomic_default_mem_order'}} expected-error {{expected at least one clause on '#pragma omp requires' directive}}
-#pragma omp requires atomic_default_mem_order(acq_rel), atomic_default_mem_order(relaxed) // expected-error {{directive '#pragma omp requires' cannot contain more than one 'atomic_default_mem_order' claus}} expected-error {{Only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}}
+#pragma omp requires atomic_default_mem_order(acq_rel), atomic_default_mem_order(relaxed) // expected-error {{directive '#pragma omp requires' cannot contain more than one 'atomic_default_mem_order' claus}} expected-error {{Only one atomic_default_mem_order clause can appear on a requires directive in a single translation unit}}
#pragma omp requires // expected-error {{expected at least one clause on '#pragma omp requires' directive}}
--- /dev/null
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s
+
+void foo2() {
+ int a;
+ #pragma omp target // expected-note 4 {{Target previously encountered here}}
+ {
+ a = a + 1;
+ }
+}
+
+#pragma omp requires atomic_default_mem_order(seq_cst)
+#pragma omp requires unified_address //expected-error {{Target region encountered before requires directive with 'unified_address' clause}}
+#pragma omp requires unified_shared_memory //expected-error {{Target region encountered before requires directive with 'unified_shared_memory' clause}}
+#pragma omp requires reverse_offload //expected-error {{Target region encountered before requires directive with 'reverse_offload' clause}}
+#pragma omp requires dynamic_allocators //expected-error {{Target region encountered before requires directive with 'dynamic_allocators' clause}}