diff options
Diffstat (limited to 'lib/Frontend')
41 files changed, 636 insertions, 503 deletions
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp index 28834a2de8..662cfd6a21 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 // //===----------------------------------------------------------------------===// // diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp index 4f622da118..b995d25441 100644 --- a/lib/Frontend/ASTMerge.cpp +++ b/lib/Frontend/ASTMerge.cpp @@ -1,9 +1,8 @@ //===-- 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" @@ -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_New(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 c7b2551cb8..221bf97c35 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" @@ -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() { @@ -759,7 +758,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 +778,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 +791,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 +1078,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 +1137,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(); @@ -1478,7 +1474,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; } @@ -1694,7 +1690,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation( if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps), PrecompilePreambleAfterNParses, - AST->FileMgr->getVirtualFileSystem())) + &AST->FileMgr->getVirtualFileSystem())) return nullptr; return AST; } @@ -1758,7 +1754,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 +1765,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 +1797,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(); @@ -1881,8 +1877,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 @@ -2215,18 +2210,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 +2232,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 @@ -2318,8 +2314,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); } diff --git a/lib/Frontend/ChainedDiagnosticConsumer.cpp b/lib/Frontend/ChainedDiagnosticConsumer.cpp index d77fd180ea..793c5ff8a2 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 1bfc25c4c7..48154ecf47 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 f666745354..9c70a70ed7 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)) { @@ -301,13 +294,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 +373,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()); @@ -490,19 +484,17 @@ 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, - getFrontendOpts().UseGlobalModuleIndex); + AllowPCHWithCompilerErrors, getPreprocessor(), getModuleCache(), + getASTContext(), getPCHContainerReader(), + getFrontendOpts().ModuleFileExtensions, TheDependencyFileGenerator.get(), + 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, @@ -512,7 +504,7 @@ IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource( 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)); @@ -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(); @@ -1031,6 +1020,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 +1083,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 +1095,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 +1242,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 +1269,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 +1469,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()); @@ -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. diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 3e6528c259..12846b18c0 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,7 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, } Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help); + Opts.ShowCheckerHelpHidden = Args.hasArg(OPT_analyzer_checker_help_hidden); Opts.ShowConfigOptionsList = Args.hasArg(OPT_analyzer_config_help); Opts.ShowEnabledCheckerList = Args.hasArg(OPT_analyzer_list_enabled_checkers); Opts.ShouldEmitErrorsOnInvalidConfigValue = @@ -422,7 +423,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"; @@ -551,7 +552,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 +589,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 +612,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); } @@ -1214,6 +1219,11 @@ 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_Rpass_EQ)) { Opts.OptimizationRemarkPattern = GenerateOptimizationRemarkRegex(Diags, Args, A); @@ -1322,6 +1332,8 @@ 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); + return Success; } @@ -1402,9 +1414,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) { @@ -1706,6 +1718,7 @@ 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.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); @@ -1894,18 +1907,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, @@ -2502,6 +2504,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 +2588,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); + 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 && @@ -2668,6 +2678,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.MaxTypeAlign = getLastArgIntValue(Args, OPT_fmax_type_align_EQ, 0, Diags); Opts.AlignDouble = Args.hasArg(OPT_malign_double); 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); @@ -2833,7 +2845,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 +2856,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 +2895,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); diff --git a/lib/Frontend/CreateInvocationFromCommandLine.cpp b/lib/Frontend/CreateInvocationFromCommandLine.cpp index 2d4c40f8b9..b62416ffd9 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 a03d4b79c8..363aff76f0 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 // //===----------------------------------------------------------------------===// // diff --git a/lib/Frontend/DependencyGraph.cpp b/lib/Frontend/DependencyGraph.cpp index c6c9ac2ea2..90624323a0 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 3bd86dc5be..22b957988f 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 f5226380b4..2f4f5ef64c 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)) { @@ -1045,6 +1044,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 a407dfc162..882d985fa0 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 // //===----------------------------------------------------------------------===// @@ -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)); @@ -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)); @@ -220,8 +221,8 @@ GenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI, 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, diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp index 0744d447e8..6ccb2c3956 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 9ea7347e77..e3f44c9999 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 9dc107c9d5..d60f5333bf 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 ac3bb713dd..d96fa81f73 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 // //===----------------------------------------------------------------------===// // @@ -433,14 +432,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); diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index 66807b097d..b0fb124251 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 // //===----------------------------------------------------------------------===// // @@ -548,7 +547,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"); } @@ -831,7 +830,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,12 +1057,17 @@ 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(); diff --git a/lib/Frontend/LangStandards.cpp b/lib/Frontend/LangStandards.cpp index 47023e58fa..05087eb41f 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 b31fbd087b..76762d58fe 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 9998f65457..4bac175539 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 fa8efcc3b5..c1d8c0d9eb 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 c6e18d9cae..ed7028769d 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 1930af187e..59467c3c41 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) { @@ -347,6 +350,8 @@ 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(); @@ -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); } @@ -743,6 +748,7 @@ void PreambleCallbacks::HandleTopLevelDecl(DeclGroupRef DG) {} std::unique_ptr<PPCallbacks> PreambleCallbacks::createPPCallbacks() { return nullptr; } +CommentHandler *PreambleCallbacks::getCommentHandler() { return nullptr; } static llvm::ManagedStatic<BuildPreambleErrorCategory> BuildPreambleErrCategory; diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index 3b835985a5..584f94db13 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(); @@ -750,6 +769,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 +799,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 1c2efe63aa..667b9f0469 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 bcf6d215c9..aaef44b79d 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 // //===----------------------------------------------------------------------===// @@ -238,7 +237,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 34ee9673cc..a5b36bc785 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 2e7baa3d95..cb4e773aca 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 ae6b51bc81..6b67ee6383 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 10ca9a7856..7b1f20408d 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 // //===----------------------------------------------------------------------===// // diff --git a/lib/Frontend/Rewrite/RewriteObjC.cpp b/lib/Frontend/Rewrite/RewriteObjC.cpp index 3e018800b9..3e50aff3c4 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 // //===----------------------------------------------------------------------===// // diff --git a/lib/Frontend/Rewrite/RewriteTest.cpp b/lib/Frontend/Rewrite/RewriteTest.cpp index b0791f4cdd..fa8232c8c3 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 22546ce4c0..754351488e 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 // //===----------------------------------------------------------------------===// diff --git a/lib/Frontend/SerializedDiagnosticReader.cpp b/lib/Frontend/SerializedDiagnosticReader.cpp index 458717819c..bb82e9ad47 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 // //===----------------------------------------------------------------------===// diff --git a/lib/Frontend/TestModuleFileExtension.cpp b/lib/Frontend/TestModuleFileExtension.cpp index 087bdc5435..561fe1012a 100644 --- a/lib/Frontend/TestModuleFileExtension.cpp +++ b/lib/Frontend/TestModuleFileExtension.cpp @@ -1,9 +1,8 @@ //===-- 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" diff --git a/lib/Frontend/TestModuleFileExtension.h b/lib/Frontend/TestModuleFileExtension.h index 41f3ca9f05..6c28e9cb68 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 diff --git a/lib/Frontend/TextDiagnostic.cpp b/lib/Frontend/TextDiagnostic.cpp index 35b99b10f9..c6ebdcaf9a 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. @@ -793,8 +791,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 +834,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 44bb2bc29b..b2497f56cb 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 a37382c116..0c0a44a138 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 21933f474f..a68ef03d4d 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; |