diff options
author | Richard Trieu <rtrieu@google.com> | 2012-05-30 01:01:11 +0000 |
---|---|---|
committer | Richard Trieu <rtrieu@google.com> | 2012-05-30 01:01:11 +0000 |
commit | 01cf09302d32cdedeb78e417c67bc57fc88821a7 (patch) | |
tree | b379d37041e6c82c2bb91002259e1505c6fc3803 | |
parent | 970c6f39da82626fcb54c0ca1deaab034ec96c12 (diff) | |
download | bcm5719-llvm-01cf09302d32cdedeb78e417c67bc57fc88821a7.tar.gz bcm5719-llvm-01cf09302d32cdedeb78e417c67bc57fc88821a7.zip |
Add new -Wunique-enum which will warn on enums which all elements have the
same value and were initialized with literals. Clang will warn on code like
this:
enum A {
FIRST = 1,
SECOND = 1
};
llvm-svn: 157666
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 43 | ||||
-rw-r--r-- | clang/test/Sema/switch.c | 2 | ||||
-rw-r--r-- | clang/test/SemaCXX/warn-unique-enum.cpp | 16 |
4 files changed, 64 insertions, 1 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 483145bb8a8..b62e3aefae1 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -20,6 +20,10 @@ def warn_variables_not_in_loop_body : Warning< "used in loop condition not modified in loop body">, InGroup<DiagGroup<"loop-analysis">>, DefaultIgnore; +def warn_identical_enum_values : Warning< + "all elements of %select{anonymous enum|%1}0 are initialized with literals " + "to value %2">, InGroup<DiagGroup<"unique-enum">>; + // Constant expressions def err_expr_not_ice : Error< "expression is not an %select{integer|integral}0 constant expression">; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 036907b6854..8f991c7fe13 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -10232,6 +10232,48 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, return New; } +// Emits a warning if every element in the enum is the same value and if +// every element is initialized with a integer or boolean literal. +static void CheckForUniqueEnumValues(Sema &S, Decl **Elements, + unsigned NumElements, EnumDecl *Enum, + QualType EnumType) { + if (S.Diags.getDiagnosticLevel(diag::warn_identical_enum_values, + Enum->getLocation()) == + DiagnosticsEngine::Ignored) + return; + + if (NumElements < 2) + return; + + llvm::APSInt FirstVal; + + for (unsigned i = 0; i != NumElements; ++i) { + EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Elements[i]); + if (!ECD) + return; + + Expr *InitExpr = ECD->getInitExpr(); + if (!InitExpr) + return; + InitExpr = InitExpr->IgnoreImpCasts(); + if (!isa<IntegerLiteral>(InitExpr) && !isa<CXXBoolLiteralExpr>(InitExpr)) + return; + + if (i == 0) { + FirstVal = ECD->getInitVal(); + continue; + } + + if (FirstVal != ECD->getInitVal()) + return; + } + + bool hasIdentifier = Enum->getIdentifier(); + S.Diag(Enum->getLocation(), diag::warn_identical_enum_values) + << hasIdentifier << EnumType << FirstVal.toString(10) + << Enum->getSourceRange(); +} + void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, SourceLocation RBraceLoc, Decl *EnumDeclX, Decl **Elements, unsigned NumElements, @@ -10455,6 +10497,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, if (InFunctionDeclarator) DeclsInPrototypeScope.push_back(Enum); + CheckForUniqueEnumValues(*this, Elements, NumElements, Enum, EnumType); } Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr, diff --git a/clang/test/Sema/switch.c b/clang/test/Sema/switch.c index 083ccb73904..e37d5da2592 100644 --- a/clang/test/Sema/switch.c +++ b/clang/test/Sema/switch.c @@ -326,7 +326,7 @@ void rdar110822110(Ints i) void test19(int i) { enum { kTest19Enum1 = 7, - kTest19Enum2 = 7 + kTest19Enum2 = kTest19Enum1 }; const int a = 3; switch (i) { diff --git a/clang/test/SemaCXX/warn-unique-enum.cpp b/clang/test/SemaCXX/warn-unique-enum.cpp new file mode 100644 index 00000000000..ddafc16aab5 --- /dev/null +++ b/clang/test/SemaCXX/warn-unique-enum.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 %s -fsyntax-only -verify -Wunique-enum +enum A { A1 = 1, A2 = 1, A3 = 1 }; // expected-warning {{all elements of 'A' are initialized with literals to value 1}} +enum { B1 = 1, B2 = 1, B3 = 1 }; // expected-warning {{all elements of anonymous enum are initialized with literals to value 1}} +enum C { C1 = true, C2 = true}; // expected-warning {{all elements of 'C' are initialized with literals to value 1}} +enum D { D1 = 5, D2 = 5L, D3 = 5UL, D4 = 5LL, D5 = 5ULL }; // expected-warning {{all elements of 'D' are initialized with literals to value 5}} + +// Don't warn on enums with less than 2 elements. +enum E { E1 = 4 }; +enum F { F1 }; +enum G {}; + +// Don't warn when integer literals do not initialize the elements. +enum H { H1 = 4, H_MAX = H1, H_MIN = H1 }; +enum I { I1 = H1, I2 = 4 }; +enum J { J1 = 4, J2 = I2 }; +enum K { K1, K2, K3, K4 }; |