forked from OSchip/llvm-project
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:
parent
c1e159ef6e
commit
42a0355816
|
@ -36,6 +36,7 @@
|
||||||
#include "NotNullTerminatedResultCheck.h"
|
#include "NotNullTerminatedResultCheck.h"
|
||||||
#include "ParentVirtualCallCheck.h"
|
#include "ParentVirtualCallCheck.h"
|
||||||
#include "PosixReturnCheck.h"
|
#include "PosixReturnCheck.h"
|
||||||
|
#include "ReservedIdentifierCheck.h"
|
||||||
#include "SignedCharMisuseCheck.h"
|
#include "SignedCharMisuseCheck.h"
|
||||||
#include "SizeofContainerCheck.h"
|
#include "SizeofContainerCheck.h"
|
||||||
#include "SizeofExpressionCheck.h"
|
#include "SizeofExpressionCheck.h"
|
||||||
|
@ -120,6 +121,8 @@ public:
|
||||||
"bugprone-parent-virtual-call");
|
"bugprone-parent-virtual-call");
|
||||||
CheckFactories.registerCheck<PosixReturnCheck>(
|
CheckFactories.registerCheck<PosixReturnCheck>(
|
||||||
"bugprone-posix-return");
|
"bugprone-posix-return");
|
||||||
|
CheckFactories.registerCheck<ReservedIdentifierCheck>(
|
||||||
|
"bugprone-reserved-identifier");
|
||||||
CheckFactories.registerCheck<SignedCharMisuseCheck>(
|
CheckFactories.registerCheck<SignedCharMisuseCheck>(
|
||||||
"bugprone-signed-char-misuse");
|
"bugprone-signed-char-misuse");
|
||||||
CheckFactories.registerCheck<SizeofContainerCheck>(
|
CheckFactories.registerCheck<SizeofContainerCheck>(
|
||||||
|
|
|
@ -28,6 +28,7 @@ add_clang_library(clangTidyBugproneModule
|
||||||
NotNullTerminatedResultCheck.cpp
|
NotNullTerminatedResultCheck.cpp
|
||||||
ParentVirtualCallCheck.cpp
|
ParentVirtualCallCheck.cpp
|
||||||
PosixReturnCheck.cpp
|
PosixReturnCheck.cpp
|
||||||
|
ReservedIdentifierCheck.cpp
|
||||||
SignedCharMisuseCheck.cpp
|
SignedCharMisuseCheck.cpp
|
||||||
SizeofContainerCheck.cpp
|
SizeofContainerCheck.cpp
|
||||||
SizeofExpressionCheck.cpp
|
SizeofExpressionCheck.cpp
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -9,8 +9,9 @@
|
||||||
#include "../ClangTidy.h"
|
#include "../ClangTidy.h"
|
||||||
#include "../ClangTidyModule.h"
|
#include "../ClangTidyModule.h"
|
||||||
#include "../ClangTidyModuleRegistry.h"
|
#include "../ClangTidyModuleRegistry.h"
|
||||||
#include "../bugprone/UnhandledSelfAssignmentCheck.h"
|
|
||||||
#include "../bugprone/BadSignalToKillThreadCheck.h"
|
#include "../bugprone/BadSignalToKillThreadCheck.h"
|
||||||
|
#include "../bugprone/ReservedIdentifierCheck.h"
|
||||||
|
#include "../bugprone/UnhandledSelfAssignmentCheck.h"
|
||||||
#include "../google/UnnamedNamespaceInHeaderCheck.h"
|
#include "../google/UnnamedNamespaceInHeaderCheck.h"
|
||||||
#include "../misc/NewDeleteOverloadsCheck.h"
|
#include "../misc/NewDeleteOverloadsCheck.h"
|
||||||
#include "../misc/NonCopyableObjects.h"
|
#include "../misc/NonCopyableObjects.h"
|
||||||
|
@ -44,6 +45,8 @@ public:
|
||||||
CheckFactories.registerCheck<PostfixOperatorCheck>(
|
CheckFactories.registerCheck<PostfixOperatorCheck>(
|
||||||
"cert-dcl21-cpp");
|
"cert-dcl21-cpp");
|
||||||
CheckFactories.registerCheck<VariadicFunctionDefCheck>("cert-dcl50-cpp");
|
CheckFactories.registerCheck<VariadicFunctionDefCheck>("cert-dcl50-cpp");
|
||||||
|
CheckFactories.registerCheck<bugprone::ReservedIdentifierCheck>(
|
||||||
|
"cert-dcl51-cpp");
|
||||||
CheckFactories.registerCheck<misc::NewDeleteOverloadsCheck>(
|
CheckFactories.registerCheck<misc::NewDeleteOverloadsCheck>(
|
||||||
"cert-dcl54-cpp");
|
"cert-dcl54-cpp");
|
||||||
CheckFactories.registerCheck<DontModifyStdNamespaceCheck>(
|
CheckFactories.registerCheck<DontModifyStdNamespaceCheck>(
|
||||||
|
@ -78,6 +81,8 @@ public:
|
||||||
CheckFactories.registerCheck<misc::StaticAssertCheck>("cert-dcl03-c");
|
CheckFactories.registerCheck<misc::StaticAssertCheck>("cert-dcl03-c");
|
||||||
CheckFactories.registerCheck<readability::UppercaseLiteralSuffixCheck>(
|
CheckFactories.registerCheck<readability::UppercaseLiteralSuffixCheck>(
|
||||||
"cert-dcl16-c");
|
"cert-dcl16-c");
|
||||||
|
CheckFactories.registerCheck<bugprone::ReservedIdentifierCheck>(
|
||||||
|
"cert-dcl37-c");
|
||||||
// ENV
|
// ENV
|
||||||
CheckFactories.registerCheck<CommandProcessorCheck>("cert-env33-c");
|
CheckFactories.registerCheck<CommandProcessorCheck>("cert-env33-c");
|
||||||
// FLP
|
// FLP
|
||||||
|
|
|
@ -70,10 +70,23 @@ Improvements to clang-tidy
|
||||||
New checks
|
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 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
|
Changes in existing checks
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
@ -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.
|
|
@ -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.
|
|
@ -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.
|
|
@ -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
|
|
@ -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;
|
|
@ -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();{{$}}
|
|
@ -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
|
|
@ -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_ {};
|
Loading…
Reference in New Issue