Skip to content

Commit 265a3df

Browse files
authored
Merge pull request #56 from rianquinn/bsl-tidy
Bug Fixes
2 parents 82eb9bf + 5777384 commit 265a3df

10 files changed

+328
-56
lines changed

clang-tools-extra/clang-tidy/bsl/ClassMemberInitCheck.cpp

+9-4
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,23 @@ void ClassMemberInitCheck::checkCtorWithInit(const CXXConstructorDecl *Ctor)
3737
const auto Parent = Ctor->getParent()->getCanonicalDecl();
3838
auto NumFields = 0;
3939

40+
if (nullptr == Parent)
41+
return;
42+
4043
for (const auto Field : Parent->fields()) {
4144
++NumFields;
4245

4346
if (!Field->hasInClassInitializer())
4447
continue;
4548

46-
const auto Init = Field->getInClassInitializer();
47-
4849
diag(Loc, "must use either in-class initializers for all fields"
4950
" or constructor initializers for all fields");
50-
diag(Init->getBeginLoc(), "found in-class initializer here",
51-
DiagnosticIDs::Note);
51+
52+
const auto Init = Field->getInClassInitializer();
53+
if (nullptr != Init) {
54+
diag(Init->getBeginLoc(), "found in-class initializer here",
55+
DiagnosticIDs::Note);
56+
}
5257

5358
return;
5459
}

clang-tools-extra/clang-tidy/bsl/DeclForbiddenCheck.cpp

-6
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,6 @@ void DeclForbiddenCheck::check(const MatchFinder::MatchResult &Result) {
3636
return;
3737
}
3838

39-
const auto BitField = dyn_cast<FieldDecl>(D);
40-
if (BitField) {
41-
diag(Loc, "bitfields are forbidden");
42-
return;
43-
}
44-
4539
const auto Friend = dyn_cast<FriendDecl>(D);
4640
if (Friend) {
4741
const auto FriendLoc = Friend->getFriendLoc();

clang-tools-extra/clang-tidy/bsl/DocumentationCheck.cpp

+16-37
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "IsDefinedInATestFile.h"
10+
911
#include "DocumentationCheck.h"
1012
#include "clang/AST/ASTContext.h"
1113
#include "clang/ASTMatchers/ASTMatchFinder.h"
1214
#include "clang/AST/Comment.h"
1315
#include "clang/AST/CommentCommandTraits.h"
1416

15-
#include <iostream>
16-
1717
using namespace clang::ast_matchers;
1818

1919
namespace clang {
@@ -81,32 +81,6 @@ bool hasAReturn(
8181
return false;
8282
}
8383

84-
bool isDefinedInATestFile(
85-
ASTContext const * const Context, Decl const * const D)
86-
{
87-
FullSourceLoc FullLocation = Context->getFullLoc(D->getBeginLoc());
88-
89-
auto const File = FullLocation.getFileEntry();
90-
if (!File)
91-
return false;
92-
93-
std::string filename{File->tryGetRealPathName()};
94-
95-
const size_t test_folder1 = filename.find("test/");
96-
const size_t test_folder2 = filename.find("test\\");
97-
const size_t test_folder3 = filename.find("tests/");
98-
const size_t test_folder4 = filename.find("tests\\");
99-
if (std::string::npos != test_folder1 ||
100-
std::string::npos != test_folder2 ||
101-
std::string::npos != test_folder3 ||
102-
std::string::npos != test_folder4)
103-
{
104-
return true;
105-
}
106-
107-
return false;
108-
}
109-
11084
clang::comments::ParamCommandComment const * hasExtraParamCommandComment(
11185
clang::comments::FullComment const * const FC)
11286
{
@@ -195,7 +169,7 @@ void DocumentationCheck::check(const MatchFinder::MatchResult &Result) {
195169
auto const *Context = Result.Context;
196170

197171
if (auto const *FD = Result.Nodes.getNodeAs<FunctionDecl>("func-decl")) {
198-
if (isDefinedInATestFile(Context, FD))
172+
if (isDefinedInATestFile(Context, FD->getBeginLoc()))
199173
return;
200174

201175
if (FD->getMemberSpecializationInfo())
@@ -204,13 +178,15 @@ void DocumentationCheck::check(const MatchFinder::MatchResult &Result) {
204178
if (FD->getTemplateSpecializationInfo())
205179
return;
206180

181+
if (auto const *CXXMD = dyn_cast<CXXMethodDecl>(FD)) {
182+
if (CXXMD->getParent()->isLambda())
183+
return;
184+
}
185+
207186
if (!hasABrief(Context, FD)) {
208187
diag(FD->getLocation(), "Function %0 is missing documentation. Are you missing the '@brief' command?") << FD;
209188
}
210189

211-
if (FD->isDeleted())
212-
return;
213-
214190
if (isa<CXXDeductionGuideDecl>(FD))
215191
return;
216192

@@ -251,12 +227,15 @@ void DocumentationCheck::check(const MatchFinder::MatchResult &Result) {
251227
}
252228

253229
if (auto const *CXXRD = Result.Nodes.getNodeAs<CXXRecordDecl>("class-decl")) {
254-
if (isDefinedInATestFile(Context, CXXRD))
230+
if (isDefinedInATestFile(Context, CXXRD->getBeginLoc()))
255231
return;
256232

257233
if (isa<ClassTemplateSpecializationDecl>(CXXRD))
258234
return;
259235

236+
if (CXXRD->isLambda())
237+
return;
238+
260239
if (CXXRD->getDefinition() != CXXRD)
261240
return;
262241

@@ -292,7 +271,7 @@ void DocumentationCheck::check(const MatchFinder::MatchResult &Result) {
292271
}
293272

294273
if (auto const *VD = Result.Nodes.getNodeAs<VarDecl>("var-decl")) {
295-
if (isDefinedInATestFile(Context, VD))
274+
if (isDefinedInATestFile(Context, VD->getBeginLoc()))
296275
return;
297276

298277
if (VD->getParentFunctionOrMethod())
@@ -309,7 +288,7 @@ void DocumentationCheck::check(const MatchFinder::MatchResult &Result) {
309288
}
310289

311290
if (auto const *FD = Result.Nodes.getNodeAs<FieldDecl>("field-decl")) {
312-
if (isDefinedInATestFile(Context, FD))
291+
if (isDefinedInATestFile(Context, FD->getBeginLoc()))
313292
return;
314293

315294
if (!hasABrief(Context, FD)) {
@@ -320,7 +299,7 @@ void DocumentationCheck::check(const MatchFinder::MatchResult &Result) {
320299
}
321300

322301
if (auto const *TAD = Result.Nodes.getNodeAs<TypeAliasDecl>("alias-decl")) {
323-
if (isDefinedInATestFile(Context, TAD))
302+
if (isDefinedInATestFile(Context, TAD->getBeginLoc()))
324303
return;
325304

326305
if (TAD->getParentFunctionOrMethod())
@@ -349,7 +328,7 @@ void DocumentationCheck::check(const MatchFinder::MatchResult &Result) {
349328
}
350329

351330
if (auto const *ED = Result.Nodes.getNodeAs<EnumDecl>("enum-decl")) {
352-
if (isDefinedInATestFile(Context, ED))
331+
if (isDefinedInATestFile(Context, ED->getBeginLoc()))
353332
return;
354333

355334
if (!hasABrief(Context, ED)) {

clang-tools-extra/clang-tidy/bsl/ElseRequiredAfterIfCheck.cpp

+18-3
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "IsDefinedInATestFile.h"
10+
911
#include "ElseRequiredAfterIfCheck.h"
1012
#include "clang/AST/ASTContext.h"
1113
#include "clang/ASTMatchers/ASTMatchFinder.h"
1214

13-
#include <iostream>
14-
1515
using namespace clang::ast_matchers;
1616

1717
namespace clang {
@@ -91,15 +91,23 @@ void ElseRequiredAfterIfCheck::registerMatchers(MatchFinder *Finder) {
9191
}
9292

9393
void ElseRequiredAfterIfCheck::check(const MatchFinder::MatchResult &Result) {
94+
auto const *Context = Result.Context;
95+
9496
const auto *IfMissingElse = Result.Nodes.getNodeAs<IfStmt>("if_missing_else");
9597
const auto *IfMissingElseNextLine = Result.Nodes.getNodeAs<IfStmt>("if_missing_else_next_line");
9698
const auto *UnneededElse = Result.Nodes.getNodeAs<Stmt>("unneeded_else");
9799

98100
if (IfMissingElse) {
101+
if (isDefinedInATestFile(Context, IfMissingElse->getIfLoc()))
102+
return;
103+
99104
diag(IfMissingElse->getIfLoc(), "'else' is required after 'if'");
100105
}
101106

102107
if (IfMissingElseNextLine) {
108+
if (isDefinedInATestFile(Context, IfMissingElseNextLine->getIfLoc()))
109+
return;
110+
103111
auto *Parent = Result.Nodes.getNodeAs<Stmt>("parent");
104112
for (auto Iter = Parent->child_begin(); Iter != Parent->child_end(); ++Iter) {
105113
auto next = Iter;
@@ -110,8 +118,15 @@ void ElseRequiredAfterIfCheck::check(const MatchFinder::MatchResult &Result) {
110118
}
111119
}
112120

113-
if (UnneededElse && UnneededElse->getBeginLoc().isValid())
121+
if (UnneededElse) {
122+
if (UnneededElse->getBeginLoc().isInvalid())
123+
return;
124+
125+
if (isDefinedInATestFile(Context, UnneededElse->getBeginLoc()))
126+
return;
127+
114128
diag(UnneededElse->getBeginLoc(), "do not use 'else' after 'return/continue/break'");
129+
}
115130
}
116131

117132
} // namespace bsl

clang-tools-extra/clang-tidy/bsl/ImplicitConversionsForbiddenCheck.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ void ImplicitConversionsForbiddenCheck::check(const MatchFinder::MatchResult &Re
4242
ICE->getCastKind() == CK_MemberPointerToBoolean ||
4343
ICE->getCastKind() == CK_PointerToBoolean ||
4444
ICE->getCastKind() == CK_ToVoid ||
45-
ICE->getCastKind() == CK_BuiltinFnToFnPtr)
45+
ICE->getCastKind() == CK_BuiltinFnToFnPtr ||
46+
ICE->getCastKind() == CK_ConstructorConversion)
4647
return;
4748

4849
// Decaying a C-Style string is ok so long as it is a literal.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//===--- IsInATestFile.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_BSL_ISINATESTFILE_H
10+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BSL_ISINATESTFILE_H
11+
12+
#include "../ClangTidyCheck.h"
13+
14+
#include "clang/AST/ASTContext.h"
15+
#include "clang/AST/Comment.h"
16+
#include "clang/AST/CommentCommandTraits.h"
17+
18+
namespace clang {
19+
namespace tidy {
20+
namespace bsl {
21+
22+
inline bool isDefinedInATestFile(
23+
ASTContext const * const Context, SourceLocation const Loc)
24+
{
25+
FullSourceLoc FullLocation = Context->getFullLoc(Loc);
26+
27+
auto const File = FullLocation.getFileEntry();
28+
if (!File)
29+
return false;
30+
31+
std::string filename{File->tryGetRealPathName()};
32+
33+
const size_t in_clang_folder = filename.find("clang-tidy");
34+
if (std::string::npos != in_clang_folder)
35+
return false;
36+
37+
const size_t test_folder1 = filename.find("test/");
38+
const size_t test_folder2 = filename.find("test\\");
39+
const size_t test_folder3 = filename.find("tests/");
40+
const size_t test_folder4 = filename.find("tests\\");
41+
if (std::string::npos != test_folder1 ||
42+
std::string::npos != test_folder2 ||
43+
std::string::npos != test_folder3 ||
44+
std::string::npos != test_folder4)
45+
{
46+
return true;
47+
}
48+
49+
return false;
50+
}
51+
52+
}
53+
}
54+
}
55+
56+
#endif

clang-tools-extra/clang-tidy/bsl/NonSafeIntegralTypesAreForbiddenCheck.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@ void NonSafeIntegralTypesAreForbiddenCheck::check(const MatchFinder::MatchResult
3232
if (name == "char")
3333
return;
3434

35+
if (auto const *parent = VD->getParentFunctionOrMethod()) {
36+
if (auto const *FD = dyn_cast<FunctionDecl>(parent)) {
37+
if (FD->isExternC())
38+
return;
39+
40+
if (FD->getNameAsString() == "main")
41+
return;
42+
}
43+
}
44+
3545
FullSourceLoc FullLocation = Result.Context->getFullLoc(VD->getBeginLoc());
3646
if (auto const File = FullLocation.getFileEntry()) {
3747
auto const filename{File->tryGetRealPathName()};

clang-tools-extra/clang-tidy/bsl/UserDefinedTypeNamesMatchHeaderNameCheck.cpp

+1-5
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ void UserDefinedTypeNamesMatchHeaderNameCheck::check(const MatchFinder::MatchRes
3838
if (isa<NamespaceDecl>(D) ||
3939
isa<FunctionDecl>(D) ||
4040
isa<FunctionTemplateDecl>(D) ||
41+
isa<TypeAliasDecl>(D) ||
4142
isa<VarDecl>(D) ||
4243
isa<VarTemplateDecl>(D) ||
4344
isa<FieldDecl>(D) ||
@@ -96,11 +97,6 @@ void UserDefinedTypeNamesMatchHeaderNameCheck::check(const MatchFinder::MatchRes
9697
if (name == filename)
9798
return;
9899

99-
if (isa<TypeAliasDecl>(D)) {
100-
if (name == filename + "_t")
101-
return;
102-
}
103-
104100
diag(D->getBeginLoc(), "User-defined types must have the same name as the header file they are "
105101
"defined in. Either name the %0 '%1', or name the header '%2'")
106102
<< D->getDeclKindName() << filename << name;

0 commit comments

Comments
 (0)