diff options
author | John McCall <rjmccall@apple.com> | 2010-03-19 18:53:26 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-03-19 18:53:26 +0000 |
commit | a2936be04fb800d93a0a8d3358f35c7b3b2ded16 (patch) | |
tree | 0211be41c177480ba87adf88d0608bfa805a458f | |
parent | d4c60909ae7ad1ab603feedf04d457d72e85fbc4 (diff) |
Promote enum types during -Wsign-compare. Fixes some spurious warnings,
mostly during conditional expressions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98975 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 5 | ||||
-rw-r--r-- | test/SemaCXX/conditional-expr.cpp | 6 | ||||
-rw-r--r-- | test/SemaCXX/warn-sign-compare.cpp | 72 |
3 files changed, 80 insertions, 3 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 3fac79deba..522a7c1076 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2045,6 +2045,11 @@ void Sema::CheckSignCompare(Expr *lex, Expr *rex, SourceLocation OpLoc, if (!tmp.isNull()) rt = tmp; } + if (const EnumType *E = lt->getAs<EnumType>()) + lt = E->getDecl()->getPromotionType(); + if (const EnumType *E = rt->getAs<EnumType>()) + rt = E->getDecl()->getPromotionType(); + // The rule is that the signed operand becomes unsigned, so isolate the // signed operand. Expr *signedOperand = lex, *unsignedOperand = rex; diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp index 4fcb0bb98d..accc8db6c4 100644 --- a/test/SemaCXX/conditional-expr.cpp +++ b/test/SemaCXX/conditional-expr.cpp @@ -154,8 +154,8 @@ void test() i1 = i1 ? i1 : ir1; int *pi1 = i1 ? &i1 : 0; pi1 = i1 ? 0 : &i1; - i1 = i1 ? i1 : EVal; // expected-warning {{operands of ? are integers of different signs}} ?? - i1 = i1 ? EVal : i1; // expected-warning {{operands of ? are integers of different signs}} ?? + i1 = i1 ? i1 : EVal; + i1 = i1 ? EVal : i1; d1 = i1 ? 'c' : 4.0; d1 = i1 ? 4.0 : 'c'; Base *pb = i1 ? (Base*)0 : (Derived*)0; @@ -191,7 +191,7 @@ void test() test0 = test0 ? (short) 10 : test0; test0 = test0 ? EVal : test0; - test0 = test0 ? EVal : (int) test0; // expected-warning {{operands of ? are integers of different signs}} + test0 = test0 ? EVal : (int) test0; // Note the thing that this does not test: since DR446, various situations // *must* create a separate temporary copy of class objects. This can only diff --git a/test/SemaCXX/warn-sign-compare.cpp b/test/SemaCXX/warn-sign-compare.cpp new file mode 100644 index 0000000000..3042bfde6e --- /dev/null +++ b/test/SemaCXX/warn-sign-compare.cpp @@ -0,0 +1,72 @@ +// RUN: %clang_cc1 -verify -fsyntax-only -Wsign-compare %s + +// NOTE: When a 'enumeral mismatch' warning is implemented then expect several +// of the following cases to be impacted. + +// namespace for anonymous enums tests +namespace test1 { + enum { A }; + enum { B = -1 }; + + template <typename T> struct Foo { + enum { C }; + enum { D = ~0U }; + }; + + enum { E = ~0U }; + + void doit_anonymous( int i ) { + int a1 = 1 ? i : A; + int a2 = 1 ? A : i; + + int b1 = 1 ? i : B; + int b2 = 1 ? B : i; + + int c1 = 1 ? i : Foo<bool>::C; + int c2 = 1 ? Foo<bool>::C : i; + + int d1 = 1 ? i : Foo<bool>::D; // expected-warning {{operands of ? are integers of different signs}} + int d2 = 1 ? Foo<bool>::D : i; // expected-warning {{operands of ? are integers of different signs}} + int d3 = 1 ? B : Foo<bool>::D; // expected-warning {{operands of ? are integers of different signs}} + int d4 = 1 ? Foo<bool>::D : B; // expected-warning {{operands of ? are integers of different signs}} + + int e1 = 1 ? i : E; // expected-warning {{operands of ? are integers of different signs}} + int e2 = 1 ? E : i; // expected-warning {{operands of ? are integers of different signs}} + int e3 = 1 ? E : B; // expected-warning {{operands of ? are integers of different signs}} + int e4 = 1 ? B : E; // expected-warning {{operands of ? are integers of different signs}} + } +} + +// namespace for named enums tests +namespace test2 { + enum Named1 { A }; + enum Named2 { B = -1 }; + + template <typename T> struct Foo { + enum Named3 { C }; + enum Named4 { D = ~0U }; + }; + + enum Named5 { E = ~0U }; + + void doit_anonymous( int i ) { + int a1 = 1 ? i : A; + int a2 = 1 ? A : i; + + int b1 = 1 ? i : B; + int b2 = 1 ? B : i; + + int c1 = 1 ? i : Foo<bool>::C; + int c2 = 1 ? Foo<bool>::C : i; + + int d1 = 1 ? i : Foo<bool>::D; // expected-warning {{operands of ? are integers of different signs}} + int d2 = 1 ? Foo<bool>::D : i; // expected-warning {{operands of ? are integers of different signs}} + int d3 = 1 ? B : Foo<bool>::D; // expected-warning {{operands of ? are integers of different signs}} + int d4 = 1 ? Foo<bool>::D : B; // expected-warning {{operands of ? are integers of different signs}} + + int e1 = 1 ? i : E; // expected-warning {{operands of ? are integers of different signs}} + int e2 = 1 ? E : i; // expected-warning {{operands of ? are integers of different signs}} + int e3 = 1 ? E : B; // expected-warning {{operands of ? are integers of different signs}} + int e4 = 1 ? B : E; // expected-warning {{operands of ? are integers of different signs}} + } +} |