This fixes the FIXMEs in ParseAnalyzeArgs, and is a prerequisite of
the static-analyzer-as-loadable-plugin refactor...

Okay to commit?
From 2575a9f661dc55eae2f9cee19a17be7ced6d4620 Mon Sep 17 00:00:00 2001
From: nobled <[email protected]>
Date: Sun, 18 Dec 2011 01:10:35 +0000
Subject: [PATCH] Let CompilerInvocation initialization indicate failure

This fixes the FIXMEs in ParseAnalyzeArgs.
---
 include/clang/Frontend/CompilerInvocation.h      |    4 +-
 lib/Frontend/CompilerInvocation.cpp              |   90 +++++++++++++++-------
 lib/Frontend/CreateInvocationFromCommandLine.cpp |    9 +-
 tools/arcmt-test/arcmt-test.cpp                  |    8 +-
 tools/driver/cc1_main.cpp                        |   17 +++--
 tools/driver/cc1as_main.cpp                      |   28 +++++--
 6 files changed, 104 insertions(+), 52 deletions(-)

diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h
index bbefdb6..821336c 100644
--- a/include/clang/Frontend/CompilerInvocation.h
+++ b/include/clang/Frontend/CompilerInvocation.h
@@ -90,13 +90,13 @@ public:
   /// @{
 
   /// CreateFromArgs - Create a compiler invocation from a list of input
-  /// options.
+  /// options. Returns true on success.
   ///
   /// \param Res [out] - The resulting invocation.
   /// \param ArgBegin - The first element in the argument vector.
   /// \param ArgEnd - The last element in the argument vector.
   /// \param Diags - The diagnostic engine to use for errors.
-  static void CreateFromArgs(CompilerInvocation &Res,
+  static bool CreateFromArgs(CompilerInvocation &Res,
                              const char* const *ArgBegin,
                              const char* const *ArgEnd,
                              DiagnosticsEngine &Diags);
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 3ad555b..18b247c 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -944,10 +944,10 @@ static unsigned getOptimizationLevel(ArgList &Args, InputKind IK,
     Args.getLastArgIntValue(OPT_O, DefaultOpt, Diags);
 }
 
-static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
+static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
                               DiagnosticsEngine &Diags) {
   using namespace cc1options;
-
+  bool Success = true;
   if (Arg *A = Args.getLastArg(OPT_analyzer_store)) {
     StringRef Name = A->getValue(Args);
     AnalysisStores Value = llvm::StringSwitch<AnalysisStores>(Name)
@@ -955,12 +955,13 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
       .Case(CMDFLAG, NAME##Model)
 #include "clang/Frontend/Analyses.def"
       .Default(NumStores);
-    // FIXME: Error handling.
-    if (Value == NumStores)
+    if (Value == NumStores) {
       Diags.Report(diag::err_drv_invalid_value)
         << A->getAsString(Args) << Name;
-    else
+      Success = false;
+    } else {
       Opts.AnalysisStoreOpt = Value;
+    }
   }
 
   if (Arg *A = Args.getLastArg(OPT_analyzer_constraints)) {
@@ -970,12 +971,13 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
       .Case(CMDFLAG, NAME##Model)
 #include "clang/Frontend/Analyses.def"
       .Default(NumConstraints);
-    // FIXME: Error handling.
-    if (Value == NumConstraints)
+    if (Value == NumConstraints) {
       Diags.Report(diag::err_drv_invalid_value)
         << A->getAsString(Args) << Name;
-    else
+      Success = false;
+    } else {
       Opts.AnalysisConstraintsOpt = Value;
+    }
   }
 
   if (Arg *A = Args.getLastArg(OPT_analyzer_output)) {
@@ -985,12 +987,13 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
       .Case(CMDFLAG, PD_##NAME)
 #include "clang/Frontend/Analyses.def"
       .Default(NUM_ANALYSIS_DIAG_CLIENTS);
-    // FIXME: Error handling.
-    if (Value == NUM_ANALYSIS_DIAG_CLIENTS)
+    if (Value == NUM_ANALYSIS_DIAG_CLIENTS) {
       Diags.Report(diag::err_drv_invalid_value)
         << A->getAsString(Args) << Name;
-    else
+      Success = false;
+    } else {
       Opts.AnalysisDiagOpt = Value;
+    }
   }
 
   if (Arg *A = Args.getLastArg(OPT_analyzer_purge)) {
@@ -1000,12 +1003,13 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
       .Case(CMDFLAG, NAME)
 #include "clang/Frontend/Analyses.def"
       .Default(NumPurgeModes);
-    // FIXME: Error handling.
-    if (Value == NumPurgeModes)
+    if (Value == NumPurgeModes) {
       Diags.Report(diag::err_drv_invalid_value)
         << A->getAsString(Args) << Name;
-    else
+      Success = false;
+    } else {
       Opts.AnalysisPurgeOpt = Value;
+    }
   }
 
   Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help);
@@ -1041,17 +1045,21 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
     for (unsigned i = 0, e = checkers.size(); i != e; ++i)
       Opts.CheckersControlList.push_back(std::make_pair(checkers[i], enable));
   }
+
+  return Success;
 }
 
-static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
+static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
                              DiagnosticsEngine &Diags) {
   using namespace cc1options;
+  bool Success = true;
 
   Opts.OptimizationLevel = getOptimizationLevel(Args, IK, Diags);
   if (Opts.OptimizationLevel > 3) {
     Diags.Report(diag::err_drv_invalid_value)
       << Args.getLastArg(OPT_O)->getAsString(Args) << Opts.OptimizationLevel;
     Opts.OptimizationLevel = 3;
+    Success = false;
   }
 
   // We must always run at least the always inlining pass.
@@ -1140,11 +1148,15 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
       .Case("non-legacy", CodeGenOptions::NonLegacy)
       .Case("mixed", CodeGenOptions::Mixed)
       .Default(~0U);
-    if (Method == ~0U)
+    if (Method == ~0U) {
       Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
-    else
+      Success = false;
+    } else {
       Opts.ObjCDispatchMethod = Method;
+    }
   }
+
+  return Success;
 }
 
 static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
@@ -1159,9 +1171,11 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
   Opts.AddMissingHeaderDeps = Args.hasArg(OPT_MG);
 }
 
-static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
+static bool ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
                                 DiagnosticsEngine &Diags) {
   using namespace cc1options;
+  bool Success = true;
+
   Opts.DiagnosticLogFile = Args.getLastArgValue(OPT_diagnostic_log_file);
   Opts.DiagnosticSerializationFile =
     Args.getLastArgValue(OPT_diagnostic_serialized_file);
@@ -1192,10 +1206,12 @@ static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
     Opts.ShowOverloads = DiagnosticsEngine::Ovl_Best;
   else if (ShowOverloads == "all")
     Opts.ShowOverloads = DiagnosticsEngine::Ovl_All;
-  else
+  else {
     Diags.Report(diag::err_drv_invalid_value)
       << Args.getLastArg(OPT_fshow_overloads_EQ)->getAsString(Args)
       << ShowOverloads;
+    Success = false;
+  }
 
   StringRef ShowCategory =
     Args.getLastArgValue(OPT_fdiagnostics_show_category, "none");
@@ -1205,23 +1221,27 @@ static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
     Opts.ShowCategories = 1;
   else if (ShowCategory == "name")
     Opts.ShowCategories = 2;
-  else
+  else {
     Diags.Report(diag::err_drv_invalid_value)
       << Args.getLastArg(OPT_fdiagnostics_show_category)->getAsString(Args)
       << ShowCategory;
+    Success = false;
+  }
 
   StringRef Format =
     Args.getLastArgValue(OPT_fdiagnostics_format, "clang");
   if (Format == "clang")
     Opts.Format = DiagnosticOptions::Clang;
-  else if (Format == "msvc") 
+  else if (Format == "msvc")
     Opts.Format = DiagnosticOptions::Msvc;
-  else if (Format == "vi") 
+  else if (Format == "vi")
     Opts.Format = DiagnosticOptions::Vi;
-  else 
+  else {
     Diags.Report(diag::err_drv_invalid_value)
       << Args.getLastArg(OPT_fdiagnostics_format)->getAsString(Args)
       << Format;
+    Success = false;
+  }
   
   Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info);
   Opts.ShowParseableFixits = Args.hasArg(OPT_fdiagnostics_parseable_fixits);
@@ -1248,6 +1268,8 @@ static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
   Opts.MessageLength = Args.getLastArgIntValue(OPT_fmessage_length, 0, Diags);
   Opts.DumpBuildInformation = Args.getLastArgValue(OPT_dump_build_information);
   Opts.Warnings = Args.getAllArgValues(OPT_W);
+
+  return Success;
 }
 
 static void ParseFileSystemArgs(FileSystemOptions &Opts, ArgList &Args) {
@@ -1994,10 +2016,12 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) {
 
 //
 
-void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
+bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
                                         const char *const *ArgBegin,
                                         const char *const *ArgEnd,
                                         DiagnosticsEngine &Diags) {
+  bool Success = true;
+
   // Parse the arguments.
   llvm::OwningPtr<OptTable> Opts(createCC1OptTable());
   unsigned MissingArgIndex, MissingArgCount;
@@ -2005,22 +2029,28 @@ void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
     Opts->ParseArgs(ArgBegin, ArgEnd,MissingArgIndex, MissingArgCount));
 
   // Check for missing argument error.
-  if (MissingArgCount)
+  if (MissingArgCount) {
     Diags.Report(diag::err_drv_missing_argument)
       << Args->getArgString(MissingArgIndex) << MissingArgCount;
+    Success = false;
+  }
 
   // Issue errors on unknown arguments.
   for (arg_iterator it = Args->filtered_begin(OPT_UNKNOWN),
-         ie = Args->filtered_end(); it != ie; ++it)
+         ie = Args->filtered_end(); it != ie; ++it) {
     Diags.Report(diag::err_drv_unknown_argument) << (*it)->getAsString(*Args);
+    Success = false;
+  }
 
-  ParseAnalyzerArgs(Res.getAnalyzerOpts(), *Args, Diags);
+  Success = ParseAnalyzerArgs(Res.getAnalyzerOpts(), *Args, Diags) && Success;
   ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), *Args);
-  ParseDiagnosticArgs(Res.getDiagnosticOpts(), *Args, Diags);
+  Success = ParseDiagnosticArgs(Res.getDiagnosticOpts(), *Args, Diags)
+            && Success;
   ParseFileSystemArgs(Res.getFileSystemOpts(), *Args);
   // FIXME: We shouldn't have to pass the DashX option around here
   InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), *Args, Diags);
-  ParseCodeGenArgs(Res.getCodeGenOpts(), *Args, DashX, Diags);
+  Success = ParseCodeGenArgs(Res.getCodeGenOpts(), *Args, DashX, Diags)
+            && Success;
   ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), *Args);
   if (DashX != IK_AST && DashX != IK_LLVM_IR) {
     ParseLangArgs(*Res.getLangOpts(), *Args, DashX, Diags);
@@ -2035,6 +2065,8 @@ void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
   ParsePreprocessorArgs(Res.getPreprocessorOpts(), *Args, FileMgr, Diags);
   ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), *Args);
   ParseTargetArgs(Res.getTargetOpts(), *Args);
+
+  return Success;
 }
 
 namespace {
diff --git a/lib/Frontend/CreateInvocationFromCommandLine.cpp b/lib/Frontend/CreateInvocationFromCommandLine.cpp
index e94b944..1d33ece 100644
--- a/lib/Frontend/CreateInvocationFromCommandLine.cpp
+++ b/lib/Frontend/CreateInvocationFromCommandLine.cpp
@@ -80,11 +80,12 @@ clang::createInvocationFromCommandLine(ArrayRef<const char *> ArgList,
   }
 
   const driver::ArgStringList &CCArgs = Cmd->getArguments();
-  CompilerInvocation *CI = new CompilerInvocation();
-  CompilerInvocation::CreateFromArgs(*CI,
+  llvm::OwningPtr<CompilerInvocation> CI(new CompilerInvocation());
+  if (!CompilerInvocation::CreateFromArgs(*CI.get(),
                                      const_cast<const char **>(CCArgs.data()),
                                      const_cast<const char **>(CCArgs.data()) +
                                      CCArgs.size(),
-                                     *Diags);
-  return CI;
+                                     *Diags))
+    return 0;
+  return CI.take();
 }
diff --git a/tools/arcmt-test/arcmt-test.cpp b/tools/arcmt-test/arcmt-test.cpp
index 3f91fcf..3dc4c11 100644
--- a/tools/arcmt-test/arcmt-test.cpp
+++ b/tools/arcmt-test/arcmt-test.cpp
@@ -118,7 +118,8 @@ static bool checkForMigration(StringRef resourcesPath,
   }
 
   CompilerInvocation CI;
-  CompilerInvocation::CreateFromArgs(CI, Args.begin(), Args.end(), *Diags);
+  if (!CompilerInvocation::CreateFromArgs(CI, Args.begin(), Args.end(), *Diags))
+    return true;
 
   if (CI.getFrontendOpts().Inputs.empty()) {
     llvm::errs() << "error: no input files\n";
@@ -159,8 +160,9 @@ static bool performTransformations(StringRef resourcesPath,
       new DiagnosticsEngine(DiagID, DiagClient));
 
   CompilerInvocation origCI;
-  CompilerInvocation::CreateFromArgs(origCI, Args.begin(), Args.end(),
-                                     *TopDiags);
+  if (!CompilerInvocation::CreateFromArgs(origCI, Args.begin(), Args.end(),
+                                     *TopDiags))
+    return true;
 
   if (origCI.getFrontendOpts().Inputs.empty()) {
     llvm::errs() << "error: no input files\n";
diff --git a/tools/driver/cc1_main.cpp b/tools/driver/cc1_main.cpp
index f1fb68d..0a14fdd 100644
--- a/tools/driver/cc1_main.cpp
+++ b/tools/driver/cc1_main.cpp
@@ -77,7 +77,8 @@ static int cc1_test(DiagnosticsEngine &Diags,
   // Create a compiler invocation.
   llvm::errs() << "cc1 creating invocation.\n";
   CompilerInvocation Invocation;
-  CompilerInvocation::CreateFromArgs(Invocation, ArgBegin, ArgEnd, Diags);
+  if (!CompilerInvocation::CreateFromArgs(Invocation, ArgBegin, ArgEnd, Diags))
+    return 1;
 
   // Convert the invocation back to argument strings.
   std::vector<std::string> InvocationArgs;
@@ -95,8 +96,9 @@ static int cc1_test(DiagnosticsEngine &Diags,
   // Convert those arguments to another invocation, and check that we got the
   // same thing.
   CompilerInvocation Invocation2;
-  CompilerInvocation::CreateFromArgs(Invocation2, Invocation2Args.begin(),
-                                     Invocation2Args.end(), Diags);
+  if (!CompilerInvocation::CreateFromArgs(Invocation2, Invocation2Args.begin(),
+                                          Invocation2Args.end(), Diags))
+    return 1;
 
   // FIXME: Implement CompilerInvocation comparison.
   if (true) {
@@ -135,8 +137,11 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd,
   // well formed diagnostic object.
   TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
   DiagnosticsEngine Diags(DiagID, DiagsBuffer);
-  CompilerInvocation::CreateFromArgs(Clang->getInvocation(), ArgBegin, ArgEnd,
-                                     Diags);
+  bool Success;
+  Success = CompilerInvocation::CreateFromArgs(Clang->getInvocation(),
+                                               ArgBegin, ArgEnd, Diags);
+  if (!Success)
+    return 1;
 
   // Infer the builtin include path if unspecified.
   if (Clang->getHeaderSearchOpts().UseBuiltinIncludes &&
@@ -157,7 +162,7 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd,
   DiagsBuffer->FlushDiagnostics(Clang->getDiagnostics());
 
   // Execute the frontend actions.
-  bool Success = ExecuteCompilerInvocation(Clang.get());
+  Success = ExecuteCompilerInvocation(Clang.get());
 
   // If any timers were active but haven't been destroyed yet, print their
   // results now.  This happens in -disable-free mode.
diff --git a/tools/driver/cc1as_main.cpp b/tools/driver/cc1as_main.cpp
index 5a17512..7faedbc 100644
--- a/tools/driver/cc1as_main.cpp
+++ b/tools/driver/cc1as_main.cpp
@@ -120,17 +120,19 @@ public:
     NoExecStack = 0;
   }
 
-  static void CreateFromArgs(AssemblerInvocation &Res, const char **ArgBegin,
+  static bool CreateFromArgs(AssemblerInvocation &Res, const char **ArgBegin,
                              const char **ArgEnd, DiagnosticsEngine &Diags);
 };
 
 }
 
-void AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
+bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
                                          const char **ArgBegin,
                                          const char **ArgEnd,
                                          DiagnosticsEngine &Diags) {
   using namespace clang::driver::cc1asoptions;
+  bool Success = true;
+
   // Parse the arguments.
   OwningPtr<OptTable> OptTbl(createCC1AsOptTable());
   unsigned MissingArgIndex, MissingArgCount;
@@ -138,14 +140,18 @@ void AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
     OptTbl->ParseArgs(ArgBegin, ArgEnd,MissingArgIndex, MissingArgCount));
 
   // Check for missing argument error.
-  if (MissingArgCount)
+  if (MissingArgCount) {
     Diags.Report(diag::err_drv_missing_argument)
       << Args->getArgString(MissingArgIndex) << MissingArgCount;
+    Success = false;
+  }
 
   // Issue errors on unknown arguments.
   for (arg_iterator it = Args->filtered_begin(cc1asoptions::OPT_UNKNOWN),
-         ie = Args->filtered_end(); it != ie; ++it)
+         ie = Args->filtered_end(); it != ie; ++it) {
     Diags.Report(diag::err_drv_unknown_argument) << (*it) ->getAsString(*Args);
+    Success = false;
+  }
 
   // Construct the invocation.
 
@@ -167,8 +173,10 @@ void AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
       const Arg *A = it;
       if (First)
         Opts.InputFile = A->getValue(*Args);
-      else
+      else {
         Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(*Args);
+        Success = false;
+      }
     }
   }
   Opts.LLVMArgs = Args->getAllArgValues(OPT_mllvm);
@@ -182,10 +190,11 @@ void AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
       .Case("null", FT_Null)
       .Case("obj", FT_Obj)
       .Default(~0U);
-    if (OutputType == ~0U)
+    if (OutputType == ~0U) {
       Diags.Report(diag::err_drv_invalid_value)
         << A->getAsString(*Args) << Name;
-    else
+      Success = false;
+    } else
       Opts.OutputType = FileType(OutputType);
   }
   Opts.ShowHelp = Args->hasArg(OPT_help);
@@ -200,6 +209,8 @@ void AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts,
   // Assemble Options
   Opts.RelaxAll = Args->hasArg(OPT_relax_all);
   Opts.NoExecStack =  Args->hasArg(OPT_no_exec_stack);
+
+  return true;
 }
 
 static formatted_raw_ostream *GetOutputStream(AssemblerInvocation &Opts,
@@ -366,7 +377,8 @@ int cc1as_main(const char **ArgBegin, const char **ArgEnd,
 
   // Parse the arguments.
   AssemblerInvocation Asm;
-  AssemblerInvocation::CreateFromArgs(Asm, ArgBegin, ArgEnd, Diags);
+  if (!AssemblerInvocation::CreateFromArgs(Asm, ArgBegin, ArgEnd, Diags))
+    return 1;
 
   // Honor -help.
   if (Asm.ShowHelp) {
-- 
1.7.4.1

_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to