aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSergio Martins <iamsergio@gmail.com>2017-12-03 18:05:38 +0000
committerSergio Martins <iamsergio@gmail.com>2017-12-03 18:10:19 +0000
commit49825f06fda23989961cfa41cd1576b58e2bcc5d (patch)
tree35edd71235740694335a2e522734bdb218cb1193 /src
parent41e79d655cd7133459706e17ab8cf794ce4e5251 (diff)
Don't try to fix strings with escaped bytes
While QString::fromUtf8("ö") is equal to QString::fromUtf8("\xc3\xb6"), QStringLiteral("ö") is not equal to QStringLiteral("\xc3\xb6") because the escaped bytes won't be converted to utf-16 but instead used directly as is. CCMAIL: faure@kde.org CCMAIL: montel@kde.org
Diffstat (limited to 'src')
-rw-r--r--src/Utils.cpp22
-rw-r--r--src/Utils.h5
-rw-r--r--src/checks/level2/qstring-allocations.cpp10
3 files changed, 36 insertions, 1 deletions
diff --git a/src/Utils.cpp b/src/Utils.cpp
index 8ceb6e95..5d0a1500 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -28,6 +28,7 @@
#include "ContextUtils.h"
#include "StmtBodyRange.h"
+#include <clang/AST/Expr.h>
#include <clang/AST/StmtCXX.h>
#include <clang/AST/ASTContext.h>
#include <clang/AST/DeclCXX.h>
@@ -885,3 +886,24 @@ SourceLocation Utils::locForNextToken(SourceLocation loc, const clang::SourceMan
return loc.getLocWithOffset(Tok.getLength() + NumWhitespaceChars);
}
+
+bool Utils::literalContainsEscapedBytes(StringLiteral *lt, const SourceManager &sm, const LangOptions &lo)
+{
+ if (!lt)
+ return false;
+
+ // The AST doesn't have the info, we need to ask the Lexer
+ SourceRange sr = lt->getSourceRange();
+ CharSourceRange cr = Lexer::getAsCharRange(sr, sm, lo);
+ const StringRef str = Lexer::getSourceText(cr, sm, lo);
+
+ for (int i = 0, size = str.size(); i < size - 1; ++i) {
+ if (str[i] == '\\') {
+ auto next = str[i+1];
+ if (next == 'U' || next == 'u' || next == 'x' || std::isdigit(next))
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/src/Utils.h b/src/Utils.h
index 740d47c4..6aabee32 100644
--- a/src/Utils.h
+++ b/src/Utils.h
@@ -273,6 +273,11 @@ namespace Utils {
CLAZYLIB_EXPORT clang::SourceLocation locForNextToken(clang::SourceLocation loc,
const clang::SourceManager &sm,
const clang::LangOptions &lo);
+
+ /**
+ * Returns true if the string literal contains escaped bytes, such as \x12, \123, \u00F6.
+ */
+ bool literalContainsEscapedBytes(clang::StringLiteral *lt, const clang::SourceManager &sm, const clang::LangOptions &lo);
}
#endif
diff --git a/src/checks/level2/qstring-allocations.cpp b/src/checks/level2/qstring-allocations.cpp
index dd0c0bef..298c8170 100644
--- a/src/checks/level2/qstring-allocations.cpp
+++ b/src/checks/level2/qstring-allocations.cpp
@@ -279,14 +279,17 @@ void QStringAllocations::VisitCtor(Stmt *stm)
vector<FixItHint> QStringAllocations::fixItReplaceWordWithWord(clang::Stmt *begin, const string &replacement, const string &replacee, int fixitType)
{
+ StringLiteral *lt = stringLiteralForCall(begin);
if (replacee == "QLatin1String") {
- StringLiteral *lt = stringLiteralForCall(begin);
if (lt && !Utils::isAscii(lt)) {
emitWarning(lt->getLocStart(), "Don't use QLatin1String with non-latin1 literals");
return {};
}
}
+ if (Utils::literalContainsEscapedBytes(lt, sm(), lo()))
+ return {};
+
vector<FixItHint> fixits;
FixItHint fixit = FixItUtils::fixItReplaceWordWithWord(&m_astContext, begin, replacement, replacee);
if (fixit.isNull()) {
@@ -387,6 +390,8 @@ std::vector<FixItHint> QStringAllocations::fixItReplaceFromLatin1OrFromUtf8(Call
StringLiteral *literal = stringLiteralForCall(callExpr);
if (literal) {
+ if (Utils::literalContainsEscapedBytes(literal, sm(), lo()))
+ return {};
if (!Utils::isAscii(literal)) {
// QString::fromLatin1() to QLatin1String() is fine
// QString::fromUtf8() to QStringLiteral() is fine
@@ -426,6 +431,9 @@ std::vector<FixItHint> QStringAllocations::fixItRawLiteral(clang::StringLiteral
if (start.isMacroID()) {
queueManualFixitWarning(start, CharPtrAllocations, "Can't use QStringLiteral in macro..");
} else {
+ if (Utils::literalContainsEscapedBytes(lt, sm(), lo()))
+ return {};
+
string revisedReplacement = lt->getLength() == 0 ? "QLatin1String" : replacement; // QLatin1String("") is better than QStringLiteral("")
if (revisedReplacement == "QStringLiteral" && lt->getLocStart().isMacroID()) {
queueManualFixitWarning(lt->getLocStart(), CharPtrAllocations, "Can't use QStringLiteral in macro...");