[OpenACC/OpenMP/Parser] Teach ParseCXXInlineMethods about pragmas - #214259
Conversation
Both OMP and OpenACC count on being able to reach their end-annotation token in order to properly recover from errors/leave the parser in good shape. This works well for 'free' functions. However, when we do a pre-parse so we can delay-evaluate member functions, a stray end-brace can end up matching the end of the function. As a result, the examples in the test would have that brace ending with an EOF, which confused both of the pragma languages. This patch teaches the ParseCXXInlineMethods functionality to ignore any braces/etc inside of a OpenACC/OpenMP pragma for the purposes of matching, since these shouldn't count towards that scoping anyway. Fixes: llvm#214195
|
@llvm/pr-subscribers-clang Author: Erich Keane (erichkeane) ChangesBoth OMP and OpenACC count on being able to reach their end-annotation token in order to properly recover from errors/leave the parser in good shape. This works well for 'free' functions. However, when we do a pre-parse so we can delay-evaluate member functions, a stray end-brace can end up matching the end of the function. As a result, the examples in the test would have that brace ending with an EOF, which confused both of the pragma languages. This patch teaches the ParseCXXInlineMethods functionality to ignore any braces/etc inside of a OpenACC/OpenMP pragma for the purposes of matching, since these shouldn't count towards that scoping anyway. Fixes: #214195 Full diff: https://github.com/llvm/llvm-project/pull/214259.diff 3 Files Affected:
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp
index be531e567046e..3f101feb26a6d 100644
--- a/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -870,6 +870,27 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
// Ran out of tokens.
return false;
+ case tok::annot_pragma_openacc:
+ case tok::annot_pragma_openmp:
+ case tok::annot_attr_openmp: {
+ // Ignore any tokens inside of a OMP/OpenACC pragma, as these should just
+ // be taken as 1.
+ tok::TokenKind EndKind = Tok.is(tok::annot_pragma_openacc)
+ ? tok::annot_pragma_openacc_end
+ : tok::annot_pragma_openmp_end;
+ Toks.push_back(Tok);
+ ConsumeAnnotationToken();
+ while (Tok.isNot(EndKind) && Tok.isNot(tok::eof)) {
+ Toks.push_back(Tok);
+ ConsumeAnyToken();
+ }
+ if (Tok.is(EndKind)) {
+ Toks.push_back(Tok);
+ ConsumeAnnotationToken();
+ }
+ break;
+ }
+
case tok::l_paren:
// Recursively consume properly-nested parens.
Toks.push_back(Tok);
diff --git a/clang/test/OpenMP/gh214195.cpp b/clang/test/OpenMP/gh214195.cpp
new file mode 100644
index 0000000000000..3247922412beb
--- /dev/null
+++ b/clang/test/OpenMP/gh214195.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 %s -verify -fopenmp
+
+struct Type {
+ void foo() {
+#pragma omp parallel private(bar })
+ // expected-error@-1{{use of undeclared identifier 'bar'}}
+ // expected-error@+1{{expected statement}}
+ }
+};
diff --git a/clang/test/ParserOpenACC/parse-constructs.cpp b/clang/test/ParserOpenACC/parse-constructs.cpp
index 6d6285ce63bd2..abe3de899abc9 100644
--- a/clang/test/ParserOpenACC/parse-constructs.cpp
+++ b/clang/test/ParserOpenACC/parse-constructs.cpp
@@ -58,3 +58,10 @@ void foo() {
auto y = [](){};
#pragma acc routine (x) seq
}
+
+struct GH214195 {
+ void foo() {
+#pragma acc cache(bar })
+ // expected-error@-1{{use of undeclared identifier 'bar'}}
+ }
+};
|
| #pragma omp parallel private(bar }) | ||
| // expected-error@-1{{use of undeclared identifier 'bar'}} | ||
| // expected-error@+1{{expected statement}} | ||
| } |
There was a problem hiding this comment.
I'm surprised there are no diagnostic for the }
There was a problem hiding this comment.
Both languages are treating "parse-assignment-expr" as a "just give up". Recovery from a parse assignment expression failure is really tough, so both languages 'punt' (the Expected-statement is because omp parallel has an associated statement, so after the pragma it tries to parse a statement).
cor3ntin
left a comment
There was a problem hiding this comment.
This change needs a release note.
Please add an entry to clang/docs/ReleaseNotes.md in the section the most adapted to the change, and referencing any Github issue this change fixes. Thanks!
🐧 Linux x64 Test ResultsThe build failed before running any tests. Click on a failure below to see the details. lib/Transforms/Vectorize/CMakeFiles/LLVMVectorize.dir/SLPVectorizer.cpp.oIf these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the |
…vm#214259) Both OMP and OpenACC count on being able to reach their end-annotation token in order to properly recover from errors/leave the parser in good shape. This works well for 'free' functions. However, when we do a pre-parse so we can delay-evaluate member functions, a stray end-brace can end up matching the end of the function. As a result, the examples in the test would have that brace ending with an EOF, which confused both of the pragma languages. This patch teaches the ParseCXXInlineMethods functionality to ignore any braces/etc inside of a OpenACC/OpenMP pragma for the purposes of matching, since these shouldn't count towards that scoping anyway. Fixes: llvm#214195
Both OMP and OpenACC count on being able to reach their end-annotation token in order to properly recover from errors/leave the parser in good shape. This works well for 'free' functions.
However, when we do a pre-parse so we can delay-evaluate member functions, a stray end-brace can end up matching the end of the function. As a result, the examples in the test would have that brace ending with an EOF, which confused both of the pragma languages.
This patch teaches the ParseCXXInlineMethods functionality to ignore any braces/etc inside of a OpenACC/OpenMP pragma for the purposes of matching, since these shouldn't count towards that scoping anyway.
Fixes: #214195