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