summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Trieu <rtrieu@google.com>2012-05-30 01:01:11 +0000
committerRichard Trieu <rtrieu@google.com>2012-05-30 01:01:11 +0000
commit01cf09302d32cdedeb78e417c67bc57fc88821a7 (patch)
treeb379d37041e6c82c2bb91002259e1505c6fc3803
parent970c6f39da82626fcb54c0ca1deaab034ec96c12 (diff)
downloadbcm5719-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.td4
-rw-r--r--clang/lib/Sema/SemaDecl.cpp43
-rw-r--r--clang/test/Sema/switch.c2
-rw-r--r--clang/test/SemaCXX/warn-unique-enum.cpp16
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 };
OpenPOWER on IntegriCloud