https://github.com/oToToT updated https://github.com/llvm/llvm-project/pull/182752
>From e297ebc28efc3b24fe131b76ca9a22ad00942440 Mon Sep 17 00:00:00 2001 From: Tommy Chiang <[email protected]> Date: Sun, 22 Feb 2026 23:59:04 +0800 Subject: [PATCH] [Sema] Guard transformed loop-hint expression before use TransformLoopHintAttr called TransformExpr(...).get() without checking that the transformed expression was usable. For `#pragma GCC unroll v()` instantiated with `v = int`, expression transformation fails and Clang can assert while validating the loop hint. Check ExprResult::isUsable() before calling get() and keep the original attribute on failure. Fixes https://github.com/llvm/llvm-project/issues/49502 --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 7 ++-- .../test/Sema/unroll-template-value-crash.cpp | 38 ++++++++++++++++++- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 37309d057fbe7..b4d8158525f04 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2166,10 +2166,11 @@ TemplateInstantiator::TransformCXXAssumeAttr(const CXXAssumeAttr *AA) { const LoopHintAttr * TemplateInstantiator::TransformLoopHintAttr(const LoopHintAttr *LH) { - Expr *TransformedExpr = getDerived().TransformExpr(LH->getValue()).get(); - - if (TransformedExpr == LH->getValue()) + ExprResult TransformedExprResult = getDerived().TransformExpr(LH->getValue()); + if (!TransformedExprResult.isUsable() || + TransformedExprResult.get() == LH->getValue()) return LH; + Expr *TransformedExpr = TransformedExprResult.get(); // Generate error if there is a problem with the value. if (getSema().CheckLoopHintExpr(TransformedExpr, LH->getLocation(), diff --git a/clang/test/Sema/unroll-template-value-crash.cpp b/clang/test/Sema/unroll-template-value-crash.cpp index cda4b897509b9..05c81959b52f2 100644 --- a/clang/test/Sema/unroll-template-value-crash.cpp +++ b/clang/test/Sema/unroll-template-value-crash.cpp @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -x c++ -verify %s -// expected-no-diagnostics template <int Unroll> void foo() { #pragma unroll Unroll @@ -33,3 +32,40 @@ void use(T t) { void test() { use(val()); } + +template <typename T> void pr49502(T v) { +#pragma GCC unroll v() // expected-error {{called object type 'int' is not a function or function pointer}} + for (;;) { + } +} + +void pr49502_caller() { + pr49502(0); // expected-note {{in instantiation of function template specialization 'pr49502<int>' requested here}} +} + +template <typename T, typename U> struct pr49502_partial; + +template <typename T> struct pr49502_partial<T, T> { + static void dependent(T v) { +#pragma GCC unroll v() // expected-error {{called object type 'int' is not a function or function pointer}} + for (;;) { + } + } + + static void mixed(T v) { +#pragma GCC unroll v() + 1 // expected-error {{called object type 'int' is not a function or function pointer}} + for (;;) { + } + } + + static void non_dependent(int v) { +#pragma GCC unroll v() // expected-error {{called object type 'int' is not a function or function pointer}} + for (;;) { + } + } +}; + +void pr49502_partial_caller() { + pr49502_partial<int, int>::dependent(0); // expected-note {{in instantiation of member function 'pr49502_partial<int, int>::dependent' requested here}} + pr49502_partial<int, int>::mixed(0); // expected-note {{in instantiation of member function 'pr49502_partial<int, int>::mixed' requested here}} +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
