Skip to content

Commit 50f9838

Browse files
committed
merge main into amd-staging
Change-Id: I490f91e99836b99e6c26269218e0c2492162493d
2 parents 0364034 + a3bb9c2 commit 50f9838

File tree

86 files changed

+3508
-866
lines changed

Some content is hidden

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

86 files changed

+3508
-866
lines changed

clang-tools-extra/clang-tidy/readability/AvoidReturnWithVoidValueCheck.cpp

+33-11
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,18 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "AvoidReturnWithVoidValueCheck.h"
10-
#include "clang/AST/Stmt.h"
11-
#include "clang/ASTMatchers/ASTMatchFinder.h"
12-
#include "clang/ASTMatchers/ASTMatchers.h"
10+
#include "../utils/BracesAroundStatement.h"
11+
#include "../utils/LexerUtils.h"
1312

1413
using namespace clang::ast_matchers;
1514

1615
namespace clang::tidy::readability {
1716

18-
static constexpr auto IgnoreMacrosName = "IgnoreMacros";
19-
static constexpr auto IgnoreMacrosDefault = true;
17+
static constexpr char IgnoreMacrosName[] = "IgnoreMacros";
18+
static const bool IgnoreMacrosDefault = true;
2019

21-
static constexpr auto StrictModeName = "StrictMode";
22-
static constexpr auto StrictModeDefault = true;
20+
static constexpr char StrictModeName[] = "StrictMode";
21+
static const bool StrictModeDefault = true;
2322

2423
AvoidReturnWithVoidValueCheck::AvoidReturnWithVoidValueCheck(
2524
StringRef Name, ClangTidyContext *Context)
@@ -32,7 +31,10 @@ void AvoidReturnWithVoidValueCheck::registerMatchers(MatchFinder *Finder) {
3231
Finder->addMatcher(
3332
returnStmt(
3433
hasReturnValue(allOf(hasType(voidType()), unless(initListExpr()))),
35-
optionally(hasParent(compoundStmt().bind("compound_parent"))))
34+
optionally(hasParent(
35+
compoundStmt(
36+
optionally(hasParent(functionDecl().bind("function_parent"))))
37+
.bind("compound_parent"))))
3638
.bind("void_return"),
3739
this);
3840
}
@@ -42,10 +44,30 @@ void AvoidReturnWithVoidValueCheck::check(
4244
const auto *VoidReturn = Result.Nodes.getNodeAs<ReturnStmt>("void_return");
4345
if (IgnoreMacros && VoidReturn->getBeginLoc().isMacroID())
4446
return;
45-
if (!StrictMode && !Result.Nodes.getNodeAs<CompoundStmt>("compound_parent"))
47+
const auto *SurroundingBlock =
48+
Result.Nodes.getNodeAs<CompoundStmt>("compound_parent");
49+
if (!StrictMode && !SurroundingBlock)
4650
return;
47-
diag(VoidReturn->getBeginLoc(), "return statement within a void function "
48-
"should not have a specified return value");
51+
DiagnosticBuilder Diag = diag(VoidReturn->getBeginLoc(),
52+
"return statement within a void function "
53+
"should not have a specified return value");
54+
const SourceLocation SemicolonPos = utils::lexer::findNextTerminator(
55+
VoidReturn->getEndLoc(), *Result.SourceManager, getLangOpts());
56+
if (SemicolonPos.isInvalid())
57+
return;
58+
if (!SurroundingBlock) {
59+
const auto BraceInsertionHints = utils::getBraceInsertionsHints(
60+
VoidReturn, getLangOpts(), *Result.SourceManager,
61+
VoidReturn->getBeginLoc());
62+
if (BraceInsertionHints)
63+
Diag << BraceInsertionHints.openingBraceFixIt()
64+
<< BraceInsertionHints.closingBraceFixIt();
65+
}
66+
Diag << FixItHint::CreateRemoval(VoidReturn->getReturnLoc());
67+
if (!Result.Nodes.getNodeAs<FunctionDecl>("function_parent") ||
68+
SurroundingBlock->body_back() != VoidReturn)
69+
Diag << FixItHint::CreateInsertion(SemicolonPos.getLocWithOffset(1),
70+
" return;", true);
4971
}
5072

5173
void AvoidReturnWithVoidValueCheck::storeOptions(

clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp

+25-132
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "BracesAroundStatementsCheck.h"
10+
#include "../utils/BracesAroundStatement.h"
1011
#include "../utils/LexerUtils.h"
1112
#include "clang/AST/ASTContext.h"
1213
#include "clang/ASTMatchers/ASTMatchers.h"
@@ -17,12 +18,10 @@ using namespace clang::ast_matchers;
1718
namespace clang::tidy::readability {
1819

1920
static tok::TokenKind getTokenKind(SourceLocation Loc, const SourceManager &SM,
20-
const ASTContext *Context) {
21+
const LangOptions &LangOpts) {
2122
Token Tok;
22-
SourceLocation Beginning =
23-
Lexer::GetBeginningOfToken(Loc, SM, Context->getLangOpts());
24-
const bool Invalid =
25-
Lexer::getRawToken(Beginning, Tok, SM, Context->getLangOpts());
23+
SourceLocation Beginning = Lexer::GetBeginningOfToken(Loc, SM, LangOpts);
24+
const bool Invalid = Lexer::getRawToken(Beginning, Tok, SM, LangOpts);
2625
assert(!Invalid && "Expected a valid token.");
2726

2827
if (Invalid)
@@ -33,64 +32,21 @@ static tok::TokenKind getTokenKind(SourceLocation Loc, const SourceManager &SM,
3332

3433
static SourceLocation
3534
forwardSkipWhitespaceAndComments(SourceLocation Loc, const SourceManager &SM,
36-
const ASTContext *Context) {
35+
const LangOptions &LangOpts) {
3736
assert(Loc.isValid());
3837
for (;;) {
3938
while (isWhitespace(*SM.getCharacterData(Loc)))
4039
Loc = Loc.getLocWithOffset(1);
4140

42-
tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
41+
tok::TokenKind TokKind = getTokenKind(Loc, SM, LangOpts);
4342
if (TokKind != tok::comment)
4443
return Loc;
4544

4645
// Fast-forward current token.
47-
Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
46+
Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts);
4847
}
4948
}
5049

51-
static SourceLocation findEndLocation(const Stmt &S, const SourceManager &SM,
52-
const ASTContext *Context) {
53-
SourceLocation Loc =
54-
utils::lexer::getUnifiedEndLoc(S, SM, Context->getLangOpts());
55-
if (!Loc.isValid())
56-
return Loc;
57-
58-
// Start searching right after S.
59-
Loc = Loc.getLocWithOffset(1);
60-
61-
for (;;) {
62-
assert(Loc.isValid());
63-
while (isHorizontalWhitespace(*SM.getCharacterData(Loc))) {
64-
Loc = Loc.getLocWithOffset(1);
65-
}
66-
67-
if (isVerticalWhitespace(*SM.getCharacterData(Loc))) {
68-
// EOL, insert brace before.
69-
break;
70-
}
71-
tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
72-
if (TokKind != tok::comment) {
73-
// Non-comment token, insert brace before.
74-
break;
75-
}
76-
77-
SourceLocation TokEndLoc =
78-
Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
79-
SourceRange TokRange(Loc, TokEndLoc);
80-
StringRef Comment = Lexer::getSourceText(
81-
CharSourceRange::getTokenRange(TokRange), SM, Context->getLangOpts());
82-
if (Comment.starts_with("/*") && Comment.contains('\n')) {
83-
// Multi-line block comment, insert brace before.
84-
break;
85-
}
86-
// else: Trailing comment, insert brace after the newline.
87-
88-
// Fast-forward current token.
89-
Loc = TokEndLoc;
90-
}
91-
return Loc;
92-
}
93-
9450
BracesAroundStatementsCheck::BracesAroundStatementsCheck(
9551
StringRef Name, ClangTidyContext *Context)
9652
: ClangTidyCheck(Name, Context),
@@ -124,7 +80,7 @@ void BracesAroundStatementsCheck::check(
12480
} else if (const auto *S = Result.Nodes.getNodeAs<DoStmt>("do")) {
12581
checkStmt(Result, S->getBody(), S->getDoLoc(), S->getWhileLoc());
12682
} else if (const auto *S = Result.Nodes.getNodeAs<WhileStmt>("while")) {
127-
SourceLocation StartLoc = findRParenLoc(S, SM, Context);
83+
SourceLocation StartLoc = findRParenLoc(S, SM, Context->getLangOpts());
12884
if (StartLoc.isInvalid())
12985
return;
13086
checkStmt(Result, S->getBody(), StartLoc);
@@ -133,7 +89,7 @@ void BracesAroundStatementsCheck::check(
13389
if (S->isConsteval())
13490
return;
13591

136-
SourceLocation StartLoc = findRParenLoc(S, SM, Context);
92+
SourceLocation StartLoc = findRParenLoc(S, SM, Context->getLangOpts());
13793
if (StartLoc.isInvalid())
13894
return;
13995
if (ForceBracesStmts.erase(S))
@@ -156,7 +112,7 @@ template <typename IfOrWhileStmt>
156112
SourceLocation
157113
BracesAroundStatementsCheck::findRParenLoc(const IfOrWhileStmt *S,
158114
const SourceManager &SM,
159-
const ASTContext *Context) {
115+
const LangOptions &LangOpts) {
160116
// Skip macros.
161117
if (S->getBeginLoc().isMacroID())
162118
return {};
@@ -170,14 +126,14 @@ BracesAroundStatementsCheck::findRParenLoc(const IfOrWhileStmt *S,
170126
}
171127

172128
SourceLocation PastCondEndLoc =
173-
Lexer::getLocForEndOfToken(CondEndLoc, 0, SM, Context->getLangOpts());
129+
Lexer::getLocForEndOfToken(CondEndLoc, 0, SM, LangOpts);
174130
if (PastCondEndLoc.isInvalid())
175131
return {};
176132
SourceLocation RParenLoc =
177-
forwardSkipWhitespaceAndComments(PastCondEndLoc, SM, Context);
133+
forwardSkipWhitespaceAndComments(PastCondEndLoc, SM, LangOpts);
178134
if (RParenLoc.isInvalid())
179135
return {};
180-
tok::TokenKind TokKind = getTokenKind(RParenLoc, SM, Context);
136+
tok::TokenKind TokKind = getTokenKind(RParenLoc, SM, LangOpts);
181137
if (TokKind != tok::r_paren)
182138
return {};
183139
return RParenLoc;
@@ -188,86 +144,23 @@ BracesAroundStatementsCheck::findRParenLoc(const IfOrWhileStmt *S,
188144
bool BracesAroundStatementsCheck::checkStmt(
189145
const MatchFinder::MatchResult &Result, const Stmt *S,
190146
SourceLocation StartLoc, SourceLocation EndLocHint) {
191-
192147
while (const auto *AS = dyn_cast<AttributedStmt>(S))
193148
S = AS->getSubStmt();
194149

195-
const SourceManager &SM = *Result.SourceManager;
196-
const ASTContext *Context = Result.Context;
197-
198-
// 1) If there's a corresponding "else" or "while", the check inserts "} "
199-
// right before that token.
200-
// 2) If there's a multi-line block comment starting on the same line after
201-
// the location we're inserting the closing brace at, or there's a non-comment
202-
// token, the check inserts "\n}" right before that token.
203-
// 3) Otherwise the check finds the end of line (possibly after some block or
204-
// line comments) and inserts "\n}" right before that EOL.
205-
if (!S || isa<CompoundStmt>(S)) {
206-
// Already inside braces.
207-
return false;
208-
}
209-
210-
// When TreeTransform, Stmt in constexpr IfStmt will be transform to NullStmt.
211-
// This NullStmt can be detected according to beginning token.
212-
const SourceLocation StmtBeginLoc = S->getBeginLoc();
213-
if (isa<NullStmt>(S) && StmtBeginLoc.isValid() &&
214-
getTokenKind(StmtBeginLoc, SM, Context) == tok::l_brace)
215-
return false;
216-
217-
if (StartLoc.isInvalid())
218-
return false;
219-
220-
// Convert StartLoc to file location, if it's on the same macro expansion
221-
// level as the start of the statement. We also need file locations for
222-
// Lexer::getLocForEndOfToken working properly.
223-
StartLoc = Lexer::makeFileCharRange(
224-
CharSourceRange::getCharRange(StartLoc, S->getBeginLoc()), SM,
225-
Context->getLangOpts())
226-
.getBegin();
227-
if (StartLoc.isInvalid())
228-
return false;
229-
StartLoc =
230-
Lexer::getLocForEndOfToken(StartLoc, 0, SM, Context->getLangOpts());
231-
232-
// StartLoc points at the location of the opening brace to be inserted.
233-
SourceLocation EndLoc;
234-
std::string ClosingInsertion;
235-
if (EndLocHint.isValid()) {
236-
EndLoc = EndLocHint;
237-
ClosingInsertion = "} ";
238-
} else {
239-
EndLoc = findEndLocation(*S, SM, Context);
240-
ClosingInsertion = "\n}";
241-
}
242-
243-
assert(StartLoc.isValid());
244-
245-
// Don't require braces for statements spanning less than certain number of
246-
// lines.
247-
if (ShortStatementLines && !ForceBracesStmts.erase(S)) {
248-
unsigned StartLine = SM.getSpellingLineNumber(StartLoc);
249-
unsigned EndLine = SM.getSpellingLineNumber(EndLoc);
250-
if (EndLine - StartLine < ShortStatementLines)
150+
const auto BraceInsertionHints = utils::getBraceInsertionsHints(
151+
S, Result.Context->getLangOpts(), *Result.SourceManager, StartLoc,
152+
EndLocHint);
153+
if (BraceInsertionHints) {
154+
if (ShortStatementLines && !ForceBracesStmts.erase(S) &&
155+
BraceInsertionHints.resultingCompoundLineExtent(*Result.SourceManager) <
156+
ShortStatementLines)
251157
return false;
158+
auto Diag = diag(BraceInsertionHints.DiagnosticPos,
159+
"statement should be inside braces");
160+
if (BraceInsertionHints.offersFixIts())
161+
Diag << BraceInsertionHints.openingBraceFixIt()
162+
<< BraceInsertionHints.closingBraceFixIt();
252163
}
253-
254-
auto Diag = diag(StartLoc, "statement should be inside braces");
255-
256-
// Change only if StartLoc and EndLoc are on the same macro expansion level.
257-
// This will also catch invalid EndLoc.
258-
// Example: LLVM_DEBUG( for(...) do_something() );
259-
// In this case fix-it cannot be provided as the semicolon which is not
260-
// visible here is part of the macro. Adding braces here would require adding
261-
// another semicolon.
262-
if (Lexer::makeFileCharRange(
263-
CharSourceRange::getTokenRange(SourceRange(
264-
SM.getSpellingLoc(StartLoc), SM.getSpellingLoc(EndLoc))),
265-
SM, Context->getLangOpts())
266-
.isInvalid())
267-
return false;
268-
269-
Diag << FixItHint::CreateInsertion(StartLoc, " {")
270-
<< FixItHint::CreateInsertion(EndLoc, ClosingInsertion);
271164
return true;
272165
}
273166

clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class BracesAroundStatementsCheck : public ClangTidyCheck {
5252
SourceLocation EndLocHint = SourceLocation());
5353
template <typename IfOrWhileStmt>
5454
SourceLocation findRParenLoc(const IfOrWhileStmt *S, const SourceManager &SM,
55-
const ASTContext *Context);
55+
const LangOptions &LangOpts);
5656
std::optional<TraversalKind> getCheckTraversalKind() const override {
5757
return TK_IgnoreUnlessSpelledInSource;
5858
}

0 commit comments

Comments
 (0)