Skip to main content

rucc_sema/check/
decl.rs

1//! Declarations: what a name means, how long the thing it names lives, and who else sees it.
2//!
3//! Design: `spec/07-types-and-semantics.md`.
4//!
5//! The type builder in `check/ty.rs` answers what a declarator says. This answers everything
6//! else a declaration decides, which is four things about each name and one relation between the
7//! declarations that share it. The four are what kind of thing it is, what linkage it has, how
8//! long it lives and how much of a definition it is, and not one of them is written down: `int
9//! x;` at file scope is an external, static, tentative definition, and the same three words in a
10//! block are a local automatic one, and the only difference between them is where they are.
11//!
12//! # Why the states are kept apart
13//!
14//! A tentative definition is not a definition and not a plain declaration, and collapsing it into
15//! either is what makes `int x; int x;` come out as an error or as two objects in a compiler that
16//! got it wrong. It is a definition only if nothing else in the translation unit defines the
17//! name, so the answer is not known where it is read, which is why [`Definition`] has three
18//! values rather than a boolean.
19//!
20//! # What is not here yet
21//!
22//! A function definition, which needs statements. A braced initializer, which is the piece after
23//! this one and which is where the string literals and the designators go.
24//!
25//! Two checks wait on something that does not exist rather than on effort. The end of the
26//! translation unit is where a tentative `int a[];` is given its one element and where an object
27//! that is still incomplete is reported, so neither is done here, since a declaration in the
28//! middle of a file has no way to know what comes after it. And a file-scope initializer is not
29//! required to be constant here, because the constant folding has no address constants yet and
30//! `int *p = &x;` is the ordinary case rather than the exotic one, so the check would be wrong
31//! far more often than it would be right. What is checked is the `constexpr` case, which is
32//! arithmetic and which the folding does answer.
33
34use rucc_ast::{self as ast, AlignSpec, FuncSpecs, StorageClass};
35use rucc_base::Symbol;
36use rucc_diag::{Diagnostic, Span};
37use rucc_types::{ArrayLen, Qualifiers, TypeId, TypeKind};
38use rucc_types::{compatible, composite, is_complete, is_function, is_void, layout};
39
40use crate::check::Checker;
41use crate::check::stmt::Enclosing;
42use crate::decl::{
43    Decl, DeclId, DeclKind, DeclList, Definition, InitList, Linkage, StorageDuration,
44};
45use crate::scope::Binding;
46
47/// What one declarator declares, before anything already declared under the name is consulted.
48#[derive(Debug, Clone, Copy)]
49struct Declared {
50    /// The name, which a declaration that reaches this point always has.
51    name: Symbol,
52    /// The type the declarator built.
53    ty: TypeId,
54    /// Whether it is an object or a function.
55    kind: DeclKind,
56    /// Who else can see the name.
57    linkage: Linkage,
58    /// How long it lives.
59    duration: StorageDuration,
60    /// How much of a definition it is.
61    state: Definition,
62    /// Whether an initializer was written. A block-scope object defines itself whether or not one
63    /// was, so [`Definition`] does not answer this, and the wording of two declarations meeting in
64    /// a block turns on it.
65    initialized: bool,
66    /// What `alignas` asked for, once it has been folded and checked.
67    alignment: Option<u32>,
68    /// Whether `constexpr` was written, which makes the object a named constant.
69    constant: bool,
70    /// Whether an attribute asks for it to exist where nothing refers to it.
71    retained: bool,
72    /// Whether the declaration says nothing about which linkage it wants and so takes whatever the
73    /// declaration before it had. This is not the same as having external linkage. A file scope
74    /// `int x;` has external linkage and no keyword, and the difference between the two is what
75    /// makes `static int x; extern int x;` legal and `static int x; int x;` not.
76    takes_prior_linkage: bool,
77    /// The name, for the diagnostics that point at one.
78    span: Span,
79}
80
81impl Checker<'_> {
82    /// Checks one declaration and gives back the objects and functions it declared.
83    ///
84    /// The run is empty for a declaration that declares neither, which is a `typedef`, a tag, a
85    /// static assertion, or one of the mistakes that leaves nothing behind.
86    pub fn check_decl(&mut self, id: ast::DeclId) -> DeclList {
87        let span = self.ast.decl_span(id);
88        match self.ast[id] {
89            ast::Decl::Error => self.tast.add_decl_refs(&[]),
90            ast::Decl::Var { specs, declarators } => self.var(specs, declarators),
91            ast::Decl::StaticAssert { cond, message } => {
92                self.static_assert(cond, message, span);
93                self.tast.add_decl_refs(&[])
94            }
95            ast::Decl::Function { specs, declarator, params, body } => {
96                match self.function(specs, declarator, params, body) {
97                    Some(id) => self.tast.add_decl_refs(&[id]),
98                    None => self.tast.add_decl_refs(&[]),
99                }
100            }
101            ast::Decl::Asm(_) => {
102                self.declaration_unsupported("an assembler statement at file scope", span);
103                self.tast.add_decl_refs(&[])
104            }
105            // An attribute declaration appertains to nothing by definition, so there is nothing
106            // to check and nothing to declare.
107            ast::Decl::Attributes(_) => self.tast.add_decl_refs(&[]),
108        }
109    }
110
111    /// A specifier list and its declarators, which is what most declarations are.
112    fn var(&mut self, specs: ast::DeclSpecsId, declarators: ast::InitDeclaratorList) -> DeclList {
113        let mut items = self.ast[declarators].to_vec();
114        if items.is_empty() {
115            self.empty_declaration(specs);
116            return self.tast.add_decl_refs(&[]);
117        }
118        let node = self.ast[specs];
119        if let Some(which) = node.deduces() {
120            // One initializer deduces one type, and there is nothing to say two declarators of
121            // one list should deduce the same one. gcc allows the one and refuses the rest,
122            // which is what happens here: the message is said once and the first declarator is
123            // checked so that its name still means something.
124            if items.len() > 1 {
125                let spelled = which.spelling();
126                self.report(
127                    Diagnostic::error(
128                        format!("'{spelled}' may only be used with a single declarator"),
129                        node.span,
130                    )
131                    .with_code("E0651"),
132                );
133                items.truncate(1);
134            }
135        }
136        let mut declared = Vec::with_capacity(items.len());
137        for item in items {
138            if let Some(id) = self.init_declarator(specs, item) {
139                declared.push(id);
140            }
141        }
142        self.tast.add_decl_refs(&declared)
143    }
144
145    /// A function definition, which is a declaration with a body under it.
146    ///
147    /// The parameters are declared once, by the type builder, when it read the prototype. They
148    /// are bound again here rather than declared again, so that the declaration the prototype
149    /// resolved `n` to in `void f(int n, int a[n])` is the one the body assigns to.
150    fn function(
151        &mut self,
152        specs: ast::DeclSpecsId,
153        declarator: ast::DeclaratorId,
154        declarations: ast::DeclList,
155        body: ast::StmtId,
156    ) -> Option<DeclId> {
157        let node = self.ast[declarator];
158        let span = node.name_span;
159        let (params, kind) = match self.ast[node.derived].first() {
160            Some(&ast::Derived::Function { params, kind, .. }) => (params, kind),
161            // A definition whose declarator does not end in a parameter list is a parse that did
162            // not work out, and the parser has already said so.
163            _ => return None,
164        };
165        // GNU's nested function, a definition inside a block. `spec/13-gnu-compat.md` section 13.2
166        // settles this one: a call to a nested function goes through a trampoline written on the
167        // stack, and a stack that can be executed is not something to add to a compiler being
168        // written now. The row in `features.toml` says the same. It is turned down here rather
169        // than left to the lowering, which had no name to give one and built a module with two
170        // symbols named `nested` out of a file that had two of them.
171        //
172        // The declaration is kept, without the body, so that the calls below it resolve. One error
173        // for the definition reads better than that error and one more for every call under it.
174        let nested = !self.scopes.at_file_scope();
175        if nested {
176            let note = "a nested function is called through a trampoline written on the stack, \
177                        which no target that enforces an unexecutable stack allows, so this \
178                        compiler does not have them and will not";
179            self.report(
180                Diagnostic::error("a function definition inside a function", span)
181                    .with_code("E0676")
182                    .note(note, span),
183            );
184        }
185        // A definition is a declarator with a function type, so it is never the plain identifier
186        // a deduced type needs, and the deduction never gets as far as an initializer to deduce
187        // from. gcc says the same thing about it as about `auto *p = q;`.
188        if let Some(which) = self.ast[specs].deduces() {
189            self.not_plain(which, span);
190            return None;
191        }
192        let ty = self.declared_type(specs, declarator);
193        // An old-style definition's identifier list said nothing about types, so the type built
194        // from the declarator has no parameters in it. The declarations under the list are where
195        // they are, and they are read here because the type builder never saw them: they are not
196        // part of the declarator at all. The type is then made again with them in it.
197        let ty = if kind == ast::ParamKind::Identifiers {
198            self.identifier_list(params, declarations);
199            let taking = self.old_style_signature(node.name, params, span);
200            self.function_taking(ty, taking)
201        } else {
202            ty
203        };
204        let name = node.name?;
205        let specs = self.ast[specs];
206        if specs.is_typedef() {
207            self.report(
208                Diagnostic::error("function definition declared 'typedef'", span)
209                    .with_code("E0589"),
210            );
211            return None;
212        }
213        let (linkage, duration) = self.placement(&specs, DeclKind::Function, name, span);
214        let alignment = match specs.align {
215            Some(align) => self.alignment(align, ty, DeclKind::Function, name, span),
216            None => None,
217        };
218        let declared = Declared {
219            name,
220            ty,
221            kind: DeclKind::Function,
222            linkage,
223            duration,
224            state: if nested { Definition::Declared } else { Definition::Defined },
225            initialized: false,
226            alignment,
227            constant: false,
228            retained: self.retains(specs.attrs),
229            takes_prior_linkage: takes_prior_linkage(&specs, DeclKind::Function),
230            span,
231        };
232        let id = self.merge(declared);
233        if nested {
234            return Some(id);
235        }
236        let (stmt, params) = self.function_body(ty, name, span, params, body);
237        let mut node = self.tast[id].clone();
238        node.params = params;
239        node.body = Some(stmt);
240        self.tast.set_decl(id, node);
241        Some(id)
242    }
243
244    /// What an old-style definition's function type takes.
245    ///
246    /// The promoted types of the identifiers, which is what a caller hands over and what
247    /// 6.7.6.3p15 compares against a prototype, unless there is a prototype in scope already. A
248    /// prototype overrules them, because the alternative is refusing the pairing that all the
249    /// code written this way relies on: a header says `int f(char);` and the file defines `f` in
250    /// the old style, and `char` promotes to `int`, so the standard's own rule makes the two
251    /// incompatible and gcc has always taken them. gcc compares each parameter as written rather
252    /// than as promoted, so a `short` where the prototype says `char` is still the mistake it
253    /// looks like, and this does the same.
254    fn old_style_signature(
255        &mut self,
256        name: Option<Symbol>,
257        params: ast::ParamList,
258        span: Span,
259    ) -> Vec<TypeId> {
260        let objects = self.prototype_params(params);
261        let written: Vec<TypeId> = objects.iter().map(|&id| self.tast[id].ty).collect();
262        let Some(prototype) = name.and_then(|name| self.prototype_in_scope(name)) else {
263            return written.iter().map(|&ty| self.default_promoted(ty)).collect();
264        };
265        if prototype.len() != written.len() {
266            // The counts disagree, so there is no pairing to check and no reason to prefer one
267            // list over the other. The merge reports it as the conflict it is.
268            return written.iter().map(|&ty| self.default_promoted(ty)).collect();
269        }
270        for (index, (&declared, &wanted)) in written.iter().zip(&prototype).enumerate() {
271            let promoted = self.default_promoted(declared);
272            if compatible(&self.types, declared, wanted)
273                || compatible(&self.types, promoted, wanted)
274            {
275                continue;
276            }
277            let at = objects.get(index).map_or(span, |&id| self.tast.decl_span(id));
278            let what = match objects.get(index).and_then(|&id| self.tast[id].name) {
279                Some(name) => format!("argument '{}' doesn't match prototype", self.text(name)),
280                None => "argument doesn't match prototype".to_string(),
281            };
282            self.report(Diagnostic::error(what, at).with_code("E0683"));
283        }
284        prototype
285    }
286
287    /// The parameter types of the prototype this name already has, if it has one.
288    ///
289    /// A variadic one is not one of these. An old-style definition cannot be the definition of a
290    /// variadic function, so there is nothing for its identifiers to line up against.
291    fn prototype_in_scope(&mut self, name: Symbol) -> Option<Vec<TypeId>> {
292        let Some(Binding::Decl(id)) = self.scopes.lookup(name) else { return None };
293        let canonical = self.types.canonical(self.tast[id].ty);
294        let TypeKind::Function(signature) = self.types.kind(canonical) else { return None };
295        let signature = self.types.signature(signature);
296        (signature.prototyped && !signature.variadic).then(|| signature.params.clone())
297    }
298
299    /// The body of a function definition, in a scope holding its parameters, and the parameters
300    /// themselves.
301    ///
302    /// One scope and not two. C 6.2.1p4 puts the parameters in the block scope of the body, which
303    /// is why `void f(int a) { int a; }` is a redeclaration and `void f(int a) { { int a; } }` is
304    /// not, so the body's own compound statement is walked here rather than through the statement
305    /// that would open a scope of its own.
306    fn function_body(
307        &mut self,
308        ty: TypeId,
309        name: Symbol,
310        span: Span,
311        params: ast::ParamList,
312        body: ast::StmtId,
313    ) -> (crate::stmt::StmtId, DeclList) {
314        let (ret, variadic) = match self.types.kind(self.types.canonical(ty)) {
315            TypeKind::Function(signature) => {
316                let signature = self.types.signature(signature);
317                (signature.ret, signature.variadic)
318            }
319            // A definition of something that is not a function has been reported by the merge,
320            // and checking the body against `int` is what keeps the rest of it worth reading.
321            _ => (self.int(), false),
322        };
323        self.scopes.push();
324        let params = self.prototype_params(params);
325        for &decl in &params {
326            if let Some(name) = self.tast[decl].name {
327                self.scopes.declare(name, Binding::Decl(decl));
328            }
329        }
330        let last_param = params.last().copied();
331        let params = self.tast.add_decl_refs(&params);
332        let name = Some(name);
333        let previous =
334            self.open_body(Enclosing { ret, at: span, variadic, last_param, params, name });
335        let stmt = self.body_block(body);
336        self.close_body(previous);
337        self.scopes.pop();
338        (stmt, params)
339    }
340
341    /// A declaration with no declarator, which declares a tag or nothing at all.
342    ///
343    /// The type is built either way, because `struct S { int x; };` is how every structure in
344    /// every header is declared and the body is where the members are checked. What is diagnosed
345    /// is the case where a type was named and there was nothing for it to be the type of.
346    fn empty_declaration(&mut self, specs: ast::DeclSpecsId) {
347        let node = self.ast[specs];
348        if matches!(node.ty, ast::TypeSpec::None) {
349            // No type was named, so there is none to build and nothing to say about what it
350            // would have been. `;` on its own gets here from every macro that ends in one,
351            // and the type builder would otherwise report the missing type as if the
352            // declaration had a declarator that needed one.
353            self.specifiers_alone(node);
354            return;
355        }
356        if let ast::TypeSpec::Auto(which) = node.ty {
357            // A deduced type with nothing to deduce from. Not a useless type name, because
358            // there is no name here that could have been useful, and not a missing initializer
359            // either, because there is no declarator to have given one to.
360            let word = which.spelling();
361            self.report(
362                Diagnostic::error(format!("`{word}` in empty declaration"), node.span)
363                    .with_code("E0669"),
364            );
365            return;
366        }
367        self.declared_specs(specs);
368        match node.ty {
369            // A record with no tag and no declarator names a type nothing can ever refer to,
370            // which is a different mistake from naming a type and forgetting the variable.
371            ast::TypeSpec::Record { tag: None, fields: Some(_), .. } => {
372                self.report(
373                    Diagnostic::warning(
374                        "unnamed struct/union that defines no instances",
375                        node.span,
376                    )
377                    .with_code("E0612"),
378                );
379            }
380            ast::TypeSpec::Record { .. } | ast::TypeSpec::Enum { .. } => {
381                if !node.quals.is_none() {
382                    self.report(
383                        Diagnostic::warning(
384                            "useless type qualifier in empty declaration",
385                            node.span,
386                        )
387                        .with_code("E0611"),
388                    );
389                }
390            }
391            _ => {
392                self.report(
393                    Diagnostic::warning("useless type name in empty declaration", node.span)
394                        .with_code("E0610"),
395                );
396            }
397        }
398    }
399
400    /// A declaration that named no type, no declarator and no tag, which is a `;` and whatever
401    /// specifiers were written before it.
402    ///
403    /// Nothing here declares anything, so all of it is dead, and what is said about it is which
404    /// specifier was the useless one. Only the first is named, because a reader who deletes the
405    /// specifier deletes the rest of them with it. A bare `;` is silent, since the parser has
406    /// already given it the one warning it deserves and every project has one.
407    fn specifiers_alone(&mut self, node: ast::DeclSpecs) {
408        // `inline` and `_Noreturn` are errors rather than warnings because neither has a
409        // meaning at all away from a function, where the other two do have one and are merely
410        // being ignored.
411        if node.func.has(FuncSpecs::INLINE) {
412            self.report(
413                Diagnostic::error("`inline` in empty declaration", node.span).with_code("E0665"),
414            );
415            return;
416        }
417        if node.func.has(FuncSpecs::NORETURN) {
418            self.report(
419                Diagnostic::error("`_Noreturn` in empty declaration", node.span).with_code("E0666"),
420            );
421            return;
422        }
423        // At file scope these two name a storage duration that file scope does not have, so
424        // there is no reading of them under which the declaration would have meant something.
425        let automatic = matches!(node.storage, Some(StorageClass::Auto | StorageClass::Register));
426        if automatic && self.scopes.at_file_scope() {
427            let word = if node.storage == Some(StorageClass::Auto) { "auto" } else { "register" };
428            self.report(
429                Diagnostic::error(format!("`{word}` in file-scope empty declaration"), node.span)
430                    .with_code("E0667"),
431            );
432            return;
433        }
434        let useless = if node.storage.is_some() {
435            "useless storage class specifier in empty declaration"
436        } else if node.thread_local {
437            "useless `_Thread_local` in empty declaration"
438        } else if !node.quals.is_none() {
439            "useless type qualifier in empty declaration"
440        } else {
441            return;
442        };
443        self.report(Diagnostic::warning(useless, node.span).with_code("E0611"));
444        self.report(Diagnostic::warning("empty declaration", node.span).with_code("E0668"));
445    }
446
447    /// One declarator of a declaration, with whatever initializer it was given.
448    fn init_declarator(
449        &mut self,
450        specs: ast::DeclSpecsId,
451        item: ast::InitDeclarator,
452    ) -> Option<DeclId> {
453        // A deduced type is not known until its initializer is checked, and until then the
454        // declaration is made with `int` so that everything else about it is still checked.
455        let deduces = self.ast[specs].deduces();
456        let deducible = deduces.is_some_and(|which| self.deducible(which, item));
457        let ty =
458            if deduces.is_some() { self.int() } else { self.declared_type(specs, item.declarator) };
459        // `constexpr` implies `const`, which C23 6.7.2p6 says and which is what makes taking the
460        // address of one and writing through it the diagnostic gcc gives it rather than silence.
461        // An array is qualified through its element, so `constexpr int a[3];` is an array of
462        // `const int` and not a `const` array, which is 6.7.3p10 and what the qualifier does.
463        let ty = if self.ast[specs].constexpr {
464            self.types.qualified(ty, Qualifiers::CONST)
465        } else {
466            ty
467        };
468        let node = self.ast[item.declarator];
469        // A declarator with no name in a declaration is a parse that did not work out, and the
470        // parser has already said so.
471        let name = node.name?;
472        let span = node.name_span;
473        let specs = self.ast[specs];
474        if specs.is_typedef() {
475            self.typedef(name, ty, &specs, item, span);
476            return None;
477        }
478        let kind = if is_function(&self.types, ty) { DeclKind::Function } else { DeclKind::Object };
479        let (linkage, duration) = self.placement(&specs, kind, name, span);
480        let state = self.definition_state(&specs, kind, item.init.is_some());
481        self.check_initializer_placement(&specs, item.init.is_some(), name, span);
482        self.check_specifiers(&specs, kind, name, span);
483        let alignment = match specs.align {
484            Some(align) => self.alignment(align, ty, kind, name, span),
485            None => None,
486        };
487        let mut declared = Declared {
488            name,
489            ty,
490            kind,
491            linkage,
492            duration,
493            state,
494            initialized: item.init.is_some(),
495            alignment,
496            constant: specs.constexpr,
497            // Written on the specifiers it is shared with the declarators beside this one, and
498            // written after the declarator it is this declaration's alone. Either place asks for
499            // the same thing, so either place is read.
500            retained: self.retains(specs.attrs) || self.retains(item.attrs),
501            takes_prior_linkage: takes_prior_linkage(&specs, kind),
502            span,
503        };
504        let id = self.merge(declared);
505        // An initializer that did not work out leaves the object without a size, and saying so
506        // a second time helps nobody, so what it did decides whether the size is asked about.
507        let mut worked = true;
508        // A declaration that deduces a type and is not written so that it can has been reported
509        // and leaves nothing here for its initializer to be checked against.
510        let init = if deduces.is_some() && !deducible { None } else { item.init };
511        if let Some(init) = init {
512            let constant = specs.constexpr;
513            // A declaration that has no type or no value of its own until its initializer is
514            // checked is what C23 calls underspecified, and its name being in scope inside that
515            // initializer is what makes a reference to it something to report rather than a use.
516            if deduces.is_some() || constant {
517                self.underspecified.push(id);
518            }
519            let deduce = deduces.map(|_| specs.quals);
520            let result = self.initializer(id, init, constant, deduce, span);
521            if deduces.is_some() || constant {
522                self.underspecified.pop();
523            }
524            match result {
525                Some((entries, ty)) => {
526                    // The type comes back because an array whose length nobody wrote takes the
527                    // one its initializer implies, and this is where it becomes the type.
528                    let mut node = self.tast[id].clone();
529                    node.init = Some(entries);
530                    node.ty = ty;
531                    self.tast.set_decl(id, node);
532                }
533                None => worked = false,
534            }
535        }
536        if kind == DeclKind::Object && worked {
537            // After the initializer, because `int a[] = { 1, 2 }` has a size and an `int a[]`
538            // with nothing after it does not, and the initializer is what tells them apart.
539            declared.ty = self.tast[id].ty;
540            self.check_storage_size(&declared);
541        }
542        Some(id)
543    }
544
545    /// A `typedef`, which declares a name for a type and nothing that exists at run time.
546    fn typedef(
547        &mut self,
548        name: Symbol,
549        ty: TypeId,
550        specs: &ast::DeclSpecs,
551        item: ast::InitDeclarator,
552        span: Span,
553    ) {
554        if item.init.is_some() {
555            let spelled = self.text(name).to_owned();
556            self.report(
557                Diagnostic::error(
558                    format!("typedef '{spelled}' is initialized (use '__typeof__' instead)"),
559                    span,
560                )
561                .with_code("E0600"),
562            );
563        }
564        if specs.align.is_some() {
565            let spelled = self.text(name).to_owned();
566            self.report(
567                Diagnostic::error(format!("alignment specified for typedef '{spelled}'"), span)
568                    .with_code("E0604"),
569            );
570        }
571        match self.scopes.lookup_here(name) {
572            // A typedef may be written twice for the same type, which is what lets two headers
573            // that both define `size_t` be included by one file.
574            Some(Binding::Typedef(previous)) if compatible(&self.types, previous, ty) => {}
575            Some(Binding::Typedef(_)) => {
576                self.conflicting_types(name, ty, None, span);
577                return;
578            }
579            Some(Binding::Decl(previous)) => {
580                self.different_kind(name, Some(previous), span);
581                return;
582            }
583            Some(Binding::Enumerator { .. }) => {
584                self.different_kind(name, None, span);
585                return;
586            }
587            None => {}
588        }
589        self.declare_typedef(name, ty);
590    }
591
592    /// The linkage and the storage duration, which the scope and the keyword decide together.
593    fn placement(
594        &mut self,
595        specs: &ast::DeclSpecs,
596        kind: DeclKind,
597        name: Symbol,
598        span: Span,
599    ) -> (Linkage, StorageDuration) {
600        let file_scope = self.scopes.at_file_scope();
601        let storage = specs.storage;
602        if kind == DeclKind::Function {
603            // A function is never automatic and never lives in a block, so the only storage
604            // class it takes is `static`, and that only where there is a file for it to be
605            // static to.
606            let invalid = match storage {
607                Some(StorageClass::Auto | StorageClass::Register) => true,
608                Some(StorageClass::Static) => !file_scope,
609                _ => false,
610            };
611            if invalid {
612                let spelled = self.text(name).to_owned();
613                self.report(
614                    Diagnostic::error(
615                        format!("invalid storage class for function '{spelled}'"),
616                        span,
617                    )
618                    .with_code("E0596"),
619                );
620            }
621            let linkage = if storage == Some(StorageClass::Static) && file_scope {
622                Linkage::Internal
623            } else {
624                Linkage::External
625            };
626            return (linkage, StorageDuration::Static);
627        }
628        if file_scope {
629            let spelled = self.text(name).to_owned();
630            match storage {
631                Some(StorageClass::Auto) => {
632                    self.report(
633                        Diagnostic::error(
634                            format!("file-scope declaration of '{spelled}' specifies 'auto'"),
635                            span,
636                        )
637                        .with_code("E0594"),
638                    );
639                }
640                // gcc words this after the GNU extension that ties a register variable to a
641                // named register, since that is the only thing `register` at file scope could
642                // mean.
643                Some(StorageClass::Register) => {
644                    self.report(
645                        Diagnostic::error(
646                            format!("register name not specified for '{spelled}'"),
647                            span,
648                        )
649                        .with_code("E0595"),
650                    );
651                }
652                _ => {}
653            }
654            let linkage = match storage {
655                Some(StorageClass::Static) => Linkage::Internal,
656                _ if specs.constexpr => Linkage::Internal,
657                _ => Linkage::External,
658            };
659            let duration =
660                if specs.thread_local { StorageDuration::Thread } else { StorageDuration::Static };
661            return (linkage, duration);
662        }
663        // A block-scope object has no linkage unless it says `extern`, in which case it names
664        // whatever the rest of the program named and lives as long as the program does.
665        let stored =
666            if specs.thread_local { StorageDuration::Thread } else { StorageDuration::Static };
667        match storage {
668            Some(StorageClass::Extern) => (Linkage::External, stored),
669            Some(StorageClass::Static) => (Linkage::None, stored),
670            _ if specs.thread_local => {
671                let spelled = self.text(name).to_owned();
672                self.report(
673                    Diagnostic::error(
674                        format!(
675                            "function-scope '{spelled}' implicitly auto and declared \
676                             '_Thread_local'"
677                        ),
678                        span,
679                    )
680                    .with_code("E0597"),
681                );
682                (Linkage::None, StorageDuration::Thread)
683            }
684            _ => (Linkage::None, StorageDuration::Automatic),
685        }
686    }
687
688    /// How much of a definition this declaration is.
689    fn definition_state(
690        &mut self,
691        specs: &ast::DeclSpecs,
692        kind: DeclKind,
693        has_init: bool,
694    ) -> Definition {
695        if kind == DeclKind::Function {
696            return Definition::Declared;
697        }
698        if has_init {
699            return Definition::Defined;
700        }
701        if specs.storage == Some(StorageClass::Extern) {
702            return Definition::Declared;
703        }
704        // A file-scope object with no initializer defines the object only if nothing else in the
705        // translation unit does, which is not known here and is what tentative means.
706        if self.scopes.at_file_scope() { Definition::Tentative } else { Definition::Defined }
707    }
708
709    /// What may and may not carry an initializer, which the storage class decides.
710    fn check_initializer_placement(
711        &mut self,
712        specs: &ast::DeclSpecs,
713        has_init: bool,
714        name: Symbol,
715        span: Span,
716    ) {
717        let spelled = self.text(name).to_owned();
718        if specs.storage == Some(StorageClass::Extern) && has_init {
719            // At file scope this is a definition written oddly, and gcc lets it through with a
720            // warning. In a block there is no object here to initialize, so it is an error.
721            let diagnostic = if self.scopes.at_file_scope() {
722                Diagnostic::warning(format!("'{spelled}' initialized and declared 'extern'"), span)
723                    .with_code("E0599")
724            } else {
725                Diagnostic::error(format!("'{spelled}' has both 'extern' and initializer"), span)
726                    .with_code("E0598")
727            };
728            self.report(diagnostic);
729        }
730        if specs.constexpr && !has_init {
731            self.report(
732                Diagnostic::error("'constexpr' requires an initialized data declaration", span)
733                    .with_code("E0617"),
734            );
735        }
736    }
737
738    /// The specifiers that mean something on a function and nothing on an object.
739    fn check_specifiers(
740        &mut self,
741        specs: &ast::DeclSpecs,
742        kind: DeclKind,
743        name: Symbol,
744        span: Span,
745    ) {
746        if kind == DeclKind::Function || specs.func.is_none() {
747            return;
748        }
749        let spelled = self.text(name).to_owned();
750        let word = if specs.func.has(FuncSpecs::INLINE) { "inline" } else { "_Noreturn" };
751        self.report(
752            Diagnostic::warning(format!("variable '{spelled}' declared '{word}'"), span)
753                .with_code("E0609"),
754        );
755    }
756
757    /// Whether there is enough of the type to make an object of it.
758    fn check_storage_size(&mut self, declared: &Declared) {
759        // An `extern` declaration makes no object, so it is allowed to name a type whose size
760        // only the definition elsewhere knows.
761        if declared.state == Definition::Declared {
762            return;
763        }
764        let spelled = self.text(declared.name).to_owned();
765        if self.is_variable_length(declared.ty) {
766            if declared.duration != StorageDuration::Automatic {
767                self.report(
768                    Diagnostic::error(
769                        format!("storage size of '{spelled}' isn't constant"),
770                        declared.span,
771                    )
772                    .with_code("E0602"),
773                );
774            }
775            return;
776        }
777        if is_complete(&self.types, declared.ty) {
778            return;
779        }
780        // A tentative definition is allowed to be an array of no size, since a later declaration
781        // may give it one and the end of the translation unit gives it one element if none does.
782        if declared.state == Definition::Tentative && self.is_unsized_array(declared.ty) {
783            return;
784        }
785        // gcc words the `void` case after the type in a block and after the size at file scope,
786        // which is not a distinction anyone would design and is what it prints.
787        let void = is_void(&self.types, declared.ty) && !self.scopes.at_file_scope();
788        let diagnostic = if void {
789            Diagnostic::error(format!("variable or field '{spelled}' declared void"), declared.span)
790                .with_code("E0603")
791        } else {
792            Diagnostic::error(format!("storage size of '{spelled}' isn't known"), declared.span)
793                .with_code("E0601")
794        };
795        self.report(diagnostic);
796    }
797
798    /// What `alignas` asked for, folded and checked against what the type already has.
799    fn alignment(
800        &mut self,
801        align: AlignSpec,
802        ty: TypeId,
803        kind: DeclKind,
804        name: Symbol,
805        span: Span,
806    ) -> Option<u32> {
807        let spelled = self.text(name).to_owned();
808        if kind == DeclKind::Function {
809            self.report(
810                Diagnostic::error(format!("alignment specified for function '{spelled}'"), span)
811                    .with_code("E0605"),
812            );
813            return None;
814        }
815        let requested = match align {
816            AlignSpec::Type(named) => {
817                let named = self.type_name(named);
818                i128::from(layout(&self.types, named, self.cx.target).ok()?.align)
819            }
820            AlignSpec::Expr(expr) => {
821                let value = self.expr(expr);
822                match self.eval_integer(value) {
823                    Ok(value) => value,
824                    Err(failed) => {
825                        if !failed.poisoned {
826                            self.report(
827                                Diagnostic::error(
828                                    "requested alignment is not an integer constant",
829                                    self.tast.expr_span(failed.at),
830                                )
831                                .with_code("E0606"),
832                            );
833                        }
834                        return None;
835                    }
836                }
837            }
838        };
839        // C23 6.7.5p4 says `alignas(0)` has no effect, which is the one value below one that is
840        // not a mistake.
841        if requested == 0 {
842            return None;
843        }
844        if requested < 0 || requested & (requested - 1) != 0 {
845            self.report(
846                Diagnostic::error(
847                    format!("requested alignment '{requested}' is not a positive power of 2"),
848                    span,
849                )
850                .with_code("E0607"),
851            );
852            return None;
853        }
854        let natural = layout(&self.types, ty, self.cx.target).map_or(1, |l| l.align);
855        if requested < i128::from(natural) {
856            self.report(
857                Diagnostic::error(
858                    format!("'_Alignas' specifiers cannot reduce alignment of '{spelled}'"),
859                    span,
860                )
861                .with_code("E0608"),
862            );
863            return None;
864        }
865        u32::try_from(requested).ok()
866    }
867
868    /// The declaration this one names, which may be one that was already made.
869    fn merge(&mut self, declared: Declared) -> DeclId {
870        // A declaration with linkage answers to one anywhere in sight, since it names the same
871        // object, and one without linkage answers only to this scope, which is what lets a
872        // function declare a local called `printf`.
873        let binding = match self.scopes.lookup_here(declared.name) {
874            Some(binding) => Some(binding),
875            // The one in sight is the innermost that has a linkage of its own. 6.2.2p4 gives
876            // `extern` the linkage of a visible prior declaration only where that declaration
877            // has one, so a local of the same name in the block outside is walked past rather
878            // than stopped at: `int v = 4; { extern int v; }` leaves the inner one naming the
879            // object at file scope, and gcc reads it the same way. The same pair written in one
880            // block is caught above, by the lookup that asks about this scope alone.
881            None if declared.linkage != Linkage::None => {
882                self.scopes.lookup_where(declared.name, |binding| match binding {
883                    Binding::Decl(id) => self.tast[id].linkage != Linkage::None,
884                    Binding::Typedef(_) | Binding::Enumerator { .. } => true,
885                })
886            }
887            None => None,
888        };
889        let previous = match binding {
890            Some(Binding::Decl(id)) => id,
891            Some(Binding::Typedef(_)) => {
892                self.different_kind(declared.name, None, declared.span);
893                return self.declare(declared);
894            }
895            Some(Binding::Enumerator { .. }) => {
896                self.different_kind(declared.name, None, declared.span);
897                return self.declare(declared);
898            }
899            None => return self.declare(declared),
900        };
901        let node = self.tast[previous].clone();
902        if node.kind != declared.kind {
903            self.different_kind(declared.name, Some(previous), declared.span);
904            return self.declare(declared);
905        }
906        if !self.check_linkage(&node, &declared, previous) {
907            return self.declare(declared);
908        }
909        if !compatible(&self.types, node.ty, declared.ty) {
910            self.conflicting_types(declared.name, declared.ty, Some(previous), declared.span);
911            return previous;
912        }
913        if node.state == Definition::Defined && declared.state == Definition::Defined {
914            let spelled = self.text(declared.name).to_owned();
915            let (note, at) = self.previous_note(previous);
916            self.report(
917                Diagnostic::error(format!("redefinition of '{spelled}'"), declared.span)
918                    .with_code("E0588")
919                    .note(note, at),
920            );
921            return previous;
922        }
923        let ty = composite(&mut self.types, node.ty, declared.ty).unwrap_or(declared.ty);
924        let merged = Decl {
925            ty,
926            // `extern` after `static` keeps the internal linkage the first declaration gave the
927            // name, which is 6.2.2p4 and what every library that hides a symbol relies on.
928            linkage: if declared.takes_prior_linkage { node.linkage } else { declared.linkage },
929            state: stronger(node.state, declared.state),
930            alignment: node.alignment.max(declared.alignment),
931            // One declaration of a name asking for it to be kept is enough, which is what lets a
932            // header write `used` on the declaration and the file define it without.
933            retained: node.retained || declared.retained,
934            ..node
935        };
936        self.tast.set_decl(previous, merged);
937        self.scopes.declare(declared.name, Binding::Decl(previous));
938        previous
939    }
940
941    /// Whether the two declarations agree about who can see the name.
942    fn check_linkage(&mut self, node: &Decl, declared: &Declared, previous: DeclId) -> bool {
943        let spelled = self.text(declared.name).to_owned();
944        let message = match (node.linkage, declared.linkage) {
945            // Two declarations in a block that both give the name a value are a redefinition, and
946            // `merge` says so in the same words it uses for a name at file scope. The linkage is
947            // the interesting part only when at least one of them stops short of saying what the
948            // object holds, which is where gcc draws the line as well.
949            (Linkage::None, Linkage::None) if node.init.is_some() && declared.initialized => {
950                return true;
951            }
952            (Linkage::None, Linkage::None) => {
953                format!("redeclaration of '{spelled}' with no linkage")
954            }
955            (Linkage::None, _) => {
956                format!("extern declaration of '{spelled}' follows declaration with no linkage")
957            }
958            (_, Linkage::None) => {
959                format!("declaration of '{spelled}' with no linkage follows extern declaration")
960            }
961            (Linkage::External, Linkage::Internal) => {
962                format!("static declaration of '{spelled}' follows non-static declaration")
963            }
964            // `extern` says nothing about which linkage it wants and takes what is there, so the
965            // contradiction is only with a declaration that says nothing at all.
966            (Linkage::Internal, Linkage::External) if !declared.takes_prior_linkage => {
967                format!("non-static declaration of '{spelled}' follows static declaration")
968            }
969            _ => return true,
970        };
971        let (note, at) = self.previous_note(previous);
972        self.report(Diagnostic::error(message, declared.span).with_code("E0592").note(note, at));
973        false
974    }
975
976    /// Puts a declaration in the tree and binds the name to it.
977    fn declare(&mut self, declared: Declared) -> DeclId {
978        let node = Decl {
979            name: Some(declared.name),
980            ty: declared.ty,
981            kind: declared.kind,
982            linkage: declared.linkage,
983            duration: declared.duration,
984            state: declared.state,
985            alignment: declared.alignment,
986            constant: declared.constant,
987            retained: declared.retained,
988            init: None,
989            params: DeclList::EMPTY,
990            body: None,
991        };
992        let id = self.tast.decl(node, declared.span);
993        self.scopes.declare(declared.name, Binding::Decl(id));
994        if self.scopes.at_file_scope() {
995            self.tast.add_top_level(id);
996        }
997        id
998    }
999
1000    /// The values an initializer stores, and the type the object ended up with.
1001    ///
1002    /// The walk itself is in `check/init.rs`. What is here is the one thing about an
1003    /// initializer that is a fact about the declaration rather than about the object: a
1004    /// function cannot have one.
1005    fn initializer(
1006        &mut self,
1007        decl: DeclId,
1008        init: ast::InitId,
1009        constant: bool,
1010        deduce: Option<ast::Quals>,
1011        span: Span,
1012    ) -> Option<(InitList, TypeId)> {
1013        let node = &self.tast[decl];
1014        let (ty, kind, name, duration) = (node.ty, node.kind, node.name, node.duration);
1015        if kind == DeclKind::Function {
1016            let spelled = name.map_or_else(String::new, |name| self.text(name).to_owned());
1017            self.report(
1018                Diagnostic::error(
1019                    format!("function '{spelled}' is initialized like a variable"),
1020                    span,
1021                )
1022                .with_code("E0615"),
1023            );
1024            return None;
1025        }
1026        let is_static = duration != StorageDuration::Automatic;
1027        match deduce {
1028            Some(quals) => self.init_deduced(name, is_static, init, constant, quals, span),
1029            None => self.init_object(ty, name, is_static, init, constant, span),
1030        }
1031    }
1032
1033    /// The message for a deduced type whose declarator is more than the name it has to be.
1034    ///
1035    /// gcc words it differently for the two spellings, since only C23's takes the attributes
1036    /// that its wording mentions.
1037    fn not_plain(&mut self, which: ast::Deduction, span: Span) {
1038        let spelled = which.spelling();
1039        let allowed = match which {
1040            ast::Deduction::Auto => ", possibly with attributes,",
1041            ast::Deduction::AutoType => "",
1042        };
1043        self.report(
1044            Diagnostic::error(
1045                format!("'{spelled}' requires a plain identifier{allowed} as declarator"),
1046                span,
1047            )
1048            .with_code("E0651"),
1049        );
1050    }
1051
1052    /// Whether a declarator that deduces its type is written so that it can.
1053    ///
1054    /// Both constraints are gcc's. A deduced type comes from an initializer, so there has to be
1055    /// one. It is the whole type, so there is nothing left for a declarator to add to it and it
1056    /// has to be a name and no more than a name: `auto *p = q;` names no type, however obvious
1057    /// what it was meant to mean.
1058    fn deducible(&mut self, which: ast::Deduction, item: ast::InitDeclarator) -> bool {
1059        let spelled = which.spelling();
1060        let node = self.ast[item.declarator];
1061        let span = if node.name.is_some() { node.name_span } else { node.span };
1062        if !self.ast[node.derived].is_empty() {
1063            self.not_plain(which, span);
1064            return false;
1065        }
1066        if item.init.is_none() {
1067            self.report(
1068                Diagnostic::error(
1069                    format!("'{spelled}' requires an initialized data declaration"),
1070                    span,
1071                )
1072                .with_code("E0651"),
1073            );
1074            return false;
1075        }
1076        true
1077    }
1078
1079    /// `static_assert`, which is the one declaration whose whole purpose is to be checked.
1080    fn static_assert(&mut self, cond: ast::ExprId, message: Option<ast::StrId>, span: Span) {
1081        let cond = self.expr(cond);
1082        let cond = self.value(cond);
1083        if self.is_poisoned(cond) {
1084            return;
1085        }
1086        let value = match self.eval_integer(cond) {
1087            Ok(value) => value,
1088            Err(failed) => {
1089                if !failed.poisoned {
1090                    self.report(
1091                        Diagnostic::error(
1092                            "expression in static assertion is not constant",
1093                            self.tast.expr_span(failed.at),
1094                        )
1095                        .with_code("E0614"),
1096                    );
1097                }
1098                return;
1099            }
1100        };
1101        if value != 0 {
1102            return;
1103        }
1104        let message = match message {
1105            Some(id) => format!("static assertion failed: {}", self.quoted(id)),
1106            None => "static assertion failed".to_owned(),
1107        };
1108        self.report(Diagnostic::error(message, span).with_code("E0613"));
1109    }
1110
1111    /// The diagnostic for two declarations of one name that do not describe the same thing.
1112    fn conflicting_types(
1113        &mut self,
1114        name: Symbol,
1115        ty: TypeId,
1116        previous: Option<DeclId>,
1117        span: Span,
1118    ) {
1119        let spelled = self.text(name).to_owned();
1120        let written = self.spell(ty);
1121        let mut diagnostic =
1122            Diagnostic::error(format!("conflicting types for '{spelled}'; have '{written}'"), span)
1123                .with_code("E0586");
1124        if let Some(previous) = previous {
1125            let (note, at) = self.previous_note(previous);
1126            diagnostic = diagnostic.note(note, at);
1127        }
1128        self.report(diagnostic);
1129    }
1130
1131    /// The diagnostic for a name that already means something of another kind.
1132    fn different_kind(&mut self, name: Symbol, previous: Option<DeclId>, span: Span) {
1133        let spelled = self.text(name).to_owned();
1134        let mut diagnostic =
1135            Diagnostic::error(format!("'{spelled}' redeclared as different kind of symbol"), span)
1136                .with_code("E0587");
1137        if let Some(previous) = previous {
1138            let (note, at) = self.previous_note(previous);
1139            diagnostic = diagnostic.note(note, at);
1140        }
1141        self.report(diagnostic);
1142    }
1143
1144    /// What the note under a redeclaration says, and where it points.
1145    ///
1146    /// A `typedef` and an enumerator get no note, because a binding is a type or a value and
1147    /// neither remembers where it was written. That is a smaller loss than it sounds: the note is
1148    /// a courtesy and the error above it names the same identifier.
1149    fn previous_note(&self, id: DeclId) -> (String, Span) {
1150        let node = &self.tast[id];
1151        let word = if node.state == Definition::Defined { "definition" } else { "declaration" };
1152        let name = node.name.map_or("", |name| self.text(name));
1153        let ty = self.spell(node.ty);
1154        (format!("previous {word} of '{name}' with type '{ty}'"), self.tast.decl_span(id))
1155    }
1156
1157    /// A string literal written back out, for the assertion that quotes its message.
1158    fn quoted(&self, id: ast::StrId) -> String {
1159        let mut out = String::from("\"");
1160        for &element in &self.ast[id].elements {
1161            match char::from_u32(element) {
1162                Some('"') => out.push_str("\\\""),
1163                Some('\\') => out.push_str("\\\\"),
1164                Some('\n') => out.push_str("\\n"),
1165                Some(c) if !c.is_control() => out.push(c),
1166                _ => out.push_str(&format!("\\x{element:x}")),
1167            }
1168        }
1169        out.push('"');
1170        out
1171    }
1172
1173    /// Whether a type is an array whose length nobody has said yet.
1174    pub(in crate::check) fn is_unsized_array(&self, ty: TypeId) -> bool {
1175        matches!(
1176            self.types.kind(self.types.canonical(ty)),
1177            TypeKind::Array { len: ArrayLen::Unknown, .. }
1178        )
1179    }
1180
1181    /// A declaration form that is recognised and not checked yet.
1182    fn declaration_unsupported(&mut self, what: &str, span: Span) {
1183        self.report(
1184            Diagnostic::error(format!("{what} is not supported yet"), span).with_code("E0519"),
1185        );
1186    }
1187}
1188
1189/// Whether a declaration says nothing about which linkage it wants, and so takes whatever the
1190/// declaration before it had.
1191///
1192/// `extern` is the spelling that does this for an object. A function that says nothing is the
1193/// other one: C 6.2.2p5 gives a function declared with no storage class the linkage `extern`
1194/// would have given it, which is what makes `static int f(void); int f(void) { return 1; }` a
1195/// pair of declarations of one static function where the same pair written on an object is two
1196/// declarations that disagree. gcc draws the line in the same place, and the idiom of declaring
1197/// a static function ahead of its definition and leaving the keyword off the definition is
1198/// common enough in real code that this is not a corner.
1199fn takes_prior_linkage(specs: &ast::DeclSpecs, kind: DeclKind) -> bool {
1200    match specs.storage {
1201        Some(StorageClass::Extern) => true,
1202        None => kind == DeclKind::Function,
1203        _ => false,
1204    }
1205}
1206
1207/// The stronger of two definition states, which is what a redeclaration leaves behind.
1208fn stronger(a: Definition, b: Definition) -> Definition {
1209    let rank = |state| match state {
1210        Definition::Declared => 0,
1211        Definition::Tentative => 1,
1212        Definition::Defined => 2,
1213    };
1214    if rank(a) >= rank(b) { a } else { b }
1215}
1216
1217#[cfg(test)]
1218mod tests {
1219    use rucc_ast::{
1220        ArraySize, AttrList, Builtin, BuiltinSet, DeclSpecs, DeclSpecsId, Declarator, DeclaratorId,
1221        Derived, ParamKind, ParamList, Quals, RecordKind, TypeSpec,
1222    };
1223    use rucc_base::Interner;
1224    use rucc_diag::{Severity, Span};
1225    use rucc_lex::{Encoding, IntConstant, IntConstantType, Remarks, StringLiteral};
1226    use rucc_session::Std;
1227    use rucc_target::{TargetInfo, Triple};
1228    use rucc_types::IntKind;
1229
1230    use super::*;
1231    use crate::check::Context;
1232    use crate::print::Printer;
1233
1234    /// The untyped tree a test checks, built by hand.
1235    ///
1236    /// Everything is built before the checker exists, because the checker borrows the interner
1237    /// for as long as it lives and a test that has started cannot invent another name.
1238    struct Fixture {
1239        ast: rucc_ast::Ast,
1240        names: Interner,
1241        target: TargetInfo,
1242    }
1243
1244    impl Fixture {
1245        fn new() -> Fixture {
1246            let target =
1247                TargetInfo::new("x86_64-unknown-linux-gnu".parse::<Triple>().expect("a triple"));
1248            Fixture { ast: rucc_ast::Ast::new(), names: Interner::new(), target }
1249        }
1250
1251        fn name(&mut self, text: &str) -> Symbol {
1252            self.names.intern(text)
1253        }
1254
1255        /// `int`, as a specifier list the test can add words to before it is added.
1256        fn int_specs(&self) -> DeclSpecs {
1257            self.builtin(BuiltinSet::INT)
1258        }
1259
1260        /// `auto` or `__auto_type`, as the specifier list that deduces a type.
1261        fn deduced(&self, which: ast::Deduction) -> DeclSpecs {
1262            let mut specs = DeclSpecs::empty(Span::DUMMY);
1263            specs.ty = TypeSpec::Auto(which);
1264            specs
1265        }
1266
1267        fn builtin(&self, keyword: BuiltinSet) -> DeclSpecs {
1268            let mut specs = DeclSpecs::empty(Span::DUMMY);
1269            let builtin = Builtin::NONE.add(keyword).expect("a keyword written once");
1270            specs.ty = TypeSpec::Builtin(builtin);
1271            specs
1272        }
1273
1274        /// `struct S`, either as a mention of the tag or as a definition of it.
1275        fn record(&mut self, tag: Option<&str>, fields: bool) -> DeclSpecs {
1276            let tag = tag.map(|tag| self.name(tag));
1277            let fields = fields.then(|| self.ast.add_member_list(&[]));
1278            let mut specs = DeclSpecs::empty(Span::DUMMY);
1279            specs.ty = TypeSpec::Record {
1280                kind: RecordKind::Struct,
1281                tag,
1282                fields,
1283                attrs: AttrList::EMPTY,
1284                pack: None,
1285            };
1286            specs
1287        }
1288
1289        fn declarator(&mut self, name: &str, derived: &[Derived]) -> DeclaratorId {
1290            let name = self.name(name);
1291            let derived = self.ast.add_derived_list(derived);
1292            self.ast.add_declarator(Declarator {
1293                name: Some(name),
1294                name_span: Span::DUMMY,
1295                derived,
1296                span: Span::DUMMY,
1297            })
1298        }
1299
1300        fn int(&mut self, value: u128) -> ast::ExprId {
1301            let ty = IntConstantType::Standard(IntKind::Int);
1302            let id = self.ast.add_int(IntConstant { value, ty, remarks: Remarks::default() });
1303            self.ast.expr(ast::Expr::Int(id), Span::DUMMY)
1304        }
1305
1306        fn use_name(&mut self, text: &str) -> ast::ExprId {
1307            let name = self.name(text);
1308            self.ast.expr(ast::Expr::Name(name), Span::DUMMY)
1309        }
1310
1311        fn string(&mut self, text: &str) -> ast::StrId {
1312            let elements = text.chars().map(|c| c as u32).collect();
1313            self.ast.add_string(StringLiteral {
1314                elements,
1315                encoding: Encoding::Plain,
1316                remarks: Remarks::default(),
1317            })
1318        }
1319
1320        /// A declaration of one name, from the specifiers, the derivations and the initializer.
1321        fn var(
1322            &mut self,
1323            specs: DeclSpecs,
1324            name: &str,
1325            derived: &[Derived],
1326            init: Option<ast::ExprId>,
1327        ) -> ast::DeclId {
1328            let declarator = self.declarator(name, derived);
1329            let init = init.map(|expr| self.ast.add_init(ast::Init::Expr(expr)));
1330            let item = ast::InitDeclarator {
1331                declarator,
1332                init,
1333                asm_label: None,
1334                attrs: AttrList::EMPTY,
1335                span: Span::DUMMY,
1336            };
1337            let declarators = self.ast.add_init_declarator_list(&[item]);
1338            let specs = self.specs(specs);
1339            self.ast.decl(ast::Decl::Var { specs, declarators }, Span::DUMMY)
1340        }
1341
1342        /// `int x;` and the like, which is what most of these are.
1343        fn object(&mut self, specs: DeclSpecs, name: &str) -> ast::DeclId {
1344            self.var(specs, name, &[], None)
1345        }
1346
1347        /// A declaration with no declarator at all.
1348        fn bare(&mut self, specs: DeclSpecs) -> ast::DeclId {
1349            let specs = self.specs(specs);
1350            let declarators = self.ast.add_init_declarator_list(&[]);
1351            self.ast.decl(ast::Decl::Var { specs, declarators }, Span::DUMMY)
1352        }
1353
1354        fn specs(&mut self, specs: DeclSpecs) -> DeclSpecsId {
1355            self.ast.add_specs(specs)
1356        }
1357
1358        /// One parameter of a prototype.
1359        fn param(
1360            &mut self,
1361            specs: DeclSpecs,
1362            name: Option<&str>,
1363            derived: &[Derived],
1364        ) -> ast::Param {
1365            let declarator = match name {
1366                Some(name) => self.declarator(name, derived),
1367                None => {
1368                    let derived = self.ast.add_derived_list(derived);
1369                    self.ast.add_declarator(Declarator {
1370                        name: None,
1371                        name_span: Span::DUMMY,
1372                        derived,
1373                        span: Span::DUMMY,
1374                    })
1375                }
1376            };
1377            let specs = self.specs(specs);
1378            ast::Param { specs: Some(specs), declarator, attrs: AttrList::EMPTY, span: Span::DUMMY }
1379        }
1380
1381        /// `(a, b)`, as the derivation that makes a declarator a function.
1382        fn takes(&mut self, params: &[ast::Param]) -> Derived {
1383            let params = self.ast.add_param_list(params);
1384            Derived::Function { params, variadic: false, kind: ParamKind::Prototype }
1385        }
1386
1387        fn stmt(&mut self, stmt: ast::Stmt) -> ast::StmtId {
1388            self.ast.stmt(stmt, Span::DUMMY)
1389        }
1390
1391        /// `{ ... }`, from the statements it holds.
1392        fn block(&mut self, body: &[ast::StmtId]) -> ast::StmtId {
1393            let body = self.ast.add_stmt_list(body);
1394            self.stmt(ast::Stmt::Compound(body))
1395        }
1396
1397        /// A function definition, from its specifiers, its name, its derivations and its body.
1398        fn define(
1399            &mut self,
1400            specs: DeclSpecs,
1401            name: &str,
1402            derived: &[Derived],
1403            body: ast::StmtId,
1404        ) -> ast::DeclId {
1405            self.define_taking(specs, name, derived, &[], body)
1406        }
1407
1408        /// The same, with the declarations an old-style definition writes under its identifier
1409        /// list. Every other definition has none.
1410        fn define_taking(
1411            &mut self,
1412            specs: DeclSpecs,
1413            name: &str,
1414            derived: &[Derived],
1415            declarations: &[ast::DeclId],
1416            body: ast::StmtId,
1417        ) -> ast::DeclId {
1418            let declarator = self.declarator(name, derived);
1419            let specs = self.specs(specs);
1420            let params = self.ast.add_decl_list(declarations);
1421            self.ast.decl(ast::Decl::Function { specs, declarator, params, body }, Span::DUMMY)
1422        }
1423
1424        fn checker(&self) -> Checker<'_> {
1425            Checker::new(&self.ast, Context::new(&self.names, &self.target, Std::C23))
1426        }
1427    }
1428
1429    /// `*`, which is the one derivation written often enough to be worth a name.
1430    fn pointer() -> Derived {
1431        Derived::Pointer { quals: Quals::NONE, attrs: AttrList::EMPTY }
1432    }
1433
1434    /// `(void)`, which is what makes a declarator a function.
1435    fn function() -> Derived {
1436        Derived::Function { params: ParamList::EMPTY, variadic: false, kind: ParamKind::Void }
1437    }
1438
1439    /// `[n]`, from whatever expression was written between the brackets.
1440    fn array(size: ast::ExprId) -> Derived {
1441        Derived::Array { size: ArraySize::Expr(size), quals: Quals::NONE, has_static: false }
1442    }
1443
1444    /// The one declaration a checked declaration declared.
1445    fn only(checker: &Checker<'_>, list: DeclList) -> DeclId {
1446        let declared = &checker.tast[list];
1447        assert_eq!(declared.len(), 1, "expected exactly one declaration, got {declared:?}");
1448        declared[0]
1449    }
1450
1451    /// One declaration and whatever hangs under it, which is what most assertions here are about.
1452    fn dump(checker: &Checker<'_>, id: DeclId) -> String {
1453        let mut printer = Printer::new(&checker.tast, &checker.types, checker.cx.names);
1454        printer.decl(id);
1455        printer.finish()
1456    }
1457
1458    /// What was reported, as the messages alone, notes included.
1459    fn messages(checker: &Checker<'_>) -> Vec<String> {
1460        checker
1461            .errors
1462            .diagnostics()
1463            .iter()
1464            .flat_map(|d| {
1465                std::iter::once(d.message.clone())
1466                    .chain(d.children.iter().map(|n| n.message.clone()))
1467            })
1468            .collect()
1469    }
1470
1471    /// The one message that was reported, which is what most of these tests expect.
1472    /// How bad each reported diagnostic was, which is the whole difference between the two
1473    /// halves of the empty declaration family.
1474    fn severities(checker: &Checker<'_>) -> Vec<Severity> {
1475        checker.errors.diagnostics().iter().map(|d| d.severity).collect()
1476    }
1477
1478    fn message(checker: &Checker<'_>) -> String {
1479        let mut reported = messages(checker);
1480        assert_eq!(reported.len(), 1, "expected exactly one diagnostic, got {reported:?}");
1481        reported.pop().expect("one message")
1482    }
1483
1484    #[test]
1485    fn a_file_scope_object_is_external_and_static_and_defines_nothing_by_itself() {
1486        let mut f = Fixture::new();
1487        let specs = f.int_specs();
1488        let decl = f.object(specs, "x");
1489
1490        let mut c = f.checker();
1491        let list = c.check_decl(decl);
1492
1493        let id = only(&c, list);
1494        assert_eq!(dump(&c, id), "decl #0 x : int object external static tentative\n");
1495        assert_eq!(c.tast.top_level(), [id]);
1496        assert!(c.errors.is_empty());
1497    }
1498
1499    #[test]
1500    fn the_same_three_words_in_a_block_are_a_local_with_no_linkage() {
1501        let mut f = Fixture::new();
1502        let specs = f.int_specs();
1503        let decl = f.object(specs, "x");
1504
1505        let mut c = f.checker();
1506        c.scopes.push();
1507        let list = c.check_decl(decl);
1508
1509        let id = only(&c, list);
1510        assert_eq!(dump(&c, id), "decl #0 x : int object automatic defined\n");
1511        assert!(c.tast.top_level().is_empty());
1512        assert!(c.errors.is_empty());
1513    }
1514
1515    #[test]
1516    fn static_at_file_scope_hides_the_name_and_in_a_block_only_lengthens_the_lifetime() {
1517        let mut f = Fixture::new();
1518        let mut specs = f.int_specs();
1519        specs.storage = Some(StorageClass::Static);
1520        let outer = f.object(specs, "x");
1521        let inner = f.object(specs, "y");
1522
1523        let mut c = f.checker();
1524        let list = c.check_decl(outer);
1525        let outer = only(&c, list);
1526        c.scopes.push();
1527        let list = c.check_decl(inner);
1528        let inner = only(&c, list);
1529
1530        assert_eq!(dump(&c, outer), "decl #0 x : int object internal static tentative\n");
1531        assert_eq!(dump(&c, inner), "decl #1 y : int object static defined\n");
1532        assert!(c.errors.is_empty());
1533    }
1534
1535    #[test]
1536    fn extern_in_a_block_names_the_object_the_file_scope_declaration_named() {
1537        let mut f = Fixture::new();
1538        let specs = f.int_specs();
1539        let outer = f.object(specs, "x");
1540        let mut specs = f.int_specs();
1541        specs.storage = Some(StorageClass::Extern);
1542        let inner = f.object(specs, "x");
1543
1544        let mut c = f.checker();
1545        let list = c.check_decl(outer);
1546        let first = only(&c, list);
1547        c.scopes.push();
1548        let list = c.check_decl(inner);
1549
1550        assert_eq!(only(&c, list), first, "the block-scope declaration is the same object");
1551        assert_eq!(dump(&c, first), "decl #0 x : int object external static tentative\n");
1552        assert!(c.errors.is_empty());
1553    }
1554
1555    #[test]
1556    fn a_declaration_and_a_definition_of_one_name_are_one_declaration() {
1557        let mut f = Fixture::new();
1558        let mut specs = f.int_specs();
1559        specs.storage = Some(StorageClass::Extern);
1560        let declared = f.object(specs, "x");
1561        let specs = f.int_specs();
1562        let one = f.int(1);
1563        let defined = f.var(specs, "x", &[], Some(one));
1564
1565        let mut c = f.checker();
1566        let list = c.check_decl(declared);
1567        let first = only(&c, list);
1568        let list = c.check_decl(defined);
1569
1570        assert_eq!(only(&c, list), first);
1571        assert_eq!(
1572            dump(&c, first),
1573            "decl #0 x : int object external static defined\n  init\n    +0\n      const 1 : int\n"
1574        );
1575        assert!(c.errors.is_empty());
1576    }
1577
1578    #[test]
1579    fn two_definitions_of_one_name_are_refused_and_the_first_one_is_pointed_at() {
1580        let mut f = Fixture::new();
1581        let specs = f.int_specs();
1582        let one = f.int(1);
1583        let first = f.var(specs, "x", &[], Some(one));
1584        let two = f.int(2);
1585        let second = f.var(specs, "x", &[], Some(two));
1586
1587        let mut c = f.checker();
1588        c.check_decl(first);
1589        c.check_decl(second);
1590
1591        assert_eq!(
1592            messages(&c),
1593            ["redefinition of 'x'", "previous definition of 'x' with type 'int'"]
1594        );
1595    }
1596
1597    #[test]
1598    fn a_redeclaration_with_another_type_says_which_type_this_one_has() {
1599        let mut f = Fixture::new();
1600        let specs = f.int_specs();
1601        let first = f.object(specs, "x");
1602        let specs = f.builtin(BuiltinSet::CHAR);
1603        let second = f.object(specs, "x");
1604
1605        let mut c = f.checker();
1606        c.check_decl(first);
1607        c.check_decl(second);
1608
1609        assert_eq!(
1610            messages(&c),
1611            [
1612                "conflicting types for 'x'; have 'char'",
1613                "previous declaration of 'x' with type 'int'"
1614            ]
1615        );
1616    }
1617
1618    #[test]
1619    fn two_declarations_of_an_array_leave_the_one_that_gave_a_bound() {
1620        let mut f = Fixture::new();
1621        let specs = f.int_specs();
1622        let first = f.var(
1623            specs,
1624            "a",
1625            &[Derived::Array {
1626                size: ArraySize::Unspecified,
1627                quals: Quals::NONE,
1628                has_static: false,
1629            }],
1630            None,
1631        );
1632        let three = f.int(3);
1633        let second = f.var(specs, "a", &[array(three)], None);
1634
1635        let mut c = f.checker();
1636        let list = c.check_decl(first);
1637        let id = only(&c, list);
1638        c.check_decl(second);
1639
1640        assert_eq!(dump(&c, id), "decl #0 a : int[3] object external static tentative\n");
1641        assert!(c.errors.is_empty());
1642    }
1643
1644    #[test]
1645    fn static_and_non_static_declarations_of_one_name_contradict_each_other_both_ways() {
1646        let mut f = Fixture::new();
1647        let plain = f.int_specs();
1648        let mut hidden = f.int_specs();
1649        hidden.storage = Some(StorageClass::Static);
1650        let (a, b) = (f.object(plain, "x"), f.object(hidden, "x"));
1651        let (c1, d) = (f.object(hidden, "y"), f.object(plain, "y"));
1652
1653        let mut c = f.checker();
1654        c.check_decl(a);
1655        c.check_decl(b);
1656        c.check_decl(c1);
1657        c.check_decl(d);
1658
1659        assert_eq!(
1660            messages(&c),
1661            [
1662                "static declaration of 'x' follows non-static declaration",
1663                "previous declaration of 'x' with type 'int'",
1664                "non-static declaration of 'y' follows static declaration",
1665                "previous declaration of 'y' with type 'int'",
1666            ]
1667        );
1668    }
1669
1670    #[test]
1671    fn extern_after_static_keeps_the_linkage_the_first_declaration_gave_the_name() {
1672        let mut f = Fixture::new();
1673        let mut specs = f.int_specs();
1674        specs.storage = Some(StorageClass::Static);
1675        let first = f.object(specs, "x");
1676        let mut specs = f.int_specs();
1677        specs.storage = Some(StorageClass::Extern);
1678        let second = f.object(specs, "x");
1679
1680        let mut c = f.checker();
1681        let list = c.check_decl(first);
1682        let id = only(&c, list);
1683        c.check_decl(second);
1684
1685        assert_eq!(dump(&c, id), "decl #0 x : int object internal static tentative\n");
1686        assert!(c.errors.is_empty());
1687    }
1688
1689    #[test]
1690    fn a_function_defined_with_no_keyword_after_a_static_declaration_is_still_static() {
1691        let mut f = Fixture::new();
1692        let mut specs = f.int_specs();
1693        specs.storage = Some(StorageClass::Static);
1694        let first = f.var(specs, "f", &[function()], None);
1695        let body = f.block(&[]);
1696        let specs = f.int_specs();
1697        let second = f.define(specs, "f", &[function()], body);
1698
1699        let mut c = f.checker();
1700        let list = c.check_decl(first);
1701        let id = only(&c, list);
1702        c.check_decl(second);
1703
1704        // The keyword is left off the definition all over real code, and C 6.2.2p5 says the
1705        // function keeps the linkage the declaration before it gave the name rather than
1706        // contradicting it. The same pair written on an object does contradict.
1707        assert_eq!(
1708            dump(&c, id),
1709            "decl #0 f : int(void) function internal defined\n  body\n    block\n"
1710        );
1711        assert!(c.errors.is_empty(), "got {:?}", messages(&c));
1712    }
1713
1714    #[test]
1715    fn two_locals_of_one_name_in_one_block_are_refused_as_having_no_linkage() {
1716        let mut f = Fixture::new();
1717        let specs = f.int_specs();
1718        let first = f.object(specs, "x");
1719        let second = f.object(specs, "x");
1720
1721        let mut c = f.checker();
1722        c.scopes.push();
1723        c.check_decl(first);
1724        c.check_decl(second);
1725
1726        assert_eq!(
1727            messages(&c),
1728            ["redeclaration of 'x' with no linkage", "previous definition of 'x' with type 'int'"]
1729        );
1730    }
1731
1732    #[test]
1733    fn an_extern_declaration_looks_past_a_local_of_the_same_name_in_the_block_outside_it() {
1734        // C 6.2.2p4 hands `extern` the linkage of a visible prior declaration only where that
1735        // declaration has a linkage of its own. The local in the block outside has none, so the
1736        // inner declaration is of the object at file scope rather than a second declaration of
1737        // the local, and it is not the contradiction the pair written in one block is. gcc reads
1738        // it the same way, and this used to report the pair in two blocks as well.
1739        let mut f = Fixture::new();
1740        let specs = f.int_specs();
1741        let file = f.object(specs, "v");
1742        let specs = f.int_specs();
1743        let local = f.object(specs, "v");
1744        let mut specs = f.int_specs();
1745        specs.storage = Some(StorageClass::Extern);
1746        let outward = f.object(specs, "v");
1747
1748        let mut c = f.checker();
1749        let list = c.check_decl(file);
1750        let first = only(&c, list);
1751        c.scopes.push();
1752        c.check_decl(local);
1753        c.scopes.push();
1754        let list = c.check_decl(outward);
1755
1756        assert!(c.errors.is_empty(), "got {:?}", messages(&c));
1757        assert_eq!(only(&c, list), first, "it names the object at file scope");
1758    }
1759
1760    #[test]
1761    fn a_name_that_already_means_a_type_is_redeclared_as_a_different_kind_of_symbol() {
1762        let mut f = Fixture::new();
1763        let mut specs = f.int_specs();
1764        specs.storage = Some(StorageClass::Typedef);
1765        let named = f.object(specs, "T");
1766        let specs = f.int_specs();
1767        let object = f.object(specs, "T");
1768
1769        let mut c = f.checker();
1770        c.check_decl(named);
1771        c.check_decl(object);
1772
1773        assert_eq!(message(&c), "'T' redeclared as different kind of symbol");
1774    }
1775
1776    #[test]
1777    fn a_typedef_may_be_written_twice_for_one_type_and_not_for_two() {
1778        let mut f = Fixture::new();
1779        let mut specs = f.int_specs();
1780        specs.storage = Some(StorageClass::Typedef);
1781        let first = f.object(specs, "T");
1782        let again = f.object(specs, "T");
1783        let mut specs = f.builtin(BuiltinSet::CHAR);
1784        specs.storage = Some(StorageClass::Typedef);
1785        let other = f.object(specs, "T");
1786
1787        let mut c = f.checker();
1788        let declared = c.check_decl(first);
1789        assert!(c.tast[declared].is_empty(), "a typedef declares nothing at run time");
1790        c.check_decl(again);
1791        assert!(c.errors.is_empty(), "the same type twice is what two headers do");
1792        c.check_decl(other);
1793
1794        assert_eq!(message(&c), "conflicting types for 'T'; have 'char'");
1795    }
1796
1797    #[test]
1798    fn a_typedef_with_an_initializer_names_the_operator_that_was_wanted_instead() {
1799        let mut f = Fixture::new();
1800        let mut specs = f.int_specs();
1801        specs.storage = Some(StorageClass::Typedef);
1802        let one = f.int(1);
1803        let decl = f.var(specs, "T", &[], Some(one));
1804
1805        let mut c = f.checker();
1806        c.check_decl(decl);
1807
1808        assert_eq!(message(&c), "typedef 'T' is initialized (use '__typeof__' instead)");
1809    }
1810
1811    #[test]
1812    fn an_object_of_a_type_with_no_size_is_refused_and_a_local_void_is_worded_apart() {
1813        let mut f = Fixture::new();
1814        let incomplete = f.record(Some("S"), false);
1815        let hidden = f.object(incomplete, "s");
1816        let void = f.builtin(BuiltinSet::VOID);
1817        let nothing = f.object(void, "x");
1818
1819        let mut c = f.checker();
1820        c.scopes.push();
1821        c.check_decl(hidden);
1822        c.check_decl(nothing);
1823
1824        assert_eq!(
1825            messages(&c),
1826            ["storage size of 's' isn't known", "variable or field 'x' declared void"]
1827        );
1828    }
1829
1830    #[test]
1831    fn an_array_with_no_bound_at_file_scope_waits_for_a_declaration_that_gives_one() {
1832        let mut f = Fixture::new();
1833        let specs = f.int_specs();
1834        let decl = f.var(
1835            specs,
1836            "a",
1837            &[Derived::Array {
1838                size: ArraySize::Unspecified,
1839                quals: Quals::NONE,
1840                has_static: false,
1841            }],
1842            None,
1843        );
1844
1845        let mut c = f.checker();
1846        let list = c.check_decl(decl);
1847
1848        assert_eq!(
1849            dump(&c, only(&c, list)),
1850            "decl #0 a : int[] object external static tentative\n"
1851        );
1852        assert!(c.errors.is_empty(), "the end of the translation unit is what decides this one");
1853    }
1854
1855    #[test]
1856    fn a_variable_length_array_may_be_automatic_and_may_not_outlive_the_block() {
1857        let mut f = Fixture::new();
1858        let specs = f.int_specs();
1859        let n = f.use_name("n");
1860        let automatic = f.var(specs, "a", &[array(n)], None);
1861        let mut specs = f.int_specs();
1862        specs.storage = Some(StorageClass::Static);
1863        let n = f.use_name("n");
1864        let stored = f.var(specs, "b", &[array(n)], None);
1865        let n = f.name("n");
1866
1867        let mut c = f.checker();
1868        c.scopes.push();
1869        let int = c.types.int(IntKind::Int);
1870        c.declare_object(n, int, Span::DUMMY);
1871        c.check_decl(automatic);
1872        assert!(c.errors.is_empty());
1873        c.check_decl(stored);
1874
1875        assert_eq!(message(&c), "storage size of 'b' isn't constant");
1876    }
1877
1878    #[test]
1879    fn auto_and_register_at_file_scope_are_each_refused_in_the_words_gcc_uses() {
1880        let mut f = Fixture::new();
1881        let mut specs = f.int_specs();
1882        specs.storage = Some(StorageClass::Auto);
1883        let automatic = f.object(specs, "x");
1884        let mut specs = f.int_specs();
1885        specs.storage = Some(StorageClass::Register);
1886        let in_a_register = f.object(specs, "y");
1887
1888        let mut c = f.checker();
1889        c.check_decl(automatic);
1890        c.check_decl(in_a_register);
1891
1892        assert_eq!(
1893            messages(&c),
1894            [
1895                "file-scope declaration of 'x' specifies 'auto'",
1896                "register name not specified for 'y'",
1897            ]
1898        );
1899    }
1900
1901    #[test]
1902    fn a_function_takes_static_at_file_scope_and_no_storage_class_anywhere_else() {
1903        let mut f = Fixture::new();
1904        let mut specs = f.int_specs();
1905        specs.storage = Some(StorageClass::Static);
1906        let hidden = f.var(specs, "f", &[function()], None);
1907        let inner = f.var(specs, "g", &[function()], None);
1908
1909        let mut c = f.checker();
1910        let list = c.check_decl(hidden);
1911        assert_eq!(dump(&c, only(&c, list)), "decl #0 f : int(void) function internal declared\n");
1912        assert!(c.errors.is_empty());
1913        c.scopes.push();
1914        c.check_decl(inner);
1915
1916        assert_eq!(message(&c), "invalid storage class for function 'g'");
1917    }
1918
1919    #[test]
1920    fn a_scalar_initializer_is_converted_to_the_type_of_the_object_it_initializes() {
1921        let mut f = Fixture::new();
1922        let specs = f.builtin(BuiltinSet::DOUBLE);
1923        let one = f.int(1);
1924        let decl = f.var(specs, "d", &[], Some(one));
1925
1926        let mut c = f.checker();
1927        c.scopes.push();
1928        let list = c.check_decl(decl);
1929
1930        assert_eq!(
1931            dump(&c, only(&c, list)),
1932            "decl #0 d : double object automatic defined\n  init\n    +0\n      \
1933             convert arithmetic : double\n        const 1 : int\n"
1934        );
1935        assert!(c.errors.is_empty());
1936    }
1937
1938    #[test]
1939    fn an_initializer_of_the_wrong_kind_names_the_conversion_it_would_have_taken() {
1940        let mut f = Fixture::new();
1941        let specs = f.int_specs();
1942        let one = f.int(1);
1943        let from_an_integer = f.var(specs, "p", &[pointer()], None.or(Some(one)));
1944        let specs = f.builtin(BuiltinSet::CHAR);
1945        let q = f.use_name("q");
1946        let from_a_pointer = f.var(specs, "r", &[pointer()], Some(q));
1947        let q = f.name("q");
1948
1949        let mut c = f.checker();
1950        c.scopes.push();
1951        let int = c.types.int(IntKind::Int);
1952        let to_int = c.types.pointer(int);
1953        c.declare_object(q, to_int, Span::DUMMY);
1954        c.check_decl(from_an_integer);
1955        c.check_decl(from_a_pointer);
1956
1957        assert_eq!(
1958            messages(&c),
1959            [
1960                "initialization of 'int *' from 'int' makes pointer from integer without a cast",
1961                "initialization of 'char *' from incompatible pointer type 'int *'",
1962            ]
1963        );
1964    }
1965
1966    #[test]
1967    fn an_array_and_a_structure_each_refuse_a_value_as_an_initializer() {
1968        let mut f = Fixture::new();
1969        let specs = f.int_specs();
1970        let two = f.int(2);
1971        let one = f.int(1);
1972        let an_array = f.var(specs, "a", &[array(two)], Some(one));
1973        let specs = f.record(Some("S"), true);
1974        let one = f.int(1);
1975        let a_record = f.var(specs, "s", &[], Some(one));
1976
1977        let mut c = f.checker();
1978        c.scopes.push();
1979        c.check_decl(an_array);
1980        c.check_decl(a_record);
1981
1982        assert_eq!(messages(&c), ["invalid initializer", "invalid initializer"]);
1983    }
1984
1985    #[test]
1986    fn extern_with_an_initializer_is_an_error_in_a_block_and_a_warning_at_file_scope() {
1987        let mut f = Fixture::new();
1988        let mut specs = f.int_specs();
1989        specs.storage = Some(StorageClass::Extern);
1990        let one = f.int(1);
1991        let outer = f.var(specs, "x", &[], Some(one));
1992        let one = f.int(1);
1993        let inner = f.var(specs, "y", &[], Some(one));
1994
1995        let mut c = f.checker();
1996        c.check_decl(outer);
1997        c.scopes.push();
1998        c.check_decl(inner);
1999
2000        assert_eq!(
2001            messages(&c),
2002            ["'x' initialized and declared 'extern'", "'y' has both 'extern' and initializer"]
2003        );
2004    }
2005
2006    #[test]
2007    fn alignas_raises_the_alignment_and_refuses_to_lower_it_or_to_take_a_number_that_is_not_one() {
2008        let mut f = Fixture::new();
2009        let sixteen = f.int(16);
2010        let mut specs = f.int_specs();
2011        specs.align = Some(AlignSpec::Expr(sixteen));
2012        let raised = f.object(specs, "x");
2013        let one = f.int(1);
2014        let mut specs = f.int_specs();
2015        specs.align = Some(AlignSpec::Expr(one));
2016        let lowered = f.object(specs, "y");
2017        let three = f.int(3);
2018        let mut specs = f.int_specs();
2019        specs.align = Some(AlignSpec::Expr(three));
2020        let odd = f.object(specs, "z");
2021
2022        let mut c = f.checker();
2023        let list = c.check_decl(raised);
2024        assert_eq!(
2025            dump(&c, only(&c, list)),
2026            "decl #0 x : int object external static tentative alignas 16\n"
2027        );
2028        c.check_decl(lowered);
2029        c.check_decl(odd);
2030
2031        assert_eq!(
2032            messages(&c),
2033            [
2034                "'_Alignas' specifiers cannot reduce alignment of 'y'",
2035                "requested alignment '3' is not a positive power of 2",
2036            ]
2037        );
2038    }
2039
2040    #[test]
2041    fn alignment_asked_for_on_a_typedef_and_on_a_function_is_refused_on_each() {
2042        let mut f = Fixture::new();
2043        let sixteen = f.int(16);
2044        let mut specs = f.int_specs();
2045        specs.align = Some(AlignSpec::Expr(sixteen));
2046        specs.storage = Some(StorageClass::Typedef);
2047        let named = f.object(specs, "T");
2048        let mut specs = f.int_specs();
2049        specs.align = Some(AlignSpec::Expr(sixteen));
2050        let called = f.var(specs, "g", &[function()], None);
2051
2052        let mut c = f.checker();
2053        c.check_decl(named);
2054        c.check_decl(called);
2055
2056        assert_eq!(
2057            messages(&c),
2058            ["alignment specified for typedef 'T'", "alignment specified for function 'g'"]
2059        );
2060    }
2061
2062    #[test]
2063    fn a_static_assertion_that_holds_says_nothing_and_one_that_fails_quotes_its_message() {
2064        let mut f = Fixture::new();
2065        let one = f.int(1);
2066        let holds = f.ast.decl(ast::Decl::StaticAssert { cond: one, message: None }, Span::DUMMY);
2067        let zero = f.int(0);
2068        let boom = f.string("boom");
2069        let fails =
2070            f.ast.decl(ast::Decl::StaticAssert { cond: zero, message: Some(boom) }, Span::DUMMY);
2071
2072        let mut c = f.checker();
2073        c.check_decl(holds);
2074        assert!(c.errors.is_empty());
2075        c.check_decl(fails);
2076
2077        assert_eq!(message(&c), "static assertion failed: \"boom\"");
2078    }
2079
2080    #[test]
2081    fn an_empty_declaration_says_what_about_it_was_useless() {
2082        let mut f = Fixture::new();
2083        let specs = f.int_specs();
2084        let a_type_name = f.bare(specs);
2085        let mut specs = f.record(Some("S"), false);
2086        specs.quals = Quals::CONST;
2087        let a_qualifier = f.bare(specs);
2088        let unnamed = f.record(None, true);
2089        let no_instances = f.bare(unnamed);
2090
2091        let mut c = f.checker();
2092        c.check_decl(a_type_name);
2093        c.check_decl(a_qualifier);
2094        c.check_decl(no_instances);
2095
2096        assert_eq!(
2097            messages(&c),
2098            [
2099                "useless type name in empty declaration",
2100                "useless type qualifier in empty declaration",
2101                "unnamed struct/union that defines no instances",
2102            ]
2103        );
2104    }
2105
2106    /// The `;` a macro leaves behind. Every project has one, so it has to cost nothing: the
2107    /// parser gives it the one pedantic warning gcc gives it and nothing here adds to that.
2108    #[test]
2109    fn a_semicolon_on_its_own_is_a_declaration_of_nothing_and_says_nothing() {
2110        let mut f = Fixture::new();
2111        let nothing = f.bare(DeclSpecs::empty(Span::DUMMY));
2112
2113        let mut c = f.checker();
2114        c.check_decl(nothing);
2115
2116        assert!(messages(&c).is_empty(), "{:?}", messages(&c));
2117    }
2118
2119    /// A specifier written with no declarator after it declares nothing, so what is worth
2120    /// saying is which specifier it was. gcc has a separate sentence for each and these are
2121    /// its words, since a program that hits one is usually a macro that expanded oddly and the
2122    /// reader is going to search for the message.
2123    #[test]
2124    fn a_specifier_with_nothing_to_apply_to_is_named_in_the_message() {
2125        let mut f = Fixture::new();
2126        let mut specs = DeclSpecs::empty(Span::DUMMY);
2127        specs.storage = Some(StorageClass::Extern);
2128        let storage = f.bare(specs);
2129        let mut specs = DeclSpecs::empty(Span::DUMMY);
2130        specs.thread_local = true;
2131        let thread = f.bare(specs);
2132        let mut specs = DeclSpecs::empty(Span::DUMMY);
2133        specs.quals = Quals::CONST;
2134        let qualifier = f.bare(specs);
2135
2136        let mut c = f.checker();
2137        c.check_decl(storage);
2138        c.check_decl(thread);
2139        c.check_decl(qualifier);
2140
2141        assert_eq!(
2142            messages(&c),
2143            [
2144                "useless storage class specifier in empty declaration",
2145                "empty declaration",
2146                "useless `_Thread_local` in empty declaration",
2147                "empty declaration",
2148                "useless type qualifier in empty declaration",
2149                "empty declaration",
2150            ]
2151        );
2152        assert!(severities(&c).iter().all(|s| *s == Severity::Warning), "all six are warnings");
2153    }
2154
2155    /// The four that are errors rather than warnings. `inline` and `_Noreturn` have no meaning
2156    /// at all away from a function, `auto` and `register` name a storage duration that file
2157    /// scope does not have, and a deduced type has nothing to deduce from.
2158    #[test]
2159    fn the_specifiers_that_cannot_be_ignored_in_an_empty_declaration_are_errors() {
2160        let mut f = Fixture::new();
2161        let mut specs = DeclSpecs::empty(Span::DUMMY);
2162        specs.func = FuncSpecs::INLINE;
2163        let inline = f.bare(specs);
2164        let mut specs = DeclSpecs::empty(Span::DUMMY);
2165        specs.func = FuncSpecs::NORETURN;
2166        let noreturn = f.bare(specs);
2167        let mut specs = DeclSpecs::empty(Span::DUMMY);
2168        specs.storage = Some(StorageClass::Register);
2169        let register = f.bare(specs);
2170        let specs = f.deduced(ast::Deduction::Auto);
2171        let deduced = f.bare(specs);
2172
2173        let mut c = f.checker();
2174        c.check_decl(inline);
2175        c.check_decl(noreturn);
2176        c.check_decl(register);
2177        c.check_decl(deduced);
2178
2179        assert_eq!(
2180            messages(&c),
2181            [
2182                "`inline` in empty declaration",
2183                "`_Noreturn` in empty declaration",
2184                "`register` in file-scope empty declaration",
2185                "`auto` in empty declaration",
2186            ]
2187        );
2188        assert!(severities(&c).iter().all(|s| *s == Severity::Error), "all four are errors");
2189    }
2190
2191    #[test]
2192    fn a_specifier_that_only_a_function_takes_is_warned_about_on_a_variable() {
2193        let mut f = Fixture::new();
2194        let mut specs = f.int_specs();
2195        specs.func = FuncSpecs::INLINE;
2196        let decl = f.object(specs, "x");
2197
2198        let mut c = f.checker();
2199        c.check_decl(decl);
2200
2201        assert_eq!(message(&c), "variable 'x' declared 'inline'");
2202    }
2203
2204    #[test]
2205    fn thread_local_in_a_block_needs_a_storage_class_that_gives_it_somewhere_to_live() {
2206        let mut f = Fixture::new();
2207        let mut specs = f.int_specs();
2208        specs.thread_local = true;
2209        let alone = f.object(specs, "x");
2210        let mut specs = f.int_specs();
2211        specs.thread_local = true;
2212        specs.storage = Some(StorageClass::Static);
2213        let stored = f.object(specs, "y");
2214
2215        let mut c = f.checker();
2216        c.scopes.push();
2217        c.check_decl(alone);
2218        assert_eq!(message(&c), "function-scope 'x' implicitly auto and declared '_Thread_local'");
2219        let list = c.check_decl(stored);
2220
2221        assert_eq!(dump(&c, only(&c, list)), "decl #1 y : int object thread defined\n");
2222    }
2223
2224    #[test]
2225    fn a_function_definition_is_a_declaration_with_its_body_under_it() {
2226        let mut f = Fixture::new();
2227        let specs = f.builtin(BuiltinSet::VOID);
2228        let body = f.block(&[]);
2229        let decl = f.define(specs, "f", &[function()], body);
2230
2231        let mut c = f.checker();
2232        let list = c.check_decl(decl);
2233
2234        let id = only(&c, list);
2235        assert_eq!(
2236            dump(&c, id),
2237            "decl #0 f : void(void) function external defined\n  body\n    block\n"
2238        );
2239        assert!(c.errors.is_empty());
2240    }
2241
2242    #[test]
2243    fn a_parameter_is_declared_once_and_the_body_names_that_declaration() {
2244        let mut f = Fixture::new();
2245        let int = f.int_specs();
2246        let n = f.param(int, Some("n"), &[]);
2247        let takes = f.takes(&[n]);
2248        let use_n = f.use_name("n");
2249        let ret = f.stmt(ast::Stmt::Return(Some(use_n)));
2250        let body = f.block(&[ret]);
2251        let specs = f.int_specs();
2252        let decl = f.define(specs, "f", &[takes], body);
2253
2254        let mut c = f.checker();
2255        let list = c.check_decl(decl);
2256
2257        let id = only(&c, list);
2258        assert_eq!(
2259            dump(&c, id),
2260            "decl #1 f : int(int) function external defined\n  params\n    decl #0 n : int \
2261             object automatic defined\n  body\n    block\n      return\n        convert lvalue \
2262             : int\n          decl #0 n : int lvalue\n"
2263        );
2264        assert!(c.errors.is_empty(), "got {:?}", messages(&c));
2265    }
2266
2267    #[test]
2268    fn a_parameter_a_definition_left_unnamed_is_still_one_of_the_parameters() {
2269        let mut f = Fixture::new();
2270        let int = f.int_specs();
2271        let a = f.param(int, Some("a"), &[]);
2272        let int = f.int_specs();
2273        let anonymous = f.param(int, None, &[]);
2274        let takes = f.takes(&[a, anonymous]);
2275        let use_a = f.use_name("a");
2276        let ret = f.stmt(ast::Stmt::Return(Some(use_a)));
2277        let body = f.block(&[ret]);
2278        let specs = f.int_specs();
2279        let decl = f.define(specs, "f", &[takes], body);
2280
2281        let mut c = f.checker();
2282        let list = c.check_decl(decl);
2283
2284        // C23 6.7.7.4p1 lets the name be left out, and the object is passed either way. The list
2285        // is what says what the function takes and in what order, so leaving it out of the list
2286        // would say the function takes one thing when its type says two.
2287        let id = only(&c, list);
2288        assert_eq!(
2289            dump(&c, id),
2290            "decl #2 f : int(int, int) function external defined\n  params\n    decl #0 a : int \
2291             object automatic defined\n    decl #1 : int object automatic defined\n  body\n    \
2292             block\n      return\n        convert lvalue : int\n          decl #0 a : int \
2293             lvalue\n"
2294        );
2295        assert!(c.errors.is_empty(), "got {:?}", messages(&c));
2296    }
2297
2298    #[test]
2299    fn a_name_declared_in_the_body_meets_the_parameter_of_the_same_name() {
2300        let mut f = Fixture::new();
2301        let int = f.int_specs();
2302        let a = f.param(int, Some("a"), &[]);
2303        let takes = f.takes(&[a]);
2304        let specs = f.int_specs();
2305        let shadow = f.object(specs, "a");
2306        let shadow = f.stmt(ast::Stmt::Decl(shadow));
2307        let body = f.block(&[shadow]);
2308        let specs = f.builtin(BuiltinSet::VOID);
2309        let decl = f.define(specs, "f", &[takes], body);
2310
2311        let mut c = f.checker();
2312        c.check_decl(decl);
2313
2314        assert_eq!(
2315            messages(&c),
2316            ["redeclaration of 'a' with no linkage", "previous definition of 'a' with type 'int'"]
2317        );
2318    }
2319
2320    #[test]
2321    fn a_block_inside_the_body_may_shadow_a_parameter() {
2322        let mut f = Fixture::new();
2323        let int = f.int_specs();
2324        let a = f.param(int, Some("a"), &[]);
2325        let takes = f.takes(&[a]);
2326        let specs = f.int_specs();
2327        let shadow = f.object(specs, "a");
2328        let shadow = f.stmt(ast::Stmt::Decl(shadow));
2329        let inner = f.block(&[shadow]);
2330        let body = f.block(&[inner]);
2331        let specs = f.builtin(BuiltinSet::VOID);
2332        let decl = f.define(specs, "f", &[takes], body);
2333
2334        let mut c = f.checker();
2335        c.check_decl(decl);
2336
2337        assert!(c.errors.is_empty(), "got {:?}", messages(&c));
2338    }
2339
2340    #[test]
2341    fn an_array_parameter_is_a_pointer_in_the_body_as_well_as_in_the_type() {
2342        let mut f = Fixture::new();
2343        let int = f.int_specs();
2344        let three = f.int(3);
2345        let a = f.param(int, Some("a"), &[array(three)]);
2346        let takes = f.takes(&[a]);
2347        let use_a = f.use_name("a");
2348        let stmt = f.stmt(ast::Stmt::Expr(use_a));
2349        let body = f.block(&[stmt]);
2350        let specs = f.builtin(BuiltinSet::VOID);
2351        let decl = f.define(specs, "f", &[takes], body);
2352
2353        let mut c = f.checker();
2354        let list = c.check_decl(decl);
2355
2356        let id = only(&c, list);
2357        assert_eq!(
2358            dump(&c, id),
2359            "decl #1 f : void(int *) function external defined\n  params\n    decl #0 a : \
2360             int * object automatic defined\n  body\n    block\n      expr\n        convert \
2361             lvalue : int *\n          decl #0 a : int * lvalue\n"
2362        );
2363        assert!(c.errors.is_empty(), "got {:?}", messages(&c));
2364    }
2365
2366    #[test]
2367    fn a_qualifier_on_a_parameter_is_the_object_s_and_not_the_function_type_s() {
2368        let mut f = Fixture::new();
2369        let mut int = f.int_specs();
2370        int.quals = Quals::CONST;
2371        let a = f.param(int, Some("a"), &[]);
2372        let takes = f.takes(&[a]);
2373        let use_a = f.use_name("a");
2374        let stmt = f.stmt(ast::Stmt::Expr(use_a));
2375        let body = f.block(&[stmt]);
2376        let specs = f.builtin(BuiltinSet::VOID);
2377        let decl = f.define(specs, "f", &[takes], body);
2378
2379        let mut c = f.checker();
2380        let list = c.check_decl(decl);
2381
2382        // The type says `int` and the object says `const int`, which is the whole of the rule:
2383        // a caller is told nothing by the `const` and the body is bound by it.
2384        let id = only(&c, list);
2385        assert_eq!(
2386            dump(&c, id),
2387            "decl #1 f : void(int) function external defined\n  params\n    decl #0 a : \
2388             const int object automatic defined\n  body\n    block\n      expr\n        \
2389             convert lvalue : int\n          decl #0 a : const int lvalue\n"
2390        );
2391        assert!(c.errors.is_empty(), "got {:?}", messages(&c));
2392    }
2393
2394    #[test]
2395    fn the_body_answers_to_the_return_type_the_definition_was_written_with() {
2396        let mut f = Fixture::new();
2397        let ret = f.stmt(ast::Stmt::Return(None));
2398        let body = f.block(&[ret]);
2399        let specs = f.int_specs();
2400        let decl = f.define(specs, "f", &[function()], body);
2401
2402        let mut c = f.checker();
2403        c.check_decl(decl);
2404
2405        assert_eq!(
2406            messages(&c),
2407            ["'return' with no value, in function returning non-void", "declared here"]
2408        );
2409    }
2410
2411    #[test]
2412    fn a_declaration_and_a_definition_of_one_function_are_one_declaration() {
2413        let mut f = Fixture::new();
2414        let specs = f.builtin(BuiltinSet::VOID);
2415        let declared = f.var(specs, "f", &[function()], None);
2416        let body = f.block(&[]);
2417        let specs = f.builtin(BuiltinSet::VOID);
2418        let defined = f.define(specs, "f", &[function()], body);
2419
2420        let mut c = f.checker();
2421        let list = c.check_decl(declared);
2422        let first = only(&c, list);
2423        let list = c.check_decl(defined);
2424
2425        assert_eq!(only(&c, list), first);
2426        assert_eq!(
2427            dump(&c, first),
2428            "decl #0 f : void(void) function external defined\n  body\n    block\n"
2429        );
2430        assert!(c.errors.is_empty(), "got {:?}", messages(&c));
2431    }
2432
2433    #[test]
2434    fn a_function_definition_declared_typedef_is_an_error() {
2435        let mut f = Fixture::new();
2436        let mut specs = f.builtin(BuiltinSet::VOID);
2437        specs.storage = Some(StorageClass::Typedef);
2438        let body = f.block(&[]);
2439        let decl = f.define(specs, "f", &[function()], body);
2440
2441        let mut c = f.checker();
2442        c.check_decl(decl);
2443
2444        assert_eq!(message(&c), "function definition declared 'typedef'");
2445    }
2446
2447    #[test]
2448    fn a_function_definition_inside_a_function_is_refused_and_the_name_still_declared() {
2449        let mut f = Fixture::new();
2450        let empty = f.block(&[]);
2451        let specs = f.builtin(BuiltinSet::VOID);
2452        let nested = f.define(specs, "g", &[function()], empty);
2453        let nested = f.stmt(ast::Stmt::Decl(nested));
2454        let call = f.use_name("g");
2455        let call = f.stmt(ast::Stmt::Expr(call));
2456        let body = f.block(&[nested, call]);
2457        let specs = f.builtin(BuiltinSet::VOID);
2458        let decl = f.define(specs, "f", &[function()], body);
2459
2460        let mut c = f.checker();
2461        c.check_decl(decl);
2462
2463        // The second message is the note, and it is here so that a rewrite of it that leaves the
2464        // continuation of a line in the text is a test failure rather than something a reader of
2465        // the output notices later.
2466        assert_eq!(
2467            messages(&c),
2468            [
2469                "a function definition inside a function",
2470                "a nested function is called through a trampoline written on the stack, which no \
2471                 target that enforces an unexecutable stack allows, so this compiler does not \
2472                 have them and will not"
2473            ],
2474            "the mention of 'g' under the definition has to resolve, so that one definition is \
2475             one error"
2476        );
2477    }
2478
2479    /// `void f(a) char a; {}`, which takes its parameter type from the declaration under the
2480    /// identifier list and then promotes it, since a promoted type is what a caller of an
2481    /// unprototyped function hands over.
2482    #[test]
2483    fn an_old_style_definition_reads_the_declarations_written_under_its_list() {
2484        let mut f = Fixture::new();
2485        let int = f.int_specs();
2486        let a = f.param(int, Some("a"), &[]);
2487        let params = f.ast.add_param_list(&[a]);
2488        let old = Derived::Function { params, variadic: false, kind: ParamKind::Identifiers };
2489        let char_specs = f.builtin(BuiltinSet::CHAR);
2490        let written = f.object(char_specs, "a");
2491        let body = f.block(&[]);
2492        let specs = f.builtin(BuiltinSet::VOID);
2493        let decl = f.define_taking(specs, "f", &[old], &[written], body);
2494
2495        let mut c = f.checker();
2496        let list = c.check_decl(decl);
2497
2498        assert_eq!(messages(&c), Vec::<String>::new());
2499        let text = dump(&c, only(&c, list));
2500        assert!(text.contains("f : void(int) function"), "{text}");
2501        // And the body sees the `char` it was declared as, whatever the caller hands over.
2502        assert!(text.contains("a : char object automatic defined"), "{text}");
2503    }
2504
2505    /// The same definition with nothing declaring `a`. C89 made it an `int` and every dialect
2506    /// after it made the line a diagnostic, and the fixture is C23.
2507    #[test]
2508    fn a_name_in_an_identifier_list_that_nothing_declares_says_so() {
2509        let mut f = Fixture::new();
2510        let int = f.int_specs();
2511        let a = f.param(int, Some("a"), &[]);
2512        let params = f.ast.add_param_list(&[a]);
2513        let old = Derived::Function { params, variadic: false, kind: ParamKind::Identifiers };
2514        let body = f.block(&[]);
2515        let specs = f.builtin(BuiltinSet::VOID);
2516        let decl = f.define(specs, "f", &[old], body);
2517
2518        let mut c = f.checker();
2519        c.check_decl(decl);
2520
2521        assert_eq!(message(&c), "type of 'a' defaults to 'int'");
2522    }
2523
2524    #[test]
2525    fn a_deduced_type_is_the_type_the_initializer_would_have_where_it_is_used() {
2526        let mut f = Fixture::new();
2527        let one = f.int(1);
2528        let decl = f.var(f.deduced(ast::Deduction::Auto), "x", &[], Some(one));
2529
2530        let mut c = f.checker();
2531        let list = c.check_decl(decl);
2532
2533        let id = only(&c, list);
2534        assert_eq!(
2535            dump(&c, id),
2536            "decl #0 x : int object external static defined\n  init\n    +0\n      const 1 : int\n"
2537        );
2538        assert!(c.errors.is_empty(), "got {:?}", messages(&c));
2539    }
2540
2541    #[test]
2542    fn a_deduced_type_is_the_one_a_use_has_so_an_array_deduces_a_pointer() {
2543        let mut f = Fixture::new();
2544        let three = f.int(3);
2545        let ints = f.int_specs();
2546        let array = f.var(ints, "a", &[array(three)], None);
2547        let a = f.use_name("a");
2548        let decl = f.var(f.deduced(ast::Deduction::AutoType), "p", &[], Some(a));
2549
2550        let mut c = f.checker();
2551        c.check_decl(array);
2552        c.scopes.push();
2553        let list = c.check_decl(decl);
2554
2555        let id = only(&c, list);
2556        assert!(dump(&c, id).starts_with("decl #1 p : int *"), "{}", dump(&c, id));
2557        assert!(c.errors.is_empty(), "got {:?}", messages(&c));
2558    }
2559
2560    #[test]
2561    fn a_deduced_type_drops_the_initializers_qualifiers_and_takes_the_declarations() {
2562        let mut f = Fixture::new();
2563        let mut ints = f.int_specs();
2564        ints.quals = Quals::CONST;
2565        let one = f.int(1);
2566        let source = f.var(ints, "c", &[], Some(one));
2567        // What is put into the new object is a value, and a value is not `const`.
2568        let c1 = f.use_name("c");
2569        let plain = f.var(f.deduced(ast::Deduction::Auto), "x", &[], Some(c1));
2570        let c2 = f.use_name("c");
2571        let mut qualified = f.deduced(ast::Deduction::Auto);
2572        qualified.quals = Quals::CONST;
2573        let kept = f.var(qualified, "y", &[], Some(c2));
2574
2575        let mut c = f.checker();
2576        c.check_decl(source);
2577        c.scopes.push();
2578        let list = c.check_decl(plain);
2579        let plain = only(&c, list);
2580        let list = c.check_decl(kept);
2581        let kept = only(&c, list);
2582
2583        assert!(dump(&c, plain).starts_with("decl #1 x : int "), "{}", dump(&c, plain));
2584        assert!(dump(&c, kept).starts_with("decl #2 y : const int "), "{}", dump(&c, kept));
2585        assert!(c.errors.is_empty(), "got {:?}", messages(&c));
2586    }
2587
2588    #[test]
2589    fn a_deduced_type_needs_a_declarator_that_is_no_more_than_a_name() {
2590        let mut f = Fixture::new();
2591        // The deduction is the whole type, so there is nothing left for a `*` to add to it.
2592        let one = f.int(1);
2593        let c23 = f.var(f.deduced(ast::Deduction::Auto), "p", &[pointer()], Some(one));
2594        let two = f.int(2);
2595        let gnu = f.var(f.deduced(ast::Deduction::AutoType), "q", &[pointer()], Some(two));
2596
2597        let mut c = f.checker();
2598        c.check_decl(c23);
2599        c.check_decl(gnu);
2600
2601        // gcc words the two differently, since only C23's takes the attributes it mentions.
2602        assert_eq!(
2603            messages(&c),
2604            [
2605                "'auto' requires a plain identifier, possibly with attributes, as declarator",
2606                "'__auto_type' requires a plain identifier as declarator",
2607            ]
2608        );
2609    }
2610
2611    #[test]
2612    fn a_deduced_type_needs_something_to_deduce_from() {
2613        let mut f = Fixture::new();
2614        let decl = f.var(f.deduced(ast::Deduction::AutoType), "x", &[], None);
2615
2616        let mut c = f.checker();
2617        c.check_decl(decl);
2618
2619        assert_eq!(message(&c), "'__auto_type' requires an initialized data declaration");
2620    }
2621
2622    #[test]
2623    fn one_initializer_deduces_one_type_so_a_second_declarator_is_refused() {
2624        let mut f = Fixture::new();
2625        // Said once and about the declaration, and the first declarator is still checked so
2626        // that its name means something for the rest of the unit.
2627        let one = f.int(1);
2628        let two = f.int(2);
2629        let x = f.declarator("x", &[]);
2630        let y = f.declarator("y", &[]);
2631        let items: Vec<ast::InitDeclarator> = [(x, one), (y, two)]
2632            .into_iter()
2633            .map(|(declarator, value)| ast::InitDeclarator {
2634                declarator,
2635                init: Some(f.ast.add_init(ast::Init::Expr(value))),
2636                asm_label: None,
2637                attrs: AttrList::EMPTY,
2638                span: Span::DUMMY,
2639            })
2640            .collect();
2641        let declarators = f.ast.add_init_declarator_list(&items);
2642        let specs = f.specs(f.deduced(ast::Deduction::Auto));
2643        let decl = f.ast.decl(ast::Decl::Var { specs, declarators }, Span::DUMMY);
2644
2645        let mut c = f.checker();
2646        let list = c.check_decl(decl);
2647
2648        let id = only(&c, list);
2649        assert_eq!(
2650            dump(&c, id),
2651            "decl #0 x : int object external static defined\n  init\n    +0\n      const 1 : int\n"
2652        );
2653        assert_eq!(message(&c), "'auto' may only be used with a single declarator");
2654    }
2655
2656    #[test]
2657    fn a_function_definition_deduces_nothing_because_it_has_no_initializer() {
2658        let mut f = Fixture::new();
2659        let body = f.block(&[]);
2660        let decl = f.define(f.deduced(ast::Deduction::Auto), "f", &[function()], body);
2661
2662        let mut c = f.checker();
2663        let list = c.check_decl(decl);
2664
2665        assert!(c.tast[list].is_empty());
2666        assert_eq!(
2667            message(&c),
2668            "'auto' requires a plain identifier, possibly with attributes, as declarator"
2669        );
2670    }
2671
2672    #[test]
2673    fn a_name_with_no_type_until_its_initializer_is_checked_may_not_be_used_in_it() {
2674        let mut f = Fixture::new();
2675        // The name is in scope inside its own initializer, which is what makes this a
2676        // reference to report rather than a use of an undeclared name.
2677        let x = f.use_name("x");
2678        let deduced = f.var(f.deduced(ast::Deduction::Auto), "x", &[], Some(x));
2679        let y = f.use_name("y");
2680        let mut ints = f.int_specs();
2681        ints.constexpr = true;
2682        let constant = f.var(ints, "y", &[], Some(y));
2683
2684        let mut c = f.checker();
2685        c.scopes.push();
2686        c.check_decl(deduced);
2687        c.check_decl(constant);
2688
2689        // A `constexpr` has a type before its initializer and no value until after it, which
2690        // C23 calls underspecified for the same reason and gcc reports the same way.
2691        assert_eq!(
2692            messages(&c),
2693            [
2694                "underspecified 'x' referenced in its initializer",
2695                "underspecified 'y' referenced in its initializer",
2696            ]
2697        );
2698    }
2699}