This is an archive of the discontinued LLVM Phabricator instance.

[Clang] Add note for bad conversion error when expression is of forward-declared type
ClosedPublic

Authored by zequanwu on Aug 5 2020, 6:48 PM.

Details

Summary

I think one note to speficify the forward declaretion location should be enough. Two notes might be too noisy.

Diff Detail

Event Timeline

zequanwu created this revision.Aug 5 2020, 6:48 PM
Herald added a project: Restricted Project. · View Herald TranscriptAug 5 2020, 6:48 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript
zequanwu requested review of this revision.Aug 5 2020, 6:48 PM
zequanwu retitled this revision from [Clang] Add note for bad conversion when expression is of forward-declared type to [Clang] Add note for bad conversion error when expression is of forward-declared type.Aug 5 2020, 6:48 PM
hans added a comment.Aug 6 2020, 4:34 AM

Thanks! This looks promising.

In addition to updating existing tests, it would be good to add a test aimed explicitly at this. Maybe you can reduce something from the example in the bug report. Maybe looking at git blame for emitBadConversionNotes() will provide hints for where existing tests for such notes were added.

clang/lib/Sema/SemaInit.cpp
8710

Can the reverse situation happen, where it's destType that's forward declared?

8713

Is the getDeclKind() still necessary even though you're doing getPointeeCXXRecordDecl() above and fromDecl is os type CXXRecordDecl*?

8714

I think we could add a new note instead of just note_forward_declaration which is more helpful, explaining that maybe the conversion would be valid if the type was defined and not just forward declared.

zequanwu added inline comments.Aug 6 2020, 2:24 PM
clang/lib/Sema/SemaInit.cpp
8710

If we only consider normal class without template, I think it's not necessary.
Here is an example of forward-declared destType.

class B{};
class A;
B *b;
A *a= b;

Even if A is defined as class A: public B{};, A *a = b is still not valid, initializing pointer to derived class with pointer to base class.

8713

Because I was thinking about excluding class template. getPointeeCXXRecordDecl() might return a ClassTemplateSpecializationDecl or ClassTemplatePartialSpecializationDecl.
For following example, it triggers the same error. Should the new note also be emitted for this case?

template<class C> class A{};
A<int> *a1;
A<char> *a2 = a1;

And the following code compiles:

template<class C> class A{};
template<> class A<char>{};
template<> class A<int> : public A<char>{};
A<int> *a1;
A<char> *a2 = a1;

This seems like the same error as normal class, could resolved by inheritance.

zequanwu added inline comments.Aug 6 2020, 2:28 PM
clang/lib/Sema/SemaInit.cpp
8710

The reverse situation could happen in class template.

template<class C> class A{};
template<class C> class B; // template<class C> class B : public A<C>{}; compiles
B<int> *b;
A<int> *a = b;
zequanwu updated this revision to Diff 283744.Aug 6 2020, 3:06 PM

Add new note and test case.
I think for the class template case, the new note might not be useful, since they might simply caused by mismatch of template arguments.

hans accepted this revision.Aug 7 2020, 10:35 AM

Looks great, thanks! I put a suggestion for different wording of the note, but I'll leave it up to you to decide.

clang/test/SemaCXX/pointer-forward-declared-class-conversion.cpp
5

Thanks, this is a much better message!

Instead of "forward declaration of class" it would be good to use the class name there, for example:

"'B1' is not defined, but forward declared here; conversion would be valid if it's derived from 'A1'"

Or something like that. Finding the right words is hard :)

This revision is now accepted and ready to land.Aug 7 2020, 10:35 AM
zequanwu updated this revision to Diff 283949.Aug 7 2020, 10:49 AM

Update diag note.

This revision was landed with ongoing or failed builds.Aug 7 2020, 11:06 AM
This revision was automatically updated to reflect the committed changes.
rsmith added a subscriber: rsmith.Sep 29 2021, 11:09 AM

Please see llvm.org/PR52014 -- this patch is not properly handling cv-qualifiers. We should not produce the new note if the destination type has qualifiers that the source type does not possess, because in that case inheritance makes no difference to whether the conversion is valid.

Please see llvm.org/PR52014 -- this patch is not properly handling cv-qualifiers. We should not produce the new note if the destination type has qualifiers that the source type does not possess, because in that case inheritance makes no difference to whether the conversion is valid.

Sent a patch to fix it: D110780