Sirui Mu aca3727e97
[clang-tidy] Treat fields in anonymous records as names in enclosing scope when checking name styles (#75701)
Currently, fields in anonymous records are treated as normal record
members during naming style check. This can be undesirable in certain
situations since these fields are used just like names in their
enclosing scopes:

```c++
class Foo {
  union {
    int iv_;    // warning: invalid case style for public member 'iv_'
    float fv_;  // warning: invalid case style for public member 'fv_'
  };
};
```

`iv_` and `fv_` are used in the code like private members of `Foo` but
their naming style comes from rules for public members.

This PR changes this behavior. It adds a new option
`CheckAnonFieldInParent` to `readability-identifier-naming`. When set to
`true`, fields in anonymous records will be treated as names in their
enclosing scopes when checking name styles. Specifically:

- If the anonymous record is defined within the file scope or in a
namespace scope, treat its fields as global variables when checking name
styles;
- If the anonymous record is defined within a function, treat its fields
as local variables when checking name styles;
- If the anonymous record is defined within a non-anonymous record,
treat its fields as non-static record members when checking name styles.
2023-12-26 15:49:41 +01:00

51 lines
2.2 KiB
C++

//===---------- ASTUtils.h - clang-tidy -----------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ASTUTILS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ASTUTILS_H
#include "clang/AST/AST.h"
namespace clang::tidy::utils {
// Returns the (closest) Function declaration surrounding |Statement| or NULL.
const FunctionDecl *getSurroundingFunction(ASTContext &Context,
const Stmt &Statement);
// Determine whether Expr is a Binary or Ternary expression.
bool isBinaryOrTernary(const Expr *E);
/// Checks whether a macro flag is present in the given argument. Only considers
/// cases of single match or match in a binary OR expression. For example,
/// <needed-flag> or <flag> | <needed-flag> | ...
bool exprHasBitFlagWithSpelling(const Expr *Flags, const SourceManager &SM,
const LangOptions &LangOpts,
StringRef FlagName);
// Check if the range is entirely contained within a macro argument.
bool rangeIsEntirelyWithinMacroArgument(SourceRange Range,
const SourceManager *SM);
// Check if the range contains any locations from a macro expansion.
bool rangeContainsMacroExpansion(SourceRange Range, const SourceManager *SM);
// Can a fix-it be issued for this whole Range?
// FIXME: false-negative if the entire range is fully expanded from a macro.
bool rangeCanBeFixed(SourceRange Range, const SourceManager *SM);
// Check if statements are same
bool areStatementsIdentical(const Stmt *FirstStmt, const Stmt *SecondStmt,
const ASTContext &Context, bool Canonical = false);
// Given a field of an anonymous record, find its corresponding
// IndirectFieldDecl in the outermost possible scope.
const IndirectFieldDecl *
findOutermostIndirectFieldDeclForField(const FieldDecl *FD);
} // namespace clang::tidy::utils
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_ASTUTILS_H