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 "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>(
|
||||
|
|
|
@ -28,6 +28,7 @@ add_clang_library(clangTidyBugproneModule
|
|||
NotNullTerminatedResultCheck.cpp
|
||||
ParentVirtualCallCheck.cpp
|
||||
PosixReturnCheck.cpp
|
||||
ReservedIdentifierCheck.cpp
|
||||
SignedCharMisuseCheck.cpp
|
||||
SizeofContainerCheck.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 "../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
|
||||
|
|
|
@ -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
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -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