Index: test/SemaCXX/warn-duplicate-enum.cpp
===================================================================
--- test/SemaCXX/warn-duplicate-enum.cpp	(revision 0)
+++ test/SemaCXX/warn-duplicate-enum.cpp	(revision 0)
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify -Wduplicate-enum
+enum M {
+  M1 = 0,  // expected-note {{element M1 declared here}}
+  M2 = -1,
+  M3,  // expected-warning {{element M3 has been implicitly assigned 0 which element M1 has been assigned}}
+  M4};
+
+enum N {
+  N1 = -1,  // expected-note {{element N1 declared here}}
+  N2,       // expected-note {{element N2 declared here}}
+  N3,
+  N4 = -2,
+  N5,  // expected-warning {{element N5 has been implicitly assigned -1 which element N1 has been assigned}}
+  N6   // expected-warning {{element N6 has been implicitly assigned 0 which element N2 has been assigned}}
+};
+
+enum { O1, O2 = -1, O3 }; // expected-warning{{element O3 has been implicitly assigned 0 which element O1 has been assigned}} \
+  // expected-note {{element O1 declared here}}
+
+enum P {
+  P1,
+  P2,
+  P3,  // expected-warning{{element P3 has been implicitly assigned 2 which element P5 has been assigned}}
+  P4 = P2,  // no warning
+  P5 = 2  // expected-note {{element P5 declared here}}
+};
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td	(revision 160463)
+++ include/clang/Basic/DiagnosticSemaKinds.td	(working copy)
@@ -26,6 +26,10 @@
 def note_identical_enum_values : Note<
   "initialize the last element with the previous element to silence "
   "this warning">;
+def warn_duplicate_enum_values : Warning<
+  "element %0 has been implicitly assigned %1 which element %2 has "
+  "been assigned">, InGroup<DiagGroup<"duplicate-enum">>, DefaultIgnore;
+def note_duplicate_element : Note<"element %0 declared here">;
 
 // Constant expressions
 def err_expr_not_ice : Error<
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp	(revision 160463)
+++ lib/Sema/SemaDecl.cpp	(working copy)
@@ -10485,6 +10485,85 @@
                                     Next->getName());
 }
 
+// Emits a warning when an element is implicitly set a value that
+// a previous element has already been set to.
+static void CheckForDuplicateEnumValues(Sema &S, Decl **Elements,
+                                        unsigned NumElements, EnumDecl *Enum,
+                                        QualType EnumType) {
+  if (S.Diags.getDiagnosticLevel(diag::warn_duplicate_enum_values,
+                                 Enum->getLocation()) ==
+      DiagnosticsEngine::Ignored)
+    return;
+
+  // Use to store the smallest APSInt size that can represent all the elements.
+  bool signedness = false;
+  unsigned bitwidth = 0;
+
+  // Skip diagnostic if previous error were found with the enum.
+  for (unsigned i = 0; i != NumElements; ++i) {
+    EnumConstantDecl *ECD = cast<EnumConstantDecl>(Elements[i]);
+    if (!ECD)
+      return;
+
+    const llvm::APSInt& Val = ECD->getInitVal();
+    if (!signedness && Val.isSigned()) {
+      signedness = true;
+     ++bitwidth;
+    }
+
+    unsigned ValWidth;
+    if (Val.isUnsigned())
+      ValWidth = Val.getActiveBits() + signedness;
+    else if (Val.isNonNegative())
+      ValWidth = Val.getActiveBits() + 1;
+    else
+      ValWidth = Val.getBitWidth() - Val.countLeadingOnes() + 1;
+
+    if (bitwidth < ValWidth)
+      bitwidth = ValWidth;
+  }
+
+  // Store a map of values to decls.  Values are extended to a common size
+  // first to for comparisons.
+  std::map<llvm::APSInt, EnumConstantDecl*> ValueMap;
+
+  for (unsigned i = 0; i != NumElements; ++i) {
+    EnumConstantDecl *ECD = cast<EnumConstantDecl>(Elements[i]);
+    if (!ECD->getInitExpr())
+      continue;
+
+    const llvm::APSInt &Val = ECD->getInitVal();
+    ValueMap.insert(std::make_pair(llvm::APSInt(Val.extOrTrunc(bitwidth),
+                                   signedness), ECD));
+  }
+
+  for (unsigned i = 0; i != NumElements; ++i) {
+    EnumConstantDecl *ECD = cast<EnumConstantDecl>(Elements[i]);
+    if (ECD->getInitExpr())
+      continue;
+
+    const llvm::APSInt &Val = ECD->getInitVal();
+    std::pair<std::map<llvm::APSInt, EnumConstantDecl*>::iterator, bool> Res;
+    Res = ValueMap.insert(std::make_pair(llvm::APSInt(Val.extOrTrunc(bitwidth),
+                                                      signedness),
+                                         ECD));
+    if (Res.second)
+      continue;
+
+    // Don't warn on: enum { A1, A2 = A1 };
+    if (Expr *E = Res.first->second->getInitExpr())
+      if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreImpCasts()))
+        if (DRE->getDecl() == ECD)
+          continue;
+
+    S.Diag(ECD->getLocation(), diag::warn_duplicate_enum_values)
+      << ECD->getName() << ECD->getInitVal().toString(10) 
+      << Res.first->second->getName() << ECD->getSourceRange();
+    S.Diag(Res.first->second->getLocation(), diag::note_duplicate_element)
+      << Res.first->second->getName();
+  }
+}
+
 void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,
                          SourceLocation RBraceLoc, Decl *EnumDeclX,
                          Decl **Elements, unsigned NumElements,
@@ -10709,6 +10788,7 @@
     DeclsInPrototypeScope.push_back(Enum);
 
   CheckForUniqueEnumValues(*this, Elements, NumElements, Enum, EnumType);
+  CheckForDuplicateEnumValues(*this, Elements, NumElements, Enum, EnumType);
 }
 
 Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr,
