Discussion:
[std-discussion] Does odr-use depend on run-time behavior?
Jan Tušil
2018-11-27 20:08:35 UTC
Permalink
Consider a program P1:
```
struct S {
~S(); // no implicit definition!
};
int main() {
S s;
}
```

Is `S::~S` odr-used in P1? Yes. Clang complains
```

undefined reference to `S::~S()'

```
because `S::~S` is potentially-invoked at the end of the function
`main` because it is invoked here,
because a block in which `s` is defined exits here. This is what N4778 says
in 10.3.6/12:

A destructor is invoked implicitly [...] for a constructed object with
automatic storage duration (6.6.4.3)
when the block in which an object is created exits (8.7).

A destructor is potentially invoked if it is invoked or as specified in
[...]
But consider a program P2:
```
struct S {
~S(); // no implicit definition!
};
int main() {
S s;
while(true)
;
}
```
The block in the function `main` never exits, so S::~S is not odr-used. But
this is weird: odr-use depends on termination, which is undecidable. The
loop may as well be trying to find a counterexample to Fermat's last
theorem, and break when successful.
A destructor is potentially invoked if it is invoked or as specified in
[...]
since I would expect the definition of `potentially-invoked destructor` to
be similar to the definition of `potentially-evaluated expression`. And
decidable.

So I have three questions:

1. is `S::~S` odr-used in P2?
2. if (1) is false, why?
3. if (1) is true, do we want it that way?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Jan Tušil
2018-11-27 20:11:39 UTC
Permalink
Post by Jan Tušil
```
struct S {
~S(); // no implicit definition!
};
int main() {
S s;
}
```
Is `S::~S` odr-used in P1? Yes. Clang complains
```
undefined reference to `S::~S()'
```
because `S::~S` is potentially-invoked at the end of the function
`main` because it is invoked here,
because a block in which `s` is defined exits here. This is what N4778
A destructor is invoked implicitly [...] for a constructed object with
automatic storage duration (6.6.4.3)
when the block in which an object is created exits (8.7).
A destructor is potentially invoked if it is invoked or as specified in
[...]
```
struct S {
~S(); // no implicit definition!
};
int main() {
S s;
while(true)
;
}
```
The block in the function `main` never exits, so S::~S is not odr-used.
But this is weird: odr-use depends on termination, which is undecidable.
The loop may as well be trying to find a counterexample to Fermat's last
theorem, and break when successful.
A destructor is potentially invoked if it is invoked or as specified in
[...]
since I would expect the definition of `potentially-invoked destructor` to
be similar to the definition of `potentially-evaluated expression`. And
decidable.
1. is `S::~S` odr-used in P2?
2. if (1) is false, why?
3. if (1) is true, do we want it that way?
So I have three questions:

1. is `S::~S` odr-used in P2?
2. if (1) is *true*, why?
3. if (1) is *false*, do we want it that way?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Hyman Rosen
2018-11-27 20:22:40 UTC
Permalink
Post by Jan Tušil
The block in the function `main` never exits, so S::~S is not odr-used.
See [intro.progress]. The compiler is allowed to assume that an empty loop
terminates.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2018-11-27 20:23:34 UTC
Permalink
Post by Jan Tušil
```
struct S {
~S(); // no implicit definition!
};
int main() {
S s;
while(true)
;
}
```
The block in the function `main` never exits, so S::~S is not odr-used. But
this is weird: odr-use depends on termination, which is undecidable.
Infinite loops (and I mean really infinite) are UB. Therefore this example is
no good.
Post by Jan Tušil
The
loop may as well be trying to find a counterexample to Fermat's last
theorem, and break when successful.
Then write that.

bool counter_example_found = false;
void fermat_iteration();
int main()
{
S s;
while (!counter_example_found)
fermat_iteration();
}

In this case, the compiler will not remove the call to the destructor.

Interestingly, the ODR-use disappears if you insert a [[noreturn]] function:

int main()
{
S s;
exit(0);
}

(but not in all compilers)
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Jan Tušil
2018-11-27 20:47:28 UTC
Permalink
Updating my question. [intro.progress]/1 says:

The implementation may assume that any thread will eventually do one of the
following:
(1.1) — terminate,
(1.2) — make a call to a library I/O function,
(1.3) — perform an access through a volatile glvalue, or
(1.4) — perform a synchronization operation or an atomic operation.

Updated question: is `S::~S` odr-used in the following program (P3)?
struct S {
~S();
};
volatile int x=0;
int main() {
S s;
while(true)
x = 1;
}

And a new question: Does the definition of odr-use in the standard depend
on what an implementation may assume?

Thanks.
Post by Jan Tušil
```
struct S {
~S(); // no implicit definition!
};
int main() {
S s;
}
```
Is `S::~S` odr-used in P1? Yes. Clang complains
```
undefined reference to `S::~S()'
```
because `S::~S` is potentially-invoked at the end of the function
`main` because it is invoked here,
because a block in which `s` is defined exits here. This is what N4778
A destructor is invoked implicitly [...] for a constructed object with
automatic storage duration (6.6.4.3)
when the block in which an object is created exits (8.7).
A destructor is potentially invoked if it is invoked or as specified in
[...]
```
struct S {
~S(); // no implicit definition!
};
int main() {
S s;
while(true)
;
}
```
The block in the function `main` never exits, so S::~S is not odr-used.
But this is weird: odr-use depends on termination, which is undecidable.
The loop may as well be trying to find a counterexample to Fermat's last
theorem, and break when successful.
A destructor is potentially invoked if it is invoked or as specified in
[...]
since I would expect the definition of `potentially-invoked destructor` to
be similar to the definition of `potentially-evaluated expression`. And
decidable.
1. is `S::~S` odr-used in P2?
2. if (1) is false, why?
3. if (1) is true, do we want it that way?
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Nicolas Lesser
2018-11-27 20:53:46 UTC
Permalink
Post by Jan Tušil
The implementation may assume that any thread will eventually do one of
(1.1) — terminate,
(1.2) — make a call to a library I/O function,
(1.3) — perform an access through a volatile glvalue, or
(1.4) — perform a synchronization operation or an atomic operation.
Updated question: is `S::~S` odr-used in the following program (P3)?
struct S {
~S();
};
volatile int x=0;
int main() {
S s;
while(true)
x = 1;
}
yes.
Whether a destructor is invoked is not a runtime property as far as the
language is concerned. [class.dtor]p12 says that the destructor for `s` is
invoked when its block scope ends. There is no runtime property here.
Post by Jan Tušil
And a new question: Does the definition of odr-use in the standard depend
on what an implementation may assume?
No it doesn't, see [basic.def.odr]p4.
Post by Jan Tušil
Thanks.
Post by Jan Tušil
```
struct S {
~S(); // no implicit definition!
};
int main() {
S s;
}
```
Is `S::~S` odr-used in P1? Yes. Clang complains
```
undefined reference to `S::~S()'
```
because `S::~S` is potentially-invoked at the end of the function
`main` because it is invoked here,
because a block in which `s` is defined exits here. This is what N4778
A destructor is invoked implicitly [...] for a constructed object with
automatic storage duration (6.6.4.3)
when the block in which an object is created exits (8.7).
A destructor is potentially invoked if it is invoked or as specified in
[...]
```
struct S {
~S(); // no implicit definition!
};
int main() {
S s;
while(true)
;
}
```
The block in the function `main` never exits, so S::~S is not odr-used.
But this is weird: odr-use depends on termination, which is undecidable.
The loop may as well be trying to find a counterexample to Fermat's last
theorem, and break when successful.
A destructor is potentially invoked if it is invoked or as specified in
[...]
since I would expect the definition of `potentially-invoked destructor`
to be similar to the definition of `potentially-evaluated expression`. And
decidable.
1. is `S::~S` odr-used in P2?
2. if (1) is false, why?
3. if (1) is true, do we want it that way?
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
https://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Jan Tušil
2018-11-27 21:10:50 UTC
Permalink
Quoting the paragraph you mention from N4778,
Post by Jan Tušil
A destructor is invoked implicitly
(12.1) — for a constructed object with static storage duration (6.6.4.1)
at program termination (6.8.3.4),
(12.2) — for a constructed object with thread storage duration (6.6.4.2)
at thread exit,
(12.3) — for a constructed object with automatic storage duration
(6.6.4.3) when the block in which an object is
created exits (8.7),
(12.4) — for a constructed temporary object when its lifetime ends (7.3.4,
6.6.6).
In each case, the context of the invocation is the context of the
construction of the object. A destructor may
also be invoked implicitly through use of a delete-expression (7.6.2.5)
for a constructed object allocated by a
new-expression (7.6.2.4); the context of the invocation is the
delete-expression. [Note: An array of class type
contains several subobjects for each of which the destructor is invoked.
—end note] A destructor can also
be invoked explicitly. A destructor is potentially invoked if it is
invoked or as specified in 7.6.2.4, 9.3.1, 10.9.2,
and 13.1. A program is ill-formed if a destructor that is potentially
invoked is deleted or not accessible from
the context of the invocation.
[class.dtor]p12 says that the destructor for `s` is invoked when its
block scope ends.

It says
Post by Jan Tušil
when the block in which an object is created exits
On exit from a scope (however accomplished), objects with automatic
storage duration (6.6.4.3) that have
been constructed in that scope are destroyed in the reverse order of their
construction. [Note: For temporaries,
see 6.6.6. —end note] Transfer out of a loop, out of a block, or back past
an initialized variable with
automatic storage duration involves the destruction of objects with
automatic storage duration that are in
scope at the point transferred from but not at the point transferred to.
(See 8.7 for transfers into blocks).
[Note: However, the program can be terminated (by calling std::exit() or
std::abort() (16.5), for
example) without destroying class objects with automatic storage duration.
—end note]
Thank you.
Post by Jan Tušil
Post by Jan Tušil
The implementation may assume that any thread will eventually do one of
(1.1) — terminate,
(1.2) — make a call to a library I/O function,
(1.3) — perform an access through a volatile glvalue, or
(1.4) — perform a synchronization operation or an atomic operation.
Updated question: is `S::~S` odr-used in the following program (P3)?
struct S {
~S();
};
volatile int x=0;
int main() {
S s;
while(true)
x = 1;
}
yes.
Whether a destructor is invoked is not a runtime property as far as the
language is concerned. [class.dtor]p12 says that the destructor for `s` is
invoked when its block scope ends. There is no runtime property here.
Post by Jan Tušil
And a new question: Does the definition of odr-use in the standard depend
on what an implementation may assume?
No it doesn't, see [basic.def.odr]p4.
Post by Jan Tušil
Thanks.
Post by Jan Tušil
```
struct S {
~S(); // no implicit definition!
};
int main() {
S s;
}
```
Is `S::~S` odr-used in P1? Yes. Clang complains
```
undefined reference to `S::~S()'
```
because `S::~S` is potentially-invoked at the end of the function
`main` because it is invoked here,
because a block in which `s` is defined exits here. This is what N4778
A destructor is invoked implicitly [...] for a constructed object with
automatic storage duration (6.6.4.3)
when the block in which an object is created exits (8.7).
A destructor is potentially invoked if it is invoked or as specified in
[...]
```
struct S {
~S(); // no implicit definition!
};
int main() {
S s;
while(true)
;
}
```
The block in the function `main` never exits, so S::~S is not odr-used.
But this is weird: odr-use depends on termination, which is undecidable.
The loop may as well be trying to find a counterexample to Fermat's last
theorem, and break when successful.
A destructor is potentially invoked if it is invoked or as specified in
[...]
since I would expect the definition of `potentially-invoked destructor`
to be similar to the definition of `potentially-evaluated expression`. And
decidable.
1. is `S::~S` odr-used in P2?
2. if (1) is false, why?
3. if (1) is true, do we want it that way?
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
https://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Brian Bi
2018-11-27 20:54:12 UTC
Permalink
I am fairly certain that odr-use is not a runtime property. When the
standard says that the destructor is "potentially invoked" if it is
"invoked", what it means by "invoked" is that the code contains an
invocation of the destructor. You are meant to disregard whether the code
is actually reachable or not.

Here's another example that avoids the infinite loop thing:

#include <cstdlib>
struct S { ~S(); }
int main() { S s; std::exit(0); }

I'm pretty sure that the standard requires S::~S() to be defined in this
program.
Post by Jan Tušil
The implementation may assume that any thread will eventually do one of
(1.1) — terminate,
(1.2) — make a call to a library I/O function,
(1.3) — perform an access through a volatile glvalue, or
(1.4) — perform a synchronization operation or an atomic operation.
Updated question: is `S::~S` odr-used in the following program (P3)?
struct S {
~S();
};
volatile int x=0;
int main() {
S s;
while(true)
x = 1;
}
And a new question: Does the definition of odr-use in the standard depend
on what an implementation may assume?
Thanks.
Post by Jan Tušil
```
struct S {
~S(); // no implicit definition!
};
int main() {
S s;
}
```
Is `S::~S` odr-used in P1? Yes. Clang complains
```
undefined reference to `S::~S()'
```
because `S::~S` is potentially-invoked at the end of the function
`main` because it is invoked here,
because a block in which `s` is defined exits here. This is what N4778
A destructor is invoked implicitly [...] for a constructed object with
automatic storage duration (6.6.4.3)
when the block in which an object is created exits (8.7).
A destructor is potentially invoked if it is invoked or as specified in
[...]
```
struct S {
~S(); // no implicit definition!
};
int main() {
S s;
while(true)
;
}
```
The block in the function `main` never exits, so S::~S is not odr-used.
But this is weird: odr-use depends on termination, which is undecidable.
The loop may as well be trying to find a counterexample to Fermat's last
theorem, and break when successful.
A destructor is potentially invoked if it is invoked or as specified in
[...]
since I would expect the definition of `potentially-invoked destructor`
to be similar to the definition of `potentially-evaluated expression`. And
decidable.
1. is `S::~S` odr-used in P2?
2. if (1) is false, why?
3. if (1) is true, do we want it that way?
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
https://groups.google.com/a/isocpp.org/group/std-discussion/.
--
*Brian Bi*
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Jan Tušil
2018-11-27 23:09:47 UTC
Permalink
Hi Brian, thanks. What the standard means by "potentially invoked" can be
found in [class.dtor]/12:

A destructor is potentially invoked if it is invoked or as specified in
7.6.2.4, 9.3.1, 10.9.2, and 13.1.
Concerning your program, and let us give it a name, P4:
#include <cstdlib>
struct S { ~S(); };
int main() { S s; std::exit(0); }

I do not think the standard requires S::~S to be defined. This compiles and
runs pretty well, and even if the destructor were defined, it would not be
executed. But clearly, S::~S is never explicitly invoked in the program.
And it is not invoked even implicitly, according to [class.decl]/12. So it
is not potentially invoked, so it is not odr-used. Therefore no need to
define S::~S.
I am fairly certain that odr-use is not a runtime property. When the
standard says that the destructor is "potentially invoked" if it is
"invoked", what it means by "invoked" is that the code contains an
invocation of the destructor. You are meant to disregard whether the code
is actually reachable or not.
#include <cstdlib>
struct S { ~S(); }
int main() { S s; std::exit(0); }
I'm pretty sure that the standard requires S::~S() to be defined in this
program.
Post by Jan Tušil
The implementation may assume that any thread will eventually do one of
(1.1) — terminate,
(1.2) — make a call to a library I/O function,
(1.3) — perform an access through a volatile glvalue, or
(1.4) — perform a synchronization operation or an atomic operation.
Updated question: is `S::~S` odr-used in the following program (P3)?
struct S {
~S();
};
volatile int x=0;
int main() {
S s;
while(true)
x = 1;
}
And a new question: Does the definition of odr-use in the standard depend
on what an implementation may assume?
Thanks.
Post by Jan Tušil
```
struct S {
~S(); // no implicit definition!
};
int main() {
S s;
}
```
Is `S::~S` odr-used in P1? Yes. Clang complains
```
undefined reference to `S::~S()'
```
because `S::~S` is potentially-invoked at the end of the function
`main` because it is invoked here,
because a block in which `s` is defined exits here. This is what N4778
A destructor is invoked implicitly [...] for a constructed object with
automatic storage duration (6.6.4.3)
when the block in which an object is created exits (8.7).
A destructor is potentially invoked if it is invoked or as specified in
[...]
```
struct S {
~S(); // no implicit definition!
};
int main() {
S s;
while(true)
;
}
```
The block in the function `main` never exits, so S::~S is not odr-used.
But this is weird: odr-use depends on termination, which is undecidable.
The loop may as well be trying to find a counterexample to Fermat's last
theorem, and break when successful.
A destructor is potentially invoked if it is invoked or as specified in
[...]
since I would expect the definition of `potentially-invoked destructor`
to be similar to the definition of `potentially-evaluated expression`. And
decidable.
1. is `S::~S` odr-used in P2?
2. if (1) is false, why?
3. if (1) is true, do we want it that way?
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
https://groups.google.com/a/isocpp.org/group/std-discussion/.
--
*Brian Bi*
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Thiago Macieira
2018-11-27 23:36:26 UTC
Permalink
Post by Brian Bi
#include <cstdlib>
struct S { ~S(); };
int main() { S s; std::exit(0); }
I do not think the standard requires S::~S to be defined.
Yes, it does.
Post by Brian Bi
This compiles and
runs pretty well, and even if the destructor were defined, it would not be
executed.
The fact that one compiler, under certain optimisation flags, allows this to
compile, is not an indication that it is correct. If S::~S is not defined
anywhere, then this program is ill-formed.
Post by Brian Bi
But clearly, S::~S is never explicitly invoked in the program.
Correct.
Post by Brian Bi
And it is not invoked even implicitly, according to [class.decl]/12. So it
is not potentially invoked, so it is not odr-used. Therefore no need to
define S::~S.
I disagree.

Let's try another one (P5):

#include <signal.h>
struct S { ~S(); };
int main() { S s; raise(SIGTERM); }

The above program never executes S::~S() and yet it must be defined.

And if your problem is calling a function outside of the standard, then (P6):

void call_exit_in_other_tu();
struct S { ~S(); };
int main() { S s; call_exit_in_other_tu(); }
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Jan Tušil
2018-11-28 00:42:30 UTC
Permalink
Does it follow from the wording that S::~S is odr-used?
I agree with you that the standard *should* require S::~S in P4 and P5 to
be odr-used. But I do not agree that it *does*.

Can you (or anyone) argue from the wording of a standard draft (say, from
n4788 <https://github.com/cplusplus/draft/blob/master/papers/n4788.pdf>)
that S::~S is that S::~S is odr-used? One potential line of reasoning would
be:

[basic.def.odr]/8
A destructor for a class is odr-used if it is potentially invoked
[class.dtor]/12
A destructor is potentially invoked if it is invoked or as specified in
7.6.2.4, 9.3.1, 10.9.2,
and 13.1.
[class.dtor]/12 (again)
A destructor is invoked implicitly [...] for a constructed object with
automatic storage duration (6.6.4.3) when the block in which an object is
created exits.
The block in which a variable of a class type `S` is declared, exits.
But the problem is, what if the block does not exit? If it exits or not,
that is a runtime property. Note that the standard does not say
A destructor is invoked implicitly [...] *where* the block in which an
object is created exits.
or
A destructor is invoked implicitly [...] *if* the block in which an
object is created exits.
At the time *when* the program is running and the block *exits*, the
destructor is implicitly invoked.
At the place of the source code *where* the block *ends*, the destructor
is implicitly invoked.
So this line of reasoning does not work. And my point is not that it should
not work, but that the wording is broken.
Post by Brian Bi
#include <cstdlib>
struct S { ~S(); };
int main() { S s; std::exit(0); }
I do not think the standard requires S::~S to be defined.
Yes, it does.
Post by Brian Bi
This compiles and
runs pretty well, and even if the destructor were defined, it would not
be
Post by Brian Bi
executed.
The fact that one compiler, under certain optimisation flags, allows this to
compile, is not an indication that it is correct. If S::~S is not defined
anywhere, then this program is ill-formed.
Post by Brian Bi
But clearly, S::~S is never explicitly invoked in the program.
Correct.
Post by Brian Bi
And it is not invoked even implicitly, according to [class.decl]/12. So
it
Post by Brian Bi
is not potentially invoked, so it is not odr-used. Therefore no need to
define S::~S.
I disagree.
#include <signal.h>
struct S { ~S(); };
int main() { S s; raise(SIGTERM); }
The above program never executes S::~S() and yet it must be defined.
void call_exit_in_other_tu();
struct S { ~S(); };
int main() { S s; call_exit_in_other_tu(); }
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Brian Bi
2018-11-28 00:52:40 UTC
Permalink
Post by Jan Tušil
Does it follow from the wording that S::~S is odr-used?
I agree with you that the standard *should* require S::~S in P4 and P5 to
be odr-used. But I do not agree that it *does*.
Can you (or anyone) argue from the wording of a standard draft (say, from
n4788 <https://github.com/cplusplus/draft/blob/master/papers/n4788.pdf>)
that S::~S is that S::~S is odr-used? One potential line of reasoning would
My argument is that odr-use is *obviously intended* to be a link-time
property, so when determining if a function is odr-used, you must interpret
the word "invoked" to mean "there is code in the program that invokes the
function", not "an invocation of the function occurs when the program is
run". However, I do agree with you that the standards text is not explicit
about this. Consider opening up an editorial issue.
Post by Jan Tušil
[basic.def.odr]/8
A destructor for a class is odr-used if it is potentially invoked
[class.dtor]/12
A destructor is potentially invoked if it is invoked or as specified in
7.6.2.4, 9.3.1, 10.9.2,
and 13.1.
[class.dtor]/12 (again)
A destructor is invoked implicitly [...] for a constructed object with
automatic storage duration (6.6.4.3) when the block in which an object is
created exits.
The block in which a variable of a class type `S` is declared, exits.
But the problem is, what if the block does not exit? If it exits or not,
that is a runtime property. Note that the standard does not say
A destructor is invoked implicitly [...] *where* the block in which an
object is created exits.
or
A destructor is invoked implicitly [...] *if* the block in which an
object is created exits.
At the time *when* the program is running and the block *exits*, the
destructor is implicitly invoked.
At the place of the source code *where* the block *ends*, the destructor
is implicitly invoked.
So this line of reasoning does not work. And my point is not that it
should not work, but that the wording is broken.
Post by Brian Bi
#include <cstdlib>
struct S { ~S(); };
int main() { S s; std::exit(0); }
I do not think the standard requires S::~S to be defined.
Yes, it does.
Post by Brian Bi
This compiles and
runs pretty well, and even if the destructor were defined, it would not
be
Post by Brian Bi
executed.
The fact that one compiler, under certain optimisation flags, allows this to
compile, is not an indication that it is correct. If S::~S is not defined
anywhere, then this program is ill-formed.
Post by Brian Bi
But clearly, S::~S is never explicitly invoked in the program.
Correct.
Post by Brian Bi
And it is not invoked even implicitly, according to [class.decl]/12. So
it
Post by Brian Bi
is not potentially invoked, so it is not odr-used. Therefore no need to
define S::~S.
I disagree.
#include <signal.h>
struct S { ~S(); };
int main() { S s; raise(SIGTERM); }
The above program never executes S::~S() and yet it must be defined.
void call_exit_in_other_tu();
struct S { ~S(); };
int main() { S s; call_exit_in_other_tu(); }
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
https://groups.google.com/a/isocpp.org/group/std-discussion/.
--
*Brian Bi*
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Jan Tušil
2018-11-28 17:59:52 UTC
Permalink
Submitted an issue: https://github.com/cplusplus/draft/issues/2541
Post by Brian Bi
Post by Jan Tušil
Does it follow from the wording that S::~S is odr-used?
I agree with you that the standard *should* require S::~S in P4 and P5
to be odr-used. But I do not agree that it *does*.
Can you (or anyone) argue from the wording of a standard draft (say, from
n4788 <https://github.com/cplusplus/draft/blob/master/papers/n4788.pdf>)
that S::~S is that S::~S is odr-used? One potential line of reasoning would
My argument is that odr-use is *obviously intended* to be a link-time
property, so when determining if a function is odr-used, you must interpret
the word "invoked" to mean "there is code in the program that invokes the
function", not "an invocation of the function occurs when the program is
run". However, I do agree with you that the standards text is not explicit
about this. Consider opening up an editorial issue.
Post by Jan Tušil
[basic.def.odr]/8
A destructor for a class is odr-used if it is potentially invoked
[class.dtor]/12
A destructor is potentially invoked if it is invoked or as specified in
7.6.2.4, 9.3.1, 10.9.2,
and 13.1.
[class.dtor]/12 (again)
A destructor is invoked implicitly [...] for a constructed object with
automatic storage duration (6.6.4.3) when the block in which an object is
created exits.
The block in which a variable of a class type `S` is declared, exits.
But the problem is, what if the block does not exit? If it exits or not,
that is a runtime property. Note that the standard does not say
A destructor is invoked implicitly [...] *where* the block in which an
object is created exits.
or
A destructor is invoked implicitly [...] *if* the block in which an
object is created exits.
At the time *when* the program is running and the block *exits*, the
destructor is implicitly invoked.
At the place of the source code *where* the block *ends*, the
destructor is implicitly invoked.
So this line of reasoning does not work. And my point is not that it
should not work, but that the wording is broken.
Post by Brian Bi
#include <cstdlib>
struct S { ~S(); };
int main() { S s; std::exit(0); }
I do not think the standard requires S::~S to be defined.
Yes, it does.
Post by Brian Bi
This compiles and
runs pretty well, and even if the destructor were defined, it would
not be
Post by Brian Bi
executed.
The fact that one compiler, under certain optimisation flags, allows this to
compile, is not an indication that it is correct. If S::~S is not defined
anywhere, then this program is ill-formed.
Post by Brian Bi
But clearly, S::~S is never explicitly invoked in the program.
Correct.
Post by Brian Bi
And it is not invoked even implicitly, according to [class.decl]/12.
So it
Post by Brian Bi
is not potentially invoked, so it is not odr-used. Therefore no need
to
Post by Brian Bi
define S::~S.
I disagree.
#include <signal.h>
struct S { ~S(); };
int main() { S s; raise(SIGTERM); }
The above program never executes S::~S() and yet it must be defined.
void call_exit_in_other_tu();
struct S { ~S(); };
int main() { S s; call_exit_in_other_tu(); }
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
https://groups.google.com/a/isocpp.org/group/std-discussion/.
--
*Brian Bi*
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Richard Smith
2018-11-28 01:48:19 UTC
Permalink
Post by Jan Tušil
Does it follow from the wording that S::~S is odr-used?
I agree with you that the standard *should* require S::~S in P4 and P5 to
be odr-used. But I do not agree that it *does*.
Can you (or anyone) argue from the wording of a standard draft (say, from
n4788 <https://github.com/cplusplus/draft/blob/master/papers/n4788.pdf>)
that S::~S is that S::~S is odr-used? One potential line of reasoning would
[basic.def.odr]/8
A destructor for a class is odr-used if it is potentially invoked
[class.dtor]/12
A destructor is potentially invoked if it is invoked or as specified in
7.6.2.4, 9.3.1, 10.9.2,
and 13.1.
[class.dtor]/12 (again)
A destructor is invoked implicitly [...] for a constructed object with
automatic storage duration (6.6.4.3) when the block in which an object is
created exits.
That happens at the close brace of the function; that's when the block
exits. It doesn't matter whether or not the close brace is ever "executed"
at runtime. What this means is that we rewrite:

int main() {
S s;
while(true)
;
} // block in which s was created exits here

... as ...

int main() {
S s;
while(true)
;
s.~S(); // odr-use of destructor
}

Perhaps it would be clearer to describe this as "at the end of the block in
which an object is created" rather than as "when the block in which an
object is created exits" but the intended meaning is the same.
Post by Jan Tušil
The block in which a variable of a class type `S` is declared, exits.
But the problem is, what if the block does not exit? If it exits or not,
that is a runtime property. Note that the standard does not say
A destructor is invoked implicitly [...] *where* the block in which an
object is created exits.
or
A destructor is invoked implicitly [...] *if* the block in which an
object is created exits.
At the time *when* the program is running and the block *exits*, the
destructor is implicitly invoked.
At the place of the source code *where* the block *ends*, the destructor
is implicitly invoked.
So this line of reasoning does not work. And my point is not that it
should not work, but that the wording is broken.
Post by Brian Bi
#include <cstdlib>
struct S { ~S(); };
int main() { S s; std::exit(0); }
I do not think the standard requires S::~S to be defined.
Yes, it does.
Post by Brian Bi
This compiles and
runs pretty well, and even if the destructor were defined, it would not
be
Post by Brian Bi
executed.
The fact that one compiler, under certain optimisation flags, allows this to
compile, is not an indication that it is correct. If S::~S is not defined
anywhere, then this program is ill-formed.
Post by Brian Bi
But clearly, S::~S is never explicitly invoked in the program.
Correct.
Post by Brian Bi
And it is not invoked even implicitly, according to [class.decl]/12. So
it
Post by Brian Bi
is not potentially invoked, so it is not odr-used. Therefore no need to
define S::~S.
I disagree.
#include <signal.h>
struct S { ~S(); };
int main() { S s; raise(SIGTERM); }
The above program never executes S::~S() and yet it must be defined.
void call_exit_in_other_tu();
struct S { ~S(); };
int main() { S s; call_exit_in_other_tu(); }
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at
https://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Jens Maurer
2018-11-28 22:10:43 UTC
Permalink
Does it follow from the wording that S::~S is odr-used?
I agree with you that the standard *should* require S::~S in P4 and P5 to be odr-used. But I do not agree that it *does*.
[basic.def.odr]/8
A destructor for a class is odr-used if it is potentially invoked
[class.dtor]/12
A destructor is potentially invoked if it is invoked or as specified in 7.6.2.4, 9.3.1, 10.9.2,
and 13.1.
[class.dtor]/12 (again)
A destructor is invoked implicitly [...] for a constructed object with automatic storage duration (6.6.4.3) when the block in which an object is
created exits.
Perhaps it would be clearer to describe this as "at the end of the
block in which an object is created" rather than as "when the block
in which an object is created exits" but the intended meaning is the
same.
We already have "potentially invoked" for situations like exceptions
thrown in the middle of the construction of a class (where we
invoke destructors for initialized subobjects); it seems to me
that the case discussed here is not much different from never
actually throwing. Thus, I think we should extend the definition
of "potentially invoked" to also include the cases in the list
in [class.dtor] p12, which is otherwise redundant with normative
statements elsewhere.

Jens
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Jan Tušil
2018-11-29 16:35:34 UTC
Permalink
Hi Jens,

I am not sure what you mean by
which is otherwise redundant with normative statements elsewhere
but the definition of potentially invoked is already extended to cases in
p12. The paragraph starts with
A destructor is invoked implicitly
which refers to the term *invoked* - if something is *invoked implicitly*,
we can also say it is *invoked*. And p12 also says that
A destructor is potentially invoked if it is invoked or [...]
The problem is elsewhere.
Thanks.
JT
Does it follow from the wording that S::~S is odr-used?
I agree with you that the standard *should* require S::~S in P4 and
P5 to be odr-used. But I do not agree that it *does*.
Can you (or anyone) argue from the wording of a standard draft (say,
from n4788 <
https://github.com/cplusplus/draft/blob/master/papers/n4788.pdf>) that
[basic.def.odr]/8
A destructor for a class is odr-used if it is potentially
invoked
[class.dtor]/12
A destructor is potentially invoked if it is invoked or as
specified in 7.6.2.4, 9.3.1, 10.9.2,
and 13.1.
[class.dtor]/12 (again)
A destructor is invoked implicitly [...] for a constructed
object with automatic storage duration (6.6.4.3) when the block in which an
object is
created exits.
Perhaps it would be clearer to describe this as "at the end of the
block in which an object is created" rather than as "when the block
in which an object is created exits" but the intended meaning is the
same.
We already have "potentially invoked" for situations like exceptions
thrown in the middle of the construction of a class (where we
invoke destructors for initialized subobjects); it seems to me
that the case discussed here is not much different from never
actually throwing. Thus, I think we should extend the definition
of "potentially invoked" to also include the cases in the list
in [class.dtor] p12, which is otherwise redundant with normative
statements elsewhere.
Jens
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Jens Maurer
2018-11-29 22:17:37 UTC
Permalink
Post by Jan Tušil
Hi Jens,
I am not sure what you mean by
which is otherwise redundant with normative statements elsewhere
I believe the list at the beginning of [class.dtor] p12, saying
when a destructor is invoked implicitly, is redundant with the
normative statements talking about destroying objects at certain
points. (Look at the targets of the cross-references in the list.)

Jens
Post by Jan Tušil
but the definition of potentially invoked is already extended to cases in p12. The paragraph starts with
A destructor is invoked implicitly
which refers to the term /invoked/ - if something is /invoked implicitly/, we can also say it is /invoked/. And p12 also says that
A destructor is potentially invoked if it is invoked or [...]
The problem is elsewhere.
Thanks.
JT
Does it follow from the wording that S::~S is odr-used?
I agree with you that the standard *should* require S::~S in P4 and P5 to be odr-used. But I do not agree that it *does*.
[basic.def.odr]/8
A destructor for a class is odr-used if it is potentially invoked
[class.dtor]/12
A destructor is potentially invoked if it is invoked or as specified in 7.6.2.4, 9.3.1, 10.9.2,
and 13.1.
[class.dtor]/12 (again)
A destructor is invoked implicitly [...] for a constructed object with automatic storage duration (6.6.4.3) when the block in which an object is
created exits.
Perhaps it would be clearer to describe this as "at the end of the
block in which an object is created" rather than as "when the block
in which an object is created exits" but the intended meaning is the
same.
We already have "potentially invoked" for situations like exceptions
thrown in the middle of the construction of a class (where we
invoke destructors for initialized subobjects); it seems to me
that the case discussed here is not much different from never
actually throwing. Thus, I think we should extend the definition
of "potentially invoked" to also include the cases in the list
in [class.dtor] p12, which is otherwise redundant with normative
statements elsewhere.
Jens
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.
Loading...