Skip to content

Commit 58b77b8

Browse files
committed
[OpenACC] Implement 'bind' clause parsing.
'bind' takes either a string literal, or an 'identifier' representing the device-side function that this routine is intended to 'bind' to (that is, to call). However, it seems that the intent is to permit the 'identifier' to reference any function, thus we're implementing this as an ID expression. Additionally, while working on this I discovered that the 'routine' ID expression parsing for C++ wouldn't allow non-static member functions to be referenced since it expected us to call it, this was fixed as a part of this patch as the 'bind' support needed it too. A test was added for routine.
1 parent 345c1ea commit 58b77b8

File tree

7 files changed

+130
-1
lines changed

7 files changed

+130
-1
lines changed

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,6 +1374,7 @@ def err_acc_expected_reduction_operator
13741374
def err_acc_invalid_reduction_operator
13751375
: Error<"invalid reduction operator, expected '+', '*', 'max', 'min', "
13761376
"'&', '|', '^', '&&', or '||'">;
1377+
def err_acc_incorrect_bind_arg : Error<"expected identifier or string literal">;
13771378

13781379
// OpenMP support.
13791380
def warn_pragma_omp_ignored : Warning<

clang/include/clang/Basic/OpenACCKinds.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,8 @@ enum class OpenACCClauseKind {
219219
Reduction,
220220
/// 'collapse' clause, allowed on 'loop' and Combined constructs.
221221
Collapse,
222+
/// 'bind' clause, allowed on routine constructs.
223+
Bind,
222224

223225
/// Represents an invalid clause, for the purposes of parsing.
224226
Invalid,
@@ -317,6 +319,9 @@ inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
317319
case OpenACCClauseKind::Collapse:
318320
return Out << "collapse";
319321

322+
case OpenACCClauseKind::Bind:
323+
return Out << "bind";
324+
320325
case OpenACCClauseKind::Invalid:
321326
return Out << "<invalid>";
322327
}

clang/include/clang/Parse/Parser.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3581,6 +3581,9 @@ class Parser : public CodeCompletionHandler {
35813581
/// Parses the clause-list for an OpenACC directive.
35823582
void ParseOpenACCClauseList(OpenACCDirectiveKind DirKind);
35833583
bool ParseOpenACCWaitArgument();
3584+
/// Parses the clause of the 'bind' argument, which can be a string literal or
3585+
/// an ID expression.
3586+
ExprResult ParseOpenACCBindClauseArgument();
35843587

35853588
private:
35863589
//===--------------------------------------------------------------------===//

clang/lib/Parse/ParseOpenACC.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ OpenACCClauseKind getOpenACCClauseKind(Token Tok) {
9191
Tok.getIdentifierInfo()->getName())
9292
.Case("attach", OpenACCClauseKind::Attach)
9393
.Case("auto", OpenACCClauseKind::Auto)
94+
.Case("bind", OpenACCClauseKind::Bind)
9495
.Case("create", OpenACCClauseKind::Create)
9596
.Case("collapse", OpenACCClauseKind::Collapse)
9697
.Case("copy", OpenACCClauseKind::Copy)
@@ -467,6 +468,7 @@ ClauseParensKind getClauseParensKind(OpenACCDirectiveKind DirKind,
467468
case OpenACCClauseKind::Host:
468469
case OpenACCClauseKind::Reduction:
469470
case OpenACCClauseKind::Collapse:
471+
case OpenACCClauseKind::Bind:
470472
return ClauseParensKind::Required;
471473

472474
case OpenACCClauseKind::Auto:
@@ -668,6 +670,12 @@ bool Parser::ParseOpenACCClauseParams(OpenACCDirectiveKind DirKind,
668670
return true;
669671
break;
670672
}
673+
case OpenACCClauseKind::Bind: {
674+
ExprResult BindArg = ParseOpenACCBindClauseArgument();
675+
if (BindArg.isInvalid())
676+
return true;
677+
break;
678+
}
671679
default:
672680
llvm_unreachable("Not a required parens type?");
673681
}
@@ -758,7 +766,7 @@ bool Parser::ParseOpenACCWaitArgument() {
758766
ExprResult Parser::ParseOpenACCIDExpression() {
759767
ExprResult Res;
760768
if (getLangOpts().CPlusPlus) {
761-
Res = ParseCXXIdExpression(/*isAddressOfOperand=*/false);
769+
Res = ParseCXXIdExpression(/*isAddressOfOperand=*/true);
762770
} else {
763771
// There isn't anything quite the same as ParseCXXIdExpression for C, so we
764772
// need to get the identifier, then call into Sema ourselves.
@@ -785,6 +793,25 @@ ExprResult Parser::ParseOpenACCIDExpression() {
785793
return getActions().CorrectDelayedTyposInExpr(Res);
786794
}
787795

796+
ExprResult Parser::ParseOpenACCBindClauseArgument() {
797+
// OpenACC 3.3 section 2.15:
798+
// The bind clause specifies the name to use when calling the procedure on a
799+
// device other than the host. If the name is specified as an identifier, it
800+
// is called as if that name were specified in the language being compiled. If
801+
// the name is specified as a string, the string is used for the procedure
802+
// name unmodified.
803+
if (getCurToken().is(tok::r_paren)) {
804+
Diag(getCurToken(), diag::err_acc_incorrect_bind_arg);
805+
return ExprError();
806+
}
807+
808+
if (tok::isStringLiteral(getCurToken().getKind()))
809+
return getActions().CorrectDelayedTyposInExpr(ParseStringLiteralExpression(
810+
/*AllowUserDefinedLiteral=*/false, /*Unevaluated=*/true));
811+
812+
return ParseOpenACCIDExpression();
813+
}
814+
788815
/// OpenACC 3.3, section 1.6:
789816
/// In this spec, a 'var' (in italics) is one of the following:
790817
/// - a variable name (a scalar, array, or compisite variable name)

clang/test/ParserOpenACC/parse-clauses.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,3 +706,26 @@ void bar();
706706

707707
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
708708
#pragma acc routine(bar) worker, vector, seq, nohost
709+
710+
711+
// Bind Clause Parsing.
712+
713+
// expected-error@+2{{expected '('}}
714+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
715+
#pragma acc routine bind
716+
void BCP1();
717+
718+
// expected-error@+2{{expected identifier or string literal}}
719+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
720+
#pragma acc routine(BCP1) bind()
721+
722+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
723+
#pragma acc routine bind("ReductionClauseParsing")
724+
void BCP2();
725+
726+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
727+
#pragma acc routine(BCP1) bind(BCP2)
728+
729+
// expected-error@+2{{use of undeclared identifier 'unknown_thing'}}
730+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
731+
#pragma acc routine(BCP1) bind(unknown_thing)

clang/test/ParserOpenACC/parse-clauses.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,56 @@ struct S {
1818
void use() {
1919
templ<7, S>();
2020
}
21+
22+
namespace NS {
23+
void NSFunc();
24+
25+
class RecordTy { // #RecTy
26+
static constexpr bool Value = false; // #VAL
27+
void priv_mem_function(); // #PrivMemFun
28+
public:
29+
static constexpr bool ValuePub = true;
30+
void mem_function();
31+
};
32+
template<typename T>
33+
class TemplTy{};
34+
void function();
35+
}
36+
37+
38+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
39+
#pragma acc routine(use) bind(NS::NSFunc)
40+
// expected-error@+3{{'RecordTy' does not refer to a value}}
41+
// expected-note@#RecTy{{declared here}}
42+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
43+
#pragma acc routine(use) bind(NS::RecordTy)
44+
// expected-error@+3{{'Value' is a private member of 'NS::RecordTy'}}
45+
// expected-note@#VAL{{implicitly declared private here}}
46+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
47+
#pragma acc routine(use) bind(NS::RecordTy::Value)
48+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
49+
#pragma acc routine(use) bind(NS::RecordTy::ValuePub)
50+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
51+
#pragma acc routine(use) bind(NS::TemplTy<int>)
52+
// expected-error@+2{{no member named 'unknown' in namespace 'NS'}}
53+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
54+
#pragma acc routine(use) bind(NS::unknown<int>)
55+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
56+
#pragma acc routine(use) bind(NS::function)
57+
// expected-error@+3{{'priv_mem_function' is a private member of 'NS::RecordTy'}}
58+
// expected-note@#PrivMemFun{{implicitly declared private here}}
59+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
60+
#pragma acc routine(use) bind(NS::RecordTy::priv_mem_function)
61+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
62+
#pragma acc routine(use) bind(NS::RecordTy::mem_function)
63+
64+
// expected-error@+2{{string literal with user-defined suffix cannot be used here}}
65+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
66+
#pragma acc routine(use) bind("unknown udl"_UDL)
67+
68+
// expected-warning@+2{{encoding prefix 'u' on an unevaluated string literal has no effect}}
69+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
70+
#pragma acc routine(use) bind(u"16 bits")
71+
// expected-warning@+2{{encoding prefix 'U' on an unevaluated string literal has no effect}}
72+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
73+
#pragma acc routine(use) bind(U"32 bits")

clang/test/ParserOpenACC/parse-constructs.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ namespace NS {
55

66
template<typename T>
77
void templ(); // expected-note 2{{declared here}}
8+
9+
class C { // #CDef
10+
void private_mem_func(); // #PrivateMemFunc
11+
public:
12+
void public_mem_func();
13+
};
814
}
915

1016
// expected-error@+2{{use of undeclared identifier 'foo'; did you mean 'NS::foo'?}}
@@ -44,3 +50,14 @@ namespace NS {
4450
// expected-error@+2 {{expected unqualified-id}}
4551
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
4652
#pragma acc routine(int)
53+
54+
// expected-error@+3{{'C' does not refer to a value}}
55+
// expected-note@#CDef{{declared here}}
56+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
57+
#pragma acc routine (NS::C)
58+
// expected-error@+3{{'private_mem_func' is a private member of 'NS::C'}}
59+
// expected-note@#PrivateMemFunc{{implicitly declared private here}}
60+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
61+
#pragma acc routine (NS::C::private_mem_func)
62+
// expected-warning@+1{{OpenACC directives not yet implemented, pragma ignored}}
63+
#pragma acc routine (NS::C::public_mem_func)

0 commit comments

Comments
 (0)