Pull Request已成功合入, 合并人@cangjie-ci
(感谢 wangyinqiang 的贡献)PR创建成功通知 | 感谢您的贡献 🎉
您好!系统已检测到您成功创建 Pull Request(PR),感谢您对项目的支持与参与!以下几点需要您着重关注:
一、PR必须关联Issue ❗️
触发门禁检查的必要步骤:在PR描述框输入Issue完整链接,完成Issue关联。
请注意,一个 Issue 不能同时关联同一 base 仓库内同一个分支的多个开启状态的 PR
二、门禁触发规则 🔧
- 门禁类型判定:由Issue关联的PR所属代码仓数量决定
- 关联多个代码仓PR:触发「多仓联合门禁」
- 关联单个代码仓PR:触发「单仓门禁」
- 启动指令与检查范围:需主动回复指令:
- 回复 "start build":执行Cangjie的主要基础检查,包含commit格式检查、静态告警分析、OAT开源声明检查、多平台构建、单元/集成测试等
- 关联同一issue的多个PR,仅需在任意一个PR里回复触发一次门禁,该PR门禁通过后,所有PR都会添加Label和测试人
- 每个pr只能同时运行一条CI流水线,如需重新启动,请先关闭运行中的,再评论触发门禁
- Markdown修改仅触发文档类构建测试门禁,不会触发Cangjie的编译测试门禁
- commit 信息格式请遵循:Conventional Commits 规范
- 请保证每一条 commit 都已添加
Signed-Off-By信息
三、合入条件 ⚠️
- 满足最低评审人数,且评审问题需全部解决;
- 禁止合入本人创建的PR,需由其他协作者操作;
- 合并前确保关联流水线任务运行成功(build-test-passed)。
四、合并PR ✅
回复 "start merge",CI流水线会自动检查所有关联PR的状态、版本号标签、检视意见密度、兼容性,若所有PR都满足合并条件,则将会同时合并所有PR。若存在不满足合并条件的PR,则不会合并任何PR。
如果希望不进行兼容性相关的检测,请任一合法审查人复制以下内容,在 start merge 前提交评论:
本 pr 不需要兼容性相关检测,对于引发的任何兼容性问题(即由于本 pr 合入将导致用户需适配代码的话),由本人承担。
If you wish to avoid compatibility-related checks, please have any approver copy the following content and submit it as a comment before sending start merge:
This PR does not require compatibility-related checks. For any compatibility issues caused by this PR (i.e., if the integration of this PR will require users to adapt their code), I will take full responsibility.
五、补充说明 📢
- 详细仓颉贡献流程:贡献流程(Cangjie Community Contribution)
- 门禁结果将自动评论至关联的所有PR,敬请留意。


start build


start merge


⏳ 正在进行兼容性检测中,可能需要2~3分钟,请稍候,若10分钟无检测结果,请重新回复 start merge。
⏳ Compatibility check in progress. It may take 2–3 minutes. Please wait. If there is no result after 10 minutes, please reply with start merge again.


✅ 合入前兼容性检测通过。
涉及仓库:Cangjie/cangjie_compiler, Cangjie/cangjie_test
结论
- 分析过程:分析 Cangjie/cangjie_compiler#1934:核对父提交 6a5e48f8 到 PR head 55ee950e 的完整差异,确认仅修改 src/CHIR/AST2CHIR/TranslateASTNode/TranslateAssignExpr.cpp 中复合赋值 VARRAY_GET 的 DebugLocation 传递;进一步检查 CHIR 范围诊断消费路径以及同类 VARRAY_SET/VARRAY_GET 构造方式,未发现公开 .cj API、ABI、跨组件符号、CLI、构建打包或成功编译路径变化。 Analyzed Cangjie/cangjie_compiler#1934 by reviewing the complete parent-to-head diff, the CHIR range-diagnostic consumer, and matching VARRAY_SET/VARRAY_GET construction patterns; no public API, ABI, cross-component symbol, CLI, packaging, or successful-compilation contract changed.
- 原因:兼容。旧版本在 VArray 复合赋值的越界下标可被静态判定时,会因 VARRAY_GET 缺少源码位置而触发内部编译器错误;新版本仅在 src/CHIR/AST2CHIR/TranslateASTNode/TranslateAssignExpr.cpp:86 将同一赋值表达式的 loc 传入 Intrinsic,供 src/CHIR/Optimization/RangePropagation.cpp:269 生成正常的越界诊断。合法源码的语义、生成代码和接口不变;变化仅把非法程序的 ICE/exit=2 修复为带源码位置的普通编译错误/exit=1,属于错误处理改善,不构成兼容性破坏。 Compatible: the change only attaches the assignment DebugLocation to VARRAY_GET so an out-of-bounds invalid program receives a normal diagnostic instead of an internal compiler error; valid-program semantics, generated code, and exposed contracts remain unchanged.
- 结论:兼容


✅ 以下PR将同时合入:
- Cangjie/cangjie_compiler#1934: fix(chir): pass source location to VARRAY_GET in compound assign to avoid ICE
- Cangjie/cangjie_test#2021: test(chir): cover VArray compound-assign out-of-bounds diagnostic
✅ The following PRs will be merged simultaneously:
- Cangjie/cangjie_compiler#1934: fix(chir): pass source location to VARRAY_GET in compound assign to avoid ICE
- Cangjie/cangjie_test#2021: test(chir): cover VArray compound-assign out-of-bounds diagnostic


变更内容(必填)
修复 cjc 编译 ICE(Internal Compiler Error: begin of range is zero, error code 12)。
问题:在
TranslateVArrayAssign中,复合赋值运算符(+=、-=、&=、^=、|=等普通复合赋值,以及走短路分支的&&=、||=)的左侧 VARRAY_GET intrinsic 创建时未传递源码位置(source location)。只要 CHIR 能把该下标判定为越界常量,越界诊断就会在零 DebugLocation 上发射,进而在DiagnosticEngineImpl::CheckRange触发InternalError。触发条件不限于 -O2:
var b = 4; test[b] |= 1)时,ConstAnalysis即可判定越界并发射诊断 → ICE。m[42 / getSize<Int64>()] |= 42这种 const func 运算)后,由RangePropagation发射诊断 → ICE。两条路径共用同一个缺失 loc 的 VARRAY_GET,故一行修复同时覆盖。
修复:在
TranslateAssignExpr.cpp:86为CreateAndAppendExpression<Intrinsic>调用补上loc首参,使其与同文件:113处CreateAndAppendVArraySet的模式一致。修复后复合赋值越界下标由 ICE 改为正常诊断 "array index is out of bounds" 并指向赋值表达式源码位置。关于位置参数的选择:VARRAY_GET 传的是
loc(整条 AssignExpr)而非上方第 81 行算好却未使用的baseLoc,这是有意的——用loc才能与同一条复合赋值生成的 VARRAY_SET 同址,两条内容相同的越界诊断被DiagnosticEngine去重成一条;若改用baseLoc,同一条语句会报两条重复诊断。(baseLoc是既有死变量,属无关改动,未在本 PR 中清理。)行为变化说明:修复前,VArray 复合赋值越界下标触发 ICE(exit=2);修复后,输出正常诊断错误并以 exit=1 正常退出。这是从非法行为到正确诊断的改善,非回归。
同类问题排查:
src/CHIR下其余CreateAndAppendExpression<Intrinsic>调用已核对——VArray 读路径(TranslateSubscriptExpr.cpp:115)本来就传了loc(本地实测读越界下标在修复前后都能正常诊断,不受影响);剩余未传loc的只有PREINITIALIZE(GlobalVarInitializer.cpp:701)和BEGIN_CATCH(TranslateTryExpr.cpp:149,以及TranslateForInExpr.cpp:551与其#else非 CJNATIVE 后端分支:553)这类编译器生成节点,本身没有对应用户源码位置,也不参与范围检查诊断。因此本 PR 一行改动即覆盖该 ICE 的全部触发路径。回归用例:配套用例在 https://gitcode.com/Cangjie/cangjie_test/pulls/2021 (同一 issue 关联,多仓联合门禁)。
详见:https://gitcode.com/Cangjie/UsersForum/issues/3351
变更类型(必填)
变更内容自检(必填)
平台差异情况:
影响组件:
编译本地自验证结果:
测试用例本地自验证结果:
验证情况:
var b = 4; test[b] |= 1):修复前同样 ICE exit=2(诊断由 ConstAnalysis 发射),修复后正确诊断 "array index 4 is past the end of array" + exit=1LLT/compiler/CHIR/ConstantSafetyCheck/VArrayIndexOutOfBounds/,与漏掉本缺陷的既有用例varrayAsg01.cj并列:varrayAsg02.cj:不依赖优化选项,下标为普通变量,覆盖 ConstAnalysis 发射路径与TranslateVArrayAssign三个分支(|=、+=普通复合赋值;&&=AND_ASSIGN;||=OR_ASSIGN),/* SCAN */逐字符比对 4 条诊断varrayAsg03.cj/varrayAsg04.cj:%enableO2折叠 const func 下标后由 RangePropagation 报出,分别对应越上界 / 越下界,/* SCAN */比对诊断位置与文本--level=0:目录内 5 个用例全 PASS;换用修复前的 cjc,三个新增用例均 FAIL;变异测试(改期望行号 / 改 range 数值 / 去掉%enableO2)均 FAIL,确认断言非空转关联的issue(必填)
https://gitcode.com/Cangjie/UsersForum/issues/3351