Draft
Fix incomplete type checking for arrays with struct element types#2
Conversation
Co-authored-by: wuzhi456 <217564920+wuzhi456@users.noreply.github.com>
…tely Co-authored-by: wuzhi456 <217564920+wuzhi456@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Implement type system and symbol table for semantic analysis
Fix incomplete type checking for arrays with struct element types
Nov 13, 2025
Owner
|
@copilot int main(int a, int a); // Error: Redefinition of 'a' 奇怪的是现在这个识别不出来错,但是int main2(int a, char a[20]) { // Error: Redefinition of 'a' |
Co-authored-by: wuzhi456 <217564920+wuzhi456@users.noreply.github.com>
Author
Fixed in commit 2f552c1. Function declarations now check for duplicate parameter names, matching the behavior of function definitions. Both |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix incomplete type checking for arrays with struct element types
Plan
Implementation
Array Type Checking (Initial Fix)
Added
requiresImmediateCompletenessCheck()method to distinguish between:Modified global variable definition to:
Function Declaration Parameter Checking (New Fix)
Added duplicate parameter name detection for function declarations:
Test Results
All project3 test cases pass:
Additional validation:
int main(int a, int a);→ Correctly errors with "Redefinition of 'a'"int main2(int a, char a[20]) {}→ Correctly errors with "Redefinition of 'a'"int func(int a, char b, int a);→ Correctly errors with "Redefinition of 'a'"int func1(int a, char b);→ Passes correctlyOriginal prompt
项目要求Project 3 - Semantic Check Part 1 (Rev. v4)
2025 年 11 月 12 日
我们于 Oct 31 发布了 v2 版本的文档,修复了文档里面的一些错误,请以 Blackboard 上最新的文档
为准。
我们于 Nov 11 发布了 v3 版本的文档,修复了文档里面的一些错误并添加了一条新的项目假设,请以
Blackboard 上最新的文档为准。
我们于 Nov 12 发布了 v4 版本的文档,明确规定了 Definition of incomplete type 的处理情况、并
详细解释了一个常见问题,请以 Blackboard 上最新的文档为准。
1 项目要求
在 Project 2 中,你已经成功构建了 Splc 语言的解析器,能够将源代码转化为语法树,并检查出语法错误。
但是,语法正确并不意味着源代码在逻辑上(即语义上)是正确的。
在 Project 3 中,你将进入语义分析的第一步:实现类型系统 (Type System) 和符号表 (Symbol Table)。在
Project 4 中,你将基于前面的类型系统和符号表进行完整的语义检查。
化为描述该变量的类型的 Java 对象。
你只需要关注第三章中所描述的几种语义错误即可。
1.1 对 Project 2 的修订
在开始 Project 3 前,请在 Splc.g4 中为 globalDef 添加一条新的规则:
函数声明:specifier Identifier LPAREN funcArgs RPAREN SEMI
1.2 项目假设
在后续所有 Project 中,所有测试样例均不会出现词法错误与语法错误,你可以删除 Project 2 中为错误恢
复做出的特判。
在 Project 3 & 4 中,我们做出如下假设:样例可能存在语义错误;(v3 新增) specifier 中的完整结构
体规则出现时,它在语法树中一定是全局变量定义或全局结构体声明的任意次子节点,即它不会出现在函数参
数(包含函数声明和函数定义)、函数体内。
1
1.3 扩展要求
扩展部分在每个 Project 之间都是独立计分的,在后续的 Project 中移除对某扩展部分的支持不影响前
序 Project 的分数。也就是说,你可以选择在前面的 Project 中完成较为简单的扩展任务;如果你发现
在后续的 Project 中完成扩展部分过于困难,你可以选择不完成后续 Project 的扩展部分,这样不会影
响你前面 Project 的分数。
本项目的扩展部分是 Project 2 中的延续:你需要确保你的类型系统能够正确处理 结构体 和 指针 的相关
语法。并且能够检查结构体中的 incomplete type 的情况。
2
1.4 名词解释
• type specifier:(语法结构上的)类型说明符。对应 Project 2 文档章节 2.2 类型说明符。
• declarator:(语法结构上的)声明符。在 Splc 语言中包含两种:变量声明 (varDec),会出现在全局变
量定义、局部变量定义、完整结构体中的成员声明;以及函数声明 (上述修订新增)。
1.5 解释:declaration & definition
正式定义:
• [1.5.1] A declaration specifies the interpretation and attributes of a set of identifiers.
• [1.5.2] A definition of an identifier is a declaration for that identifier that:
− for an object (variable), causes storage to be reserved for that object (variable);
− for a function, includes the function body.
声明 (Declaration) 就像在电话簿的索引(符号表)里说:“我们要登记一个人,名字叫 x,他是一个 int 类型。”
编译器看到声明后,会说:“好的,我认识 x 了。如果我看到有人使用 x,我知道它应该被当作一个 int 来对
待。”
声明不分配内存(对于变量)或不提供函数体(对于函数)。
尽管 C 语言中可以对同一个对象(变量或函数)进行多次声明,但是在我们的 Splc 中,不存在像 C 语言
中那样的变量声明(extern int a;),仅存在函数声明。并且我们规定:同名的函数声明只能出现一次,并且
其定义(若有)一定与其声明相符1。
定义 (Definition) 就像在电话簿的具体条目里说:“x 的具体住址是内存 0x1000(请在这里给他分配空间)。”或
者“myFunc 的具体工作内容是 { ... }(请把这段代码编译成机器码)。”
定义会分配存储空间(对于变量)或提供函数体(对于函数)。
在整个程序中,同一个实体(变量或函数)2只能被定义一次。
一个定义同时也是一个声明。它在“创建”这个实体的同时,也“介绍”了它自己。
注意,我们只对变量和函数说 Definition,我们从不对一个完整结构体的声明说它是一个定义。
示例
int a() {} // 这是函数
a' 的定义,也是一个声明 int b(char); // 这是函数b' 的声明int b(char); // 这是函数 `b' 的重复声明,Splc 不允许这种情况
int global_var; // 这是全局变量的定义
int main() {
global_var = 3;
int local_var; // 这是局部变量的定义
}
1判断定义与声明是否相同是下一次 Project 的任务。
2显然,同一个 Identifier 可能指向不同的实体。
3
2 Project 3 要求
2.1 类型系统
你的类型系统需要能够解析语法树中的 specifier 与 varDec,并表达以下类型:
• 基础类型(Primitive Type):包含 int 与 char。
• 定长数组类型(Array Type):包含基础类型 (element type) 和数组长度,如 int a[10] 和 char b[2][3]。
• 结构体类型(Structure Type):包括完整声明的结构体(内含字段声明)与不完整声明的结构体两种。
• 指针类型(Pointer Type):包含被指向的类型,例如 int *a。
• 你支持的所有类型的任意组合,例如 struct a[10]、int *a[123] 和 int (*a)[123]。
完整定义:
• [2.1.1] The meaning of a value stored in an object or returned by a function is determined by the type of
the expression used to access it. (An identifier declared to be an object is the simplest such expression;
the type is specified in the declaration of the identifier.)
• [2.1.2] Types are partitioned into object types (types that describe objects) and function types (types
that describe functions). At various points within a translation unit an object type may be incomplete
(lacking sufficient information to determine the size of objects of that type) or complete (having sufficient
information).
• [2.1.3] The char and int are called the basic types. The basic types are complete object types.
• [2.1.4] A function type describes a function with specified return type. A function type is characterized
by its return type and the number and types of its parameters.
• [2.1.5] Any number of derived types can be constructed from the object types3
, as follows:
− [2.1.6] An array type describes a contiguously allocated nonempty set of objects with a particular
member object type, called the element type. The element type shall be complete whenever the array
type is specified. Array types are characterized by their element type and by the number of elements
in the array. An array type is said to be derived from its element type, and if its element type is T,
the array type is sometimes called “array of T”. The construction of an array type from an element
type is called “array type derivation”.
− [2.1.7] A structure type describes a sequentially allocated nonempty set of member objects (and, in
certain circumstances, an incomplete array)(v3 删除), each of which has an optionally specified name
and possibly distinct type.
− [2.1.8] A pointer type may be derived from an object type, called the referenced type. A pointer type
describes an object whose value provides a reference to an entity of the referenced type. A pointer
type derived from the referenced type T is sometimes c...
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.