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