This is an archive of the discontinued LLVM Phabricator instance.

[Sema] Fixes for enum handling for tautological comparison diagnostics
ClosedPublic

Authored by lebedev.ri on Oct 20 2017, 6:32 AM.

Details

Summary

As Mattias Eriksson has reported in PR35009, in C, for enums, the underlying type should
be used when checking for the tautological comparison, unlike C++, where the enumerator
values define the value range. So if not in CPlusPlus mode, use the enum underlying type.

Also, i have discovered a problem (a crash) when evaluating tautological-ness of the following comparison:

enum A { A_a = 0 };
if (a < 0) // expected-warning {{comparison of unsigned enum expression < 0 is always false}}
return 0;

This affects both the C and C++, but after the first fix, only C++ code was affected.
That was also fixed, while preserving (i think?) the proper diagnostic output.

And while there, attempt to enhance the test coverage.
Yes, some tests got moved around, sorry about that :)

Fixes PR35009

Diff Detail

Repository
rL LLVM

Event Timeline

lebedev.ri created this revision.Oct 20 2017, 6:32 AM
efriedma added inline comments.
lib/Sema/SemaChecking.cpp
8612 ↗(On Diff #119653)

Why are you changing this here, as opposed to changing IntRange::forValueOfCanonicalType?

Rakete1111 added inline comments.
lib/Sema/SemaChecking.cpp
8610 ↗(On Diff #119653)

Please drop the braces.

8616 ↗(On Diff #119653)

You missed a dot at the end.

8665 ↗(On Diff #119653)

You can define Result lower down (and make it const).

8713 ↗(On Diff #119653)

Same as before. Also, shouldn't this be a function instead of duplicating the same code two times?

test/Sema/outof-range-enum-constant-compare.c
1 ↗(On Diff #119653)

I don't know what the convention is, but I would prefer to use platform independent tests wherever possible. I couldn't find a flag to change the underlying type of an enum, so I'm not sure if my suggestion is even feasible.

lebedev.ri marked 5 inline comments as done.

Addressed review notes.

For C++, enum handling clearly needs more work, because not all tautological comparisons are actually diagnosed,
so there is no clang/test/Sema/outof-range-enum-constant-compare.cpp, clang/test/Sema/tautological-constant-enum-compare.cpp for this very reason.

aaron.ballman added inline comments.Oct 21 2017, 5:37 AM
lib/Sema/SemaChecking.cpp
8185 ↗(On Diff #119705)

For enum types in C code, use the underlying datatype.

8186 ↗(On Diff #119705)

Can use const auto * here.

8188 ↗(On Diff #119705)

Here as well.

8189 ↗(On Diff #119705)

For enum types in C++,

8593 ↗(On Diff #119705)

Both is not very descriptive -- I think Zero might be an improvement.

lebedev.ri marked 2 inline comments as done.

Address review notes.

lib/Sema/SemaChecking.cpp
8186 ↗(On Diff #119705)

I do agree that as per coding style, that is preferred but the rest of the class would still use the
explicitly-spelled types, and IMO not deviating from local coding style in small changes might be best?

(clang-tidy does not complain about this, but maybe that is because it is not aware of this LLVM internal type casting functions)

But if you insist i will change it.

8593 ↗(On Diff #119705)

But then it will be confusing what is the difference between Zero and Min for unsigned types.
I think i should just clarify the comment here.

8612 ↗(On Diff #119653)

No particular reason. Initially i had trouble with moving it into IntRange::forValueOfCanonicalType(),
so i left that in the state that you saw. Now done.

test/Sema/outof-range-enum-constant-compare.c
1 ↗(On Diff #119653)

https://reviews.llvm.org/D38101?id=118143#inline-338796
That is exactly the flag to change the underlying type of an enum.
I believe the RUN lines are correct here.

aaron.ballman added inline comments.Oct 21 2017, 8:19 AM
lib/Sema/SemaChecking.cpp
8593 ↗(On Diff #119757)

when -> When

8619 ↗(On Diff #119757)

Instead of default constructing the Optional, you should use llvm::None instead.

8186 ↗(On Diff #119705)

Consistency is best, so you might as well leave it. A follow-up NFC commit would be fine if you wanted to switch everything to auto.

8593 ↗(On Diff #119705)

Okay, that comment adds sufficient clarity for me.

lebedev.ri marked an inline comment as done.

Address review notes.

lib/Sema/SemaChecking.cpp
8619 ↗(On Diff #119757)

Thank you for the suggestion, i did not really know about llvm::None.
However only the last return can be enhanced:

clang/lib/Sema/SemaChecking.cpp:8619:23: error: incompatible operand types ('(anonymous namespace)::LimitType' and 'llvm::NoneType')
    return Value == 0 ? LimitType::Both : llvm::None;
                      ^ ~~~~~~~~~~~~~~~   ~~~~~~~~~~
aaron.ballman accepted this revision.Oct 21 2017, 9:28 AM

LGTM!

lib/Sema/SemaChecking.cpp
8619 ↗(On Diff #119757)

Blech, that's because there's no common type for the :? operator. I think it'd be worse to split this into multiple statements just to use llvm::None, so it's fine as-is.

This revision is now accepted and ready to land.Oct 21 2017, 9:28 AM
This revision was automatically updated to reflect the committed changes.