inclyc updated this revision to Diff 449517. inclyc added a comment. .
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D130906/new/ https://reviews.llvm.org/D130906 Files: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaChecking.cpp clang/test/SemaCXX/format-strings.cpp
Index: clang/test/SemaCXX/format-strings.cpp =================================================================== --- clang/test/SemaCXX/format-strings.cpp +++ clang/test/SemaCXX/format-strings.cpp @@ -163,3 +163,48 @@ t::func4("Hello %s"); // expected-warning {{more '%' conversions than data arguments}} } } +#if __cplusplus >= 201103L +namespace evaluated { + +constexpr const char *basic() { + return +"%s %d"; // expected-note {{format string is defined here}} +} + +constexpr const char *correct_fmt() { + return +"%d %d"; +} + +constexpr const char *string_linebreak() { + return +"%d %d" +"%d %s"; // expected-note {{format string is defined here}} +} + +/*non-constexpr*/ const char *not_literal() { + return +"%d %d" +"%d %s"; +} + +constexpr const char *inner_call() { + return "%d %s"; // expected-note {{format string is defined here}} +} + +constexpr const char *wrap_constexpr() { + return inner_call(); +} + + +void f() { + printf(basic(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}} + printf(correct_fmt(), 1, 2); + printf(string_linebreak(), 1, 2, 3, 4); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}} + printf(not_literal(), 1, 2, 3, 4); // expected-warning {{format string is not a string literal}} + printf(wrap_constexpr(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}} +} + + +} +#endif Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -8473,6 +8473,9 @@ llvm::SmallBitVector &CheckedVarArgs, UncoveredArgHandler &UncoveredArg, bool IgnoreStringsWithoutSpecifiers); +static const Expr *maybeConstEvalStringLiteral(ASTContext &Context, + const Expr *E); + // Determine if an expression is a string literal or constant string. // If this function returns false on the arguments to a function expecting a // format string, we will usually need to emit a warning. @@ -8713,7 +8716,11 @@ } } } - + if (auto *SLE = maybeConstEvalStringLiteral(S.Context, E)) + return checkFormatStringExpr(S, SLE, Args, APK, format_idx, firstDataArg, + Type, CallType, /*InFunctionCall*/ false, + CheckedVarArgs, UncoveredArg, Offset, + IgnoreStringsWithoutSpecifiers); return SLCT_NotALiteral; } case Stmt::ObjCMessageExprClass: { @@ -8823,6 +8830,20 @@ } } +// If this expression can be evaluated at compile-time, +// check if the result is a StringLiteral and return it +// otherwise return nullptr +static const Expr *maybeConstEvalStringLiteral(ASTContext &Context, + const Expr *E) { + Expr::EvalResult Result; + if (E->EvaluateAsRValue(Result, Context) && Result.Val.isLValue()) { + auto *LVE = Result.Val.getLValueBase().dyn_cast<const Expr *>(); + if (isa_and_nonnull<StringLiteral>(LVE)) + return LVE; + } + return nullptr; +} + Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) { return llvm::StringSwitch<FormatStringType>(Format->getType()->getName()) .Case("scanf", FST_Scanf) Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -61,6 +61,8 @@ enum without a fixed underlying type is set to a value outside the range of the enumeration's values. Fixes `Issue 50055: <https://github.com/llvm/llvm-project/issues/50055>`_. +- Clang will now check compile-time determinable string literals as format strings. + This fixes `Issue 55805: <https://github.com/llvm/llvm-project/issues/55805>`_. Non-comprehensive list of changes in this release -------------------------------------------------
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits