Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions clang/include/clang/ASTMatchers/ASTMatchers.h
Original file line number Diff line number Diff line change
Expand Up @@ -8723,6 +8723,21 @@ AST_MATCHER_P(OMPExecutableDirective, hasAnyClause,
Builder) != Clauses.end();
}

/// Matches any ``#pragma omp target update`` executable directive.
///
/// Given
///
/// \code
/// #pragma omp target update from(a)
/// #pragma omp target update to(b)
/// \endcode
///
/// ``ompTargetUpdateDirective()`` matches both ``omp target update from(a)``
/// and ``omp target update to(b)``.
extern const internal::VariadicDynCastAllOfMatcher<Stmt,
OMPTargetUpdateDirective>
ompTargetUpdateDirective;

/// Matches OpenMP ``default`` clause.
///
/// Given
Expand Down Expand Up @@ -8836,6 +8851,30 @@ AST_MATCHER_P(OMPExecutableDirective, isAllowedToContainClauseKind,
Finder->getASTContext().getLangOpts().OpenMP);
}

/// Matches OpenMP ``from`` clause.
///
/// Given
///
/// \code
/// #pragma omp target update from(a)
/// \endcode
///
/// ``ompFromClause()`` matches ``from(a)``.
extern const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPFromClause>
ompFromClause;

/// Matches OpenMP ``to`` clause.
///
/// Given
///
/// \code
/// #pragma omp target update to(a)
/// \endcode
///
/// ``ompToClause()`` matches ``to(a)``.
extern const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPToClause>
ompToClause;

//----------------------------------------------------------------------------//
// End OpenMP handling.
//----------------------------------------------------------------------------//
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/ASTMatchers/ASTMatchersInternal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1124,8 +1124,13 @@ AST_TYPELOC_TRAVERSE_MATCHER_DEF(

const internal::VariadicDynCastAllOfMatcher<Stmt, OMPExecutableDirective>
ompExecutableDirective;
const internal::VariadicDynCastAllOfMatcher<Stmt, OMPTargetUpdateDirective>
ompTargetUpdateDirective;
const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPDefaultClause>
ompDefaultClause;
const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPFromClause>
ompFromClause;
const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPToClause> ompToClause;
const internal::VariadicDynCastAllOfMatcher<Decl, CXXDeductionGuideDecl>
cxxDeductionGuideDecl;

Expand Down
3 changes: 3 additions & 0 deletions clang/lib/ASTMatchers/Dynamic/Registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,10 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(ofClass);
REGISTER_MATCHER(ofKind);
REGISTER_MATCHER(ompDefaultClause);
REGISTER_MATCHER(ompFromClause);
REGISTER_MATCHER(ompToClause);
REGISTER_MATCHER(ompExecutableDirective);
REGISTER_MATCHER(ompTargetUpdateDirective);
REGISTER_MATCHER(on);
REGISTER_MATCHER(onImplicitObjectArgument);
REGISTER_MATCHER(opaqueValueExpr);
Expand Down
197 changes: 197 additions & 0 deletions clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4734,6 +4734,203 @@ void x() {
EXPECT_TRUE(matchesWithOpenMP(Source8, Matcher));
}

TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_From_IsStandaloneDirective) {
auto Matcher = ompTargetUpdateDirective(isStandaloneDirective());

StringRef Source0 = R"(
void foo() {
int arr[8];
#pragma omp target update from(arr[0:8:2])
;
}
)";
EXPECT_TRUE(matchesWithOpenMP(Source0, Matcher));
}

TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_To_IsStandaloneDirective) {
auto Matcher = ompTargetUpdateDirective(isStandaloneDirective());

StringRef Source0 = R"(
void foo() {
int arr[8];
#pragma omp target update to(arr[0:8:2])
;
}
)";
EXPECT_TRUE(matchesWithOpenMP(Source0, Matcher));
}

TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_From_HasStructuredBlock) {
StringRef Source0 = R"(
void foo() {
int arr[8];
#pragma omp target update from(arr[0:8:2])
;
}
)";
EXPECT_TRUE(notMatchesWithOpenMP(
Source0, ompTargetUpdateDirective(hasStructuredBlock(nullStmt()))));
}

TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_To_HasStructuredBlock) {
StringRef Source0 = R"(
void foo() {
int arr[8];
#pragma omp target update to(arr[0:8:2])
;
}
)";
EXPECT_TRUE(notMatchesWithOpenMP(
Source0, ompTargetUpdateDirective(hasStructuredBlock(nullStmt()))));
}

TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_From_HasClause) {
auto Matcher = ompTargetUpdateDirective(hasAnyClause(ompFromClause()));

StringRef Source0 = R"(
void foo() {
int arr[8];
#pragma omp target update from(arr[0:8:2])
;
}
)";
EXPECT_TRUE(matchesWithOpenMP(Source0, Matcher));

auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"});
ASSERT_TRUE(astUnit);

auto Results = match(ompTargetUpdateDirective().bind("directive"),
astUnit->getASTContext());
ASSERT_FALSE(Results.empty());

const auto *Directive =
Results[0].getNodeAs<OMPTargetUpdateDirective>("directive");
ASSERT_TRUE(Directive);

OMPFromClause *FromClause = nullptr;
for (auto *Clause : Directive->clauses()) {
if ((FromClause = dyn_cast<OMPFromClause>(Clause))) {
break;
}
}
ASSERT_TRUE(FromClause);

for (const auto *VarExpr : FromClause->varlist()) {
const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr);
if (!ArraySection)
continue;
// base (arr)
const Expr *Base = ArraySection->getBase();
ASSERT_TRUE(Base);

// lower bound (0)
const Expr *LowerBound = ArraySection->getLowerBound();
ASSERT_TRUE(LowerBound);

// length (8)
const Expr *Length = ArraySection->getLength();
ASSERT_TRUE(Length);

// stride (2)
const Expr *Stride = ArraySection->getStride();
ASSERT_TRUE(Stride);
}
}

TEST_P(ASTMatchersTest, OMPTargetUpdateDirective_To_HasClause) {
auto Matcher = ompTargetUpdateDirective(hasAnyClause(ompToClause()));

StringRef Source0 = R"(
void foo() {
int arr[8];
#pragma omp target update to(arr[0:8:2])
;
}
)";
EXPECT_TRUE(matchesWithOpenMP(Source0, Matcher));

auto astUnit = tooling::buildASTFromCodeWithArgs(Source0, {"-fopenmp"});
ASSERT_TRUE(astUnit);

auto Results = match(ompTargetUpdateDirective().bind("directive"),
astUnit->getASTContext());
ASSERT_FALSE(Results.empty());

const auto *Directive =
Results[0].getNodeAs<OMPTargetUpdateDirective>("directive");
ASSERT_TRUE(Directive);

OMPToClause *ToClause = nullptr;
for (auto *Clause : Directive->clauses()) {
if ((ToClause = dyn_cast<OMPToClause>(Clause))) {
break;
}
}
ASSERT_TRUE(ToClause);

for (const auto *VarExpr : ToClause->varlist()) {
const auto *ArraySection = dyn_cast<ArraySectionExpr>(VarExpr);
if (!ArraySection)
continue;

const Expr *Base = ArraySection->getBase();
ASSERT_TRUE(Base);

const Expr *LowerBound = ArraySection->getLowerBound();
ASSERT_TRUE(LowerBound);

const Expr *Length = ArraySection->getLength();
ASSERT_TRUE(Length);

const Expr *Stride = ArraySection->getStride();
ASSERT_TRUE(Stride);
}
}

TEST_P(ASTMatchersTest,
OMPTargetUpdateDirective_IsAllowedToContainClauseKind_From) {
auto Matcher = ompTargetUpdateDirective(
isAllowedToContainClauseKind(llvm::omp::OMPC_from));

StringRef Source0 = R"(
void x() {
;
}
)";
EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher));

StringRef Source1 = R"(
void foo() {
int arr[8];
#pragma omp target update from(arr[0:8:2])
;
}
)";
EXPECT_TRUE(matchesWithOpenMP(Source1, Matcher));
}

TEST_P(ASTMatchersTest,
OMPTargetUpdateDirective_IsAllowedToContainClauseKind_To) {
auto Matcher = ompTargetUpdateDirective(
isAllowedToContainClauseKind(llvm::omp::OMPC_to));

StringRef Source0 = R"(
void x() {
;
}
)";
EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher));

StringRef Source1 = R"(
void foo() {
int arr[8];
#pragma omp target update to(arr[0:8:2])
;
}
)";
EXPECT_TRUE(matchesWithOpenMP(Source1, Matcher));
}

TEST_P(ASTMatchersTest, HasAnyBase_DirectBase) {
if (!GetParam().isCXX()) {
return;
Expand Down
Loading
Loading