Index: lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp	(revision 179922)
+++ lib/StaticAnalyzer/Checkers/SimpleStreamChecker.cpp	(working copy)
@@ -20,6 +20,8 @@
 #include "clang/StaticAnalyzer/Core/Checker.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>

 using namespace clang;
 using namespace ento;
@@ -27,16 +29,29 @@
 namespace {
 typedef SmallVector<SymbolRef, 2> SymbolVector;

+std::string ConvertToString(const Expr *From) {
+  std::string SStr;
+  llvm::raw_string_ostream S(SStr);
+  From->printPretty(S, 0, PrintingPolicy(LangOptions()));
+  return S.str();
+}
+
 struct StreamState {
 private:
   enum Kind { Opened, Closed } K;
+  std::string FileName;
   StreamState(Kind InK) : K(InK) { }
+  StreamState(Kind InK, std::string InFileName)
+    : K(InK), FileName(InFileName) { }

 public:
   bool isOpened() const { return K == Opened; }
   bool isClosed() const { return K == Closed; }
+  const std::string &getFileName() const { return FileName; }

-  static StreamState getOpened() { return StreamState(Opened); }
+  static StreamState getOpened(std::string InName) {
+    return StreamState(Opened, InName);
+  }
   static StreamState getClosed() { return StreamState(Closed); }

   bool operator==(const StreamState &X) const {
@@ -44,6 +59,7 @@
   }
   void Profile(llvm::FoldingSetNodeID &ID) const {
     ID.AddInteger(K);
+    ID.AddString(FileName);
   }
 };

@@ -135,7 +151,9 @@

   // Generate the next transition (an edge in the exploded graph).
   ProgramStateRef State = C.getState();
-  State = State->set<StreamMap>(FileDesc, StreamState::getOpened());
+  // Get the name of the file being opened.
+  std::string FileName = ConvertToString(Call.getArgExpr(0));
+  State = State->set<StreamMap>(FileDesc, StreamState::getOpened(FileName));
   C.addTransition(State);
 }

@@ -226,11 +244,12 @@
                                                CheckerContext &C,
                                                ExplodedNode *ErrNode) const {
   // Attach bug reports to the leak node.
-  // TODO: Identify the leaked file descriptor.
   for (SmallVector<SymbolRef, 2>::iterator
       I = LeakedStreams.begin(), E = LeakedStreams.end(); I != E; ++I) {
+    const StreamState *SS = C.getState()->get<StreamMap>(*I);
     BugReport *R = new BugReport(*LeakBugType,
-        "Opened file is never closed; potential resource leak", ErrNode);
+        "File: " + SS->getFileName() +
+        " is never closed; potential resource leak", ErrNode);
     R->markInteresting(*I);
     C.emitReport(R);
   }
Index: test/Analysis/simple-stream-checks.c
===================================================================
--- test/Analysis/simple-stream-checks.c	(revision 179922)
+++ test/Analysis/simple-stream-checks.c	(working copy)
@@ -20,7 +20,7 @@
     fputs ("fopen example", F);
   }

-  if (Data) // expected-warning {{Opened file is never closed; potential resource leak}}
+  if (Data) // expected-warning {{File: "myfile.txt" is never closed; potential resource leak}}
     return *Data;
   else
     return 0;
@@ -45,11 +45,11 @@

 void leakOnEnfOfPath1(int *Data) {
   FILE *F = fopen("myfile.txt", "w");
-} // expected-warning {{Opened file is never closed; potential resource leak}}
+} // expected-warning {{File: "myfile.txt" is never closed; potential resource leak}}

 void leakOnEnfOfPath2(int *Data) {
   FILE *F = fopen("myfile.txt", "w");
-  return; // expected-warning {{Opened file is never closed; potential resource leak}}
+  return; // expected-warning {{File: "myfile.txt" is never closed; potential resource leak}}
 }

 FILE *leakOnEnfOfPath3(int *Data) {
@@ -74,18 +74,18 @@
 void SymbolDoesNotEscapeThoughStringAPIs(char *Data) {
   FILE *F = fopen("myfile.txt", "w");
   fputc(*Data, F);
-  return; // expected-warning {{Opened file is never closed; potential resource leak}}
+  return; // expected-warning {{File: "myfile.txt" is never closed; potential resource leak}}
 }

 void passConstPointer(const FILE * F);
 void testPassConstPointer() {
   FILE *F = fopen("myfile.txt", "w");
   passConstPointer(F);
-  return; // expected-warning {{Opened file is never closed; potential resource leak}}
+  return; // expected-warning {{File: "myfile.txt" is never closed; potential resource leak}}
 }

 void testPassToSystemHeaderFunctionIndirectly() {
   FileStruct fs;
   fs.p = fopen("myfile.txt", "w");
   fakeSystemHeaderCall(&fs);
-}  // expected-warning {{Opened file is never closed; potential resource leak}}
+}  // expected-warning {{File: "myfile.txt" is never closed; potential resource leak}}
