Index: include/clang/AST/GlobalDecl.h =================================================================== --- include/clang/AST/GlobalDecl.h +++ include/clang/AST/GlobalDecl.h @@ -31,6 +31,7 @@ NoStub = 0, Initializer, AtExit, + GlobalArrayDestructor }; /// GlobalDecl - represents a global declaration. This can either be a Index: include/clang/Driver/Job.h =================================================================== --- include/clang/Driver/Job.h +++ include/clang/Driver/Job.h @@ -130,6 +130,11 @@ /// Set whether to print the input filenames when executing. void setPrintInputFilenames(bool P) { PrintInputFilenames = P; } + + /// When set, we will try re-entering this process for the CC1 command + /// execution, instead of creating a new process. This is an optimization for + /// speed. + static thread_local bool ReenterTool; }; /// Like Command, but with a fallback which is executed in case Index: include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h =================================================================== --- include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h +++ include/clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h @@ -53,8 +53,13 @@ static CachedFileSystemEntry createDirectoryEntry(llvm::vfs::Status &&Stat); /// \returns True if the entry is valid. - bool isValid() const { return !MaybeStat || MaybeStat->isStatusKnown(); } + bool isValid() const { return MaybeStat && MaybeStat->isStatusKnown(); } + std::error_code getErrorCode() const { + assert(!isValid() && "does not have an error code"); + return MaybeStat.getError(); + } + /// \returns The error or the file's contents. llvm::ErrorOr getContents() const { if (!MaybeStat) @@ -155,6 +160,9 @@ return It == Cache.end() ? nullptr : It->getValue(); } + llvm::ErrorOr + getOrCreateFileSystemEntry(const StringRef Filename); + DependencyScanningFilesystemSharedCache &SharedCache; /// The local cache is used by the worker thread to cache file system queries /// locally instead of querying the global cache every time. Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -1910,7 +1910,8 @@ llvm::Function *InitFn) { // If we're not emitting codeview, use the mangled name. For Itanium, this is // arbitrary. - if (!CGM.getCodeGenOpts().EmitCodeView) + if (!CGM.getCodeGenOpts().EmitCodeView || + StubKind == DynamicInitKind::GlobalArrayDestructor) return InitFn->getName(); // Print the normal qualified name for the variable, then break off the last @@ -1935,6 +1936,7 @@ switch (StubKind) { case DynamicInitKind::NoStub: + case DynamicInitKind::GlobalArrayDestructor: llvm_unreachable("not an initializer"); case DynamicInitKind::Initializer: OS << "`dynamic initializer for '"; @@ -3569,7 +3571,8 @@ if (Name.startswith("\01")) Name = Name.substr(1); - if (!HasDecl || D->isImplicit() || D->hasAttr()) { + if (!HasDecl || D->isImplicit() || D->hasAttr() || + (isa(D) && GD.getDynamicInitKind() != DynamicInitKind::NoStub)) { Flags |= llvm::DINode::FlagArtificial; // Artificial functions should not silently reuse CurLoc. CurLoc = SourceLocation(); Index: lib/CodeGen/CGDeclCXX.cpp =================================================================== --- lib/CodeGen/CGDeclCXX.cpp +++ lib/CodeGen/CGDeclCXX.cpp @@ -247,6 +247,8 @@ CGF.StartFunction(GlobalDecl(&VD, DynamicInitKind::AtExit), CGM.getContext().VoidTy, fn, FI, FunctionArgList()); + // Emit an artificial location for this function. + auto AL = ApplyDebugLocation::CreateArtificial(CGF); llvm::CallInst *call = CGF.Builder.CreateCall(dtor, addr); @@ -642,8 +644,9 @@ StartFunction(GlobalDecl(D, DynamicInitKind::Initializer), getContext().VoidTy, Fn, getTypes().arrangeNullaryFunction(), - FunctionArgList(), D->getLocation(), - D->getInit()->getExprLoc()); + FunctionArgList()); + // Emit an artificial location for this function. + auto AL = ApplyDebugLocation::CreateArtificial(*this); // Use guarded initialization if the global variable is weak. This // occurs for, e.g., instantiated static data members and @@ -768,7 +771,10 @@ CurEHLocation = VD->getBeginLoc(); - StartFunction(VD, getContext().VoidTy, fn, FI, args); + StartFunction(GlobalDecl(VD, DynamicInitKind::GlobalArrayDestructor), + getContext().VoidTy, fn, FI, args); + // Emit an artificial location for this function. + auto AL = ApplyDebugLocation::CreateArtificial(*this); emitDestroy(addr, type, destroyer, useEHCleanupForArray); Index: lib/Driver/Distro.cpp =================================================================== --- lib/Driver/Distro.cpp +++ lib/Driver/Distro.cpp @@ -18,6 +18,9 @@ using namespace clang; static Distro::DistroType DetectDistro(llvm::vfs::FileSystem &VFS) { +#ifdef _WIN32 + return Distro::UnknownDistro; +#endif llvm::ErrorOr> File = VFS.getBufferForFile("/etc/lsb-release"); if (File) { Index: lib/Driver/Driver.cpp =================================================================== --- lib/Driver/Driver.cpp +++ lib/Driver/Driver.cpp @@ -271,7 +271,8 @@ if (CCCIsCPP() || (PhaseArg = DAL.getLastArg(options::OPT_E)) || (PhaseArg = DAL.getLastArg(options::OPT__SLASH_EP)) || (PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM)) || - (PhaseArg = DAL.getLastArg(options::OPT__SLASH_P))) { + (PhaseArg = DAL.getLastArg(options::OPT__SLASH_P)) || + (PhaseArg = DAL.getLastArg(options::OPT_Eonly))) { FinalPhase = phases::Preprocess; // --precompile only runs up to precompilation. @@ -1324,6 +1325,10 @@ BuildJobs(C); + // Call a new clang.exe for rendering the preprocessed output, to minimize the + // chances of a crash (in case this function was called due to an exception) + Command::ReenterTool = false; + // If there were errors building the compilation, quit now. if (Trap.hasErrorOccurred()) { Diag(clang::diag::note_drv_command_failed_diag_msg) Index: lib/Driver/Job.cpp =================================================================== --- lib/Driver/Job.cpp +++ lib/Driver/Job.cpp @@ -19,8 +19,11 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/CrashRecoveryContext.h" +#include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" +#include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Program.h" #include "llvm/Support/raw_ostream.h" #include @@ -313,6 +316,8 @@ Environment.push_back(nullptr); } +LLVM_THREAD_LOCAL bool Command::ReenterTool = true; + int Command::Execute(ArrayRef> Redirects, std::string *ErrMsg, bool *ExecutionFailed) const { if (PrintInputFilenames) { @@ -321,7 +326,7 @@ llvm::outs().flush(); } - SmallVector Argv; + SmallVector Argv; Optional> Env; std::vector ArgvVectorStorage; @@ -332,42 +337,81 @@ Env = makeArrayRef(ArgvVectorStorage); } + typedef int (*ClangDriverMainFunc)(SmallVectorImpl &); + ClangDriverMainFunc ClangDriverMain = nullptr; + + if (ReenterTool) { + StringRef F = llvm::sys::path::filename(Executable); + if (F.endswith_lower(".exe")) + F = F.drop_back(4); + for (auto &A : {"clang", "clang++", "clang-cl", "clang-cpp"}) { + if (F.equals_lower(A)) { + ClangDriverMain = (ClangDriverMainFunc)(intptr_t) + llvm::sys::DynamicLibrary::SearchForAddressOfSymbol( + "ClangDriverMain"); + break; + } + } + } + if (ResponseFile == nullptr) { Argv.push_back(Executable); Argv.append(Arguments.begin(), Arguments.end()); - Argv.push_back(nullptr); + if (!ClangDriverMain) + Argv.push_back(nullptr); + } else { + // If the command is too large, we need to put arguments in a response file. + std::string RespContents; + llvm::raw_string_ostream SS(RespContents); - auto Args = llvm::toStringRefArray(Argv.data()); - return llvm::sys::ExecuteAndWait( - Executable, Args, Env, Redirects, /*secondsToWait*/ 0, - /*memoryLimit*/ 0, ErrMsg, ExecutionFailed); + // Write file contents and build the Argv vector + writeResponseFile(SS); + buildArgvForResponseFile(Argv); + if (!ClangDriverMain) + Argv.push_back(nullptr); + SS.flush(); + + // Save the response file in the appropriate encoding + if (std::error_code EC = writeFileWithEncoding( + ResponseFile, RespContents, Creator.getResponseFileEncoding())) { + if (ErrMsg) + *ErrMsg = EC.message(); + if (ExecutionFailed) + *ExecutionFailed = true; + return -1; + } } - // We need to put arguments in a response file (command is too large) - // Open stream to store the response file contents - std::string RespContents; - llvm::raw_string_ostream SS(RespContents); + if (ClangDriverMain) { + if (ExecutionFailed) + *ExecutionFailed = false; - // Write file contents and build the Argv vector - writeResponseFile(SS); - buildArgvForResponseFile(Argv); - Argv.push_back(nullptr); - SS.flush(); + static bool CRCEnabled{}; + if (!CRCEnabled) { + llvm::CrashRecoveryContext::Enable(); + CRCEnabled = true; + } - // Save the response file in the appropriate encoding - if (std::error_code EC = writeFileWithEncoding( - ResponseFile, RespContents, Creator.getResponseFileEncoding())) { - if (ErrMsg) - *ErrMsg = EC.message(); - if (ExecutionFailed) - *ExecutionFailed = true; - return -1; + llvm::CrashRecoveryContext CRC; + CRC.EnableExceptionHandler = true; + + const void *PrettyState = llvm::SavePrettyStackState(); + + int Ret = 0; + auto ExecuteClangMain = [&]() { Ret = ClangDriverMain(Argv); }; + + if (!CRC.RunSafely(ExecuteClangMain)) { + llvm::RestorePrettyStackState(PrettyState); + return CRC.RetCode; + } + return Ret; + } else { + auto Args = llvm::toStringRefArray(Argv.data()); + return llvm::sys::ExecuteAndWait(Executable, Args, Env, Redirects, + /*secondsToWait*/ 0, + /*memoryLimit*/ 0, ErrMsg, + ExecutionFailed); } - - auto Args = llvm::toStringRefArray(Argv.data()); - return llvm::sys::ExecuteAndWait(Executable, Args, Env, Redirects, - /*secondsToWait*/ 0, - /*memoryLimit*/ 0, ErrMsg, ExecutionFailed); } FallbackCommand::FallbackCommand(const Action &Source_, const Tool &Creator_, Index: lib/Driver/ToolChains/Clang.cpp =================================================================== --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -41,6 +41,7 @@ #include "llvm/Support/Process.h" #include "llvm/Support/TargetParser.h" #include "llvm/Support/YAMLParser.h" +#include "llvm/Support/InitLLVM.h" #ifdef LLVM_ON_UNIX #include // For getuid(). @@ -3869,7 +3870,7 @@ // We normally speed up the clang process a bit by skipping destructors at // exit, but when we're generating diagnostics we can rely on some of the // cleanup. - if (!C.isForDiagnostics()) + if (!C.isForDiagnostics() && !llvm::InitLLVM::RunningInBuildozer()) CmdArgs.push_back("-disable-free"); #ifdef NDEBUG Index: lib/Frontend/CompilerInstance.cpp =================================================================== --- lib/Frontend/CompilerInstance.cpp +++ lib/Frontend/CompilerInstance.cpp @@ -645,6 +645,9 @@ llvm::sys::fs::remove(OF.TempFilename); } + // Don't leak file added by RemoveFileOnSignal() in + // CompilerInstance::createOutputFile() + llvm::sys::DontRemoveFileOnSignal(OF.TempFilename); } } else if (!OF.Filename.empty() && EraseFiles) llvm::sys::fs::remove(OF.Filename); Index: lib/Tooling/CommonOptionsParser.cpp =================================================================== --- lib/Tooling/CommonOptionsParser.cpp +++ lib/Tooling/CommonOptionsParser.cpp @@ -86,21 +86,21 @@ static cl::opt BuildPath("p", cl::desc("Build path"), cl::Optional, cl::cat(Category), - cl::sub(*cl::AllSubCommands)); + cl::allSub()); static cl::list SourcePaths( cl::Positional, cl::desc(" [... ]"), OccurrencesFlag, - cl::cat(Category), cl::sub(*cl::AllSubCommands)); + cl::cat(Category), cl::allSub()); static cl::list ArgsAfter( "extra-arg", cl::desc("Additional argument to append to the compiler command line"), - cl::cat(Category), cl::sub(*cl::AllSubCommands)); + cl::cat(Category), cl::allSub()); static cl::list ArgsBefore( "extra-arg-before", cl::desc("Additional argument to prepend to the compiler command line"), - cl::cat(Category), cl::sub(*cl::AllSubCommands)); + cl::cat(Category), cl::allSub()); cl::ResetAllOptionOccurrences(); Index: lib/Tooling/DependencyScanning/CMakeLists.txt =================================================================== --- lib/Tooling/DependencyScanning/CMakeLists.txt +++ lib/Tooling/DependencyScanning/CMakeLists.txt @@ -1,4 +1,5 @@ set(LLVM_LINK_COMPONENTS + BinaryFormat Core Support ) Index: lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp =================================================================== --- lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp +++ lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp @@ -8,6 +8,7 @@ #include "clang/Tooling/DependencyScanning/DependencyScanningFilesystem.h" #include "clang/Lex/DependencyDirectivesSourceMinimizer.h" +#include "llvm/BinaryFormat/Magic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Threading.h" @@ -31,13 +32,16 @@ F.getBuffer(Stat->getName()); if (!MaybeBuffer) return MaybeBuffer.getError(); + const auto &Buffer = *MaybeBuffer; + llvm::file_magic M = llvm::identify_magic(Buffer->getBuffer()); + llvm::SmallString<1024> MinimizedFileContents; // Minimize the file down to directives that might affect the dependencies. - const auto &Buffer = *MaybeBuffer; SmallVector Tokens; - if (!Minimize || minimizeSourceToDependencyDirectives( - Buffer->getBuffer(), MinimizedFileContents, Tokens)) { + if (!Minimize || M == llvm::file_magic::clang_pch || + minimizeSourceToDependencyDirectives(Buffer->getBuffer(), + MinimizedFileContents, Tokens)) { // Use the original file unless requested otherwise, or // if the minimization failed. // FIXME: Propage the diagnostic if desired by the client. @@ -103,15 +107,13 @@ return It.first->getValue(); } -llvm::ErrorOr -DependencyScanningWorkerFilesystem::status(const Twine &Path) { - SmallString<256> OwnedFilename; - StringRef Filename = Path.toStringRef(OwnedFilename); +llvm::ErrorOr +DependencyScanningWorkerFilesystem::getOrCreateFileSystemEntry( + const StringRef Filename) { + if (const CachedFileSystemEntry *Entry = getCachedEntry(Filename)) { + return Entry; + } - // Check the local cache first. - if (const CachedFileSystemEntry *Entry = getCachedEntry(Filename)) - return Entry->getStatus(); - // FIXME: Handle PCM/PCH files. // FIXME: Handle module map files. @@ -141,9 +143,22 @@ // Store the result in the local cache. setCachedEntry(Filename, Result); - return Result->getStatus(); + return Result; } +llvm::ErrorOr +DependencyScanningWorkerFilesystem::status(const Twine &Path) { + SmallString<256> OwnedFilename; + StringRef Filename = Path.toStringRef(OwnedFilename); + const llvm::ErrorOr Result = + getOrCreateFileSystemEntry(Filename); + if (!Result) + return Result.getError(); + if (!(*Result)->isValid()) + return (*Result)->getErrorCode(); + return (*Result)->getStatus(); +} + namespace { /// The VFS that is used by clang consumes the \c CachedFileSystemEntry using @@ -173,13 +188,18 @@ llvm::ErrorOr> createFile(const CachedFileSystemEntry *Entry) { - llvm::ErrorOr Contents = Entry->getContents(); - if (!Contents) - return Contents.getError(); - return std::make_unique( - llvm::MemoryBuffer::getMemBuffer(*Contents, Entry->getName(), - /*RequiresNullTerminator=*/false), - *Entry->getStatus()); + if (!Entry->isValid()) + return Entry->getErrorCode(); + std::unique_ptr Buf; + if (!Entry->getStatus()->isDirectory()) { + llvm::ErrorOr Contents = Entry->getContents(); + if (!Contents) + return Contents.getError(); + Buf = llvm::MemoryBuffer::getMemBuffer(*Contents, Entry->getName(), + /*RequiresNullTerminator=*/false); + } + return std::make_unique(std::move(Buf), + *Entry->getStatus()); } } // end anonymous namespace @@ -189,30 +209,9 @@ SmallString<256> OwnedFilename; StringRef Filename = Path.toStringRef(OwnedFilename); - // Check the local cache first. - if (const CachedFileSystemEntry *Entry = getCachedEntry(Filename)) - return createFile(Entry); - - // FIXME: Handle PCM/PCH files. - // FIXME: Handle module map files. - - bool KeepOriginalSource = IgnoredFiles.count(Filename); - DependencyScanningFilesystemSharedCache::SharedFileSystemEntry - &SharedCacheEntry = SharedCache.get(Filename); - const CachedFileSystemEntry *Result; - { - std::unique_lock LockGuard(SharedCacheEntry.ValueLock); - CachedFileSystemEntry &CacheEntry = SharedCacheEntry.Value; - - if (!CacheEntry.isValid()) { - CacheEntry = CachedFileSystemEntry::createFileEntry( - Filename, getUnderlyingFS(), !KeepOriginalSource); - } - - Result = &CacheEntry; - } - - // Store the result in the local cache. - setCachedEntry(Filename, Result); - return createFile(Result); + const llvm::ErrorOr Result = + getOrCreateFileSystemEntry(Filename); + if (!Result) + return Result.getError(); + return createFile(Result.get()/*, PPSkipMappings*/); } Index: test/CodeGenCXX/debug-info-atexit-stub.cpp =================================================================== --- test/CodeGenCXX/debug-info-atexit-stub.cpp +++ test/CodeGenCXX/debug-info-atexit-stub.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -emit-llvm %s -triple x86_64-windows-msvc -gcodeview -debug-info-kind=limited -o - | FileCheck %s + +struct a { + ~a(); +}; +template struct c : a { + c(void (b::*)()); +}; +struct B { + virtual void e(); +}; +c *d() { static c f(&B::e); return &f; } + +// CHECK: define internal void @"??__Ff@?1??d@@YAPEAU?$c@UB@@@@XZ@YAXXZ"() +// CHECK-SAME: !dbg ![[SUBPROGRAM:[0-9]+]] { +// CHECK: call void @"??1?$c@UB@@@@QEAA@XZ"(%struct.c* @"?f@?1??d@@YAPEAU?$c@UB@@@@XZ@4U2@A"), !dbg ![[LOCATION:[0-9]+]] +// CHECK-NEXT: ret void, !dbg ![[LOCATION]] +// CHECK: ![[SUBPROGRAM]] = distinct !DISubprogram(name: "`dynamic atexit destructor for 'f'" +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: ![[LOCATION]] = !DILocation(line: 0, scope: ![[SUBPROGRAM]]) \ No newline at end of file Index: test/CodeGenCXX/debug-info-destroy-helper.cpp =================================================================== --- test/CodeGenCXX/debug-info-destroy-helper.cpp +++ test/CodeGenCXX/debug-info-destroy-helper.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -emit-llvm %s -triple x86_64-windows-msvc -gcodeview -debug-info-kind=limited -o - | FileCheck %s + +struct b { + b(char *); + ~b(); +}; +struct a { + ~a(); +}; +struct { + b c; + const a &d; +} e[]{nullptr, {}}; + +// CHECK: define internal void @__cxx_global_array_dtor(i8* %0) +// CHECK-SAME: !dbg ![[SUBPROGRAM:[0-9]+]] { +// CHECK: arraydestroy.body +// CHECK: %arraydestroy.elementPast = +// CHECK-SAME: !dbg ![[LOCATION:[0-9]+]] +// CHECK: call void @"??1@@QEAA@XZ"(%struct.anon* %arraydestroy.element) +// CHECK-SAME: !dbg ![[LOCATION]] +// CHECK: ![[SUBPROGRAM]] = distinct !DISubprogram(name: "__cxx_global_array_dtor" +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: ![[LOCATION]] = !DILocation(line: 0, Index: test/CodeGenCXX/debug-info-global-ctor-dtor.cpp =================================================================== --- test/CodeGenCXX/debug-info-global-ctor-dtor.cpp +++ test/CodeGenCXX/debug-info-global-ctor-dtor.cpp @@ -29,25 +29,26 @@ A FooTpl::sdm_tpl(sizeof(U) + sizeof(T)); template A FooTpl::sdm_tpl; -// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_var_init",{{.*}} line: 15,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-NOKEXT: !DISubprogram(name: "__dtor_glob",{{.*}} line: 15,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_var_init.1",{{.*}} line: 16,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_array_dtor",{{.*}} line: 16,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-NOKEXT: !DISubprogram(name: "__dtor_array",{{.*}} line: 16,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-NOKEXT: !DISubprogram(name: "__dtor__ZZ3foovE4stat",{{.*}} line: 19,{{.*}} DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_var_init",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-NOKEXT: !DISubprogram(name: "__dtor_glob",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_var_init.1",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-NOKEXT: !DISubprogram(name: "__cxx_global_array_dtor",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-NOKEXT: !DISubprogram(name: "__dtor_array",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-NOKEXT: !DISubprogram(name: "__dtor__ZZ3foovE4stat",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition // CHECK-NOKEXT: !DISubprogram({{.*}} DISPFlagLocalToUnit | DISPFlagDefinition // CHECK-KEXT: !DISubprogram({{.*}} DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-MSVC: !DISubprogram(name: "`dynamic initializer for 'glob'",{{.*}} line: 15,{{.*}}: DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-MSVC: !DISubprogram(name: "`dynamic atexit destructor for 'glob'",{{.*}} line: 15,{{.*}}: DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-MSVC: !DISubprogram(name: "`dynamic initializer for 'array'",{{.*}} line: 16,{{.*}}: DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-MSVC: !DISubprogram(name: "__cxx_global_array_dtor",{{.*}} line: 16,{{.*}}: DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-MSVC: !DISubprogram(name: "`dynamic atexit destructor for 'array'",{{.*}} line: 16,{{.*}}: DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-MSVC: !DISubprogram(name: "`dynamic atexit destructor for 'stat'",{{.*}} line: 19,{{.*}}: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-MSVC: !DISubprogram(name: "`dynamic initializer for 'glob'",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-MSVC: !DISubprogram(name: "`dynamic atexit destructor for 'glob'",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-MSVC: !DISubprogram(name: "`dynamic initializer for 'array'",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-MSVC: !DISubprogram(name: "__cxx_global_array_dtor",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-MSVC: !DISubprogram(name: "`dynamic atexit destructor for 'array'",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-MSVC: !DISubprogram(name: "`dynamic atexit destructor for 'stat'",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition // MSVC does weird stuff when templates are involved, so we don't match exactly, // but these names are reasonable. // FIXME: These should not be marked DISPFlagLocalToUnit. -// CHECK-MSVC: !DISubprogram(name: "FooTpl::`dynamic initializer for 'sdm_tpl'",{{.*}} line: 29,{{.*}}: DISPFlagLocalToUnit | DISPFlagDefinition -// CHECK-MSVC: !DISubprogram(name: "FooTpl::`dynamic atexit destructor for 'sdm_tpl'",{{.*}} line: 29,{{.*}}: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-MSVC: !DISubprogram(name: "FooTpl::`dynamic initializer for 'sdm_tpl'",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-MSVC: !DISubprogram(name: "FooTpl::`dynamic atexit destructor for 'sdm_tpl'",{{.*}} flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition +// CHECK-MSVC: !DISubprogram(linkageName: "_GLOBAL__sub_I_debug_info_global_ctor_dtor.cpp",{{.*}} flags: DIFlagArtificial \ No newline at end of file Index: test/CodeGenCXX/debug-info-line.cpp =================================================================== --- test/CodeGenCXX/debug-info-line.cpp +++ test/CodeGenCXX/debug-info-line.cpp @@ -314,7 +314,7 @@ // CHECK: [[DBG_F9]] = !DILocation(line: 1000, // CHECK: [[DBG_F10_STORE]] = !DILocation(line: 1100, // CHECK: [[DBG_GLBL_CTOR_B]] = !DILocation(line: 1200, -// CHECK: [[DBG_GLBL_DTOR_B]] = !DILocation(line: 1200, +// CHECK: [[DBG_GLBL_DTOR_B]] = !DILocation(line: 0, // CHECK: [[DBG_F11]] = !DILocation(line: 1300, // CHECK: [[DBG_F12]] = !DILocation(line: 1400, // CHECK: [[DBG_F13]] = !DILocation(line: 1500, Index: tools/clang-refactor/ClangRefactor.cpp =================================================================== --- tools/clang-refactor/ClangRefactor.cpp +++ tools/clang-refactor/ClangRefactor.cpp @@ -39,11 +39,11 @@ static cl::opt Verbose("v", cl::desc("Use verbose output"), cl::cat(cl::GeneralCategory), - cl::sub(*cl::AllSubCommands)); + cl::allSub()); static cl::opt Inplace("i", cl::desc("Inplace edit s"), cl::cat(cl::GeneralCategory), - cl::sub(*cl::AllSubCommands)); + cl::allSub()); } // end namespace opts Index: tools/clang-scan-deps/CMakeLists.txt =================================================================== --- tools/clang-scan-deps/CMakeLists.txt +++ tools/clang-scan-deps/CMakeLists.txt @@ -4,6 +4,7 @@ ) add_clang_tool(clang-scan-deps +#add_clang_library(clang-scan-deps SHARED ClangScanDeps.cpp ) Index: tools/clang-scan-deps/ClangScanDeps.cpp =================================================================== --- tools/clang-scan-deps/ClangScanDeps.cpp +++ tools/clang-scan-deps/ClangScanDeps.cpp @@ -214,7 +214,8 @@ // Print out the dependency results to STDOUT by default. SharedStream DependencyOS(llvm::outs()); - DependencyScanningService Service(ScanMode, ReuseFileManager); + static DependencyScanningService Service(ScanMode, ReuseFileManager); + #if LLVM_ENABLE_THREADS unsigned NumWorkers = NumThreads == 0 ? llvm::hardware_concurrency() : NumThreads; @@ -264,3 +265,59 @@ return HadErrors; } + +__declspec(dllexport) +int scan(int argc, const char **argv, char * buffer) { + llvm::cl::ResetAllOptionOccurrences(); + llvm::cl::HideUnrelatedOptions(DependencyScannerCategory); + + std::string ErrorMessage; + std::unique_ptr Compilations = + tooling::JSONCompilationDatabase::loadFromBuffer( + argv[2], ErrorMessage, + tooling::JSONCommandLineSyntax::AutoDetect); + if (!Compilations) { + llvm::errs() << "error: " << ErrorMessage << "\n"; + return 1; + } + + llvm::cl::PrintOptionValues(); + + // By default the tool runs on all inputs in the CDB. + std::vector> Inputs; + for (const auto &Command : Compilations->getAllCompileCommands()) + Inputs.emplace_back(Command.Filename, Command.Directory); + + // The command options are rewritten to run Clang in preprocessor only mode. + auto AdjustingCompilations = + std::make_unique( + std::move(Compilations)); + AdjustingCompilations->appendArgumentsAdjuster( + [](const tooling::CommandLineArguments &Args, StringRef /*unused*/) { + tooling::CommandLineArguments AdjustedArgs = Args; + AdjustedArgs.push_back("-o"); + AdjustedArgs.push_back("/dev/null"); + AdjustedArgs.push_back("-Xclang"); + AdjustedArgs.push_back("-Eonly"); + AdjustedArgs.push_back("-Xclang"); + AdjustedArgs.push_back("-sys-header-deps"); + AdjustedArgs.push_back("-Wno-error"); + return AdjustedArgs; + }); + + SharedStream Errs(llvm::errs()); + std::string Output; + llvm::raw_string_ostream StrOut(Output); + SharedStream DependencyOS(StrOut); + + static DependencyScanningService Service(ScanMode, ReuseFileManager); + + std::unique_ptr WorkerTools; + WorkerTools = std::make_unique(Service, *AdjustingCompilations, DependencyOS, Errs); + + std::vector WorkerThreads; + + bool HadErrors = WorkerTools->runOnFile(Inputs[0].first, Inputs[0].second); + strcpy(buffer, Output.c_str()); + return HadErrors; +} Index: tools/driver/cc1_main.cpp =================================================================== --- tools/driver/cc1_main.cpp +++ tools/driver/cc1_main.cpp @@ -36,6 +36,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" @@ -69,7 +70,7 @@ // We cannot recover from llvm errors. When reporting a fatal error, exit // with status 70 to generate crash diagnostics. For BSD systems this is // defined as an internal software error. Otherwise, exit with status 1. - exit(GenCrashDiag ? 70 : 1); + llvm::sys::Process::ExitCurrentProcess(GenCrashDiag ? 70 : 1); } #ifdef LINK_POLLY_INTO_TOOLS Index: tools/driver/driver.cpp =================================================================== --- tools/driver/driver.cpp +++ tools/driver/driver.cpp @@ -30,6 +30,8 @@ #include "llvm/Option/OptTable.h" #include "llvm/Option/Option.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/CrashRecoveryContext.h" +#include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" @@ -46,6 +48,7 @@ #include #include #include +#include using namespace clang; using namespace clang::driver; using namespace llvm::opt; @@ -318,6 +321,8 @@ return 1; } +int ClangDriverMain(SmallVectorImpl& argv); + int main(int argc_, const char **argv_) { noteBottomOfStack(); llvm::InitLLVM X(argc_, argv_); @@ -327,6 +332,18 @@ return 1; llvm::InitializeAllTargets(); + return ClangDriverMain(argv); +} + +int ClangDriverMain(SmallVectorImpl& argv) { + static LLVM_THREAD_LOCAL bool EnterPE = true; + if (EnterPE) { + llvm::sys::DynamicLibrary::AddSymbol("ClangDriverMain", (void*)(intptr_t)&ClangDriverMain); + EnterPE = false; + } else { + llvm::cl::ResetAllOptionOccurrences(); + } + auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(argv[0]); llvm::BumpPtrAllocator A; @@ -502,7 +519,7 @@ #ifdef _WIN32 // Exit status should not be negative on Win32, unless abnormal termination. - // Once abnormal termiation was caught, negative status should not be + // Once abnormal termination was caught, negative status should not be // propagated. if (Res < 0) Res = 1;