11 #include "clang/Frontend/CompilerInstance.h"
12 #include "clang/Lex/Preprocessor.h"
13 #include "llvm/Support/ConvertUTF.h"
15 using namespace clang;
19 bool HonorLineBreaks =
true) {
20 const char *CurPtr = Buffer.begin();
35 SmallVector<BidiChar> BidiContexts;
42 while (CurPtr < Buffer.end()) {
43 unsigned char C = *CurPtr;
47 (
C == 0xA ||
C == 0xD || (0x1C <=
C &&
C <= 0x1E) ||
C == 0x85);
48 bool IsSegmentSep = (
C == 0x9 ||
C == 0xB ||
C == 0x1F);
49 if (IsParagrapSep || IsSegmentSep)
53 llvm::UTF32 CodePoint;
54 llvm::ConversionResult Result = llvm::convertUTF8Sequence(
55 (
const llvm::UTF8 **)&CurPtr, (
const llvm::UTF8 *)Buffer.end(),
56 &CodePoint, llvm::strictConversion);
59 if (Result != llvm::conversionOK) {
65 if (CodePoint == RLO || CodePoint == RLE || CodePoint == LRO ||
67 BidiContexts.push_back(PDF);
69 else if (CodePoint == PDF) {
70 if (!BidiContexts.empty() && BidiContexts.back() == PDF)
71 BidiContexts.pop_back();
74 else if (CodePoint == RLI || CodePoint == LRI || CodePoint == FSI)
75 BidiContexts.push_back(PDI);
77 else if (CodePoint == PDI) {
78 auto R = std::find(BidiContexts.rbegin(), BidiContexts.rend(), PDI);
79 if (R != BidiContexts.rend())
80 BidiContexts.resize(BidiContexts.rend() - R - 1);
83 else if (CodePoint == PS)
86 return !BidiContexts.empty();
90 :
public CommentHandler {
93 llvm::Optional<std::string> User)
100 PP.getSourceManager(),
PP.getLangOpts());
105 "comment contains misleading bidirectional Unicode characters");
117 *this, Context->getOptions().User)) {}
122 const SourceManager &SM, Preprocessor *
PP, Preprocessor *ModuleExpanderPP) {
123 PP->addCommentHandler(Handler.get());
127 const ast_matchers::MatchFinder::MatchResult &Result) {
128 if (
const auto *SL = Result.Nodes.getNodeAs<StringLiteral>(
"strlit")) {
129 StringRef Literal = SL->getBytes();
131 diag(SL->getBeginLoc(),
"string literal contains misleading "
132 "bidirectional Unicode characters");
137 ast_matchers::MatchFinder *Finder) {
138 Finder->addMatcher(ast_matchers::stringLiteral().bind(
"strlit"),
this);