diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 8649b7a..c4e50ac 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5165,7 +5165,8 @@ def warn_scanf_scanlist_incomplete : Warning<
   "no closing ']' for '%%[' in scanf format string">,
   InGroup<Format>;
 def note_format_string_defined : Note<"format string is defined here">;
- 
+def note_printf_c_str: Note< "did you mean to use .c_str()?">;
+
 def warn_null_arg : Warning<
   "null passed to a callee which requires a non-null argument">,
   InGroup<NonNull>;
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index e35f45b..33cf75f 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -16,6 +16,7 @@
 #include "clang/Sema/Sema.h"
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Analysis/Analyses/FormatString.h"
 #include "clang/AST/ASTContext.h"
@@ -2263,6 +2264,38 @@ void CheckPrintfHandler::HandleIgnoredFlag(
                          getSpecifierRange(ignoredFlag.getPosition(), 1)));
 }
 
+// Determines if the specified is a C++ class or struct containing
+// a member with the specified name and kind (e.g. a CXXMethodDecl named
+// "c_str()"
+template<typename FieldKind>
+static bool CXXRecordHasMemberNamed(StringRef Name, Sema &S, QualType Ty) {
+  const RecordType *RT = Ty->getAs<RecordType>();
+
+  if (!RT)
+    return false;
+  const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
+  if (!RD)
+    return false;
+
+  LookupResult R(S, &S.PP.getIdentifierTable().get(Name), SourceLocation(),
+                 Sema::LookupMemberName);
+
+  // We just need to check to see if the filter turns up a member of the right
+  // type at this point.
+  if (S.LookupQualifiedName(R, RT->getDecl())) {
+    LookupResult::Filter filter = R.makeFilter();
+    while (filter.hasNext()) {
+      NamedDecl *decl = filter.next()->getUnderlyingDecl();
+      if (isa<FieldKind>(decl)) {
+        filter.done();
+        return true;
+      }
+    }
+    filter.done();
+  }
+  return false;
+}
+
 bool
 CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier
                                             &FS,
@@ -2439,6 +2472,19 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier
         Ex->getLocStart(),
         /*IsStringLocation*/false,
         getSpecifierRange(startSpecifier, specifierLen));
+
+      // Check if a string was passed when a char* was needed, and offer a
+      // better diagnostic if so.
+      const QualType CharPtrT = S.Context.getPointerType(S.Context.CharTy);
+
+      if (ATR.isValid() &&
+          CXXRecordHasMemberNamed<CXXMethodDecl>("c_str", S, Ex->getType()) &&
+          ATR.matchesType(S.Context, CharPtrT)) {
+        S.Diag(Ex->getLocStart(), diag::note_printf_c_str)
+            << Ex->getSourceRange()
+            << FixItHint::CreateInsertion(Ex->getLocEnd(), ".c_str()");
+    }
+
     }
   }
 
diff --git a/test/SemaCXX/printf-cstr.cpp b/test/SemaCXX/printf-cstr.cpp
new file mode 100644
index 0000000..b3badc8
--- /dev/null
+++ b/test/SemaCXX/printf-cstr.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -Wall -fsyntax-only -Wformat -verify %s
+
+#include <stdarg.h>
+
+extern "C" {
+extern int printf(const char *restrict, ...);
+}
+
+class HasCStr {
+  const char *str;
+ public:
+  HasCStr(const char *s): str(s) { }
+  const char *c_str() {return str;}
+};
+
+class HasNoCStr {
+  const char *str;
+ public:
+  HasNoCStr(const char *s): str(s) { }
+  const char *not_c_str() {return str;}
+};
+
+void f() {
+  char str[] = "test";
+  HasCStr hcs(str);
+  HasNoCStr hncs(str);
+  printf("%d: %s\n", 10, hcs.c_str());
+  printf("%d: %s\n", 10, hcs); // expected-error{{cannot pass object of non-POD type 'HasCStr'}} \
+  // expected-warning{{format specifies type 'char *' but the argument has type 'HasCStr'}} \
+  // expected-note{{did you mean to use .c_str()?}}
+  printf("%d: %s\n", 10, hncs); // expected-error{{cannot pass object of non-POD type 'HasNoCStr'}} \
+  // expected-warning{{format specifies type 'char *' but the argument has type 'HasNoCStr'}}
+}
