From: Daniel Dunbar Date: Fri, 13 Nov 2009 02:06:12 +0000 (+0000) Subject: Move input kind identification (-x) into FrontendOptions. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fbe2fafe317a757031e4f24026a77dd305607d32;p=clang Move input kind identification (-x) into FrontendOptions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@87066 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index 0674c0bb40..5131166324 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H #include "clang/Frontend/CommandLineSourceLoc.h" +#include "llvm/ADT/StringRef.h" #include #include @@ -19,6 +20,21 @@ namespace clang { /// FrontendOptions - Options for controlling the behavior of the frontend. class FrontendOptions { public: + enum InputKind { + IK_None, + IK_Asm, + IK_C, + IK_CXX, + IK_ObjC, + IK_ObjCXX, + IK_PreprocessedC, + IK_PreprocessedCXX, + IK_PreprocessedObjC, + IK_PreprocessedObjCXX, + IK_OpenCL, + IK_AST + }; + unsigned DebugCodeCompletionPrinter : 1; ///< Use the debug printer for code /// completion results. unsigned DisableFree : 1; ///< Disable memory freeing on exit. @@ -44,8 +60,8 @@ public: /// If given, the name of the target ABI to use. std::string TargetABI; - /// The input files. - std::vector InputFilenames; + /// The input files and their types. + std::vector > Inputs; /// The output file, if any. std::string OutputFile; @@ -70,6 +86,13 @@ public: ShowStats = 0; ShowTimers = 0; } + + /// getInputKindForExtension - Return the appropriate input kind for a file + /// extension. For example, "c" would return IK_C. + /// + /// \return The input kind for the extension, or IK_None if the extension is + /// not recognized. + static InputKind getInputKindForExtension(llvm::StringRef Extension); }; } // end namespace clang diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt index 007f1d12a3..61df8721d9 100644 --- a/lib/Frontend/CMakeLists.txt +++ b/lib/Frontend/CMakeLists.txt @@ -11,6 +11,7 @@ add_clang_library(clangFrontend DiagChecker.cpp DocumentXML.cpp FixItRewriter.cpp + FrontendOptions.cpp GeneratePCH.cpp HTMLDiagnostics.cpp HTMLPrint.cpp diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp new file mode 100644 index 0000000000..96549de3bd --- /dev/null +++ b/lib/Frontend/FrontendOptions.cpp @@ -0,0 +1,31 @@ +//===--- FrontendOptions.cpp ----------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/FrontendOptions.h" +#include "llvm/ADT/StringSwitch.h" +using namespace clang; + +FrontendOptions::InputKind +FrontendOptions::getInputKindForExtension(llvm::StringRef Extension) { + return llvm::StringSwitch(Extension) + .Case("ast", IK_AST) + .Case("c", IK_C) + .Cases("S", "s", IK_Asm) + .Case("i", IK_PreprocessedC) + .Case("ii", IK_PreprocessedCXX) + .Case("m", IK_ObjC) + .Case("mi", IK_PreprocessedObjC) + .Cases("mm", "M", IK_ObjCXX) + .Case("mii", IK_PreprocessedObjCXX) + .Case("C", IK_CXX) + .Cases("C", "cc", "cp", IK_CXX) + .Cases("cpp", "CPP", "c++", "cxx", IK_CXX) + .Case("cl", IK_OpenCL) + .Default(IK_C); +} diff --git a/tools/clang-cc/Options.cpp b/tools/clang-cc/Options.cpp index 5b3800f3f2..0a6c2143e0 100644 --- a/tools/clang-cc/Options.cpp +++ b/tools/clang-cc/Options.cpp @@ -321,6 +321,44 @@ static llvm::cl::opt EmptyInputOnly("empty-input-only", llvm::cl::desc("Force running on an empty input file")); +static llvm::cl::opt +InputType("x", llvm::cl::desc("Input language type"), + llvm::cl::init(FrontendOptions::IK_None), + llvm::cl::values(clEnumValN(FrontendOptions::IK_C, "c", "C"), + clEnumValN(FrontendOptions::IK_OpenCL, "cl", "OpenCL C"), + clEnumValN(FrontendOptions::IK_CXX, "c++", "C++"), + clEnumValN(FrontendOptions::IK_ObjC, "objective-c", + "Objective C"), + clEnumValN(FrontendOptions::IK_ObjCXX, "objective-c++", + "Objective C++"), + clEnumValN(FrontendOptions::IK_PreprocessedC, + "cpp-output", + "Preprocessed C"), + clEnumValN(FrontendOptions::IK_Asm, + "assembler-with-cpp", + "Assembly Source Codde"), + clEnumValN(FrontendOptions::IK_PreprocessedCXX, + "c++-cpp-output", + "Preprocessed C++"), + clEnumValN(FrontendOptions::IK_PreprocessedObjC, + "objective-c-cpp-output", + "Preprocessed Objective C"), + clEnumValN(FrontendOptions::IK_PreprocessedObjCXX, + "objective-c++-cpp-output", + "Preprocessed Objective C++"), + clEnumValN(FrontendOptions::IK_C, "c-header", + "C header"), + clEnumValN(FrontendOptions::IK_ObjC, "objective-c-header", + "Objective-C header"), + clEnumValN(FrontendOptions::IK_CXX, "c++-header", + "C++ header"), + clEnumValN(FrontendOptions::IK_ObjCXX, + "objective-c++-header", + "Objective-C++ header"), + clEnumValN(FrontendOptions::IK_AST, "ast", + "Clang AST"), + clEnumValEnd)); + static llvm::cl::list InputFilenames(llvm::cl::Positional, llvm::cl::desc("")); @@ -791,7 +829,6 @@ void clang::InitializeFrontendOptions(FrontendOptions &Opts) { Opts.EmptyInputOnly = EmptyInputOnly; Opts.FixItAll = FixItAll; Opts.FixItLocations = FixItAtLocations; - Opts.InputFilenames = InputFilenames; Opts.OutputFile = OutputFile; Opts.RelocatablePCH = RelocatablePCH; Opts.ShowMacrosInCodeCompletion = CodeCompletionWantsMacros; @@ -802,8 +839,21 @@ void clang::InitializeFrontendOptions(FrontendOptions &Opts) { Opts.ViewClassInheritance = InheritanceViewCls; // '-' is the default input if none is given. - if (Opts.InputFilenames.empty()) - Opts.InputFilenames.push_back("-"); + if (InputFilenames.empty()) { + FrontendOptions::InputKind IK = InputType; + if (IK == FrontendOptions::IK_None) IK = FrontendOptions::IK_C; + Opts.Inputs.push_back(std::make_pair(IK, "-")); + } else { + for (unsigned i = 0, e = InputFilenames.size(); i != e; ++i) { + FrontendOptions::InputKind IK = InputType; + llvm::StringRef Ext = + llvm::StringRef(InputFilenames[i]).rsplit('.').second; + if (IK == FrontendOptions::IK_None) + IK = FrontendOptions::getInputKindForExtension(Ext); + Opts.Inputs.push_back(std::make_pair(IK, InputFilenames[i])); + + } + } } void clang::InitializeHeaderSearchOptions(HeaderSearchOptions &Opts, @@ -972,44 +1022,47 @@ void clang::InitializePreprocessorOptions(PreprocessorOptions &Opts) { Opts.addInclude(*OrderedPaths[i].second); } -void clang::InitializeLangOptions(LangOptions &Options, LangKind LK, +void clang::InitializeLangOptions(LangOptions &Options, + FrontendOptions::InputKind IK, TargetInfo &Target, const CodeGenOptions &CodeGenOpts) { using namespace langoptions; bool NoPreprocess = false; - switch (LK) { - default: assert(0 && "Unknown language kind!"); - case langkind_asm_cpp: + switch (IK) { + case FrontendOptions::IK_None: + case FrontendOptions::IK_AST: + assert(0 && "Invalid input kind!"); + case FrontendOptions::IK_Asm: Options.AsmPreprocessor = 1; // FALLTHROUGH - case langkind_c_cpp: + case FrontendOptions::IK_PreprocessedC: NoPreprocess = true; // FALLTHROUGH - case langkind_c: + case FrontendOptions::IK_C: // Do nothing. break; - case langkind_cxx_cpp: + case FrontendOptions::IK_PreprocessedCXX: NoPreprocess = true; // FALLTHROUGH - case langkind_cxx: + case FrontendOptions::IK_CXX: Options.CPlusPlus = 1; break; - case langkind_objc_cpp: + case FrontendOptions::IK_PreprocessedObjC: NoPreprocess = true; // FALLTHROUGH - case langkind_objc: + case FrontendOptions::IK_ObjC: Options.ObjC1 = Options.ObjC2 = 1; break; - case langkind_objcxx_cpp: + case FrontendOptions::IK_PreprocessedObjCXX: NoPreprocess = true; // FALLTHROUGH - case langkind_objcxx: + case FrontendOptions::IK_ObjCXX: Options.ObjC1 = Options.ObjC2 = 1; Options.CPlusPlus = 1; break; - case langkind_ocl: + case FrontendOptions::IK_OpenCL: Options.OpenCL = 1; Options.AltiVec = 1; Options.CXXOperatorNames = 1; @@ -1044,23 +1097,24 @@ void clang::InitializeLangOptions(LangOptions &Options, LangKind LK, if (LangStd == lang_unspecified) { // Based on the base language, pick one. - switch (LK) { - case langkind_ast: assert(0 && "Invalid call for AST inputs"); - case lang_unspecified: assert(0 && "Unknown base language"); - case langkind_ocl: + switch (IK) { + case FrontendOptions::IK_None: + case FrontendOptions::IK_AST: + assert(0 && "Invalid input kind!"); + case FrontendOptions::IK_OpenCL: LangStd = lang_c99; break; - case langkind_c: - case langkind_asm_cpp: - case langkind_c_cpp: - case langkind_objc: - case langkind_objc_cpp: + case FrontendOptions::IK_Asm: + case FrontendOptions::IK_C: + case FrontendOptions::IK_PreprocessedC: + case FrontendOptions::IK_ObjC: + case FrontendOptions::IK_PreprocessedObjC: LangStd = lang_gnu99; break; - case langkind_cxx: - case langkind_cxx_cpp: - case langkind_objcxx: - case langkind_objcxx_cpp: + case FrontendOptions::IK_CXX: + case FrontendOptions::IK_PreprocessedCXX: + case FrontendOptions::IK_ObjCXX: + case FrontendOptions::IK_PreprocessedObjCXX: LangStd = lang_gnucxx98; break; } @@ -1139,7 +1193,7 @@ void clang::InitializeLangOptions(LangOptions &Options, LangKind LK, // Default to not accepting '$' in identifiers when preprocessing assembler, // but do accept when preprocessing C. FIXME: these defaults are right for // darwin, are they right everywhere? - Options.DollarIdents = LK != langkind_asm_cpp; + Options.DollarIdents = IK != FrontendOptions::IK_Asm; if (DollarsInIdents.getPosition()) // Explicit setting overrides default. Options.DollarIdents = DollarsInIdents; diff --git a/tools/clang-cc/Options.h b/tools/clang-cc/Options.h index 558f24cc92..b3fe36f0d3 100644 --- a/tools/clang-cc/Options.h +++ b/tools/clang-cc/Options.h @@ -10,6 +10,7 @@ #ifndef LLVM_CLANGCC_OPTIONS_H #define LLVM_CLANGCC_OPTIONS_H +#include "clang/Frontend/FrontendOptions.h" #include "llvm/ADT/StringRef.h" namespace clang { @@ -25,21 +26,6 @@ class PreprocessorOptions; class PreprocessorOutputOptions; class TargetInfo; -enum LangKind { - langkind_unspecified, - langkind_c, - langkind_c_cpp, - langkind_asm_cpp, - langkind_cxx, - langkind_cxx_cpp, - langkind_objc, - langkind_objc_cpp, - langkind_objcxx, - langkind_objcxx_cpp, - langkind_ocl, - langkind_ast -}; - void InitializeAnalyzerOptions(AnalyzerOptions &Opts); void InitializeDependencyOutputOptions(DependencyOutputOptions &Opts); @@ -55,7 +41,8 @@ void InitializeHeaderSearchOptions(HeaderSearchOptions &Opts, llvm::StringRef BuiltinIncludePath, const LangOptions &Lang); -void InitializeLangOptions(LangOptions &Options, LangKind LK, +void InitializeLangOptions(LangOptions &Options, + FrontendOptions::InputKind LK, TargetInfo &Target, const CodeGenOptions &CodeGenOpts); diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp index 25672f9311..350933efc3 100644 --- a/tools/clang-cc/clang-cc.cpp +++ b/tools/clang-cc/clang-cc.cpp @@ -53,7 +53,6 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringSwitch.h" #include "llvm/Config/config.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" @@ -165,40 +164,6 @@ ProgAction(llvm::cl::desc("Choose output type:"), llvm::cl::ZeroOrMore, "Rewrite Blocks to C"), clEnumValEnd)); -//===----------------------------------------------------------------------===// -// Language Options -//===----------------------------------------------------------------------===// - -static llvm::cl::opt -BaseLang("x", llvm::cl::desc("Base language to compile"), - llvm::cl::init(langkind_unspecified), - llvm::cl::values(clEnumValN(langkind_c, "c", "C"), - clEnumValN(langkind_ocl, "cl", "OpenCL C"), - clEnumValN(langkind_cxx, "c++", "C++"), - clEnumValN(langkind_objc, "objective-c", "Objective C"), - clEnumValN(langkind_objcxx,"objective-c++","Objective C++"), - clEnumValN(langkind_c_cpp, "cpp-output", - "Preprocessed C"), - clEnumValN(langkind_asm_cpp, "assembler-with-cpp", - "Preprocessed asm"), - clEnumValN(langkind_cxx_cpp, "c++-cpp-output", - "Preprocessed C++"), - clEnumValN(langkind_objc_cpp, "objective-c-cpp-output", - "Preprocessed Objective C"), - clEnumValN(langkind_objcxx_cpp, "objective-c++-cpp-output", - "Preprocessed Objective C++"), - clEnumValN(langkind_c, "c-header", - "C header"), - clEnumValN(langkind_objc, "objective-c-header", - "Objective-C header"), - clEnumValN(langkind_cxx, "c++-header", - "C++ header"), - clEnumValN(langkind_objcxx, "objective-c++-header", - "Objective-C++ header"), - clEnumValN(langkind_ast, "ast", - "Clang AST"), - clEnumValEnd)); - //===----------------------------------------------------------------------===// // Utility Methods //===----------------------------------------------------------------------===// @@ -860,43 +825,6 @@ static void LLVMErrorHandler(void *UserData, const std::string &Message) { exit(1); } -static LangKind GetLanguage(const std::vector &Inputs) { - // If -x was given, that's the language. - if (BaseLang != langkind_unspecified) - return BaseLang; - - // Otherwise guess it from the input filenames; - LangKind LK = langkind_unspecified; - for (unsigned i = 0, e = Inputs.size(); i != e; ++i) { - llvm::StringRef Name(Inputs[i]); - LangKind ThisKind = llvm::StringSwitch(Name.rsplit('.').second) - .Case("ast", langkind_ast) - .Case("c", langkind_c) - .Cases("S", "s", langkind_asm_cpp) - .Case("i", langkind_c_cpp) - .Case("ii", langkind_cxx_cpp) - .Case("m", langkind_objc) - .Case("mi", langkind_objc_cpp) - .Cases("mm", "M", langkind_objcxx) - .Case("mii", langkind_objcxx_cpp) - .Case("C", langkind_cxx) - .Cases("C", "cc", "cp", langkind_cxx) - .Cases("cpp", "CPP", "c++", "cxx", langkind_cxx) - .Case("cl", langkind_ocl) - .Default(langkind_c); - - if (LK != langkind_unspecified && ThisKind != LK) { - llvm::errs() << "error: cannot have multiple input files of distinct " - << "language kinds without -x\n"; - exit(1); - } - - LK = ThisKind; - } - - return LK; -} - static TargetInfo * ConstructCompilerInvocation(CompilerInvocation &Opts, Diagnostic &Diags, const char *Argv0, @@ -931,14 +859,23 @@ ConstructCompilerInvocation(CompilerInvocation &Opts, Diagnostic &Diags, // options. InitializeCodeGenOptions(Opts.getCodeGenOpts(), *Target); + // Determine the input language, we currently require all files to match. + FrontendOptions::InputKind IK = Opts.getFrontendOpts().Inputs[0].first; + for (unsigned i = 1, e = Opts.getFrontendOpts().Inputs.size(); i != e; ++i) { + if (Opts.getFrontendOpts().Inputs[i].first != IK) { + llvm::errs() << "error: cannot have multiple input files of distinct " + << "language kinds without -x\n"; + return 0; + } + } + // Initialize language options. // // FIXME: These aren't used during operations on ASTs. Split onto a separate // code path to make this obvious. - LangKind LK = GetLanguage(Opts.getFrontendOpts().InputFilenames); - IsAST = LK == langkind_ast; + IsAST = (IK == FrontendOptions::IK_AST); if (!IsAST) - InitializeLangOptions(Opts.getLangOpts(), LK, *Target, + InitializeLangOptions(Opts.getLangOpts(), IK, *Target, Opts.getCodeGenOpts()); // Initialize the static analyzer options. @@ -1043,7 +980,7 @@ int main(int argc, char **argv) { ClangFrontendTimer = new llvm::Timer("Clang front-end time"); if (CompOpts.getDiagnosticOpts().VerifyDiagnostics && - CompOpts.getFrontendOpts().InputFilenames.size() > 1) { + CompOpts.getFrontendOpts().Inputs.size() > 1) { fprintf(stderr, "-verify only works on single input files.\n"); return 1; } @@ -1058,9 +995,9 @@ int main(int argc, char **argv) { // Create a file manager object to provide access to and cache the filesystem. FileManager FileMgr; - for (unsigned i = 0, e = CompOpts.getFrontendOpts().InputFilenames.size(); + for (unsigned i = 0, e = CompOpts.getFrontendOpts().Inputs.size(); i != e; ++i) { - const std::string &InFile = CompOpts.getFrontendOpts().InputFilenames[i]; + const std::string &InFile = CompOpts.getFrontendOpts().Inputs[i].second; // AST inputs are handled specially. if (IsAST) {