Skip to content

Commit a15a141

Browse files
committed
[OPENMP50]Add parsing/sema analysis for declare variant score.
Context selectors may include optional score clause in format `score(<expr>):`, where `<expr>` must be a constant integer expression. Added parsing/sema analysis only. llvm-svn: 373502
1 parent 2a0c8b1 commit a15a141

File tree

9 files changed

+101
-15
lines changed

9 files changed

+101
-15
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3290,12 +3290,19 @@ def OMPDeclareVariant : InheritableAttr {
32903290
let Documentation = [OMPDeclareVariantDocs];
32913291
let Args = [
32923292
ExprArgument<"VariantFuncRef">,
3293+
ExprArgument<"Score">,
32933294
EnumArgument<"CtxSelectorSet", "CtxSelectorSetType",
32943295
[ "", "implementation"
32953296
],
32963297
[
32973298
"CtxSetUnknown", "CtxSetImplementation"
32983299
]>,
3300+
EnumArgument<"CtxScore", "ScoreType",
3301+
[ "", "score"
3302+
],
3303+
[
3304+
"ScoreUnknown", "ScoreSpecified"
3305+
]>,
32993306
EnumArgument<"CtxSelector", "CtxSelectorType",
33003307
[ "", "vendor"
33013308
],
@@ -3305,6 +3312,13 @@ def OMPDeclareVariant : InheritableAttr {
33053312
StringArgument<"ImplVendor", 1>
33063313
];
33073314
let AdditionalMembers = [{
3315+
void printScore(raw_ostream & OS, const PrintingPolicy &Policy) const {
3316+
if (const Expr *E = getScore()) {
3317+
OS << "score(";
3318+
E->printPretty(OS, nullptr, Policy);
3319+
OS << "):";
3320+
}
3321+
}
33083322
void printPrettyPragma(raw_ostream & OS, const PrintingPolicy &Policy)
33093323
const {
33103324
assert(getCtxSelectorSet() != CtxSetUnknown &&
@@ -3322,6 +3336,7 @@ def OMPDeclareVariant : InheritableAttr {
33223336
switch (getCtxSelector()) {
33233337
case CtxVendor:
33243338
OS << "vendor(";
3339+
printScore(OS, Policy);
33253340
OS << getImplVendor();
33263341
OS << ")";
33273342
break;

clang/include/clang/Sema/Sema.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9109,11 +9109,14 @@ class Sema {
91099109
OMPDeclareVariantAttr::CtxSelectorType Ctx =
91109110
OMPDeclareVariantAttr::CtxUnknown;
91119111
StringRef ImplVendor;
9112+
ExprResult CtxScore;
91129113
explicit OpenMPDeclareVariantCtsSelectorData() = default;
91139114
explicit OpenMPDeclareVariantCtsSelectorData(
91149115
OMPDeclareVariantAttr::CtxSelectorSetType CtxSet,
9115-
OMPDeclareVariantAttr::CtxSelectorType Ctx, StringRef ImplVendor)
9116-
: CtxSet(CtxSet), Ctx(Ctx), ImplVendor(ImplVendor) {}
9116+
OMPDeclareVariantAttr::CtxSelectorType Ctx, StringRef ImplVendor,
9117+
ExprResult CtxScore)
9118+
: CtxSet(CtxSet), Ctx(Ctx), ImplVendor(ImplVendor), CtxScore(CtxScore) {
9119+
}
91179120
};
91189121

91199122
/// Checks if the variant/multiversion functions are compatible.

clang/lib/Parse/ParseOpenMP.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,31 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
786786
LinModifiers, Steps, SourceRange(Loc, EndLoc));
787787
}
788788

789+
/// Parse optional 'score' '(' <expr> ')' ':'.
790+
static ExprResult parseContextScore(Parser &P) {
791+
ExprResult ScoreExpr;
792+
SmallString<16> Buffer;
793+
StringRef SelectorName =
794+
P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
795+
OMPDeclareVariantAttr::ScoreType ScoreKind =
796+
OMPDeclareVariantAttr::ScoreUnknown;
797+
(void)OMPDeclareVariantAttr::ConvertStrToScoreType(SelectorName, ScoreKind);
798+
if (ScoreKind == OMPDeclareVariantAttr::ScoreUnknown)
799+
return ScoreExpr;
800+
assert(ScoreKind == OMPDeclareVariantAttr::ScoreSpecified &&
801+
"Expected \"score\" clause.");
802+
(void)P.ConsumeToken();
803+
SourceLocation RLoc;
804+
ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc);
805+
// Parse ':'
806+
if (P.getCurToken().is(tok::colon))
807+
(void)P.ConsumeAnyToken();
808+
else
809+
P.Diag(P.getCurToken(), diag::warn_pragma_expected_colon)
810+
<< "context selector score clause";
811+
return ScoreExpr;
812+
}
813+
789814
/// Parse context selector for 'implementation' selector set:
790815
/// 'vendor' '(' <vendor> ')'
791816
static void
@@ -815,6 +840,7 @@ parseImplementationSelector(Parser &P,
815840
BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
816841
(void)T.expectAndConsume(diag::err_expected_lparen_after,
817842
CtxSelectorName.data());
843+
Data.CtxScore = parseContextScore(P);
818844
// Parse <vendor>.
819845
StringRef VendorName;
820846
if (Tok.is(tok::identifier)) {

clang/lib/Sema/SemaOpenMP.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5112,8 +5112,23 @@ void Sema::ActOnOpenMPDeclareVariantDirective(
51125112
if (Data.CtxSet == OMPDeclareVariantAttr::CtxSetUnknown ||
51135113
Data.Ctx == OMPDeclareVariantAttr::CtxUnknown)
51145114
return;
5115+
Expr *Score = nullptr;
5116+
OMPDeclareVariantAttr::ScoreType ST = OMPDeclareVariantAttr::ScoreUnknown;
5117+
if (Data.CtxScore.isUsable()) {
5118+
ST = OMPDeclareVariantAttr::ScoreSpecified;
5119+
Score = Data.CtxScore.get();
5120+
if (!Score->isTypeDependent() && !Score->isValueDependent() &&
5121+
!Score->isInstantiationDependent() &&
5122+
!Score->containsUnexpandedParameterPack()) {
5123+
llvm::APSInt Result;
5124+
ExprResult ICE = VerifyIntegerConstantExpression(Score, &Result);
5125+
if (ICE.isInvalid())
5126+
return;
5127+
}
5128+
}
51155129
auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
5116-
Context, VariantRef, Data.CtxSet, Data.Ctx, Data.ImplVendor, SR);
5130+
Context, VariantRef, Score, Data.CtxSet, ST, Data.Ctx, Data.ImplVendor,
5131+
SR);
51175132
FD->addAttr(NewAttr);
51185133
}
51195134

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,15 +388,20 @@ static void instantiateOMPDeclareVariantAttr(
388388
if (Expr *E = Attr.getVariantFuncRef())
389389
VariantFuncRef = Subst(E);
390390

391+
ExprResult Score;
392+
if (Expr *E = Attr.getScore())
393+
Score = Subst(E);
394+
391395
// Check function/variant ref.
392396
Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
393397
S.checkOpenMPDeclareVariantFunction(
394398
S.ConvertDeclToDeclGroup(New), VariantFuncRef.get(), Attr.getRange());
395399
if (!DeclVarData)
396400
return;
397401
// Instantiate the attribute.
398-
Sema::OpenMPDeclareVariantCtsSelectorData Data(
399-
Attr.getCtxSelectorSet(), Attr.getCtxSelector(), Attr.getImplVendor());
402+
Sema::OpenMPDeclareVariantCtsSelectorData Data(Attr.getCtxSelectorSet(),
403+
Attr.getCtxSelector(),
404+
Attr.getImplVendor(), Score);
400405
S.ActOnOpenMPDeclareVariantDirective(DeclVarData.getValue().first,
401406
DeclVarData.getValue().second,
402407
Attr.getRange(), Data);

clang/test/OpenMP/declare_variant_ast_print.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ int foo(void);
1010
#pragma omp declare variant(foo) match(xxx={vvv})
1111
#pragma omp declare variant(foo) match(implementation={vendor(ibm)}, implementation={vendor(llvm)})
1212
#pragma omp declare variant(foo) match(implementation={vendor(unknown)})
13+
#pragma omp declare variant(foo) match(implementation={vendor(score(5): ibm)})
1314
int bar(void);
1415

1516
// CHECK: int foo();
17+
// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(score(5):ibm)})
1618
// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(unknown)})
1719
// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(ibm)})
1820
// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(llvm)})

clang/test/OpenMP/declare_variant_ast_print.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,23 @@ T foofoo() { return T(); }
1717
// CHECK-NEXT: return int();
1818
// CHECK-NEXT: }
1919

20-
// CHECK: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(unknown)})
20+
// CHECK: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(score(5):ibm)})
21+
// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(unknown)})
2122
// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(ibm)})
2223
// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(llvm)})
2324
// CHECK-NEXT: int bar();
2425
#pragma omp declare variant(foofoo <int>) match(xxx = {})
2526
#pragma omp declare variant(foofoo <int>) match(xxx = {vvv})
2627
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(ibm)}, implementation={vendor(llvm)})
2728
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(unknown)})
29+
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score(5): ibm)})
2830
int bar();
2931

30-
// CHECK: #pragma omp declare variant(foofoo<T>) match(implementation={vendor(unknown)})
32+
// CHECK: #pragma omp declare variant(foofoo<T>) match(implementation={vendor(score(C + 5):ibm)})
33+
// CHECK-NEXT: #pragma omp declare variant(foofoo<T>) match(implementation={vendor(unknown)})
3134
// CHECK-NEXT: #pragma omp declare variant(foofoo<T>) match(implementation={vendor(ibm)})
3235
// CHECK-NEXT: #pragma omp declare variant(foofoo<T>) match(implementation={vendor(llvm)})
33-
// CHECK-NEXT: template <typename T> T barbar();
36+
// CHECK-NEXT: template <typename T, int C> T barbar();
3437
#pragma omp declare variant(foofoo <T>) match(xxx = {})
3538
#pragma omp declare variant(foofoo <T>) match(xxx = {vvv})
3639
#pragma omp declare variant(foofoo <T>) match(user = {score(<expr>) : condition(<expr>)})
@@ -39,19 +42,21 @@ int bar();
3942
#pragma omp declare variant(foofoo <T>) match(user = {condition(<expr>)})
4043
#pragma omp declare variant(foofoo <T>) match(implementation={vendor(ibm)}, implementation={vendor(llvm)})
4144
#pragma omp declare variant(foofoo <T>) match(implementation={vendor(unknown)})
42-
template <typename T>
45+
#pragma omp declare variant(foofoo <T>) match(implementation={vendor(score(C+5): ibm)})
46+
template <typename T, int C>
4347
T barbar();
4448

45-
// CHECK: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(unknown)})
49+
// CHECK: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(score(3 + 5):ibm)})
50+
// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(unknown)})
4651
// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(ibm)})
4752
// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(llvm)})
48-
// CHECK-NEXT: template<> int barbar<int>();
53+
// CHECK-NEXT: template<> int barbar<int, 3>();
4954

5055
// CHECK-NEXT: int baz() {
51-
// CHECK-NEXT: return barbar<int>();
56+
// CHECK-NEXT: return barbar<int, 3>();
5257
// CHECK-NEXT: }
5358
int baz() {
54-
return barbar<int>();
59+
return barbar<int, 3>();
5560
}
5661

5762
// CHECK: template <class C> void h_ref(C *hp, C *hp2, C *hq, C *lin) {

clang/test/OpenMP/declare_variant_messages.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ int foo(void);
3030
#pragma omp declare variant(foo) match(implementation={vendor}) // expected-error {{expected '(' after 'vendor'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-error {{expected ')'}} expected-note {{to match this '('}}
3131
#pragma omp declare variant(foo) match(implementation={vendor(}) // expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-error {{expected ')'}} expected-note {{to match this '('}}
3232
#pragma omp declare variant(foo) match(implementation={vendor()}) // expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}}
33+
#pragma omp declare variant(foo) match(implementation={vendor(score ibm)}) // expected-error {{expected '(' after 'score'}} expected-warning {{missing ':' after context selector score clause - ignoring}}
34+
#pragma omp declare variant(foo) match(implementation={vendor(score( ibm)}) // expected-error {{expected ')'}} expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note {{to match this '('}}
35+
#pragma omp declare variant(foo) match(implementation={vendor(score(2 ibm)}) // expected-error 2 {{expected ')'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note 2 {{to match this '('}}
36+
#pragma omp declare variant(foo) match(implementation={vendor(score(foo()) ibm)}) // expected-warning {{missing ':' after context selector score clause - ignoring}} expected-error {{expression is not an integer constant expression}}
37+
#pragma omp declare variant(foo) match(implementation={vendor(score(5): ibm)})
3338
int bar(void);
3439

3540
// expected-error@+2 {{'#pragma omp declare variant' can only be applied to functions}}

clang/test/OpenMP/declare_variant_messages.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
int foo();
99

1010
template <typename T>
11-
T foofoo();
11+
T foofoo(); // expected-note 2 {{declared here}}
1212

1313
#pragma omp declare variant // expected-error {{expected '(' after 'declare variant'}}
1414
#pragma omp declare variant( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
@@ -33,6 +33,11 @@ T foofoo();
3333
#pragma omp declare variant(foofoo <int>) match(implementation={vendor}) // expected-error {{expected '(' after 'vendor'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-error {{expected ')'}} expected-note {{to match this '('}}
3434
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(}) // expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-error {{expected ')'}} expected-note {{to match this '('}}
3535
#pragma omp declare variant(foofoo <int>) match(implementation={vendor()}) // expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}}
36+
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score ibm)}) // expected-error {{expected '(' after 'score'}} expected-warning {{missing ':' after context selector score clause - ignoring}}
37+
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score( ibm)}) // expected-error {{expected ')'}} expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note {{to match this '('}}
38+
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score(2 ibm)}) // expected-error 2 {{expected ')'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note 2 {{to match this '('}}
39+
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score(foofoo <int>()) ibm)}) // expected-warning {{missing ':' after context selector score clause - ignoring}} expected-error {{expression is not an integral constant expression}} expected-note {{non-constexpr function 'foofoo<int>' cannot be used in a constant expression}}
40+
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score(5): ibm)})
3641
int bar();
3742

3843
#pragma omp declare variant // expected-error {{expected '(' after 'declare variant'}}
@@ -57,7 +62,12 @@ int bar();
5762
#pragma omp declare variant(foofoo <T>) match(user = {condition(<expr>)})
5863
#pragma omp declare variant(foofoo <T>) match(xxx = {vvv} xxx) // expected-error {{expected ','}} expected-error {{expected '=' after 'xxx' context selector set name on 'omp declare variant' directive}}
5964
#pragma omp declare variant(foofoo <T>) match(xxx = {vvv}) xxx // expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
60-
template <typename T>
65+
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score ibm)}) // expected-error {{expected '(' after 'score'}} expected-warning {{missing ':' after context selector score clause - ignoring}}
66+
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score( ibm)}) // expected-error {{expected ')'}} expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note {{to match this '('}}
67+
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score(C ibm)}) // expected-error 2 {{expected ')'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note 2 {{to match this '('}}
68+
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score(foofoo <int>()) ibm)}) // expected-warning {{missing ':' after context selector score clause - ignoring}} expected-error {{expression is not an integral constant expression}} expected-note {{non-constexpr function 'foofoo<int>' cannot be used in a constant expression}}
69+
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score(C+5): ibm)})
70+
template <typename T, int C>
6171
T barbar();
6272

6373
// expected-error@+2 {{'#pragma omp declare variant' can only be applied to functions}}

0 commit comments

Comments
 (0)