Skip to content

Commit 0b8fc2c

Browse files
author
Artem Gindinson
committed
Merge from 'main' to 'sycl-web' (#10)
CONFLICT (content): Merge conflict in clang/lib/Basic/Targets.cpp
2 parents 52fea20 + 8fbfc92 commit 0b8fc2c

File tree

121 files changed

+1710
-879
lines changed

Some content is hidden

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

121 files changed

+1710
-879
lines changed

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

Lines changed: 29 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "BracesAroundStatementsCheck.h"
10+
#include "../utils/LexerUtils.h"
1011
#include "clang/AST/ASTContext.h"
1112
#include "clang/ASTMatchers/ASTMatchers.h"
1213
#include "clang/Lex/Lexer.h"
@@ -16,10 +17,9 @@ using namespace clang::ast_matchers;
1617
namespace clang {
1718
namespace tidy {
1819
namespace readability {
19-
namespace {
2020

21-
tok::TokenKind getTokenKind(SourceLocation Loc, const SourceManager &SM,
22-
const ASTContext *Context) {
21+
static tok::TokenKind getTokenKind(SourceLocation Loc, const SourceManager &SM,
22+
const ASTContext *Context) {
2323
Token Tok;
2424
SourceLocation Beginning =
2525
Lexer::GetBeginningOfToken(Loc, SM, Context->getLangOpts());
@@ -33,9 +33,9 @@ tok::TokenKind getTokenKind(SourceLocation Loc, const SourceManager &SM,
3333
return Tok.getKind();
3434
}
3535

36-
SourceLocation forwardSkipWhitespaceAndComments(SourceLocation Loc,
37-
const SourceManager &SM,
38-
const ASTContext *Context) {
36+
static SourceLocation
37+
forwardSkipWhitespaceAndComments(SourceLocation Loc, const SourceManager &SM,
38+
const ASTContext *Context) {
3939
assert(Loc.isValid());
4040
for (;;) {
4141
while (isWhitespace(*SM.getCharacterData(Loc)))
@@ -50,31 +50,15 @@ SourceLocation forwardSkipWhitespaceAndComments(SourceLocation Loc,
5050
}
5151
}
5252

53-
SourceLocation findEndLocation(SourceLocation LastTokenLoc,
54-
const SourceManager &SM,
55-
const ASTContext *Context) {
53+
static SourceLocation findEndLocation(const Stmt &S, const SourceManager &SM,
54+
const ASTContext *Context) {
5655
SourceLocation Loc =
57-
Lexer::GetBeginningOfToken(LastTokenLoc, SM, Context->getLangOpts());
58-
// Loc points to the beginning of the last (non-comment non-ws) token
59-
// before end or ';'.
60-
assert(Loc.isValid());
61-
bool SkipEndWhitespaceAndComments = true;
62-
tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
63-
if (TokKind == tok::NUM_TOKENS || TokKind == tok::semi ||
64-
TokKind == tok::r_brace) {
65-
// If we are at ";" or "}", we found the last token. We could use as well
66-
// `if (isa<NullStmt>(S))`, but it wouldn't work for nested statements.
67-
SkipEndWhitespaceAndComments = false;
68-
}
56+
utils::lexer::getUnifiedEndLoc(S, SM, Context->getLangOpts());
57+
if (!Loc.isValid())
58+
return Loc;
6959

70-
Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
71-
// Loc points past the last token before end or after ';'.
72-
if (SkipEndWhitespaceAndComments) {
73-
Loc = forwardSkipWhitespaceAndComments(Loc, SM, Context);
74-
tok::TokenKind TokKind = getTokenKind(Loc, SM, Context);
75-
if (TokKind == tok::semi)
76-
Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, Context->getLangOpts());
77-
}
60+
// Start searching right after S.
61+
Loc = Loc.getLocWithOffset(1);
7862

7963
for (;;) {
8064
assert(Loc.isValid());
@@ -109,8 +93,6 @@ SourceLocation findEndLocation(SourceLocation LastTokenLoc,
10993
return Loc;
11094
}
11195

112-
} // namespace
113-
11496
BracesAroundStatementsCheck::BracesAroundStatementsCheck(
11597
StringRef Name, ClangTidyContext *Context)
11698
: ClangTidyCheck(Name, Context),
@@ -224,13 +206,6 @@ bool BracesAroundStatementsCheck::checkStmt(
224206
const SourceManager &SM = *Result.SourceManager;
225207
const ASTContext *Context = Result.Context;
226208

227-
// Treat macros.
228-
CharSourceRange FileRange = Lexer::makeFileCharRange(
229-
CharSourceRange::getTokenRange(S->getSourceRange()), SM,
230-
Context->getLangOpts());
231-
if (FileRange.isInvalid())
232-
return false;
233-
234209
// Convert InitialLoc to file location, if it's on the same macro expansion
235210
// level as the start of the statement. We also need file locations for
236211
// Lexer::getLocForEndOfToken working properly.
@@ -250,13 +225,12 @@ bool BracesAroundStatementsCheck::checkStmt(
250225
EndLoc = EndLocHint;
251226
ClosingInsertion = "} ";
252227
} else {
253-
const auto FREnd = FileRange.getEnd().getLocWithOffset(-1);
254-
EndLoc = findEndLocation(FREnd, SM, Context);
228+
EndLoc = findEndLocation(*S, SM, Context);
255229
ClosingInsertion = "\n}";
256230
}
257231

258232
assert(StartLoc.isValid());
259-
assert(EndLoc.isValid());
233+
260234
// Don't require braces for statements spanning less than certain number of
261235
// lines.
262236
if (ShortStatementLines && !ForceBracesStmts.erase(S)) {
@@ -267,6 +241,20 @@ bool BracesAroundStatementsCheck::checkStmt(
267241
}
268242

269243
auto Diag = diag(StartLoc, "statement should be inside braces");
244+
245+
// Change only if StartLoc and EndLoc are on the same macro expansion level.
246+
// This will also catch invalid EndLoc.
247+
// Example: LLVM_DEBUG( for(...) do_something() );
248+
// In this case fix-it cannot be provided as the semicolon which is not
249+
// visible here is part of the macro. Adding braces here would require adding
250+
// another semicolon.
251+
if (Lexer::makeFileCharRange(
252+
CharSourceRange::getTokenRange(SourceRange(
253+
SM.getSpellingLoc(StartLoc), SM.getSpellingLoc(EndLoc))),
254+
SM, Context->getLangOpts())
255+
.isInvalid())
256+
return false;
257+
270258
Diag << FixItHint::CreateInsertion(StartLoc, " {")
271259
<< FixItHint::CreateInsertion(EndLoc, ClosingInsertion);
272260
return true;

clang-tools-extra/clang-tidy/utils/LexerUtils.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "LexerUtils.h"
10+
#include "clang/AST/AST.h"
1011
#include "clang/Basic/SourceManager.h"
1112

1213
namespace clang {
@@ -148,6 +149,70 @@ llvm::Optional<Token> getQualifyingToken(tok::TokenKind TK,
148149
return LastMatchAfterTemplate != None ? LastMatchAfterTemplate
149150
: LastMatchBeforeTemplate;
150151
}
152+
153+
static bool breakAndReturnEnd(const Stmt &S) {
154+
return isa<CompoundStmt, DeclStmt, NullStmt>(S);
155+
}
156+
157+
static bool breakAndReturnEndPlus1Token(const Stmt &S) {
158+
return isa<Expr, DoStmt, ReturnStmt, BreakStmt, ContinueStmt, GotoStmt, SEHLeaveStmt>(S);
159+
}
160+
161+
// Given a Stmt which does not include it's semicolon this method returns the
162+
// SourceLocation of the semicolon.
163+
static SourceLocation getSemicolonAfterStmtEndLoc(const SourceLocation &EndLoc,
164+
const SourceManager &SM,
165+
const LangOptions &LangOpts) {
166+
167+
if (EndLoc.isMacroID()) {
168+
// Assuming EndLoc points to a function call foo within macro F.
169+
// This method is supposed to return location of the semicolon within
170+
// those macro arguments:
171+
// F ( foo() ; )
172+
// ^ EndLoc ^ SpellingLoc ^ next token of SpellingLoc
173+
const SourceLocation SpellingLoc = SM.getSpellingLoc(EndLoc);
174+
Optional<Token> NextTok =
175+
findNextTokenSkippingComments(SpellingLoc, SM, LangOpts);
176+
177+
// Was the next token found successfully?
178+
// All macro issues are simply resolved by ensuring it's a semicolon.
179+
if (NextTok && NextTok->is(tok::TokenKind::semi)) {
180+
// Ideally this would return `F` with spelling location `;` (NextTok)
181+
// following the examle above. For now simply return NextTok location.
182+
return NextTok->getLocation();
183+
}
184+
185+
// Fallthrough to 'normal handling'.
186+
// F ( foo() ) ;
187+
// ^ EndLoc ^ SpellingLoc ) ^ next token of EndLoc
188+
}
189+
190+
Optional<Token> NextTok = findNextTokenSkippingComments(EndLoc, SM, LangOpts);
191+
192+
// Testing for semicolon again avoids some issues with macros.
193+
if (NextTok && NextTok->is(tok::TokenKind::semi))
194+
return NextTok->getLocation();
195+
196+
return SourceLocation();
197+
}
198+
199+
SourceLocation getUnifiedEndLoc(const Stmt &S, const SourceManager &SM,
200+
const LangOptions &LangOpts) {
201+
202+
const Stmt *LastChild = &S;
203+
while (!LastChild->children().empty() && !breakAndReturnEnd(*LastChild) &&
204+
!breakAndReturnEndPlus1Token(*LastChild)) {
205+
for (const Stmt *Child : LastChild->children())
206+
LastChild = Child;
207+
}
208+
209+
if (!breakAndReturnEnd(*LastChild) &&
210+
breakAndReturnEndPlus1Token(*LastChild))
211+
return getSemicolonAfterStmtEndLoc(S.getEndLoc(), SM, LangOpts);
212+
213+
return S.getEndLoc();
214+
}
215+
151216
} // namespace lexer
152217
} // namespace utils
153218
} // namespace tidy

clang-tools-extra/clang-tidy/utils/LexerUtils.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
#include "clang/Lex/Lexer.h"
1515

1616
namespace clang {
17+
18+
class Stmt;
19+
1720
namespace tidy {
1821
namespace utils {
1922
namespace lexer {
@@ -104,6 +107,11 @@ llvm::Optional<Token> getQualifyingToken(tok::TokenKind TK,
104107
const ASTContext &Context,
105108
const SourceManager &SM);
106109

110+
/// Stmt->getEndLoc does not always behave the same way depending on Token type.
111+
/// See implementation for exceptions.
112+
SourceLocation getUnifiedEndLoc(const Stmt &S, const SourceManager &SM,
113+
const LangOptions &LangOpts);
114+
107115
} // namespace lexer
108116
} // namespace utils
109117
} // namespace tidy

0 commit comments

Comments
 (0)