Add a -Wclass-varargs to warn on objects of any class type being passed through an ellipsis. Since C++11 relaxed the rules on this, we allow a lot more bad code through silently, such as:
const char *format = "%s";
std::experimental::string_view view = "foo";
printf(format, view);
In this case, not only warn about a class type being used here, but also suggest that calling c_str() might be a good idea.
llvm-svn: 202461
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index e9e9742..5229274 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2765,7 +2765,7 @@
const analyze_printf::OptionalFlag &flag,
const char *startSpecifier, unsigned specifierLen);
bool checkForCStrMembers(const analyze_printf::ArgType &AT,
- const Expr *E, const CharSourceRange &CSR);
+ const Expr *E);
};
}
@@ -2899,11 +2899,12 @@
if (!RT)
return Results;
const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
- if (!RD)
+ if (!RD || !RD->getDefinition())
return Results;
LookupResult R(S, &S.PP.getIdentifierTable().get(Name), SourceLocation(),
Sema::LookupMemberName);
+ R.suppressDiagnostics();
// We just need to include all members of the right kind turned up by the
// filter, at this point.
@@ -2916,12 +2917,26 @@
return Results;
}
+/// Check if we could call '.c_str()' on an object.
+///
+/// FIXME: This returns the wrong results in some cases (if cv-qualifiers don't
+/// allow the call, or if it would be ambiguous).
+bool Sema::hasCStrMethod(const Expr *E) {
+ typedef llvm::SmallPtrSet<CXXMethodDecl*, 1> MethodSet;
+ MethodSet Results =
+ CXXRecordMembersNamed<CXXMethodDecl>("c_str", *this, E->getType());
+ for (MethodSet::iterator MI = Results.begin(), ME = Results.end();
+ MI != ME; ++MI)
+ if ((*MI)->getMinRequiredArguments() == 0)
+ return true;
+ return false;
+}
+
// Check if a (w)string was passed when a (w)char* was needed, and offer a
// better diagnostic if so. AT is assumed to be valid.
// Returns true when a c_str() conversion method is found.
bool CheckPrintfHandler::checkForCStrMembers(
- const analyze_printf::ArgType &AT, const Expr *E,
- const CharSourceRange &CSR) {
+ const analyze_printf::ArgType &AT, const Expr *E) {
typedef llvm::SmallPtrSet<CXXMethodDecl*, 1> MethodSet;
MethodSet Results =
@@ -2930,7 +2945,7 @@
for (MethodSet::iterator MI = Results.begin(), ME = Results.end();
MI != ME; ++MI) {
const CXXMethodDecl *Method = *MI;
- if (Method->getNumParams() == 0 &&
+ if (Method->getMinRequiredArguments() == 0 &&
AT.matchesType(S.Context, Method->getReturnType())) {
// FIXME: Suggest parens if the expression needs them.
SourceLocation EndLoc =
@@ -3317,7 +3332,7 @@
<< CSR
<< E->getSourceRange(),
E->getLocStart(), /*IsStringLocation*/false, CSR);
- checkForCStrMembers(AT, E, CSR);
+ checkForCStrMembers(AT, E);
break;
case Sema::VAK_Invalid: