Opened 11 months ago

Last modified 9 months ago

#203 new defect

Polymorphic Structure Initalization Errors

Reported by: ajbeach Owned by:
Priority: major Component: cfa-cc
Version: 1.0 Keywords:
Cc:

Description (last modified by mlbrooks)

So I am pretty sure there is more than one bug here, but I'm not entirely sure where the lines are. There are a few places nothing is found, a few times extra options are found. There are times initialization style matters and there are times it doesn't.

Just because it might be a problem I made it a bit easier to pick out each one.

// Can be changed here or on the command line.
#ifndef SHOW_ERROR
#define SHOW_ERROR 0
#endif

forall(dtype A)
struct empty {
    // Nothing.
};

forall(dtype B)
struct counter {
    int count;
};

forall(dtype C)
struct wrap_e {
    empty(C) field;
};

forall(dtype D)
struct wrap_c {
    counter(D) field;
};

forall(dtype E)
struct wrap_d {
    E * field;
};

forall(otype F)
struct wrap_o {
    F field;
};

forall(dtype G)
struct base_vtable {
    base_vtable(G) const * const parent;
};

forall(dtype H)
struct child_vtable {
    base_vtable(H) const * const parent;
};

empty(int) empty_obj = {};
empty(char) empty_obj = {};
counter(int) count_obj = {5};
counter(char) count_obj = {5};

base_vtable(int) base_vtable_instance @= { 0 };
base_vtable(char) base_vtable_instance @= { 0 };

#if SHOW_ERROR == 2
// No alternatives:
wrap_e(char) error_obj @= { empty_obj };

#elif SHOW_ERROR == 3
// GCC: initializer element is not constant
wrap_c(int) error_obj @= { count_obj };

#elif SHOW_ERROR == 4
// GCC: initializer element is not constant
wrap_c(char) error_obj @= { count_obj };

#elif SHOW_ERROR == 7
// Initalizer too deep:
wrap_e(bool) error_obj = { {} };

#elif SHOW_ERROR == 8
// Initalizer too deep:
wrap_c(bool) error_obj = { { 0 } };

#elif SHOW_ERROR == 9
// Assertion failure:
wrap_e(bool) error_obj @= { {} };

#endif

// Related things that do not produce errors.

int some_int = -7;
char some_char = 'c';

wrap_e(int) wrap_obj = { empty_obj };
wrap_c(int) wrap_obj = { count_obj };
wrap_d(int) wrap_obj = { &some_int };
wrap_d(char) wrap_obj @= { &some_char };
wrap_o(int) wrap_obj = { 13 };
wrap_o(char) wrap_obj @= { 'c' };

// related to SHOW_ERROR == 3
void local_case3() {
    // correctly picks preferred among 2 alternatives
    wrap_c(int) error_obj @= { count_obj };
}

// related to SHOW_ERROR == 4
void local_case4() {
    // correctly picks preferred among 2 alternatives
    wrap_c(char) error_obj @= { count_obj };
}

// formerely SHOW_ERROR == 5
// correctly picks preferred among 2 alternatives
child_vtable(int) child_vtable_instance = {
    &base_vtable_instance
};

// formerely SHOW_ERROR == 6
// correctly picks preferred among 2 alternatives
child_vtable(char) child_vtable_instance @= {
    &base_vtable_instance
};


int main(void) {
    wrap_e(int) wrap_obj = { empty_obj };
    wrap_c(int) wrap_obj = { count_obj };
    wrap_d(int) wrap_obj = { &some_int };
    wrap_d(char) wrap_obj @= { &some_char };
    wrap_o(int) wrap_obj = { 13 };
    wrap_o(char) wrap_obj @= { 'c' };

    {
        wrap_e(bool) alpha;
        wrap_e(bool) beta;
        beta = alpha;
        // alpha.field = beta.field; (See #166.)
        wrap_e(bool) delta = { beta };
    }
    {
        wrap_c(bool) alpha;
        wrap_c(bool) beta;
        beta = alpha;
        // alpha.field = beta.field; (See #166.)
        wrap_c(bool) delta = { beta };
    }

    return 0;
}

Change History (6)

comment:1 Changed 11 months ago by ajbeach

Description: modified (diff)

comment:2 Changed 11 months ago by ajbeach

Description: modified (diff)
Summary: Polymorphic Structure and Polymorphic Structure ErrorsPolymorphic Structure Initalization Errors

Some of the error cases may have actually been bad code. I removed them and renamed the ticket to hopefully describe the remaining cases better. I also included some more examples of code that do work because I dug up a few cases (copy constructor) that does work. Also I dug up a few more cases that are errors but are almost certainly other errors, maybe this ticket should be split up.

comment:3 Changed 11 months ago by ajbeach

Description: modified (diff)

One of the cases actually did work, removed the old first case.

comment:4 Changed 11 months ago by ajbeach

So #189 has been solved and that fixed 3-6, it might be time to pull out the remaining cases into new more descriptive tickets and close this one.

comment:5 Changed 11 months ago by f37yu

bug 2 is caused by this line of code in AggregateIterator::operator*:

		// CurrentObject.cc:298
		virtual std::list<InitAlternative> operator*() const {
			if (memberIter && *memberIter) { // if empty object, *memberIter is invalid
				std::list<InitAlternative> ret = memberIter->first();
				PRINT( std::cerr << "sub: " << sub << std::endl; )
				for ( InitAlternative & alt : ret ) {
					PRINT( std::cerr << "iterating and adding designators" << std::endl; )
					alt.designation->get_designators().push_front( new VariableExpr( strict_dynamic_cast< ObjectDecl * >( *curMember ) ) );
					// need to substitute for generic types, so that casts are to concrete types
					PRINT( std::cerr << "  type is: " << alt.type; )
					sub.apply( alt.type ); // also apply to designation??
					PRINT( std::cerr << " ==> " << alt.type << std::endl; )
				}
				return ret;
			}
			return std::list<InitAlternative>(); // <- here
		}

this causes an empty object to have no init alternatives in a non-constructed initializer expression (@= statement)
intuitively, this corner case should produce an "empty alternative" rather than no alternative. I'm not clear about how the alternatives are described, so I don't know what is the correct fix.

Last edited 11 months ago by f37yu (previous) (diff)

comment:6 Changed 9 months ago by mlbrooks

Description: modified (diff)

Modified the test program for accuracy with our compiler's current behaviour. Resolver behaviour that now works (since fix of #189) moved to section "Related things that do not produce errors," which removes error cases 4 and 5 and splits cases 3 and 4. Additionally, in cases 3 and 4, having the declaration in a function works (so that's now under "Related things that do not produce errors") while having the declaration be global does not work (so that's now shown with the now-reachable GCC error).

Note: See TracTickets for help on using tickets.