Bugs 2746 and 3261

These are complete show-stoppers for us. Is there any hope
they may be fixed soon? Are there workarounds (even dirty
ones) we might use so as to proceed with our work?
Many thanks,

    Roberto

PR2746 shouldn't be too hard to implement, it's just that nobody has
gotten around to it yet. It's just a matter of fixing the cast code
in Sema to implement additional rules when the destination type is a
union, and subsequently fixing CodeGen to know how to deal with it.

For PR3261, I'm not sure, but you might be able to pull some tricks
with location information.

-Eli

Eli Friedman wrote:

These are complete show-stoppers for us. Is there any hope
they may be fixed soon? Are there workarounds (even dirty
ones) we might use so as to proceed with our work?
Many thanks,

PR2746 shouldn't be too hard to implement, it's just that nobody has
gotten around to it yet. It's just a matter of fixing the cast code
in Sema to implement additional rules when the destination type is a
union, and subsequently fixing CodeGen to know how to deal with it.

Hi Eli,

thanks for your message. We do not use CodeGen, so perhaps all we need
is to convince Sema (on our local copy) not to reject the code.
Can you please give us instructions on how to achieve that?

For PR3261, I'm not sure, but you might be able to pull some tricks
with location information.

Paolo, can you please look at that?
Thanks,

    Roberto

The relevant code is in Sema::CheckCastTypes. At a minimum, you can
add a check like "if (castType->isUnionType()) return false;"; that
should let through the code in question with very little work. The
proper solution involves checking the legality of the cast; that
requires some code to check whether the union has a member which is
compatible with the type of the input expression.

-Eli

I am not sure that Eli meant, types do not have location information (at
least in the form of SourceLocation).

So when I am visiting a enum or struct type and I use getDecl(), I can get
the source location from the declaration, but I can't know if the source
point is where I am or not.

Am I wrong?

pb

Eli Friedman wrote:

Eli Friedman wrote:

These are complete show-stoppers for us. Is there any hope
they may be fixed soon? Are there workarounds (even dirty
ones) we might use so as to proceed with our work?
Many thanks,

PR2746 shouldn't be too hard to implement, it's just that nobody has
gotten around to it yet. It's just a matter of fixing the cast code
in Sema to implement additional rules when the destination type is a
union, and subsequently fixing CodeGen to know how to deal with it.

Hi Eli,

thanks for your message. We do not use CodeGen, so perhaps all we need
is to convince Sema (on our local copy) not to reject the code.
Can you please give us instructions on how to achieve that?

The relevant code is in Sema::CheckCastTypes. At a minimum, you can
add a check like "if (castType->isUnionType()) return false;"; that
should let through the code in question with very little work. The
proper solution involves checking the legality of the cast; that
requires some code to check whether the union has a member which is
compatible with the type of the input expression.

Hi Eli,

why should we restrict to unions? For instance, the following
testcase is a simplified one coming from vstfpd-0.9.2:

struct S {
    int one;
    int two;
};

struct S const foo(void) ;

struct S tmp ;

void priv_sock_init() {
   tmp = (struct S) foo();
}

All the best,

    Roberto

13 jan 2009 kl. 08.30 skrev Roberto Bagnara:

Hi Eli,

why should we restrict to unions? For instance, the following
testcase is a simplified one coming from vstfpd-0.9.2:

struct S {
   int one;
   int two;
};

struct S const foo(void) ;

struct S tmp ;

void priv_sock_init() {
  tmp = (struct S) foo();
}

All the best,

   Roberto

Hi Roberto,

I think the fix for the above test would be something like

Index: lib/Sema/SemaExpr.cpp

Yep, that'll do it. Please go ahead and commit.

  - Doug

No, but a type doesn't exist by itself; there should be an associated
declaration or expression you can get the current source location
from.

-Eli

Let's see a simple but evocative example.
I have the clang AST of this code segment.

Using the function that overrides
HandleTranslationUnit(clang::TranslationUnit&)
I want to pretty print:

Here the code:
struct B;

struct A {
struct B* b;
};

struct B {
struct A* a;
};

Okay, so at this point, all types are defined, so isDefinition()
returns true, so you can't figure out whether it was defined at a
certain point.

The tree has three RecordDecl, visiting the first and pretty printing is easy.
But when I am in the second, isDefinition() returns true and I loop in the
field declarations; for each I get field name, if it is a bitfield and
eventually the related expression and a type.
The type is struct B (pointer a part), even if I recall the SourceLocation of
the FieldDecl (or the including RecordDecl) while visiting the type, how can I
know that the declaration is not actually there?

The approach I was thinking of is something like the following:
suppose you're trying to pretty-print the "struct B* b;" bit. Let S
designate the location immediately before the keyword "struct", let E
designate the location immediately after the semicolon, and let D
designate the beginning of the definition of struct B. We can
conclude that "struct B* b;" doesn't contain the definition of B by
looking at the locations: D is after E, so the field declaration
cannot contain the definition. Similar reasoning applies for "struct
A* a;"; let S to E be the field declaration, and let D be the
beginning of the definition of struct A. D is before S, so the field
declaration doesn't contain the definition.

Unfortunately, though, there isn't any easy way to compare source
locations like that; it should be possible, I think, but I don't know
the details of how to write it. Also, I'm not sure if you can get the
relevant source locations easily, particularly S. I think ongoing
work with DeclGroups will help here eventually, but I'm not sure of
the details.

There is another possible approach: take the location of the beginning
of the first declarator in the declaration (the "*b" bit), and scan
backwards through the source code to see if you find a "}" before the
first occurrence of the "struct" keyword. It's quite messy in terms
of layering, and I'm not sure how preprocessor stuff would factor into
it, but I think it's feasible. I don't know the details here either,
but I remember reading that the ObjC rewriter does some similar stuff.

I'm putting cfe-dev back onto the CC list so that people more familiar
with this stuff can comment; this is really outside the stuff I've
really tried.

-Eli

> Let's see a simple but evocative example.
> I have the clang AST of this code segment.
>
> Using the function that overrides
> HandleTranslationUnit(clang::TranslationUnit&)
> I want to pretty print:
>
> Here the code:
> struct B;
>
> struct A {
> struct B* b;
> };

The approach I was thinking of is something like the following:
suppose you're trying to pretty-print the "struct B* b;" bit. Let S
designate the location immediately before the keyword "struct", let E
designate the location immediately after the semicolon, and let D
designate the beginning of the definition of struct B.

But declaration have only one program point, I can't have both the position of
`struct' and of `;' in the line `struct B* b;'

It might work if I could have both...

Maybe FieldDecl and TypedefDecl should have isDefinition() like function too?
So we could distinguish easily if the type inside is defined there or not.

Unfortunately, though, there isn't any easy way to compare source
locations like that; it should be possible, I think, but I don't know
the details of how to write it. Also, I'm not sure if you can get the
relevant source locations easily, particularly S. I think ongoing
work with DeclGroups will help here eventually, but I'm not sure of
the details.

Since SourceLocation contains both line and column it would be easy to
implement an order. It is still a problem for tokens where isValid() or
isFileID()) are false, but maybe it is not possible in this context.

There is another possible approach: take the location of the beginning
of the first declarator in the declaration (the "*b" bit), and scan
backwards through the source code to see if you find a "}" before the
first occurrence of the "struct" keyword. It's quite messy in terms
of layering, and I'm not sure how preprocessor stuff would factor into
it, but I think it's feasible. I don't know the details here either,
but I remember reading that the ObjC rewriter does some similar stuff.

This is indeed a problem to implement at AST level.

I'm putting cfe-dev back onto the CC list so that people more familiar
with this stuff can comment; this is really outside the stuff I've
really tried.

-Eli

Thanks!
pb