Topic: Definition of an incomplete object


Author: "Ivan A. Kosarev" <ik@unicals.com>
Date: Thu, 26 Mar 2009 21:43:46 CST
Raw View
Hi there,

C++03 3.9 #6 says that no object shall be defined to have an incomplete
type. In the same time 8.3.4 #3 states that the first expression in a
sequence of adjacent array declarators can be omitted if it is followed
by an initializer.

Now consider the code:

int a[] = { 0 };

By the rules described in 3.1 #2, the declaration is a definition. By
8.3.4 #3 it is a valid declaration as the "[]" array declarator is
followed by the initializer. However, at the point of declaration (that
is, just before processing of the initializer) the type of the object
"a" is incomplete.

If the wordings of the Standard mean the object shall first be declared
(and not defined) to have the incomplete type "int[]", then where is the
wording that describes the point when the name "a" turns from a declared
one to a defined one?

Otherwise, shall there be an exception written in 3.9 #6 that allows
objects to be defined (and not declared) to have an incomplete type in
such cases?

Thanks,

--

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Fri, 27 Mar 2009 15:24:30 CST
Raw View
xOn Mar 27, 4:43 am, "Ivan A. Kosarev" <i...@unicals.com> wrote:

> C++03 3.9 #6 says that no object shall be defined to have an
> incomplete type. In the same time 8.3.4 #3 states that the
> first expression in a sequence of adjacent array declarators
> can be omitted if it is followed by an initializer.

> Now consider the code:

> int a[] = { 0 };

> By the rules described in 3.1 #2, the declaration is a
> definition. By 8.3.4 #3 it is a valid declaration as the "[]"
> array declarator is followed by the initializer. However, at
> the point of declaration (that is, just before processing of
> the initializer) the type of the object "a" is incomplete.

This is a special case, of course.  The type being defined here
is int[1], which is a complete type.  Although the symbol is
visible immediately before the initializer, the definition
includes the initializer.

I is an interesting case.  Is something like the following
legal:

     template< std::size_t N >
     int f( int a[N] ) ;

     int a[] = { f( a ) } ;

If I'm not mistaken, the call to f, here, requires a complete
type.  (FWIW: both Sun CC and g++ reject it.)

> If the wordings of the Standard mean the object shall first be
> declared (and not defined) to have the incomplete type
> "int[]", then where is the wording that describes the point
> when the name "a" turns from a declared one to a defined one?

An object isn't "declared" or "defined".  A statement is a
declaration or a definition (or rather, only a declaration or
both a declaration and a definition).  A statement which is a
definition defines an object.

> Otherwise, shall there be an exception written in 3.9 #6 that
> allows objects to be defined (and not declared) to have an
> incomplete type in such cases?

I don't think that there's a problem, although perhaps a note to
the effect that in this case, the type is incomplete until the
end of the initializer wouldn't hurt.

--
James Kanze (GABI Software)             email:james.kanze@gmail.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kuyper <jameskuyper@verizon.net>
Date: Fri, 27 Mar 2009 15:39:40 CST
Raw View
Ivan A. Kosarev wrote:
> Hi there,
>
> C++03 3.9 #6 says that no object shall be defined to have an incomplete
> type. In the same time 8.3.4 #3 states that the first expression in a
> sequence of adjacent array declarators can be omitted if it is followed
> by an initializer.
>
> Now consider the code:
>
> int a[] = { 0 };
>
> By the rules described in 3.1 #2, the declaration is a definition. By
> 8.3.4 #3 it is a valid declaration as the "[]" array declarator is
> followed by the initializer. However, at the point of declaration (that
> is, just before processing of the initializer) the type of the object
> "a" is incomplete.
>
> If the wordings of the Standard mean the object shall first be declared
> (and not defined) to have the incomplete type "int[]",  then where is the
> wording that describes the point when the name "a" turns from a declared
> one to a defined one?

The point of declaration (3.3.1p1) starts at the end of the declarator,
before the initializer, and that is were the scope of the declared
identifier starts. However, that is not the point were the declaration ends.

Your declaration is an example of Section 7p1:
> simple-declaration:
>  decl-specifier-seqopt init-declarator-listopt ;

An init-declarator, as the name implies, includes both the declarator
and the initializer (8p1):
> init-declarator:
>  declarator initializerop

Therefore, a simple declaration doesn't stop at the point of
declaration, it continues all the way over to the terminating ';',
including the initializer along the way. Therefore, 'a' is neither
declared nor defined (per 3.1p2, which you've already cited), until
after the end of the initializer.

The identifier 'a' can be used at any point after the declarator, since
it's scope has started, but if used before the end of the initializer it
still has an incomplete type, and therefore cannot be used in any
fashion that requires a complete type (such as "sizeof a"). By the end
of the definition, the length of the array is known, and 'a' therefore
no longer has an incomplete type, so the definition does not violate 3.9p6.

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Bart van Ingen Schenau <bart@ingen.ddns.info>
Date: Sat, 28 Mar 2009 23:24:41 CST
Raw View
Ivan A. Kosarev wrote:

> Hi there,
>
> C++03 3.9 #6 says that no object shall be defined to have an
> incomplete type. In the same time 8.3.4 #3 states that the first
> expression in a sequence of adjacent array declarators can be omitted
> if it is followed by an initializer.
>
> Now consider the code:
>
> int a[] = { 0 };
>
> By the rules described in 3.1 #2, the declaration is a definition. By
> 8.3.4 #3 it is a valid declaration as the "[]" array declarator is
> followed by the initializer. However, at the point of declaration
> (that is, just before processing of the initializer) the type of the
> object "a" is incomplete.

No. The object a in your example has the type 'array of 1 int',
according to clause 8.3.4/3, last sentence.
That clause leaves no wiggle-room that the type might be incomplete. At
worst, it requires the compiler to perform a pre-scan of the
initialisation list to determine the number of elements.

>
> If the wordings of the Standard mean the object shall first be
> declared (and not defined) to have the incomplete type "int[]", then
> where is the wording that describes the point when the name "a" turns
> from a declared one to a defined one?
>
> Otherwise, shall there be an exception written in 3.9 #6 that allows
> objects to be defined (and not declared) to have an incomplete type in
> such cases?

Neither of these is needed, because the type of the object is never
incomplete.

>
> Thanks,
>
Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://c-faq.com/
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Ivan A. Kosarev" <ik@unicals.com>
Date: Sun, 29 Mar 2009 00:18:13 CST
Raw View
James Kanze wrote:
> I don't think that there's a problem, although perhaps a note to
> the effect that in this case, the type is incomplete until the
> end of the initializer wouldn't hurt.

Not a great problem indeed. However, keeping the Standard wordings in
consistency helps express the intentions implied.

--

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Ivan A. Kosarev" <ik@unicals.com>
Date: Sun, 29 Mar 2009 00:17:17 CST
Raw View
James Kuyper wrote:
> Therefore, a simple declaration doesn't stop at the point of
> declaration, it continues all the way over to the terminating ';',
> including the initializer along the way. Therefore, 'a' is neither
> declared nor defined (per 3.1p2, which you've already cited), until
> after the end of the initializer.

The point that "a" is not declared (nor defined) before the initializer
is completely processed contradicts 3.3.1 #1 and numerous examples in
the Standard.

> The identifier 'a' can be used at any point after the declarator, since
> it's scope has started, but if used before the end of the initializer it
> still has an incomplete type, and therefore cannot be used in any
> fashion that requires a complete type (such as "sizeof a"). By the end

For any name to be of a complete or incomplete type it shall first be
declared or defined what contradicts your words above.

> of the definition, the length of the array is known, and 'a' therefore
> no longer has an incomplete type, so the definition does not violate 3.9p6.

It's not about types. I would like to know whether the name "a" is
declared or defined at the point of its declaration.

--

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Ivan A. Kosarev" <ik@unicals.com>
Date: Sun, 29 Mar 2009 15:50:56 CST
Raw View
Bart van Ingen Schenau wrote:
> No. The object a in your example has the type 'array of 1 int',
> according to clause 8.3.4/3, last sentence.
> That clause leaves no wiggle-room that the type might be incomplete. At
> worst, it requires the compiler to perform a pre-scan of the
> initialisation list to determine the number of elements.

3.9 #7 allows an array to be first declared to be of an unknown bound
and then be completed at some other point. It's not clear if the wording
applies to the case we discuss (primarily because these are the only
words the Standard spare to the "completing redeclarations").

In either case, from the spectrum of opinions I can only conclude that
this matter needs a clarification.

--

[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kuyper <jameskuyper@verizon.net>
Date: Sun, 29 Mar 2009 17:41:41 CST
Raw View
Ivan A. Kosarev wrote:
>
> James Kuyper wrote:
>>
>> Therefore, a simple declaration doesn't stop at the point of
>> declaration, it continues all the way over to the terminating ';',
>> including the initializer along the way. Therefore, 'a' is neither
>> declared nor defined (per 3.1p2, which you've already cited), until
>> after the end of the initializer.
>
> The point that "a" is not declared (nor defined) before the initializer
> is completely processed contradicts 3.3.1 #1 and numerous examples in
> the Standard.

No, there's no contradiction with 3.3.1 #1. The "point of declaration"
described by 3.3.1p1 is the point at which the scope of the identifier
starts. It does not mark completion of the declaration; that's
determined by the grammar, not by 3.3.1p1.

>> The identifier 'a' can be used at any point after the declarator, since
>> it's scope has started, but if used before the end of the initializer it
>> still has an incomplete type, and therefore cannot be used in any
>> fashion that requires a complete type (such as "sizeof a"). By the end
>
> For any name to be of a complete or incomplete type it shall first be
> declared or defined what contradicts your words above.

3.9p5: "... an array of unknown size ... is an incompletely-defined
type ....". At the point of declaration, the size of the array 'a' is
not yet know, so it is an incompletely-defined type.

3.9p6: "The declared type of an array object might be an array of
unknown size and therefore be incomplete at one point in a translation
unit and complete later on; the array types at those two points
(   array of unknown bound of T    and    array of N T   ) are different
types."

>> of the definition, the length of the array is known, and 'a' therefore
>> no longer has an incomplete type, so the definition does not violate 3.9p6.
>
> It's not about types. I would like to know whether the name "a" is
> declared or defined at the point of its declaration.

It can be incompletely declared at the point of declaration; your code
provides an example of how this can be the case. At the point of
declaration no initializers have yet been processed, nor has the
absence of an initializers been identified, so it cannot be a
definition yet.


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Sun, 29 Mar 2009 18:08:29 CST
Raw View
On Mar 29, 8:17 am, "Ivan A. Kosarev" <i...@unicals.com> wrote:
> James Kuyper wrote:
> > Therefore, a simple declaration doesn't stop at the point of
> > declaration, it continues all the way over to the
> > terminating ';', including the initializer along the way.
> > Therefore, 'a' is neither declared nor defined (per 3.1p2,
> > which you've already cited), until after the end of the
> > initializer.

> The point that "a" is not declared (nor defined) before the
> initializer is completely processed contradicts 3.3.1 #1 and
> numerous examples in the Standard.

You're confusing two different things.  The symbol "a" is
declared at the end of the declarator (before the
initialization).  The declaration, however, is only complete at
the end of the init-declarator, and if the declaration is also a
definition, the "object" isn't defined until the end of the
init-declarator.

This is vaguely like the case of a function definition; the name
of the function is declared at the end of the declarator, and is
visible in the function try block, the constructor initializers
and the function body (so the function can be called
recursively).  The function isn't defined, however, until the
last closing brace of the function body or the function try
block.

> > The identifier 'a' can be used at any point after the
> > declarator, since it's scope has started, but if used before
> > the end of the initializer it still has an incomplete type,
> > and therefore cannot be used in any fashion that requires a
> > complete type (such as "sizeof a"). By the end

> For any name to be of a complete or incomplete type it shall
> first be declared or defined what contradicts your words
> above.

No.  The standard is very clear about this:    3.3.1/1: "The point
of declaration for a name is immediately after its complete
declarator (clause 8) and before its initializer (if any),
except as noted below."  In other words, before the end of the
declaration (which includes initialization).  The standard
doesn't speak of a "point of definition", because in many ways,
it's irrelevant.  An object with a non-trivial constructor
doesn't exist, however, before it has been initialized, so you
can't really speak of the "definition" of an object before the
initializers are known.  (More generally, objects don't exist
until the program executed.)

> > of the definition, the length of the array is known, and 'a'
> > therefore no longer has an incomplete type, so the
> > definition does not violate 3.9p6.

> It's not about types. I would like to know whether the name
> "a" is declared or defined at the point of its declaration.

The name is declared at the point of declaration, i.e. at the
end of the declarator.  A name is never defined (in the sense I
think you mean---in a very real sense, the name is defined as
soon as it is declared).  And an object is only defined at
run-time.

--
James Kanze (GABI Software)             email:james.kanze@gmail.com
Conseils en informatique orient   e objet/
                  Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Ivan A. Kosarev" <ik@unicals.com>
Date: Mon, 30 Mar 2009 18:39:24 CST
Raw View
James Kanze wrote:
> On Mar 29, 8:17 am, "Ivan A. Kosarev" <i...@unicals.com> wrote:
>> James Kuyper wrote:
>>> Therefore, 'a' is neither declared nor defined (per 3.1p2,
>>> which you've already cited), until after the end of the
>>> initializer.
>
>> The point that "a" is not declared (nor defined) before the
>> initializer is completely processed contradicts 3.3.1 #1 and
>> numerous examples in the Standard.
>
> You're confusing two different things.  The symbol "a" is
> declared at the end of the declarator (before the
> initialization).  The declaration, however, is only complete at
> the end of the init-declarator, and if the declaration is also a
> definition, the "object" isn't defined until the end of the
> init-declarator.

This is one of the possible interpretations I described in the initial
message. The only problem with this one is that there is only one point
of declaration per a declaration and there are no points of definitions
other than points of declarations so I asked where is the verse in the
Standard that says that the declared object becomes a defined one.

> This is vaguely like the case of a function definition; the name
> of the function is declared at the end of the declarator, and is
> visible in the function try block, the constructor initializers

Not true, sorry. In presence of a body of a function the name of the
function is defined at the point of declaration; see 3.1 #2.

There is no need to declare the name and then turn it to a defined one.

>> For any name to be of a complete or incomplete type it shall
>> first be declared or defined what contradicts your words
>> above.
>
> No.  The standard is very clear about this:    3.3.1/1: "The point
> of declaration for a name is immediately after its complete
> declarator (clause 8) and before its initializer (if any),
> except as noted below."  In other words, before the end of the
> declaration (which includes initialization).  The standard
> doesn't speak of a "point of definition", because in many ways,
> it's irrelevant.  An object with a non-trivial constructor
> doesn't exist, however, before it has been initialized, so you
> can't really speak of the "definition" of an object before the
> initializers are known.  (More generally, objects don't exist
> until the program executed.)

I'm not sure I follow. If the name "a" is declared before the
initializer is processed (as you wrote above), then why to invent the
names that are not declared though visible in their scopes?

> The name is declared at the point of declaration, i.e. at the
> end of the declarator.  A name is never defined (in the sense I
> think you mean---in a very real sense, the name is defined as
> soon as it is declared).  And an object is only defined at
> run-time.

It's all about names which are compile-time things.

--


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Ivan A. Kosarev" <ik@unicals.com>
Date: Mon, 30 Mar 2009 18:33:26 CST
Raw View
James Kuyper wrote:
> Ivan A. Kosarev wrote:
>>
>>> including the initializer along the way. Therefore, 'a' is neither
>>> declared nor defined (per 3.1p2, which you've already cited), until
>>> after the end of the initializer.
>>
>> The point that "a" is not declared (nor defined) before the initializer
>> is completely processed contradicts 3.3.1 #1 and numerous examples in
>> the Standard.
>
> No, there's no contradiction with 3.3.1 #1. The "point of declaration"
> described by 3.3.1p1 is the point at which the scope of the identifier
> starts. It does not mark completion of the declaration; that's
> determined by the grammar, not by 3.3.1p1.

This interpretation is okay except that there is no a concept of
introduced but not declared name exist. There are no "names introduced
to have a type" nor "names introduced to have a linkage".

Say, 3.4.1 #4 reads:

"A name used in global scope, outside of any function, class or
user-declared namespace, shall be declared before its use in global scope."

Given a name is not declared until associated initializer is completely
processed, the following code, which is a well-known well-formed
declaration, violates the sentence cited.

void *v = &v;

Also, the term "point of declaration" seem to be about the point where a
given name declares and not just becomes visible in a scope. The word
"declaration" obviously has a non-grammar sense here.

>>> The identifier 'a' can be used at any point after the declarator, since
>>> it's scope has started, but if used before the end of the initializer it
>>> still has an incomplete type, and therefore cannot be used in any
>>> fashion that requires a complete type (such as "sizeof a"). By the end
>>
>> For any name to be of a complete or incomplete type it shall first be
>> declared or defined what contradicts your words above.
>
> 3.9p5: "... an array of unknown size ... is an incompletely-defined
> type ....". At the point of declaration, the size of the array 'a' is
> not yet know, so it is an incompletely-defined type.

BTW, as Bart van Ingen Schenau noted, it is technically possible to know
the size of the array at the point of declaration.

> 3.9p6: "The declared type of an array object might be an array of
> unknown size and therefore be incomplete at one point in a translation
> unit and complete later on; the array types at those two points
> (?array of unknown bound of T? and ?array of N T?) are different
> types."

Again, for the name "a" to be suitable for this statement, it shall
first be declared to have an array type of unknown bound.

>> It's not about types. I would like to know whether the name "a" is
>> declared or defined at the point of its declaration.
>
> It can be incompletely declared at the point of declaration; your code
> provides an example of how this can be the case. At the point of
> declaration no initializers have yet been processed, nor has the
> absence of an initializers been identified, so it cannot be a
> definition yet.

The incompletely defined objects look like yet another concept the
Standard says nothing about.

Also, why do you think that at point of declaration it's not known if
the initializer present? Even if to consider this matter purely
technically, we have to know that the token that follows the complete
declarator does not begin a function or array declarator. Given the
token is "=", we know that there is an initializer follows.

And even if it would really be hard to determine if an initializer is
specified, that wouldn't be an argument in whatever related to
interpretation of the Standard.

--


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Andy V <vesper.spamonly.andy53@gmail.com>
Date: Tue, 31 Mar 2009 15:35:12 CST
Raw View
What about:

#include <typeinfo>
const char * arr[] =
{
 typeid (arr).name(),
 typeid (arr[0]).name()
};

What does the standard say about the values in arr[0] and arr[1]?

VC8 says:

arr[0] : char const * [0]
arr[1] : char const *

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]