Commit e4779883 authored by Daniel's avatar Daniel Committed by Aaron Ballman
Browse files

Fix readability-identifier-naming to prevent variables becoming keywords.

Do not provide a fix-it when clang-tidy encounters a name that would become
a keyword.
parent 3e855714
Loading
Loading
Loading
Loading
+42 −20
Original line number Diff line number Diff line
@@ -691,10 +691,11 @@ static void addUsage(IdentifierNamingCheck::NamingCheckFailureMap &Failures,
  if (!Failure.RawUsageLocs.insert(FixLocation.getRawEncoding()).second)
    return;

  if (!Failure.ShouldFix)
  if (!Failure.ShouldFix())
    return;

  Failure.ShouldFix = utils::rangeCanBeFixed(Range, SourceMgr);
  if (!utils::rangeCanBeFixed(Range, SourceMgr))
    Failure.FixStatus = IdentifierNamingCheck::ShouldFixStatus::InsideMacro;
}

/// Convenience method when the usage to be added is a NamedDecl
@@ -873,6 +874,16 @@ void IdentifierNamingCheck::check(const MatchFinder::MatchResult &Result) {
          DeclarationNameInfo(Decl->getDeclName(), Decl->getLocation())
              .getSourceRange();

      const IdentifierTable &Idents = Decl->getASTContext().Idents;
      auto CheckNewIdentifier = Idents.find(Fixup);
      if (CheckNewIdentifier != Idents.end()) {
        const IdentifierInfo *Ident = CheckNewIdentifier->second;
        if (Ident->isKeyword(getLangOpts()))
          Failure.FixStatus = ShouldFixStatus::ConflictsWithKeyword;
        else if (Ident->hasMacroDefinition())
          Failure.FixStatus = ShouldFixStatus::ConflictsWithMacroDefinition;
      }

      Failure.Fixup = std::move(Fixup);
      Failure.KindName = std::move(KindName);
      addUsage(NamingCheckFailures, Decl, Range);
@@ -935,16 +946,26 @@ void IdentifierNamingCheck::onEndOfTranslationUnit() {
    if (Failure.KindName.empty())
      continue;

    if (Failure.ShouldFix) {
      auto Diag = diag(Decl.first, "invalid case style for %0 '%1'")
                  << Failure.KindName << Decl.second;

    if (Failure.ShouldNotify()) {
      auto Diag =
          diag(Decl.first,
               "invalid case style for %0 '%1'%select{|" // Case 0 is empty on
                                                         // purpose, because we
                                                         // intent to provide a
                                                         // fix
               "; cannot be fixed because '%3' would conflict with a keyword|"
               "; cannot be fixed because '%3' would conflict with a macro "
               "definition}2")
          << Failure.KindName << Decl.second
          << static_cast<int>(Failure.FixStatus) << Failure.Fixup;

      if (Failure.ShouldFix()) {
        for (const auto &Loc : Failure.RawUsageLocs) {
        // We assume that the identifier name is made of one token only. This is
        // always the case as we ignore usages in macros that could build
          // We assume that the identifier name is made of one token only. This
          // is always the case as we ignore usages in macros that could build
          // identifier names by combining multiple tokens.
          //
        // For destructors, we alread take care of it by remembering the
          // For destructors, we already take care of it by remembering the
          // location of the start of the identifier and not the start of the
          // tilde.
          //
@@ -957,6 +978,7 @@ void IdentifierNamingCheck::onEndOfTranslationUnit() {
      }
    }
  }
}

} // namespace readability
} // namespace tidy
+26 −2
Original line number Diff line number Diff line
@@ -65,6 +65,24 @@ public:
    std::string Suffix;
  };

  /// This enum will be used in %select of the diagnostic message.
  /// Each value below IgnoreFailureThreshold should have an error message.
  enum class ShouldFixStatus {
    ShouldFix,
    ConflictsWithKeyword, /// The fixup will conflict with a language keyword,
                          /// so we can't fix it automatically.
    ConflictsWithMacroDefinition, /// The fixup will conflict with a macro
                                  /// definition, so we can't fix it
                                  /// automatically.

    /// Values pass this threshold will be ignored completely
    /// i.e no message, no fixup.
    IgnoreFailureThreshold,

    InsideMacro, /// If the identifier was used or declared within a macro we
                 /// won't offer a fixup for safety reasons.
  };

  /// Holds an identifier name check failure, tracking the kind of the
  /// identifer, its possible fixup and the starting locations of all the
  /// identifier usages.
@@ -76,13 +94,19 @@ public:
    ///
    /// ie: if the identifier was used or declared within a macro we won't offer
    /// a fixup for safety reasons.
    bool ShouldFix;
    bool ShouldFix() const { return FixStatus == ShouldFixStatus::ShouldFix; }

    bool ShouldNotify() const {
      return FixStatus < ShouldFixStatus::IgnoreFailureThreshold;
    }

    ShouldFixStatus FixStatus = ShouldFixStatus::ShouldFix;

    /// A set of all the identifier usages starting SourceLocation, in
    /// their encoded form.
    llvm::DenseSet<unsigned> RawUsageLocs;

    NamingCheckFailure() : ShouldFix(true) {}
    NamingCheckFailure() = default;
  };

  typedef std::pair<SourceLocation, std::string> NamingCheckId;
+2 −0
Original line number Diff line number Diff line
@@ -581,6 +581,8 @@ public:
  iterator end() const   { return HashTable.end(); }
  unsigned size() const  { return HashTable.size(); }

  iterator find(StringRef Name) const { return HashTable.find(Name); }

  /// Print some statistics to stderr that indicate how well the
  /// hashing is doing.
  void PrintStats() const;