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