My question is similar to this one, but subtly different.
Suppose I have two translation units, exec.cpp
and lib.cpp
, as followed:
// exec.cpp
int foo();
int main() {
return foo();
}
and
// lib.cpp
auto foo() {
return 42;
}
Is it legal to compile and link them together? Or is it ill-formed NDR?
Note: both g++ and clang generate the expected executable (i.e. returns 42) with command <compiler> exec.cpp lib.cpp -o program
Note: Arguably this is a bad practice (as the return type can change if the implementation changes, and breaks the code). But I still would like to know the answer.
All standard references below refers to N4861: March 2020 post-Prague working draft/C++20 DIS..
From [basic.link]/11 [emphasis mine]:
After all adjustments of types (during which typedefs are replaced by their definitions), the types specified by all declarations referring to a given variable or function shall be identical, except that declarations for an array object can specify array types that differ by the presence or absence of a major array bound ([dcl.array]). A violation of this rule on type identity does not require a diagnostic.
[dcl.spec.auto]/3 covers that a placeholder type can appear with a function declarator, and if this declarator does not include a trailing-return-type (as is the case of OP's example)
[...] Otherwise [no trailing-return-type], the function declarator shall declare a function.
where
[...] the return type of the function is deduced from non-discarded
return
statements, if any, in the body of the function ([stmt.if]).
[dcl.fct]/1 covers function declarators that do not include a trailing-return-type [emphasis mine, removing opt parts of the grammar that do not apply in this particular example]:
In a declaration
T D
whereD
has the form [...] the type of the declarator-id inD
is “derived-declarator-type-list function of parameter-type-list returningT
” [...]
Thus, the two declarations
int f(); // #1
auto foo() { // #2
// [dcl.spec.auto]/3:
// return type deduced to 'int'
}
both declare functions where the type of the associated declarator-id in D
of these T D
declarations is
“derived-declarator-type-list function of parameter-type-list returning
T
”
where in both cases, T
is int
:
#1
,#2
.Thus, the declarations #1
and #2
, after all adjustments of types, have identical (function) types, thus fulfilling [basic.link]/11, and the OP's example is well-formed. Any slight variation of the definition of auto f()
, however, could lead to a deduced return type which is not int
, in which case [basic.link]/11 is violated, NDR.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With