llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Akash Manna (akash-manna-sky) <details> <summary>Changes</summary> Fixes #<!-- -->140074 When building the iteration count of an OpenMP loop, Sema derives a few integer types from bit widths, e.g. to promote the upper bound to an unsigned type as wide as the wider bound so that `upper - lower` cannot overflow. Those types came from `ASTContext::getIntTypeForBitwidth`, which only knows the standard integer widths and returns a null type for anything else. With a bound or loop counter of type `_BitInt(931)` the request was for a 960-bit type, the result was null, and it went straight into `PerformImplicitConversion`, which asserted. The `collapse(2)` in the reduced reproducer is incidental; a plain `#pragma omp for` on the same loop crashes the same way. The loop analysis now goes through a small helper that asks for the standard type first and otherwise builds the `_BitInt` type of that width and signedness with `ASTContext::getBitIntType`. It is used at the three places that derive a type from a loop width: the upper-bound promotion in `calculateNumIters`, the conversion to the loop variable's width in `buildNumIterations`, and the logical iteration type in `ActOnOpenMPCanonicalLoop`. Wide `_BitInt` loop variables are then narrowed to the runtime's 64-bit iteration variable with the existing warning, the same as `__int128` today. --- Full diff: https://github.com/llvm/llvm-project/pull/226464.diff 3 Files Affected: - (modified) clang/docs/ReleaseNotes.md (+2) - (modified) clang/lib/Sema/SemaOpenMP.cpp (+15-4) - (added) clang/test/OpenMP/for_loop_bitint_messages.c (+46) ``````````diff diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index f4a34a37aff52..fff1667b64967 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -965,6 +965,8 @@ The `alpha.cplusplus.UseAfterLifetimeEnd` checker was renamed to `alpha.core.Use - The `holds` clause on the `assume` directive now lowers side-effect-free conditions to `llvm.assume`, enabling downstream optimizations. Previously the clause was parsed but its condition was discarded without effect. +- Fixed a crash when the loop variable or a loop bound of an OpenMP loop has a + `_BitInt` type wider than any standard integer type. (#GH140074) ### SYCL Support diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 2e4d9f2f82f0b..4c0aee013f3c3 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -5640,6 +5640,16 @@ class CaptureVars : public TreeTransform<CaptureVars> { }; } // namespace +/// Like ASTContext::getIntTypeForBitwidth, but falls back to a _BitInt type +/// when no standard integer type has the requested width. +static QualType getIntTypeForBitwidthOrBitInt(ASTContext &C, unsigned Bits, + bool Signed) { + QualType Ty = C.getIntTypeForBitwidth(Bits, Signed); + if (Ty.isNull()) + Ty = C.getBitIntType(/*IsUnsigned=*/!Signed, Bits); + return Ty; +} + static VarDecl *precomputeExpr(Sema &Actions, SmallVectorImpl<Stmt *> &BodyStmts, Expr *E, StringRef Name) { @@ -5960,7 +5970,7 @@ StmtResult SemaOpenMP::ActOnOpenMPCanonicalLoop(Stmt *AStmt) { QualType LogicalTy = Ctx.getUnsignedPointerDiffType(); if (CounterTy->isIntegerType()) { unsigned BitWidth = Ctx.getIntWidth(CounterTy); - LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false); + LogicalTy = getIntTypeForBitwidthOrBitInt(Ctx, BitWidth, /*Signed=*/false); } // Analyze the loop increment. @@ -8953,8 +8963,9 @@ calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc, uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy); if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) || (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) { - QualType CastType = SemaRef.Context.getIntTypeForBitwidth( - LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0); + QualType CastType = getIntTypeForBitwidthOrBitInt( + SemaRef.Context, LowerSize > UpperSize ? LowerSize : UpperSize, + /*Signed=*/false); Upper = SemaRef .PerformImplicitConversion( @@ -9261,7 +9272,7 @@ Expr *OpenMPIterationSpaceChecker::buildNumIterations( UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type); bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation() : Type->hasSignedIntegerRepresentation(); - Type = C.getIntTypeForBitwidth(NewSize, IsSigned); + Type = getIntTypeForBitwidthOrBitInt(C, NewSize, IsSigned); if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) { Diff = SemaRef.PerformImplicitConversion(Diff.get(), Type, AssignmentAction::Converting, diff --git a/clang/test/OpenMP/for_loop_bitint_messages.c b/clang/test/OpenMP/for_loop_bitint_messages.c new file mode 100644 index 0000000000000..b40ec17598380 --- /dev/null +++ b/clang/test/OpenMP/for_loop_bitint_messages.c @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -fsyntax-only -fopenmp -std=c23 -triple x86_64-unknown-unknown -verify %s +// RUN: %clang_cc1 -fsyntax-only -fopenmp -fopenmp-enable-irbuilder -std=c23 -triple x86_64-unknown-unknown -verify %s +// RUN: %clang_cc1 -fsyntax-only -fopenmp-simd -std=c23 -triple x86_64-unknown-unknown -verify %s + +// RUN: %clang_cc1 -fopenmp -std=c23 -triple x86_64-unknown-unknown -emit-llvm -o - -DCODEGEN %s | FileCheck %s + +typedef _BitInt(931) B931; + +void sink(B931, B931); + +// GH140074 +// CHECK-LABEL: define {{.*}}void @gh140074_bound( +// CHECK: call void @__kmpc_for_static_init_{{4|8u?}}( +void gh140074_bound(int a, B931 b) { +#pragma omp for + for (int i = a; i < b; i++) + sink(i, b); +} + +#ifndef CODEGEN +void gh140074_reduced(int a, B931 b) { +#pragma omp for collapse(2) // expected-note {{as specified in 'collapse' clause}} + for (int i = a; i < b; i++) + sink(i, b); // expected-error {{expected 2 for loops after '#pragma omp for', but found only 1}} +} +#endif + +// CHECK-LABEL: define {{.*}}void @bitint_iv( +// CHECK: call void @__kmpc_for_static_init_{{4|8u?}}( +void bitint_iv(B931 x) { + // expected-warning@+2 {{OpenMP loop iteration variable cannot have more than 64 bits size and will be narrowed}} +#pragma omp for + for (B931 i = 0; i < x; ++i) + sink(i, x); +} + +// CHECK-LABEL: define {{.*}}void @bitint_collapse( +// CHECK: call void @__kmpc_for_static_init_{{4|8u?}}( +void bitint_collapse(B931 a, B931 b, B931 c, B931 d, B931 e, B931 f) { + // expected-warning@+3 {{OpenMP loop iteration variable cannot have more than 64 bits size and will be narrowed}} + // expected-warning@+3 {{OpenMP loop iteration variable cannot have more than 64 bits size and will be narrowed}} +#pragma omp for collapse(2) + for (B931 i = a; i < b; i += c) + for (B931 j = d; j > e; j += f) + sink(i, j); +} `````````` </details> https://github.com/llvm/llvm-project/pull/226464 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
