Add `bugprone-reserved-identifier`

This patch adds bugprone-reserved-identifier, which flags uses of __names _Like
::_this, which are reserved for the implementation. The check can optionally be
inverted, i.e. configured to flag any names that are _not_ reserved, which may
be useful for e.g. standard library implementors.
This commit is contained in:
Logan Smith 2020-01-17 08:43:20 -05:00 committed by Aaron Ballman
parent c1e159ef6e
commit 42a0355816
14 changed files with 711 additions and 1 deletions

View File

@ -36,6 +36,7 @@
#include "NotNullTerminatedResultCheck.h"
#include "ParentVirtualCallCheck.h"
#include "PosixReturnCheck.h"
#include "ReservedIdentifierCheck.h"
#include "SignedCharMisuseCheck.h"
#include "SizeofContainerCheck.h"
#include "SizeofExpressionCheck.h"
@ -120,6 +121,8 @@ public:
"bugprone-parent-virtual-call");
CheckFactories.registerCheck<PosixReturnCheck>(
"bugprone-posix-return");
CheckFactories.registerCheck<ReservedIdentifierCheck>(
"bugprone-reserved-identifier");
CheckFactories.registerCheck<SignedCharMisuseCheck>(
"bugprone-signed-char-misuse");
CheckFactories.registerCheck<SizeofContainerCheck>(

View File

@ -28,6 +28,7 @@ add_clang_library(clangTidyBugproneModule
NotNullTerminatedResultCheck.cpp
ParentVirtualCallCheck.cpp
PosixReturnCheck.cpp
ReservedIdentifierCheck.cpp
SignedCharMisuseCheck.cpp
SizeofContainerCheck.cpp
SizeofExpressionCheck.cpp

View File

@ -0,0 +1,178 @@
//===--- ReservedIdentifierCheck.cpp - 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
//
//===----------------------------------------------------------------------===//
#include "ReservedIdentifierCheck.h"
#include "../utils/Matchers.h"
#include "../utils/OptionsUtils.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include <algorithm>
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace bugprone {
static const char DoubleUnderscoreTag[] = "du";
static const char UnderscoreCapitalTag[] = "uc";
static const char GlobalUnderscoreTag[] = "global-under";
static const char NonReservedTag[] = "non-reserved";
static const char Message[] =
"declaration uses identifier '%0', which is %select{a reserved "
"identifier|not a reserved identifier|reserved in the global namespace}1";
static int getMessageSelectIndex(StringRef Tag) {
if (Tag == NonReservedTag)
return 1;
if (Tag == GlobalUnderscoreTag)
return 2;
return 0;
}
ReservedIdentifierCheck::ReservedIdentifierCheck(StringRef Name,
ClangTidyContext *Context)
: RenamerClangTidyCheck(Name, Context),
Invert(Options.get("Invert", false)),
AllowedIdentifiers(utils::options::parseStringList(
Options.get("AllowedIdentifiers", ""))) {}
void ReservedIdentifierCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "Invert", Invert);
Options.store(Opts, "AllowedIdentifiers",
utils::options::serializeStringList(AllowedIdentifiers));
}
static std::string collapseConsecutive(StringRef Str, char C) {
std::string Result;
std::unique_copy(Str.begin(), Str.end(), std::back_inserter(Result),
[C](char A, char B) { return A == C && B == C; });
return Result;
}
static bool hasReservedDoubleUnderscore(StringRef Name,
const LangOptions &LangOpts) {
if (LangOpts.CPlusPlus)
return Name.find("__") != StringRef::npos;
return Name.startswith("__");
}
static Optional<std::string>
getDoubleUnderscoreFixup(StringRef Name, const LangOptions &LangOpts) {
if (hasReservedDoubleUnderscore(Name, LangOpts))
return collapseConsecutive(Name, '_');
return None;
}
static bool startsWithUnderscoreCapital(StringRef Name) {
return Name.size() >= 2 && Name[0] == '_' && std::isupper(Name[1]);
}
static Optional<std::string> getUnderscoreCapitalFixup(StringRef Name) {
if (startsWithUnderscoreCapital(Name))
return std::string(Name.drop_front(1));
return None;
}
static bool startsWithUnderscoreInGlobalNamespace(StringRef Name,
bool IsInGlobalNamespace) {
return IsInGlobalNamespace && Name.size() >= 1 && Name[0] == '_';
}
static Optional<std::string>
getUnderscoreGlobalNamespaceFixup(StringRef Name, bool IsInGlobalNamespace) {
if (startsWithUnderscoreInGlobalNamespace(Name, IsInGlobalNamespace))
return std::string(Name.drop_front(1));
return None;
}
static std::string getNonReservedFixup(std::string Name) {
assert(!Name.empty());
if (Name[0] == '_' || std::isupper(Name[0]))
Name.insert(Name.begin(), '_');
else
Name.insert(Name.begin(), 2, '_');
return Name;
}
static Optional<RenamerClangTidyCheck::FailureInfo>
getFailureInfoImpl(StringRef Name, bool IsInGlobalNamespace,
const LangOptions &LangOpts, bool Invert,
ArrayRef<std::string> AllowedIdentifiers) {
assert(!Name.empty());
if (llvm::is_contained(AllowedIdentifiers, Name))
return None;
// TODO: Check for names identical to language keywords, and other names
// specifically reserved by language standards, e.g. C++ 'zombie names' and C
// future library directions
using FailureInfo = RenamerClangTidyCheck::FailureInfo;
if (!Invert) {
Optional<FailureInfo> Info;
auto AppendFailure = [&](StringRef Kind, std::string &&Fixup) {
if (!Info) {
Info = FailureInfo{Kind, std::move(Fixup)};
} else {
Info->KindName += Kind;
Info->Fixup = std::move(Fixup);
}
};
auto InProgressFixup = [&] {
return Info
.map([](const FailureInfo &Info) { return StringRef(Info.Fixup); })
.getValueOr(Name);
};
if (auto Fixup = getDoubleUnderscoreFixup(InProgressFixup(), LangOpts))
AppendFailure(DoubleUnderscoreTag, *std::move(Fixup));
if (auto Fixup = getUnderscoreCapitalFixup(InProgressFixup()))
AppendFailure(UnderscoreCapitalTag, *std::move(Fixup));
if (auto Fixup = getUnderscoreGlobalNamespaceFixup(InProgressFixup(),
IsInGlobalNamespace))
AppendFailure(GlobalUnderscoreTag, *std::move(Fixup));
return Info;
}
if (!(hasReservedDoubleUnderscore(Name, LangOpts) ||
startsWithUnderscoreCapital(Name) ||
startsWithUnderscoreInGlobalNamespace(Name, IsInGlobalNamespace)))
return FailureInfo{NonReservedTag, getNonReservedFixup(Name)};
return None;
}
Optional<RenamerClangTidyCheck::FailureInfo>
ReservedIdentifierCheck::GetDeclFailureInfo(const NamedDecl *Decl,
const SourceManager &) const {
assert(Decl && Decl->getIdentifier() && !Decl->getName().empty() &&
!Decl->isImplicit() &&
"Decl must be an explicit identifier with a name.");
return getFailureInfoImpl(Decl->getName(),
isa<TranslationUnitDecl>(Decl->getDeclContext()),
getLangOpts(), Invert, AllowedIdentifiers);
}
Optional<RenamerClangTidyCheck::FailureInfo>
ReservedIdentifierCheck::GetMacroFailureInfo(const Token &MacroNameTok,
const SourceManager &) const {
return getFailureInfoImpl(MacroNameTok.getIdentifierInfo()->getName(), true,
getLangOpts(), Invert, AllowedIdentifiers);
}
RenamerClangTidyCheck::DiagInfo
ReservedIdentifierCheck::GetDiagInfo(const NamingCheckId &ID,
const NamingCheckFailure &Failure) const {
return DiagInfo{Message, [&](DiagnosticBuilder &diag) {
diag << ID.second
<< getMessageSelectIndex(Failure.Info.KindName);
}};
};
} // namespace bugprone
} // namespace tidy
} // namespace clang

View File

@ -0,0 +1,57 @@
//===--- ReservedIdentifierCheck.h - clang-tidy -----------------*- C++ -*-===//
//
// 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_BUGPRONE_RESERVEDIDENTIFIERCHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_RESERVEDIDENTIFIERCHECK_H
#include "../utils/RenamerClangTidyCheck.h"
#include "llvm/ADT/Optional.h"
#include <string>
#include <vector>
namespace clang {
namespace tidy {
namespace bugprone {
/// Checks for usages of identifiers reserved for use by the implementation.
///
/// The C and C++ standards both reserve the following names for such use:
/// * identifiers that begin with an underscore followed by an uppercase letter;
/// * identifiers in the global namespace that begin with an underscore.
///
/// The C standard additionally reserves names beginning with a double
/// underscore, while the C++ standard strengthens this to reserve names with a
/// double underscore occurring anywhere.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-reserved-identifier.html
class ReservedIdentifierCheck final : public RenamerClangTidyCheck {
const bool Invert;
const std::vector<std::string> AllowedIdentifiers;
public:
ReservedIdentifierCheck(StringRef Name, ClangTidyContext *Context);
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
private:
llvm::Optional<FailureInfo>
GetDeclFailureInfo(const NamedDecl *Decl,
const SourceManager &SM) const override;
llvm::Optional<FailureInfo>
GetMacroFailureInfo(const Token &MacroNameTok,
const SourceManager &SM) const override;
DiagInfo GetDiagInfo(const NamingCheckId &ID,
const NamingCheckFailure &Failure) const override;
};
} // namespace bugprone
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_RESERVEDIDENTIFIERCHECK_H

View File

@ -9,8 +9,9 @@
#include "../ClangTidy.h"
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
#include "../bugprone/UnhandledSelfAssignmentCheck.h"
#include "../bugprone/BadSignalToKillThreadCheck.h"
#include "../bugprone/ReservedIdentifierCheck.h"
#include "../bugprone/UnhandledSelfAssignmentCheck.h"
#include "../google/UnnamedNamespaceInHeaderCheck.h"
#include "../misc/NewDeleteOverloadsCheck.h"
#include "../misc/NonCopyableObjects.h"
@ -44,6 +45,8 @@ public:
CheckFactories.registerCheck<PostfixOperatorCheck>(
"cert-dcl21-cpp");
CheckFactories.registerCheck<VariadicFunctionDefCheck>("cert-dcl50-cpp");
CheckFactories.registerCheck<bugprone::ReservedIdentifierCheck>(
"cert-dcl51-cpp");
CheckFactories.registerCheck<misc::NewDeleteOverloadsCheck>(
"cert-dcl54-cpp");
CheckFactories.registerCheck<DontModifyStdNamespaceCheck>(
@ -78,6 +81,8 @@ public:
CheckFactories.registerCheck<misc::StaticAssertCheck>("cert-dcl03-c");
CheckFactories.registerCheck<readability::UppercaseLiteralSuffixCheck>(
"cert-dcl16-c");
CheckFactories.registerCheck<bugprone::ReservedIdentifierCheck>(
"cert-dcl37-c");
// ENV
CheckFactories.registerCheck<CommandProcessorCheck>("cert-env33-c");
// FLP

View File

@ -70,10 +70,23 @@ Improvements to clang-tidy
New checks
^^^^^^^^^^
- New :doc:`bugprone-reserved-identifier
<clang-tidy/checks/bugprone-reserved-identifier>` check.
Checks for usages of identifiers reserved for use by the implementation.
New aliases
^^^^^^^^^^^
- New alias :doc:`cert-dcl37-c
<clang-tidy/checks/cert-dcl37-c>` to
:doc:`bugprone-reserved-identifier
<clang-tidy/checks/bugprone-reserved-identifier>` was added.
- New alias :doc:`cert-dcl51-cpp
<clang-tidy/checks/cert-dcl51-cpp>` to
:doc:`bugprone-reserved-identifier
<clang-tidy/checks/bugprone-reserved-identifier>` was added.
Changes in existing checks
^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -0,0 +1,56 @@
.. title:: clang-tidy - bugprone-reserved-identifier
bugprone-reserved-identifier
============================
`cert-dcl37-c` and `cert-dcl51-cpp` redirect here as an alias for this check.
Checks for usages of identifiers reserved for use by the implementation.
The C and C++ standards both reserve the following names for such use:
* identifiers that begin with an underscore followed by an uppercase letter;
* identifiers in the global namespace that begin with an underscore.
The C standard additionally reserves names beginning with a double underscore,
while the C++ standard strengthens this to reserve names with a double
underscore occurring anywhere.
Violating the naming rules above results in undefined behavior.
.. code-block:: c++
namespace NS {
void __f(); // name is not allowed in user code
using _Int = int; // same with this
#define cool__macro // also this
}
int _g(); // disallowed in global namespace only
The check can also be inverted, i.e. it can be configured to flag any
identifier that is _not_ a reserved identifier. This mode is for use by e.g.
standard library implementors, to ensure they don't infringe on the user
namespace.
This check does not (yet) check for other reserved names, e.g. macro names
identical to language keywords, and names specifically reserved by language
standards, e.g. C++ 'zombie names' and C future library directions.
This check corresponds to CERT C Coding Standard rule `DCL37-C. Do not declare
or define a reserved identifier
<https://wiki.sei.cmu.edu/confluence/display/c/DCL37-C.+Do+not+declare+or+define+a+reserved+identifier>`_
as well as its C++ counterpart, `DCL51-CPP. Do not declare or define a reserved
identifier
<https://wiki.sei.cmu.edu/confluence/display/cplusplus/DCL51-CPP.+Do+not+declare+or+define+a+reserved+identifier>`_.
Options
-------
.. option:: Invert
If non-zero, inverts the check, i.e. flags names that are not reserved.
Default is `0`.
.. option:: AllowedIdentifiers
Semicolon-separated list of names that the check ignores. Default is an
empty list.

View File

@ -0,0 +1,10 @@
.. title:: clang-tidy - cert-dcl37-c
.. meta::
:http-equiv=refresh: 5;URL=bugprone-reserved-identifier.html
cert-dcl37-c
============
The cert-dcl37-c check is an alias, please see
`bugprone-reserved-identifier <bugprone-reserved-identifier.html>`_ for more
information.

View File

@ -0,0 +1,10 @@
.. title:: clang-tidy - cert-dcl51-cpp
.. meta::
:http-equiv=refresh: 5;URL=bugprone-reserved-identifier.html
cert-dcl51-cpp
==============
The cert-dcl51-cpp check is an alias, please see
`bugprone-reserved-identifier <bugprone-reserved-identifier.html>`_ for more
information.

View File

@ -0,0 +1,33 @@
namespace std {
void __f() {}
template <class _Tp>
class reference_wrapper {
public:
typedef _Tp type;
private:
type *__f_;
public:
reference_wrapper(type &__f)
: __f_(&__f) {}
// access
operator type &() const { return *__f_; }
type &get() const { return *__f_; }
};
template <class _Tp>
inline reference_wrapper<_Tp>
ref(_Tp &__t) noexcept {
return reference_wrapper<_Tp>(__t);
}
template <class _Tp>
inline reference_wrapper<_Tp>
ref(reference_wrapper<_Tp> __t) noexcept {
return ref(__t.get());
}
} // namespace std

View File

@ -0,0 +1,58 @@
#define _HEADER_MACRO(m) int m = 0
namespace _Header_Ns {
class _Header_Object {
int _Header_Member;
};
float _Header_Global;
void _Header_Function() {}
using _Header_Alias = int;
} // namespace _Header_Ns
//
#define __header_macro(m) int m = 0
namespace __header_ns {
class __header_object {
int __header_member;
};
float __header_global;
void __header_function() {}
using __header_alias = int;
} // namespace __header_ns
//
#define header_macro__m(m) int m = 0
namespace header_ns__n {
class header_object__o {
int header_member__m;
};
float header_global__g;
void header_function__f() {}
using header_alias__a = int;
} // namespace header_ns__n
//
#define _header_macro(m) int m = 0
namespace _header_ns {}
class _header_object {};
float _header_global;
void _header_function() {}
using _header_alias = int;

View File

@ -0,0 +1,10 @@
// RUN: %check_clang_tidy %s bugprone-reserved-identifier %t
// in C, double underscores are fine except at the beginning
void foo__();
void f__o__o();
void f_________oo();
void __foo();
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: declaration uses identifier '__foo', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}void foo();{{$}}

View File

@ -0,0 +1,70 @@
// RUN: %check_clang_tidy %s bugprone-reserved-identifier %t -- \
// RUN: -config='{CheckOptions: [ \
// RUN: {key: bugprone-reserved-identifier.Invert, value: 1}, \
// RUN: {key: bugprone-reserved-identifier.AllowedIdentifiers, value: std;reference_wrapper;ref;cref;type;get}, \
// RUN: ]}' -- \
// RUN: -I%S/Inputs/bugprone-reserved-identifier \
// RUN: -isystem %S/Inputs/bugprone-reserved-identifier/system
namespace std {
void __f() {}
void f();
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: declaration uses identifier 'f', which is not a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}void __f();{{$}}
struct helper {};
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: declaration uses identifier 'helper', which is not a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}struct __helper {};{{$}}
struct Helper {};
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: declaration uses identifier 'Helper', which is not a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}struct _Helper {};{{$}}
struct _helper2 {};
// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: declaration uses identifier '_helper2', which is not a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}struct __helper2 {};{{$}}
template <class _Tp>
class reference_wrapper {
public:
typedef _Tp type;
private:
type *__f_;
public:
reference_wrapper(type &__f)
: __f_(&__f) {}
// access
operator type &() const { return *__f_; }
type &get() const { return *__f_; }
};
template <class _Tp>
inline reference_wrapper<_Tp>
ref(_Tp &__t) noexcept {
return reference_wrapper<_Tp>(__t);
}
template <class _Tp>
inline reference_wrapper<_Tp>
ref(reference_wrapper<_Tp> __t) noexcept {
return ref(__t.get());
}
template <class Up>
// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: declaration uses identifier 'Up', which is not a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}template <class _Up>{{$}}
inline reference_wrapper<const Up>
cref(const Up &u) noexcept {
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: declaration uses identifier 'u', which is not a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}cref(const Up &__u) noexcept {{{$}}
return reference_wrapper<const Up>(u);
}
template <class _Tp>
inline reference_wrapper<_Tp>
cref(reference_wrapper<const _Tp> __t) noexcept {
return cref(__t.get());
}
} // namespace std

View File

@ -0,0 +1,206 @@
// RUN: %check_clang_tidy %s bugprone-reserved-identifier %t -- -- \
// RUN: -I%S/Inputs/bugprone-reserved-identifier \
// RUN: -isystem %S/Inputs/bugprone-reserved-identifier/system
// no warnings expected without -header-filter=
#include "user-header.h"
#include <system-header.h>
#define _MACRO(m) int m = 0
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: declaration uses identifier '_MACRO', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}#define MACRO(m) int m = 0{{$}}
namespace _Ns {
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: declaration uses identifier '_Ns', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}namespace Ns {{{$}}
class _Object {
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration uses identifier '_Object', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}class Object {{{$}}
int _Member;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration uses identifier '_Member', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}} int Member;{{$}}
};
float _Global;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration uses identifier '_Global', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}float Global;{{$}}
void _Function() {}
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: declaration uses identifier '_Function', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}void Function() {}{{$}}
using _Alias = int;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration uses identifier '_Alias', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}using Alias = int;{{$}}
template <typename _TemplateParam>
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: declaration uses identifier '_TemplateParam', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}template <typename TemplateParam>{{$}}
struct S {};
} // namespace _Ns
//
#define __macro(m) int m = 0
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: declaration uses identifier '__macro', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}#define macro(m) int m = 0{{$}}
namespace __ns {
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: declaration uses identifier '__ns', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}namespace ns {{{$}}
class __object {
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration uses identifier '__object', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}class _object {{{$}}
int __member;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration uses identifier '__member', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}} int _member;{{$}}
};
float __global;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration uses identifier '__global', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}float _global;{{$}}
void __function() {}
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: declaration uses identifier '__function', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}void _function() {}{{$}}
using __alias = int;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration uses identifier '__alias', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}using _alias = int;{{$}}
template <typename __templateParam>
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: declaration uses identifier '__templateParam', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}template <typename _templateParam>{{$}}
struct S {};
} // namespace __ns
//
#define macro___m(m) int m = 0
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: declaration uses identifier 'macro___m', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}#define macro_m(m) int m = 0{{$}}
namespace ns___n {
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: declaration uses identifier 'ns___n', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}namespace ns_n {{{$}}
class object___o {
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration uses identifier 'object___o', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}class object_o {{{$}}
int member___m;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration uses identifier 'member___m', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}} int member_m;{{$}}
};
float global___g;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration uses identifier 'global___g', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}float global_g;{{$}}
void function___f() {}
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: declaration uses identifier 'function___f', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}void function_f() {}{{$}}
using alias___a = int;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration uses identifier 'alias___a', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}using alias_a = int;{{$}}
template <typename templateParam___t>
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: declaration uses identifier 'templateParam___t', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}template <typename templateParam_t>{{$}}
struct S {};
} // namespace ns___n
//
#define _macro(m) int m = 0
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: declaration uses identifier '_macro', which is reserved in the global namespace [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}#define macro(m) int m = 0{{$}}
namespace _ns {
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: declaration uses identifier '_ns', which is reserved in the global namespace [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}namespace ns {{{$}}
int _i;
// no warning
} // namespace _ns
class _object {
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration uses identifier '_object', which is reserved in the global namespace [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}class object {{{$}}
int _member;
// no warning
};
float _global;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration uses identifier '_global', which is reserved in the global namespace [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}float global;{{$}}
void _function() {}
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: declaration uses identifier '_function', which is reserved in the global namespace [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}void function() {}{{$}}
using _alias = int;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: declaration uses identifier '_alias', which is reserved in the global namespace [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}using alias = int;{{$}}
template <typename _templateParam> // no warning, template params are not in the global namespace
struct S {};
void _float() {}
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: declaration uses identifier '_float', which is reserved in the global namespace; cannot be fixed because 'float' would conflict with a keyword [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}void _float() {}{{$}}
#define SOME_MACRO
int SOME__MACRO;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: declaration uses identifier 'SOME__MACRO', which is a reserved identifier; cannot be fixed because 'SOME_MACRO' would conflict with a macro definition [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}int SOME__MACRO;{{$}}
void _TWO__PROBLEMS() {}
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: declaration uses identifier '_TWO__PROBLEMS', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}void TWO_PROBLEMS() {}{{$}}
void _two__problems() {}
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: declaration uses identifier '_two__problems', which is a reserved identifier [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}void two_problems() {}{{$}}
int __;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: declaration uses identifier '__', which is a reserved identifier; cannot be fixed automatically [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}int __;{{$}}
int _________;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: declaration uses identifier '_________', which is a reserved identifier; cannot be fixed automatically [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}int _________;{{$}}
int _;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: declaration uses identifier '_', which is reserved in the global namespace; cannot be fixed automatically [bugprone-reserved-identifier]
// CHECK-FIXES: {{^}}int _;{{$}}
// these should pass
#define MACRO(m) int m = 0
namespace Ns {
class Object {
int Member;
};
float Global;
void Function() {}
using Alias = int;
template <typename TemplateParam>
struct S {};
} // namespace Ns
namespace ns_ {
class object_ {
int member_;
};
float global_;
void function_() {}
using alias_ = int;
template <typename templateParam_>
struct S {};
} // namespace ns_
class object_ {
int member_;
};
float global_;
void function_() {}
using alias_ = int;
template <typename templateParam_>
struct S_ {};