forked from OSchip/llvm-project
126 lines
4.3 KiB
C++
126 lines
4.3 KiB
C++
//===--- LexerUtils.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 "LexerUtils.h"
|
|
|
|
namespace clang {
|
|
namespace tidy {
|
|
namespace utils {
|
|
namespace lexer {
|
|
|
|
Token getPreviousToken(SourceLocation Location, const SourceManager &SM,
|
|
const LangOptions &LangOpts, bool SkipComments) {
|
|
Token Token;
|
|
Token.setKind(tok::unknown);
|
|
Location = Location.getLocWithOffset(-1);
|
|
auto StartOfFile = SM.getLocForStartOfFile(SM.getFileID(Location));
|
|
while (Location != StartOfFile) {
|
|
Location = Lexer::GetBeginningOfToken(Location, SM, LangOpts);
|
|
if (!Lexer::getRawToken(Location, Token, SM, LangOpts) &&
|
|
(!SkipComments || !Token.is(tok::comment))) {
|
|
break;
|
|
}
|
|
Location = Location.getLocWithOffset(-1);
|
|
}
|
|
return Token;
|
|
}
|
|
|
|
SourceLocation findPreviousTokenStart(SourceLocation Start,
|
|
const SourceManager &SM,
|
|
const LangOptions &LangOpts) {
|
|
if (Start.isInvalid() || Start.isMacroID())
|
|
return SourceLocation();
|
|
|
|
SourceLocation BeforeStart = Start.getLocWithOffset(-1);
|
|
if (BeforeStart.isInvalid() || BeforeStart.isMacroID())
|
|
return SourceLocation();
|
|
|
|
return Lexer::GetBeginningOfToken(BeforeStart, SM, LangOpts);
|
|
}
|
|
|
|
SourceLocation findPreviousTokenKind(SourceLocation Start,
|
|
const SourceManager &SM,
|
|
const LangOptions &LangOpts,
|
|
tok::TokenKind TK) {
|
|
while (true) {
|
|
SourceLocation L = findPreviousTokenStart(Start, SM, LangOpts);
|
|
if (L.isInvalid() || L.isMacroID())
|
|
return SourceLocation();
|
|
|
|
Token T;
|
|
if (Lexer::getRawToken(L, T, SM, LangOpts, /*IgnoreWhiteSpace=*/true))
|
|
return SourceLocation();
|
|
|
|
if (T.is(TK))
|
|
return T.getLocation();
|
|
|
|
Start = L;
|
|
}
|
|
}
|
|
|
|
SourceLocation findNextTerminator(SourceLocation Start, const SourceManager &SM,
|
|
const LangOptions &LangOpts) {
|
|
return findNextAnyTokenKind(Start, SM, LangOpts, tok::comma, tok::semi);
|
|
}
|
|
|
|
bool rangeContainsExpansionsOrDirectives(SourceRange Range,
|
|
const SourceManager &SM,
|
|
const LangOptions &LangOpts) {
|
|
assert(Range.isValid() && "Invalid Range for relexing provided");
|
|
SourceLocation Loc = Range.getBegin();
|
|
|
|
while (Loc < Range.getEnd()) {
|
|
if (Loc.isMacroID())
|
|
return true;
|
|
|
|
llvm::Optional<Token> Tok = Lexer::findNextToken(Loc, SM, LangOpts);
|
|
|
|
if (!Tok)
|
|
return true;
|
|
|
|
if (Tok->is(tok::hash))
|
|
return true;
|
|
|
|
Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts).getLocWithOffset(1);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
llvm::Optional<Token> getConstQualifyingToken(CharSourceRange Range,
|
|
const ASTContext &Context,
|
|
const SourceManager &SM) {
|
|
std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Range.getBegin());
|
|
StringRef File = SM.getBufferData(LocInfo.first);
|
|
Lexer RawLexer(SM.getLocForStartOfFile(LocInfo.first), Context.getLangOpts(),
|
|
File.begin(), File.data() + LocInfo.second, File.end());
|
|
llvm::Optional<Token> FirstConstTok;
|
|
Token LastTokInRange;
|
|
Token Tok;
|
|
while (!RawLexer.LexFromRawLexer(Tok) &&
|
|
Range.getEnd() != Tok.getLocation() &&
|
|
!SM.isBeforeInTranslationUnit(Range.getEnd(), Tok.getLocation())) {
|
|
if (Tok.is(tok::raw_identifier)) {
|
|
IdentifierInfo &Info = Context.Idents.get(
|
|
StringRef(SM.getCharacterData(Tok.getLocation()), Tok.getLength()));
|
|
Tok.setIdentifierInfo(&Info);
|
|
Tok.setKind(Info.getTokenID());
|
|
}
|
|
if (Tok.is(tok::kw_const) && !FirstConstTok)
|
|
FirstConstTok = Tok;
|
|
LastTokInRange = Tok;
|
|
}
|
|
// If the last token in the range is a `const`, then it const qualifies the
|
|
// type. Otherwise, the first `const` token, if any, is the qualifier.
|
|
return LastTokInRange.is(tok::kw_const) ? LastTokInRange : FirstConstTok;
|
|
}
|
|
} // namespace lexer
|
|
} // namespace utils
|
|
} // namespace tidy
|
|
} // namespace clang
|