[PATCH] D90555: [clangd] Handle duplicate enum constants in PopulateSwitch tweak

Sam McCall via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Nov 6 05:30:32 PST 2020


sammccall added a comment.

Thanks!
This makes sense to me, I assumed at first that the expr could be something complicated that we'd have to const-evaluate, thought clearly this already happens (and we do assume it's a ConstantExpr).



================
Comment at: clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp:115
 
-  // We trigger if there are fewer cases than enum values (and no case covers
-  // multiple values). This guarantees we'll have at least one case to insert.
----------------
It would still be nice to keep a high-level comment about the strategy.
(Not *this* comment of course, as this patch changes the strategy!)


================
Comment at: clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp:117
 
-  // We trigger if there are fewer cases than enum values (and no case covers
-  // multiple values). This guarantees we'll have at least one case to insert.
-  // We don't yet determine what the cases are, as that means evaluating
-  // expressions.
-  auto I = EnumD->enumerator_begin();
-  auto E = EnumD->enumerator_end();
+  // Special case of the empty enum
+  if (EnumD->enumerator_begin() == EnumD->enumerator_end())
----------------
why is the special case needed?


================
Comment at: clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp:126
+
+  llvm::SmallMapVector<llvm::APSInt, bool, 32> EnumConstants;
+  for (auto *EnumConstant : EnumD->enumerators()) {
----------------
It looks as if we're now doing (via prepare + apply combined):

1. Collect all constants into a `SmallMapVector<APSInt,bool>`.
2. Iterate over cases, marking covered constants
3. Prepare returns true if there are unmarked constants
4. Collect all cases into a `SmallSet<APSInt>`
5. Iterate over the constants, inserting text for those not in the set.

This seems equivalent, but less redundant:
1. Collect all constants into a `MapVector<APSInt, EnumConstantDecl*>` (e.g. `MissingEnumerators`)
2. Iterate over cases, deleting covered constants
3. Prepare returns true if any constant remains
4. Iterate over the map, inserting text for every element in the map


================
Comment at: clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp:141
     const CaseStmt *CS = cast<CaseStmt>(CaseList);
     // Case statement covers multiple values, so just counting doesn't work.
     if (CS->caseStmtIsGNURange())
----------------
this comment no longer holds (we're not counting anymore).

Could just say // GNU range cases are rare, we don't support them


================
Comment at: clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp:151
+
+    if (CE->getResultStorageKind() != ConstantExpr::RSK_Int64)
+      return false;
----------------
why can we not hit the APValue case?


================
Comment at: clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp:191
   for (EnumConstantDecl *Enumerator : EnumD->enumerators()) {
-    if (ExistingEnumerators.contains(Enumerator->getInitVal()))
+    // Try to insert this Enumerator into the set. If this fails, the value was
+    // either already there to begin with or we have already added it using a
----------------
Maybe just "Skip if value already covered (possibly under a different name)"?
("try to insert... if this fails" is just echoing the code)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D90555/new/

https://reviews.llvm.org/D90555



More information about the cfe-commits mailing list