diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp index 03dcfa5f81109..e6f44dd51b459 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp @@ -9,6 +9,7 @@ #include "IdentifierNamingCheck.h" #include "../GlobList.h" +#include "../utils/ASTUtils.h" #include "clang/AST/CXXInheritance.h" #include "clang/Lex/PPCallbacks.h" #include "clang/Lex/Preprocessor.h" @@ -286,7 +287,9 @@ IdentifierNamingCheck::FileStyle IdentifierNamingCheck::getFileStyleFromOptions( HPTOpt.value_or(IdentifierNamingCheck::HPT_Off)); } bool IgnoreMainLike = Options.get("IgnoreMainLikeFunctions", false); - return {std::move(Styles), std::move(HNOption), IgnoreMainLike}; + bool CheckAnonFieldInParent = Options.get("CheckAnonFieldInParent", false); + return {std::move(Styles), std::move(HNOption), IgnoreMainLike, + CheckAnonFieldInParent}; } std::string IdentifierNamingCheck::HungarianNotation::getDeclTypeName( @@ -859,6 +862,8 @@ void IdentifierNamingCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "IgnoreFailedSplit", IgnoreFailedSplit); Options.store(Opts, "IgnoreMainLikeFunctions", MainFileStyle->isIgnoringMainLikeFunction()); + Options.store(Opts, "CheckAnonFieldInParent", + MainFileStyle->isCheckingAnonFieldInParentScope()); } bool IdentifierNamingCheck::matchesStyle( @@ -1111,7 +1116,7 @@ std::string IdentifierNamingCheck::fixupWithStyle( StyleKind IdentifierNamingCheck::findStyleKind( const NamedDecl *D, ArrayRef> NamingStyles, - bool IgnoreMainLikeFunctions) const { + bool IgnoreMainLikeFunctions, bool CheckAnonFieldInParentScope) const { assert(D && D->getIdentifier() && !D->getName().empty() && !D->isImplicit() && "Decl must be an explicit identifier with a name."); @@ -1185,29 +1190,14 @@ StyleKind IdentifierNamingCheck::findStyleKind( } if (const auto *Decl = dyn_cast(D)) { - QualType Type = Decl->getType(); - - if (!Type.isNull() && Type.isConstQualified()) { - if (NamingStyles[SK_ConstantMember]) - return SK_ConstantMember; - - if (NamingStyles[SK_Constant]) - return SK_Constant; + if (CheckAnonFieldInParentScope) { + const RecordDecl *Record = Decl->getParent(); + if (Record->isAnonymousStructOrUnion()) { + return findStyleKindForAnonField(Decl, NamingStyles); + } } - if (Decl->getAccess() == AS_private && NamingStyles[SK_PrivateMember]) - return SK_PrivateMember; - - if (Decl->getAccess() == AS_protected && NamingStyles[SK_ProtectedMember]) - return SK_ProtectedMember; - - if (Decl->getAccess() == AS_public && NamingStyles[SK_PublicMember]) - return SK_PublicMember; - - if (NamingStyles[SK_Member]) - return SK_Member; - - return SK_Invalid; + return findStyleKindForField(Decl, Decl->getType(), NamingStyles); } if (const auto *Decl = dyn_cast(D)) { @@ -1244,66 +1234,7 @@ StyleKind IdentifierNamingCheck::findStyleKind( } if (const auto *Decl = dyn_cast(D)) { - QualType Type = Decl->getType(); - - if (Decl->isConstexpr() && NamingStyles[SK_ConstexprVariable]) - return SK_ConstexprVariable; - - if (!Type.isNull() && Type.isConstQualified()) { - if (Decl->isStaticDataMember() && NamingStyles[SK_ClassConstant]) - return SK_ClassConstant; - - if (Decl->isFileVarDecl() && Type.getTypePtr()->isAnyPointerType() && - NamingStyles[SK_GlobalConstantPointer]) - return SK_GlobalConstantPointer; - - if (Decl->isFileVarDecl() && NamingStyles[SK_GlobalConstant]) - return SK_GlobalConstant; - - if (Decl->isStaticLocal() && NamingStyles[SK_StaticConstant]) - return SK_StaticConstant; - - if (Decl->isLocalVarDecl() && Type.getTypePtr()->isAnyPointerType() && - NamingStyles[SK_LocalConstantPointer]) - return SK_LocalConstantPointer; - - if (Decl->isLocalVarDecl() && NamingStyles[SK_LocalConstant]) - return SK_LocalConstant; - - if (Decl->isFunctionOrMethodVarDecl() && NamingStyles[SK_LocalConstant]) - return SK_LocalConstant; - - if (NamingStyles[SK_Constant]) - return SK_Constant; - } - - if (Decl->isStaticDataMember() && NamingStyles[SK_ClassMember]) - return SK_ClassMember; - - if (Decl->isFileVarDecl() && Type.getTypePtr()->isAnyPointerType() && - NamingStyles[SK_GlobalPointer]) - return SK_GlobalPointer; - - if (Decl->isFileVarDecl() && NamingStyles[SK_GlobalVariable]) - return SK_GlobalVariable; - - if (Decl->isStaticLocal() && NamingStyles[SK_StaticVariable]) - return SK_StaticVariable; - - if (Decl->isLocalVarDecl() && Type.getTypePtr()->isAnyPointerType() && - NamingStyles[SK_LocalPointer]) - return SK_LocalPointer; - - if (Decl->isLocalVarDecl() && NamingStyles[SK_LocalVariable]) - return SK_LocalVariable; - - if (Decl->isFunctionOrMethodVarDecl() && NamingStyles[SK_LocalVariable]) - return SK_LocalVariable; - - if (NamingStyles[SK_Variable]) - return SK_Variable; - - return SK_Invalid; + return findStyleKindForVar(Decl, Decl->getType(), NamingStyles); } if (const auto *Decl = dyn_cast(D)) { @@ -1442,12 +1373,13 @@ IdentifierNamingCheck::getDeclFailureInfo(const NamedDecl *Decl, if (!FileStyle.isActive()) return std::nullopt; - return getFailureInfo(HungarianNotation.getDeclTypeName(Decl), - Decl->getName(), Decl, Loc, FileStyle.getStyles(), - FileStyle.getHNOption(), - findStyleKind(Decl, FileStyle.getStyles(), - FileStyle.isIgnoringMainLikeFunction()), - SM, IgnoreFailedSplit); + return getFailureInfo( + HungarianNotation.getDeclTypeName(Decl), Decl->getName(), Decl, Loc, + FileStyle.getStyles(), FileStyle.getHNOption(), + findStyleKind(Decl, FileStyle.getStyles(), + FileStyle.isIgnoringMainLikeFunction(), + FileStyle.isCheckingAnonFieldInParentScope()), + SM, IgnoreFailedSplit); } std::optional @@ -1496,5 +1428,114 @@ IdentifierNamingCheck::getStyleForFile(StringRef FileName) const { return It.first->getValue(); } +StyleKind IdentifierNamingCheck::findStyleKindForAnonField( + const FieldDecl *AnonField, + ArrayRef> NamingStyles) const { + const IndirectFieldDecl *IFD = + utils::findOutermostIndirectFieldDeclForField(AnonField); + assert(IFD && "Found an anonymous record field without an IndirectFieldDecl"); + + QualType Type = AnonField->getType(); + + if (const auto *F = dyn_cast(IFD->chain().front())) { + return findStyleKindForField(F, Type, NamingStyles); + } + + if (const auto *V = IFD->getVarDecl()) { + return findStyleKindForVar(V, Type, NamingStyles); + } + + return SK_Invalid; +} + +StyleKind IdentifierNamingCheck::findStyleKindForField( + const FieldDecl *Field, QualType Type, + ArrayRef> NamingStyles) const { + if (!Type.isNull() && Type.isConstQualified()) { + if (NamingStyles[SK_ConstantMember]) + return SK_ConstantMember; + + if (NamingStyles[SK_Constant]) + return SK_Constant; + } + + if (Field->getAccess() == AS_private && NamingStyles[SK_PrivateMember]) + return SK_PrivateMember; + + if (Field->getAccess() == AS_protected && NamingStyles[SK_ProtectedMember]) + return SK_ProtectedMember; + + if (Field->getAccess() == AS_public && NamingStyles[SK_PublicMember]) + return SK_PublicMember; + + if (NamingStyles[SK_Member]) + return SK_Member; + + return SK_Invalid; +} + +StyleKind IdentifierNamingCheck::findStyleKindForVar( + const VarDecl *Var, QualType Type, + ArrayRef> NamingStyles) const { + if (Var->isConstexpr() && NamingStyles[SK_ConstexprVariable]) + return SK_ConstexprVariable; + + if (!Type.isNull() && Type.isConstQualified()) { + if (Var->isStaticDataMember() && NamingStyles[SK_ClassConstant]) + return SK_ClassConstant; + + if (Var->isFileVarDecl() && Type.getTypePtr()->isAnyPointerType() && + NamingStyles[SK_GlobalConstantPointer]) + return SK_GlobalConstantPointer; + + if (Var->isFileVarDecl() && NamingStyles[SK_GlobalConstant]) + return SK_GlobalConstant; + + if (Var->isStaticLocal() && NamingStyles[SK_StaticConstant]) + return SK_StaticConstant; + + if (Var->isLocalVarDecl() && Type.getTypePtr()->isAnyPointerType() && + NamingStyles[SK_LocalConstantPointer]) + return SK_LocalConstantPointer; + + if (Var->isLocalVarDecl() && NamingStyles[SK_LocalConstant]) + return SK_LocalConstant; + + if (Var->isFunctionOrMethodVarDecl() && NamingStyles[SK_LocalConstant]) + return SK_LocalConstant; + + if (NamingStyles[SK_Constant]) + return SK_Constant; + } + + if (Var->isStaticDataMember() && NamingStyles[SK_ClassMember]) + return SK_ClassMember; + + if (Var->isFileVarDecl() && Type.getTypePtr()->isAnyPointerType() && + NamingStyles[SK_GlobalPointer]) + return SK_GlobalPointer; + + if (Var->isFileVarDecl() && NamingStyles[SK_GlobalVariable]) + return SK_GlobalVariable; + + if (Var->isStaticLocal() && NamingStyles[SK_StaticVariable]) + return SK_StaticVariable; + + if (Var->isLocalVarDecl() && Type.getTypePtr()->isAnyPointerType() && + NamingStyles[SK_LocalPointer]) + return SK_LocalPointer; + + if (Var->isLocalVarDecl() && NamingStyles[SK_LocalVariable]) + return SK_LocalVariable; + + if (Var->isFunctionOrMethodVarDecl() && NamingStyles[SK_LocalVariable]) + return SK_LocalVariable; + + if (NamingStyles[SK_Variable]) + return SK_Variable; + + return SK_Invalid; +} + } // namespace readability } // namespace clang::tidy diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h index 14626981cc42d..27c8e4bc768c4 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h @@ -127,9 +127,11 @@ class IdentifierNamingCheck final : public RenamerClangTidyCheck { struct FileStyle { FileStyle() : IsActive(false), IgnoreMainLikeFunctions(false) {} FileStyle(SmallVectorImpl> &&Styles, - HungarianNotationOption HNOption, bool IgnoreMainLike) + HungarianNotationOption HNOption, bool IgnoreMainLike, + bool CheckAnonFieldInParent) : Styles(std::move(Styles)), HNOption(std::move(HNOption)), - IsActive(true), IgnoreMainLikeFunctions(IgnoreMainLike) {} + IsActive(true), IgnoreMainLikeFunctions(IgnoreMainLike), + CheckAnonFieldInParentScope(CheckAnonFieldInParent) {} ArrayRef> getStyles() const { assert(IsActive); @@ -144,11 +146,16 @@ class IdentifierNamingCheck final : public RenamerClangTidyCheck { bool isActive() const { return IsActive; } bool isIgnoringMainLikeFunction() const { return IgnoreMainLikeFunctions; } + bool isCheckingAnonFieldInParentScope() const { + return CheckAnonFieldInParentScope; + } + private: SmallVector, 0> Styles; HungarianNotationOption HNOption; bool IsActive; bool IgnoreMainLikeFunctions; + bool CheckAnonFieldInParentScope; }; IdentifierNamingCheck::FileStyle @@ -175,7 +182,7 @@ class IdentifierNamingCheck final : public RenamerClangTidyCheck { StyleKind findStyleKind( const NamedDecl *D, ArrayRef> NamingStyles, - bool IgnoreMainLikeFunctions) const; + bool IgnoreMainLikeFunctions, bool CheckAnonFieldInParentScope) const; std::optional getFailureInfo( StringRef Type, StringRef Name, const NamedDecl *ND, @@ -199,6 +206,19 @@ class IdentifierNamingCheck final : public RenamerClangTidyCheck { const FileStyle &getStyleForFile(StringRef FileName) const; + /// Find the style kind of a field in an anonymous record. + StyleKind findStyleKindForAnonField( + const FieldDecl *AnonField, + ArrayRef> NamingStyles) const; + + StyleKind findStyleKindForField( + const FieldDecl *Field, QualType Type, + ArrayRef> NamingStyles) const; + + StyleKind + findStyleKindForVar(const VarDecl *Var, QualType Type, + ArrayRef> NamingStyles) const; + /// Stores the style options as a vector, indexed by the specified \ref /// StyleKind, for a given directory. mutable llvm::StringMap NamingStylesCache; diff --git a/clang-tools-extra/clang-tidy/utils/ASTUtils.cpp b/clang-tools-extra/clang-tidy/utils/ASTUtils.cpp index 64333f2c18745..fd5dadc9b01db 100644 --- a/clang-tools-extra/clang-tidy/utils/ASTUtils.cpp +++ b/clang-tools-extra/clang-tidy/utils/ASTUtils.cpp @@ -113,4 +113,28 @@ bool areStatementsIdentical(const Stmt *FirstStmt, const Stmt *SecondStmt, return DataFirst == DataSecond; } +const IndirectFieldDecl * +findOutermostIndirectFieldDeclForField(const FieldDecl *FD) { + const RecordDecl *Record = FD->getParent(); + assert(Record->isAnonymousStructOrUnion() && + "FD must be a field in an anonymous record"); + + const DeclContext *Context = Record; + while (isa(Context) && + cast(Context)->isAnonymousStructOrUnion()) { + Context = Context->getParent(); + } + + // Search for the target IndirectFieldDecl within the located context. + for (const auto *D : Context->decls()) { + const auto *IFD = dyn_cast(D); + if (!IFD) + continue; + if (IFD->getAnonField() == FD) + return IFD; + } + + return nullptr; +} + } // namespace clang::tidy::utils diff --git a/clang-tools-extra/clang-tidy/utils/ASTUtils.h b/clang-tools-extra/clang-tidy/utils/ASTUtils.h index 1bba5daf2fc76..6c3e54facd020 100644 --- a/clang-tools-extra/clang-tidy/utils/ASTUtils.h +++ b/clang-tools-extra/clang-tidy/utils/ASTUtils.h @@ -40,6 +40,11 @@ bool rangeCanBeFixed(SourceRange Range, const SourceManager *SM); 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 diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index ce82063dbfe23..fe7f40d95fe6c 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -454,7 +454,10 @@ Changes in existing checks has been enhanced, particularly within complex types like function pointers and cases where style checks were omitted when functions started with macros. Added support for C++20 ``concept`` declarations. ``Camel_Snake_Case`` and - ``camel_Snake_Case`` now detect more invalid identifier names. + ``camel_Snake_Case`` now detect more invalid identifier names. Fields in + anonymous records (i.e. anonymous structs and unions) now can be checked with + the naming rules associated with their enclosing scopes rather than the naming + rules of public struct/union members. - Improved :doc:`readability-implicit-bool-conversion ` check to take diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-naming.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-naming.rst index e36bbee394f17..2affb55cfa9ad 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-naming.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-naming.rst @@ -42,6 +42,7 @@ The following options are described below: - :option:`AbstractClassCase`, :option:`AbstractClassPrefix`, :option:`AbstractClassSuffix`, :option:`AbstractClassIgnoredRegexp`, :option:`AbstractClassHungarianPrefix` - :option:`AggressiveDependentMemberLookup` + - :option:`CheckAnonFieldInParent` - :option:`ClassCase`, :option:`ClassPrefix`, :option:`ClassSuffix`, :option:`ClassIgnoredRegexp`, :option:`ClassHungarianPrefix` - :option:`ClassConstantCase`, :option:`ClassConstantPrefix`, :option:`ClassConstantSuffix`, :option:`ClassConstantIgnoredRegexp`, :option:`ClassConstantHungarianPrefix` - :option:`ClassMemberCase`, :option:`ClassMemberPrefix`, :option:`ClassMemberSuffix`, :option:`ClassMemberIgnoredRegexp`, :option:`ClassMemberHungarianPrefix` @@ -207,6 +208,32 @@ After if AggressiveDependentMemberLookup is `true`: } }; +.. option:: CheckAnonFieldInParent + + When set to `true`, fields in anonymous records (i.e. anonymous + unions and structs) will be treated as names in the enclosing scope + rather than public members of the anonymous record for the purpose + of name checking. + +For example: + +.. code-block:: c++ + + class Foo { + private: + union { + int iv_; + float fv_; + }; + }; + +If :option:`CheckAnonFieldInParent` is `false`, you may get warnings +that ``iv_`` and ``fv_`` are not coherent to public member names, because +``iv_`` and ``fv_`` are public members of the anonymous union. When +:option:`CheckAnonFieldInParent` is `true`, ``iv_`` and ``fv_`` will be +treated as private data members of ``Foo`` for the purpose of name checking +and thus no warnings will be emitted. + .. option:: ClassCase When defined, the check will ensure class names conform to the diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-anon-record-fields.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-anon-record-fields.cpp new file mode 100644 index 0000000000000..1b4d4e924a721 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-anon-record-fields.cpp @@ -0,0 +1,185 @@ +// RUN: %check_clang_tidy -std=c++20 %s readability-identifier-naming %t -- \ +// RUN: -config='{CheckOptions: { \ +// RUN: readability-identifier-naming.CheckAnonFieldInParent: true, \ +// RUN: readability-identifier-naming.ClassConstantCase: CamelCase, \ +// RUN: readability-identifier-naming.ClassConstantPrefix: 'k', \ +// RUN: readability-identifier-naming.ClassMemberCase: CamelCase, \ +// RUN: readability-identifier-naming.ConstantCase: UPPER_CASE, \ +// RUN: readability-identifier-naming.ConstantSuffix: '_CST', \ +// RUN: readability-identifier-naming.ConstexprVariableCase: lower_case, \ +// RUN: readability-identifier-naming.GlobalConstantCase: UPPER_CASE, \ +// RUN: readability-identifier-naming.GlobalVariableCase: lower_case, \ +// RUN: readability-identifier-naming.GlobalVariablePrefix: 'g_', \ +// RUN: readability-identifier-naming.LocalConstantCase: CamelCase, \ +// RUN: readability-identifier-naming.LocalConstantPrefix: 'k', \ +// RUN: readability-identifier-naming.LocalVariableCase: lower_case, \ +// RUN: readability-identifier-naming.MemberCase: CamelCase, \ +// RUN: readability-identifier-naming.MemberPrefix: 'm_', \ +// RUN: readability-identifier-naming.ConstantMemberCase: lower_case, \ +// RUN: readability-identifier-naming.PrivateMemberPrefix: '__', \ +// RUN: readability-identifier-naming.ProtectedMemberPrefix: '_', \ +// RUN: readability-identifier-naming.PublicMemberCase: lower_case, \ +// RUN: readability-identifier-naming.StaticConstantCase: UPPER_CASE, \ +// RUN: readability-identifier-naming.StaticVariableCase: camelBack, \ +// RUN: readability-identifier-naming.StaticVariablePrefix: 's_', \ +// RUN: readability-identifier-naming.VariableCase: lower_case, \ +// RUN: readability-identifier-naming.GlobalPointerCase: CamelCase, \ +// RUN: readability-identifier-naming.GlobalPointerSuffix: '_Ptr', \ +// RUN: readability-identifier-naming.GlobalConstantPointerCase: UPPER_CASE, \ +// RUN: readability-identifier-naming.GlobalConstantPointerSuffix: '_Ptr', \ +// RUN: readability-identifier-naming.LocalPointerCase: CamelCase, \ +// RUN: readability-identifier-naming.LocalPointerPrefix: 'l_', \ +// RUN: readability-identifier-naming.LocalConstantPointerCase: CamelCase, \ +// RUN: readability-identifier-naming.LocalConstantPointerPrefix: 'lc_', \ +// RUN: }}' + +static union { + int global; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for global variable 'global' +// CHECK-FIXES: {{^}} int g_global;{{$}} + + const int global_const; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: invalid case style for global constant 'global_const' +// CHECK-FIXES: {{^}} const int GLOBAL_CONST;{{$}} + + int *global_ptr; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for global pointer 'global_ptr' +// CHECK-FIXES: {{^}} int *GlobalPtr_Ptr;{{$}} + + int *const global_const_ptr; +// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: invalid case style for global constant pointer 'global_const_ptr' +// CHECK-FIXES: {{^}} int *const GLOBAL_CONST_PTR_Ptr;{{$}} +}; + +namespace ns { + +static union { + int ns_global; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for global variable 'ns_global' +// CHECK-FIXES: {{^}} int g_ns_global;{{$}} + + const int ns_global_const; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: invalid case style for global constant 'ns_global_const' +// CHECK-FIXES: {{^}} const int NS_GLOBAL_CONST;{{$}} + + int *ns_global_ptr; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for global pointer 'ns_global_ptr' +// CHECK-FIXES: {{^}} int *NsGlobalPtr_Ptr;{{$}} + + int *const ns_global_const_ptr; +// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: invalid case style for global constant pointer 'ns_global_const_ptr' +// CHECK-FIXES: {{^}} int *const NS_GLOBAL_CONST_PTR_Ptr;{{$}} +}; + +namespace { + +union { + int anon_ns_global; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for global variable 'anon_ns_global' +// CHECK-FIXES: {{^}} int g_anon_ns_global;{{$}} + + const int anon_ns_global_const; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: invalid case style for global constant 'anon_ns_global_const' +// CHECK-FIXES: {{^}} const int ANON_NS_GLOBAL_CONST;{{$}} + + int *anon_ns_global_ptr; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: invalid case style for global pointer 'anon_ns_global_ptr' +// CHECK-FIXES: {{^}} int *AnonNsGlobalPtr_Ptr;{{$}} + + int *const anon_ns_global_const_ptr; +// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: invalid case style for global constant pointer 'anon_ns_global_const_ptr' +// CHECK-FIXES: {{^}} int *const ANON_NS_GLOBAL_CONST_PTR_Ptr;{{$}} +}; + +} + +} + + +class Foo { +public: + union { + int PubMember; +// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for public member 'PubMember' +// CHECK-FIXES: {{^}} int pub_member;{{$}} + + const int PubConstMember; +// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: invalid case style for constant member 'PubConstMember' +// CHECK-FIXES: {{^}} const int pub_const_member;{{$}} + + int *PubPtrMember; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for public member 'PubPtrMember' +// CHECK-FIXES: {{^}} int *pub_ptr_member;{{$}} + + int *const PubConstPtrMember; +// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: invalid case style for constant member 'PubConstPtrMember' +// CHECK-FIXES: {{^}} int *const pub_const_ptr_member;{{$}} + }; + +protected: + union { + int prot_member; +// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for protected member 'prot_member' +// CHECK-FIXES: {{^}} int _prot_member;{{$}} + + const int prot_const_member; + + int *prot_ptr_member; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for protected member 'prot_ptr_member' +// CHECK-FIXES: {{^}} int *_prot_ptr_member;{{$}} + + int *const prot_const_ptr_member; + }; + + +private: + union { + int pri_member; +// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for private member 'pri_member' +// CHECK-FIXES: {{^}} int __pri_member;{{$}} + + const int pri_const_member; + + int *pri_ptr_member; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for private member 'pri_ptr_member' +// CHECK-FIXES: {{^}} int *__pri_ptr_member;{{$}} + + int *const pri_const_ptr_member; + }; +}; + +void test() { + union { + int local; + + const int local_const; +// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: invalid case style for local constant 'local_const' +// CHECK-FIXES: {{^}} const int kLocalConst;{{$}} + + int *local_ptr; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for local pointer 'local_ptr' +// CHECK-FIXES: {{^}} int *l_LocalPtr;{{$}} + + int *const local_const_ptr; +// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: invalid case style for local constant pointer 'local_const_ptr' +// CHECK-FIXES: {{^}} int *const lc_LocalConstPtr;{{$}} + }; + + static union { + int local_static; +// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: invalid case style for static variable 'local_static' +// CHECK-FIXES: {{^}} int s_localStatic;{{$}} + + const int local_static_const; +// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: invalid case style for static constant 'local_static_const' +// CHECK-FIXES: {{^}} const int LOCAL_STATIC_CONST;{{$}} + + int *local_static_ptr; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: invalid case style for static variable 'local_static_ptr' +// CHECK-FIXES: {{^}} int *s_localStaticPtr;{{$}} + + int *const local_static_const_ptr; +// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: invalid case style for static constant 'local_static_const_ptr' +// CHECK-FIXES: {{^}} int *const LOCAL_STATIC_CONST_PTR;{{$}} + }; +}