[cfe-commits] r39678 - in /cfe/cfe/trunk/Driver: DiagChecker.cpp DiagChecker.h TextDiagnosticBuffer.cpp TextDiagnosticBuffer.h clang.cpp

bwendlin at cs.uiuc.edu bwendlin at cs.uiuc.edu
Wed Jul 11 09:47:03 PDT 2007


Author: bwendlin
Date: Wed Jul 11 11:47:03 2007
New Revision: 39678

URL: http://llvm.org/viewvc/llvm-project?rev=39678&view=rev
Log:
Submitted by: Bill Wendling
Reviewed by: Chris Lattner

- Added a new diagnostic client, TextDiagnosticBuffer. It buffers all
  reported diagnostics.
- Use the new diagnostic client to check that expected diagnostics are
  actually emitted. The way this is done is to put the expected
  diagnostic in a comment on the line you expect it to be emitted for.
  Like this:

    int X = A; // expected-warning {{blah}}

- Use -parse-ast-check to use this feature.

Added:
    cfe/cfe/trunk/Driver/DiagChecker.cpp   (with props)
    cfe/cfe/trunk/Driver/DiagChecker.h   (with props)
    cfe/cfe/trunk/Driver/TextDiagnosticBuffer.cpp   (with props)
    cfe/cfe/trunk/Driver/TextDiagnosticBuffer.h   (with props)
Modified:
    cfe/cfe/trunk/Driver/clang.cpp

Added: cfe/cfe/trunk/Driver/DiagChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Driver/DiagChecker.cpp?rev=39678&view=auto

==============================================================================
--- cfe/cfe/trunk/Driver/DiagChecker.cpp (added)
+++ cfe/cfe/trunk/Driver/DiagChecker.cpp Wed Jul 11 11:47:03 2007
@@ -0,0 +1,216 @@
+//===--- LLVMDiagChecker.cpp - Diagnostic Checking Functions --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bill Wendling and is distributed under the
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Process the input files and check that the diagnostic messages are expected.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LLVMDiagChecker.h"
+#include "ASTStreamers.h"
+#include "TextDiagnosticBuffer.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Preprocessor.h"
+using namespace clang;
+
+// USING THE DIAGNOSTIC CHECKER:
+//
+// Indicating that a line expects an error or a warning is simple. Put a comment
+// on the line that has the diagnostic, use "expected-{error,warning}" to tag
+// if it's an expected error or warning, and place the expected text between {{
+// and }} markers. The full text doesn't have to be included, only enough to
+// ensure that the correct diagnostic was emitted.
+//
+// Here's an example:
+//
+//   int A = B; // expected-error {{use of undeclared identifier 'B'}}
+//
+// You can place as many diagnostics on one line as you wish. To make the code
+// more readable, you can use slash-newline to separate out the diagnostics.
+
+static const char * const ExpectedErrStr = "expected-error";
+static const char * const ExpectedWarnStr = "expected-warning";
+
+/// FindDiagnostics - Go through the comment and see if it indicates expected
+/// diagnostics. If so, then put them in a diagnostic list.
+/// 
+static void FindDiagnostics(const std::string &Comment,
+                            TextDiagnosticBuffer &DiagClient,
+                            DiagList &ExpectedDiags,
+                            SourceManager &SourceMgr,
+                            SourceLocation Pos,
+                            const char * const ExpectedStr) {
+  // Find all expected diagnostics
+  typedef std::string::size_type size_type;
+  size_type ColNo = std::string::npos;
+
+  for (;;) {
+    ColNo = Comment.find(ExpectedStr, ColNo);
+    if (ColNo == std::string::npos) break;
+
+    size_type OpenDiag = Comment.find_first_of("{{", ColNo);
+
+    if (OpenDiag == std::string::npos) {
+      fprintf(stderr,
+              "oops:%d: Cannot find beginning of expected error string\n",
+              SourceMgr.getLineNumber(Pos));
+      break;
+    }
+
+    OpenDiag += 2;
+    size_type CloseDiag = Comment.find_first_of("}}", OpenDiag);
+
+    if (CloseDiag == std::string::npos) {
+      fprintf(stderr,
+              "oops:%d: Cannot find end of expected error string\n",
+              SourceMgr.getLineNumber(Pos));
+      break;
+    }
+
+    std::string Msg(Comment.substr(OpenDiag, CloseDiag - OpenDiag));
+    ExpectedDiags.push_back(std::make_pair(Pos, Msg));
+    ColNo = CloseDiag + 2;
+  }
+}
+
+/// ProcessFileDiagnosticChecking - This lexes the file and finds all of the
+/// expected errors and warnings. It then does the actual parsing of the
+/// program. The parsing will report its diagnostics, and a function can be
+/// called later to report any discrepencies between the diagnostics expected
+/// and those actually seen.
+/// 
+void clang::ProcessFileDiagnosticChecking(TextDiagnosticBuffer &DiagClient,
+                                          Preprocessor &PP,
+                                          const std::string &InFile,
+                                          SourceManager &SourceMgr,
+                                          unsigned MainFileID,
+                                          DiagList &ExpectedErrors,
+                                          DiagList &ExpectedWarnings) {
+  LexerToken Tok;
+  PP.SetCommentRetentionState(true, true);
+
+  // Enter the cave.
+  PP.EnterSourceFile(MainFileID, 0, true);
+
+  do {
+    PP.Lex(Tok);
+
+    if (Tok.getKind() == tok::comment) {
+      std::string Comment = PP.getSpelling(Tok);
+
+      // Find all expected errors
+      FindDiagnostics(Comment, DiagClient, ExpectedErrors, SourceMgr,
+                      Tok.getLocation(), ExpectedErrStr);
+
+      // Find all expected warnings
+      FindDiagnostics(Comment, DiagClient, ExpectedWarnings, SourceMgr,
+                      Tok.getLocation(), ExpectedWarnStr);
+    }
+  } while (Tok.getKind() != tok::eof);
+
+  // Parsing the specified input file.
+  PP.SetCommentRetentionState(false, false);
+  BuildASTs(PP, MainFileID, false);
+}
+
+typedef TextDiagnosticBuffer::const_iterator const_diag_iterator;
+
+/// PrintProblem - This takes a diagnostic map of the delta between expected and
+/// seen diagnostics. If there's anything in it, then something unexpected
+/// happened. Print the map out in a nice format and return "true". If the map
+/// is empty and we're not going to print things, then return "false".
+/// 
+static bool PrintProblem(SourceManager &SourceMgr,
+                         const_diag_iterator diag_begin,
+                         const_diag_iterator diag_end,
+                         const char *Msg) {
+  if (diag_begin == diag_end) return false;
+
+  fprintf(stderr, "%s\n", Msg);
+
+  for (; diag_begin != diag_end; ++diag_begin)
+    fprintf(stderr, "  LineNo %d:\n    %s\n",
+            SourceMgr.getLineNumber(diag_begin->first),
+            diag_begin->second.c_str());
+
+  return true;
+}
+
+/// CompareDiagLists - Compare two diangnostic lists and return the difference
+/// between them.
+/// 
+static bool CompareDiagLists(SourceManager &SourceMgr,
+                             const_diag_iterator d1_begin,
+                             const_diag_iterator d1_end,
+                             const_diag_iterator d2_begin,
+                             const_diag_iterator d2_end,
+                             const char *Msg) {
+  TextDiagnosticBuffer::DiagList DiffList;
+
+  for (; d1_begin != d1_end; ++d1_begin) {
+    const std::string &Diag = d1_begin->second;
+    bool Found = false;
+
+    for (; d2_begin != d2_end; ++d2_begin) {
+      if (d2_begin->second.find(Diag) != std::string::npos ||
+          Diag.find(d2_begin->second) != std::string::npos) {
+        Found = true;
+        break;
+      }
+    }
+
+    if (!Found)
+      DiffList.push_back(std::make_pair(d1_begin->first, Diag));
+  }
+
+  return PrintProblem(SourceMgr, DiffList.begin(), DiffList.end(), Msg);
+}
+
+/// ReportCheckingResults - This compares the expected results to those that
+/// were actually reported. It emits any discrepencies. Return "true" if there
+/// were problems. Return "false" otherwise.
+/// 
+bool clang::ReportCheckingResults(TextDiagnosticBuffer &DiagClient,
+                                  const DiagList &ExpectedErrors,
+                                  const DiagList &ExpectedWarnings,
+                                  SourceManager &SourceMgr) {
+  // We want to capture the delta between what was expected and what was
+  // seen.
+  //
+  //   Expected \ Seen - set expected but not seen
+  //   Seen \ Expected - set seen but not expected
+  bool HadProblem = false;
+
+  // See if there were errors that were expected but not seen.
+  HadProblem |= CompareDiagLists(SourceMgr,
+                                 ExpectedErrors.begin(), ExpectedErrors.end(),
+                                 DiagClient.err_begin(), DiagClient.err_end(),
+                                 "Errors expected but not seen:");
+
+  // See if there were errors that were seen but not expected.
+  HadProblem |= CompareDiagLists(SourceMgr,
+                                 DiagClient.err_begin(), DiagClient.err_end(),
+                                 ExpectedErrors.begin(), ExpectedErrors.end(),
+                                 "Errors seen but not expected:");
+
+  // See if there were warnings that were expected but not seen.
+  HadProblem |= CompareDiagLists(SourceMgr,
+                                 ExpectedWarnings.begin(),
+                                 ExpectedWarnings.end(),
+                                 DiagClient.warn_begin(), DiagClient.warn_end(),
+                                 "Warnings expected but not seen:");
+
+  // See if there were warnings that were seen but not expected.
+  HadProblem |= CompareDiagLists(SourceMgr,
+                                 DiagClient.warn_begin(), DiagClient.warn_end(),
+                                 ExpectedWarnings.begin(),
+                                 ExpectedWarnings.end(),
+                                 "Warnings seen but not expected:");
+
+  return HadProblem;
+}

Propchange: cfe/cfe/trunk/Driver/DiagChecker.cpp

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/cfe/trunk/Driver/DiagChecker.cpp

------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: cfe/cfe/trunk/Driver/DiagChecker.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Driver/DiagChecker.h?rev=39678&view=auto

==============================================================================
--- cfe/cfe/trunk/Driver/DiagChecker.h (added)
+++ cfe/cfe/trunk/Driver/DiagChecker.h Wed Jul 11 11:47:03 2007
@@ -0,0 +1,42 @@
+//===--- LLVMDiagChecker.h - Diagnostic Checking Functions ------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bill Wendling and is distributed under the
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Check diagnostic messages.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef DRIVER_LLVM_DIAG_CHECKER_H_
+#define DRIVER_LLVM_DIAG_CHECKER_H_
+
+#include <string>
+#include <vector>
+
+namespace clang {
+
+class Preprocessor;
+class SourceLocation;
+class SourceManager;
+class TextDiagnosticBuffer;
+
+typedef std::vector<std::pair<SourceLocation, std::string> > DiagList;
+
+void ProcessFileDiagnosticChecking(TextDiagnosticBuffer &DiagClient,
+                                   Preprocessor &PP, const std::string &InFile,
+                                   SourceManager &SourceMgr,
+                                   unsigned MainFileID,
+                                   DiagList &ExpectedErrors,
+                                   DiagList &ExpectedWarnings);
+bool ReportCheckingResults(TextDiagnosticBuffer &DiagClient,
+                           const DiagList &ExpectedErrors,
+                           const DiagList &ExpectedWarnings,
+                           SourceManager &SourceMgr);
+
+} // end clang namespace
+
+#endif

Propchange: cfe/cfe/trunk/Driver/DiagChecker.h

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/cfe/trunk/Driver/DiagChecker.h

------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: cfe/cfe/trunk/Driver/TextDiagnosticBuffer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Driver/TextDiagnosticBuffer.cpp?rev=39678&view=auto

==============================================================================
--- cfe/cfe/trunk/Driver/TextDiagnosticBuffer.cpp (added)
+++ cfe/cfe/trunk/Driver/TextDiagnosticBuffer.cpp Wed Jul 11 11:47:03 2007
@@ -0,0 +1,38 @@
+//===--- TextDiagnosticBuffer.cpp - Buffer Text Diagnostics ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bill Wendling and is distributed under the
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a concrete diagnostic client, which buffers the diagnostic messages.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TextDiagnosticBuffer.h"
+#include "clang/Basic/SourceManager.h"
+using namespace clang;
+
+/// HandleDiagnostic - Store the errors & warnings that are reported.
+/// 
+void TextDiagnosticBuffer::HandleDiagnostic(Diagnostic::Level Level,
+                                            SourceLocation Pos,
+                                            diag::kind ID,
+                                            const std::string *Strs,
+                                            unsigned NumStrs,
+                                            const SourceRange *,
+                                            unsigned) {
+  switch (Level) {
+  default: assert(0 && "Diagnostic not handled during diagnostic buffering!");
+  case Diagnostic::Warning:
+    Warnings.push_back(std::make_pair(Pos, FormatDiagnostic(Level, ID, Strs,
+                                                            NumStrs)));
+    break;
+  case Diagnostic::Error:
+    Errors.push_back(std::make_pair(Pos, FormatDiagnostic(Level, ID, Strs,
+                                                          NumStrs)));
+    break;
+  }
+}

Propchange: cfe/cfe/trunk/Driver/TextDiagnosticBuffer.cpp

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/cfe/trunk/Driver/TextDiagnosticBuffer.cpp

------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: cfe/cfe/trunk/Driver/TextDiagnosticBuffer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Driver/TextDiagnosticBuffer.h?rev=39678&view=auto

==============================================================================
--- cfe/cfe/trunk/Driver/TextDiagnosticBuffer.h (added)
+++ cfe/cfe/trunk/Driver/TextDiagnosticBuffer.h Wed Jul 11 11:47:03 2007
@@ -0,0 +1,57 @@
+//===--- TextDiagnosticBuffer.h - Buffer Text Diagnostics -------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bill Wendling and is distributed under the
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is a concrete diagnostic client, which buffers the diagnostic messages.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef DRIVER_TEXT_DIAGNOSTIC_BUFFER_H_
+#define DRIVER_TEXT_DIAGNOSTIC_BUFFER_H_
+
+#include "TextDiagnostics.h"
+#include <vector>
+
+namespace clang {
+
+class Preprocessor;
+class SourceManager;
+
+class TextDiagnosticBuffer : public TextDiagnostics {
+public:
+  typedef std::vector<std::pair<SourceLocation, std::string> > DiagList;
+  typedef DiagList::iterator iterator;
+  typedef DiagList::const_iterator const_iterator;
+private:
+  DiagList Errors;
+  DiagList Warnings;
+public:
+  TextDiagnosticBuffer(SourceManager &sourceMgr)
+    : TextDiagnostics(sourceMgr) {}
+
+  iterator err_begin()              { return Errors.begin(); }
+  iterator err_end()                { return Errors.end(); }
+  const_iterator err_begin() const  { return Errors.begin(); }
+  const_iterator err_end() const    { return Errors.end(); }
+
+  iterator warn_begin()             { return Warnings.begin(); }
+  iterator warn_end()               { return Warnings.end(); }
+  const_iterator warn_begin() const { return Warnings.begin(); }
+  const_iterator warn_end() const   { return Warnings.end(); }
+
+  virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+                                SourceLocation Pos,
+                                diag::kind ID, const std::string *Strs,
+                                unsigned NumStrs,
+                                const SourceRange *Ranges, 
+                                unsigned NumRanges);
+};
+
+} // end namspace clang
+
+#endif

Propchange: cfe/cfe/trunk/Driver/TextDiagnosticBuffer.h

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/cfe/trunk/Driver/TextDiagnosticBuffer.h

------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Modified: cfe/cfe/trunk/Driver/clang.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Driver/clang.cpp?rev=39678&r1=39677&r2=39678&view=diff

==============================================================================
--- cfe/cfe/trunk/Driver/clang.cpp (original)
+++ cfe/cfe/trunk/Driver/clang.cpp Wed Jul 11 11:47:03 2007
@@ -24,6 +24,8 @@
 
 #include "clang.h"
 #include "ASTStreamers.h"
+#include "LLVMDiagChecker.h"
+#include "TextDiagnosticBuffer.h"
 #include "TextDiagnosticPrinter.h"
 #include "clang/Parse/Parser.h"
 #include "clang/Lex/HeaderSearch.h"
@@ -47,6 +49,7 @@
 enum ProgActions {
   EmitLLVM,                     // Emit a .ll file.
   ParseASTPrint,                // Parse ASTs and print them.
+  ParseASTCheck,                // Parse ASTs and check diagnostics.
   ParseAST,                     // Parse ASTs.
   ParsePrintCallbacks,          // Parse and print each callback.
   ParseSyntaxOnly,              // Parse and perform semantic analysis.
@@ -76,6 +79,8 @@
                         "Run parser and build ASTs"),
              clEnumValN(ParseASTPrint, "parse-ast-print",
                         "Run parser, build ASTs, then print ASTs"),
+             clEnumValN(ParseASTCheck, "parse-ast-check",
+                        "Run parser, build ASTs, then check diagnostics"),
              clEnumValN(EmitLLVM, "emit-llvm",
                         "Build ASTs then convert to LLVM, emit .ll file"),
              clEnumValEnd));
@@ -756,6 +761,9 @@
                              HeaderSearch &HeaderInfo,
                              const LangOptions &LangInfo) {
   switch (ProgAction) {
+  default:
+    fprintf(stderr, "Unexpected program action!\n");
+    return;
   case DumpTokens: {                 // Token dump mode.
     LexerToken Tok;
     // Start parsing the specified input file.
@@ -807,35 +815,19 @@
     HeaderInfo.PrintStats();
     fprintf(stderr, "\n");
   }
-  
-  HeaderInfo.ClearFileInfo();
 }
 
 static llvm::cl::list<std::string>
 InputFilenames(llvm::cl::Positional, llvm::cl::desc("<input files>"));
 
-int main(int argc, char **argv) {
-  llvm::cl::ParseCommandLineOptions(argc, argv, " llvm cfe\n");
-  llvm::sys::PrintStackTraceOnErrorSignal();
-  
-  // If no input was specified, read from stdin.
-  if (InputFilenames.empty())
-    InputFilenames.push_back("-");
-  
-  /// Create a SourceManager object.  This tracks and owns all the file buffers
-  /// allocated to the program.
-  SourceManager SourceMgr;
-  
-  // Create a file manager object to provide access to and cache the filesystem.
-  FileManager FileMgr;
-  
-  // Initialize language options, inferring file types from input filenames.
-  // FIXME: This infers info from the first file, we should clump by language
-  // to handle 'x.c y.c a.cpp b.cpp'.
-  LangOptions LangInfo;
-  InitializeBaseLanguage(LangInfo, InputFilenames[0]);
-  InitializeLanguageStandard(LangInfo);
-  
+/// PerformNormalFileProcessing - This processes each file in turn, printing out
+/// the diagnostic messages to stderr. It returns a pair: number of diagnostic
+/// messages, number of errors.
+/// 
+static std::pair<unsigned, unsigned>
+PerformNormalFileProcessing(SourceManager &SourceMgr,
+                            FileManager &FileMgr,
+                            LangOptions &LangInfo) {
   // Print diagnostics to stderr.
   TextDiagnosticPrinter OurDiagnosticClient(SourceMgr);
   
@@ -850,7 +842,7 @@
   if (Target == 0) {
     fprintf(stderr,
             "Sorry, don't know what target this is, please use -arch.\n");
-    return 1;
+    exit(1);
   }
   
   // Process the -I options and set them in the HeaderInfo.
@@ -870,12 +862,103 @@
 
     ProcessInputFile(PP, MainFileID, InFile, SourceMgr,
                      OurDiagnosticClient, HeaderInfo, LangInfo);
+    HeaderInfo.ClearFileInfo();
   }
   
   unsigned NumDiagnostics = Diags.getNumDiagnostics();
+
   if (NumDiagnostics)
     fprintf(stderr, "%d diagnostic%s generated.\n", NumDiagnostics,
             (NumDiagnostics == 1 ? "" : "s"));
+
+  return std::make_pair(Diags.getNumDiagnostics(), Diags.getNumErrors());
+}
+
+/// PerformDiagnosticChecking - This processes each file in turn, checking that
+/// each diagnostic message is expect.
+/// 
+static std::pair<unsigned, unsigned>
+PerformDiagnosticChecking(SourceManager &SourceMgr,
+                          FileManager &FileMgr,
+                          LangOptions &LangInfo) {
+  // Check diagnostic messages.
+  TextDiagnosticBuffer OurDiagnosticClient(SourceMgr);
+  
+  // Configure our handling of diagnostics.
+  Diagnostic Diags(OurDiagnosticClient);
+  InitializeDiagnostics(Diags);
+  
+  // Get information about the targets being compiled for.  Note that this
+  // pointer and the TargetInfoImpl objects are never deleted by this toy
+  // driver.
+  TargetInfo *Target = CreateTargetInfo(Diags);
+  if (Target == 0) {
+    fprintf(stderr,
+            "Sorry, don't know what target this is, please use -arch.\n");
+    exit(1);
+  }
+  
+  // Process the -I options and set them in the HeaderInfo.
+  HeaderSearch HeaderInfo(FileMgr);
+  OurDiagnosticClient.setHeaderSearch(HeaderInfo);
+  InitializeIncludePaths(HeaderInfo, FileMgr, Diags, LangInfo);
+
+  DiagList ExpectedErrors;
+  DiagList ExpectedWarnings;
+  
+  for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) {
+    // Set up the preprocessor with these options.
+    Preprocessor PP(Diags, LangInfo, *Target, SourceMgr, HeaderInfo);
+    OurDiagnosticClient.setPreprocessor(PP);
+    const std::string &InFile = InputFilenames[i];
+    unsigned MainFileID = InitializePreprocessor(PP, InFile, SourceMgr,
+                                                 HeaderInfo, LangInfo);
+
+    if (!MainFileID) continue;
+
+    ProcessFileDiagnosticChecking(OurDiagnosticClient, PP, InFile,
+                                  SourceMgr, MainFileID, ExpectedErrors,
+                                  ExpectedWarnings);
+    HeaderInfo.ClearFileInfo();
+  }
+
+  if (ReportCheckingResults(OurDiagnosticClient, ExpectedErrors,
+                            ExpectedWarnings, SourceMgr))
+    // There were errors. Fake it.
+    return std::make_pair(1, 1);
+
+  return std::make_pair(0, 0);
+}
+
+int main(int argc, char **argv) {
+  llvm::cl::ParseCommandLineOptions(argc, argv, " llvm cfe\n");
+  llvm::sys::PrintStackTraceOnErrorSignal();
+  
+  // If no input was specified, read from stdin.
+  if (InputFilenames.empty())
+    InputFilenames.push_back("-");
+  
+  /// Create a SourceManager object.  This tracks and owns all the file buffers
+  /// allocated to the program.
+  SourceManager SourceMgr;
+  
+  // Create a file manager object to provide access to and cache the filesystem.
+  FileManager FileMgr;
+  
+  // Initialize language options, inferring file types from input filenames.
+  // FIXME: This infers info from the first file, we should clump by language
+  // to handle 'x.c y.c a.cpp b.cpp'.
+  LangOptions LangInfo;
+  InitializeBaseLanguage(LangInfo, InputFilenames[0]);
+  InitializeLanguageStandard(LangInfo);
+
+  // Pair to represent the number of diagnostics and number of errors emitted.
+  std::pair<unsigned, unsigned> NumDiagsOutput = std::make_pair(0, 0);
+
+  if (ProgAction != ParseASTCheck)
+    NumDiagsOutput = PerformNormalFileProcessing(SourceMgr, FileMgr, LangInfo);
+  else
+    NumDiagsOutput = PerformDiagnosticChecking(SourceMgr, FileMgr, LangInfo);
   
   if (Stats) {
     // Printed from high-to-low level.
@@ -884,5 +967,5 @@
     fprintf(stderr, "\n");
   }
   
-  return Diags.getNumErrors() != 0;
+  return NumDiagsOutput.second != 0;
 }





More information about the cfe-commits mailing list