diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-05-02 18:30:45 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-05-02 18:30:45 +0000 |
commit | 570918821a8492048e6ab54955c9864bd6c3e952 (patch) | |
tree | f9d0d3f3478c298aaf51987483bbbbefe8e6631b /lib/Frontend | |
parent | f0c55418e2b09eaab37c820d3756cc1b4584d084 (diff) | |
download | src-test2-570918821a8492048e6ab54955c9864bd6c3e952.tar.gz src-test2-570918821a8492048e6ab54955c9864bd6c3e952.zip |
Notes
Diffstat (limited to 'lib/Frontend')
-rw-r--r-- | lib/Frontend/ASTUnit.cpp | 27 | ||||
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 36 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 264 | ||||
-rw-r--r-- | lib/Frontend/FrontendAction.cpp | 271 | ||||
-rw-r--r-- | lib/Frontend/FrontendActions.cpp | 274 | ||||
-rw-r--r-- | lib/Frontend/FrontendOptions.cpp | 36 | ||||
-rw-r--r-- | lib/Frontend/InitPreprocessor.cpp | 2 | ||||
-rw-r--r-- | lib/Frontend/LangStandards.cpp | 8 | ||||
-rw-r--r-- | lib/Frontend/PrintPreprocessedOutput.cpp | 113 | ||||
-rw-r--r-- | lib/Frontend/Rewrite/InclusionRewriter.cpp | 31 | ||||
-rw-r--r-- | lib/Frontend/VerifyDiagnosticConsumer.cpp | 2 |
11 files changed, 579 insertions, 485 deletions
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 2acdc6494f85..32ee9d3e9961 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -1076,9 +1076,11 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, assert(Clang->getFrontendOpts().Inputs.size() == 1 && "Invocation must have exactly one source file!"); - assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_AST && + assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == + InputKind::Source && "FIXME: AST inputs not yet supported here!"); - assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_LLVM_IR && + assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() != + InputKind::LLVM_IR && "IR inputs not support here!"); // Configure the various subsystems. @@ -1552,9 +1554,11 @@ ASTUnit::getMainBufferWithPrecompiledPreamble( assert(Clang->getFrontendOpts().Inputs.size() == 1 && "Invocation must have exactly one source file!"); - assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_AST && + assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == + InputKind::Source && "FIXME: AST inputs not yet supported here!"); - assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_LLVM_IR && + assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() != + InputKind::LLVM_IR && "IR inputs not support here!"); // Clear out old caches and data. @@ -1810,10 +1814,12 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction( assert(Clang->getFrontendOpts().Inputs.size() == 1 && "Invocation must have exactly one source file!"); - assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_AST && + assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == + InputKind::Source && "FIXME: AST inputs not yet supported here!"); - assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_LLVM_IR && - "IR inputs not supported here!"); + assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() != + InputKind::LLVM_IR && + "IR inputs not support here!"); // Configure the various subsystems. AST->TheSema.reset(); @@ -2399,11 +2405,12 @@ void ASTUnit::CodeComplete( assert(Clang->getFrontendOpts().Inputs.size() == 1 && "Invocation must have exactly one source file!"); - assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_AST && + assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == + InputKind::Source && "FIXME: AST inputs not yet supported here!"); - assert(Clang->getFrontendOpts().Inputs[0].getKind() != IK_LLVM_IR && + assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() != + InputKind::LLVM_IR && "IR inputs not support here!"); - // Use the source and file managers that we were given. Clang->setFileManager(&FileMgr); diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 8b4b16920668..a7b5fa7dfd29 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -858,7 +858,8 @@ bool CompilerInstance::InitializeSourceManager( /*SearchPath=*/nullptr, /*RelativePath=*/nullptr, /*RequestingModule=*/nullptr, - /*SuggestedModule=*/nullptr, /*SkipCache=*/true); + /*SuggestedModule=*/nullptr, /*IsMapped=*/nullptr, + /*SkipCache=*/true); // Also add the header to /showIncludes output. if (File) DepOpts.ShowIncludesPretendHeader = File->getName(); @@ -1015,14 +1016,14 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { /// \brief Determine the appropriate source input kind based on language /// options. -static InputKind getSourceInputKindFromOptions(const LangOptions &LangOpts) { +static InputKind::Language getLanguageFromOptions(const LangOptions &LangOpts) { if (LangOpts.OpenCL) - return IK_OpenCL; + return InputKind::OpenCL; if (LangOpts.CUDA) - return IK_CUDA; + return InputKind::CUDA; if (LangOpts.ObjC1) - return LangOpts.CPlusPlus? IK_ObjCXX : IK_ObjC; - return LangOpts.CPlusPlus? IK_CXX : IK_C; + return LangOpts.CPlusPlus ? InputKind::ObjCXX : InputKind::ObjC; + return LangOpts.CPlusPlus ? InputKind::CXX : InputKind::C; } /// \brief Compile a module file for the given module, using the options @@ -1079,10 +1080,13 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance, FrontendOpts.DisableFree = false; FrontendOpts.GenerateGlobalModuleIndex = false; FrontendOpts.BuildingImplicitModule = true; + FrontendOpts.OriginalModuleMap = + ModMap.getModuleMapFileForUniquing(Module)->getName(); // Force implicitly-built modules to hash the content of the module file. HSOpts.ModulesHashContent = true; FrontendOpts.Inputs.clear(); - InputKind IK = getSourceInputKindFromOptions(*Invocation->getLangOpts()); + InputKind IK(getLanguageFromOptions(*Invocation->getLangOpts()), + InputKind::ModuleMap); // Don't free the remapped file buffers; they are owned by our caller. PPOpts.RetainRemappedFileBuffers = true; @@ -1127,11 +1131,12 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance, if (const FileEntry *ModuleMapFile = ModMap.getContainingModuleMapFile(Module)) { // Use the module map where this module resides. - FrontendOpts.Inputs.emplace_back(ModuleMapFile->getName(), IK); + FrontendOpts.Inputs.emplace_back(ModuleMapFile->getName(), IK, + +Module->IsSystem); } else { SmallString<128> FakeModuleMapFile(Module->Directory->getName()); llvm::sys::path::append(FakeModuleMapFile, "__inferred_module.map"); - FrontendOpts.Inputs.emplace_back(FakeModuleMapFile, IK); + FrontendOpts.Inputs.emplace_back(FakeModuleMapFile, IK, +Module->IsSystem); llvm::raw_string_ostream OS(InferredModuleMapContent); Module->print(OS); @@ -1144,11 +1149,6 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance, SourceMgr.overrideFileContents(ModuleMapFile, std::move(ModuleMapBuffer)); } - // Construct a module-generating action. Passing through the module map is - // safe because the FileManager is shared between the compiler instances. - GenerateModuleFromModuleMapAction CreateModuleAction( - ModMap.getModuleMapFileForUniquing(Module), Module->IsSystem); - ImportingInstance.getDiagnostics().Report(ImportLoc, diag::remark_module_build) << Module->Name << ModuleFileName; @@ -1157,8 +1157,12 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance, // thread so that we get a stack large enough. const unsigned ThreadStackSize = 8 << 20; llvm::CrashRecoveryContext CRC; - CRC.RunSafelyOnThread([&]() { Instance.ExecuteAction(CreateModuleAction); }, - ThreadStackSize); + CRC.RunSafelyOnThread( + [&]() { + GenerateModuleFromModuleMapAction Action; + Instance.ExecuteAction(Action); + }, + ThreadStackSize); ImportingInstance.getDiagnostics().Report(ImportLoc, diag::remark_module_build_done) diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 8cdb8298ee9e..d3ebf48315e2 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -81,7 +81,7 @@ using namespace llvm::opt; static unsigned getOptimizationLevel(ArgList &Args, InputKind IK, DiagnosticsEngine &Diags) { unsigned DefaultOpt = 0; - if (IK == IK_OpenCL && !Args.hasArg(OPT_cl_opt_disable)) + if (IK.getLanguage() == InputKind::OpenCL && !Args.hasArg(OPT_cl_opt_disable)) DefaultOpt = 2; if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { @@ -652,7 +652,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.EmitSummaryIndex = A && A->containsValue("thin"); Opts.LTOUnit = Args.hasFlag(OPT_flto_unit, OPT_fno_lto_unit, false); if (Arg *A = Args.getLastArg(OPT_fthinlto_index_EQ)) { - if (IK != IK_LLVM_IR) + if (IK.getLanguage() != InputKind::LLVM_IR) Diags.Report(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args) << "-x ir"; Opts.ThinLTOIndexFile = Args.getLastArgValue(OPT_fthinlto_index_EQ); @@ -1347,42 +1347,54 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, << "ARC migration" << "ObjC migration"; } - InputKind DashX = IK_None; + InputKind DashX(InputKind::Unknown); if (const Arg *A = Args.getLastArg(OPT_x)) { - DashX = llvm::StringSwitch<InputKind>(A->getValue()) - .Case("c", IK_C) - .Case("cl", IK_OpenCL) - .Case("cuda", IK_CUDA) - .Case("c++", IK_CXX) - .Case("objective-c", IK_ObjC) - .Case("objective-c++", IK_ObjCXX) - .Case("cpp-output", IK_PreprocessedC) - .Case("assembler-with-cpp", IK_Asm) - .Case("c++-cpp-output", IK_PreprocessedCXX) - .Case("cuda-cpp-output", IK_PreprocessedCuda) - .Case("objective-c-cpp-output", IK_PreprocessedObjC) - .Case("objc-cpp-output", IK_PreprocessedObjC) - .Case("objective-c++-cpp-output", IK_PreprocessedObjCXX) - .Case("objc++-cpp-output", IK_PreprocessedObjCXX) - .Case("c-header", IK_C) - .Case("cl-header", IK_OpenCL) - .Case("objective-c-header", IK_ObjC) - .Case("c++-header", IK_CXX) - .Case("objective-c++-header", IK_ObjCXX) - .Cases("ast", "pcm", IK_AST) - .Case("ir", IK_LLVM_IR) - .Case("renderscript", IK_RenderScript) - .Default(IK_None); - if (DashX == IK_None) + StringRef XValue = A->getValue(); + + // Parse suffixes: '<lang>(-header|[-module-map][-cpp-output])'. + // FIXME: Supporting '<lang>-header-cpp-output' would be useful. + bool Preprocessed = XValue.consume_back("-cpp-output"); + bool ModuleMap = XValue.consume_back("-module-map"); + IsHeaderFile = + !Preprocessed && !ModuleMap && XValue.consume_back("-header"); + + // Principal languages. + DashX = llvm::StringSwitch<InputKind>(XValue) + .Case("c", InputKind::C) + .Case("cl", InputKind::OpenCL) + .Case("cuda", InputKind::CUDA) + .Case("c++", InputKind::CXX) + .Case("objective-c", InputKind::ObjC) + .Case("objective-c++", InputKind::ObjCXX) + .Case("renderscript", InputKind::RenderScript) + .Default(InputKind::Unknown); + + // "objc[++]-cpp-output" is an acceptable synonym for + // "objective-c[++]-cpp-output". + if (DashX.isUnknown() && Preprocessed && !IsHeaderFile && !ModuleMap) + DashX = llvm::StringSwitch<InputKind>(XValue) + .Case("objc", InputKind::ObjC) + .Case("objc++", InputKind::ObjCXX) + .Default(InputKind::Unknown); + + // Some special cases cannot be combined with suffixes. + if (DashX.isUnknown() && !Preprocessed && !ModuleMap && !IsHeaderFile) + DashX = llvm::StringSwitch<InputKind>(XValue) + .Case("cpp-output", InputKind(InputKind::C).getPreprocessed()) + .Case("assembler-with-cpp", InputKind::Asm) + .Cases("ast", "pcm", + InputKind(InputKind::Unknown, InputKind::Precompiled)) + .Case("ir", InputKind::LLVM_IR) + .Default(InputKind::Unknown); + + if (DashX.isUnknown()) Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); - IsHeaderFile = llvm::StringSwitch<bool>(A->getValue()) - .Case("c-header", true) - .Case("cl-header", true) - .Case("objective-c-header", true) - .Case("c++-header", true) - .Case("objective-c++-header", true) - .Default(false); + + if (Preprocessed) + DashX = DashX.getPreprocessed(); + if (ModuleMap) + DashX = DashX.withFormat(InputKind::ModuleMap); } // '-' is the default input if none is given. @@ -1392,13 +1404,22 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Inputs.push_back("-"); for (unsigned i = 0, e = Inputs.size(); i != e; ++i) { InputKind IK = DashX; - if (IK == IK_None) { + if (IK.isUnknown()) { IK = FrontendOptions::getInputKindForExtension( StringRef(Inputs[i]).rsplit('.').second); + // FIXME: Warn on this? + if (IK.isUnknown()) + IK = InputKind::C; // FIXME: Remove this hack. if (i == 0) DashX = IK; } + + // The -emit-module action implicitly takes a module map. + if (Opts.ProgramAction == frontend::GenerateModule && + IK.getFormat() == InputKind::Source) + IK = IK.withFormat(InputKind::ModuleMap); + Opts.Inputs.emplace_back(std::move(Inputs[i]), IK); } @@ -1564,53 +1585,48 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, // Set some properties which depend solely on the input kind; it would be nice // to move these to the language standard, and have the driver resolve the // input kind + language standard. - if (IK == IK_Asm) { + // + // FIXME: Perhaps a better model would be for a single source file to have + // multiple language standards (C / C++ std, ObjC std, OpenCL std, OpenMP std) + // simultaneously active? + if (IK.getLanguage() == InputKind::Asm) { Opts.AsmPreprocessor = 1; - } else if (IK == IK_ObjC || - IK == IK_ObjCXX || - IK == IK_PreprocessedObjC || - IK == IK_PreprocessedObjCXX) { + } else if (IK.isObjectiveC()) { Opts.ObjC1 = Opts.ObjC2 = 1; } if (LangStd == LangStandard::lang_unspecified) { // Based on the base language, pick one. - switch (IK) { - case IK_None: - case IK_AST: - case IK_LLVM_IR: + switch (IK.getLanguage()) { + case InputKind::Unknown: + case InputKind::LLVM_IR: llvm_unreachable("Invalid input kind!"); - case IK_OpenCL: - LangStd = LangStandard::lang_opencl; + case InputKind::OpenCL: + LangStd = LangStandard::lang_opencl10; break; - case IK_CUDA: - case IK_PreprocessedCuda: + case InputKind::CUDA: LangStd = LangStandard::lang_cuda; break; - case IK_Asm: - case IK_C: - case IK_PreprocessedC: + case InputKind::Asm: + case InputKind::C: // The PS4 uses C99 as the default C standard. if (T.isPS4()) LangStd = LangStandard::lang_gnu99; else LangStd = LangStandard::lang_gnu11; break; - case IK_ObjC: - case IK_PreprocessedObjC: + case InputKind::ObjC: LangStd = LangStandard::lang_gnu11; break; - case IK_CXX: - case IK_PreprocessedCXX: - case IK_ObjCXX: - case IK_PreprocessedObjCXX: + case InputKind::CXX: + case InputKind::ObjCXX: // The PS4 uses C++11 as the default C++ standard. if (T.isPS4()) LangStd = LangStandard::lang_gnucxx11; else LangStd = LangStandard::lang_gnucxx98; break; - case IK_RenderScript: + case InputKind::RenderScript: LangStd = LangStandard::lang_c99; break; } @@ -1626,13 +1642,13 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, Opts.CPlusPlus1z = Std.isCPlusPlus1z(); Opts.Digraphs = Std.hasDigraphs(); Opts.GNUMode = Std.isGNUMode(); - Opts.GNUInline = Std.isC89(); + Opts.GNUInline = !Opts.C99 && !Opts.CPlusPlus; Opts.HexFloats = Std.hasHexFloats(); Opts.ImplicitInt = Std.hasImplicitInt(); // Set OpenCL Version. - Opts.OpenCL = Std.isOpenCL() || IK == IK_OpenCL; - if (LangStd == LangStandard::lang_opencl) + Opts.OpenCL = Std.isOpenCL(); + if (LangStd == LangStandard::lang_opencl10) Opts.OpenCLVersion = 100; else if (LangStd == LangStandard::lang_opencl11) Opts.OpenCLVersion = 110; @@ -1655,13 +1671,12 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, } } - Opts.CUDA = IK == IK_CUDA || IK == IK_PreprocessedCuda || - LangStd == LangStandard::lang_cuda; + Opts.CUDA = IK.getLanguage() == InputKind::CUDA; if (Opts.CUDA) // Set default FP_CONTRACT to FAST. Opts.setDefaultFPContractMode(LangOptions::FPC_Fast); - Opts.RenderScript = IK == IK_RenderScript; + Opts.RenderScript = IK.getLanguage() == InputKind::RenderScript; if (Opts.RenderScript) { Opts.NativeHalfType = 1; Opts.NativeHalfArgsAndReturns = 1; @@ -1705,58 +1720,65 @@ static Visibility parseVisibility(Arg *arg, ArgList &args, /// Check if input file kind and language standard are compatible. static bool IsInputCompatibleWithStandard(InputKind IK, const LangStandard &S) { - switch (IK) { - case IK_C: - case IK_ObjC: - case IK_PreprocessedC: - case IK_PreprocessedObjC: - if (S.isC89() || S.isC99()) - return true; - break; - case IK_CXX: - case IK_ObjCXX: - case IK_PreprocessedCXX: - case IK_PreprocessedObjCXX: - if (S.isCPlusPlus()) - return true; - break; - case IK_OpenCL: - if (S.isOpenCL()) - return true; - break; - case IK_CUDA: - case IK_PreprocessedCuda: - if (S.isCPlusPlus()) - return true; - break; - default: - // For other inputs, accept (and ignore) all -std= values. + switch (IK.getLanguage()) { + case InputKind::Unknown: + case InputKind::LLVM_IR: + llvm_unreachable("should not parse language flags for this input"); + + case InputKind::C: + case InputKind::ObjC: + case InputKind::RenderScript: + return S.getLanguage() == InputKind::C; + + case InputKind::OpenCL: + return S.getLanguage() == InputKind::OpenCL; + + case InputKind::CXX: + case InputKind::ObjCXX: + return S.getLanguage() == InputKind::CXX; + + case InputKind::CUDA: + // FIXME: What -std= values should be permitted for CUDA compilations? + return S.getLanguage() == InputKind::CUDA || + S.getLanguage() == InputKind::CXX; + + case InputKind::Asm: + // Accept (and ignore) all -std= values. + // FIXME: The -std= value is not ignored; it affects the tokenization + // and preprocessing rules if we're preprocessing this asm input. return true; } - return false; + + llvm_unreachable("unexpected input language"); } /// Get language name for given input kind. static const StringRef GetInputKindName(InputKind IK) { - switch (IK) { - case IK_C: - case IK_ObjC: - case IK_PreprocessedC: - case IK_PreprocessedObjC: - return "C/ObjC"; - case IK_CXX: - case IK_ObjCXX: - case IK_PreprocessedCXX: - case IK_PreprocessedObjCXX: - return "C++/ObjC++"; - case IK_OpenCL: + switch (IK.getLanguage()) { + case InputKind::C: + return "C"; + case InputKind::ObjC: + return "Objective-C"; + case InputKind::CXX: + return "C++"; + case InputKind::ObjCXX: + return "Objective-C++"; + case InputKind::OpenCL: return "OpenCL"; - case IK_CUDA: - case IK_PreprocessedCuda: + case InputKind::CUDA: return "CUDA"; - default: - llvm_unreachable("Cannot decide on name for InputKind!"); + case InputKind::RenderScript: + return "RenderScript"; + + case InputKind::Asm: + return "Asm"; + case InputKind::LLVM_IR: + return "LLVM IR"; + + case InputKind::Unknown: + break; } + llvm_unreachable("unknown input language"); } static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, @@ -1767,7 +1789,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, LangStandard::Kind LangStd = LangStandard::lang_unspecified; if (const Arg *A = Args.getLastArg(OPT_std_EQ)) { LangStd = llvm::StringSwitch<LangStandard::Kind>(A->getValue()) -#define LANGSTANDARD(id, name, desc, features) \ +#define LANGSTANDARD(id, name, lang, desc, features) \ .Case(name, LangStandard::lang_##id) #define LANGSTANDARD_ALIAS(id, alias) \ .Case(alias, LangStandard::lang_##id) @@ -1783,8 +1805,20 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, const LangStandard &Std = LangStandard::getLangStandardForKind( static_cast<LangStandard::Kind>(KindValue)); if (IsInputCompatibleWithStandard(IK, Std)) { - Diags.Report(diag::note_drv_use_standard) - << Std.getName() << Std.getDescription(); + auto Diag = Diags.Report(diag::note_drv_use_standard); + Diag << Std.getName() << Std.getDescription(); + unsigned NumAliases = 0; +#define LANGSTANDARD(id, name, lang, desc, features) +#define LANGSTANDARD_ALIAS(id, alias) \ + if (KindValue == LangStandard::lang_##id) ++NumAliases; +#define LANGSTANDARD_ALIAS_DEPR(id, alias) +#include "clang/Frontend/LangStandards.def" + Diag << NumAliases; +#define LANGSTANDARD(id, name, lang, desc, features) +#define LANGSTANDARD_ALIAS(id, alias) \ + if (KindValue == LangStandard::lang_##id) Diag << alias; +#define LANGSTANDARD_ALIAS_DEPR(id, alias) +#include "clang/Frontend/LangStandards.def" } } } else { @@ -1803,7 +1837,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) { LangStandard::Kind OpenCLLangStd = llvm::StringSwitch<LangStandard::Kind>(A->getValue()) - .Cases("cl", "CL", LangStandard::lang_opencl) + .Cases("cl", "CL", LangStandard::lang_opencl10) .Cases("cl1.1", "CL1.1", LangStandard::lang_opencl11) .Cases("cl1.2", "CL1.2", LangStandard::lang_opencl12) .Cases("cl2.0", "CL2.0", LangStandard::lang_opencl20) @@ -2533,7 +2567,8 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, Res.getTargetOpts()); ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Res.getFileSystemOpts().WorkingDir); - if (DashX == IK_AST || DashX == IK_LLVM_IR) { + if (DashX.getFormat() == InputKind::Precompiled || + DashX.getLanguage() == InputKind::LLVM_IR) { // ObjCAAutoRefCount and Sanitize LangOpts are used to setup the // PassManager in BackendUtil.cpp. They need to be initializd no matter // what the input type is. @@ -2547,8 +2582,9 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, Diags, LangOpts.Sanitize); } else { // Other LangOpts are only initialzed when the input is not AST or LLVM IR. + // FIXME: Should we really be calling this for an InputKind::Asm input? ParseLangArgs(LangOpts, Args, DashX, Res.getTargetOpts(), - Res.getPreprocessorOpts(), Diags); + Res.getPreprocessorOpts(), Diags); if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC) LangOpts.ObjCExceptions = 1; } diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp index 0dd07d9f817b..d26b6937b851 100644 --- a/lib/Frontend/FrontendAction.cpp +++ b/lib/Frontend/FrontendAction.cpp @@ -224,6 +224,231 @@ static bool ReadOriginalFileName(CompilerInstance &CI, std::string &InputFile) return true; } +static SmallVectorImpl<char> & +operator+=(SmallVectorImpl<char> &Includes, StringRef RHS) { + Includes.append(RHS.begin(), RHS.end()); + return Includes; +} + +static void addHeaderInclude(StringRef HeaderName, + SmallVectorImpl<char> &Includes, + const LangOptions &LangOpts, + bool IsExternC) { + if (IsExternC && LangOpts.CPlusPlus) + Includes += "extern \"C\" {\n"; + if (LangOpts.ObjC1) + Includes += "#import \""; + else + Includes += "#include \""; + + Includes += HeaderName; + + Includes += "\"\n"; + if (IsExternC && LangOpts.CPlusPlus) + Includes += "}\n"; +} + +/// \brief Collect the set of header includes needed to construct the given +/// module and update the TopHeaders file set of the module. +/// +/// \param Module The module we're collecting includes from. +/// +/// \param Includes Will be augmented with the set of \#includes or \#imports +/// needed to load all of the named headers. +static std::error_code +collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr, + ModuleMap &ModMap, clang::Module *Module, + SmallVectorImpl<char> &Includes) { + // Don't collect any headers for unavailable modules. + if (!Module->isAvailable()) + return std::error_code(); + + // Add includes for each of these headers. + for (auto HK : {Module::HK_Normal, Module::HK_Private}) { + for (Module::Header &H : Module->Headers[HK]) { + Module->addTopHeader(H.Entry); + // Use the path as specified in the module map file. We'll look for this + // file relative to the module build directory (the directory containing + // the module map file) so this will find the same file that we found + // while parsing the module map. + addHeaderInclude(H.NameAsWritten, Includes, LangOpts, Module->IsExternC); + } + } + // Note that Module->PrivateHeaders will not be a TopHeader. + + if (Module::Header UmbrellaHeader = Module->getUmbrellaHeader()) { + Module->addTopHeader(UmbrellaHeader.Entry); + if (Module->Parent) + // Include the umbrella header for submodules. + addHeaderInclude(UmbrellaHeader.NameAsWritten, Includes, LangOpts, + Module->IsExternC); + } else if (Module::DirectoryName UmbrellaDir = Module->getUmbrellaDir()) { + // Add all of the headers we find in this subdirectory. + std::error_code EC; + SmallString<128> DirNative; + llvm::sys::path::native(UmbrellaDir.Entry->getName(), DirNative); + + vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); + for (vfs::recursive_directory_iterator Dir(FS, DirNative, EC), End; + Dir != End && !EC; Dir.increment(EC)) { + // Check whether this entry has an extension typically associated with + // headers. + if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->getName())) + .Cases(".h", ".H", ".hh", ".hpp", true) + .Default(false)) + continue; + + const FileEntry *Header = FileMgr.getFile(Dir->getName()); + // FIXME: This shouldn't happen unless there is a file system race. Is + // that worth diagnosing? + if (!Header) + continue; + + // If this header is marked 'unavailable' in this module, don't include + // it. + if (ModMap.isHeaderUnavailableInModule(Header, Module)) + continue; + + // Compute the relative path from the directory to this file. + SmallVector<StringRef, 16> Components; + auto PathIt = llvm::sys::path::rbegin(Dir->getName()); + for (int I = 0; I != Dir.level() + 1; ++I, ++PathIt) + Components.push_back(*PathIt); + SmallString<128> RelativeHeader(UmbrellaDir.NameAsWritten); + for (auto It = Components.rbegin(), End = Components.rend(); It != End; + ++It) + llvm::sys::path::append(RelativeHeader, *It); + + // Include this header as part of the umbrella directory. + Module->addTopHeader(Header); + addHeaderInclude(RelativeHeader, Includes, LangOpts, Module->IsExternC); + } + + if (EC) + return EC; + } + + // Recurse into submodules. + for (clang::Module::submodule_iterator Sub = Module->submodule_begin(), + SubEnd = Module->submodule_end(); + Sub != SubEnd; ++Sub) + if (std::error_code Err = collectModuleHeaderIncludes( + LangOpts, FileMgr, ModMap, *Sub, Includes)) + return Err; + + return std::error_code(); +} + +/// Parse a module map and compute the corresponding real input buffer that +/// should be used to build the module described by that module map and the +/// current module name. +static std::unique_ptr<llvm::MemoryBuffer> +getInputBufferForModuleMap(CompilerInstance &CI, StringRef Filename, + bool IsSystem) { + // Find the module map file. + const FileEntry *ModuleMap = + CI.getFileManager().getFile(Filename, /*openFile*/true); + if (!ModuleMap) { + CI.getDiagnostics().Report(diag::err_module_map_not_found) + << Filename; + return nullptr; + } + + // Find the module map file from which it was generated, if different. + const FileEntry *OriginalModuleMap = ModuleMap; + StringRef OriginalModuleMapName = CI.getFrontendOpts().OriginalModuleMap; + if (!OriginalModuleMapName.empty()) { + OriginalModuleMap = CI.getFileManager().getFile(OriginalModuleMapName, + /*openFile*/ true); + if (!OriginalModuleMap) { + CI.getDiagnostics().Report(diag::err_module_map_not_found) + << OriginalModuleMapName; + return nullptr; + } + } + + // Parse the module map file. + HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); + if (HS.loadModuleMapFile(ModuleMap, IsSystem)) + return nullptr; + + if (CI.getLangOpts().CurrentModule.empty()) { + CI.getDiagnostics().Report(diag::err_missing_module_name); + + // FIXME: Eventually, we could consider asking whether there was just + // a single module described in the module map, and use that as a + // default. Then it would be fairly trivial to just "compile" a module + // map with a single module (the common case). + return nullptr; + } + + // If we're being run from the command-line, the module build stack will not + // have been filled in yet, so complete it now in order to allow us to detect + // module cycles. + SourceManager &SourceMgr = CI.getSourceManager(); + if (SourceMgr.getModuleBuildStack().empty()) + SourceMgr.pushModuleBuildStack(CI.getLangOpts().CurrentModule, + FullSourceLoc(SourceLocation(), SourceMgr)); + + // Dig out the module definition. + Module *M = HS.lookupModule(CI.getLangOpts().CurrentModule, + /*AllowSearch=*/false); + if (!M) { + CI.getDiagnostics().Report(diag::err_missing_module) + << CI.getLangOpts().CurrentModule << Filename; + + return nullptr; + } + + // Check whether we can build this module at all. + clang::Module::Requirement Requirement; + clang::Module::UnresolvedHeaderDirective MissingHeader; + if (!M->isAvailable(CI.getLangOpts(), CI.getTarget(), Requirement, + MissingHeader)) { + if (MissingHeader.FileNameLoc.isValid()) { + CI.getDiagnostics().Report(MissingHeader.FileNameLoc, + diag::err_module_header_missing) + << MissingHeader.IsUmbrella << MissingHeader.FileName; + } else { + CI.getDiagnostics().Report(diag::err_module_unavailable) + << M->getFullModuleName() << Requirement.second << Requirement.first; + } + + return nullptr; + } + + if (OriginalModuleMap != ModuleMap) { + M->IsInferred = true; + HS.getModuleMap().setInferredModuleAllowedBy(M, OriginalModuleMap); + } + + FileManager &FileMgr = CI.getFileManager(); + + // Collect the set of #includes we need to build the module. + SmallString<256> HeaderContents; + std::error_code Err = std::error_code(); + if (Module::Header UmbrellaHeader = M->getUmbrellaHeader()) + addHeaderInclude(UmbrellaHeader.NameAsWritten, HeaderContents, + CI.getLangOpts(), M->IsExternC); + Err = collectModuleHeaderIncludes( + CI.getLangOpts(), FileMgr, + CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), M, + HeaderContents); + + if (Err) { + CI.getDiagnostics().Report(diag::err_module_cannot_create_includes) + << M->getFullModuleName() << Err.message(); + return nullptr; + } + + // Inform the preprocessor that includes from within the input buffer should + // be resolved relative to the build directory of the module map file. + CI.getPreprocessor().setMainFileDir(M->Directory); + + return llvm::MemoryBuffer::getMemBufferCopy( + HeaderContents, Module::getModuleInputBufferName()); +} + bool FrontendAction::BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input) { assert(!Instance && "Already processing a source file!"); @@ -232,13 +457,15 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, setCompilerInstance(&CI); StringRef InputFile = Input.getFile(); + FrontendInputFile FileToProcess = Input; bool HasBegunSourceFile = false; if (!BeginInvocation(CI)) goto failure; // AST files follow a very different path, since they share objects via the // AST unit. - if (Input.getKind() == IK_AST) { + if (Input.getKind().getFormat() == InputKind::Precompiled) { + // FIXME: We should not be asserting on bad command-line arguments. assert(!usesPreprocessorOnly() && "Attempt to pass AST file to preprocessor only action!"); assert(hasASTFileSupport() && @@ -296,8 +523,19 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, if (!CI.hasSourceManager()) CI.createSourceManager(CI.getFileManager()); + // Set up embedding for any specified files. Do this before we load any + // source files, including the primary module map for the compilation. + for (const auto &F : CI.getFrontendOpts().ModulesEmbedFiles) { + if (const auto *FE = CI.getFileManager().getFile(F, /*openFile*/true)) + CI.getSourceManager().setFileIsTransient(FE); + else + CI.getDiagnostics().Report(diag::err_modules_embed_file_not_found) << F; + } + if (CI.getFrontendOpts().ModulesEmbedAllFiles) + CI.getSourceManager().setAllFilesAreTransient(true); + // IR files bypass the rest of initialization. - if (Input.getKind() == IK_LLVM_IR) { + if (Input.getKind().getLanguage() == InputKind::LLVM_IR) { assert(hasIRSupport() && "This action does not have IR file support!"); @@ -359,13 +597,34 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, &CI.getPreprocessor()); HasBegunSourceFile = true; + // For module map files, we first parse the module map and synthesize a + // "<module-includes>" buffer before more conventional processing. + if (Input.getKind().getFormat() == InputKind::ModuleMap) { + CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleMap); + + auto Buffer = getInputBufferForModuleMap(CI, InputFile, Input.isSystem()); + if (!Buffer) + goto failure; + + Module *CurrentModule = + CI.getPreprocessor().getHeaderSearchInfo().lookupModule( + CI.getLangOpts().CurrentModule, + /*AllowSearch=*/false); + assert(CurrentModule && "no module info for current module"); + + // The input that we end up processing is the generated buffer, not the + // module map file itself. + FileToProcess = FrontendInputFile( + Buffer.release(), Input.getKind().withFormat(InputKind::Source), + CurrentModule->IsSystem); + } + // Initialize the action. if (!BeginSourceFileAction(CI, InputFile)) goto failure; - // Initialize the main file entry. It is important that this occurs after - // BeginSourceFileAction, which may change CurrentInput during module builds. - if (!CI.InitializeSourceManager(CurrentInput)) + // Initialize the main file entry. + if (!CI.InitializeSourceManager(FileToProcess)) goto failure; // Create the AST context and consumer unless this is a preprocessor only @@ -497,6 +756,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, if (HasBegunSourceFile) CI.getDiagnosticClient().EndSourceFile(); CI.clearOutputFiles(/*EraseFiles=*/true); + CI.getLangOpts().setCompilingModule(LangOptions::CMK_None); setCurrentInput(FrontendInputFile()); setCompilerInstance(nullptr); return false; @@ -579,6 +839,7 @@ void FrontendAction::EndSourceFile() { setCompilerInstance(nullptr); setCurrentInput(FrontendInputFile()); + CI.getLangOpts().setCompilingModule(LangOptions::CMK_None); } bool FrontendAction::shouldEraseOutputFiles() { diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index e818038b1354..dd7c12f60f0e 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -164,242 +164,9 @@ GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI, return llvm::make_unique<MultiplexConsumer>(std::move(Consumers)); } -bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI, - StringRef Filename) { - // Set up embedding for any specified files. Do this before we load any - // source files, including the primary module map for the compilation. - for (const auto &F : CI.getFrontendOpts().ModulesEmbedFiles) { - if (const auto *FE = CI.getFileManager().getFile(F, /*openFile*/true)) - CI.getSourceManager().setFileIsTransient(FE); - else - CI.getDiagnostics().Report(diag::err_modules_embed_file_not_found) << F; - } - if (CI.getFrontendOpts().ModulesEmbedAllFiles) - CI.getSourceManager().setAllFilesAreTransient(true); - - return true; -} - - -static SmallVectorImpl<char> & -operator+=(SmallVectorImpl<char> &Includes, StringRef RHS) { - Includes.append(RHS.begin(), RHS.end()); - return Includes; -} - -static void addHeaderInclude(StringRef HeaderName, - SmallVectorImpl<char> &Includes, - const LangOptions &LangOpts, - bool IsExternC) { - if (IsExternC && LangOpts.CPlusPlus) - Includes += "extern \"C\" {\n"; - if (LangOpts.ObjC1) - Includes += "#import \""; - else - Includes += "#include \""; - - Includes += HeaderName; - - Includes += "\"\n"; - if (IsExternC && LangOpts.CPlusPlus) - Includes += "}\n"; -} - -/// \brief Collect the set of header includes needed to construct the given -/// module and update the TopHeaders file set of the module. -/// -/// \param Module The module we're collecting includes from. -/// -/// \param Includes Will be augmented with the set of \#includes or \#imports -/// needed to load all of the named headers. -static std::error_code -collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr, - ModuleMap &ModMap, clang::Module *Module, - SmallVectorImpl<char> &Includes) { - // Don't collect any headers for unavailable modules. - if (!Module->isAvailable()) - return std::error_code(); - - // Add includes for each of these headers. - for (auto HK : {Module::HK_Normal, Module::HK_Private}) { - for (Module::Header &H : Module->Headers[HK]) { - Module->addTopHeader(H.Entry); - // Use the path as specified in the module map file. We'll look for this - // file relative to the module build directory (the directory containing - // the module map file) so this will find the same file that we found - // while parsing the module map. - addHeaderInclude(H.NameAsWritten, Includes, LangOpts, Module->IsExternC); - } - } - // Note that Module->PrivateHeaders will not be a TopHeader. - - if (Module::Header UmbrellaHeader = Module->getUmbrellaHeader()) { - Module->addTopHeader(UmbrellaHeader.Entry); - if (Module->Parent) - // Include the umbrella header for submodules. - addHeaderInclude(UmbrellaHeader.NameAsWritten, Includes, LangOpts, - Module->IsExternC); - } else if (Module::DirectoryName UmbrellaDir = Module->getUmbrellaDir()) { - // Add all of the headers we find in this subdirectory. - std::error_code EC; - SmallString<128> DirNative; - llvm::sys::path::native(UmbrellaDir.Entry->getName(), DirNative); - - vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); - for (vfs::recursive_directory_iterator Dir(FS, DirNative, EC), End; - Dir != End && !EC; Dir.increment(EC)) { - // Check whether this entry has an extension typically associated with - // headers. - if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->getName())) - .Cases(".h", ".H", ".hh", ".hpp", true) - .Default(false)) - continue; - - const FileEntry *Header = FileMgr.getFile(Dir->getName()); - // FIXME: This shouldn't happen unless there is a file system race. Is - // that worth diagnosing? - if (!Header) - continue; - - // If this header is marked 'unavailable' in this module, don't include - // it. - if (ModMap.isHeaderUnavailableInModule(Header, Module)) - continue; - - // Compute the relative path from the directory to this file. - SmallVector<StringRef, 16> Components; - auto PathIt = llvm::sys::path::rbegin(Dir->getName()); - for (int I = 0; I != Dir.level() + 1; ++I, ++PathIt) - Components.push_back(*PathIt); - SmallString<128> RelativeHeader(UmbrellaDir.NameAsWritten); - for (auto It = Components.rbegin(), End = Components.rend(); It != End; - ++It) - llvm::sys::path::append(RelativeHeader, *It); - - // Include this header as part of the umbrella directory. - Module->addTopHeader(Header); - addHeaderInclude(RelativeHeader, Includes, LangOpts, Module->IsExternC); - } - - if (EC) - return EC; - } - - // Recurse into submodules. - for (clang::Module::submodule_iterator Sub = Module->submodule_begin(), - SubEnd = Module->submodule_end(); - Sub != SubEnd; ++Sub) - if (std::error_code Err = collectModuleHeaderIncludes( - LangOpts, FileMgr, ModMap, *Sub, Includes)) - return Err; - - return std::error_code(); -} - bool GenerateModuleFromModuleMapAction::BeginSourceFileAction( CompilerInstance &CI, StringRef Filename) { - CI.getLangOpts().setCompilingModule(LangOptions::CMK_ModuleMap); - - if (!GenerateModuleAction::BeginSourceFileAction(CI, Filename)) - return false; - - // Find the module map file. - const FileEntry *ModuleMap = - CI.getFileManager().getFile(Filename, /*openFile*/true); - if (!ModuleMap) { - CI.getDiagnostics().Report(diag::err_module_map_not_found) - << Filename; - return false; - } - - // Parse the module map file. - HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); - if (HS.loadModuleMapFile(ModuleMap, IsSystem)) - return false; - - if (CI.getLangOpts().CurrentModule.empty()) { - CI.getDiagnostics().Report(diag::err_missing_module_name); - - // FIXME: Eventually, we could consider asking whether there was just - // a single module described in the module map, and use that as a - // default. Then it would be fairly trivial to just "compile" a module - // map with a single module (the common case). - return false; - } - - // If we're being run from the command-line, the module build stack will not - // have been filled in yet, so complete it now in order to allow us to detect - // module cycles. - SourceManager &SourceMgr = CI.getSourceManager(); - if (SourceMgr.getModuleBuildStack().empty()) - SourceMgr.pushModuleBuildStack(CI.getLangOpts().CurrentModule, - FullSourceLoc(SourceLocation(), SourceMgr)); - - // Dig out the module definition. - Module = HS.lookupModule(CI.getLangOpts().CurrentModule, - /*AllowSearch=*/false); - if (!Module) { - CI.getDiagnostics().Report(diag::err_missing_module) - << CI.getLangOpts().CurrentModule << Filename; - - return false; - } - - // Check whether we can build this module at all. - clang::Module::Requirement Requirement; - clang::Module::UnresolvedHeaderDirective MissingHeader; - if (!Module->isAvailable(CI.getLangOpts(), CI.getTarget(), Requirement, - MissingHeader)) { - if (MissingHeader.FileNameLoc.isValid()) { - CI.getDiagnostics().Report(MissingHeader.FileNameLoc, - diag::err_module_header_missing) - << MissingHeader.IsUmbrella << MissingHeader.FileName; - } else { - CI.getDiagnostics().Report(diag::err_module_unavailable) - << Module->getFullModuleName() - << Requirement.second << Requirement.first; - } - - return false; - } - - if (ModuleMapForUniquing && ModuleMapForUniquing != ModuleMap) { - Module->IsInferred = true; - HS.getModuleMap().setInferredModuleAllowedBy(Module, ModuleMapForUniquing); - } else { - ModuleMapForUniquing = ModuleMap; - } - - FileManager &FileMgr = CI.getFileManager(); - - // Collect the set of #includes we need to build the module. - SmallString<256> HeaderContents; - std::error_code Err = std::error_code(); - if (Module::Header UmbrellaHeader = Module->getUmbrellaHeader()) - addHeaderInclude(UmbrellaHeader.NameAsWritten, HeaderContents, - CI.getLangOpts(), Module->IsExternC); - Err = collectModuleHeaderIncludes( - CI.getLangOpts(), FileMgr, - CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), Module, - HeaderContents); - - if (Err) { - CI.getDiagnostics().Report(diag::err_module_cannot_create_includes) - << Module->getFullModuleName() << Err.message(); - return false; - } - - // Inform the preprocessor that includes from within the input buffer should - // be resolved relative to the build directory of the module map file. - CI.getPreprocessor().setMainFileDir(Module->Directory); - - std::unique_ptr<llvm::MemoryBuffer> InputBuffer = - llvm::MemoryBuffer::getMemBufferCopy(HeaderContents, - Module::getModuleInputBufferName()); - // Ownership of InputBuffer will be transferred to the SourceManager. - setCurrentInput(FrontendInputFile(InputBuffer.release(), getCurrentFileKind(), - Module->IsSystem)); - return true; + return GenerateModuleAction::BeginSourceFileAction(CI, Filename); } std::unique_ptr<raw_pwrite_stream> @@ -408,10 +175,13 @@ GenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI, // If no output file was provided, figure out where this module would go // in the module cache. if (CI.getFrontendOpts().OutputFile.empty()) { + StringRef ModuleMapFile = CI.getFrontendOpts().OriginalModuleMap; + if (ModuleMapFile.empty()) + ModuleMapFile = InFile; + HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); CI.getFrontendOpts().OutputFile = - HS.getModuleFileName(CI.getLangOpts().CurrentModule, - ModuleMapForUniquing->getName(), + HS.getModuleFileName(CI.getLangOpts().CurrentModule, ModuleMapFile, /*UsePrebuiltPath=*/false); } @@ -777,29 +547,27 @@ void PrintPreprocessedAction::ExecuteAction() { } void PrintPreambleAction::ExecuteAction() { - switch (getCurrentFileKind()) { - case IK_C: - case IK_CXX: - case IK_ObjC: - case IK_ObjCXX: - case IK_OpenCL: - case IK_CUDA: + switch (getCurrentFileKind().getLanguage()) { + case InputKind::C: + case InputKind::CXX: + case InputKind::ObjC: + case InputKind::ObjCXX: + case InputKind::OpenCL: + case InputKind::CUDA: break; - case IK_None: - case IK_Asm: - case IK_PreprocessedC: - case IK_PreprocessedCuda: - case IK_PreprocessedCXX: - case IK_PreprocessedObjC: - case IK_PreprocessedObjCXX: - case IK_AST: - case IK_LLVM_IR: - case IK_RenderScript: + case InputKind::Unknown: + case InputKind::Asm: + case InputKind::LLVM_IR: + case InputKind::RenderScript: // We can't do anything with these. return; } + // We don't expect to find any #include directives in a preprocessed input. + if (getCurrentFileKind().isPreprocessed()) + return; + CompilerInstance &CI = getCompilerInstance(); auto Buffer = CI.getFileManager().getBufferForFile(getCurrentFile()); if (Buffer) { diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp index 6a82084aff1b..dca434588fb1 100644 --- a/lib/Frontend/FrontendOptions.cpp +++ b/lib/Frontend/FrontendOptions.cpp @@ -13,22 +13,22 @@ using namespace clang; InputKind FrontendOptions::getInputKindForExtension(StringRef Extension) { return llvm::StringSwitch<InputKind>(Extension) - .Cases("ast", "pcm", IK_AST) - .Case("c", IK_C) - .Cases("S", "s", IK_Asm) - .Case("i", IK_PreprocessedC) - .Case("ii", IK_PreprocessedCXX) - .Case("cui", IK_PreprocessedCuda) - .Case("m", IK_ObjC) - .Case("mi", IK_PreprocessedObjC) - .Cases("mm", "M", IK_ObjCXX) - .Case("mii", IK_PreprocessedObjCXX) - .Cases("C", "cc", "cp", IK_CXX) - .Cases("cpp", "CPP", "c++", "cxx", "hpp", IK_CXX) - .Case("cppm", IK_CXX) - .Case("iim", IK_PreprocessedCXX) - .Case("cl", IK_OpenCL) - .Case("cu", IK_CUDA) - .Cases("ll", "bc", IK_LLVM_IR) - .Default(IK_C); + .Cases("ast", "pcm", InputKind(InputKind::Unknown, InputKind::Precompiled)) + .Case("c", InputKind::C) + .Cases("S", "s", InputKind::Asm) + .Case("i", InputKind(InputKind::C).getPreprocessed()) + .Case("ii", InputKind(InputKind::CXX).getPreprocessed()) + .Case("cui", InputKind(InputKind::CUDA).getPreprocessed()) + .Case("m", InputKind::ObjC) + .Case("mi", InputKind(InputKind::ObjC).getPreprocessed()) + .Cases("mm", "M", InputKind::ObjCXX) + .Case("mii", InputKind(InputKind::ObjCXX).getPreprocessed()) + .Cases("C", "cc", "cp", InputKind::CXX) + .Cases("cpp", "CPP", "c++", "cxx", "hpp", InputKind::CXX) + .Case("cppm", InputKind::CXX) + .Case("iim", InputKind(InputKind::CXX).getPreprocessed()) + .Case("cl", InputKind::OpenCL) + .Case("cu", InputKind::CUDA) + .Cases("ll", "bc", InputKind::LLVM_IR) + .Default(InputKind::Unknown); } diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index 0dd04e8a8fff..9257dcae84cd 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -1041,6 +1041,8 @@ void clang::InitializePreprocessor( // Install things like __POWERPC__, __GNUC__, etc into the macro table. if (InitOpts.UsePredefines) { + // FIXME: This will create multiple definitions for most of the predefined + // macros. This is not the right way to handle this. if (LangOpts.CUDA && PP.getAuxTargetInfo()) InitializePredefinedMacros(*PP.getAuxTargetInfo(), LangOpts, FEOpts, Builder); diff --git a/lib/Frontend/LangStandards.cpp b/lib/Frontend/LangStandards.cpp index f133327f4298..47023e58fa0b 100644 --- a/lib/Frontend/LangStandards.cpp +++ b/lib/Frontend/LangStandards.cpp @@ -13,15 +13,15 @@ using namespace clang; using namespace clang::frontend; -#define LANGSTANDARD(id, name, desc, features) \ - static const LangStandard Lang_##id = { name, desc, features }; +#define LANGSTANDARD(id, name, lang, desc, features) \ +static const LangStandard Lang_##id = { name, desc, features, InputKind::lang }; #include "clang/Frontend/LangStandards.def" const LangStandard &LangStandard::getLangStandardForKind(Kind K) { switch (K) { case lang_unspecified: llvm::report_fatal_error("getLangStandardForKind() on unspecified kind"); -#define LANGSTANDARD(id, name, desc, features) \ +#define LANGSTANDARD(id, name, lang, desc, features) \ case lang_##id: return Lang_##id; #include "clang/Frontend/LangStandards.def" } @@ -30,7 +30,7 @@ const LangStandard &LangStandard::getLangStandardForKind(Kind K) { const LangStandard *LangStandard::getLangStandardForName(StringRef Name) { Kind K = llvm::StringSwitch<Kind>(Name) -#define LANGSTANDARD(id, name, desc, features) \ +#define LANGSTANDARD(id, name, lang, desc, features) \ .Case(name, lang_##id) #include "clang/Frontend/LangStandards.def" .Default(lang_unspecified); diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index d48b952ef203..ffedf3cac847 100644 --- a/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/lib/Frontend/PrintPreprocessedOutput.cpp @@ -172,7 +172,8 @@ public: /// MacroUndefined - This hook is called whenever a macro #undef is seen. void MacroUndefined(const Token &MacroNameTok, - const MacroDefinition &MD) override; + const MacroDefinition &MD, + const MacroDirective *Undef) override; }; } // end anonymous namespace @@ -323,43 +324,50 @@ void PrintPPOutputPPCallbacks::InclusionDirective(SourceLocation HashLoc, StringRef SearchPath, StringRef RelativePath, const Module *Imported) { - if (Imported) { - // When preprocessing, turn implicit imports into @imports. - // FIXME: This is a stop-gap until a more comprehensive "preprocessing with - // modules" solution is introduced. + // In -dI mode, dump #include directives prior to dumping their content or + // interpretation. + if (DumpIncludeDirectives) { startNewLineIfNeeded(); MoveToLine(HashLoc); - if (PP.getLangOpts().ObjC2) { - OS << "@import " << Imported->getFullModuleName() << ";" - << " /* clang -E: implicit import for \"" << File->getName() - << "\" */"; - } else { - const std::string TokenText = PP.getSpelling(IncludeTok); - assert(!TokenText.empty()); - OS << "#" << TokenText << " " - << (IsAngled ? '<' : '"') - << FileName - << (IsAngled ? '>' : '"') - << " /* clang -E: implicit import for module " - << Imported->getFullModuleName() << " */"; - } - // Since we want a newline after the @import, but not a #<line>, start a new - // line immediately. - EmittedTokensOnThisLine = true; + const std::string TokenText = PP.getSpelling(IncludeTok); + assert(!TokenText.empty()); + OS << "#" << TokenText << " " + << (IsAngled ? '<' : '"') << FileName << (IsAngled ? '>' : '"') + << " /* clang -E -dI */"; + setEmittedDirectiveOnThisLine(); startNewLineIfNeeded(); - } else { - // Not a module import; it's a more vanilla inclusion of some file using one - // of: #include, #import, #include_next, #include_macros. - if (DumpIncludeDirectives) { + } + + // When preprocessing, turn implicit imports into module import pragmas. + if (Imported) { + switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { + case tok::pp_include: + case tok::pp_import: + case tok::pp_include_next: startNewLineIfNeeded(); MoveToLine(HashLoc); - const std::string TokenText = PP.getSpelling(IncludeTok); - assert(!TokenText.empty()); - OS << "#" << TokenText << " " + OS << "#pragma clang module import " << Imported->getFullModuleName() + << " /* clang -E: implicit import for " + << "#" << PP.getSpelling(IncludeTok) << " " << (IsAngled ? '<' : '"') << FileName << (IsAngled ? '>' : '"') - << " /* clang -E -dI */"; - setEmittedDirectiveOnThisLine(); + << " */"; + // Since we want a newline after the pragma, but not a #<line>, start a + // new line immediately. + EmittedTokensOnThisLine = true; startNewLineIfNeeded(); + break; + + case tok::pp___include_macros: + // #__include_macros has no effect on a user of a preprocessed source + // file; the only effect is on preprocessing. + // + // FIXME: That's not *quite* true: it causes the module in question to + // be loaded, which can affect downstream diagnostics. + break; + + default: + llvm_unreachable("unknown include directive kind"); + break; } } } @@ -389,7 +397,8 @@ void PrintPPOutputPPCallbacks::MacroDefined(const Token &MacroNameTok, } void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok, - const MacroDefinition &MD) { + const MacroDefinition &MD, + const MacroDirective *Undef) { // Only print out macro definitions in -dD mode. if (!DumpDefines) return; @@ -773,26 +782,33 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS, // Expand macros in pragmas with -fms-extensions. The assumption is that // the majority of pragmas in such a file will be Microsoft pragmas. - PP.AddPragmaHandler(new UnknownPragmaHandler( - "#pragma", Callbacks, + // Remember the handlers we will add so that we can remove them later. + std::unique_ptr<UnknownPragmaHandler> MicrosoftExtHandler( + new UnknownPragmaHandler( + "#pragma", Callbacks, + /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); + + std::unique_ptr<UnknownPragmaHandler> GCCHandler(new UnknownPragmaHandler( + "#pragma GCC", Callbacks, /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); - PP.AddPragmaHandler( - "GCC", new UnknownPragmaHandler( - "#pragma GCC", Callbacks, - /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); - PP.AddPragmaHandler( - "clang", new UnknownPragmaHandler( - "#pragma clang", Callbacks, - /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); + + std::unique_ptr<UnknownPragmaHandler> ClangHandler(new UnknownPragmaHandler( + "#pragma clang", Callbacks, + /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); + + PP.AddPragmaHandler(MicrosoftExtHandler.get()); + PP.AddPragmaHandler("GCC", GCCHandler.get()); + PP.AddPragmaHandler("clang", ClangHandler.get()); // The tokens after pragma omp need to be expanded. // // OpenMP [2.1, Directive format] // Preprocessing tokens following the #pragma omp are subject to macro // replacement. - PP.AddPragmaHandler("omp", - new UnknownPragmaHandler("#pragma omp", Callbacks, - /*RequireTokenExpansion=*/true)); + std::unique_ptr<UnknownPragmaHandler> OpenMPHandler( + new UnknownPragmaHandler("#pragma omp", Callbacks, + /*RequireTokenExpansion=*/true)); + PP.AddPragmaHandler("omp", OpenMPHandler.get()); PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks)); @@ -820,4 +836,11 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS, // Read all the preprocessed tokens, printing them out to the stream. PrintPreprocessedTokens(PP, Tok, Callbacks, *OS); *OS << '\n'; + + // Remove the handlers we just added to leave the preprocessor in a sane state + // so that it can be reused (for example by a clang::Parser instance). + PP.RemovePragmaHandler(MicrosoftExtHandler.get()); + PP.RemovePragmaHandler("GCC", GCCHandler.get()); + PP.RemovePragmaHandler("clang", ClangHandler.get()); + PP.RemovePragmaHandler("omp", OpenMPHandler.get()); } diff --git a/lib/Frontend/Rewrite/InclusionRewriter.cpp b/lib/Frontend/Rewrite/InclusionRewriter.cpp index d953da2e4fd2..ee61f76d029d 100644 --- a/lib/Frontend/Rewrite/InclusionRewriter.cpp +++ b/lib/Frontend/Rewrite/InclusionRewriter.cpp @@ -52,7 +52,7 @@ class InclusionRewriter : public PPCallbacks { public: InclusionRewriter(Preprocessor &PP, raw_ostream &OS, bool ShowLineMarkers, bool UseLineDirectives); - bool Process(FileID FileId, SrcMgr::CharacteristicKind FileType); + void Process(FileID FileId, SrcMgr::CharacteristicKind FileType); void setPredefinesBuffer(const llvm::MemoryBuffer *Buf) { PredefinesBuffer = Buf; } @@ -132,7 +132,7 @@ void InclusionRewriter::WriteLineInfo(StringRef Filename, int Line, } void InclusionRewriter::WriteImplicitModuleImport(const Module *Mod) { - OS << "@import " << Mod->getFullModuleName() << ";" + OS << "#pragma clang module import " << Mod->getFullModuleName() << " /* clang -frewrite-includes: implicit import */" << MainEOL; } @@ -392,7 +392,7 @@ bool InclusionRewriter::HandleHasInclude( // FIXME: Why don't we call PP.LookupFile here? const FileEntry *File = PP.getHeaderSearchInfo().LookupFile( Filename, SourceLocation(), isAngled, nullptr, CurDir, Includers, nullptr, - nullptr, nullptr, nullptr, false); + nullptr, nullptr, nullptr, nullptr); FileExists = File != nullptr; return true; @@ -400,9 +400,8 @@ bool InclusionRewriter::HandleHasInclude( /// Use a raw lexer to analyze \p FileId, incrementally copying parts of it /// and including content of included files recursively. -bool InclusionRewriter::Process(FileID FileId, - SrcMgr::CharacteristicKind FileType) -{ +void InclusionRewriter::Process(FileID FileId, + SrcMgr::CharacteristicKind FileType) { bool Invalid; const MemoryBuffer &FromFile = *SM.getBuffer(FileId, &Invalid); assert(!Invalid && "Attempting to process invalid inclusion"); @@ -419,7 +418,7 @@ bool InclusionRewriter::Process(FileID FileId, WriteLineInfo(FileName, 1, FileType, " 1"); if (SM.getFileIDSize(FileId) == 0) - return false; + return; // The next byte to be copied from the source file, which may be non-zero if // the lexer handled a BOM. @@ -450,19 +449,14 @@ bool InclusionRewriter::Process(FileID FileId, WriteLineInfo(FileName, Line - 1, FileType, ""); StringRef LineInfoExtra; SourceLocation Loc = HashToken.getLocation(); - if (const Module *Mod = PP.getLangOpts().ObjC2 - ? FindModuleAtLocation(Loc) - : nullptr) + if (const Module *Mod = FindModuleAtLocation(Loc)) WriteImplicitModuleImport(Mod); else if (const IncludedFile *Inc = FindIncludeAtLocation(Loc)) { - // include and recursively process the file - if (Process(Inc->Id, Inc->FileType)) { - // and set lineinfo back to this file, if the nested one was - // actually included - // `2' indicates returning to a file (after having included - // another file. - LineInfoExtra = " 2"; - } + // Include and recursively process the file. + Process(Inc->Id, Inc->FileType); + // Add line marker to indicate we're returning from an included + // file. + LineInfoExtra = " 2"; } // fix up lineinfo (since commented out directive changed line // numbers) for inclusions that were skipped due to header guards @@ -571,7 +565,6 @@ bool InclusionRewriter::Process(FileID FileId, OutputContentUpTo(FromFile, NextToWrite, SM.getFileOffset(SM.getLocForEndOfFile(FileId)), LocalEOL, Line, /*EnsureNewline=*/true); - return true; } /// InclusionRewriterInInput - Implement -frewrite-includes mode. diff --git a/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp index ae16ea177ffe..427d15ed703a 100644 --- a/lib/Frontend/VerifyDiagnosticConsumer.cpp +++ b/lib/Frontend/VerifyDiagnosticConsumer.cpp @@ -400,7 +400,7 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM, const DirectoryLookup *CurDir; const FileEntry *FE = PP->LookupFile(Pos, Filename, false, nullptr, nullptr, CurDir, - nullptr, nullptr, nullptr); + nullptr, nullptr, nullptr, nullptr); if (!FE) { Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), diag::err_verify_missing_file) << Filename << KindStr; |