Skip to content

[OpenACC/OpenMP/Parser] Teach ParseCXXInlineMethods about pragmas - #214259

Merged
erichkeane merged 2 commits into
llvm:mainfrom
erichkeane:GH214195
Aug 5, 2026
Merged

[OpenACC/OpenMP/Parser] Teach ParseCXXInlineMethods about pragmas#214259
erichkeane merged 2 commits into
llvm:mainfrom
erichkeane:GH214195

Conversation

@erichkeane

Copy link
Copy Markdown
Contributor

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

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
@llvmorg-github-actions llvmorg-github-actions Bot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:openmp OpenMP related changes to Clang labels Aug 5, 2026
@llvmorg-github-actions

Copy link
Copy Markdown

@llvm/pr-subscribers-clang

Author: Erich Keane (erichkeane)

Changes

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


Full diff: https://github.com/llvm/llvm-project/pull/214259.diff

3 Files Affected:

  • (modified) clang/lib/Parse/ParseCXXInlineMethods.cpp (+21)
  • (added) clang/test/OpenMP/gh214195.cpp (+9)
  • (modified) clang/test/ParserOpenACC/parse-constructs.cpp (+7)
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'}}
+  }
+};

Comment on lines +5 to +8
#pragma omp parallel private(bar })
// expected-error@-1{{use of undeclared identifier 'bar'}}
// expected-error@+1{{expected statement}}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised there are no diagnostic for the }

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 cor3ntin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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!

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

🐧 Linux x64 Test Results

The build failed before running any tests. Click on a failure below to see the details.

lib/Transforms/Vectorize/CMakeFiles/LLVMVectorize.dir/SLPVectorizer.cpp.o
FAILED: lib/Transforms/Vectorize/CMakeFiles/LLVMVectorize.dir/SLPVectorizer.cpp.o
sccache /opt/llvm/bin/clang++ -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GLIBCXX_USE_CXX11_ABI=1 -D_GNU_SOURCE -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/lib/Transforms/Vectorize -I/home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/lib/Transforms/Vectorize -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/include -gmlt -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wno-pass-failed -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -O3 -DNDEBUG -std=c++17 -UNDEBUG -fno-exceptions -funwind-tables -fno-rtti -MD -MT lib/Transforms/Vectorize/CMakeFiles/LLVMVectorize.dir/SLPVectorizer.cpp.o -MF lib/Transforms/Vectorize/CMakeFiles/LLVMVectorize.dir/SLPVectorizer.cpp.o.d -o lib/Transforms/Vectorize/CMakeFiles/LLVMVectorize.dir/SLPVectorizer.cpp.o -c /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
/home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp:9004:18: error: captured structured bindings are a C++20 extension [-Werror,-Wc++20-extensions]
9004 |                 [V](const TreeEntry *TE) {
|                  ^
/home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp:9001:21: note: 'V' declared here
9001 |   for (const auto &[V, Owners] : ReassocScalarToTreeEntries)
|                     ^
1 error generated.

If 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 infrastructure label.

@erichkeane
erichkeane merged commit 6f0763d into llvm:main Aug 5, 2026
11 of 13 checks passed
jinge90 pushed a commit to jinge90/llvm-project that referenced this pull request Aug 6, 2026
…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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:openmp OpenMP related changes to Clang clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[clang][OpenACC] Crash when parsing malformed #pragma acc cache directive

3 participants