diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:49 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:49 +0000 |
commit | 2298981669bf3bd63335a4be179bc0f96823a8f4 (patch) | |
tree | 1cbe2eb27f030d2d70b80ee5ca3c86bee7326a9f /lib/Frontend | |
parent | 9a83721404652cea39e9f02ae3e3b5c964602a5c (diff) | |
download | src-2298981669bf3bd63335a4be179bc0f96823a8f4.tar.gz src-2298981669bf3bd63335a4be179bc0f96823a8f4.zip |
Vendor import of stripped clang trunk r366426 (just before thevendor/clang/clang-trunk-r366426
release_90 branch point):
https://llvm.org/svn/llvm-project/cfe/trunk@366426
Notes
Notes:
svn path=/vendor/clang/dist/; revision=351280
svn path=/vendor/clang/clang-trunk-r366426/; revision=351281; tag=vendor/clang/clang-trunk-r366426
Diffstat (limited to 'lib/Frontend')
42 files changed, 1592 insertions, 982 deletions
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp index 28834a2de8a2..26154ee2e856 100644 --- a/lib/Frontend/ASTConsumers.cpp +++ b/lib/Frontend/ASTConsumers.cpp @@ -1,9 +1,8 @@ //===--- ASTConsumers.cpp - ASTConsumer implementations -------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -35,10 +34,12 @@ namespace { public: enum Kind { DumpFull, Dump, Print, None }; - ASTPrinter(std::unique_ptr<raw_ostream> Out, Kind K, StringRef FilterString, + ASTPrinter(std::unique_ptr<raw_ostream> Out, Kind K, + ASTDumpOutputFormat Format, StringRef FilterString, bool DumpLookups = false) : Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)), - OutputKind(K), FilterString(FilterString), DumpLookups(DumpLookups) {} + OutputKind(K), OutputFormat(Format), FilterString(FilterString), + DumpLookups(DumpLookups) {} void HandleTranslationUnit(ASTContext &Context) override { TranslationUnitDecl *D = Context.getTranslationUnitDecl(); @@ -91,7 +92,7 @@ namespace { PrintingPolicy Policy(D->getASTContext().getLangOpts()); D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true); } else if (OutputKind != None) - D->dump(Out, OutputKind == DumpFull); + D->dump(Out, OutputKind == DumpFull, OutputFormat); } raw_ostream &Out; @@ -100,6 +101,9 @@ namespace { /// How to output individual declarations. Kind OutputKind; + /// What format should the output take? + ASTDumpOutputFormat OutputFormat; + /// Which declarations or DeclContexts to display. std::string FilterString; @@ -136,20 +140,18 @@ std::unique_ptr<ASTConsumer> clang::CreateASTPrinter(std::unique_ptr<raw_ostream> Out, StringRef FilterString) { return llvm::make_unique<ASTPrinter>(std::move(Out), ASTPrinter::Print, - FilterString); + ADOF_Default, FilterString); } std::unique_ptr<ASTConsumer> -clang::CreateASTDumper(std::unique_ptr<raw_ostream> Out, - StringRef FilterString, - bool DumpDecls, - bool Deserialize, - bool DumpLookups) { +clang::CreateASTDumper(std::unique_ptr<raw_ostream> Out, StringRef FilterString, + bool DumpDecls, bool Deserialize, bool DumpLookups, + ASTDumpOutputFormat Format) { assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump"); return llvm::make_unique<ASTPrinter>(std::move(Out), Deserialize ? ASTPrinter::DumpFull : DumpDecls ? ASTPrinter::Dump : - ASTPrinter::None, + ASTPrinter::None, Format, FilterString, DumpLookups); } diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp index 4f622da118c5..14d781ccdf93 100644 --- a/lib/Frontend/ASTMerge.cpp +++ b/lib/Frontend/ASTMerge.cpp @@ -1,16 +1,15 @@ //===-- ASTMerge.cpp - AST Merging Frontend Action --------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "clang/Frontend/ASTUnit.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ASTImporter.h" -#include "clang/AST/ASTImporterLookupTable.h" +#include "clang/AST/ASTImporterSharedState.h" #include "clang/Basic/Diagnostic.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendActions.h" @@ -39,7 +38,7 @@ void ASTMergeAction::ExecuteAction() { &CI.getASTContext()); IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(CI.getDiagnostics().getDiagnosticIDs()); - ASTImporterLookupTable LookupTable( + auto SharedState = std::make_shared<ASTImporterSharedState>( *CI.getASTContext().getTranslationUnitDecl()); for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) { IntrusiveRefCntPtr<DiagnosticsEngine> @@ -56,7 +55,7 @@ void ASTMergeAction::ExecuteAction() { ASTImporter Importer(CI.getASTContext(), CI.getFileManager(), Unit->getASTContext(), Unit->getFileManager(), - /*MinimalImport=*/false, &LookupTable); + /*MinimalImport=*/false, SharedState); TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl(); for (auto *D : TU->decls()) { @@ -66,11 +65,13 @@ void ASTMergeAction::ExecuteAction() { if (II->isStr("__va_list_tag") || II->isStr("__builtin_va_list")) continue; - Decl *ToD = Importer.Import(D); + llvm::Expected<Decl *> ToDOrError = Importer.Import(D); - if (ToD) { - DeclGroupRef DGR(ToD); + if (ToDOrError) { + DeclGroupRef DGR(*ToDOrError); CI.getASTConsumer().HandleTopLevelDecl(DGR); + } else { + llvm::consumeError(ToDOrError.takeError()); } } } diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index c7b2551cb8d7..7445a94cfe59 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -1,9 +1,8 @@ //===- ASTUnit.cpp - ASTUnit utility --------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -31,7 +30,6 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" -#include "clang/Basic/MemoryBufferCache.h" #include "clang/Basic/Module.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" @@ -61,6 +59,7 @@ #include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ASTWriter.h" #include "clang/Serialization/ContinuousRangeMap.h" +#include "clang/Serialization/InMemoryModuleCache.h" #include "clang/Serialization/Module.h" #include "clang/Serialization/PCHContainerOperations.h" #include "llvm/ADT/ArrayRef.h" @@ -76,7 +75,7 @@ #include "llvm/ADT/StringSet.h" #include "llvm/ADT/Twine.h" #include "llvm/ADT/iterator_range.h" -#include "llvm/Bitcode/BitstreamWriter.h" +#include "llvm/Bitstream/BitstreamWriter.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CrashRecoveryContext.h" @@ -218,8 +217,8 @@ struct ASTUnit::ASTWriterData { llvm::BitstreamWriter Stream; ASTWriter Writer; - ASTWriterData(MemoryBufferCache &PCMCache) - : Stream(Buffer), Writer(Stream, Buffer, PCMCache, {}) {} + ASTWriterData(InMemoryModuleCache &ModuleCache) + : Stream(Buffer), Writer(Stream, Buffer, ModuleCache, {}) {} }; void ASTUnit::clearFileLevelDecls() { @@ -609,17 +608,20 @@ private: }; /// Diagnostic consumer that saves each diagnostic it is given. -class StoredDiagnosticConsumer : public DiagnosticConsumer { +class FilterAndStoreDiagnosticConsumer : public DiagnosticConsumer { SmallVectorImpl<StoredDiagnostic> *StoredDiags; SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags; + bool CaptureNonErrorsFromIncludes = true; const LangOptions *LangOpts = nullptr; SourceManager *SourceMgr = nullptr; public: - StoredDiagnosticConsumer( + FilterAndStoreDiagnosticConsumer( SmallVectorImpl<StoredDiagnostic> *StoredDiags, - SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags) - : StoredDiags(StoredDiags), StandaloneDiags(StandaloneDiags) { + SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags, + bool CaptureNonErrorsFromIncludes) + : StoredDiags(StoredDiags), StandaloneDiags(StandaloneDiags), + CaptureNonErrorsFromIncludes(CaptureNonErrorsFromIncludes) { assert((StoredDiags || StandaloneDiags) && "No output collections were passed to StoredDiagnosticConsumer."); } @@ -635,21 +637,25 @@ public: const Diagnostic &Info) override; }; -/// RAII object that optionally captures diagnostics, if +/// RAII object that optionally captures and filters diagnostics, if /// there is no diagnostic client to capture them already. class CaptureDroppedDiagnostics { DiagnosticsEngine &Diags; - StoredDiagnosticConsumer Client; + FilterAndStoreDiagnosticConsumer Client; DiagnosticConsumer *PreviousClient = nullptr; std::unique_ptr<DiagnosticConsumer> OwningPreviousClient; public: CaptureDroppedDiagnostics( - bool RequestCapture, DiagnosticsEngine &Diags, + CaptureDiagsKind CaptureDiagnostics, DiagnosticsEngine &Diags, SmallVectorImpl<StoredDiagnostic> *StoredDiags, SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags) - : Diags(Diags), Client(StoredDiags, StandaloneDiags) { - if (RequestCapture || Diags.getClient() == nullptr) { + : Diags(Diags), + Client(StoredDiags, StandaloneDiags, + CaptureDiagnostics != + CaptureDiagsKind::AllWithoutNonErrorsFromIncludes) { + if (CaptureDiagnostics != CaptureDiagsKind::None || + Diags.getClient() == nullptr) { OwningPreviousClient = Diags.takeClient(); PreviousClient = Diags.getClient(); Diags.setClient(&Client, false); @@ -668,8 +674,16 @@ static ASTUnit::StandaloneDiagnostic makeStandaloneDiagnostic(const LangOptions &LangOpts, const StoredDiagnostic &InDiag); -void StoredDiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level Level, - const Diagnostic &Info) { +static bool isInMainFile(const clang::Diagnostic &D) { + if (!D.hasSourceManager() || !D.getLocation().isValid()) + return false; + + auto &M = D.getSourceManager(); + return M.isWrittenInMainFile(M.getExpansionLoc(D.getLocation())); +} + +void FilterAndStoreDiagnosticConsumer::HandleDiagnostic( + DiagnosticsEngine::Level Level, const Diagnostic &Info) { // Default implementation (Warnings/errors count). DiagnosticConsumer::HandleDiagnostic(Level, Info); @@ -677,6 +691,11 @@ void StoredDiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level Level, // about. This effectively drops diagnostics from modules we're building. // FIXME: In the long run, ee don't want to drop source managers from modules. if (!Info.hasSourceManager() || &Info.getSourceManager() == SourceMgr) { + if (!CaptureNonErrorsFromIncludes && Level <= DiagnosticsEngine::Warning && + !isInMainFile(Info)) { + return; + } + StoredDiagnostic *ResultDiag = nullptr; if (StoredDiags) { StoredDiags->emplace_back(Level, Info); @@ -724,10 +743,13 @@ ASTUnit::getBufferForFile(StringRef Filename, std::string *ErrorStr) { /// Configure the diagnostics object for use with ASTUnit. void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags, - ASTUnit &AST, bool CaptureDiagnostics) { + ASTUnit &AST, + CaptureDiagsKind CaptureDiagnostics) { assert(Diags.get() && "no DiagnosticsEngine was provided"); - if (CaptureDiagnostics) - Diags->setClient(new StoredDiagnosticConsumer(&AST.StoredDiagnostics, nullptr)); + if (CaptureDiagnostics != CaptureDiagsKind::None) + Diags->setClient(new FilterAndStoreDiagnosticConsumer( + &AST.StoredDiagnostics, nullptr, + CaptureDiagnostics != CaptureDiagsKind::AllWithoutNonErrorsFromIncludes)); } std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( @@ -735,7 +757,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( WhatToLoad ToLoad, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, const FileSystemOptions &FileSystemOpts, bool UseDebugInfo, bool OnlyLocalDecls, ArrayRef<RemappedFile> RemappedFiles, - bool CaptureDiagnostics, bool AllowPCHWithCompilerErrors, + CaptureDiagsKind CaptureDiagnostics, bool AllowPCHWithCompilerErrors, bool UserFilesAreVolatile) { std::unique_ptr<ASTUnit> AST(new ASTUnit(true)); @@ -759,7 +781,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( AST->SourceMgr = new SourceManager(AST->getDiagnostics(), AST->getFileManager(), UserFilesAreVolatile); - AST->PCMCache = new MemoryBufferCache; + AST->ModuleCache = new InMemoryModuleCache; AST->HSOpts = std::make_shared<HeaderSearchOptions>(); AST->HSOpts->ModuleFormat = PCHContainerRdr.getFormat(); AST->HeaderInfo.reset(new HeaderSearch(AST->HSOpts, @@ -779,7 +801,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( AST->PP = std::make_shared<Preprocessor>( AST->PPOpts, AST->getDiagnostics(), *AST->LangOpts, - AST->getSourceManager(), *AST->PCMCache, HeaderInfo, AST->ModuleLoader, + AST->getSourceManager(), HeaderInfo, AST->ModuleLoader, /*IILookup=*/nullptr, /*OwnsHeaderSearch=*/false); Preprocessor &PP = *AST->PP; @@ -792,10 +814,10 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( bool disableValid = false; if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION")) disableValid = true; - AST->Reader = new ASTReader(PP, AST->Ctx.get(), PCHContainerRdr, {}, - /*isysroot=*/"", - /*DisableValidation=*/disableValid, - AllowPCHWithCompilerErrors); + AST->Reader = new ASTReader( + PP, *AST->ModuleCache, AST->Ctx.get(), PCHContainerRdr, {}, + /*isysroot=*/"", + /*DisableValidation=*/disableValid, AllowPCHWithCompilerErrors); AST->Reader->setListener(llvm::make_unique<ASTInfoCollector>( *AST->PP, AST->Ctx.get(), *AST->HSOpts, *AST->PPOpts, *AST->LangOpts, @@ -1079,28 +1101,29 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, if (!Invocation) return true; + if (VFS && FileMgr) + assert(VFS == &FileMgr->getVirtualFileSystem() && + "VFS passed to Parse and VFS in FileMgr are different"); + auto CCInvocation = std::make_shared<CompilerInvocation>(*Invocation); if (OverrideMainBuffer) { assert(Preamble && "No preamble was built, but OverrideMainBuffer is not null"); - IntrusiveRefCntPtr<llvm::vfs::FileSystem> OldVFS = VFS; Preamble->AddImplicitPreamble(*CCInvocation, VFS, OverrideMainBuffer.get()); - if (OldVFS != VFS && FileMgr) { - assert(OldVFS == FileMgr->getVirtualFileSystem() && - "VFS passed to Parse and VFS in FileMgr are different"); - FileMgr = new FileManager(FileMgr->getFileSystemOpts(), VFS); - } + // VFS may have changed... } // Create the compiler instance to use for building the AST. std::unique_ptr<CompilerInstance> Clang( new CompilerInstance(std::move(PCHContainerOps))); - if (FileMgr && VFS) { - assert(VFS == FileMgr->getVirtualFileSystem() && - "VFS passed to Parse and VFS in FileMgr are different"); - } else if (VFS) { - Clang->setVirtualFileSystem(VFS); - } + + // Ensure that Clang has a FileManager with the right VFS, which may have + // changed above in AddImplicitPreamble. If VFS is nullptr, rely on + // createFileManager to create one. + if (VFS && FileMgr && &FileMgr->getVirtualFileSystem() == VFS) + Clang->setFileManager(&*FileMgr); + else + FileMgr = Clang->createFileManager(std::move(VFS)); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance> @@ -1137,10 +1160,6 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, // Configure the various subsystems. LangOpts = Clang->getInvocation().LangOpts; FileSystemOpts = Clang->getFileSystemOpts(); - if (!FileMgr) { - Clang->createFileManager(); - FileMgr = &Clang->getFileManager(); - } ResetForParse(); @@ -1187,8 +1206,10 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, else PreambleSrcLocCache.clear(); - if (!Act->Execute()) + if (llvm::Error Err = Act->Execute()) { + consumeError(std::move(Err)); // FIXME this drops errors on the floor. goto error; + } transferASTDataFromCompilerInstance(*Clang); @@ -1308,22 +1329,22 @@ ASTUnit::getMainBufferWithPrecompiledPreamble( PreambleInvocationIn.getDiagnosticOpts()); getDiagnostics().setNumWarnings(NumWarningsInPreamble); - PreambleRebuildCounter = 1; + PreambleRebuildCountdown = 1; return MainFileBuffer; } else { Preamble.reset(); PreambleDiagnostics.clear(); TopLevelDeclsInPreamble.clear(); PreambleSrcLocCache.clear(); - PreambleRebuildCounter = 1; + PreambleRebuildCountdown = 1; } } // If the preamble rebuild counter > 1, it's because we previously // failed to build a preamble and we're not yet ready to try // again. Decrement the counter and return a failure. - if (PreambleRebuildCounter > 1) { - --PreambleRebuildCounter; + if (PreambleRebuildCountdown > 1) { + --PreambleRebuildCountdown; return nullptr; } @@ -1333,13 +1354,15 @@ ASTUnit::getMainBufferWithPrecompiledPreamble( if (!AllowRebuild) return nullptr; + ++PreambleCounter; + SmallVector<StandaloneDiagnostic, 4> NewPreambleDiagsStandalone; SmallVector<StoredDiagnostic, 4> NewPreambleDiags; ASTUnitPreambleCallbacks Callbacks; { llvm::Optional<CaptureDroppedDiagnostics> Capture; - if (CaptureDiagnostics) - Capture.emplace(/*RequestCapture=*/true, *Diagnostics, &NewPreambleDiags, + if (CaptureDiagnostics != CaptureDiagsKind::None) + Capture.emplace(CaptureDiagnostics, *Diagnostics, &NewPreambleDiags, &NewPreambleDiagsStandalone); // We did not previously compute a preamble, or it can't be reused anyway. @@ -1360,18 +1383,19 @@ ASTUnit::getMainBufferWithPrecompiledPreamble( if (NewPreamble) { Preamble = std::move(*NewPreamble); - PreambleRebuildCounter = 1; + PreambleRebuildCountdown = 1; } else { switch (static_cast<BuildPreambleError>(NewPreamble.getError().value())) { case BuildPreambleError::CouldntCreateTempFile: // Try again next time. - PreambleRebuildCounter = 1; + PreambleRebuildCountdown = 1; return nullptr; case BuildPreambleError::CouldntCreateTargetInfo: case BuildPreambleError::BeginSourceFileFailed: case BuildPreambleError::CouldntEmitPCH: + case BuildPreambleError::BadInputs: // These erros are more likely to repeat, retry after some period. - PreambleRebuildCounter = DefaultPreambleRebuildInterval; + PreambleRebuildCountdown = DefaultPreambleRebuildInterval; return nullptr; } llvm_unreachable("unexpected BuildPreambleError"); @@ -1466,7 +1490,8 @@ StringRef ASTUnit::getASTFileName() const { std::unique_ptr<ASTUnit> ASTUnit::create(std::shared_ptr<CompilerInvocation> CI, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, - bool CaptureDiagnostics, bool UserFilesAreVolatile) { + CaptureDiagsKind CaptureDiagnostics, + bool UserFilesAreVolatile) { std::unique_ptr<ASTUnit> AST(new ASTUnit(false)); ConfigureDiags(Diags, *AST, CaptureDiagnostics); IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = @@ -1478,7 +1503,7 @@ ASTUnit::create(std::shared_ptr<CompilerInvocation> CI, AST->UserFilesAreVolatile = UserFilesAreVolatile; AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr, UserFilesAreVolatile); - AST->PCMCache = new MemoryBufferCache; + AST->ModuleCache = new InMemoryModuleCache; return AST; } @@ -1488,7 +1513,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction( std::shared_ptr<PCHContainerOperations> PCHContainerOps, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FrontendAction *Action, ASTUnit *Unit, bool Persistent, StringRef ResourceFilesPath, - bool OnlyLocalDecls, bool CaptureDiagnostics, + bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics, unsigned PrecompilePreambleAfterNParses, bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion, bool UserFilesAreVolatile, std::unique_ptr<ASTUnit> *ErrAST) { @@ -1511,7 +1536,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction( AST->OnlyLocalDecls = OnlyLocalDecls; AST->CaptureDiagnostics = CaptureDiagnostics; if (PrecompilePreambleAfterNParses > 0) - AST->PreambleRebuildCounter = PrecompilePreambleAfterNParses; + AST->PreambleRebuildCountdown = PrecompilePreambleAfterNParses; AST->TUKind = Action ? Action->getTranslationUnitKind() : TU_Complete; AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults; AST->IncludeBriefCommentsInCodeCompletion @@ -1609,7 +1634,8 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction( Clang->setASTConsumer( llvm::make_unique<MultiplexConsumer>(std::move(Consumers))); } - if (!Act->Execute()) { + if (llvm::Error Err = Act->Execute()) { + consumeError(std::move(Err)); // FIXME this drops errors on the floor. AST->transferASTDataFromCompilerInstance(*Clang); if (OwnAST && ErrAST) ErrAST->swap(OwnAST); @@ -1645,7 +1671,7 @@ bool ASTUnit::LoadFromCompilerInvocation( std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer; if (PrecompilePreambleAfterNParses > 0) { - PreambleRebuildCounter = PrecompilePreambleAfterNParses; + PreambleRebuildCountdown = PrecompilePreambleAfterNParses; OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS); getDiagnostics().Reset(); @@ -1666,7 +1692,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation( std::shared_ptr<CompilerInvocation> CI, std::shared_ptr<PCHContainerOperations> PCHContainerOps, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FileManager *FileMgr, - bool OnlyLocalDecls, bool CaptureDiagnostics, + bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics, unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind, bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion, bool UserFilesAreVolatile) { @@ -1694,7 +1720,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation( if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps), PrecompilePreambleAfterNParses, - AST->FileMgr->getVirtualFileSystem())) + &AST->FileMgr->getVirtualFileSystem())) return nullptr; return AST; } @@ -1703,7 +1729,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine( const char **ArgBegin, const char **ArgEnd, std::shared_ptr<PCHContainerOperations> PCHContainerOps, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath, - bool OnlyLocalDecls, bool CaptureDiagnostics, + bool OnlyLocalDecls, CaptureDiagsKind CaptureDiagnostics, ArrayRef<RemappedFile> RemappedFiles, bool RemappedFilesKeepOriginalName, unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind, bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion, @@ -1758,7 +1784,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine( VFS = llvm::vfs::getRealFileSystem(); VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS); AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS); - AST->PCMCache = new MemoryBufferCache; + AST->ModuleCache = new InMemoryModuleCache; AST->OnlyLocalDecls = OnlyLocalDecls; AST->CaptureDiagnostics = CaptureDiagnostics; AST->TUKind = TUKind; @@ -1769,7 +1795,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine( AST->Invocation = CI; AST->SkipFunctionBodies = SkipFunctionBodies; if (ForSerialization) - AST->WriterData.reset(new ASTWriterData(*AST->PCMCache)); + AST->WriterData.reset(new ASTWriterData(*AST->ModuleCache)); // Zero out now to ease cleanup during crash recovery. CI = nullptr; Diags = nullptr; @@ -1801,7 +1827,7 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, if (!VFS) { assert(FileMgr && "FileMgr is null on Reparse call"); - VFS = FileMgr->getVirtualFileSystem(); + VFS = &FileMgr->getVirtualFileSystem(); } clearFileLevelDecls(); @@ -1823,7 +1849,7 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, // If we have a preamble file lying around, or if we might try to // build a precompiled preamble, do so now. std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer; - if (Preamble || PreambleRebuildCounter > 0) + if (Preamble || PreambleRebuildCountdown > 0) OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS); @@ -1881,8 +1907,7 @@ namespace { public: AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next, const CodeCompleteOptions &CodeCompleteOpts) - : CodeCompleteConsumer(CodeCompleteOpts, Next.isOutputBinary()), - AST(AST), Next(Next) { + : CodeCompleteConsumer(CodeCompleteOpts), AST(AST), Next(Next) { // Compute the set of contexts in which we will look when we don't have // any information about the specific context. NormalContexts @@ -2161,7 +2186,7 @@ void ASTUnit::CodeComplete( // Set up diagnostics, capturing any diagnostics produced. Clang->setDiagnostics(&Diag); - CaptureDroppedDiagnostics Capture(true, + CaptureDroppedDiagnostics Capture(CaptureDiagsKind::All, Clang->getDiagnostics(), &StoredDiagnostics, nullptr); ProcessWarningOptions(Diag, Inv.getDiagnosticOpts()); @@ -2215,18 +2240,18 @@ void ASTUnit::CodeComplete( if (Preamble) { std::string CompleteFilePath(File); - auto VFS = FileMgr.getVirtualFileSystem(); - auto CompleteFileStatus = VFS->status(CompleteFilePath); + auto &VFS = FileMgr.getVirtualFileSystem(); + auto CompleteFileStatus = VFS.status(CompleteFilePath); if (CompleteFileStatus) { llvm::sys::fs::UniqueID CompleteFileID = CompleteFileStatus->getUniqueID(); std::string MainPath(OriginalSourceFile); - auto MainStatus = VFS->status(MainPath); + auto MainStatus = VFS.status(MainPath); if (MainStatus) { llvm::sys::fs::UniqueID MainID = MainStatus->getUniqueID(); if (CompleteFileID == MainID && Line > 1) OverrideMainBuffer = getMainBufferWithPrecompiledPreamble( - PCHContainerOps, Inv, VFS, false, Line - 1); + PCHContainerOps, Inv, &VFS, false, Line - 1); } } } @@ -2237,7 +2262,8 @@ void ASTUnit::CodeComplete( assert(Preamble && "No preamble was built, but OverrideMainBuffer is not null"); - auto VFS = FileMgr.getVirtualFileSystem(); + IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = + &FileMgr.getVirtualFileSystem(); Preamble->AddImplicitPreamble(Clang->getInvocation(), VFS, OverrideMainBuffer.get()); // FIXME: there is no way to update VFS if it was changed by @@ -2257,7 +2283,9 @@ void ASTUnit::CodeComplete( std::unique_ptr<SyntaxOnlyAction> Act; Act.reset(new SyntaxOnlyAction); if (Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) { - Act->Execute(); + if (llvm::Error Err = Act->Execute()) { + consumeError(std::move(Err)); // FIXME this drops errors on the floor. + } Act->EndSourceFile(); } } @@ -2318,8 +2346,8 @@ bool ASTUnit::serialize(raw_ostream &OS) { SmallString<128> Buffer; llvm::BitstreamWriter Stream(Buffer); - MemoryBufferCache PCMCache; - ASTWriter Writer(Stream, Buffer, PCMCache, {}); + InMemoryModuleCache ModuleCache; + ASTWriter Writer(Stream, Buffer, ModuleCache, {}); return serializeUnit(Writer, Buffer, getSema(), hasErrors, OS); } @@ -2419,8 +2447,8 @@ void ASTUnit::addFileLevelDecl(Decl *D) { return; } - LocDeclsTy::iterator I = std::upper_bound(Decls->begin(), Decls->end(), - LocDecl, llvm::less_first()); + LocDeclsTy::iterator I = + llvm::upper_bound(*Decls, LocDecl, llvm::less_first()); Decls->insert(I, LocDecl); } @@ -2445,9 +2473,9 @@ void ASTUnit::findFileRegionDecls(FileID File, unsigned Offset, unsigned Length, return; LocDeclsTy::iterator BeginIt = - std::lower_bound(LocDecls.begin(), LocDecls.end(), - std::make_pair(Offset, (Decl *)nullptr), - llvm::less_first()); + llvm::partition_point(LocDecls, [=](std::pair<unsigned, Decl *> LD) { + return LD.first < Offset; + }); if (BeginIt != LocDecls.begin()) --BeginIt; @@ -2458,9 +2486,9 @@ void ASTUnit::findFileRegionDecls(FileID File, unsigned Offset, unsigned Length, BeginIt->second->isTopLevelDeclInObjCContainer()) --BeginIt; - LocDeclsTy::iterator EndIt = std::upper_bound( - LocDecls.begin(), LocDecls.end(), - std::make_pair(Offset + Length, (Decl *)nullptr), llvm::less_first()); + LocDeclsTy::iterator EndIt = llvm::upper_bound( + LocDecls, std::make_pair(Offset + Length, (Decl *)nullptr), + llvm::less_first()); if (EndIt != LocDecls.end()) ++EndIt; diff --git a/lib/Frontend/ChainedDiagnosticConsumer.cpp b/lib/Frontend/ChainedDiagnosticConsumer.cpp index d77fd180ea0d..793c5ff8a2b5 100644 --- a/lib/Frontend/ChainedDiagnosticConsumer.cpp +++ b/lib/Frontend/ChainedDiagnosticConsumer.cpp @@ -1,9 +1,8 @@ //===- ChainedDiagnosticConsumer.cpp - Chain Diagnostic Clients -----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Frontend/ChainedIncludesSource.cpp b/lib/Frontend/ChainedIncludesSource.cpp index 1bfc25c4c778..48154ecf4742 100644 --- a/lib/Frontend/ChainedIncludesSource.cpp +++ b/lib/Frontend/ChainedIncludesSource.cpp @@ -1,9 +1,8 @@ //===- ChainedIncludesSource.cpp - Chained PCHs in Memory -------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -83,9 +82,9 @@ createASTReader(CompilerInstance &CI, StringRef pchFile, ASTDeserializationListener *deserialListener = nullptr) { Preprocessor &PP = CI.getPreprocessor(); std::unique_ptr<ASTReader> Reader; - Reader.reset(new ASTReader(PP, &CI.getASTContext(), + Reader.reset(new ASTReader(PP, CI.getModuleCache(), &CI.getASTContext(), CI.getPCHContainerReader(), - /*Extensions=*/{ }, + /*Extensions=*/{}, /*isysroot=*/"", /*DisableValidation=*/true)); for (unsigned ti = 0; ti < bufNames.size(); ++ti) { StringRef sr(bufNames[ti]); @@ -160,8 +159,8 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource( auto Buffer = std::make_shared<PCHBuffer>(); ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions; auto consumer = llvm::make_unique<PCHGenerator>( - Clang->getPreprocessor(), "-", /*isysroot=*/"", Buffer, - Extensions, /*AllowASTWithErrors=*/true); + Clang->getPreprocessor(), Clang->getModuleCache(), "-", /*isysroot=*/"", + Buffer, Extensions, /*AllowASTWithErrors=*/true); Clang->getASTContext().setASTMutationListener( consumer->GetASTMutationListener()); Clang->setASTConsumer(std::move(consumer)); diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index f66674535423..cf0267549e75 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -1,9 +1,8 @@ //===--- CompilerInstance.cpp ---------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -14,7 +13,6 @@ #include "clang/Basic/CharInfo.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" -#include "clang/Basic/MemoryBufferCache.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/Stack.h" #include "clang/Basic/TargetInfo.h" @@ -36,6 +34,7 @@ #include "clang/Sema/Sema.h" #include "clang/Serialization/ASTReader.h" #include "clang/Serialization/GlobalModuleIndex.h" +#include "clang/Serialization/InMemoryModuleCache.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/BuryPointer.h" #include "llvm/Support/CrashRecoveryContext.h" @@ -47,6 +46,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/TimeProfiler.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" #include <sys/stat.h> @@ -58,15 +58,12 @@ using namespace clang; CompilerInstance::CompilerInstance( std::shared_ptr<PCHContainerOperations> PCHContainerOps, - MemoryBufferCache *SharedPCMCache) - : ModuleLoader(/* BuildingModule = */ SharedPCMCache), + InMemoryModuleCache *SharedModuleCache) + : ModuleLoader(/* BuildingModule = */ SharedModuleCache), Invocation(new CompilerInvocation()), - PCMCache(SharedPCMCache ? SharedPCMCache : new MemoryBufferCache), - ThePCHContainerOperations(std::move(PCHContainerOps)) { - // Don't allow this to invalidate buffers in use by others. - if (SharedPCMCache) - getPCMCache().finalizeCurrentBuffers(); -} + ModuleCache(SharedModuleCache ? SharedModuleCache + : new InMemoryModuleCache), + ThePCHContainerOperations(std::move(PCHContainerOps)) {} CompilerInstance::~CompilerInstance() { assert(OutputFiles.empty() && "Still output files in flight?"); @@ -93,10 +90,6 @@ void CompilerInstance::setAuxTarget(TargetInfo *Value) { AuxTarget = Value; } void CompilerInstance::setFileManager(FileManager *Value) { FileMgr = Value; - if (Value) - VirtualFileSystem = Value->getVirtualFileSystem(); - else - VirtualFileSystem.reset(); } void CompilerInstance::setSourceManager(SourceManager *Value) { @@ -137,7 +130,7 @@ IntrusiveRefCntPtr<ASTReader> CompilerInstance::getModuleManager() const { return ModuleManager; } void CompilerInstance::setModuleManager(IntrusiveRefCntPtr<ASTReader> Reader) { - assert(PCMCache.get() == &Reader->getModuleManager().getPCMCache() && + assert(ModuleCache.get() == &Reader->getModuleManager().getModuleCache() && "Expected ASTReader to use the same PCM cache"); ModuleManager = std::move(Reader); } @@ -177,7 +170,7 @@ static void collectIncludePCH(CompilerInstance &CI, std::error_code EC; SmallString<128> DirNative; llvm::sys::path::native(PCHDir->getName(), DirNative); - llvm::vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); + llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); SimpleASTReaderListener Validator(CI.getPreprocessor()); for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd; Dir != DirEnd && !EC; Dir.increment(EC)) { @@ -239,9 +232,13 @@ static void SetUpDiagnosticLog(DiagnosticOptions *DiagOpts, std::move(StreamOwner)); if (CodeGenOpts) Logger->setDwarfDebugFlags(CodeGenOpts->DwarfDebugFlags); - assert(Diags.ownsClient()); - Diags.setClient( - new ChainedDiagnosticConsumer(Diags.takeClient(), std::move(Logger))); + if (Diags.ownsClient()) { + Diags.setClient( + new ChainedDiagnosticConsumer(Diags.takeClient(), std::move(Logger))); + } else { + Diags.setClient( + new ChainedDiagnosticConsumer(Diags.getClient(), std::move(Logger))); + } } static void SetupSerializedDiagnostics(DiagnosticOptions *DiagOpts, @@ -301,13 +298,14 @@ CompilerInstance::createDiagnostics(DiagnosticOptions *Opts, // File Manager -FileManager *CompilerInstance::createFileManager() { - if (!hasVirtualFileSystem()) { - IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = - createVFSFromCompilerInvocation(getInvocation(), getDiagnostics()); - setVirtualFileSystem(VFS); - } - FileMgr = new FileManager(getFileSystemOpts(), VirtualFileSystem); +FileManager *CompilerInstance::createFileManager( + IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) { + if (!VFS) + VFS = FileMgr ? &FileMgr->getVirtualFileSystem() + : createVFSFromCompilerInvocation(getInvocation(), + getDiagnostics()); + assert(VFS && "FileManager has no VFS?"); + FileMgr = new FileManager(getFileSystemOpts(), std::move(VFS)); return FileMgr.get(); } @@ -379,11 +377,11 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) { HeaderSearch *HeaderInfo = new HeaderSearch(getHeaderSearchOptsPtr(), getSourceManager(), getDiagnostics(), getLangOpts(), &getTarget()); - PP = std::make_shared<Preprocessor>( - Invocation->getPreprocessorOptsPtr(), getDiagnostics(), getLangOpts(), - getSourceManager(), getPCMCache(), *HeaderInfo, *this, - /*IdentifierInfoLookup=*/nullptr, - /*OwnsHeaderSearch=*/true, TUKind); + PP = std::make_shared<Preprocessor>(Invocation->getPreprocessorOptsPtr(), + getDiagnostics(), getLangOpts(), + getSourceManager(), *HeaderInfo, *this, + /*IdentifierInfoLookup=*/nullptr, + /*OwnsHeaderSearch=*/true, TUKind); getTarget().adjust(getLangOpts()); PP->Initialize(getTarget(), getAuxTarget()); @@ -417,8 +415,7 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) { // Handle generating dependencies, if requested. const DependencyOutputOptions &DepOpts = getDependencyOutputOpts(); if (!DepOpts.OutputFile.empty()) - TheDependencyFileGenerator.reset( - DependencyFileGenerator::CreateAndAttachToPreprocessor(*PP, DepOpts)); + addDependencyCollector(std::make_shared<DependencyFileGenerator>(DepOpts)); if (!DepOpts.DOTOutputFile.empty()) AttachDependencyGraphGen(*PP, DepOpts.DOTOutputFile, getHeaderSearchOpts().Sysroot); @@ -490,29 +487,26 @@ void CompilerInstance::createPCHExternalASTSource( bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0; ModuleManager = createPCHExternalASTSource( Path, getHeaderSearchOpts().Sysroot, DisablePCHValidation, - AllowPCHWithCompilerErrors, getPreprocessor(), getASTContext(), - getPCHContainerReader(), - getFrontendOpts().ModuleFileExtensions, - TheDependencyFileGenerator.get(), - DependencyCollectors, - DeserializationListener, - OwnDeserializationListener, Preamble, + AllowPCHWithCompilerErrors, getPreprocessor(), getModuleCache(), + getASTContext(), getPCHContainerReader(), + getFrontendOpts().ModuleFileExtensions, DependencyCollectors, + DeserializationListener, OwnDeserializationListener, Preamble, getFrontendOpts().UseGlobalModuleIndex); } IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource( StringRef Path, StringRef Sysroot, bool DisablePCHValidation, - bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context, + bool AllowPCHWithCompilerErrors, Preprocessor &PP, + InMemoryModuleCache &ModuleCache, ASTContext &Context, const PCHContainerReader &PCHContainerRdr, ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions, - DependencyFileGenerator *DependencyFile, ArrayRef<std::shared_ptr<DependencyCollector>> DependencyCollectors, void *DeserializationListener, bool OwnDeserializationListener, bool Preamble, bool UseGlobalModuleIndex) { HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts(); IntrusiveRefCntPtr<ASTReader> Reader(new ASTReader( - PP, &Context, PCHContainerRdr, Extensions, + PP, ModuleCache, &Context, PCHContainerRdr, Extensions, Sysroot.empty() ? "" : Sysroot.data(), DisablePCHValidation, AllowPCHWithCompilerErrors, /*AllowConfigurationMismatch*/ false, HSOpts.ModulesValidateSystemHeaders, UseGlobalModuleIndex)); @@ -525,8 +519,6 @@ IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource( static_cast<ASTDeserializationListener *>(DeserializationListener), /*TakeOwnership=*/OwnDeserializationListener); - if (DependencyFile) - DependencyFile->AttachToASTReader(*Reader); for (auto &Listener : DependencyCollectors) Listener->attachToASTReader(*Reader); @@ -593,12 +585,6 @@ void CompilerInstance::createCodeCompletionConsumer() { setCodeCompletionConsumer(nullptr); return; } - - if (CompletionConsumer->isOutputBinary() && - llvm::sys::ChangeStdoutToBinary()) { - getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary); - setCodeCompletionConsumer(nullptr); - } } void CompilerInstance::createFrontendTimer() { @@ -929,6 +915,9 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { // Adjust target options based on codegen options. getTarget().adjustTargetOptions(getCodeGenOpts(), getTargetOpts()); + if (auto *Aux = getAuxTarget()) + getTarget().setAuxTarget(Aux); + // rewriter project will change target built-in bool type from its default. if (getFrontendOpts().ProgramAction == frontend::RewriteObjC) getTarget().noSignedCharForObjCBool(); @@ -952,7 +941,9 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { getSourceManager().clearIDTables(); if (Act.BeginSourceFile(*this, FIF)) { - Act.Execute(); + if (llvm::Error Err = Act.Execute()) { + consumeError(std::move(Err)); // FIXME this drops errors on the floor. + } Act.EndSourceFile(); } } @@ -1031,6 +1022,8 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc, [](CompilerInstance &) {}, llvm::function_ref<void(CompilerInstance &)> PostBuildStep = [](CompilerInstance &) {}) { + llvm::TimeTraceScope TimeScope("Module Compile", ModuleName); + // Construct a compiler invocation for creating this module. auto Invocation = std::make_shared<CompilerInvocation>(ImportingInstance.getInvocation()); @@ -1092,11 +1085,11 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc, Invocation->getModuleHash() && "Module hash mismatch!"); // Construct a compiler instance that will be used to actually create the - // module. Since we're sharing a PCMCache, + // module. Since we're sharing an in-memory module cache, // CompilerInstance::CompilerInstance is responsible for finalizing the // buffers to prevent use-after-frees. CompilerInstance Instance(ImportingInstance.getPCHContainerOperations(), - &ImportingInstance.getPreprocessor().getPCMCache()); + &ImportingInstance.getModuleCache()); auto &Inv = *Invocation; Instance.setInvocation(std::move(Invocation)); @@ -1104,8 +1097,6 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc, ImportingInstance.getDiagnosticClient()), /*ShouldOwnClient=*/true); - Instance.setVirtualFileSystem(&ImportingInstance.getVirtualFileSystem()); - // Note that this module is part of the module build stack, so that we // can detect cycles in the module graph. Instance.setFileManager(&ImportingInstance.getFileManager()); @@ -1253,7 +1244,7 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance, llvm::LockFileManager Locked(ModuleFileName); switch (Locked) { case llvm::LockFileManager::LFS_Error: - // PCMCache takes care of correctness and locks are only necessary for + // ModuleCache takes care of correctness and locks are only necessary for // performance. Fallback to building the module in case of any lock // related errors. Diags.Report(ModuleNameLoc, diag::remark_module_lock_failure) @@ -1280,9 +1271,9 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance, case llvm::LockFileManager::Res_OwnerDied: continue; // try again to get the lock. case llvm::LockFileManager::Res_Timeout: - // Since PCMCache takes care of correctness, we try waiting for another - // process to complete the build so clang does not do it done twice. If - // case of timeout, build it ourselves. + // Since ModuleCache takes care of correctness, we try waiting for + // another process to complete the build so clang does not do it done + // twice. If case of timeout, build it ourselves. Diags.Report(ModuleNameLoc, diag::remark_module_lock_timeout) << Module->Name; // Clear the lock file so that future invocations can make progress. @@ -1480,14 +1471,13 @@ void CompilerInstance::createModuleManager() { "Reading modules", *FrontendTimerGroup); ModuleManager = new ASTReader( - getPreprocessor(), &getASTContext(), getPCHContainerReader(), - getFrontendOpts().ModuleFileExtensions, + getPreprocessor(), getModuleCache(), &getASTContext(), + getPCHContainerReader(), getFrontendOpts().ModuleFileExtensions, Sysroot.empty() ? "" : Sysroot.c_str(), PPOpts.DisablePCHValidation, /*AllowASTWithCompilerErrors=*/false, /*AllowConfigurationMismatch=*/false, HSOpts.ModulesValidateSystemHeaders, - getFrontendOpts().UseGlobalModuleIndex, - std::move(ReadTimer)); + getFrontendOpts().UseGlobalModuleIndex, std::move(ReadTimer)); if (hasASTConsumer()) { ModuleManager->setDeserializationListener( getASTConsumer().GetASTDeserializationListener()); @@ -1500,8 +1490,6 @@ void CompilerInstance::createModuleManager() { if (hasASTConsumer()) ModuleManager->StartTranslationUnit(&getASTConsumer()); - if (TheDependencyFileGenerator) - TheDependencyFileGenerator->AttachToASTReader(*ModuleManager); for (auto &Listener : DependencyCollectors) Listener->attachToASTReader(*ModuleManager); } @@ -1710,6 +1698,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, Timer.init("loading." + ModuleFileName, "Loading " + ModuleFileName, *FrontendTimerGroup); llvm::TimeRegion TimeLoading(FrontendTimerGroup ? &Timer : nullptr); + llvm::TimeTraceScope TimeScope("Module Load", ModuleName); // Try to load the module file. If we are not trying to load from the // module cache, we don't know how to rebuild modules. @@ -2056,9 +2045,16 @@ GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex( hasPreprocessor()) { llvm::sys::fs::create_directories( getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); - GlobalModuleIndex::writeIndex( - getFileManager(), getPCHContainerReader(), - getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); + if (llvm::Error Err = GlobalModuleIndex::writeIndex( + getFileManager(), getPCHContainerReader(), + getPreprocessor().getHeaderSearchInfo().getModuleCachePath())) { + // FIXME this drops the error on the floor. This code is only used for + // typo correction and drops more than just this one source of errors + // (such as the directory creation failure above). It should handle the + // error. + consumeError(std::move(Err)); + return nullptr; + } ModuleManager->resetForReload(); ModuleManager->loadGlobalIndex(); GlobalIndex = ModuleManager->getGlobalIndex(); @@ -2083,9 +2079,13 @@ GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex( } } if (RecreateIndex) { - GlobalModuleIndex::writeIndex( - getFileManager(), getPCHContainerReader(), - getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); + if (llvm::Error Err = GlobalModuleIndex::writeIndex( + getFileManager(), getPCHContainerReader(), + getPreprocessor().getHeaderSearchInfo().getModuleCachePath())) { + // FIXME As above, this drops the error on the floor. + consumeError(std::move(Err)); + return nullptr; + } ModuleManager->resetForReload(); ModuleManager->loadGlobalIndex(); GlobalIndex = ModuleManager->getGlobalIndex(); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 3e6528c25982..8a9844096f08 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1,9 +1,8 @@ //===- CompilerInvocation.cpp ---------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -27,6 +26,7 @@ #include "clang/Basic/Visibility.h" #include "clang/Basic/XRayInstr.h" #include "clang/Config/config.h" +#include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "clang/Frontend/CommandLineSourceLoc.h" @@ -285,6 +285,16 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, } Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help); + Opts.ShowCheckerHelpAlpha = Args.hasArg(OPT_analyzer_checker_help_alpha); + Opts.ShowCheckerHelpDeveloper = + Args.hasArg(OPT_analyzer_checker_help_developer); + + Opts.ShowCheckerOptionList = Args.hasArg(OPT_analyzer_checker_option_help); + Opts.ShowCheckerOptionAlphaList = + Args.hasArg(OPT_analyzer_checker_option_help_alpha); + Opts.ShowCheckerOptionDeveloperList = + Args.hasArg(OPT_analyzer_checker_option_help_developer); + Opts.ShowConfigOptionsList = Args.hasArg(OPT_analyzer_config_help); Opts.ShowEnabledCheckerList = Args.hasArg(OPT_analyzer_list_enabled_checkers); Opts.ShouldEmitErrorsOnInvalidConfigValue = @@ -299,6 +309,7 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, Args.hasArg(OPT_analyzer_viz_egraph_graphviz); Opts.DumpExplodedGraphTo = Args.getLastArgValue(OPT_analyzer_dump_egraph); Opts.NoRetryExhausted = Args.hasArg(OPT_analyzer_disable_retry_exhausted); + Opts.AnalyzerWerror = Args.hasArg(OPT_analyzer_werror); Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers); Opts.AnalyzerDisplayProgress = Args.hasArg(OPT_analyzer_display_progress); Opts.AnalyzeNestedBlocks = @@ -422,7 +433,7 @@ static void initOption(AnalyzerOptions::ConfigTable &Config, OptionField = DefaultVal; bool HasFailed = getStringOption(Config, Name, std::to_string(DefaultVal)) - .getAsInteger(10, OptionField); + .getAsInteger(0, OptionField); if (Diags && HasFailed) Diags->Report(diag::err_analyzer_config_invalid_input) << Name << "an unsigned"; @@ -456,6 +467,10 @@ static void parseAnalyzerConfigs(AnalyzerOptions &AnOpts, if (!Diags) return; + if (AnOpts.ShouldTrackConditionsDebug && !AnOpts.ShouldTrackConditions) + Diags->Report(diag::err_analyzer_config_invalid_input) + << "track-conditions-debug" << "'track-conditions' to also be enabled"; + if (!AnOpts.CTUDir.empty() && !llvm::sys::fs::is_directory(AnOpts.CTUDir)) Diags->Report(diag::err_analyzer_config_invalid_input) << "ctu-dir" << "a filename"; @@ -551,7 +566,7 @@ static void parseSanitizerKinds(StringRef FlagName, DiagnosticsEngine &Diags, SanitizerSet &S) { for (const auto &Sanitizer : Sanitizers) { SanitizerMask K = parseSanitizerValue(Sanitizer, /*AllowGroups=*/false); - if (K == 0) + if (K == SanitizerMask()) Diags.Report(diag::err_drv_invalid_value) << FlagName << Sanitizer; else S.set(K, true); @@ -588,6 +603,7 @@ static void setPGOInstrumentor(CodeGenOptions &Opts, ArgList &Args, .Case("none", CodeGenOptions::ProfileNone) .Case("clang", CodeGenOptions::ProfileClangInstr) .Case("llvm", CodeGenOptions::ProfileIRInstr) + .Case("csllvm", CodeGenOptions::ProfileCSIRInstr) .Default(~0U); if (I == ~0U) { Diags.Report(diag::err_drv_invalid_pgo_instrumentor) << A->getAsString(Args) @@ -610,9 +626,12 @@ static void setPGOUseInstrumentor(CodeGenOptions &Opts, } std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader = std::move(ReaderOrErr.get()); - if (PGOReader->isIRLevelProfile()) - Opts.setProfileUse(CodeGenOptions::ProfileIRInstr); - else + if (PGOReader->isIRLevelProfile()) { + if (PGOReader->hasCSIRLevelProfile()) + Opts.setProfileUse(CodeGenOptions::ProfileCSIRInstr); + else + Opts.setProfileUse(CodeGenOptions::ProfileIRInstr); + } else Opts.setProfileUse(CodeGenOptions::ProfileClangInstr); } @@ -668,6 +687,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, StringRef Name = A->getValue(); if (Name == "Accelerate") Opts.setVecLib(CodeGenOptions::Accelerate); + else if (Name == "MASSV") + Opts.setVecLib(CodeGenOptions::MASSV); else if (Name == "SVML") Opts.setVecLib(CodeGenOptions::SVML); else if (Name == "none") @@ -710,24 +731,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.WholeProgramVTables = Args.hasArg(OPT_fwhole_program_vtables); Opts.LTOVisibilityPublicStd = Args.hasArg(OPT_flto_visibility_public_std); Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file); + Opts.SplitDwarfOutput = Args.getLastArgValue(OPT_split_dwarf_output); Opts.SplitDwarfInlining = !Args.hasArg(OPT_fno_split_dwarf_inlining); - - if (Arg *A = - Args.getLastArg(OPT_enable_split_dwarf, OPT_enable_split_dwarf_EQ)) { - if (A->getOption().matches(options::OPT_enable_split_dwarf)) { - Opts.setSplitDwarfMode(CodeGenOptions::SplitFileFission); - } else { - StringRef Name = A->getValue(); - if (Name == "single") - Opts.setSplitDwarfMode(CodeGenOptions::SingleFileFission); - else if (Name == "split") - Opts.setSplitDwarfMode(CodeGenOptions::SplitFileFission); - else - Diags.Report(diag::err_drv_invalid_value) - << A->getAsString(Args) << Name; - } - } - Opts.DebugTypeExtRefs = Args.hasArg(OPT_dwarf_ext_refs); Opts.DebugExplicitImport = Args.hasArg(OPT_dwarf_explicit_import); Opts.DebugFwdTemplateParams = Args.hasArg(OPT_debug_forward_template_params); @@ -742,6 +747,13 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.DisableLLVMPasses = Args.hasArg(OPT_disable_llvm_passes); Opts.DisableLifetimeMarkers = Args.hasArg(OPT_disable_lifetimemarkers); + + llvm::Triple T(TargetOpts.Triple); + llvm::Triple::ArchType Arch = T.getArch(); + if (Opts.OptimizationLevel > 0 && + (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64)) + Opts.EnableDebugEntryValues = Args.hasArg(OPT_femit_debug_entry_values); + Opts.DisableO0ImplyOptNone = Args.hasArg(OPT_disable_O0_optnone); Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone); Opts.IndirectTlsSegRefs = Args.hasArg(OPT_mno_tls_direct_seg_refs); @@ -1214,6 +1226,16 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, if (!Opts.OptRecordFile.empty()) NeedLocTracking = true; + if (Arg *A = Args.getLastArg(OPT_opt_record_passes)) { + Opts.OptRecordPasses = A->getValue(); + NeedLocTracking = true; + } + + if (Arg *A = Args.getLastArg(OPT_opt_record_format)) { + Opts.OptRecordFormat = A->getValue(); + NeedLocTracking = true; + } + if (Arg *A = Args.getLastArg(OPT_Rpass_EQ)) { Opts.OptimizationRemarkPattern = GenerateOptimizationRemarkRegex(Diags, Args, A); @@ -1322,6 +1344,10 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.DefaultFunctionAttrs = Args.getAllArgValues(OPT_default_function_attr); + Opts.PassPlugins = Args.getAllArgValues(OPT_fpass_plugin_EQ); + + Opts.SymbolPartition = Args.getLastArgValue(OPT_fsymbol_partition_EQ); + return Success; } @@ -1402,9 +1428,9 @@ static bool checkVerifyPrefixes(const std::vector<std::string> &VerifyPrefixes, for (const auto &Prefix : VerifyPrefixes) { // Every prefix must start with a letter and contain only alphanumeric // characters, hyphens, and underscores. - auto BadChar = std::find_if(Prefix.begin(), Prefix.end(), - [](char C){return !isAlphanumeric(C) - && C != '-' && C != '_';}); + auto BadChar = llvm::find_if(Prefix, [](char C) { + return !isAlphanumeric(C) && C != '-' && C != '_'; + }); if (BadChar != Prefix.end() || !isLetter(Prefix[0])) { Success = false; if (Diags) { @@ -1592,6 +1618,22 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, llvm_unreachable("Invalid option in group!"); case OPT_ast_list: Opts.ProgramAction = frontend::ASTDeclList; break; + case OPT_ast_dump_all_EQ: + case OPT_ast_dump_EQ: { + unsigned Val = llvm::StringSwitch<unsigned>(A->getValue()) + .CaseLower("default", ADOF_Default) + .CaseLower("json", ADOF_JSON) + .Default(std::numeric_limits<unsigned>::max()); + + if (Val != std::numeric_limits<unsigned>::max()) + Opts.ASTDumpFormat = static_cast<ASTDumpOutputFormat>(Val); + else { + Diags.Report(diag::err_drv_invalid_value) + << A->getAsString(Args) << A->getValue(); + Opts.ASTDumpFormat = ADOF_Default; + } + LLVM_FALLTHROUGH; + } case OPT_ast_dump: case OPT_ast_dump_all: case OPT_ast_dump_lookups: @@ -1633,6 +1675,25 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::GenerateHeaderModule; break; case OPT_emit_pch: Opts.ProgramAction = frontend::GeneratePCH; break; + case OPT_emit_iterface_stubs: { + llvm::Optional<frontend::ActionKind> ProgramAction = + llvm::StringSwitch<llvm::Optional<frontend::ActionKind>>( + Args.hasArg(OPT_iterface_stub_version_EQ) + ? Args.getLastArgValue(OPT_iterface_stub_version_EQ) + : "") + .Case("experimental-yaml-elf-v1", + frontend::GenerateInterfaceYAMLExpV1) + .Case("experimental-tapi-elf-v1", + frontend::GenerateInterfaceTBEExpV1) + .Default(llvm::None); + if (!ProgramAction) + Diags.Report(diag::err_drv_invalid_value) + << "Must specify a valid interface stub format type using " + << "-interface-stub-version=<experimental-tapi-elf-v1 | " + "experimental-yaml-elf-v1>"; + Opts.ProgramAction = *ProgramAction; + break; + } case OPT_init_only: Opts.ProgramAction = frontend::InitOnly; break; case OPT_fsyntax_only: @@ -1659,6 +1720,10 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::MigrateSource; break; case OPT_Eonly: Opts.ProgramAction = frontend::RunPreprocessorOnly; break; + case OPT_print_dependency_directives_minimized_source: + Opts.ProgramAction = + frontend::PrintDependencyDirectivesSourceMinimizerOutput; + break; } } @@ -1706,6 +1771,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ShowHelp = Args.hasArg(OPT_help); Opts.ShowStats = Args.hasArg(OPT_print_stats); Opts.ShowTimers = Args.hasArg(OPT_ftime_report); + Opts.PrintSupportedCPUs = Args.hasArg(OPT_print_supported_cpus); + Opts.TimeTrace = Args.hasArg(OPT_ftime_trace); Opts.ShowVersion = Args.hasArg(OPT_version); Opts.ASTMergeFiles = Args.getAllArgValues(OPT_ast_merge); Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm); @@ -1713,8 +1780,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.FixOnlyWarnings = Args.hasArg(OPT_fix_only_warnings); Opts.FixAndRecompile = Args.hasArg(OPT_fixit_recompile); Opts.FixToTemporaries = Args.hasArg(OPT_fixit_to_temp); - Opts.ASTDumpDecls = Args.hasArg(OPT_ast_dump); - Opts.ASTDumpAll = Args.hasArg(OPT_ast_dump_all); + Opts.ASTDumpDecls = Args.hasArg(OPT_ast_dump, OPT_ast_dump_EQ); + Opts.ASTDumpAll = Args.hasArg(OPT_ast_dump_all, OPT_ast_dump_all_EQ); Opts.ASTDumpFilter = Args.getLastArgValue(OPT_ast_dump_filter); Opts.ASTDumpLookups = Args.hasArg(OPT_ast_dump_lookups); Opts.UseGlobalModuleIndex = !Args.hasArg(OPT_fno_modules_global_index); @@ -1894,18 +1961,7 @@ std::string CompilerInvocation::GetResourcesPath(const char *Argv0, void *MainAddr) { std::string ClangExecutable = llvm::sys::fs::getMainExecutable(Argv0, MainAddr); - StringRef Dir = llvm::sys::path::parent_path(ClangExecutable); - - // Compute the path to the resource directory. - StringRef ClangResourceDir(CLANG_RESOURCE_DIR); - SmallString<128> P(Dir); - if (ClangResourceDir != "") - llvm::sys::path::append(P, ClangResourceDir); - else - llvm::sys::path::append(P, "..", Twine("lib") + CLANG_LIBDIR_SUFFIX, - "clang", CLANG_VERSION_STRING); - - return P.str(); + return Driver::GetResourcesPath(ClangExecutable, CLANG_RESOURCE_DIR); } static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, @@ -2117,6 +2173,7 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, Opts.C99 = Std.isC99(); Opts.C11 = Std.isC11(); Opts.C17 = Std.isC17(); + Opts.C2x = Std.isC2x(); Opts.CPlusPlus = Std.isCPlusPlus(); Opts.CPlusPlus11 = Std.isCPlusPlus11(); Opts.CPlusPlus14 = Std.isCPlusPlus14(); @@ -2150,9 +2207,15 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, Opts.NativeHalfType = 1; Opts.NativeHalfArgsAndReturns = 1; Opts.OpenCLCPlusPlus = Opts.CPlusPlus; + // Include default header file for OpenCL. if (Opts.IncludeDefaultHeader) { - PPOpts.Includes.push_back("opencl-c.h"); + if (Opts.DeclareOpenCLBuiltins) { + // Only include base header file for builtin types and constants. + PPOpts.Includes.push_back("opencl-c-base.h"); + } else { + PPOpts.Includes.push_back("opencl-c.h"); + } } } @@ -2183,6 +2246,9 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, Opts.AlignedAllocation = Opts.CPlusPlus17; Opts.DollarIdents = !Opts.AsmPreprocessor; + + // Enable [[]] attributes in C++11 and C2x by default. + Opts.DoubleSquareBracketAttributes = Opts.CPlusPlus11 || Opts.C2x; } /// Attempt to parse a visibility value out of the given argument. @@ -2354,6 +2420,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, } Opts.IncludeDefaultHeader = Args.hasArg(OPT_finclude_default_header); + Opts.DeclareOpenCLBuiltins = Args.hasArg(OPT_fdeclare_opencl_builtins); llvm::Triple T(TargetOpts.Triple); CompilerInvocation::setLangDefaults(Opts, IK, T, PPOpts, LangStd); @@ -2502,6 +2569,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, if (Args.hasArg(OPT_fvisibility_global_new_delete_hidden)) Opts.GlobalAllocationFunctionVisibilityHidden = 1; + if (Args.hasArg(OPT_fapply_global_visibility_to_externs)) + Opts.SetVisibilityForExternDecls = 1; + if (Args.hasArg(OPT_ftrapv)) { Opts.setSignedOverflowBehavior(LangOptions::SOB_Trapping); // Set the handler, if one is specified. @@ -2583,20 +2653,25 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL && Opts.OpenCLVersion == 200); Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional); - Opts.CoroutinesTS = Args.hasArg(OPT_fcoroutines_ts); + Opts.Coroutines = Opts.CPlusPlus2a || Args.hasArg(OPT_fcoroutines_ts); - // Enable [[]] attributes in C++11 by default. Opts.DoubleSquareBracketAttributes = Args.hasFlag(OPT_fdouble_square_bracket_attributes, - OPT_fno_double_square_bracket_attributes, Opts.CPlusPlus11); + OPT_fno_double_square_bracket_attributes, + Opts.DoubleSquareBracketAttributes); + Opts.CPlusPlusModules = Opts.CPlusPlus2a; Opts.ModulesTS = Args.hasArg(OPT_fmodules_ts); - Opts.Modules = Args.hasArg(OPT_fmodules) || Opts.ModulesTS; + Opts.Modules = + Args.hasArg(OPT_fmodules) || Opts.ModulesTS || Opts.CPlusPlusModules; Opts.ModulesStrictDeclUse = Args.hasArg(OPT_fmodules_strict_decluse); Opts.ModulesDeclUse = Args.hasArg(OPT_fmodules_decluse) || Opts.ModulesStrictDeclUse; + // FIXME: We only need this in C++ modules / Modules TS if we might textually + // enter a different module (eg, when building a header unit). Opts.ModulesLocalVisibility = - Args.hasArg(OPT_fmodules_local_submodule_visibility) || Opts.ModulesTS; + Args.hasArg(OPT_fmodules_local_submodule_visibility) || Opts.ModulesTS || + Opts.CPlusPlusModules; Opts.ModulesCodegen = Args.hasArg(OPT_fmodules_codegen); Opts.ModulesDebugInfo = Args.hasArg(OPT_fmodules_debuginfo); Opts.ModulesSearchAll = Opts.Modules && @@ -2667,7 +2742,13 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.PackStruct = getLastArgIntValue(Args, OPT_fpack_struct_EQ, 0, Diags); Opts.MaxTypeAlign = getLastArgIntValue(Args, OPT_fmax_type_align_EQ, 0, Diags); Opts.AlignDouble = Args.hasArg(OPT_malign_double); + Opts.LongDoubleSize = Args.hasArg(OPT_mlong_double_128) + ? 128 + : Args.hasArg(OPT_mlong_double_64) ? 64 : 0; + Opts.PPCIEEELongDouble = Args.hasArg(OPT_mabi_EQ_ieeelongdouble); Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags); + Opts.ROPI = Args.hasArg(OPT_fropi); + Opts.RWPI = Args.hasArg(OPT_frwpi); Opts.PIE = Args.hasArg(OPT_pic_is_pie); Opts.Static = Args.hasArg(OPT_static_define); Opts.DumpRecordLayoutsSimple = Args.hasArg(OPT_fdump_record_layouts_simple); @@ -2697,6 +2778,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.HalfArgsAndReturns = Args.hasArg(OPT_fallow_half_arguments_and_returns) | Opts.NativeHalfArgsAndReturns; Opts.GNUAsm = !Args.hasArg(OPT_fno_gnu_inline_asm); + Opts.Cmse = Args.hasArg(OPT_mcmse); // Armv8-M Security Extensions // __declspec is enabled by default for the PS4 by the driver, and also // enabled for Microsoft Extensions or Borland Extensions, here. @@ -2833,7 +2915,6 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, // Set the flag to prevent the implementation from emitting device exception // handling code for those requiring so. - Opts.OpenMPHostCXXExceptions = Opts.Exceptions && Opts.CXXExceptions; if ((Opts.OpenMPIsDevice && T.isNVPTX()) || Opts.OpenCLCPlusPlus) { Opts.Exceptions = 0; Opts.CXXExceptions = 0; @@ -2845,6 +2926,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.OpenMPCUDABlocksPerSM = getLastArgIntValue(Args, options::OPT_fopenmp_cuda_blocks_per_sm_EQ, Opts.OpenMPCUDABlocksPerSM, Diags); + Opts.OpenMPCUDAReductionBufNum = getLastArgIntValue( + Args, options::OPT_fopenmp_cuda_teams_reduction_recs_num_EQ, + Opts.OpenMPCUDAReductionBufNum, Diags); } // Prevent auto-widening the representation of loop counters during an @@ -2881,6 +2965,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, << Opts.OMPHostIRFile; } + Opts.SYCLIsDevice = Args.hasArg(options::OPT_fsycl_is_device); + // Set CUDA mode for OpenMP target NVPTX if specified in options Opts.OpenMPCUDAMode = Opts.OpenMPIsDevice && T.isNVPTX() && Args.hasArg(options::OPT_fopenmp_cuda_mode); @@ -3050,6 +3136,8 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { case frontend::GenerateModuleInterface: case frontend::GenerateHeaderModule: case frontend::GeneratePCH: + case frontend::GenerateInterfaceYAMLExpV1: + case frontend::GenerateInterfaceTBEExpV1: case frontend::ParseSyntaxOnly: case frontend::ModuleFileInfo: case frontend::VerifyPCH: @@ -3069,6 +3157,7 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { case frontend::PrintPreprocessedInput: case frontend::RewriteMacros: case frontend::RunPreprocessorOnly: + case frontend::PrintDependencyDirectivesSourceMinimizerOutput: return true; } llvm_unreachable("invalid frontend action"); @@ -3333,10 +3422,8 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, Res.getFrontendOpts().ProgramAction); // Turn on -Wspir-compat for SPIR target. - auto Arch = T.getArch(); - if (Arch == llvm::Triple::spir || Arch == llvm::Triple::spir64) { + if (T.isSPIR()) Res.getDiagnosticOpts().Warnings.push_back("spir-compat"); - } // If sanitizer is enabled, disable OPT_ffine_grained_bitfield_accesses. if (Res.getCodeGenOpts().FineGrainedBitfieldAccesses && diff --git a/lib/Frontend/CreateInvocationFromCommandLine.cpp b/lib/Frontend/CreateInvocationFromCommandLine.cpp index 2d4c40f8b9f1..b62416ffd9e7 100644 --- a/lib/Frontend/CreateInvocationFromCommandLine.cpp +++ b/lib/Frontend/CreateInvocationFromCommandLine.cpp @@ -1,9 +1,8 @@ //===--- CreateInvocationFromCommandLine.cpp - CompilerInvocation from Args ==// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp index a03d4b79c8b9..375eb91ae366 100644 --- a/lib/Frontend/DependencyFile.cpp +++ b/lib/Frontend/DependencyFile.cpp @@ -1,9 +1,8 @@ //===--- DependencyFile.cpp - Generate dependency file --------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -33,8 +32,10 @@ namespace { struct DepCollectorPPCallbacks : public PPCallbacks { DependencyCollector &DepCollector; SourceManager &SM; - DepCollectorPPCallbacks(DependencyCollector &L, SourceManager &SM) - : DepCollector(L), SM(SM) { } + DiagnosticsEngine &Diags; + DepCollectorPPCallbacks(DependencyCollector &L, SourceManager &SM, + DiagnosticsEngine &Diags) + : DepCollector(L), SM(SM), Diags(Diags) {} void FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType, @@ -58,6 +59,16 @@ struct DepCollectorPPCallbacks : public PPCallbacks { /*IsModuleFile*/false, /*IsMissing*/false); } + void FileSkipped(const FileEntry &SkippedFile, const Token &FilenameTok, + SrcMgr::CharacteristicKind FileType) override { + StringRef Filename = + llvm::sys::path::remove_leading_dotslash(SkippedFile.getName()); + DepCollector.maybeAddDependency(Filename, /*FromModule=*/false, + /*IsSystem=*/isSystem(FileType), + /*IsModuleFile=*/false, + /*IsMissing=*/false); + } + void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File, @@ -71,9 +82,20 @@ struct DepCollectorPPCallbacks : public PPCallbacks { // Files that actually exist are handled by FileChanged. } - void EndOfMainFile() override { - DepCollector.finishedMainFile(); + void HasInclude(SourceLocation Loc, StringRef SpelledFilename, bool IsAngled, + const FileEntry *File, + SrcMgr::CharacteristicKind FileType) override { + if (!File) + return; + StringRef Filename = + llvm::sys::path::remove_leading_dotslash(File->getName()); + DepCollector.maybeAddDependency(Filename, /*FromModule=*/false, + /*IsSystem=*/isSystem(FileType), + /*IsModuleFile=*/false, + /*IsMissing=*/false); } + + void EndOfMainFile() override { DepCollector.finishedMainFile(Diags); } }; struct DepCollectorMMCallbacks : public ModuleMapCallbacks { @@ -118,9 +140,16 @@ struct DepCollectorASTListener : public ASTReaderListener { void DependencyCollector::maybeAddDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsMissing) { - if (Seen.insert(Filename).second && - sawDependency(Filename, FromModule, IsSystem, IsModuleFile, IsMissing)) + if (sawDependency(Filename, FromModule, IsSystem, IsModuleFile, IsMissing)) + addDependency(Filename); +} + +bool DependencyCollector::addDependency(StringRef Filename) { + if (Seen.insert(Filename).second) { Dependencies.push_back(Filename); + return true; + } + return false; } static bool isSpecialFilename(StringRef Filename) { @@ -139,8 +168,8 @@ bool DependencyCollector::sawDependency(StringRef Filename, bool FromModule, DependencyCollector::~DependencyCollector() { } void DependencyCollector::attachToPreprocessor(Preprocessor &PP) { - PP.addPPCallbacks( - llvm::make_unique<DepCollectorPPCallbacks>(*this, PP.getSourceManager())); + PP.addPPCallbacks(llvm::make_unique<DepCollectorPPCallbacks>( + *this, PP.getSourceManager(), PP.getDiagnostics())); PP.getHeaderSearchInfo().getModuleMap().addModuleMapCallbacks( llvm::make_unique<DepCollectorMMCallbacks>(*this)); } @@ -148,206 +177,57 @@ void DependencyCollector::attachToASTReader(ASTReader &R) { R.addListener(llvm::make_unique<DepCollectorASTListener>(*this)); } -namespace { -/// Private implementation for DependencyFileGenerator -class DFGImpl : public PPCallbacks { - std::vector<std::string> Files; - llvm::StringSet<> FilesSet; - const Preprocessor *PP; - std::string OutputFile; - std::vector<std::string> Targets; - bool IncludeSystemHeaders; - bool PhonyTarget; - bool AddMissingHeaderDeps; - bool SeenMissingHeader; - bool IncludeModuleFiles; - DependencyOutputFormat OutputFormat; - unsigned InputFileIndex; - -private: - bool FileMatchesDepCriteria(const char *Filename, - SrcMgr::CharacteristicKind FileType); - void OutputDependencyFile(); - -public: - DFGImpl(const Preprocessor *_PP, const DependencyOutputOptions &Opts) - : PP(_PP), OutputFile(Opts.OutputFile), Targets(Opts.Targets), +DependencyFileGenerator::DependencyFileGenerator( + const DependencyOutputOptions &Opts) + : OutputFile(Opts.OutputFile), Targets(Opts.Targets), IncludeSystemHeaders(Opts.IncludeSystemHeaders), PhonyTarget(Opts.UsePhonyTargets), - AddMissingHeaderDeps(Opts.AddMissingHeaderDeps), - SeenMissingHeader(false), + AddMissingHeaderDeps(Opts.AddMissingHeaderDeps), SeenMissingHeader(false), IncludeModuleFiles(Opts.IncludeModuleFiles), - OutputFormat(Opts.OutputFormat), - InputFileIndex(0) { - for (const auto &ExtraDep : Opts.ExtraDeps) { - if (AddFilename(ExtraDep)) - ++InputFileIndex; - } - } - - void FileChanged(SourceLocation Loc, FileChangeReason Reason, - SrcMgr::CharacteristicKind FileType, - FileID PrevFID) override; - - void FileSkipped(const FileEntry &SkippedFile, const Token &FilenameTok, - SrcMgr::CharacteristicKind FileType) override; - - void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, - StringRef FileName, bool IsAngled, - CharSourceRange FilenameRange, const FileEntry *File, - StringRef SearchPath, StringRef RelativePath, - const Module *Imported, - SrcMgr::CharacteristicKind FileType) override; - - void HasInclude(SourceLocation Loc, StringRef SpelledFilename, bool IsAngled, - const FileEntry *File, - SrcMgr::CharacteristicKind FileType) override; - - void EndOfMainFile() override { - OutputDependencyFile(); + OutputFormat(Opts.OutputFormat), InputFileIndex(0) { + for (const auto &ExtraDep : Opts.ExtraDeps) { + if (addDependency(ExtraDep)) + ++InputFileIndex; } - - bool AddFilename(StringRef Filename); - bool includeSystemHeaders() const { return IncludeSystemHeaders; } - bool includeModuleFiles() const { return IncludeModuleFiles; } -}; - -class DFGMMCallback : public ModuleMapCallbacks { - DFGImpl &Parent; -public: - DFGMMCallback(DFGImpl &Parent) : Parent(Parent) {} - void moduleMapFileRead(SourceLocation Loc, const FileEntry &Entry, - bool IsSystem) override { - if (!IsSystem || Parent.includeSystemHeaders()) - Parent.AddFilename(Entry.getName()); - } -}; - -class DFGASTReaderListener : public ASTReaderListener { - DFGImpl &Parent; -public: - DFGASTReaderListener(DFGImpl &Parent) - : Parent(Parent) { } - bool needsInputFileVisitation() override { return true; } - bool needsSystemInputFileVisitation() override { - return Parent.includeSystemHeaders(); - } - void visitModuleFile(StringRef Filename, - serialization::ModuleKind Kind) override; - bool visitInputFile(StringRef Filename, bool isSystem, - bool isOverridden, bool isExplicitModule) override; -}; } -DependencyFileGenerator::DependencyFileGenerator(void *Impl) -: Impl(Impl) { } - -DependencyFileGenerator *DependencyFileGenerator::CreateAndAttachToPreprocessor( - clang::Preprocessor &PP, const clang::DependencyOutputOptions &Opts) { - - if (Opts.Targets.empty()) { +void DependencyFileGenerator::attachToPreprocessor(Preprocessor &PP) { + if (Targets.empty()) { PP.getDiagnostics().Report(diag::err_fe_dependency_file_requires_MT); - return nullptr; + return; } // Disable the "file not found" diagnostic if the -MG option was given. - if (Opts.AddMissingHeaderDeps) + if (AddMissingHeaderDeps) PP.SetSuppressIncludeNotFoundError(true); - DFGImpl *Callback = new DFGImpl(&PP, Opts); - PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callback)); - PP.getHeaderSearchInfo().getModuleMap().addModuleMapCallbacks( - llvm::make_unique<DFGMMCallback>(*Callback)); - return new DependencyFileGenerator(Callback); + DependencyCollector::attachToPreprocessor(PP); } -void DependencyFileGenerator::AttachToASTReader(ASTReader &R) { - DFGImpl *I = reinterpret_cast<DFGImpl *>(Impl); - assert(I && "missing implementation"); - R.addListener(llvm::make_unique<DFGASTReaderListener>(*I)); -} +bool DependencyFileGenerator::sawDependency(StringRef Filename, bool FromModule, + bool IsSystem, bool IsModuleFile, + bool IsMissing) { + if (IsMissing) { + // Handle the case of missing file from an inclusion directive. + if (AddMissingHeaderDeps) + return true; + SeenMissingHeader = true; + return false; + } + if (IsModuleFile && !IncludeModuleFiles) + return false; -/// FileMatchesDepCriteria - Determine whether the given Filename should be -/// considered as a dependency. -bool DFGImpl::FileMatchesDepCriteria(const char *Filename, - SrcMgr::CharacteristicKind FileType) { if (isSpecialFilename(Filename)) return false; if (IncludeSystemHeaders) return true; - return !isSystem(FileType); + return !IsSystem; } -void DFGImpl::FileChanged(SourceLocation Loc, - FileChangeReason Reason, - SrcMgr::CharacteristicKind FileType, - FileID PrevFID) { - if (Reason != PPCallbacks::EnterFile) - return; - - // Dependency generation really does want to go all the way to the - // file entry for a source location to find out what is depended on. - // We do not want #line markers to affect dependency generation! - SourceManager &SM = PP->getSourceManager(); - - const FileEntry *FE = - SM.getFileEntryForID(SM.getFileID(SM.getExpansionLoc(Loc))); - if (!FE) return; - - StringRef Filename = FE->getName(); - if (!FileMatchesDepCriteria(Filename.data(), FileType)) - return; - - AddFilename(llvm::sys::path::remove_leading_dotslash(Filename)); -} - -void DFGImpl::FileSkipped(const FileEntry &SkippedFile, - const Token &FilenameTok, - SrcMgr::CharacteristicKind FileType) { - StringRef Filename = SkippedFile.getName(); - if (!FileMatchesDepCriteria(Filename.data(), FileType)) - return; - - AddFilename(llvm::sys::path::remove_leading_dotslash(Filename)); -} - -void DFGImpl::InclusionDirective(SourceLocation HashLoc, - const Token &IncludeTok, - StringRef FileName, - bool IsAngled, - CharSourceRange FilenameRange, - const FileEntry *File, - StringRef SearchPath, - StringRef RelativePath, - const Module *Imported, - SrcMgr::CharacteristicKind FileType) { - if (!File) { - if (AddMissingHeaderDeps) - AddFilename(FileName); - else - SeenMissingHeader = true; - } -} - -void DFGImpl::HasInclude(SourceLocation Loc, StringRef SpelledFilename, - bool IsAngled, const FileEntry *File, - SrcMgr::CharacteristicKind FileType) { - if (!File) - return; - StringRef Filename = File->getName(); - if (!FileMatchesDepCriteria(Filename.data(), FileType)) - return; - AddFilename(llvm::sys::path::remove_leading_dotslash(Filename)); -} - -bool DFGImpl::AddFilename(StringRef Filename) { - if (FilesSet.insert(Filename).second) { - Files.push_back(Filename); - return true; - } - return false; +void DependencyFileGenerator::finishedMainFile(DiagnosticsEngine &Diags) { + outputDependencyFile(Diags); } /// Print the filename, with escaping or quoting that accommodates the three @@ -429,7 +309,7 @@ static void PrintFilename(raw_ostream &OS, StringRef Filename, } } -void DFGImpl::OutputDependencyFile() { +void DependencyFileGenerator::outputDependencyFile(DiagnosticsEngine &Diags) { if (SeenMissingHeader) { llvm::sys::fs::remove(OutputFile); return; @@ -438,11 +318,14 @@ void DFGImpl::OutputDependencyFile() { std::error_code EC; llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_Text); if (EC) { - PP->getDiagnostics().Report(diag::err_fe_error_opening) << OutputFile - << EC.message(); + Diags.Report(diag::err_fe_error_opening) << OutputFile << EC.message(); return; } + outputDependencyFile(OS); +} + +void DependencyFileGenerator::outputDependencyFile(llvm::raw_ostream &OS) { // Write out the dependency targets, trying to avoid overly long // lines when possible. We try our best to emit exactly the same // dependency file as GCC (4.2), assuming the included files are the @@ -470,6 +353,7 @@ void DFGImpl::OutputDependencyFile() { // Now add each dependency in the order it was seen, but avoiding // duplicates. + ArrayRef<std::string> Files = getDependencies(); for (StringRef File : Files) { // Start a new line if this would exceed the column limit. Make // sure to leave space for a trailing " \" in case we need to @@ -497,20 +381,3 @@ void DFGImpl::OutputDependencyFile() { } } } - -bool DFGASTReaderListener::visitInputFile(llvm::StringRef Filename, - bool IsSystem, bool IsOverridden, - bool IsExplicitModule) { - assert(!IsSystem || needsSystemInputFileVisitation()); - if (IsOverridden || IsExplicitModule) - return true; - - Parent.AddFilename(Filename); - return true; -} - -void DFGASTReaderListener::visitModuleFile(llvm::StringRef Filename, - serialization::ModuleKind Kind) { - if (Parent.includeModuleFiles()) - Parent.AddFilename(Filename); -} diff --git a/lib/Frontend/DependencyGraph.cpp b/lib/Frontend/DependencyGraph.cpp index c6c9ac2ea2fa..90624323a000 100644 --- a/lib/Frontend/DependencyGraph.cpp +++ b/lib/Frontend/DependencyGraph.cpp @@ -1,9 +1,8 @@ //===--- DependencyGraph.cpp - Generate dependency file -------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Frontend/DiagnosticRenderer.cpp b/lib/Frontend/DiagnosticRenderer.cpp index 3bd86dc5beaa..22b957988f46 100644 --- a/lib/Frontend/DiagnosticRenderer.cpp +++ b/lib/Frontend/DiagnosticRenderer.cpp @@ -1,9 +1,8 @@ //===- DiagnosticRenderer.cpp - Diagnostic Pretty-Printing ----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp index f5226380b4dd..d724bbce3749 100644 --- a/lib/Frontend/FrontendAction.cpp +++ b/lib/Frontend/FrontendAction.cpp @@ -1,9 +1,8 @@ //===--- FrontendAction.cpp -----------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -361,7 +360,7 @@ static std::error_code collectModuleHeaderIncludes( SmallString<128> DirNative; llvm::sys::path::native(UmbrellaDir.Entry->getName(), DirNative); - llvm::vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); + llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); for (llvm::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 @@ -715,7 +714,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, SmallString<128> DirNative; llvm::sys::path::native(PCHDir->getName(), DirNative); bool Found = false; - llvm::vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); + llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd; Dir != DirEnd && !EC; Dir.increment(EC)) { @@ -925,7 +924,7 @@ failure: return false; } -bool FrontendAction::Execute() { +llvm::Error FrontendAction::Execute() { CompilerInstance &CI = getCompilerInstance(); if (CI.hasFrontendTimer()) { @@ -940,12 +939,18 @@ bool FrontendAction::Execute() { CI.hasPreprocessor()) { StringRef Cache = CI.getPreprocessor().getHeaderSearchInfo().getModuleCachePath(); - if (!Cache.empty()) - GlobalModuleIndex::writeIndex(CI.getFileManager(), - CI.getPCHContainerReader(), Cache); + if (!Cache.empty()) { + if (llvm::Error Err = GlobalModuleIndex::writeIndex( + CI.getFileManager(), CI.getPCHContainerReader(), Cache)) { + // FIXME this drops the error on the floor, but + // Index/pch-from-libclang.c seems to rely on dropping at least some of + // the error conditions! + consumeError(std::move(Err)); + } + } } - return true; + return llvm::Error::success(); } void FrontendAction::EndSourceFile() { @@ -1045,6 +1050,9 @@ PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI, llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!"); } +bool WrapperFrontendAction::PrepareToExecuteAction(CompilerInstance &CI) { + return WrappedAction->PrepareToExecuteAction(CI); +} std::unique_ptr<ASTConsumer> WrapperFrontendAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index a407dfc162bb..e37afae5332a 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -1,9 +1,8 @@ //===--- FrontendActions.cpp ----------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -15,6 +14,7 @@ #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/MultiplexConsumer.h" #include "clang/Frontend/Utils.h" +#include "clang/Lex/DependencyDirectivesSourceMinimizer.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/PreprocessorOptions.h" @@ -24,8 +24,8 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/YAMLTraits.h" +#include "llvm/Support/raw_ostream.h" #include <memory> #include <system_error> @@ -74,11 +74,10 @@ ASTPrintAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { std::unique_ptr<ASTConsumer> ASTDumpAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - return CreateASTDumper(nullptr /*Dump to stdout.*/, - CI.getFrontendOpts().ASTDumpFilter, - CI.getFrontendOpts().ASTDumpDecls, - CI.getFrontendOpts().ASTDumpAll, - CI.getFrontendOpts().ASTDumpLookups); + const FrontendOptions &Opts = CI.getFrontendOpts(); + return CreateASTDumper(nullptr /*Dump to stdout.*/, Opts.ASTDumpFilter, + Opts.ASTDumpDecls, Opts.ASTDumpAll, + Opts.ASTDumpLookups, Opts.ASTDumpFormat); } std::unique_ptr<ASTConsumer> @@ -110,10 +109,10 @@ GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { auto Buffer = std::make_shared<PCHBuffer>(); std::vector<std::unique_ptr<ASTConsumer>> Consumers; Consumers.push_back(llvm::make_unique<PCHGenerator>( - CI.getPreprocessor(), OutputFile, Sysroot, - Buffer, FrontendOpts.ModuleFileExtensions, - CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, - FrontendOpts.IncludeTimestamps)); + CI.getPreprocessor(), CI.getModuleCache(), OutputFile, Sysroot, Buffer, + FrontendOpts.ModuleFileExtensions, + CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, + FrontendOpts.IncludeTimestamps, +CI.getLangOpts().CacheGeneratedPCH)); Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator( CI, InFile, OutputFile, std::move(OS), Buffer)); @@ -140,7 +139,7 @@ GeneratePCHAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile, std::unique_ptr<raw_pwrite_stream> OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, /*RemoveFileOnSignal=*/false, InFile, - /*Extension=*/"", /*useTemporary=*/true); + /*Extension=*/"", /*UseTemporary=*/true); if (!OS) return nullptr; @@ -173,11 +172,13 @@ GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI, std::vector<std::unique_ptr<ASTConsumer>> Consumers; Consumers.push_back(llvm::make_unique<PCHGenerator>( - CI.getPreprocessor(), OutputFile, Sysroot, - Buffer, CI.getFrontendOpts().ModuleFileExtensions, - /*AllowASTWithErrors=*/false, - /*IncludeTimestamps=*/ - +CI.getFrontendOpts().BuildingImplicitModule)); + CI.getPreprocessor(), CI.getModuleCache(), OutputFile, Sysroot, Buffer, + CI.getFrontendOpts().ModuleFileExtensions, + /*AllowASTWithErrors=*/false, + /*IncludeTimestamps=*/ + +CI.getFrontendOpts().BuildingImplicitModule, + /*ShouldCacheASTInMemory=*/ + +CI.getFrontendOpts().BuildingImplicitModule)); Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator( CI, InFile, OutputFile, std::move(OS), Buffer)); return llvm::make_unique<MultiplexConsumer>(std::move(Consumers)); @@ -214,14 +215,14 @@ GenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI, // We use a temporary to avoid race conditions. return CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, /*RemoveFileOnSignal=*/false, InFile, - /*Extension=*/"", /*useTemporary=*/true, + /*Extension=*/"", /*UseTemporary=*/true, /*CreateMissingDirectories=*/true); } bool GenerateModuleInterfaceAction::BeginSourceFileAction( CompilerInstance &CI) { - if (!CI.getLangOpts().ModulesTS) { - CI.getDiagnostics().Report(diag::err_module_interface_requires_modules_ts); + if (!CI.getLangOpts().ModulesTS && !CI.getLangOpts().CPlusPlusModules) { + CI.getDiagnostics().Report(diag::err_module_interface_requires_cpp_modules); return false; } @@ -238,7 +239,7 @@ GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI, bool GenerateHeaderModuleAction::PrepareToExecuteAction( CompilerInstance &CI) { - if (!CI.getLangOpts().Modules && !CI.getLangOpts().ModulesTS) { + if (!CI.getLangOpts().Modules) { CI.getDiagnostics().Report(diag::err_header_module_requires_modules); return false; } @@ -287,7 +288,7 @@ bool GenerateHeaderModuleAction::BeginSourceFileAction( const DirectoryLookup *CurDir = nullptr; const FileEntry *FE = HS.LookupFile( Name, SourceLocation(), /*Angled*/ false, nullptr, CurDir, - None, nullptr, nullptr, nullptr, nullptr, nullptr); + None, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); if (!FE) { CI.getDiagnostics().Report(diag::err_module_header_file_not_found) << Name; @@ -330,8 +331,8 @@ void VerifyPCHAction::ExecuteAction() { bool Preamble = CI.getPreprocessorOpts().PrecompiledPreambleBytes.first != 0; const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot; std::unique_ptr<ASTReader> Reader(new ASTReader( - CI.getPreprocessor(), &CI.getASTContext(), CI.getPCHContainerReader(), - CI.getFrontendOpts().ModuleFileExtensions, + CI.getPreprocessor(), CI.getModuleCache(), &CI.getASTContext(), + CI.getPCHContainerReader(), CI.getFrontendOpts().ModuleFileExtensions, Sysroot.empty() ? "" : Sysroot.c_str(), /*DisableValidation*/ false, /*AllowPCHWithCompilerErrors*/ false, @@ -908,3 +909,33 @@ void DumpCompilerOptionsAction::ExecuteAction() { OS << "}"; } + +void PrintDependencyDirectivesSourceMinimizerAction::ExecuteAction() { + CompilerInstance &CI = getCompilerInstance(); + SourceManager &SM = CI.getPreprocessor().getSourceManager(); + const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID()); + + llvm::SmallString<1024> Output; + llvm::SmallVector<minimize_source_to_dependency_directives::Token, 32> Toks; + if (minimizeSourceToDependencyDirectives( + FromFile->getBuffer(), Output, Toks, &CI.getDiagnostics(), + SM.getLocForStartOfFile(SM.getMainFileID()))) { + assert(CI.getDiagnostics().hasErrorOccurred() && + "no errors reported for failure"); + + // Preprocess the source when verifying the diagnostics to capture the + // 'expected' comments. + if (CI.getDiagnosticOpts().VerifyDiagnostics) { + // Make sure we don't emit new diagnostics! + CI.getDiagnostics().setSuppressAllDiagnostics(); + Preprocessor &PP = getCompilerInstance().getPreprocessor(); + PP.EnterMainSourceFile(); + Token Tok; + do { + PP.Lex(Tok); + } while (Tok.isNot(tok::eof)); + } + return; + } + llvm::outs() << Output; +} diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp index 0744d447e816..6ccb2c395604 100644 --- a/lib/Frontend/FrontendOptions.cpp +++ b/lib/Frontend/FrontendOptions.cpp @@ -1,9 +1,8 @@ //===- FrontendOptions.cpp ------------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Frontend/FrontendTiming.cpp b/lib/Frontend/FrontendTiming.cpp index 9ea7347e7797..e3f44c9999f6 100644 --- a/lib/Frontend/FrontendTiming.cpp +++ b/lib/Frontend/FrontendTiming.cpp @@ -1,9 +1,8 @@ -//===- FronendTiming.cpp - Implements Frontend timing utils --------------===// +//===- FrontendTiming.cpp - Implements Frontend timing utils -------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Frontend/HeaderIncludeGen.cpp b/lib/Frontend/HeaderIncludeGen.cpp index 9dc107c9d546..d60f5333bf5b 100644 --- a/lib/Frontend/HeaderIncludeGen.cpp +++ b/lib/Frontend/HeaderIncludeGen.cpp @@ -1,9 +1,8 @@ -//===--- HeaderIncludes.cpp - Generate Header Includes --------------------===// +//===-- HeaderIncludeGen.cpp - Generate Header Includes -------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index ac3bb713ddcc..d65d13489dc4 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -1,9 +1,8 @@ //===--- InitHeaderSearch.cpp - Initialize header search paths ------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -211,6 +210,10 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, const HeaderSearchOptions &HSOpts) { llvm::Triple::OSType os = triple.getOS(); + if (triple.isOSDarwin()) { + llvm_unreachable("Include management is handled in the driver."); + } + if (HSOpts.UseStandardSystemIncludes) { switch (os) { case llvm::Triple::CloudABI: @@ -366,49 +369,7 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths( // FIXME: temporary hack: hard-coded paths. if (triple.isOSDarwin()) { - bool IsBaseFound = true; - switch (triple.getArch()) { - default: break; - - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - IsBaseFound = AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", - "powerpc-apple-darwin10", "", - "ppc64", triple); - IsBaseFound |= AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0", - "powerpc-apple-darwin10", "", - "ppc64", triple); - break; - - case llvm::Triple::x86: - case llvm::Triple::x86_64: - IsBaseFound = AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", - "i686-apple-darwin10", "", - "x86_64", triple); - IsBaseFound |= AddGnuCPlusPlusIncludePaths( - "/usr/include/c++/4.0.0", "i686-apple-darwin8", "", "", triple); - break; - - case llvm::Triple::arm: - case llvm::Triple::thumb: - IsBaseFound = AddGnuCPlusPlusIncludePaths( - "/usr/include/c++/4.2.1", "arm-apple-darwin10", "v7", "", triple); - IsBaseFound |= AddGnuCPlusPlusIncludePaths( - "/usr/include/c++/4.2.1", "arm-apple-darwin10", "v6", "", triple); - break; - - case llvm::Triple::aarch64: - IsBaseFound = AddGnuCPlusPlusIncludePaths( - "/usr/include/c++/4.2.1", "arm64-apple-darwin10", "", "", triple); - break; - } - // Warn when compiling pure C++ / Objective-C++ only. - if (!IsBaseFound && - !(LangOpts.CUDA || LangOpts.OpenCL || LangOpts.RenderScript)) { - Headers.getDiags().Report(SourceLocation(), - diag::warn_stdlibcxx_not_found); - } - return; + llvm_unreachable("Include management is handled in the driver."); } switch (os) { @@ -433,14 +394,6 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths( case llvm::Triple::DragonFly: AddPath("/usr/include/c++/5.0", CXXSystem, false); break; - case llvm::Triple::OpenBSD: { - std::string t = triple.getTriple(); - if (t.substr(0, 6) == "x86_64") - t.replace(0, 6, "amd64"); - AddGnuCPlusPlusIncludePaths("/usr/include/g++", - t, "", "", triple); - break; - } case llvm::Triple::Minix: AddGnuCPlusPlusIncludePaths("/usr/gnu/include/c++/4.4.3", "", "", "", triple); @@ -461,9 +414,11 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang, default: break; // Everything else continues to use this routine's logic. + case llvm::Triple::Emscripten: case llvm::Triple::Linux: case llvm::Triple::Hurd: case llvm::Triple::Solaris: + case llvm::Triple::WASI: return; case llvm::Triple::Win32: @@ -471,6 +426,22 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang, triple.isOSBinFormatMachO()) return; break; + + case llvm::Triple::UnknownOS: + if (triple.getArch() == llvm::Triple::wasm32 || + triple.getArch() == llvm::Triple::wasm64) + return; + break; + } + + // All header search logic is handled in the Driver for Darwin. + if (triple.isOSDarwin()) { + if (HSOpts.UseStandardSystemIncludes) { + // Add the default framework include paths on Darwin. + AddPath("/System/Library/Frameworks", System, true); + AddPath("/Library/Frameworks", System, true); + } + return; } if (Lang.CPlusPlus && !Lang.AsmPreprocessor && @@ -483,14 +454,6 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang, } AddDefaultCIncludePaths(triple, HSOpts); - - // Add the default framework include paths on Darwin. - if (HSOpts.UseStandardSystemIncludes) { - if (triple.isOSDarwin()) { - AddPath("/System/Library/Frameworks", System, true); - AddPath("/Library/Frameworks", System, true); - } - } } /// RemoveDuplicates - If there are duplicate directory entries in the specified diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index 66807b097d40..3906e2ae1b98 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -1,9 +1,8 @@ //===--- InitPreprocessor.cpp - PP initialization code. ---------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -123,10 +122,10 @@ static void DefineFloatMacros(MacroBuilder &Builder, StringRef Prefix, "4.94065645841246544176568792868221e-324", "1.92592994438723585305597794258492732e-34"); int MantissaDigits = PickFP(Sem, 11, 24, 53, 64, 106, 113); - int Min10Exp = PickFP(Sem, -13, -37, -307, -4931, -291, -4931); + int Min10Exp = PickFP(Sem, -4, -37, -307, -4931, -291, -4931); int Max10Exp = PickFP(Sem, 4, 38, 308, 4932, 308, 4932); - int MinExp = PickFP(Sem, -14, -125, -1021, -16381, -968, -16381); - int MaxExp = PickFP(Sem, 15, 128, 1024, 16384, 1024, 16384); + int MinExp = PickFP(Sem, -13, -125, -1021, -16381, -968, -16381); + int MaxExp = PickFP(Sem, 16, 128, 1024, 16384, 1024, 16384); Min = PickFP(Sem, "6.103515625e-5", "1.17549435e-38", "2.2250738585072014e-308", "3.36210314311209350626e-4932", "2.00416836000897277799610805135016e-292", @@ -412,7 +411,7 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, if (LangOpts.OpenCLCPlusPlusVersion == 100) Builder.defineMacro("__OPENCL_CPP_VERSION__", "100"); else - llvm_unreachable("Unsupported OpenCL C++ version"); + llvm_unreachable("Unsupported C++ version for OpenCL"); Builder.defineMacro("__CL_CPP_VERSION_1_0__", "100"); } else { // OpenCL v1.0 and v1.1 do not have a predefined macro to indicate the @@ -541,6 +540,8 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts, Builder.defineMacro("__cpp_template_template_args", "201611L"); // C++20 features. + if (LangOpts.CPlusPlus2a) + Builder.defineMacro("__cpp_conditional_explicit", "201806L"); if (LangOpts.Char8) Builder.defineMacro("__cpp_char8_t", "201811L"); Builder.defineMacro("__cpp_impl_destroying_delete", "201806L"); @@ -548,7 +549,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts, // TS features. if (LangOpts.ConceptsTS) Builder.defineMacro("__cpp_experimental_concepts", "1L"); - if (LangOpts.CoroutinesTS) + if (LangOpts.Coroutines) Builder.defineMacro("__cpp_coroutines", "201703L"); } @@ -603,10 +604,9 @@ static void InitializePredefinedMacros(const TargetInfo &TI, // Support for #pragma redefine_extname (Sun compatibility) Builder.defineMacro("__PRAGMA_REDEFINE_EXTNAME", "1"); - // As sad as it is, enough software depends on the __VERSION__ for version - // checks that it is necessary to report 4.2.1 (the base GCC version we claim - // compatibility with) first. - Builder.defineMacro("__VERSION__", "\"4.2.1 Compatible " + + // Previously this macro was set to a string aiming to achieve compatibility + // with GCC 4.2.1. Now, just return the full Clang version + Builder.defineMacro("__VERSION__", "\"" + Twine(getClangFullCPPVersion()) + "\""); // Initialize language-specific preprocessor defines. @@ -831,7 +831,8 @@ static void InitializePredefinedMacros(const TargetInfo &TI, DefineFmt("__UINTPTR", TI.getUIntPtrType(), TI, Builder); DefineTypeWidth("__UINTPTR_WIDTH__", TI.getUIntPtrType(), TI, Builder); - DefineFloatMacros(Builder, "FLT16", &TI.getHalfFormat(), "F16"); + if (TI.hasFloat16Type()) + DefineFloatMacros(Builder, "FLT16", &TI.getHalfFormat(), "F16"); DefineFloatMacros(Builder, "FLT", &TI.getFloatFormat(), "F"); DefineFloatMacros(Builder, "DBL", &TI.getDoubleFormat(), ""); DefineFloatMacros(Builder, "LDBL", &TI.getLongDoubleFormat(), "L"); @@ -1057,16 +1058,20 @@ static void InitializePredefinedMacros(const TargetInfo &TI, Builder.defineMacro("__CLANG_CUDA_APPROX_TRANSCENDENTALS__"); } + // Define a macro indicating that the source file is being compiled with a + // SYCL device compiler which doesn't produce host binary. + if (LangOpts.SYCLIsDevice) { + Builder.defineMacro("__SYCL_DEVICE_ONLY__", "1"); + } + // OpenCL definitions. if (LangOpts.OpenCL) { -#define OPENCLEXT(Ext) \ - if (TI.getSupportedOpenCLOpts().isSupported(#Ext, \ - LangOpts.OpenCLVersion)) \ - Builder.defineMacro(#Ext); +#define OPENCLEXT(Ext) \ + if (TI.getSupportedOpenCLOpts().isSupported(#Ext, LangOpts)) \ + Builder.defineMacro(#Ext); #include "clang/Basic/OpenCLExtensions.def" - auto Arch = TI.getTriple().getArch(); - if (Arch == llvm::Triple::spir || Arch == llvm::Triple::spir64) + if (TI.getTriple().isSPIR()) Builder.defineMacro("__IMAGE_SUPPORT__"); } diff --git a/lib/Frontend/InterfaceStubFunctionsConsumer.cpp b/lib/Frontend/InterfaceStubFunctionsConsumer.cpp new file mode 100644 index 000000000000..fbba9ae4d6a7 --- /dev/null +++ b/lib/Frontend/InterfaceStubFunctionsConsumer.cpp @@ -0,0 +1,378 @@ +//===--- InterfaceStubFunctionsConsumer.cpp -------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/Mangle.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/Sema/TemplateInstCallback.h" +#include "llvm/BinaryFormat/ELF.h" + +using namespace clang; + +class InterfaceStubFunctionsConsumer : public ASTConsumer { + CompilerInstance &Instance; + StringRef InFile; + StringRef Format; + std::set<std::string> ParsedTemplates; + + enum RootDeclOrigin { TopLevel = 0, FromTU = 1, IsLate = 2 }; + struct MangledSymbol { + std::string ParentName; + uint8_t Type; + uint8_t Binding; + std::vector<std::string> Names; + MangledSymbol() = delete; + + MangledSymbol(const std::string &ParentName, uint8_t Type, uint8_t Binding, + std::vector<std::string> Names) + : ParentName(ParentName), Type(Type), Binding(Binding), Names(Names) {} + }; + using MangledSymbols = std::map<const NamedDecl *, MangledSymbol>; + + bool WriteNamedDecl(const NamedDecl *ND, MangledSymbols &Symbols, int RDO) { + // Here we filter out anything that's not set to DefaultVisibility. + // DefaultVisibility is set on a decl when -fvisibility is not specified on + // the command line (or specified as default) and the decl does not have + // __attribute__((visibility("hidden"))) set or when the command line + // argument is set to hidden but the decl explicitly has + // __attribute__((visibility ("default"))) set. We do this so that the user + // can have fine grain control of what they want to expose in the stub. + auto isVisible = [](const NamedDecl *ND) -> bool { + return ND->getVisibility() == DefaultVisibility; + }; + + auto ignoreDecl = [this, isVisible](const NamedDecl *ND) -> bool { + if (!isVisible(ND)) + return true; + + if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) + if ((VD->getStorageClass() == StorageClass::SC_Extern) || + (VD->getStorageClass() == StorageClass::SC_Static && + VD->getParentFunctionOrMethod() == nullptr)) + return true; + + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { + if (FD->isInlined() && !isa<CXXMethodDecl>(FD) && + !Instance.getLangOpts().GNUInline) + return true; + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { + if (const auto *RC = dyn_cast<CXXRecordDecl>(MD->getParent())) + if (isa<ClassTemplateDecl>(RC->getParent()) || !isVisible(RC)) + return true; + if (MD->isDependentContext() || !MD->hasBody()) + return true; + } + if (FD->getStorageClass() == StorageClass::SC_Static) + return true; + } + return false; + }; + + auto getParentFunctionDecl = [](const NamedDecl *ND) -> const NamedDecl * { + if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) + if (const auto *FD = + dyn_cast_or_null<FunctionDecl>(VD->getParentFunctionOrMethod())) + return FD; + return nullptr; + }; + + auto getMangledNames = [](const NamedDecl *ND) -> std::vector<std::string> { + if (!ND) + return {""}; + ASTNameGenerator NameGen(ND->getASTContext()); + std::vector<std::string> MangledNames = NameGen.getAllManglings(ND); + if (isa<CXXConstructorDecl>(ND) || isa<CXXDestructorDecl>(ND)) + return MangledNames; +#ifdef EXPENSIVE_CHECKS + assert(MangledNames.size() <= 1 && "Expected only one name mangling."); +#endif + return {NameGen.getName(ND)}; + }; + + if (!(RDO & FromTU)) + return true; + if (Symbols.find(ND) != Symbols.end()) + return true; + // - Currently have not figured out how to produce the names for FieldDecls. + // - Do not want to produce symbols for function paremeters. + if (isa<FieldDecl>(ND) || isa<ParmVarDecl>(ND)) + return true; + + const NamedDecl *ParentDecl = getParentFunctionDecl(ND); + if ((ParentDecl && ignoreDecl(ParentDecl)) || ignoreDecl(ND)) + return true; + + if (RDO & IsLate) { + Instance.getDiagnostics().Report(diag::err_asm_invalid_type_in_input) + << "Generating Interface Stubs is not supported with " + "delayed template parsing."; + } else { + if (const auto *FD = dyn_cast<FunctionDecl>(ND)) + if (FD->isDependentContext()) + return true; + + const bool IsWeak = (ND->hasAttr<WeakAttr>() || + ND->hasAttr<WeakRefAttr>() || ND->isWeakImported()); + + Symbols.insert(std::make_pair( + ND, + MangledSymbol(getMangledNames(ParentDecl).front(), + // Type: + isa<VarDecl>(ND) ? llvm::ELF::STT_OBJECT + : llvm::ELF::STT_FUNC, + // Binding: + IsWeak ? llvm::ELF::STB_WEAK : llvm::ELF::STB_GLOBAL, + getMangledNames(ND)))); + } + return true; + } + + void + HandleDecls(const llvm::iterator_range<DeclContext::decl_iterator> &Decls, + MangledSymbols &Symbols, int RDO) { + for (const auto *D : Decls) + HandleNamedDecl(dyn_cast<NamedDecl>(D), Symbols, RDO); + } + + void HandleTemplateSpecializations(const FunctionTemplateDecl &FTD, + MangledSymbols &Symbols, int RDO) { + for (const auto *D : FTD.specializations()) + HandleNamedDecl(dyn_cast<NamedDecl>(D), Symbols, RDO); + } + + void HandleTemplateSpecializations(const ClassTemplateDecl &CTD, + MangledSymbols &Symbols, int RDO) { + for (const auto *D : CTD.specializations()) + HandleNamedDecl(dyn_cast<NamedDecl>(D), Symbols, RDO); + } + + bool HandleNamedDecl(const NamedDecl *ND, MangledSymbols &Symbols, int RDO) { + if (!ND) + return false; + + switch (ND->getKind()) { + default: + break; + case Decl::Kind::Namespace: + HandleDecls(cast<NamespaceDecl>(ND)->decls(), Symbols, RDO); + return true; + case Decl::Kind::CXXRecord: + HandleDecls(cast<CXXRecordDecl>(ND)->decls(), Symbols, RDO); + return true; + case Decl::Kind::ClassTemplateSpecialization: + HandleDecls(cast<ClassTemplateSpecializationDecl>(ND)->decls(), Symbols, + RDO); + return true; + case Decl::Kind::ClassTemplate: + HandleTemplateSpecializations(*cast<ClassTemplateDecl>(ND), Symbols, RDO); + return true; + case Decl::Kind::FunctionTemplate: + HandleTemplateSpecializations(*cast<FunctionTemplateDecl>(ND), Symbols, + RDO); + return true; + case Decl::Kind::TemplateTypeParm: + return true; + case Decl::Kind::Var: + case Decl::Kind::ParmVar: + case Decl::Kind::CXXMethod: + case Decl::Kind::CXXConstructor: + case Decl::Kind::CXXDestructor: + case Decl::Kind::Function: + case Decl::Kind::Field: + if (WriteNamedDecl(ND, Symbols, RDO)) + return true; + } + + // While interface stubs are in the development stage, it's probably best to + // catch anything that's not a VarDecl or Template/FunctionDecl. + Instance.getDiagnostics().Report(diag::err_asm_invalid_type_in_input) + << "Expected a function or function template decl."; + return false; + } + +public: + InterfaceStubFunctionsConsumer(CompilerInstance &Instance, StringRef InFile, + StringRef Format) + : Instance(Instance), InFile(InFile), Format(Format) {} + + void HandleTranslationUnit(ASTContext &context) override { + struct Visitor : public RecursiveASTVisitor<Visitor> { + bool VisitNamedDecl(NamedDecl *ND) { + if (const auto *FD = dyn_cast<FunctionDecl>(ND)) + if (FD->isLateTemplateParsed()) { + LateParsedDecls.insert(FD); + return true; + } + + if (const auto *VD = dyn_cast<ValueDecl>(ND)) { + ValueDecls.insert(VD); + return true; + } + + NamedDecls.insert(ND); + return true; + } + + std::set<const NamedDecl *> LateParsedDecls; + std::set<NamedDecl *> NamedDecls; + std::set<const ValueDecl *> ValueDecls; + } v; + + v.TraverseDecl(context.getTranslationUnitDecl()); + + MangledSymbols Symbols; + auto OS = Instance.createDefaultOutputFile(/*Binary=*/false, InFile, "ifs"); + if (!OS) + return; + + if (Instance.getLangOpts().DelayedTemplateParsing) { + clang::Sema &S = Instance.getSema(); + for (const auto *FD : v.LateParsedDecls) { + clang::LateParsedTemplate &LPT = + *S.LateParsedTemplateMap.find(cast<FunctionDecl>(FD))->second; + S.LateTemplateParser(S.OpaqueParser, LPT); + HandleNamedDecl(FD, Symbols, (FromTU | IsLate)); + } + } + + for (const NamedDecl *ND : v.ValueDecls) + HandleNamedDecl(ND, Symbols, FromTU); + for (const NamedDecl *ND : v.NamedDecls) + HandleNamedDecl(ND, Symbols, FromTU); + + auto writeIfoYaml = [this](const llvm::Triple &T, + const MangledSymbols &Symbols, + const ASTContext &context, StringRef Format, + raw_ostream &OS) -> void { + OS << "--- !" << Format << "\n"; + OS << "FileHeader:\n"; + OS << " Class: ELFCLASS"; + OS << (T.isArch64Bit() ? "64" : "32"); + OS << "\n"; + OS << " Data: ELFDATA2"; + OS << (T.isLittleEndian() ? "LSB" : "MSB"); + OS << "\n"; + OS << " Type: ET_REL\n"; + OS << " Machine: " + << llvm::StringSwitch<llvm::StringRef>(T.getArchName()) + .Case("x86_64", "EM_X86_64") + .Case("i386", "EM_386") + .Case("i686", "EM_386") + .Case("aarch64", "EM_AARCH64") + .Case("amdgcn", "EM_AMDGPU") + .Case("r600", "EM_AMDGPU") + .Case("arm", "EM_ARM") + .Case("thumb", "EM_ARM") + .Case("avr", "EM_AVR") + .Case("mips", "EM_MIPS") + .Case("mipsel", "EM_MIPS") + .Case("mips64", "EM_MIPS") + .Case("mips64el", "EM_MIPS") + .Case("msp430", "EM_MSP430") + .Case("ppc", "EM_PPC") + .Case("ppc64", "EM_PPC64") + .Case("ppc64le", "EM_PPC64") + .Case("x86", T.isOSIAMCU() ? "EM_IAMCU" : "EM_386") + .Case("x86_64", "EM_X86_64") + .Default("EM_NONE") + << "\nSymbols:\n"; + for (const auto &E : Symbols) { + const MangledSymbol &Symbol = E.second; + for (auto Name : Symbol.Names) { + OS << " - Name: " + << (Symbol.ParentName.empty() || Instance.getLangOpts().CPlusPlus + ? "" + : (Symbol.ParentName + ".")) + << Name << "\n" + << " Type: STT_"; + switch (Symbol.Type) { + default: + case llvm::ELF::STT_NOTYPE: + OS << "NOTYPE"; + break; + case llvm::ELF::STT_OBJECT: + OS << "OBJECT"; + break; + case llvm::ELF::STT_FUNC: + OS << "FUNC"; + break; + } + OS << "\n Binding: STB_" + << ((Symbol.Binding == llvm::ELF::STB_WEAK) ? "WEAK" : "GLOBAL") + << "\n"; + } + } + OS << "...\n"; + OS.flush(); + }; + + auto writeIfoElfAbiYaml = + [this](const llvm::Triple &T, const MangledSymbols &Symbols, + const ASTContext &context, StringRef Format, + raw_ostream &OS) -> void { + OS << "--- !" << Format << "\n"; + OS << "TbeVersion: 1.0\n"; + OS << "Arch: " << T.getArchName() << "\n"; + OS << "Symbols:\n"; + for (const auto &E : Symbols) { + const MangledSymbol &Symbol = E.second; + for (auto Name : Symbol.Names) { + OS << " " + << (Symbol.ParentName.empty() || Instance.getLangOpts().CPlusPlus + ? "" + : (Symbol.ParentName + ".")) + << Name << ": { Type: "; + switch (Symbol.Type) { + default: + llvm_unreachable( + "clang -emit-iterface-stubs: Unexpected symbol type."); + case llvm::ELF::STT_NOTYPE: + OS << "NoType"; + break; + case llvm::ELF::STT_OBJECT: { + auto VD = cast<ValueDecl>(E.first)->getType(); + OS << "Object, Size: " + << context.getTypeSizeInChars(VD).getQuantity(); + break; + } + case llvm::ELF::STT_FUNC: + OS << "Func"; + break; + } + if (Symbol.Binding == llvm::ELF::STB_WEAK) + OS << ", Weak: true"; + OS << " }\n"; + } + } + OS << "...\n"; + OS.flush(); + }; + + if (Format == "experimental-yaml-elf-v1") + writeIfoYaml(Instance.getTarget().getTriple(), Symbols, context, Format, + *OS); + else + writeIfoElfAbiYaml(Instance.getTarget().getTriple(), Symbols, context, + Format, *OS); + } +}; + +std::unique_ptr<ASTConsumer> +GenerateInterfaceYAMLExpV1Action::CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) { + return llvm::make_unique<InterfaceStubFunctionsConsumer>( + CI, InFile, "experimental-yaml-elf-v1"); +} + +std::unique_ptr<ASTConsumer> +GenerateInterfaceTBEExpV1Action::CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) { + return llvm::make_unique<InterfaceStubFunctionsConsumer>( + CI, InFile, "experimental-tapi-elf-v1"); +} diff --git a/lib/Frontend/LangStandards.cpp b/lib/Frontend/LangStandards.cpp index 47023e58fa0b..05087eb41f01 100644 --- a/lib/Frontend/LangStandards.cpp +++ b/lib/Frontend/LangStandards.cpp @@ -1,9 +1,8 @@ //===--- LangStandards.cpp - Language Standard Definitions ----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Frontend/LayoutOverrideSource.cpp b/lib/Frontend/LayoutOverrideSource.cpp index b31fbd087ba7..76762d58fe25 100644 --- a/lib/Frontend/LayoutOverrideSource.cpp +++ b/lib/Frontend/LayoutOverrideSource.cpp @@ -1,9 +1,8 @@ //===--- LayoutOverrideSource.cpp --Override Record Layouts ---------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "clang/Frontend/LayoutOverrideSource.h" diff --git a/lib/Frontend/LogDiagnosticPrinter.cpp b/lib/Frontend/LogDiagnosticPrinter.cpp index 9998f65457cf..4bac17553999 100644 --- a/lib/Frontend/LogDiagnosticPrinter.cpp +++ b/lib/Frontend/LogDiagnosticPrinter.cpp @@ -1,9 +1,8 @@ //===--- LogDiagnosticPrinter.cpp - Log Diagnostic Printer ----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/lib/Frontend/ModuleDependencyCollector.cpp b/lib/Frontend/ModuleDependencyCollector.cpp index fa8efcc3b53c..c1d8c0d9eb24 100644 --- a/lib/Frontend/ModuleDependencyCollector.cpp +++ b/lib/Frontend/ModuleDependencyCollector.cpp @@ -1,9 +1,8 @@ //===--- ModuleDependencyCollector.cpp - Collect module dependencies ------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -99,24 +98,6 @@ struct ModuleDependencyMMCallbacks : public ModuleMapCallbacks { } -// TODO: move this to Support/Path.h and check for HAVE_REALPATH? -static bool real_path(StringRef SrcPath, SmallVectorImpl<char> &RealPath) { -#ifdef LLVM_ON_UNIX - char CanonicalPath[PATH_MAX]; - - // TODO: emit a warning in case this fails...? - if (!realpath(SrcPath.str().c_str(), CanonicalPath)) - return false; - - SmallString<256> RPath(CanonicalPath); - RealPath.swap(RPath); - return true; -#else - // FIXME: Add support for systems without realpath. - return false; -#endif -} - void ModuleDependencyCollector::attachToASTReader(ASTReader &R) { R.addListener(llvm::make_unique<ModuleDependencyListener>(*this)); } @@ -131,7 +112,7 @@ void ModuleDependencyCollector::attachToPreprocessor(Preprocessor &PP) { static bool isCaseSensitivePath(StringRef Path) { SmallString<256> TmpDest = Path, UpperDest, RealDest; // Remove component traversals, links, etc. - if (!real_path(Path, TmpDest)) + if (llvm::sys::fs::real_path(Path, TmpDest)) return true; // Current default value in vfs.yaml Path = TmpDest; @@ -141,7 +122,7 @@ static bool isCaseSensitivePath(StringRef Path) { // already expects when sensitivity isn't setup. for (auto &C : Path) UpperDest.push_back(toUppercase(C)); - if (real_path(UpperDest, RealDest) && Path.equals(RealDest)) + if (!llvm::sys::fs::real_path(UpperDest, RealDest) && Path.equals(RealDest)) return false; return true; } @@ -187,7 +168,7 @@ bool ModuleDependencyCollector::getRealPath(StringRef SrcPath, // Computing the real path is expensive, cache the search through the // parent path directory. if (DirWithSymLink == SymLinkMap.end()) { - if (!real_path(Dir, RealPath)) + if (llvm::sys::fs::real_path(Dir, RealPath)) return false; SymLinkMap[Dir] = RealPath.str(); } else { diff --git a/lib/Frontend/MultiplexConsumer.cpp b/lib/Frontend/MultiplexConsumer.cpp index c6e18d9cae21..ed7028769d34 100644 --- a/lib/Frontend/MultiplexConsumer.cpp +++ b/lib/Frontend/MultiplexConsumer.cpp @@ -1,9 +1,8 @@ //===- MultiplexConsumer.cpp - AST Consumer for PCH Generation --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -104,6 +103,7 @@ public: const ObjCInterfaceDecl *IFD) override; void DeclarationMarkedUsed(const Decl *D) override; void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override; + void DeclarationMarkedOpenMPAllocate(const Decl *D, const Attr *A) override; void DeclarationMarkedOpenMPDeclareTarget(const Decl *D, const Attr *Attr) override; void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) override; @@ -209,6 +209,11 @@ void MultiplexASTMutationListener::DeclarationMarkedOpenMPThreadPrivate( for (size_t i = 0, e = Listeners.size(); i != e; ++i) Listeners[i]->DeclarationMarkedOpenMPThreadPrivate(D); } +void MultiplexASTMutationListener::DeclarationMarkedOpenMPAllocate( + const Decl *D, const Attr *A) { + for (ASTMutationListener *L : Listeners) + L->DeclarationMarkedOpenMPAllocate(D, A); +} void MultiplexASTMutationListener::DeclarationMarkedOpenMPDeclareTarget( const Decl *D, const Attr *Attr) { for (auto *L : Listeners) diff --git a/lib/Frontend/PrecompiledPreamble.cpp b/lib/Frontend/PrecompiledPreamble.cpp index 1930af187e7a..276a9676eaa9 100644 --- a/lib/Frontend/PrecompiledPreamble.cpp +++ b/lib/Frontend/PrecompiledPreamble.cpp @@ -1,9 +1,8 @@ //===--- PrecompiledPreamble.cpp - Build precompiled preambles --*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -19,6 +18,7 @@ #include "clang/Frontend/FrontendActions.h" #include "clang/Frontend/FrontendOptions.h" #include "clang/Lex/Lexer.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Lex/PreprocessorOptions.h" #include "clang/Serialization/ASTWriter.h" #include "llvm/ADT/StringExtras.h" @@ -157,9 +157,12 @@ private: class PrecompilePreambleConsumer : public PCHGenerator { public: PrecompilePreambleConsumer(PrecompilePreambleAction &Action, - const Preprocessor &PP, StringRef isysroot, + const Preprocessor &PP, + InMemoryModuleCache &ModuleCache, + StringRef isysroot, std::unique_ptr<raw_ostream> Out) - : PCHGenerator(PP, "", isysroot, std::make_shared<PCHBuffer>(), + : PCHGenerator(PP, ModuleCache, "", isysroot, + std::make_shared<PCHBuffer>(), ArrayRef<std::shared_ptr<ModuleFileExtension>>(), /*AllowASTWithErrors=*/true), Action(Action), Out(std::move(Out)) {} @@ -211,7 +214,7 @@ PrecompilePreambleAction::CreateASTConsumer(CompilerInstance &CI, Sysroot.clear(); return llvm::make_unique<PrecompilePreambleConsumer>( - *this, CI.getPreprocessor(), Sysroot, std::move(OS)); + *this, CI.getPreprocessor(), CI.getModuleCache(), Sysroot, std::move(OS)); } template <class T> bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) { @@ -296,14 +299,13 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build( // created. This complexity should be lifted elsewhere. Clang->getTarget().adjust(Clang->getLangOpts()); - assert(Clang->getFrontendOpts().Inputs.size() == 1 && - "Invocation must have exactly one source file!"); - assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == - InputKind::Source && - "FIXME: AST inputs not yet supported here!"); - assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() != - InputKind::LLVM_IR && - "IR inputs not support here!"); + if (Clang->getFrontendOpts().Inputs.size() != 1 || + Clang->getFrontendOpts().Inputs[0].getKind().getFormat() != + InputKind::Source || + Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() == + InputKind::LLVM_IR) { + return BuildPreambleError::BadInputs; + } // Clear out old caches and data. Diagnostics.Reset(); @@ -347,8 +349,11 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build( Callbacks.createPPCallbacks(); if (DelegatedPPCallbacks) Clang->getPreprocessor().addPPCallbacks(std::move(DelegatedPPCallbacks)); + if (auto CommentHandler = Callbacks.getCommentHandler()) + Clang->getPreprocessor().addCommentHandler(CommentHandler); - Act->Execute(); + if (llvm::Error Err = Act->Execute()) + return errorToErrorCode(std::move(Err)); // Run the callbacks. Callbacks.AfterExecute(*Clang); @@ -372,7 +377,7 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build( PrecompiledPreamble::PreambleFileHash::createForFile(File->getSize(), ModTime); } else { - llvm::MemoryBuffer *Buffer = SourceMgr.getMemoryBufferForFile(File); + const llvm::MemoryBuffer *Buffer = SourceMgr.getMemoryBufferForFile(File); FilesInPreamble[File->getName()] = PrecompiledPreamble::PreambleFileHash::createForMemoryBuffer(Buffer); } @@ -449,20 +454,33 @@ bool PrecompiledPreamble::CanReuse(const CompilerInvocation &Invocation, Status.getSize(), llvm::sys::toTimeT(Status.getLastModificationTime())); } + // OverridenFileBuffers tracks only the files not found in VFS. + llvm::StringMap<PreambleFileHash> OverridenFileBuffers; for (const auto &RB : PreprocessorOpts.RemappedFileBuffers) { - llvm::vfs::Status Status; - if (!moveOnNoError(VFS->status(RB.first), Status)) - return false; - - OverriddenFiles[Status.getUniqueID()] = + const PrecompiledPreamble::PreambleFileHash PreambleHash = PreambleFileHash::createForMemoryBuffer(RB.second); + llvm::vfs::Status Status; + if (moveOnNoError(VFS->status(RB.first), Status)) + OverriddenFiles[Status.getUniqueID()] = PreambleHash; + else + OverridenFileBuffers[RB.first] = PreambleHash; } // Check whether anything has changed. for (const auto &F : FilesInPreamble) { + auto OverridenFileBuffer = OverridenFileBuffers.find(F.first()); + if (OverridenFileBuffer != OverridenFileBuffers.end()) { + // The file's buffer was remapped and the file was not found in VFS. + // Check whether it matches up with the previous mapping. + if (OverridenFileBuffer->second != F.second) + return false; + continue; + } + llvm::vfs::Status Status; if (!moveOnNoError(VFS->status(F.first()), Status)) { - // If we can't stat the file, assume that something horrible happened. + // If the file's buffer is not remapped and we can't stat it, + // assume that something horrible happened. return false; } @@ -476,7 +494,8 @@ bool PrecompiledPreamble::CanReuse(const CompilerInvocation &Invocation, continue; } - // The file was not remapped; check whether it has changed on disk. + // Neither the file's buffer nor the file itself was remapped; + // check whether it has changed on disk. if (Status.getSize() != uint64_t(F.second.Size) || llvm::sys::toTimeT(Status.getLastModificationTime()) != F.second.ModTime) @@ -743,6 +762,7 @@ void PreambleCallbacks::HandleTopLevelDecl(DeclGroupRef DG) {} std::unique_ptr<PPCallbacks> PreambleCallbacks::createPPCallbacks() { return nullptr; } +CommentHandler *PreambleCallbacks::getCommentHandler() { return nullptr; } static llvm::ManagedStatic<BuildPreambleErrorCategory> BuildPreambleErrCategory; @@ -764,6 +784,8 @@ std::string BuildPreambleErrorCategory::message(int condition) const { return "BeginSourceFile() return an error"; case BuildPreambleError::CouldntEmitPCH: return "Could not emit PCH"; + case BuildPreambleError::BadInputs: + return "Command line arguments must contain exactly one source file"; } llvm_unreachable("unexpected BuildPreambleError"); } diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index 3b835985a54c..732edacffbe3 100644 --- a/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/lib/Frontend/PrintPreprocessedOutput.cpp @@ -1,9 +1,8 @@ //===--- PrintPreprocessedOutput.cpp - Implement the -E mode --------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -144,6 +143,8 @@ public: ArrayRef<int> Ids) override; void PragmaWarningPush(SourceLocation Loc, int Level) override; void PragmaWarningPop(SourceLocation Loc) override; + void PragmaExecCharsetPush(SourceLocation Loc, StringRef Str) override; + void PragmaExecCharsetPop(SourceLocation Loc) override; void PragmaAssumeNonNullBegin(SourceLocation Loc) override; void PragmaAssumeNonNullEnd(SourceLocation Loc) override; @@ -554,6 +555,24 @@ void PrintPPOutputPPCallbacks::PragmaWarningPop(SourceLocation Loc) { setEmittedDirectiveOnThisLine(); } +void PrintPPOutputPPCallbacks::PragmaExecCharsetPush(SourceLocation Loc, + StringRef Str) { + startNewLineIfNeeded(); + MoveToLine(Loc); + OS << "#pragma character_execution_set(push"; + if (!Str.empty()) + OS << ", " << Str; + OS << ')'; + setEmittedDirectiveOnThisLine(); +} + +void PrintPPOutputPPCallbacks::PragmaExecCharsetPop(SourceLocation Loc) { + startNewLineIfNeeded(); + MoveToLine(Loc); + OS << "#pragma character_execution_set(pop)"; + setEmittedDirectiveOnThisLine(); +} + void PrintPPOutputPPCallbacks:: PragmaAssumeNonNullBegin(SourceLocation Loc) { startNewLineIfNeeded(); @@ -645,7 +664,7 @@ struct UnknownPragmaHandler : public PragmaHandler { bool RequireTokenExpansion) : Prefix(prefix), Callbacks(callbacks), ShouldExpandTokens(RequireTokenExpansion) {} - void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, Token &PragmaTok) override { // Figure out what line we went to and insert the appropriate number of // newline characters. @@ -659,7 +678,8 @@ struct UnknownPragmaHandler : public PragmaHandler { auto Toks = llvm::make_unique<Token[]>(1); Toks[0] = PragmaTok; PP.EnterTokenStream(std::move(Toks), /*NumToks=*/1, - /*DisableMacroExpansion=*/false); + /*DisableMacroExpansion=*/false, + /*IsReinject=*/false); PP.Lex(PragmaTok); } Token PrevToken; @@ -750,6 +770,15 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, reinterpret_cast<Module *>(Tok.getAnnotationValue())); PP.Lex(Tok); continue; + } else if (Tok.is(tok::annot_header_unit)) { + // This is a header-name that has been (effectively) converted into a + // module-name. + // FIXME: The module name could contain non-identifier module name + // components. We don't have a good way to round-trip those. + Module *M = reinterpret_cast<Module *>(Tok.getAnnotationValue()); + std::string Name = M->getFullModuleName(); + OS.write(Name.data(), Name.size()); + Callbacks->HandleNewlinesInToken(Name.data(), Name.size()); } else if (Tok.isAnnotation()) { // Ignore annotation tokens created by pragmas - the pragmas themselves // will be reproduced in the preprocessed output. @@ -771,12 +800,12 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, Callbacks->HandleNewlinesInToken(TokPtr, Len); } else { std::string S = PP.getSpelling(Tok); - OS.write(&S[0], S.size()); + OS.write(S.data(), S.size()); // Tokens that can contain embedded newlines need to adjust our current // line number. if (Tok.getKind() == tok::comment || Tok.getKind() == tok::unknown) - Callbacks->HandleNewlinesInToken(&S[0], S.size()); + Callbacks->HandleNewlinesInToken(S.data(), S.size()); } Callbacks->setEmittedTokensOnThisLine(); diff --git a/lib/Frontend/Rewrite/FixItRewriter.cpp b/lib/Frontend/Rewrite/FixItRewriter.cpp index 1c2efe63aa19..667b9f0469f7 100644 --- a/lib/Frontend/Rewrite/FixItRewriter.cpp +++ b/lib/Frontend/Rewrite/FixItRewriter.cpp @@ -1,9 +1,8 @@ //===- FixItRewriter.cpp - Fix-It Rewriter Diagnostic Client --------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Frontend/Rewrite/FrontendActions.cpp b/lib/Frontend/Rewrite/FrontendActions.cpp index bcf6d215c998..0f1a0584c72b 100644 --- a/lib/Frontend/Rewrite/FrontendActions.cpp +++ b/lib/Frontend/Rewrite/FrontendActions.cpp @@ -1,9 +1,8 @@ //===--- FrontendActions.cpp ----------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -130,7 +129,11 @@ bool FixItRecompile::BeginInvocation(CompilerInstance &CI) { FixItOpts->FixOnlyWarnings = FEOpts.FixOnlyWarnings; FixItRewriter Rewriter(CI.getDiagnostics(), CI.getSourceManager(), CI.getLangOpts(), FixItOpts.get()); - FixAction->Execute(); + if (llvm::Error Err = FixAction->Execute()) { + // FIXME this drops the error on the floor. + consumeError(std::move(Err)); + return false; + } err = Rewriter.WriteFixedFiles(&RewrittenFiles); @@ -238,7 +241,7 @@ public: // Rewrite the contents of the module in a separate compiler instance. CompilerInstance Instance(CI.getPCHContainerOperations(), - &CI.getPreprocessor().getPCMCache()); + &CI.getModuleCache()); Instance.setInvocation( std::make_shared<CompilerInvocation>(CI.getInvocation())); Instance.createDiagnostics( diff --git a/lib/Frontend/Rewrite/HTMLPrint.cpp b/lib/Frontend/Rewrite/HTMLPrint.cpp index 34ee9673cc54..a5b36bc7856c 100644 --- a/lib/Frontend/Rewrite/HTMLPrint.cpp +++ b/lib/Frontend/Rewrite/HTMLPrint.cpp @@ -1,9 +1,8 @@ //===--- HTMLPrint.cpp - Source code -> HTML pretty-printing --------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Frontend/Rewrite/InclusionRewriter.cpp b/lib/Frontend/Rewrite/InclusionRewriter.cpp index 2e7baa3d9581..cb4e773aca87 100644 --- a/lib/Frontend/Rewrite/InclusionRewriter.cpp +++ b/lib/Frontend/Rewrite/InclusionRewriter.cpp @@ -1,9 +1,8 @@ //===--- InclusionRewriter.cpp - Rewrite includes into their expansions ---===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -415,7 +414,7 @@ bool InclusionRewriter::HandleHasInclude( // FIXME: Why don't we call PP.LookupFile here? const FileEntry *File = PP.getHeaderSearchInfo().LookupFile( Filename, SourceLocation(), isAngled, Lookup, CurDir, Includers, nullptr, - nullptr, nullptr, nullptr, nullptr); + nullptr, nullptr, nullptr, nullptr, nullptr); FileExists = File != nullptr; return true; diff --git a/lib/Frontend/Rewrite/RewriteMacros.cpp b/lib/Frontend/Rewrite/RewriteMacros.cpp index ae6b51bc814f..6b67ee638353 100644 --- a/lib/Frontend/Rewrite/RewriteMacros.cpp +++ b/lib/Frontend/Rewrite/RewriteMacros.cpp @@ -1,9 +1,8 @@ //===--- RewriteMacros.cpp - Rewrite macros into their expansions ---------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/lib/Frontend/Rewrite/RewriteModernObjC.cpp index 10ca9a785699..bd091ee03351 100644 --- a/lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ b/lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -1,9 +1,8 @@ -//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===// +//===-- RewriteModernObjC.cpp - Playground for the code rewriter ----------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -882,9 +881,8 @@ RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) { IvarT, nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - MemberExpr *ME = new (Context) - MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(), - FD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *ME = MemberExpr::CreateImplicit( + *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary); IvarT = Context->getDecltypeType(ME, ME->getType()); } } @@ -2430,7 +2428,7 @@ void RewriteModernObjC::SynthMsgSendFunctionDecl() { assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), - ArgTys, /*isVariadic=*/true); + ArgTys, /*variadic=*/true); MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), @@ -2444,7 +2442,7 @@ void RewriteModernObjC::SynthMsgSendSuperFunctionDecl() { SmallVector<QualType, 2> ArgTys; ArgTys.push_back(Context->VoidTy); QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), - ArgTys, /*isVariadic=*/true); + ArgTys, /*variadic=*/true); MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), @@ -2463,7 +2461,7 @@ void RewriteModernObjC::SynthMsgSendStretFunctionDecl() { assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), - ArgTys, /*isVariadic=*/true); + ArgTys, /*variadic=*/true); MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), @@ -2479,7 +2477,7 @@ void RewriteModernObjC::SynthMsgSendSuperStretFunctionDecl() { SmallVector<QualType, 2> ArgTys; ArgTys.push_back(Context->VoidTy); QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), - ArgTys, /*isVariadic=*/true); + ArgTys, /*variadic=*/true); MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), @@ -2499,7 +2497,7 @@ void RewriteModernObjC::SynthMsgSendFpretFunctionDecl() { assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); QualType msgSendType = getSimpleFunctionType(Context->DoubleTy, - ArgTys, /*isVariadic=*/true); + ArgTys, /*variadic=*/true); MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), @@ -2737,9 +2735,9 @@ Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) { Context->getPointerType(Context->VoidPtrTy), nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - MemberExpr *ArrayLiteralME = new (Context) - MemberExpr(NSArrayCallExpr, false, SourceLocation(), ARRFD, - SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *ArrayLiteralME = + MemberExpr::CreateImplicit(*Context, NSArrayCallExpr, false, ARRFD, + ARRFD->getType(), VK_LValue, OK_Ordinary); QualType ConstIdT = Context->getObjCIdType().withConst(); CStyleCastExpr * ArrayLiteralObjects = NoTypeInfoCStyleCastExpr(Context, @@ -2866,9 +2864,9 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral Context->getPointerType(Context->VoidPtrTy), nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - MemberExpr *DictLiteralValueME = new (Context) - MemberExpr(NSValueCallExpr, false, SourceLocation(), ARRFD, - SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *DictLiteralValueME = + MemberExpr::CreateImplicit(*Context, NSValueCallExpr, false, ARRFD, + ARRFD->getType(), VK_LValue, OK_Ordinary); QualType ConstIdT = Context->getObjCIdType().withConst(); CStyleCastExpr * DictValueObjects = NoTypeInfoCStyleCastExpr(Context, @@ -2879,9 +2877,9 @@ Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral Expr *NSKeyCallExpr = CallExpr::Create( *Context, NSDictDRE, KeyExprs, NSDictFType, VK_LValue, SourceLocation()); - MemberExpr *DictLiteralKeyME = new (Context) - MemberExpr(NSKeyCallExpr, false, SourceLocation(), ARRFD, - SourceLocation(), ARRFD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *DictLiteralKeyME = + MemberExpr::CreateImplicit(*Context, NSKeyCallExpr, false, ARRFD, + ARRFD->getType(), VK_LValue, OK_Ordinary); CStyleCastExpr * DictKeyObjects = NoTypeInfoCStyleCastExpr(Context, @@ -3181,9 +3179,8 @@ Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFla returnType, nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - MemberExpr *ME = new (Context) - MemberExpr(STCE, false, SourceLocation(), FieldD, SourceLocation(), - FieldD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *ME = MemberExpr::CreateImplicit( + *Context, STCE, false, FieldD, FieldD->getType(), VK_LValue, OK_Ordinary); return ME; } @@ -4630,9 +4627,8 @@ Stmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp Context->VoidPtrTy, nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - MemberExpr *ME = - new (Context) MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(), - FD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *ME = MemberExpr::CreateImplicit( + *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary); CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType, CK_BitCast, ME); @@ -4677,9 +4673,8 @@ Stmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) { Context->VoidPtrTy, nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - MemberExpr *ME = new (Context) - MemberExpr(DeclRefExp, isArrow, SourceLocation(), FD, SourceLocation(), - FD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *ME = MemberExpr::CreateImplicit( + *Context, DeclRefExp, isArrow, FD, FD->getType(), VK_LValue, OK_Ordinary); StringRef Name = VD->getName(); FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(), @@ -4687,9 +4682,8 @@ Stmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) { Context->VoidPtrTy, nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - ME = - new (Context) MemberExpr(ME, true, SourceLocation(), FD, SourceLocation(), - DeclRefExp->getType(), VK_LValue, OK_Ordinary); + ME = MemberExpr::CreateImplicit(*Context, ME, true, FD, DeclRefExp->getType(), + VK_LValue, OK_Ordinary); // Need parens to enforce precedence. ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(), @@ -7529,9 +7523,8 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { IvarT, nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - MemberExpr *ME = new (Context) - MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(), - FD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *ME = MemberExpr::CreateImplicit( + *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary); IvarT = Context->getDecltypeType(ME, ME->getType()); } } @@ -7558,9 +7551,9 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { D->getType(), nullptr, /*BitWidth=*/D->getBitWidth(), /*Mutable=*/true, ICIS_NoInit); - MemberExpr *ME = new (Context) - MemberExpr(PE, /*isArrow*/ false, SourceLocation(), FD, - SourceLocation(), FD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *ME = + MemberExpr::CreateImplicit(*Context, PE, /*isArrow*/ false, FD, + FD->getType(), VK_LValue, OK_Ordinary); Replacement = ME; } diff --git a/lib/Frontend/Rewrite/RewriteObjC.cpp b/lib/Frontend/Rewrite/RewriteObjC.cpp index 3e018800b909..05078baee790 100644 --- a/lib/Frontend/Rewrite/RewriteObjC.cpp +++ b/lib/Frontend/Rewrite/RewriteObjC.cpp @@ -1,9 +1,8 @@ //===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -2336,7 +2335,7 @@ void RewriteObjC::SynthMsgSendFunctionDecl() { assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), - ArgTys, /*isVariadic=*/true); + ArgTys, /*variadic=*/true); MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), @@ -2358,7 +2357,7 @@ void RewriteObjC::SynthMsgSendSuperFunctionDecl() { assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), - ArgTys, /*isVariadic=*/true); + ArgTys, /*variadic=*/true); MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), @@ -2377,7 +2376,7 @@ void RewriteObjC::SynthMsgSendStretFunctionDecl() { assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), - ArgTys, /*isVariadic=*/true); + ArgTys, /*variadic=*/true); MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), @@ -2401,7 +2400,7 @@ void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() { assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), - ArgTys, /*isVariadic=*/true); + ArgTys, /*variadic=*/true); MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), @@ -2421,7 +2420,7 @@ void RewriteObjC::SynthMsgSendFpretFunctionDecl() { assert(!argT.isNull() && "Can't find 'SEL' type"); ArgTys.push_back(argT); QualType msgSendType = getSimpleFunctionType(Context->DoubleTy, - ArgTys, /*isVariadic=*/true); + ArgTys, /*variadic=*/true); MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), @@ -3794,9 +3793,8 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) { Context->VoidPtrTy, nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - MemberExpr *ME = - new (Context) MemberExpr(PE, true, SourceLocation(), FD, SourceLocation(), - FD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *ME = MemberExpr::CreateImplicit( + *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary); CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType, CK_BitCast, ME); @@ -3841,9 +3839,9 @@ Stmt *RewriteObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) { Context->VoidPtrTy, nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - MemberExpr *ME = new (Context) - MemberExpr(DeclRefExp, isArrow, SourceLocation(), FD, SourceLocation(), - FD->getType(), VK_LValue, OK_Ordinary); + MemberExpr *ME = + MemberExpr::CreateImplicit(*Context, DeclRefExp, isArrow, FD, + FD->getType(), VK_LValue, OK_Ordinary); StringRef Name = VD->getName(); FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(), @@ -3851,9 +3849,8 @@ Stmt *RewriteObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) { Context->VoidPtrTy, nullptr, /*BitWidth=*/nullptr, /*Mutable=*/true, ICIS_NoInit); - ME = - new (Context) MemberExpr(ME, true, SourceLocation(), FD, SourceLocation(), - DeclRefExp->getType(), VK_LValue, OK_Ordinary); + ME = MemberExpr::CreateImplicit(*Context, ME, true, FD, DeclRefExp->getType(), + VK_LValue, OK_Ordinary); // Need parens to enforce precedence. ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(), @@ -5831,10 +5828,10 @@ Stmt *RewriteObjCFragileABI::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { OldRange.getEnd(), castExpr); if (IV->isFreeIvar() && - declaresSameEntity(CurMethodDef->getClassInterface(), iFaceDecl->getDecl())) { - MemberExpr *ME = new (Context) - MemberExpr(PE, true, SourceLocation(), D, IV->getLocation(), - D->getType(), VK_LValue, OK_Ordinary); + declaresSameEntity(CurMethodDef->getClassInterface(), + iFaceDecl->getDecl())) { + MemberExpr *ME = MemberExpr::CreateImplicit( + *Context, PE, true, D, D->getType(), VK_LValue, OK_Ordinary); Replacement = ME; } else { IV->setBase(PE); diff --git a/lib/Frontend/Rewrite/RewriteTest.cpp b/lib/Frontend/Rewrite/RewriteTest.cpp index b0791f4cddd7..fa8232c8c3c9 100644 --- a/lib/Frontend/Rewrite/RewriteTest.cpp +++ b/lib/Frontend/Rewrite/RewriteTest.cpp @@ -1,9 +1,8 @@ //===--- RewriteTest.cpp - Rewriter playground ----------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Frontend/SerializedDiagnosticPrinter.cpp b/lib/Frontend/SerializedDiagnosticPrinter.cpp index 22546ce4c097..c1434a95cc70 100644 --- a/lib/Frontend/SerializedDiagnosticPrinter.cpp +++ b/lib/Frontend/SerializedDiagnosticPrinter.cpp @@ -1,9 +1,8 @@ //===--- SerializedDiagnosticPrinter.cpp - Serializer for diagnostics -----===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -21,6 +20,8 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Bitstream/BitCodes.h" +#include "llvm/Bitstream/BitstreamReader.h" #include "llvm/Support/raw_ostream.h" #include <utility> diff --git a/lib/Frontend/SerializedDiagnosticReader.cpp b/lib/Frontend/SerializedDiagnosticReader.cpp index 458717819c41..eca6f5ee1803 100644 --- a/lib/Frontend/SerializedDiagnosticReader.cpp +++ b/lib/Frontend/SerializedDiagnosticReader.cpp @@ -1,9 +1,8 @@ //===- SerializedDiagnosticReader.cpp - Reads diagnostics -----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -14,8 +13,8 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Bitcode/BitCodes.h" -#include "llvm/Bitcode/BitstreamReader.h" +#include "llvm/Bitstream/BitCodes.h" +#include "llvm/Bitstream/BitstreamReader.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorOr.h" @@ -42,21 +41,47 @@ std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) { return SDError::InvalidSignature; // Sniff for the signature. - if (Stream.Read(8) != 'D' || - Stream.Read(8) != 'I' || - Stream.Read(8) != 'A' || - Stream.Read(8) != 'G') + for (unsigned char C : {'D', 'I', 'A', 'G'}) { + if (Expected<llvm::SimpleBitstreamCursor::word_t> Res = Stream.Read(8)) { + if (Res.get() == C) + continue; + } else { + // FIXME this drops the error on the floor. + consumeError(Res.takeError()); + } return SDError::InvalidSignature; + } // Read the top level blocks. while (!Stream.AtEndOfStream()) { - if (Stream.ReadCode() != llvm::bitc::ENTER_SUBBLOCK) + if (Expected<unsigned> Res = Stream.ReadCode()) { + if (Res.get() != llvm::bitc::ENTER_SUBBLOCK) + return SDError::InvalidDiagnostics; + } else { + // FIXME this drops the error on the floor. + consumeError(Res.takeError()); return SDError::InvalidDiagnostics; + } std::error_code EC; - switch (Stream.ReadSubBlockID()) { - case llvm::bitc::BLOCKINFO_BLOCK_ID: - BlockInfo = Stream.ReadBlockInfoBlock(); + Expected<unsigned> MaybeSubBlockID = Stream.ReadSubBlockID(); + if (!MaybeSubBlockID) { + // FIXME this drops the error on the floor. + consumeError(MaybeSubBlockID.takeError()); + return SDError::InvalidDiagnostics; + } + + switch (MaybeSubBlockID.get()) { + case llvm::bitc::BLOCKINFO_BLOCK_ID: { + Expected<Optional<llvm::BitstreamBlockInfo>> MaybeBlockInfo = + Stream.ReadBlockInfoBlock(); + if (!MaybeBlockInfo) { + // FIXME this drops the error on the floor. + consumeError(MaybeBlockInfo.takeError()); + return SDError::InvalidDiagnostics; + } + BlockInfo = std::move(MaybeBlockInfo.get()); + } if (!BlockInfo) return SDError::MalformedBlockInfoBlock; Stream.setBlockInfo(&*BlockInfo); @@ -70,8 +95,11 @@ std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) { return EC; continue; default: - if (!Stream.SkipBlock()) + if (llvm::Error Err = Stream.SkipBlock()) { + // FIXME this drops the error on the floor. + consumeError(std::move(Err)); return SDError::MalformedTopLevelBlock; + } continue; } } @@ -90,11 +118,23 @@ SerializedDiagnosticReader::skipUntilRecordOrBlock( BlockOrRecordID = 0; while (!Stream.AtEndOfStream()) { - unsigned Code = Stream.ReadCode(); + unsigned Code; + if (Expected<unsigned> Res = Stream.ReadCode()) + Code = Res.get(); + else + return llvm::errorToErrorCode(Res.takeError()); - switch ((llvm::bitc::FixedAbbrevIDs)Code) { + if (Code >= static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV)) { + // We found a record. + BlockOrRecordID = Code; + return Cursor::Record; + } + switch (static_cast<llvm::bitc::FixedAbbrevIDs>(Code)) { case llvm::bitc::ENTER_SUBBLOCK: - BlockOrRecordID = Stream.ReadSubBlockID(); + if (Expected<unsigned> Res = Stream.ReadSubBlockID()) + BlockOrRecordID = Res.get(); + else + return llvm::errorToErrorCode(Res.takeError()); return Cursor::BlockBegin; case llvm::bitc::END_BLOCK: @@ -103,16 +143,15 @@ SerializedDiagnosticReader::skipUntilRecordOrBlock( return Cursor::BlockEnd; case llvm::bitc::DEFINE_ABBREV: - Stream.ReadAbbrevRecord(); + if (llvm::Error Err = Stream.ReadAbbrevRecord()) + return llvm::errorToErrorCode(std::move(Err)); continue; case llvm::bitc::UNABBREV_RECORD: return SDError::UnsupportedConstruct; - default: - // We found a record. - BlockOrRecordID = Code; - return Cursor::Record; + case llvm::bitc::FIRST_APPLICATION_ABBREV: + llvm_unreachable("Unexpected abbrev id."); } } @@ -121,8 +160,12 @@ SerializedDiagnosticReader::skipUntilRecordOrBlock( std::error_code SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) { - if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_META)) + if (llvm::Error Err = + Stream.EnterSubBlock(clang::serialized_diags::BLOCK_META)) { + // FIXME this drops the error on the floor. + consumeError(std::move(Err)); return SDError::MalformedMetadataBlock; + } bool VersionChecked = false; @@ -136,8 +179,11 @@ SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) { case Cursor::Record: break; case Cursor::BlockBegin: - if (Stream.SkipBlock()) + if (llvm::Error Err = Stream.SkipBlock()) { + // FIXME this drops the error on the floor. + consumeError(std::move(Err)); return SDError::MalformedMetadataBlock; + } LLVM_FALLTHROUGH; case Cursor::BlockEnd: if (!VersionChecked) @@ -146,7 +192,10 @@ SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) { } SmallVector<uint64_t, 1> Record; - unsigned RecordID = Stream.readRecord(BlockOrCode, Record); + Expected<unsigned> MaybeRecordID = Stream.readRecord(BlockOrCode, Record); + if (!MaybeRecordID) + return errorToErrorCode(MaybeRecordID.takeError()); + unsigned RecordID = MaybeRecordID.get(); if (RecordID == RECORD_VERSION) { if (Record.size() < 1) @@ -160,8 +209,12 @@ SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) { std::error_code SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) { - if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG)) + if (llvm::Error Err = + Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG)) { + // FIXME this drops the error on the floor. + consumeError(std::move(Err)); return SDError::MalformedDiagnosticBlock; + } std::error_code EC; if ((EC = visitStartOfDiagnostic())) @@ -180,8 +233,11 @@ SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) { if (BlockOrCode == serialized_diags::BLOCK_DIAG) { if ((EC = readDiagnosticBlock(Stream))) return EC; - } else if (!Stream.SkipBlock()) + } else if (llvm::Error Err = Stream.SkipBlock()) { + // FIXME this drops the error on the floor. + consumeError(std::move(Err)); return SDError::MalformedSubBlock; + } continue; case Cursor::BlockEnd: if ((EC = visitEndOfDiagnostic())) @@ -194,7 +250,11 @@ SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) { // Read the record. Record.clear(); StringRef Blob; - unsigned RecID = Stream.readRecord(BlockOrCode, Record, &Blob); + Expected<unsigned> MaybeRecID = + Stream.readRecord(BlockOrCode, Record, &Blob); + if (!MaybeRecID) + return errorToErrorCode(MaybeRecID.takeError()); + unsigned RecID = MaybeRecID.get(); if (RecID < serialized_diags::RECORD_FIRST || RecID > serialized_diags::RECORD_LAST) diff --git a/lib/Frontend/TestModuleFileExtension.cpp b/lib/Frontend/TestModuleFileExtension.cpp index 087bdc543548..354aa7f5cd3f 100644 --- a/lib/Frontend/TestModuleFileExtension.cpp +++ b/lib/Frontend/TestModuleFileExtension.cpp @@ -1,16 +1,15 @@ //===-- TestModuleFileExtension.cpp - Module Extension Tester -------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "TestModuleFileExtension.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Serialization/ASTReader.h" #include "llvm/ADT/Hashing.h" -#include "llvm/Bitcode/BitstreamWriter.h" +#include "llvm/Bitstream/BitstreamWriter.h" #include "llvm/Support/raw_ostream.h" #include <cstdio> using namespace clang; @@ -49,7 +48,12 @@ TestModuleFileExtension::Reader::Reader(ModuleFileExtension *Ext, // Read the extension block. SmallVector<uint64_t, 4> Record; while (true) { - llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + llvm::Expected<llvm::BitstreamEntry> MaybeEntry = + Stream.advanceSkippingSubblocks(); + if (!MaybeEntry) + (void)MaybeEntry.takeError(); + llvm::BitstreamEntry Entry = MaybeEntry.get(); + switch (Entry.Kind) { case llvm::BitstreamEntry::SubBlock: case llvm::BitstreamEntry::EndBlock: @@ -62,8 +66,12 @@ TestModuleFileExtension::Reader::Reader(ModuleFileExtension *Ext, Record.clear(); StringRef Blob; - unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob); - switch (RecCode) { + Expected<unsigned> MaybeRecCode = + Stream.readRecord(Entry.ID, Record, &Blob); + if (!MaybeRecCode) + fprintf(stderr, "Failed reading rec code: %s\n", + toString(MaybeRecCode.takeError()).c_str()); + switch (MaybeRecCode.get()) { case FIRST_EXTENSION_RECORD_ID: { StringRef Message = Blob.substr(0, Record[0]); fprintf(stderr, "Read extension block message: %s\n", diff --git a/lib/Frontend/TestModuleFileExtension.h b/lib/Frontend/TestModuleFileExtension.h index 41f3ca9f05fc..13e090783b11 100644 --- a/lib/Frontend/TestModuleFileExtension.h +++ b/lib/Frontend/TestModuleFileExtension.h @@ -1,9 +1,8 @@ //===-- TestModuleFileExtension.h - Module Extension Tester -----*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_FRONTEND_TESTMODULEFILEEXTENSION_H @@ -12,7 +11,7 @@ #include "clang/Serialization/ModuleFileExtension.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Bitcode/BitstreamReader.h" +#include "llvm/Bitstream/BitstreamReader.h" #include <string> namespace clang { diff --git a/lib/Frontend/TextDiagnostic.cpp b/lib/Frontend/TextDiagnostic.cpp index 35b99b10f94a..d0c91286250e 100644 --- a/lib/Frontend/TextDiagnostic.cpp +++ b/lib/Frontend/TextDiagnostic.cpp @@ -1,9 +1,8 @@ //===--- TextDiagnostic.cpp - Text Diagnostic Pretty-Printing -------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -334,8 +333,7 @@ static void selectInterestingSourceRegion(std::string &SourceLine, // No special characters are allowed in CaretLine. assert(CaretLine.end() == - std::find_if(CaretLine.begin(), CaretLine.end(), - [](char c) { return c < ' ' || '~' < c; })); + llvm::find_if(CaretLine, [](char c) { return c < ' ' || '~' < c; })); // Find the slice that we need to display the full caret line // correctly. @@ -767,7 +765,28 @@ void TextDiagnostic::emitFilename(StringRef Filename, const SourceManager &SM) { const DirectoryEntry *Dir = SM.getFileManager().getDirectory( llvm::sys::path::parent_path(Filename)); if (Dir) { + // We want to print a simplified absolute path, i. e. without "dots". + // + // The hardest part here are the paths like "<part1>/<link>/../<part2>". + // On Unix-like systems, we cannot just collapse "<link>/..", because + // paths are resolved sequentially, and, thereby, the path + // "<part1>/<part2>" may point to a different location. That is why + // we use FileManager::getCanonicalName(), which expands all indirections + // with llvm::sys::fs::real_path() and caches the result. + // + // On the other hand, it would be better to preserve as much of the + // original path as possible, because that helps a user to recognize it. + // real_path() expands all links, which sometimes too much. Luckily, + // on Windows we can just use llvm::sys::path::remove_dots(), because, + // on that system, both aforementioned paths point to the same place. +#ifdef _WIN32 + SmallString<4096> DirName = Dir->getName(); + llvm::sys::fs::make_absolute(DirName); + llvm::sys::path::native(DirName); + llvm::sys::path::remove_dots(DirName, /* remove_dot_dot */ true); +#else StringRef DirName = SM.getFileManager().getCanonicalName(Dir); +#endif llvm::sys::path::append(AbsoluteFilename, DirName, llvm::sys::path::filename(Filename)); Filename = StringRef(AbsoluteFilename.data(), AbsoluteFilename.size()); @@ -793,8 +812,6 @@ void TextDiagnostic::emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, const FileEntry *FE = Loc.getFileEntry(); if (FE && FE->isValid()) { emitFilename(FE->getName(), Loc.getManager()); - if (FE->isInPCH()) - OS << " (in PCH)"; OS << ": "; } } @@ -838,7 +855,7 @@ void TextDiagnostic::emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, if (LangOpts.MSCompatibilityVersion && !LangOpts.isCompatibleWithMSVC(LangOptions::MSVC2015)) OS << ' '; - OS << ": "; + OS << ':'; break; } diff --git a/lib/Frontend/TextDiagnosticBuffer.cpp b/lib/Frontend/TextDiagnosticBuffer.cpp index 44bb2bc29bc0..b2497f56cbcd 100644 --- a/lib/Frontend/TextDiagnosticBuffer.cpp +++ b/lib/Frontend/TextDiagnosticBuffer.cpp @@ -1,9 +1,8 @@ //===- TextDiagnosticBuffer.cpp - Buffer Text Diagnostics -----------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp index a37382c116ae..0c0a44a1388b 100644 --- a/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/lib/Frontend/TextDiagnosticPrinter.cpp @@ -1,9 +1,8 @@ //===--- TextDiagnosticPrinter.cpp - Diagnostic Printer -------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp index 21933f474ff5..a68ef03d4db1 100644 --- a/lib/Frontend/VerifyDiagnosticConsumer.cpp +++ b/lib/Frontend/VerifyDiagnosticConsumer.cpp @@ -1,9 +1,8 @@ //===- VerifyDiagnosticConsumer.cpp - Verifying Diagnostic Client ---------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -51,23 +50,6 @@ using Directive = VerifyDiagnosticConsumer::Directive; using DirectiveList = VerifyDiagnosticConsumer::DirectiveList; using ExpectedData = VerifyDiagnosticConsumer::ExpectedData; -VerifyDiagnosticConsumer::VerifyDiagnosticConsumer(DiagnosticsEngine &Diags_) - : Diags(Diags_), PrimaryClient(Diags.getClient()), - PrimaryClientOwner(Diags.takeClient()), - Buffer(new TextDiagnosticBuffer()), Status(HasNoDirectives) { - if (Diags.hasSourceManager()) - setSourceManager(Diags.getSourceManager()); -} - -VerifyDiagnosticConsumer::~VerifyDiagnosticConsumer() { - assert(!ActiveSourceFiles && "Incomplete parsing of source files!"); - assert(!CurrentPreprocessor && "CurrentPreprocessor should be invalid!"); - SrcManager = nullptr; - CheckDiagnostics(); - assert(!Diags.ownsClient() && - "The VerifyDiagnosticConsumer takes over ownership of the client!"); -} - #ifndef NDEBUG namespace { @@ -94,86 +76,6 @@ public: #endif -// DiagnosticConsumer interface. - -void VerifyDiagnosticConsumer::BeginSourceFile(const LangOptions &LangOpts, - const Preprocessor *PP) { - // Attach comment handler on first invocation. - if (++ActiveSourceFiles == 1) { - if (PP) { - CurrentPreprocessor = PP; - this->LangOpts = &LangOpts; - setSourceManager(PP->getSourceManager()); - const_cast<Preprocessor *>(PP)->addCommentHandler(this); -#ifndef NDEBUG - // Debug build tracks parsed files. - const_cast<Preprocessor *>(PP)->addPPCallbacks( - llvm::make_unique<VerifyFileTracker>(*this, *SrcManager)); -#endif - } - } - - assert((!PP || CurrentPreprocessor == PP) && "Preprocessor changed!"); - PrimaryClient->BeginSourceFile(LangOpts, PP); -} - -void VerifyDiagnosticConsumer::EndSourceFile() { - assert(ActiveSourceFiles && "No active source files!"); - PrimaryClient->EndSourceFile(); - - // Detach comment handler once last active source file completed. - if (--ActiveSourceFiles == 0) { - if (CurrentPreprocessor) - const_cast<Preprocessor *>(CurrentPreprocessor)-> - removeCommentHandler(this); - - // Check diagnostics once last file completed. - CheckDiagnostics(); - CurrentPreprocessor = nullptr; - LangOpts = nullptr; - } -} - -void VerifyDiagnosticConsumer::HandleDiagnostic( - DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) { - if (Info.hasSourceManager()) { - // If this diagnostic is for a different source manager, ignore it. - if (SrcManager && &Info.getSourceManager() != SrcManager) - return; - - setSourceManager(Info.getSourceManager()); - } - -#ifndef NDEBUG - // Debug build tracks unparsed files for possible - // unparsed expected-* directives. - if (SrcManager) { - SourceLocation Loc = Info.getLocation(); - if (Loc.isValid()) { - ParsedStatus PS = IsUnparsed; - - Loc = SrcManager->getExpansionLoc(Loc); - FileID FID = SrcManager->getFileID(Loc); - - const FileEntry *FE = SrcManager->getFileEntryForID(FID); - if (FE && CurrentPreprocessor && SrcManager->isLoadedFileID(FID)) { - // If the file is a modules header file it shall not be parsed - // for expected-* directives. - HeaderSearch &HS = CurrentPreprocessor->getHeaderSearchInfo(); - if (HS.findModuleForHeader(FE)) - PS = IsUnparsedNoDirectives; - } - - UpdateParsedFileStatus(*SrcManager, FID, PS); - } - } -#endif - - // Send the diagnostic to the buffer, we will check it once we reach the end - // of the source file (or are destructed). - Buffer->HandleDiagnostic(DiagLevel, Info); -} - //===----------------------------------------------------------------------===// // Checking diagnostics implementation. //===----------------------------------------------------------------------===// @@ -242,17 +144,31 @@ public: bool Next(unsigned &N) { unsigned TMP = 0; P = C; - for (; P < End && P[0] >= '0' && P[0] <= '9'; ++P) { + PEnd = P; + for (; PEnd < End && *PEnd >= '0' && *PEnd <= '9'; ++PEnd) { TMP *= 10; - TMP += P[0] - '0'; + TMP += *PEnd - '0'; } - if (P == C) + if (PEnd == C) return false; - PEnd = P; N = TMP; return true; } + // Return true if a marker is next. + // A marker is the longest match for /#[A-Za-z0-9_-]+/. + bool NextMarker() { + P = C; + if (P == End || *P != '#') + return false; + PEnd = P; + ++PEnd; + while ((isAlphanumeric(*PEnd) || *PEnd == '-' || *PEnd == '_') && + PEnd < End) + ++PEnd; + return PEnd > P + 1; + } + // Return true if string literal S is matched in content. // When true, P marks begin-position of the match, and calling Advance sets C // to end-position of the match. @@ -334,6 +250,10 @@ public: return C < End; } + // Return the text matched by the previous next/search. + // Behavior is undefined if previous next/search failed. + StringRef Match() { return StringRef(P, PEnd - P); } + // Skip zero or more whitespace. void SkipWhitespace() { for (; C < End && isWhitespace(*C); ++C) @@ -354,6 +274,7 @@ public: // Position of next char in content. const char *C; + // Previous next/search subject start. const char *P; private: @@ -361,17 +282,142 @@ private: const char *PEnd = nullptr; }; +// The information necessary to create a directive. +struct UnattachedDirective { + DirectiveList *DL = nullptr; + bool RegexKind = false; + SourceLocation DirectivePos, ContentBegin; + std::string Text; + unsigned Min = 1, Max = 1; +}; + +// Attach the specified directive to the line of code indicated by +// \p ExpectedLoc. +void attachDirective(DiagnosticsEngine &Diags, const UnattachedDirective &UD, + SourceLocation ExpectedLoc, bool MatchAnyLine = false) { + // Construct new directive. + std::unique_ptr<Directive> D = + Directive::create(UD.RegexKind, UD.DirectivePos, ExpectedLoc, + MatchAnyLine, UD.Text, UD.Min, UD.Max); + + std::string Error; + if (!D->isValid(Error)) { + Diags.Report(UD.ContentBegin, diag::err_verify_invalid_content) + << (UD.RegexKind ? "regex" : "string") << Error; + } + + UD.DL->push_back(std::move(D)); +} + } // anonymous +// Tracker for markers in the input files. A marker is a comment of the form +// +// n = 123; // #123 +// +// ... that can be referred to by a later expected-* directive: +// +// // expected-error@#123 {{undeclared identifier 'n'}} +// +// Marker declarations must be at the start of a comment or preceded by +// whitespace to distinguish them from uses of markers in directives. +class VerifyDiagnosticConsumer::MarkerTracker { + DiagnosticsEngine &Diags; + + struct Marker { + SourceLocation DefLoc; + SourceLocation RedefLoc; + SourceLocation UseLoc; + }; + llvm::StringMap<Marker> Markers; + + // Directives that couldn't be created yet because they name an unknown + // marker. + llvm::StringMap<llvm::SmallVector<UnattachedDirective, 2>> DeferredDirectives; + +public: + MarkerTracker(DiagnosticsEngine &Diags) : Diags(Diags) {} + + // Register a marker. + void addMarker(StringRef MarkerName, SourceLocation Pos) { + auto InsertResult = Markers.insert( + {MarkerName, Marker{Pos, SourceLocation(), SourceLocation()}}); + + Marker &M = InsertResult.first->second; + if (!InsertResult.second) { + // Marker was redefined. + M.RedefLoc = Pos; + } else { + // First definition: build any deferred directives. + auto Deferred = DeferredDirectives.find(MarkerName); + if (Deferred != DeferredDirectives.end()) { + for (auto &UD : Deferred->second) { + if (M.UseLoc.isInvalid()) + M.UseLoc = UD.DirectivePos; + attachDirective(Diags, UD, Pos); + } + DeferredDirectives.erase(Deferred); + } + } + } + + // Register a directive at the specified marker. + void addDirective(StringRef MarkerName, const UnattachedDirective &UD) { + auto MarkerIt = Markers.find(MarkerName); + if (MarkerIt != Markers.end()) { + Marker &M = MarkerIt->second; + if (M.UseLoc.isInvalid()) + M.UseLoc = UD.DirectivePos; + return attachDirective(Diags, UD, M.DefLoc); + } + DeferredDirectives[MarkerName].push_back(UD); + } + + // Ensure we have no remaining deferred directives, and no + // multiply-defined-and-used markers. + void finalize() { + for (auto &MarkerInfo : Markers) { + StringRef Name = MarkerInfo.first(); + Marker &M = MarkerInfo.second; + if (M.RedefLoc.isValid() && M.UseLoc.isValid()) { + Diags.Report(M.UseLoc, diag::err_verify_ambiguous_marker) << Name; + Diags.Report(M.DefLoc, diag::note_verify_ambiguous_marker) << Name; + Diags.Report(M.RedefLoc, diag::note_verify_ambiguous_marker) << Name; + } + } + + for (auto &DeferredPair : DeferredDirectives) { + Diags.Report(DeferredPair.second.front().DirectivePos, + diag::err_verify_no_such_marker) + << DeferredPair.first(); + } + } +}; + /// ParseDirective - Go through the comment and see if it indicates expected /// diagnostics. If so, then put them in the appropriate directive list. /// /// Returns true if any valid directives were found. static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM, Preprocessor *PP, SourceLocation Pos, - VerifyDiagnosticConsumer::DirectiveStatus &Status) { + VerifyDiagnosticConsumer::DirectiveStatus &Status, + VerifyDiagnosticConsumer::MarkerTracker &Markers) { DiagnosticsEngine &Diags = PP ? PP->getDiagnostics() : SM.getDiagnostics(); + // First, scan the comment looking for markers. + for (ParseHelper PH(S); !PH.Done();) { + if (!PH.Search("#", true)) + break; + PH.C = PH.P; + if (!PH.NextMarker()) { + PH.Next("#"); + PH.Advance(); + continue; + } + PH.Advance(); + Markers.addMarker(PH.Match(), Pos); + } + // A single comment may contain multiple directives. bool FoundDirective = false; for (ParseHelper PH(S); !PH.Done();) { @@ -382,41 +428,41 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM, if (!(Prefixes.size() == 1 ? PH.Search(*Prefixes.begin(), true, true) : PH.Search("", true, true))) break; + + StringRef DToken = PH.Match(); PH.Advance(); // Default directive kind. - bool RegexKind = false; - const char* KindStr = "string"; + UnattachedDirective D; + const char *KindStr = "string"; // Parse the initial directive token in reverse so we can easily determine // its exact actual prefix. If we were to parse it from the front instead, // it would be harder to determine where the prefix ends because there // might be multiple matching -verify prefixes because some might prefix // others. - StringRef DToken(PH.P, PH.C - PH.P); // Regex in initial directive token: -re if (DToken.endswith("-re")) { - RegexKind = true; + D.RegexKind = true; KindStr = "regex"; DToken = DToken.substr(0, DToken.size()-3); } // Type in initial directive token: -{error|warning|note|no-diagnostics} - DirectiveList *DL = nullptr; bool NoDiag = false; StringRef DType; if (DToken.endswith(DType="-error")) - DL = ED ? &ED->Errors : nullptr; + D.DL = ED ? &ED->Errors : nullptr; else if (DToken.endswith(DType="-warning")) - DL = ED ? &ED->Warnings : nullptr; + D.DL = ED ? &ED->Warnings : nullptr; else if (DToken.endswith(DType="-remark")) - DL = ED ? &ED->Remarks : nullptr; + D.DL = ED ? &ED->Remarks : nullptr; else if (DToken.endswith(DType="-note")) - DL = ED ? &ED->Notes : nullptr; + D.DL = ED ? &ED->Notes : nullptr; else if (DToken.endswith(DType="-no-diagnostics")) { NoDiag = true; - if (RegexKind) + if (D.RegexKind) continue; } else @@ -446,11 +492,12 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM, // If a directive has been found but we're not interested // in storing the directive information, return now. - if (!DL) + if (!D.DL) return true; // Next optional token: @ SourceLocation ExpectedLoc; + StringRef Marker; bool MatchAnyLine = false; if (!PH.Next("@")) { ExpectedLoc = Pos; @@ -472,6 +519,8 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM, // Absolute line number. if (Line > 0) ExpectedLoc = SM.translateLineCol(SM.getFileID(Pos), Line, 1); + } else if (PH.NextMarker()) { + Marker = PH.Match(); } else if (PP && PH.Search(":")) { // Specific source file. StringRef Filename(PH.C, PH.P-PH.C); @@ -481,7 +530,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, nullptr, nullptr); if (!FE) { Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), diag::err_verify_missing_file) << Filename << KindStr; @@ -502,7 +551,7 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM, ExpectedLoc = SourceLocation(); } - if (ExpectedLoc.isInvalid() && !MatchAnyLine) { + if (ExpectedLoc.isInvalid() && !MatchAnyLine && Marker.empty()) { Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), diag::err_verify_missing_line) << KindStr; continue; @@ -514,29 +563,27 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM, PH.SkipWhitespace(); // Next optional token: positive integer or a '+'. - unsigned Min = 1; - unsigned Max = 1; - if (PH.Next(Min)) { + if (PH.Next(D.Min)) { PH.Advance(); // A positive integer can be followed by a '+' meaning min // or more, or by a '-' meaning a range from min to max. if (PH.Next("+")) { - Max = Directive::MaxCount; + D.Max = Directive::MaxCount; PH.Advance(); } else if (PH.Next("-")) { PH.Advance(); - if (!PH.Next(Max) || Max < Min) { + if (!PH.Next(D.Max) || D.Max < D.Min) { Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), diag::err_verify_invalid_range) << KindStr; continue; } PH.Advance(); } else { - Max = Min; + D.Max = D.Min; } } else if (PH.Next("+")) { // '+' on its own means "1 or more". - Max = Directive::MaxCount; + D.Max = Directive::MaxCount; PH.Advance(); } @@ -551,7 +598,6 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM, } PH.Advance(); const char* const ContentBegin = PH.C; // mark content begin - // Search for token: }} if (!PH.SearchClosingBrace("{{", "}}")) { Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), @@ -561,43 +607,137 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM, const char* const ContentEnd = PH.P; // mark content end PH.Advance(); + D.DirectivePos = Pos; + D.ContentBegin = Pos.getLocWithOffset(ContentBegin - PH.Begin); + // Build directive text; convert \n to newlines. - std::string Text; StringRef NewlineStr = "\\n"; StringRef Content(ContentBegin, ContentEnd-ContentBegin); size_t CPos = 0; size_t FPos; while ((FPos = Content.find(NewlineStr, CPos)) != StringRef::npos) { - Text += Content.substr(CPos, FPos-CPos); - Text += '\n'; + D.Text += Content.substr(CPos, FPos-CPos); + D.Text += '\n'; CPos = FPos + NewlineStr.size(); } - if (Text.empty()) - Text.assign(ContentBegin, ContentEnd); + if (D.Text.empty()) + D.Text.assign(ContentBegin, ContentEnd); // Check that regex directives contain at least one regex. - if (RegexKind && Text.find("{{") == StringRef::npos) { - Diags.Report(Pos.getLocWithOffset(ContentBegin-PH.Begin), - diag::err_verify_missing_regex) << Text; + if (D.RegexKind && D.Text.find("{{") == StringRef::npos) { + Diags.Report(D.ContentBegin, diag::err_verify_missing_regex) << D.Text; return false; } - // Construct new directive. - std::unique_ptr<Directive> D = Directive::create( - RegexKind, Pos, ExpectedLoc, MatchAnyLine, Text, Min, Max); + if (Marker.empty()) + attachDirective(Diags, D, ExpectedLoc, MatchAnyLine); + else + Markers.addDirective(Marker, D); + FoundDirective = true; + } - std::string Error; - if (D->isValid(Error)) { - DL->push_back(std::move(D)); - FoundDirective = true; - } else { - Diags.Report(Pos.getLocWithOffset(ContentBegin-PH.Begin), - diag::err_verify_invalid_content) - << KindStr << Error; + return FoundDirective; +} + +VerifyDiagnosticConsumer::VerifyDiagnosticConsumer(DiagnosticsEngine &Diags_) + : Diags(Diags_), PrimaryClient(Diags.getClient()), + PrimaryClientOwner(Diags.takeClient()), + Buffer(new TextDiagnosticBuffer()), Markers(new MarkerTracker(Diags)), + Status(HasNoDirectives) { + if (Diags.hasSourceManager()) + setSourceManager(Diags.getSourceManager()); +} + +VerifyDiagnosticConsumer::~VerifyDiagnosticConsumer() { + assert(!ActiveSourceFiles && "Incomplete parsing of source files!"); + assert(!CurrentPreprocessor && "CurrentPreprocessor should be invalid!"); + SrcManager = nullptr; + CheckDiagnostics(); + assert(!Diags.ownsClient() && + "The VerifyDiagnosticConsumer takes over ownership of the client!"); +} + +// DiagnosticConsumer interface. + +void VerifyDiagnosticConsumer::BeginSourceFile(const LangOptions &LangOpts, + const Preprocessor *PP) { + // Attach comment handler on first invocation. + if (++ActiveSourceFiles == 1) { + if (PP) { + CurrentPreprocessor = PP; + this->LangOpts = &LangOpts; + setSourceManager(PP->getSourceManager()); + const_cast<Preprocessor *>(PP)->addCommentHandler(this); +#ifndef NDEBUG + // Debug build tracks parsed files. + const_cast<Preprocessor *>(PP)->addPPCallbacks( + llvm::make_unique<VerifyFileTracker>(*this, *SrcManager)); +#endif } } - return FoundDirective; + assert((!PP || CurrentPreprocessor == PP) && "Preprocessor changed!"); + PrimaryClient->BeginSourceFile(LangOpts, PP); +} + +void VerifyDiagnosticConsumer::EndSourceFile() { + assert(ActiveSourceFiles && "No active source files!"); + PrimaryClient->EndSourceFile(); + + // Detach comment handler once last active source file completed. + if (--ActiveSourceFiles == 0) { + if (CurrentPreprocessor) + const_cast<Preprocessor *>(CurrentPreprocessor)-> + removeCommentHandler(this); + + // Diagnose any used-but-not-defined markers. + Markers->finalize(); + + // Check diagnostics once last file completed. + CheckDiagnostics(); + CurrentPreprocessor = nullptr; + LangOpts = nullptr; + } +} + +void VerifyDiagnosticConsumer::HandleDiagnostic( + DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) { + if (Info.hasSourceManager()) { + // If this diagnostic is for a different source manager, ignore it. + if (SrcManager && &Info.getSourceManager() != SrcManager) + return; + + setSourceManager(Info.getSourceManager()); + } + +#ifndef NDEBUG + // Debug build tracks unparsed files for possible + // unparsed expected-* directives. + if (SrcManager) { + SourceLocation Loc = Info.getLocation(); + if (Loc.isValid()) { + ParsedStatus PS = IsUnparsed; + + Loc = SrcManager->getExpansionLoc(Loc); + FileID FID = SrcManager->getFileID(Loc); + + const FileEntry *FE = SrcManager->getFileEntryForID(FID); + if (FE && CurrentPreprocessor && SrcManager->isLoadedFileID(FID)) { + // If the file is a modules header file it shall not be parsed + // for expected-* directives. + HeaderSearch &HS = CurrentPreprocessor->getHeaderSearchInfo(); + if (HS.findModuleForHeader(FE)) + PS = IsUnparsedNoDirectives; + } + + UpdateParsedFileStatus(*SrcManager, FID, PS); + } + } +#endif + + // Send the diagnostic to the buffer, we will check it once we reach the end + // of the source file (or are destructed). + Buffer->HandleDiagnostic(DiagLevel, Info); } /// HandleComment - Hook into the preprocessor and extract comments containing @@ -621,7 +761,7 @@ bool VerifyDiagnosticConsumer::HandleComment(Preprocessor &PP, // Fold any "\<EOL>" sequences size_t loc = C.find('\\'); if (loc == StringRef::npos) { - ParseDirective(C, &ED, SM, &PP, CommentBegin, Status); + ParseDirective(C, &ED, SM, &PP, CommentBegin, Status, *Markers); return false; } @@ -651,7 +791,7 @@ bool VerifyDiagnosticConsumer::HandleComment(Preprocessor &PP, } if (!C2.empty()) - ParseDirective(C2, &ED, SM, &PP, CommentBegin, Status); + ParseDirective(C2, &ED, SM, &PP, CommentBegin, Status, *Markers); return false; } @@ -685,9 +825,12 @@ static bool findDirectives(SourceManager &SM, FileID FID, std::string Comment = RawLex.getSpelling(Tok, SM, LangOpts); if (Comment.empty()) continue; + // We don't care about tracking markers for this phase. + VerifyDiagnosticConsumer::MarkerTracker Markers(SM.getDiagnostics()); + // Find first directive. if (ParseDirective(Comment, nullptr, SM, nullptr, Tok.getLocation(), - Status)) + Status, Markers)) return true; } return false; |