Move input kind identification (-x) into FrontendOptions.

llvm-svn: 87066
This commit is contained in:
Daniel Dunbar 2009-11-13 02:06:12 +00:00
parent 3c55718016
commit 27b19dc1b5
6 changed files with 159 additions and 126 deletions

View File

@ -11,6 +11,7 @@
#define LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H
#include "clang/Frontend/CommandLineSourceLoc.h"
#include "llvm/ADT/StringRef.h"
#include <string>
#include <vector>
@ -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<std::string> InputFilenames;
/// The input files and their types.
std::vector<std::pair<InputKind, std::string> > 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

View File

@ -11,6 +11,7 @@ add_clang_library(clangFrontend
DiagChecker.cpp
DocumentXML.cpp
FixItRewriter.cpp
FrontendOptions.cpp
GeneratePCH.cpp
HTMLDiagnostics.cpp
HTMLPrint.cpp

View File

@ -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<InputKind>(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);
}

View File

@ -321,6 +321,44 @@ static llvm::cl::opt<bool>
EmptyInputOnly("empty-input-only",
llvm::cl::desc("Force running on an empty input file"));
static llvm::cl::opt<FrontendOptions::InputKind>
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<std::string>
InputFilenames(llvm::cl::Positional, llvm::cl::desc("<input files>"));
@ -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;

View File

@ -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);

View File

@ -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<LangKind>
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<std::string> &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<LangKind>(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) {