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
8617

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

Rakete1111 added inline comments.
lib/Sema/SemaChecking.cpp
8615

Please drop the braces.

8617

You missed a dot at the end.

8666

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

8713

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
2

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

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

8186

Can use const auto * here.

8188

Here as well.

8189

For enum types in C++,

8592

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

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.

8592

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.

8617

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
2

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
8186

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.

8592

Okay, that comment adds sufficient clarity for me.

8593

when -> When

8619

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

lebedev.ri marked an inline comment as done.

Address review notes.

lib/Sema/SemaChecking.cpp
8619

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

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.