https://github.com/akash-manna-sky updated https://github.com/llvm/llvm-project/pull/228914
>From aa2addf995c8bdfea74305fe4f1ed657cd87eb3c Mon Sep 17 00:00:00 2001 From: Akash Manna <[email protected]> Date: Sun, 4 Oct 2026 21:40:48 +0530 Subject: [PATCH 1/2] [Clang][OpenMP] Fix crash on `atomic` with an erroneous statement A statement under `#pragma omp atomic` that already has an error, such as `0--;`, reaches OpenMPAtomicUpdateChecker as a RecoveryExpr. The checker reported it with the NotAValidExpression code, which has no matching option in note_omp_atomic_update, so formatting the note hit an assertion. Return early without a diagnostic when the expression contains errors, and remove NotAValidExpression so the error codes match the note again. Fixes #107979 --- clang/docs/ReleaseNotes.md | 2 ++ clang/lib/Sema/SemaOpenMP.cpp | 9 ++------ clang/test/OpenMP/atomic_messages.c | 32 ++++++++++++++++++++++----- clang/test/OpenMP/atomic_messages.cpp | 32 ++++++++++++++++++++++----- 4 files changed, 56 insertions(+), 19 deletions(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index bf194e87f76a6..4d08c8c390c46 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -1077,6 +1077,8 @@ The `alpha.cplusplus.UseAfterLifetimeEnd` checker was renamed to `alpha.core.Use - Added the OpenMP 6.1 `#pragma omp flatten` loop transformation and the `depth` clause. Flatten combines perfectly nested canonical loops into one loop. `depth(k)` selects how many outermost loops to combine (default 2). +- Fixed a crash when the statement of an OpenMP `atomic` directive contains an + invalid expression, such as `0--;`. (#GH107979) - Canonicalize intra-tiles in loop tiling. `#pragma omp tile` still emits a min-bounded inner loop, which vectorizes well. When a parent directive such as `for collapse(n)` needs a constant per-tile trip count, Clang rereads a diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index efc570a8933f1..9b7b9b36e42c1 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -12467,9 +12467,6 @@ class OpenMPAtomicUpdateChecker { /// RHS binary operation does not have reference to the updated LHS /// part. NotAnUpdateExpression, - /// An expression contains semantical error not related to - /// 'omp atomic [update]' - NotAValidExpression, /// No errors is found. NoError }; @@ -12610,6 +12607,8 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId, // x = expr binop x; if (auto *AtomicBody = dyn_cast<Expr>(S)) { AtomicBody = AtomicBody->IgnoreParenImpCasts(); + if (AtomicBody->containsErrors()) + return true; if (AtomicBody->getType()->isScalarType() || AtomicBody->isInstantiationDependent()) { if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>( @@ -12647,10 +12646,6 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId, ErrorFound = NotABinaryOrUnaryExpression; NoteLoc = ErrorLoc = AtomicBody->getExprLoc(); NoteRange = ErrorRange = AtomicBody->getSourceRange(); - } else if (AtomicBody->containsErrors()) { - ErrorFound = NotAValidExpression; - NoteLoc = ErrorLoc = AtomicBody->getExprLoc(); - NoteRange = ErrorRange = AtomicBody->getSourceRange(); } } else { ErrorFound = NotAScalarType; diff --git a/clang/test/OpenMP/atomic_messages.c b/clang/test/OpenMP/atomic_messages.c index f4e7db52494af..991dc916f2d2b 100644 --- a/clang/test/OpenMP/atomic_messages.c +++ b/clang/test/OpenMP/atomic_messages.c @@ -1,10 +1,10 @@ -// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp -fopenmp-version=45 -ferror-limit 100 %s -Wuninitialized -// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp -fopenmp-version=50 -ferror-limit 100 %s -Wuninitialized -// RUN: %clang_cc1 -DOMP51 -verify=expected,omp50,omp51 -fopenmp -ferror-limit 100 %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp -fopenmp-version=45 -ferror-limit 150 %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp -fopenmp-version=50 -ferror-limit 150 %s -Wuninitialized +// RUN: %clang_cc1 -DOMP51 -verify=expected,omp50,omp51 -fopenmp -ferror-limit 150 %s -Wuninitialized -// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 %s -Wuninitialized -// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-simd -fopenmp-version=50 -ferror-limit 100 %s -Wuninitialized -// RUN: %clang_cc1 -DOMP51 -verify=expected,omp50,omp51 -fopenmp-simd -ferror-limit 100 %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp-simd -fopenmp-version=45 -ferror-limit 150 %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-simd -fopenmp-version=50 -ferror-limit 150 %s -Wuninitialized +// RUN: %clang_cc1 -DOMP51 -verify=expected,omp50,omp51 -fopenmp-simd -ferror-limit 150 %s -Wuninitialized void xxx(int argc) { int x; // expected-note {{initialize the variable 'x' to silence this warning}} @@ -397,6 +397,26 @@ void hint(void) { a += 1; } +void gh107979(void) { + int x = 0, v = 0; +#pragma omp atomic + 0--; // expected-error {{expression is not assignable}} +#pragma omp atomic + --0; // expected-error {{expression is not assignable}} +#pragma omp atomic + 0++; // expected-error {{expression is not assignable}} +#pragma omp atomic update + 0 += 1; // expected-error {{expression is not assignable}} +#pragma omp atomic + x += 0--; // expected-error {{expression is not assignable}} +#pragma omp atomic capture + v = 0--; // expected-error {{expression is not assignable}} +#pragma omp atomic capture + { v = x; x += 0--; } // expected-error {{expression is not assignable}} +#pragma omp atomic + x--; +} + #ifdef OMP51 extern void bbar(void); extern int ffoo(void); diff --git a/clang/test/OpenMP/atomic_messages.cpp b/clang/test/OpenMP/atomic_messages.cpp index c4e240a0ebb4e..188f4faa3b873 100644 --- a/clang/test/OpenMP/atomic_messages.cpp +++ b/clang/test/OpenMP/atomic_messages.cpp @@ -1,10 +1,10 @@ -// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp -fopenmp-version=45 -ferror-limit 150 %s -Wuninitialized -// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp -fopenmp-version=50 -ferror-limit 150 %s -Wuninitialized -// RUN: %clang_cc1 -DOMP51 -verify=expected,omp50,omp51 -fopenmp -ferror-limit 150 %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp -fopenmp-version=45 -ferror-limit 200 %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp -fopenmp-version=50 -ferror-limit 200 %s -Wuninitialized +// RUN: %clang_cc1 -DOMP51 -verify=expected,omp50,omp51 -fopenmp -ferror-limit 200 %s -Wuninitialized -// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp-simd -fopenmp-version=45 -ferror-limit 150 %s -Wuninitialized -// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-simd -fopenmp-version=50 -ferror-limit 150 %s -Wuninitialized -// RUN: %clang_cc1 -DOMP51 -verify=expected,omp50,omp51 -fopenmp-simd -ferror-limit 150 %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp45 -fopenmp-simd -fopenmp-version=45 -ferror-limit 200 %s -Wuninitialized +// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-simd -fopenmp-version=50 -ferror-limit 200 %s -Wuninitialized +// RUN: %clang_cc1 -DOMP51 -verify=expected,omp50,omp51 -fopenmp-simd -ferror-limit 200 %s -Wuninitialized int foo() { L1: @@ -992,6 +992,26 @@ int mixed() { return mixed<int>(); } +void gh107979() { + int x = 0, v = 0; +#pragma omp atomic + 0--; // expected-error {{expression is not assignable}} +#pragma omp atomic + --0; // expected-error {{expression is not assignable}} +#pragma omp atomic + 0++; // expected-error {{expression is not assignable}} +#pragma omp atomic update + 0 += 1; // expected-error {{expression is not assignable}} +#pragma omp atomic + x += 0--; // expected-error {{expression is not assignable}} +#pragma omp atomic capture + v = 0--; // expected-error {{expression is not assignable}} +#pragma omp atomic capture + { v = x; x += 0--; } // expected-error {{expression is not assignable}} +#pragma omp atomic + x--; +} + #ifdef OMP51 struct U {}; struct U operator<(U, U); >From e2431eb2a373938af6475c7ba53e6921b6f13eec Mon Sep 17 00:00:00 2001 From: Akash Manna <[email protected]> Date: Mon, 5 Oct 2026 10:28:12 +0530 Subject: [PATCH 2/2] Add the missing %select option instead of removing the error code Keep NotAValidExpression and give note_omp_atomic_update a matching option. The early return on containsErrors() also rejected valid statements that only refer to a variable with an erroneous initializer. --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 ++- clang/lib/Sema/SemaOpenMP.cpp | 9 +++++++-- clang/test/OpenMP/atomic_messages.c | 15 ++++++++++++--- clang/test/OpenMP/atomic_messages.cpp | 15 ++++++++++++--- 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 9208aba1445d7..d1ace2592e703 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -12398,7 +12398,8 @@ def err_omp_atomic_not_expression_statement : Error< def note_omp_atomic_update: Note< "%select{expected an expression statement|expected built-in binary or unary operator|expected unary decrement/increment operation|" "expected expression of scalar type|expected assignment expression|expected built-in binary operator|" - "expected one of '+', '*', '-', '/', '&', '^', '%|', '<<', or '>>' built-in operations|expected in right hand side of expression}0">; + "expected one of '+', '*', '-', '/', '&', '^', '%|', '<<', or '>>' built-in operations|expected in right hand side of expression|" + "expected a valid expression}0">; def err_omp_atomic_capture_not_expression_statement : Error< "the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x'," " where x and v are both lvalue expressions with scalar type">; diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 9b7b9b36e42c1..efc570a8933f1 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -12467,6 +12467,9 @@ class OpenMPAtomicUpdateChecker { /// RHS binary operation does not have reference to the updated LHS /// part. NotAnUpdateExpression, + /// An expression contains semantical error not related to + /// 'omp atomic [update]' + NotAValidExpression, /// No errors is found. NoError }; @@ -12607,8 +12610,6 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId, // x = expr binop x; if (auto *AtomicBody = dyn_cast<Expr>(S)) { AtomicBody = AtomicBody->IgnoreParenImpCasts(); - if (AtomicBody->containsErrors()) - return true; if (AtomicBody->getType()->isScalarType() || AtomicBody->isInstantiationDependent()) { if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>( @@ -12646,6 +12647,10 @@ bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId, ErrorFound = NotABinaryOrUnaryExpression; NoteLoc = ErrorLoc = AtomicBody->getExprLoc(); NoteRange = ErrorRange = AtomicBody->getSourceRange(); + } else if (AtomicBody->containsErrors()) { + ErrorFound = NotAValidExpression; + NoteLoc = ErrorLoc = AtomicBody->getExprLoc(); + NoteRange = ErrorRange = AtomicBody->getSourceRange(); } } else { ErrorFound = NotAScalarType; diff --git a/clang/test/OpenMP/atomic_messages.c b/clang/test/OpenMP/atomic_messages.c index 991dc916f2d2b..48203c5fbbc15 100644 --- a/clang/test/OpenMP/atomic_messages.c +++ b/clang/test/OpenMP/atomic_messages.c @@ -400,19 +400,28 @@ void hint(void) { void gh107979(void) { int x = 0, v = 0; #pragma omp atomic + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an lvalue expression with scalar type}} + // expected-note@+1 {{expected a valid expression}} 0--; // expected-error {{expression is not assignable}} #pragma omp atomic + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an lvalue expression with scalar type}} + // expected-note@+1 {{expected a valid expression}} --0; // expected-error {{expression is not assignable}} #pragma omp atomic + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an lvalue expression with scalar type}} + // expected-note@+1 {{expected a valid expression}} 0++; // expected-error {{expression is not assignable}} #pragma omp atomic update + // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an lvalue expression with scalar type}} + // expected-note@+1 {{expected a valid expression}} 0 += 1; // expected-error {{expression is not assignable}} -#pragma omp atomic - x += 0--; // expected-error {{expression is not assignable}} #pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both lvalue expressions with scalar type}} + // expected-note@+1 {{expected a valid expression}} v = 0--; // expected-error {{expression is not assignable}} + int w = 0--; // expected-error {{expression is not assignable}} #pragma omp atomic capture - { v = x; x += 0--; } // expected-error {{expression is not assignable}} + { v = w; w++; } #pragma omp atomic x--; } diff --git a/clang/test/OpenMP/atomic_messages.cpp b/clang/test/OpenMP/atomic_messages.cpp index 188f4faa3b873..05a51dc76c9cb 100644 --- a/clang/test/OpenMP/atomic_messages.cpp +++ b/clang/test/OpenMP/atomic_messages.cpp @@ -995,19 +995,28 @@ int mixed() { void gh107979() { int x = 0, v = 0; #pragma omp atomic + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an lvalue expression with scalar type}} + // expected-note@+1 {{expected a valid expression}} 0--; // expected-error {{expression is not assignable}} #pragma omp atomic + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an lvalue expression with scalar type}} + // expected-note@+1 {{expected a valid expression}} --0; // expected-error {{expression is not assignable}} #pragma omp atomic + // expected-error@+2 {{the statement for 'atomic' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an lvalue expression with scalar type}} + // expected-note@+1 {{expected a valid expression}} 0++; // expected-error {{expression is not assignable}} #pragma omp atomic update + // expected-error@+2 {{the statement for 'atomic update' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x', where x is an lvalue expression with scalar type}} + // expected-note@+1 {{expected a valid expression}} 0 += 1; // expected-error {{expression is not assignable}} -#pragma omp atomic - x += 0--; // expected-error {{expression is not assignable}} #pragma omp atomic capture + // expected-error@+2 {{the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x', where x and v are both lvalue expressions with scalar type}} + // expected-note@+1 {{expected a valid expression}} v = 0--; // expected-error {{expression is not assignable}} + int w = 0--; // expected-error {{expression is not assignable}} #pragma omp atomic capture - { v = x; x += 0--; } // expected-error {{expression is not assignable}} + { v = w; w++; } #pragma omp atomic x--; } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
