Hi,
New iteration where char16_t is taken care of.
//Anders
________________________________________
Från: Jordan Rose [[email protected]]
Skickat: den 22 oktober 2013 21:08
Till: Daniel Marjamäki
Cc: Richard Smith; Anders Rönnholm; cfe commits
Ämne: Re: [PATCH] [StaticAnalyzer] New checker StringPlusChar
On Oct 21, 2013, at 22:39 , Daniel Marjamäki <[email protected]>
wrote:
>
> Hello!
>
> There was a thread about the new checker StringPlusChar:
> http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20130930/thread.html#89826
>
> I wonder what we need to do to make you happy?
>
> My last response is here:
> http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20131007/090324.html
>
> About this:
>> The idea and the patch both seem good to me, other than the diagnostic
>> wording. Perhaps something like:
>> adding %0 to %1 does not append to the string
>
> The latest patch from Anders fixes this, it writes such messages:
>
> char *str = 0;
> char *str2 = str + 'c'; // expected-warning {{adding 'char' to a string
> pointer does not append to the string}} expected-note {{use array indexing to
> silence this warning}}
I'm sorry, this still doesn't include the type:
// clang++ -fsyntax-only -std=c++11
char *str = 0;
char *str2 = str + u'a'; // expected-warning {{adding 'char16_t' to a string
pointer does not append to the string}}
Jordan
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp (revision 193226)
+++ lib/Sema/SemaExpr.cpp (working copy)
@@ -6971,6 +6971,55 @@
Self.Diag(OpLoc, diag::note_string_plus_int_silence);
}
+/// \brief Emit a warning when adding a char literal to a string.
+static void diagnoseStringPlusChar(Sema &Self, SourceLocation OpLoc,
+ Expr *LHSExpr, Expr *RHSExpr) {
+ const DeclRefExpr *StringRefExpr =
+ dyn_cast<DeclRefExpr>(LHSExpr->IgnoreImpCasts());
+ const CharacterLiteral *CharExpr =
+ dyn_cast<CharacterLiteral>(RHSExpr->IgnoreImpCasts());
+ if (!StringRefExpr) {
+ StringRefExpr = dyn_cast<DeclRefExpr>(RHSExpr->IgnoreImpCasts());
+ CharExpr = dyn_cast<CharacterLiteral>(LHSExpr->IgnoreImpCasts());
+ }
+
+ if (!CharExpr || !StringRefExpr)
+ return;
+
+ const QualType StringType = StringRefExpr->getType();
+
+ // Return if not a PointerType.
+ if (!StringType->isAnyPointerType())
+ return;
+
+ // Return if not a CharacterType.
+ if (!StringType->getPointeeType()->isAnyCharacterType())
+ return;
+
+ SourceRange DiagRange(LHSExpr->getLocStart(), RHSExpr->getLocEnd());
+ const QualType CharType = CharExpr->getType();
+ if (!CharType->isAnyCharacterType() &&
+ CharType->isIntegerType() &&
+ CharExpr->getValue() <= UCHAR_MAX) {
+ Self.Diag(OpLoc, diag::warn_string_plus_char)
+ << DiagRange << Self.getASTContext().CharTy;
+ } else {
+ Self.Diag(OpLoc, diag::warn_string_plus_char)
+ << DiagRange << CharExpr->getType();
+ }
+
+ // Only print a fixit for str + char, not for char + str.
+ if (isa<CharacterLiteral>(RHSExpr->IgnoreImpCasts())) {
+ SourceLocation EndLoc = Self.PP.getLocForEndOfToken(RHSExpr->getLocEnd());
+ Self.Diag(OpLoc, diag::note_string_plus_char_silence)
+ << FixItHint::CreateInsertion(LHSExpr->getLocStart(), "&")
+ << FixItHint::CreateReplacement(SourceRange(OpLoc), "[")
+ << FixItHint::CreateInsertion(EndLoc, "]");
+ } else {
+ Self.Diag(OpLoc, diag::note_string_plus_char_silence);
+ }
+}
+
/// \brief Emit error when two pointers are incompatible.
static void diagnosePointerIncompatibility(Sema &S, SourceLocation Loc,
Expr *LHSExpr, Expr *RHSExpr) {
@@ -6997,9 +7046,11 @@
if (LHS.isInvalid() || RHS.isInvalid())
return QualType();
- // Diagnose "string literal" '+' int.
- if (Opc == BO_Add)
+ // Diagnose "string literal" '+' int and string '+' "char literal".
+ if (Opc == BO_Add) {
diagnoseStringPlusInt(*this, Loc, LHS.get(), RHS.get());
+ diagnoseStringPlusChar(*this, Loc, LHS.get(), RHS.get());
+ }
// handle the common case first (both operands are arithmetic).
if (!compType.isNull() && compType->isArithmeticType()) {
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td (revision 193226)
+++ include/clang/Basic/DiagnosticSemaKinds.td (working copy)
@@ -4294,6 +4294,12 @@
def note_string_plus_int_silence : Note<
"use array indexing to silence this warning">;
+def warn_string_plus_char : Warning<
+ "adding %0 to a string pointer does not append to the string">,
+ InGroup<StringPlusChar>;
+def note_string_plus_char_silence : Note<
+ "use array indexing to silence this warning">;
+
def warn_sizeof_array_param : Warning<
"sizeof on array function parameter will return size of %0 instead of %1">,
InGroup<SizeofArrayArgument>;
Index: include/clang/Basic/DiagnosticGroups.td
===================================================================
--- include/clang/Basic/DiagnosticGroups.td (revision 193226)
+++ include/clang/Basic/DiagnosticGroups.td (working copy)
@@ -269,6 +269,7 @@
def StaticFloatInit : DiagGroup<"static-float-init", [GNUStaticFloatInit]>;
def GNUStatementExpression : DiagGroup<"gnu-statement-expression">;
def StringPlusInt : DiagGroup<"string-plus-int">;
+def StringPlusChar : DiagGroup<"string-plus-char">;
def StrncatSize : DiagGroup<"strncat-size">;
def TautologicalOutOfRangeCompare : DiagGroup<"tautological-constant-out-of-range-compare">;
def TautologicalCompare : DiagGroup<"tautological-compare",
Index: test/SemaCXX/string-plus-char.cpp
===================================================================
--- test/SemaCXX/string-plus-char.cpp (revision 0)
+++ test/SemaCXX/string-plus-char.cpp (working copy)
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+
+class A {
+public:
+ A(): str() { }
+ A(const char *p) { }
+ A(char *p) : str(p + 'a') { } // expected-warning {{adding 'char' to a string pointer does not append to the string}} expected-note {{use array indexing to silence this warning}}
+ A& operator+(const char *p) { return *this; }
+ A& operator+(char ch) { return *this; }
+ char * str;
+};
+
+void f(const char *s) {
+ A a = s + 'a'; // // expected-warning {{adding 'char' to a string pointer does not append to the string}} expected-note {{use array indexing to silence this warning}}
+ a = a + s + 'b'; // no-warning
+
+ char *str = 0;
+ char *str2 = str + 'c'; // expected-warning {{adding 'char' to a string pointer does not append to the string}} expected-note {{use array indexing to silence this warning}}
+
+ const char *constStr = s + 'c'; // expected-warning {{adding 'char' to a string pointer does not append to the string}} expected-note {{use array indexing to silence this warning}}
+
+ str = 'c' + str;// expected-warning {{adding 'char' to a string pointer does not append to the string}} expected-note {{use array indexing to silence this warning}}
+
+ wchar_t *wstr;
+ wstr = wstr + L'c'; // expected-warning {{adding 'wchar_t' to a string pointer does not append to the string}} expected-note {{use array indexing to silence this warning}}
+ str2 = str + u'a'; // expected-warning {{adding 'char16_t' to a string pointer does not append to the string}} expected-note {{use array indexing to silence this warning}}
+
+ // no-warning
+ char c = 'c';
+ str = str + c;
+ str = c + str;
+}
Index: test/Sema/string-plus-char.c
===================================================================
--- test/Sema/string-plus-char.c (revision 0)
+++ test/Sema/string-plus-char.c (working copy)
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+void f(const char *s) {
+ char *str = 0;
+ char *str2 = str + 'c'; // expected-warning {{adding 'char' to a string pointer does not append to the string}} expected-note {{use array indexing to silence this warning}}
+
+ const char *constStr = s + 'c'; // expected-warning {{adding 'char' to a string pointer does not append to the string}} expected-note {{use array indexing to silence this warning}}
+
+ str = 'c' + str;// expected-warning {{adding 'char' to a string pointer does not append to the string}} expected-note {{use array indexing to silence this warning}}
+
+ // no-warning
+ char c = 'c';
+ str = str + c;
+ str = c + str;
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits