Skip to content

Commit 60def6d

Browse files
authored
LLVM and SPIRV-LLVM-Translator pull down #1083
2 parents d86ee2f + d357add commit 60def6d

File tree

2,875 files changed

+127262
-50015
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

2,875 files changed

+127262
-50015
lines changed

clang-tools-extra/clang-tidy/add_new_check.py

Lines changed: 65 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -294,37 +294,87 @@ def write_test(module_path, module, check_name, test_extension):
294294
def update_checks_list(clang_tidy_path):
295295
docs_dir = os.path.join(clang_tidy_path, '../docs/clang-tidy/checks')
296296
filename = os.path.normpath(os.path.join(docs_dir, 'list.rst'))
297+
# Read the content of the current list.rst file
297298
with open(filename, 'r') as f:
298299
lines = f.readlines()
300+
# Get all existing docs
299301
doc_files = list(filter(lambda s: s.endswith('.rst') and s != 'list.rst',
300302
os.listdir(docs_dir)))
301303
doc_files.sort()
302304

303-
def format_link(doc_file):
305+
def has_auto_fix(check_name):
306+
dirname, _, check_name = check_name.partition("-")
307+
308+
checkerCode = os.path.join(dirname, get_camel_name(check_name)) + ".cpp"
309+
310+
if not os.path.isfile(checkerCode):
311+
return ""
312+
313+
with open(checkerCode) as f:
314+
code = f.read()
315+
if 'FixItHint' in code or "ReplacementText" in code or "fixit" in code:
316+
# Some simple heuristics to figure out if a checker has an autofix or not.
317+
return ' "Yes"'
318+
return ""
319+
320+
def process_doc(doc_file):
304321
check_name = doc_file.replace('.rst', '')
322+
305323
with open(os.path.join(docs_dir, doc_file), 'r') as doc:
306324
content = doc.read()
307325
match = re.search('.*:orphan:.*', content)
326+
308327
if match:
309-
return ''
328+
# Orphan page, don't list it.
329+
return '', ''
310330

311331
match = re.search('.*:http-equiv=refresh: \d+;URL=(.*).html.*',
312332
content)
313-
if match:
314-
return ' %(check)s (redirects to %(target)s) <%(check)s>\n' % {
315-
'check': check_name,
316-
'target': match.group(1)
317-
}
318-
return ' %s\n' % check_name
333+
# Is it a redirect?
334+
return check_name, match
335+
336+
def format_link(doc_file):
337+
check_name, match = process_doc(doc_file)
338+
if not match and check_name:
339+
return ' `%(check)s <%(check)s.html>`_,%(autofix)s\n' % {
340+
'check': check_name,
341+
'autofix': has_auto_fix(check_name)
342+
}
343+
else:
344+
return ''
345+
346+
def format_link_alias(doc_file):
347+
check_name, match = process_doc(doc_file)
348+
if match and check_name:
349+
if match.group(1) == 'https://clang.llvm.org/docs/analyzer/checkers':
350+
title_redirect = 'Clang Static Analyzer'
351+
else:
352+
title_redirect = match.group(1)
353+
# The checker is just a redirect.
354+
return ' `%(check)s <%(check)s.html>`_, `%(title)s <%(target)s.html>`_,%(autofix)s\n' % {
355+
'check': check_name,
356+
'target': match.group(1),
357+
'title': title_redirect,
358+
'autofix': has_auto_fix(match.group(1))
359+
}
360+
return ''
319361

320362
checks = map(format_link, doc_files)
363+
checks_alias = map(format_link_alias, doc_files)
321364

322365
print('Updating %s...' % filename)
323366
with open(filename, 'w') as f:
324367
for line in lines:
325368
f.write(line)
326-
if line.startswith('.. toctree::'):
369+
if line.strip() == ".. csv-table::":
370+
# We dump the checkers
371+
f.write(' :header: "Name", "Offers fixes"\n\n')
327372
f.writelines(checks)
373+
# and the aliases
374+
f.write('\n\n')
375+
f.write('.. csv-table:: Aliases..\n')
376+
f.write(' :header: "Name", "Redirect", "Offers fixes"\n\n')
377+
f.writelines(checks_alias)
328378
break
329379

330380

@@ -345,6 +395,11 @@ def write_docs(module_path, module, check_name):
345395
'underline': '=' * len(check_name_dashes)})
346396

347397

398+
def get_camel_name(check_name):
399+
return ''.join(map(lambda elem: elem.capitalize(),
400+
check_name.split('-'))) + 'Check'
401+
402+
348403
def main():
349404
language_to_extension = {
350405
'c': 'c',
@@ -384,13 +439,11 @@ def main():
384439

385440
module = args.module
386441
check_name = args.check
387-
442+
check_name_camel = get_camel_name(check_name)
388443
if check_name.startswith(module):
389444
print('Check name "%s" must not start with the module "%s". Exiting.' % (
390445
check_name, module))
391446
return
392-
check_name_camel = ''.join(map(lambda elem: elem.capitalize(),
393-
check_name.split('-'))) + 'Check'
394447
clang_tidy_path = os.path.dirname(sys.argv[0])
395448
module_path = os.path.join(clang_tidy_path, module)
396449

clang-tools-extra/clang-tidy/bugprone/BranchCloneCheck.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ namespace bugprone {
5959

6060
void BranchCloneCheck::registerMatchers(MatchFinder *Finder) {
6161
Finder->addMatcher(
62-
ifStmt(stmt().bind("if"),
62+
ifStmt(unless(allOf(isConstexpr(), isInTemplateInstantiation())),
63+
stmt().bind("if"),
6364
hasParent(stmt(unless(ifStmt(hasElse(equalsBoundNode("if")))))),
6465
hasElse(stmt().bind("else"))),
6566
this);

clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "NotNullTerminatedResultCheck.h"
3737
#include "ParentVirtualCallCheck.h"
3838
#include "PosixReturnCheck.h"
39+
#include "ReservedIdentifierCheck.h"
3940
#include "SignedCharMisuseCheck.h"
4041
#include "SizeofContainerCheck.h"
4142
#include "SizeofExpressionCheck.h"
@@ -120,6 +121,8 @@ class BugproneModule : public ClangTidyModule {
120121
"bugprone-parent-virtual-call");
121122
CheckFactories.registerCheck<PosixReturnCheck>(
122123
"bugprone-posix-return");
124+
CheckFactories.registerCheck<ReservedIdentifierCheck>(
125+
"bugprone-reserved-identifier");
123126
CheckFactories.registerCheck<SignedCharMisuseCheck>(
124127
"bugprone-signed-char-misuse");
125128
CheckFactories.registerCheck<SizeofContainerCheck>(

clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ add_clang_library(clangTidyBugproneModule
2828
NotNullTerminatedResultCheck.cpp
2929
ParentVirtualCallCheck.cpp
3030
PosixReturnCheck.cpp
31+
ReservedIdentifierCheck.cpp
3132
SignedCharMisuseCheck.cpp
3233
SizeofContainerCheck.cpp
3334
SizeofExpressionCheck.cpp
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
//===--- ReservedIdentifierCheck.cpp - clang-tidy -------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "ReservedIdentifierCheck.h"
10+
#include "../utils/Matchers.h"
11+
#include "../utils/OptionsUtils.h"
12+
#include "clang/AST/ASTContext.h"
13+
#include "clang/ASTMatchers/ASTMatchFinder.h"
14+
#include <algorithm>
15+
#include <cctype>
16+
17+
using namespace clang::ast_matchers;
18+
19+
namespace clang {
20+
namespace tidy {
21+
namespace bugprone {
22+
23+
static const char DoubleUnderscoreTag[] = "du";
24+
static const char UnderscoreCapitalTag[] = "uc";
25+
static const char GlobalUnderscoreTag[] = "global-under";
26+
static const char NonReservedTag[] = "non-reserved";
27+
28+
static const char Message[] =
29+
"declaration uses identifier '%0', which is %select{a reserved "
30+
"identifier|not a reserved identifier|reserved in the global namespace}1";
31+
32+
static int getMessageSelectIndex(StringRef Tag) {
33+
if (Tag == NonReservedTag)
34+
return 1;
35+
if (Tag == GlobalUnderscoreTag)
36+
return 2;
37+
return 0;
38+
}
39+
40+
ReservedIdentifierCheck::ReservedIdentifierCheck(StringRef Name,
41+
ClangTidyContext *Context)
42+
: RenamerClangTidyCheck(Name, Context),
43+
Invert(Options.get("Invert", false)),
44+
AllowedIdentifiers(utils::options::parseStringList(
45+
Options.get("AllowedIdentifiers", ""))) {}
46+
47+
void ReservedIdentifierCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
48+
Options.store(Opts, "Invert", Invert);
49+
Options.store(Opts, "AllowedIdentifiers",
50+
utils::options::serializeStringList(AllowedIdentifiers));
51+
}
52+
53+
static std::string collapseConsecutive(StringRef Str, char C) {
54+
std::string Result;
55+
std::unique_copy(Str.begin(), Str.end(), std::back_inserter(Result),
56+
[C](char A, char B) { return A == C && B == C; });
57+
return Result;
58+
}
59+
60+
static bool hasReservedDoubleUnderscore(StringRef Name,
61+
const LangOptions &LangOpts) {
62+
if (LangOpts.CPlusPlus)
63+
return Name.find("__") != StringRef::npos;
64+
return Name.startswith("__");
65+
}
66+
67+
static Optional<std::string>
68+
getDoubleUnderscoreFixup(StringRef Name, const LangOptions &LangOpts) {
69+
if (hasReservedDoubleUnderscore(Name, LangOpts))
70+
return collapseConsecutive(Name, '_');
71+
return None;
72+
}
73+
74+
static bool startsWithUnderscoreCapital(StringRef Name) {
75+
return Name.size() >= 2 && Name[0] == '_' && std::isupper(Name[1]);
76+
}
77+
78+
static Optional<std::string> getUnderscoreCapitalFixup(StringRef Name) {
79+
if (startsWithUnderscoreCapital(Name))
80+
return std::string(Name.drop_front(1));
81+
return None;
82+
}
83+
84+
static bool startsWithUnderscoreInGlobalNamespace(StringRef Name,
85+
bool IsInGlobalNamespace) {
86+
return IsInGlobalNamespace && Name.size() >= 1 && Name[0] == '_';
87+
}
88+
89+
static Optional<std::string>
90+
getUnderscoreGlobalNamespaceFixup(StringRef Name, bool IsInGlobalNamespace) {
91+
if (startsWithUnderscoreInGlobalNamespace(Name, IsInGlobalNamespace))
92+
return std::string(Name.drop_front(1));
93+
return None;
94+
}
95+
96+
static std::string getNonReservedFixup(std::string Name) {
97+
assert(!Name.empty());
98+
if (Name[0] == '_' || std::isupper(Name[0]))
99+
Name.insert(Name.begin(), '_');
100+
else
101+
Name.insert(Name.begin(), 2, '_');
102+
return Name;
103+
}
104+
105+
static Optional<RenamerClangTidyCheck::FailureInfo>
106+
getFailureInfoImpl(StringRef Name, bool IsInGlobalNamespace,
107+
const LangOptions &LangOpts, bool Invert,
108+
ArrayRef<std::string> AllowedIdentifiers) {
109+
assert(!Name.empty());
110+
if (llvm::is_contained(AllowedIdentifiers, Name))
111+
return None;
112+
113+
// TODO: Check for names identical to language keywords, and other names
114+
// specifically reserved by language standards, e.g. C++ 'zombie names' and C
115+
// future library directions
116+
117+
using FailureInfo = RenamerClangTidyCheck::FailureInfo;
118+
if (!Invert) {
119+
Optional<FailureInfo> Info;
120+
auto AppendFailure = [&](StringRef Kind, std::string &&Fixup) {
121+
if (!Info) {
122+
Info = FailureInfo{Kind, std::move(Fixup)};
123+
} else {
124+
Info->KindName += Kind;
125+
Info->Fixup = std::move(Fixup);
126+
}
127+
};
128+
auto InProgressFixup = [&] {
129+
return Info
130+
.map([](const FailureInfo &Info) { return StringRef(Info.Fixup); })
131+
.getValueOr(Name);
132+
};
133+
if (auto Fixup = getDoubleUnderscoreFixup(InProgressFixup(), LangOpts))
134+
AppendFailure(DoubleUnderscoreTag, std::move(*Fixup));
135+
if (auto Fixup = getUnderscoreCapitalFixup(InProgressFixup()))
136+
AppendFailure(UnderscoreCapitalTag, std::move(*Fixup));
137+
if (auto Fixup = getUnderscoreGlobalNamespaceFixup(InProgressFixup(),
138+
IsInGlobalNamespace))
139+
AppendFailure(GlobalUnderscoreTag, std::move(*Fixup));
140+
141+
return Info;
142+
}
143+
if (!(hasReservedDoubleUnderscore(Name, LangOpts) ||
144+
startsWithUnderscoreCapital(Name) ||
145+
startsWithUnderscoreInGlobalNamespace(Name, IsInGlobalNamespace)))
146+
return FailureInfo{NonReservedTag, getNonReservedFixup(Name)};
147+
return None;
148+
}
149+
150+
Optional<RenamerClangTidyCheck::FailureInfo>
151+
ReservedIdentifierCheck::GetDeclFailureInfo(const NamedDecl *Decl,
152+
const SourceManager &) const {
153+
assert(Decl && Decl->getIdentifier() && !Decl->getName().empty() &&
154+
!Decl->isImplicit() &&
155+
"Decl must be an explicit identifier with a name.");
156+
return getFailureInfoImpl(Decl->getName(),
157+
isa<TranslationUnitDecl>(Decl->getDeclContext()),
158+
getLangOpts(), Invert, AllowedIdentifiers);
159+
}
160+
161+
Optional<RenamerClangTidyCheck::FailureInfo>
162+
ReservedIdentifierCheck::GetMacroFailureInfo(const Token &MacroNameTok,
163+
const SourceManager &) const {
164+
return getFailureInfoImpl(MacroNameTok.getIdentifierInfo()->getName(), true,
165+
getLangOpts(), Invert, AllowedIdentifiers);
166+
}
167+
168+
RenamerClangTidyCheck::DiagInfo
169+
ReservedIdentifierCheck::GetDiagInfo(const NamingCheckId &ID,
170+
const NamingCheckFailure &Failure) const {
171+
return DiagInfo{Message, [&](DiagnosticBuilder &diag) {
172+
diag << ID.second
173+
<< getMessageSelectIndex(Failure.Info.KindName);
174+
}};
175+
};
176+
177+
} // namespace bugprone
178+
} // namespace tidy
179+
} // namespace clang
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//===--- ReservedIdentifierCheck.h - clang-tidy -----------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_RESERVEDIDENTIFIERCHECK_H
10+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_RESERVEDIDENTIFIERCHECK_H
11+
12+
#include "../utils/RenamerClangTidyCheck.h"
13+
#include "llvm/ADT/Optional.h"
14+
#include <string>
15+
#include <vector>
16+
17+
namespace clang {
18+
namespace tidy {
19+
namespace bugprone {
20+
21+
/// Checks for usages of identifiers reserved for use by the implementation.
22+
///
23+
/// The C and C++ standards both reserve the following names for such use:
24+
/// * identifiers that begin with an underscore followed by an uppercase letter;
25+
/// * identifiers in the global namespace that begin with an underscore.
26+
///
27+
/// The C standard additionally reserves names beginning with a double
28+
/// underscore, while the C++ standard strengthens this to reserve names with a
29+
/// double underscore occurring anywhere.
30+
///
31+
/// For the user-facing documentation see:
32+
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-reserved-identifier.html
33+
class ReservedIdentifierCheck final : public RenamerClangTidyCheck {
34+
const bool Invert;
35+
const std::vector<std::string> AllowedIdentifiers;
36+
37+
public:
38+
ReservedIdentifierCheck(StringRef Name, ClangTidyContext *Context);
39+
40+
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
41+
42+
private:
43+
llvm::Optional<FailureInfo>
44+
GetDeclFailureInfo(const NamedDecl *Decl,
45+
const SourceManager &SM) const override;
46+
llvm::Optional<FailureInfo>
47+
GetMacroFailureInfo(const Token &MacroNameTok,
48+
const SourceManager &SM) const override;
49+
DiagInfo GetDiagInfo(const NamingCheckId &ID,
50+
const NamingCheckFailure &Failure) const override;
51+
};
52+
53+
} // namespace bugprone
54+
} // namespace tidy
55+
} // namespace clang
56+
57+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_RESERVEDIDENTIFIERCHECK_H

0 commit comments

Comments
 (0)