Skip to content

Commit 53fe3df

Browse files
authored
[OpenMP] Allow begin/end declare variant in executable context (#139344)
We are missing a few declerative directives in the parser for executable and declerative directives causing us to error out if they are inside of functions. This adds support for begin/end declare variant by reusing the logic we used in global scope.
1 parent ccbba2c commit 53fe3df

File tree

4 files changed

+122
-71
lines changed

4 files changed

+122
-71
lines changed

clang/include/clang/Parse/Parser.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3537,6 +3537,9 @@ class Parser : public CodeCompletionHandler {
35373537
DeclarationName &Name,
35383538
AccessSpecifier AS = AS_none);
35393539

3540+
/// Parses 'omp begin declare variant' directive.
3541+
bool ParseOpenMPDeclareBeginVariantDirective(SourceLocation Loc);
3542+
35403543
/// Tries to parse cast part of OpenMP array shaping operation:
35413544
/// '[' expression ']' { '[' expression ']' } ')'.
35423545
bool tryParseOpenMPArrayShapingCastPart();

clang/lib/Parse/ParseOpenMP.cpp

Lines changed: 92 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,72 @@ TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range,
668668
DeclaratorInfo);
669669
}
670670

671+
/// Parses 'omp begin declare variant' directive.
672+
// The syntax is:
673+
// { #pragma omp begin declare variant clause }
674+
// <function-declaration-or-definition-sequence>
675+
// { #pragma omp end declare variant }
676+
//
677+
bool Parser::ParseOpenMPDeclareBeginVariantDirective(SourceLocation Loc) {
678+
OMPTraitInfo *ParentTI =
679+
Actions.OpenMP().getOMPTraitInfoForSurroundingScope();
680+
ASTContext &ASTCtx = Actions.getASTContext();
681+
OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
682+
if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI)) {
683+
while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
684+
;
685+
// Skip the last annot_pragma_openmp_end.
686+
(void)ConsumeAnnotationToken();
687+
return true;
688+
}
689+
690+
// Skip last tokens.
691+
skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant);
692+
693+
ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
694+
695+
VariantMatchInfo VMI;
696+
TI.getAsVariantMatchInfo(ASTCtx, VMI);
697+
698+
std::function<void(StringRef)> DiagUnknownTrait = [this,
699+
Loc](StringRef ISATrait) {
700+
// TODO Track the selector locations in a way that is accessible here
701+
// to improve the diagnostic location.
702+
Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
703+
};
704+
TargetOMPContext OMPCtx(
705+
ASTCtx, std::move(DiagUnknownTrait),
706+
/* CurrentFunctionDecl */ nullptr,
707+
/* ConstructTraits */ ArrayRef<llvm::omp::TraitProperty>(),
708+
Actions.OpenMP().getOpenMPDeviceNum());
709+
710+
if (isVariantApplicableInContext(VMI, OMPCtx,
711+
/*DeviceOrImplementationSetOnly=*/true)) {
712+
Actions.OpenMP().ActOnOpenMPBeginDeclareVariant(Loc, TI);
713+
return false;
714+
}
715+
716+
// Elide all the code till the matching end declare variant was found.
717+
unsigned Nesting = 1;
718+
SourceLocation DKLoc;
719+
OpenMPDirectiveKind DK = OMPD_unknown;
720+
do {
721+
DKLoc = Tok.getLocation();
722+
DK = parseOpenMPDirectiveKind(*this);
723+
if (DK == OMPD_end_declare_variant)
724+
--Nesting;
725+
else if (DK == OMPD_begin_declare_variant)
726+
++Nesting;
727+
if (!Nesting || isEofOrEom())
728+
break;
729+
ConsumeAnyToken();
730+
} while (true);
731+
732+
parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant, DK,
733+
Loc, DKLoc, /* SkipUntilOpenMPEnd */ true);
734+
return false;
735+
}
736+
671737
namespace {
672738
/// RAII that recreates function context for correct parsing of clauses of
673739
/// 'declare simd' construct.
@@ -2244,79 +2310,23 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
22442310
break;
22452311
}
22462312
case OMPD_begin_declare_variant: {
2247-
// The syntax is:
2248-
// { #pragma omp begin declare variant clause }
2249-
// <function-declaration-or-definition-sequence>
2250-
// { #pragma omp end declare variant }
2251-
//
22522313
ConsumeToken();
2253-
OMPTraitInfo *ParentTI =
2254-
Actions.OpenMP().getOMPTraitInfoForSurroundingScope();
2255-
ASTContext &ASTCtx = Actions.getASTContext();
2256-
OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
2257-
if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI)) {
2258-
while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
2259-
;
2314+
if (!ParseOpenMPDeclareBeginVariantDirective(Loc)) {
22602315
// Skip the last annot_pragma_openmp_end.
2261-
(void)ConsumeAnnotationToken();
2262-
break;
2316+
if (!isEofOrEom())
2317+
ConsumeAnnotationToken();
22632318
}
2264-
2265-
// Skip last tokens.
2266-
skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant);
2267-
2268-
ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
2269-
2270-
VariantMatchInfo VMI;
2271-
TI.getAsVariantMatchInfo(ASTCtx, VMI);
2272-
2273-
std::function<void(StringRef)> DiagUnknownTrait =
2274-
[this, Loc](StringRef ISATrait) {
2275-
// TODO Track the selector locations in a way that is accessible here
2276-
// to improve the diagnostic location.
2277-
Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
2278-
};
2279-
TargetOMPContext OMPCtx(
2280-
ASTCtx, std::move(DiagUnknownTrait),
2281-
/* CurrentFunctionDecl */ nullptr,
2282-
/* ConstructTraits */ ArrayRef<llvm::omp::TraitProperty>(),
2283-
Actions.OpenMP().getOpenMPDeviceNum());
2284-
2285-
if (isVariantApplicableInContext(VMI, OMPCtx,
2286-
/*DeviceOrImplementationSetOnly=*/true)) {
2287-
Actions.OpenMP().ActOnOpenMPBeginDeclareVariant(Loc, TI);
2288-
break;
2289-
}
2290-
2291-
// Elide all the code till the matching end declare variant was found.
2292-
unsigned Nesting = 1;
2293-
SourceLocation DKLoc;
2294-
OpenMPDirectiveKind DK = OMPD_unknown;
2295-
do {
2296-
DKLoc = Tok.getLocation();
2297-
DK = parseOpenMPDirectiveKind(*this);
2298-
if (DK == OMPD_end_declare_variant)
2299-
--Nesting;
2300-
else if (DK == OMPD_begin_declare_variant)
2301-
++Nesting;
2302-
if (!Nesting || isEofOrEom())
2303-
break;
2304-
ConsumeAnyToken();
2305-
} while (true);
2306-
2307-
parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant,
2308-
DK, Loc, DKLoc, /* SkipUntilOpenMPEnd */ true);
2309-
if (isEofOrEom())
2310-
return nullptr;
2311-
break;
2319+
return nullptr;
23122320
}
23132321
case OMPD_end_declare_variant: {
2322+
ConsumeToken();
23142323
if (Actions.OpenMP().isInOpenMPDeclareVariantScope())
23152324
Actions.OpenMP().ActOnOpenMPEndDeclareVariant();
23162325
else
23172326
Diag(Loc, diag::err_expected_begin_declare_variant);
2318-
ConsumeToken();
2319-
break;
2327+
// Skip the last annot_pragma_openmp_end.
2328+
ConsumeAnnotationToken();
2329+
return nullptr;
23202330
}
23212331
case OMPD_declare_variant:
23222332
case OMPD_declare_simd: {
@@ -3028,12 +3038,28 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
30283038
Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);
30293039
break;
30303040
}
3041+
case OMPD_begin_declare_variant: {
3042+
ConsumeToken();
3043+
if (!ParseOpenMPDeclareBeginVariantDirective(Loc)) {
3044+
// Skip the last annot_pragma_openmp_end.
3045+
if (!isEofOrEom())
3046+
ConsumeAnnotationToken();
3047+
}
3048+
return Directive;
3049+
}
3050+
case OMPD_end_declare_variant: {
3051+
ConsumeToken();
3052+
if (Actions.OpenMP().isInOpenMPDeclareVariantScope())
3053+
Actions.OpenMP().ActOnOpenMPEndDeclareVariant();
3054+
else
3055+
Diag(Loc, diag::err_expected_begin_declare_variant);
3056+
ConsumeAnnotationToken();
3057+
break;
3058+
}
30313059
case OMPD_declare_simd:
30323060
case OMPD_begin_declare_target:
30333061
case OMPD_end_declare_target:
30343062
case OMPD_requires:
3035-
case OMPD_begin_declare_variant:
3036-
case OMPD_end_declare_variant:
30373063
case OMPD_declare_variant:
30383064
Diag(Tok, diag::err_omp_unexpected_directive)
30393065
<< 1 << getOpenMPDirectiveName(DKind, OMPVersion);
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp -x c -std=c99 -fms-extensions -Wno-pragma-pack %s
2+
// RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp-simd -x c -std=c99 -fms-extensions -Wno-pragma-pack %s
3+
4+
// expected-no-diagnostics
5+
6+
#pragma omp begin declare variant match(implementation={vendor(ibm)})
7+
void f(int);
8+
#pragma omp end declare variant
9+
10+
#pragma omp begin declare variant match(implementation={vendor(llvm)})
11+
void f(void);
12+
#pragma omp end declare variant
13+
14+
int main() {
15+
#pragma omp begin declare variant match(implementation={vendor(ibm)})
16+
int i = 0;
17+
f(i);
18+
#pragma omp end declare variant
19+
20+
#pragma omp begin declare variant match(implementation={vendor(llvm)})
21+
f();
22+
#pragma omp end declare variant
23+
}

clang/test/OpenMP/begin_declare_variant_messages.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616
#pragma omp variant begin // expected-error {{expected an OpenMP directive}}
1717
#pragma omp declare variant end // expected-error {{function declaration is expected after 'declare variant' directive}}
1818
#pragma omp begin declare variant // omp50-error {{expected 'match' clause on 'omp declare variant' directive}} omp51-error {{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}}
19-
#pragma omp end declare variant
20-
// TODO: Issue an error message
19+
#pragma omp end declare variant // expected-error {{'#pragma omp end declare variant' with no matching '#pragma omp begin declare variant'}}
2120
#pragma omp end declare variant // expected-error {{'#pragma omp end declare variant' with no matching '#pragma omp begin declare variant'}}
2221
#pragma omp end declare variant // expected-error {{'#pragma omp end declare variant' with no matching '#pragma omp begin declare variant'}}
2322
#pragma omp end declare variant // expected-error {{'#pragma omp end declare variant' with no matching '#pragma omp begin declare variant'}}
@@ -27,11 +26,11 @@ int foo(void);
2726
const int var;
2827

2928
#pragma omp begin declare variant // omp50-error {{expected 'match' clause on 'omp declare variant' directive}} omp51-error {{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}}
30-
#pragma omp end declare variant
29+
#pragma omp end declare variant // expected-error {{'#pragma omp end declare variant' with no matching '#pragma omp begin declare variant'}}
3130
#pragma omp begin declare variant xxx // omp50-error {{expected 'match' clause on 'omp declare variant' directive}} omp51-error {{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}}
32-
#pragma omp end declare variant
31+
#pragma omp end declare variant // expected-error {{'#pragma omp end declare variant' with no matching '#pragma omp begin declare variant'}}
3332
#pragma omp begin declare variant match // expected-error {{expected '(' after 'match'}}
34-
#pragma omp end declare variant
33+
#pragma omp end declare variant // expected-error {{'#pragma omp end declare variant' with no matching '#pragma omp begin declare variant'}}
3534
#pragma omp begin declare variant match( // expected-error {{expected ')'}} expected-warning {{expected identifier or string literal describing a context set; set skipped}} expected-note {{context set options are: 'construct' 'device' 'target_device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} expected-note {{to match this '('}}
3635
#pragma omp end declare variant
3736
#pragma omp begin declare variant match() // expected-warning {{expected identifier or string literal describing a context set; set skipped}} expected-note {{context set options are: 'construct' 'device' 'target_device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}}

0 commit comments

Comments
 (0)