diff options
Diffstat (limited to 'lib/Frontend')
-rw-r--r-- | lib/Frontend/ASTUnit.cpp | 64 | ||||
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 74 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 168 | ||||
-rw-r--r-- | lib/Frontend/FrontendAction.cpp | 23 | ||||
-rw-r--r-- | lib/Frontend/FrontendActions.cpp | 26 | ||||
-rw-r--r-- | lib/Frontend/InitHeaderSearch.cpp | 1 | ||||
-rw-r--r-- | lib/Frontend/InitPreprocessor.cpp | 108 | ||||
-rw-r--r-- | lib/Frontend/MultiplexConsumer.cpp | 32 | ||||
-rw-r--r-- | lib/Frontend/PrecompiledPreamble.cpp | 261 | ||||
-rw-r--r-- | lib/Frontend/PrintPreprocessedOutput.cpp | 24 | ||||
-rw-r--r-- | lib/Frontend/Rewrite/FrontendActions.cpp | 2 | ||||
-rw-r--r-- | lib/Frontend/Rewrite/RewriteModernObjC.cpp | 2 | ||||
-rw-r--r-- | lib/Frontend/Rewrite/RewriteObjC.cpp | 2 | ||||
-rw-r--r-- | lib/Frontend/TextDiagnosticBuffer.cpp | 37 | ||||
-rw-r--r-- | lib/Frontend/VerifyDiagnosticConsumer.cpp | 143 |
15 files changed, 731 insertions, 236 deletions
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 1094e6d089a6..1160df15a920 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -243,7 +243,8 @@ static unsigned getDeclShowContexts(const NamedDecl *ND, uint64_t Contexts = 0; if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) || - isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND)) { + isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND) || + isa<TypeAliasTemplateDecl>(ND)) { // Types can appear in these contexts. if (LangOpts.CPlusPlus || !isa<TagDecl>(ND)) Contexts |= (1LL << CodeCompletionContext::CCC_TopLevel) @@ -263,8 +264,12 @@ static unsigned getDeclShowContexts(const NamedDecl *ND, Contexts |= (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver); // In Objective-C, you can only be a subclass of another Objective-C class - if (isa<ObjCInterfaceDecl>(ND)) + if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) { + // Objective-C interfaces can be used in a class property expression. + if (ID->getDefinition()) + Contexts |= (1LL << CodeCompletionContext::CCC_Expression); Contexts |= (1LL << CodeCompletionContext::CCC_ObjCInterfaceName); + } // Deal with tag names. if (isa<EnumDecl>(ND)) { @@ -542,6 +547,9 @@ private: // Initialize the ASTContext Context->InitBuiltinTypes(*Target); + // Adjust printing policy based on language options. + Context->setPrintingPolicy(PrintingPolicy(LangOpt)); + // We didn't have access to the comment options when the ASTContext was // constructed, so register them now. Context->getCommentCommandTraits().registerCommentOptions( @@ -962,9 +970,8 @@ public: } } - void HandleMacroDefined(const Token &MacroNameTok, - const MacroDirective *MD) override { - AddDefinedMacroToHash(MacroNameTok, Hash); + std::unique_ptr<PPCallbacks> createPPCallbacks() override { + return llvm::make_unique<MacroDefinitionTrackerPPCallbacks>(Hash); } private: @@ -1016,6 +1023,19 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, if (!Invocation) return true; + auto CCInvocation = std::make_shared<CompilerInvocation>(*Invocation); + if (OverrideMainBuffer) { + assert(Preamble && + "No preamble was built, but OverrideMainBuffer is not null"); + IntrusiveRefCntPtr<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); + } + } + // Create the compiler instance to use for building the AST. std::unique_ptr<CompilerInstance> Clang( new CompilerInstance(std::move(PCHContainerOps))); @@ -1030,7 +1050,7 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance> CICleanup(Clang.get()); - Clang->setInvocation(std::make_shared<CompilerInvocation>(*Invocation)); + Clang->setInvocation(CCInvocation); OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile(); // Set up diagnostics, capturing any diagnostics that would @@ -1084,9 +1104,6 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, // If the main file has been overridden due to the use of a preamble, // make that override happen and introduce the preamble. if (OverrideMainBuffer) { - assert(Preamble && "No preamble was built, but OverrideMainBuffer is not null"); - Preamble->AddImplicitPreamble(Clang->getInvocation(), OverrideMainBuffer.get()); - // The stored diagnostic has the old source manager in it; update // the locations to refer into the new source manager. Since we've // been careful to make sure that the source manager's state @@ -1275,7 +1292,7 @@ ASTUnit::getMainBufferWithPrecompiledPreamble( llvm::ErrorOr<PrecompiledPreamble> NewPreamble = PrecompiledPreamble::Build( PreambleInvocationIn, MainFileBuffer.get(), Bounds, *Diagnostics, VFS, - PCHContainerOps, Callbacks); + PCHContainerOps, /*StoreInMemory=*/false, Callbacks); if (NewPreamble) { Preamble = std::move(*NewPreamble); PreambleRebuildCounter = 1; @@ -1658,7 +1675,6 @@ ASTUnit *ASTUnit::LoadFromCommandLine( PreprocessorOptions &PPOpts = CI->getPreprocessorOpts(); PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName; PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors; - PPOpts.GeneratePreamble = PrecompilePreambleAfterNParses != 0; PPOpts.SingleFileParseMode = SingleFileParse; // Override the resources path. @@ -2152,8 +2168,16 @@ void ASTUnit::CodeComplete( // If the main file has been overridden due to the use of a preamble, // make that override happen and introduce the preamble. if (OverrideMainBuffer) { - assert(Preamble && "No preamble was built, but OverrideMainBuffer is not null"); - Preamble->AddImplicitPreamble(Clang->getInvocation(), OverrideMainBuffer.get()); + assert(Preamble && + "No preamble was built, but OverrideMainBuffer is not null"); + + auto VFS = FileMgr.getVirtualFileSystem(); + Preamble->AddImplicitPreamble(Clang->getInvocation(), VFS, + OverrideMainBuffer.get()); + // FIXME: there is no way to update VFS if it was changed by + // AddImplicitPreamble as FileMgr is accepted as a parameter by this method. + // We use on-disk preambles instead and rely on FileMgr's VFS to ensure the + // PCH files are always readable. OwnedBuffers.push_back(OverrideMainBuffer.release()); } else { PreprocessorOpts.PrecompiledPreambleBytes.first = 0; @@ -2395,7 +2419,7 @@ SourceLocation ASTUnit::getLocation(const FileEntry *File, /// \brief If \arg Loc is a loaded location from the preamble, returns /// the corresponding local location of the main file, otherwise it returns /// \arg Loc. -SourceLocation ASTUnit::mapLocationFromPreamble(SourceLocation Loc) { +SourceLocation ASTUnit::mapLocationFromPreamble(SourceLocation Loc) const { FileID PreambleID; if (SourceMgr) PreambleID = SourceMgr->getPreambleFileID(); @@ -2416,7 +2440,7 @@ SourceLocation ASTUnit::mapLocationFromPreamble(SourceLocation Loc) { /// \brief If \arg Loc is a local location of the main file but inside the /// preamble chunk, returns the corresponding loaded location from the /// preamble, otherwise it returns \arg Loc. -SourceLocation ASTUnit::mapLocationToPreamble(SourceLocation Loc) { +SourceLocation ASTUnit::mapLocationToPreamble(SourceLocation Loc) const { FileID PreambleID; if (SourceMgr) PreambleID = SourceMgr->getPreambleFileID(); @@ -2434,7 +2458,7 @@ SourceLocation ASTUnit::mapLocationToPreamble(SourceLocation Loc) { return Loc; } -bool ASTUnit::isInPreambleFileID(SourceLocation Loc) { +bool ASTUnit::isInPreambleFileID(SourceLocation Loc) const { FileID FID; if (SourceMgr) FID = SourceMgr->getPreambleFileID(); @@ -2445,7 +2469,7 @@ bool ASTUnit::isInPreambleFileID(SourceLocation Loc) { return SourceMgr->isInFileID(Loc, FID); } -bool ASTUnit::isInMainFileID(SourceLocation Loc) { +bool ASTUnit::isInMainFileID(SourceLocation Loc) const { FileID FID; if (SourceMgr) FID = SourceMgr->getMainFileID(); @@ -2456,7 +2480,7 @@ bool ASTUnit::isInMainFileID(SourceLocation Loc) { return SourceMgr->isInFileID(Loc, FID); } -SourceLocation ASTUnit::getEndOfPreambleFileID() { +SourceLocation ASTUnit::getEndOfPreambleFileID() const { FileID FID; if (SourceMgr) FID = SourceMgr->getPreambleFileID(); @@ -2467,7 +2491,7 @@ SourceLocation ASTUnit::getEndOfPreambleFileID() { return SourceMgr->getLocForEndOfFile(FID); } -SourceLocation ASTUnit::getStartOfMainFileID() { +SourceLocation ASTUnit::getStartOfMainFileID() const { FileID FID; if (SourceMgr) FID = SourceMgr->getMainFileID(); @@ -2543,7 +2567,7 @@ const FileEntry *ASTUnit::getPCHFile() { return nullptr; } -bool ASTUnit::isModuleFile() { +bool ASTUnit::isModuleFile() const { return isMainFileAST() && getLangOpts().isCompilingModule(); } diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index bb6a665cb456..32f1232bbe24 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -300,12 +300,16 @@ CompilerInstance::createDiagnostics(DiagnosticOptions *Opts, // File Manager -void CompilerInstance::createFileManager() { +FileManager *CompilerInstance::createFileManager() { if (!hasVirtualFileSystem()) { - // TODO: choose the virtual file system based on the CompilerInvocation. - setVirtualFileSystem(vfs::getRealFileSystem()); + if (IntrusiveRefCntPtr<vfs::FileSystem> VFS = + createVFSFromCompilerInvocation(getInvocation(), getDiagnostics())) + setVirtualFileSystem(VFS); + else + return nullptr; } FileMgr = new FileManager(getFileSystemOpts(), VirtualFileSystem); + return FileMgr.get(); } // Source Manager @@ -382,6 +386,7 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) { Invocation->getPreprocessorOptsPtr(), getDiagnostics(), getLangOpts(), getSourceManager(), getPCMCache(), *HeaderInfo, *this, PTHMgr, /*OwnsHeaderSearch=*/true, TUKind); + getTarget().adjust(getLangOpts()); PP->Initialize(getTarget(), getAuxTarget()); // Note that this is different then passing PTHMgr to Preprocessor's ctor. @@ -759,9 +764,15 @@ std::unique_ptr<llvm::raw_pwrite_stream> CompilerInstance::createOutputFile( if (UseTemporary) { // Create a temporary file. - SmallString<128> TempPath; - TempPath = OutFile; + // Insert -%%%%%%%% before the extension (if any), and because some tools + // (noticeable, clang's own GlobalModuleIndex.cpp) glob for build + // artifacts, also append .tmp. + StringRef OutputExtension = llvm::sys::path::extension(OutFile); + SmallString<128> TempPath = + StringRef(OutFile).drop_back(OutputExtension.size()); TempPath += "-%%%%%%%%"; + TempPath += OutputExtension; + TempPath += ".tmp"; int fd; std::error_code EC = llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath); @@ -832,8 +843,8 @@ bool CompilerInstance::InitializeSourceManager( : Input.isSystem() ? SrcMgr::C_System : SrcMgr::C_User; if (Input.isBuffer()) { - SourceMgr.setMainFileID(SourceMgr.createFileID( - std::unique_ptr<llvm::MemoryBuffer>(Input.getBuffer()), Kind)); + SourceMgr.setMainFileID(SourceMgr.createFileID(SourceManager::Unowned, + Input.getBuffer(), Kind)); assert(SourceMgr.getMainFileID().isValid() && "Couldn't establish MainFileID!"); return true; @@ -997,8 +1008,17 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { OS << " and "; if (NumErrors) OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s"); - if (NumWarnings || NumErrors) - OS << " generated.\n"; + if (NumWarnings || NumErrors) { + OS << " generated"; + if (getLangOpts().CUDA) { + if (!getLangOpts().CUDAIsDevice) { + OS << " when compiling for host"; + } else { + OS << " when compiling for " << getTargetOpts().CPU; + } + } + OS << ".\n"; + } } if (getFrontendOpts().ShowStats) { @@ -1595,7 +1615,22 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, Module::NameVisibilityKind Visibility, bool IsInclusionDirective) { // Determine what file we're searching from. - StringRef ModuleName = Path[0].first->getName(); + // FIXME: Should we be deciding whether this is a submodule (here and + // below) based on -fmodules-ts or should we pass a flag and make the + // caller decide? + std::string ModuleName; + if (getLangOpts().ModulesTS) { + // FIXME: Same code as Sema::ActOnModuleDecl() so there is probably a + // better place/way to do this. + for (auto &Piece : Path) { + if (!ModuleName.empty()) + ModuleName += "."; + ModuleName += Piece.first->getName(); + } + } + else + ModuleName = Path[0].first->getName(); + SourceLocation ModuleNameLoc = Path[0].second; // If we've already handled this import, just return the cached result. @@ -1620,6 +1655,14 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, } else if (ModuleName == getLangOpts().CurrentModule) { // This is the module we're building. Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); + /// FIXME: perhaps we should (a) look for a module using the module name + // to file map (PrebuiltModuleFiles) and (b) diagnose if still not found? + //if (Module == nullptr) { + // getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found) + // << ModuleName; + // ModuleBuildFailed = true; + // return ModuleLoadResult(); + //} Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first; } else { // Search for a module with the given name. @@ -1641,16 +1684,17 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, } // Try to load the module from the prebuilt module path. - if (Source == ModuleNotFound && !HSOpts.PrebuiltModulePaths.empty()) { - ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName( - ModuleName, "", /*UsePrebuiltPath*/ true); + if (Source == ModuleNotFound && (!HSOpts.PrebuiltModuleFiles.empty() || + !HSOpts.PrebuiltModulePaths.empty())) { + ModuleFileName = + PP->getHeaderSearchInfo().getPrebuiltModuleFileName(ModuleName); if (!ModuleFileName.empty()) Source = PrebuiltModulePath; } // Try to load the module from the module cache. if (Source == ModuleNotFound && Module) { - ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(Module); + ModuleFileName = PP->getHeaderSearchInfo().getCachedModuleFileName(Module); Source = ModuleCache; } @@ -1810,7 +1854,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, // Verify that the rest of the module path actually corresponds to // a submodule. - if (Path.size() > 1) { + if (!getLangOpts().ModulesTS && Path.size() > 1) { for (unsigned I = 1, N = Path.size(); I != N; ++I) { StringRef Name = Path[I].first->getName(); clang::Module *Sub = Module->findSubmodule(Name); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 0d0869c815d3..2e8a737de4e4 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -527,7 +527,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file); Opts.SplitDwarfInlining = !Args.hasArg(OPT_fno_split_dwarf_inlining); Opts.DebugTypeExtRefs = Args.hasArg(OPT_dwarf_ext_refs); - Opts.DebugExplicitImport = Triple.isPS4CPU(); + Opts.DebugExplicitImport = Args.hasArg(OPT_dwarf_explicit_import); + Opts.DebugFwdTemplateParams = Args.hasArg(OPT_debug_forward_template_params); for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) Opts.DebugPrefixMap.insert(StringRef(Arg).split('=')); @@ -545,6 +546,11 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, OPT_fuse_register_sized_bitfield_access); Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing); Opts.StructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa); + Opts.NewStructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa) && + Args.hasArg(OPT_new_struct_path_tbaa); + Opts.FineGrainedBitfieldAccesses = + Args.hasFlag(OPT_ffine_grained_bitfield_accesses, + OPT_fno_fine_grained_bitfield_accesses, false); Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags); Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants); Opts.NoCommon = Args.hasArg(OPT_fno_common); @@ -564,6 +570,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.SampleProfileFile = Args.getLastArgValue(OPT_fprofile_sample_use_EQ); Opts.DebugInfoForProfiling = Args.hasFlag( OPT_fdebug_info_for_profiling, OPT_fno_debug_info_for_profiling, false); + Opts.GnuPubnames = Args.hasArg(OPT_ggnu_pubnames); setPGOInstrumentor(Opts, Args, Diags); Opts.InstrProfileOutput = @@ -632,9 +639,11 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Args.hasArg(OPT_cl_no_signed_zeros) || Args.hasArg(OPT_cl_unsafe_math_optimizations) || Args.hasArg(OPT_cl_fast_relaxed_math)); + Opts.Reassociate = Args.hasArg(OPT_mreassociate); Opts.FlushDenorm = Args.hasArg(OPT_cl_denorms_are_zero); Opts.CorrectlyRoundedDivSqrt = Args.hasArg(OPT_cl_fp32_correctly_rounded_divide_sqrt); + Opts.Reciprocals = Args.getAllArgValues(OPT_mrecip_EQ); Opts.ReciprocalMath = Args.hasArg(OPT_freciprocal_math); Opts.NoTrappingMath = Args.hasArg(OPT_fno_trapping_math); Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss); @@ -648,6 +657,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Args.hasArg(OPT_mincremental_linker_compatible); Opts.PIECopyRelocations = Args.hasArg(OPT_mpie_copy_relocations); + Opts.NoPLT = Args.hasArg(OPT_fno_plt); Opts.OmitLeafFramePointer = Args.hasArg(OPT_momit_leaf_frame_pointer); Opts.SaveTempLabels = Args.hasArg(OPT_msave_temp_labels); Opts.NoDwarfDirectoryAsm = Args.hasArg(OPT_fno_dwarf_directory_asm); @@ -679,6 +689,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.NoUseJumpTables = Args.hasArg(OPT_fno_jump_tables); + Opts.ProfileSampleAccurate = Args.hasArg(OPT_fprofile_sample_accurate); + Opts.PrepareForLTO = Args.hasArg(OPT_flto, OPT_flto_EQ); Opts.EmitSummaryIndex = false; if (Arg *A = Args.getLastArg(OPT_flto_EQ)) { @@ -702,6 +714,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.VectorizeLoop = Args.hasArg(OPT_vectorize_loops); Opts.VectorizeSLP = Args.hasArg(OPT_vectorize_slp); + Opts.PreferVectorWidth = Args.getLastArgValue(OPT_mprefer_vector_width_EQ); + Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name); Opts.VerifyModule = !Args.hasArg(OPT_disable_llvm_verifier); @@ -769,7 +783,13 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.PreserveVec3Type = Args.hasArg(OPT_fpreserve_vec3_type); Opts.InstrumentFunctions = Args.hasArg(OPT_finstrument_functions); + Opts.InstrumentFunctionsAfterInlining = + Args.hasArg(OPT_finstrument_functions_after_inlining); + Opts.InstrumentFunctionEntryBare = + Args.hasArg(OPT_finstrument_function_entry_bare); Opts.XRayInstrumentFunctions = Args.hasArg(OPT_fxray_instrument); + Opts.XRayAlwaysEmitCustomEvents = + Args.hasArg(OPT_fxray_always_emit_customevents); Opts.XRayInstructionThreshold = getLastArgIntValue(Args, OPT_fxray_instruction_threshold_EQ, 200, Diags); Opts.InstrumentForProfiling = Args.hasArg(OPT_pg); @@ -821,11 +841,19 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.SanitizeCoverageNoPrune = Args.hasArg(OPT_fsanitize_coverage_no_prune); Opts.SanitizeCoverageInline8bitCounters = Args.hasArg(OPT_fsanitize_coverage_inline_8bit_counters); + Opts.SanitizeCoveragePCTable = Args.hasArg(OPT_fsanitize_coverage_pc_table); + Opts.SanitizeCoverageStackDepth = + Args.hasArg(OPT_fsanitize_coverage_stack_depth); Opts.SanitizeMemoryTrackOrigins = getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags); Opts.SanitizeMemoryUseAfterDtor = - Args.hasArg(OPT_fsanitize_memory_use_after_dtor); + Args.hasFlag(OPT_fsanitize_memory_use_after_dtor, + OPT_fno_sanitize_memory_use_after_dtor, + false); + Opts.SanitizeMinimalRuntime = Args.hasArg(OPT_fsanitize_minimal_runtime); Opts.SanitizeCfiCrossDso = Args.hasArg(OPT_fsanitize_cfi_cross_dso); + Opts.SanitizeCfiICallGeneralizePointers = + Args.hasArg(OPT_fsanitize_cfi_icall_generalize_pointers); Opts.SanitizeStats = Args.hasArg(OPT_fsanitize_stats); if (Arg *A = Args.getLastArg(OPT_fsanitize_address_use_after_scope, OPT_fno_sanitize_address_use_after_scope)) { @@ -1003,9 +1031,12 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts, // They won't be discovered by the regular preprocessor, so // we let make / ninja to know about this implicit dependency. Opts.ExtraDeps = Args.getAllArgValues(OPT_fdepfile_entry); - auto ModuleFiles = Args.getAllArgValues(OPT_fmodule_file); - Opts.ExtraDeps.insert(Opts.ExtraDeps.end(), ModuleFiles.begin(), - ModuleFiles.end()); + // Only the -fmodule-file=<file> form. + for (const Arg *A : Args.filtered(OPT_fmodule_file)) { + StringRef Val = A->getValue(); + if (Val.find('=') == StringRef::npos) + Opts.ExtraDeps.push_back(Val); + } } static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) { @@ -1041,6 +1072,26 @@ static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) { llvm::sys::Process::StandardErrHasColors()); } +static bool checkVerifyPrefixes(const std::vector<std::string> &VerifyPrefixes, + DiagnosticsEngine *Diags) { + bool Success = true; + 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 != '_';}); + if (BadChar != Prefix.end() || !isLetter(Prefix[0])) { + Success = false; + if (Diags) { + Diags->Report(diag::err_drv_invalid_value) << "-verify=" << Prefix; + Diags->Report(diag::note_drv_verify_prefix_spelling); + } + } + } + return Success; +} + bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, DiagnosticsEngine *Diags, bool DefaultDiagColor, bool DefaultShowOpt) { @@ -1128,7 +1179,18 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info); Opts.ShowParseableFixits = Args.hasArg(OPT_fdiagnostics_parseable_fixits); Opts.ShowPresumedLoc = !Args.hasArg(OPT_fno_diagnostics_use_presumed_location); - Opts.VerifyDiagnostics = Args.hasArg(OPT_verify); + Opts.VerifyDiagnostics = Args.hasArg(OPT_verify) || Args.hasArg(OPT_verify_EQ); + Opts.VerifyPrefixes = Args.getAllArgValues(OPT_verify_EQ); + if (Args.hasArg(OPT_verify)) + Opts.VerifyPrefixes.push_back("expected"); + // Keep VerifyPrefixes in its original order for the sake of diagnostics, and + // then sort it to prepare for fast lookup using std::binary_search. + if (!checkVerifyPrefixes(Opts.VerifyPrefixes, Diags)) { + Opts.VerifyDiagnostics = false; + Success = false; + } + else + std::sort(Opts.VerifyPrefixes.begin(), Opts.VerifyPrefixes.end()); DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None; Success &= parseDiagnosticLevelMask("-verify-ignore-unexpected=", Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ), @@ -1334,7 +1396,12 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.UseGlobalModuleIndex = !Args.hasArg(OPT_fno_modules_global_index); Opts.GenerateGlobalModuleIndex = Opts.UseGlobalModuleIndex; Opts.ModuleMapFiles = Args.getAllArgValues(OPT_fmodule_map_file); - Opts.ModuleFiles = Args.getAllArgValues(OPT_fmodule_file); + // Only the -fmodule-file=<file> form. + for (const Arg *A : Args.filtered(OPT_fmodule_file)) { + StringRef Val = A->getValue(); + if (Val.find('=') == StringRef::npos) + Opts.ModuleFiles.push_back(Val); + } Opts.ModulesEmbedFiles = Args.getAllArgValues(OPT_fmodules_embed_file_EQ); Opts.ModulesEmbedAllFiles = Args.hasArg(OPT_fmodules_embed_all_files); Opts.IncludeTimestamps = !Args.hasArg(OPT_fno_pch_timestamp); @@ -1345,6 +1412,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, = Args.hasArg(OPT_code_completion_patterns); Opts.CodeCompleteOpts.IncludeGlobals = !Args.hasArg(OPT_no_code_completion_globals); + Opts.CodeCompleteOpts.IncludeNamespaceLevelDecls + = !Args.hasArg(OPT_no_code_completion_ns_level_decls); Opts.CodeCompleteOpts.IncludeBriefComments = Args.hasArg(OPT_code_completion_brief_comments); @@ -1538,6 +1607,12 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, Opts.ModuleCachePath = P.str(); Opts.ModuleUserBuildPath = Args.getLastArgValue(OPT_fmodules_user_build_path); + // Only the -fmodule-file=<name>=<file> form. + for (const Arg *A : Args.filtered(OPT_fmodule_file)) { + StringRef Val = A->getValue(); + if (Val.find('=') != StringRef::npos) + Opts.PrebuiltModuleFiles.insert(Val.split('=')); + } for (const Arg *A : Args.filtered(OPT_fprebuilt_module_path)) Opts.AddPrebuiltModulePath(A->getValue()); Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash); @@ -1690,11 +1765,7 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, break; case InputKind::CXX: case InputKind::ObjCXX: - // The PS4 uses C++11 as the default C++ standard. - if (T.isPS4()) - LangStd = LangStandard::lang_gnucxx11; - else - LangStd = LangStandard::lang_gnucxx98; + LangStd = LangStandard::lang_gnucxx14; break; case InputKind::RenderScript: LangStd = LangStandard::lang_c99; @@ -1706,10 +1777,11 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, Opts.LineComment = Std.hasLineComments(); Opts.C99 = Std.isC99(); Opts.C11 = Std.isC11(); + Opts.C17 = Std.isC17(); Opts.CPlusPlus = Std.isCPlusPlus(); Opts.CPlusPlus11 = Std.isCPlusPlus11(); Opts.CPlusPlus14 = Std.isCPlusPlus14(); - Opts.CPlusPlus1z = Std.isCPlusPlus1z(); + Opts.CPlusPlus17 = Std.isCPlusPlus17(); Opts.CPlusPlus2a = Std.isCPlusPlus2a(); Opts.Digraphs = Std.hasDigraphs(); Opts.GNUMode = Std.isGNUMode(); @@ -1765,7 +1837,7 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, Opts.GNUKeywords = Opts.GNUMode; Opts.CXXOperatorNames = Opts.CPlusPlus; - Opts.AlignedAllocation = Opts.CPlusPlus1z; + Opts.AlignedAllocation = Opts.CPlusPlus17; Opts.DollarIdents = !Opts.AsmPreprocessor; } @@ -2084,7 +2156,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs // is specified, or -std is set to a conforming mode. // Trigraphs are disabled by default in c++1z onwards. - Opts.Trigraphs = !Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus1z; + Opts.Trigraphs = !Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17; Opts.Trigraphs = Args.hasFlag(OPT_ftrigraphs, OPT_fno_trigraphs, Opts.Trigraphs); @@ -2104,7 +2176,18 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.Exceptions = Args.hasArg(OPT_fexceptions); Opts.ObjCExceptions = Args.hasArg(OPT_fobjc_exceptions); Opts.CXXExceptions = Args.hasArg(OPT_fcxx_exceptions); - Opts.SjLjExceptions = Args.hasArg(OPT_fsjlj_exceptions); + + // Handle exception personalities + Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions, + options::OPT_fseh_exceptions, + options::OPT_fdwarf_exceptions); + if (A) { + const Option &Opt = A->getOption(); + Opts.SjLjExceptions = Opt.matches(options::OPT_fsjlj_exceptions); + Opts.SEHExceptions = Opt.matches(options::OPT_fseh_exceptions); + Opts.DWARFExceptions = Opt.matches(options::OPT_fdwarf_exceptions); + } + Opts.ExternCNoUnwind = Args.hasArg(OPT_fexternc_nounwind); Opts.TraditionalCPP = Args.hasArg(OPT_traditional_cpp); @@ -2114,6 +2197,12 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, && Opts.OpenCLVersion >= 200); Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional); Opts.CoroutinesTS = 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.ModulesTS = Args.hasArg(OPT_fmodules_ts); Opts.Modules = Args.hasArg(OPT_fmodules) || Opts.ModulesTS; Opts.ModulesStrictDeclUse = Args.hasArg(OPT_fmodules_strict_decluse); @@ -2130,7 +2219,16 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.ImplicitModules = !Args.hasArg(OPT_fno_implicit_modules); Opts.CharIsSigned = Opts.OpenCL || !Args.hasArg(OPT_fno_signed_char); Opts.WChar = Opts.CPlusPlus && !Args.hasArg(OPT_fno_wchar); - Opts.ShortWChar = Args.hasFlag(OPT_fshort_wchar, OPT_fno_short_wchar, false); + if (const Arg *A = Args.getLastArg(OPT_fwchar_type_EQ)) { + Opts.WCharSize = llvm::StringSwitch<unsigned>(A->getValue()) + .Case("char", 1) + .Case("short", 2) + .Case("int", 4) + .Default(0); + if (Opts.WCharSize == 0) + Diags.Report(diag::err_fe_invalid_wchar_type) << A->getValue(); + } + Opts.WCharIsSigned = Args.hasFlag(OPT_fsigned_wchar, OPT_fno_signed_wchar, true); Opts.ShortEnums = Args.hasArg(OPT_fshort_enums); Opts.Freestanding = Args.hasArg(OPT_ffreestanding); Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; @@ -2266,12 +2364,12 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, // Check for MS default calling conventions being specified. if (Arg *A = Args.getLastArg(OPT_fdefault_calling_conv_EQ)) { LangOptions::DefaultCallingConvention DefaultCC = - llvm::StringSwitch<LangOptions::DefaultCallingConvention>( - A->getValue()) + llvm::StringSwitch<LangOptions::DefaultCallingConvention>(A->getValue()) .Case("cdecl", LangOptions::DCC_CDecl) .Case("fastcall", LangOptions::DCC_FastCall) .Case("stdcall", LangOptions::DCC_StdCall) .Case("vectorcall", LangOptions::DCC_VectorCall) + .Case("regcall", LangOptions::DCC_RegCall) .Default(LangOptions::DCC_None); if (DefaultCC == LangOptions::DCC_None) Diags.Report(diag::err_drv_invalid_value) @@ -2282,7 +2380,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, bool emitError = (DefaultCC == LangOptions::DCC_FastCall || DefaultCC == LangOptions::DCC_StdCall) && Arch != llvm::Triple::x86; - emitError |= DefaultCC == LangOptions::DCC_VectorCall && + emitError |= (DefaultCC == LangOptions::DCC_VectorCall || + DefaultCC == LangOptions::DCC_RegCall) && !(Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64); if (emitError) Diags.Report(diag::err_drv_argument_not_allowed_with) @@ -2334,13 +2433,27 @@ 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. + if (Opts.OpenMPIsDevice && T.isNVPTX()) { + Opts.Exceptions = 0; + Opts.CXXExceptions = 0; + } + // Get the OpenMP target triples if any. if (Arg *A = Args.getLastArg(options::OPT_fopenmp_targets_EQ)) { for (unsigned i = 0; i < A->getNumValues(); ++i) { llvm::Triple TT(A->getValue(i)); - if (TT.getArch() == llvm::Triple::UnknownArch) + if (TT.getArch() == llvm::Triple::UnknownArch || + !(TT.getArch() == llvm::Triple::ppc || + TT.getArch() == llvm::Triple::ppc64 || + TT.getArch() == llvm::Triple::ppc64le || + TT.getArch() == llvm::Triple::nvptx || + TT.getArch() == llvm::Triple::nvptx64 || + TT.getArch() == llvm::Triple::x86 || + TT.getArch() == llvm::Triple::x86_64)) Diags.Report(clang::diag::err_drv_invalid_omp_target) << A->getValue(i); else Opts.OMPTargetTriples.push_back(TT); @@ -2425,6 +2538,11 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.XRayInstrument = Args.hasFlag(OPT_fxray_instrument, OPT_fnoxray_instrument, false); + // -fxray-always-emit-customevents + Opts.XRayAlwaysEmitCustomEvents = + Args.hasFlag(OPT_fxray_always_emit_customevents, + OPT_fnoxray_always_emit_customevents, false); + // -fxray-{always,never}-instrument= filenames. Opts.XRayAlwaysInstrumentFiles = Args.getAllArgValues(OPT_fxray_always_instrument); @@ -2603,7 +2721,6 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args, Opts.FeaturesAsWritten = Args.getAllArgValues(OPT_target_feature); Opts.LinkerVersion = Args.getLastArgValue(OPT_target_linker_version); Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple)); - Opts.Reciprocals = Args.getAllArgValues(OPT_mrecip_EQ); // Use the default target triple if unspecified. if (Opts.Triple.empty()) Opts.Triple = llvm::sys::getDefaultTargetTriple(); @@ -2710,6 +2827,13 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, if (Arch == llvm::Triple::spir || Arch == llvm::Triple::spir64) { Res.getDiagnosticOpts().Warnings.push_back("spir-compat"); } + + // If sanitizer is enabled, disable OPT_ffine_grained_bitfield_accesses. + if (Res.getCodeGenOpts().FineGrainedBitfieldAccesses && + !Res.getLangOpts()->Sanitize.empty()) { + Res.getCodeGenOpts().FineGrainedBitfieldAccesses = false; + Diags.Report(diag::warn_drv_fine_grained_bitfield_accesses_ignored); + } return Success; } diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp index 704d51509851..12226b231417 100644 --- a/lib/Frontend/FrontendAction.cpp +++ b/lib/Frontend/FrontendAction.cpp @@ -633,18 +633,12 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, return true; } - if (!CI.hasVirtualFileSystem()) { - if (IntrusiveRefCntPtr<vfs::FileSystem> VFS = - createVFSFromCompilerInvocation(CI.getInvocation(), - CI.getDiagnostics())) - CI.setVirtualFileSystem(VFS); - else + // Set up the file and source managers, if needed. + if (!CI.hasFileManager()) { + if (!CI.createFileManager()) { goto failure; + } } - - // Set up the file and source managers, if needed. - if (!CI.hasFileManager()) - CI.createFileManager(); if (!CI.hasSourceManager()) CI.createSourceManager(CI.getFileManager()); @@ -754,10 +748,11 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, goto failure; // Reinitialize the main file entry to refer to the new input. - if (!CI.InitializeSourceManager(FrontendInputFile( - Buffer.release(), Input.getKind().withFormat(InputKind::Source), - CurrentModule->IsSystem))) - goto failure; + auto Kind = CurrentModule->IsSystem ? SrcMgr::C_System : SrcMgr::C_User; + auto &SourceMgr = CI.getSourceManager(); + auto BufferID = SourceMgr.createFileID(std::move(Buffer), Kind); + assert(BufferID.isValid() && "couldn't creaate module buffer ID"); + SourceMgr.setMainFileID(BufferID); } } diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index d42400183a43..ffa5b410d2d8 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -80,9 +80,12 @@ DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI, std::unique_ptr<ASTConsumer> GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { std::string Sysroot; + if (!ComputeASTConsumerArguments(CI, /*ref*/ Sysroot)) + return nullptr; + std::string OutputFile; std::unique_ptr<raw_pwrite_stream> OS = - ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile); + CreateOutputFile(CI, InFile, /*ref*/ OutputFile); if (!OS) return nullptr; @@ -103,17 +106,20 @@ GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { return llvm::make_unique<MultiplexConsumer>(std::move(Consumers)); } -std::unique_ptr<raw_pwrite_stream> -GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI, - StringRef InFile, - std::string &Sysroot, - std::string &OutputFile) { +bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI, + std::string &Sysroot) { Sysroot = CI.getHeaderSearchOpts().Sysroot; if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) { CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot); - return nullptr; + return false; } + return true; +} + +std::unique_ptr<llvm::raw_pwrite_stream> +GeneratePCHAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile, + std::string &OutputFile) { // We use createOutputFile here because this is exposed via libclang, and we // must disable the RemoveFileOnSignal behavior. // We use a temporary to avoid race conditions. @@ -185,8 +191,8 @@ GenerateModuleFromModuleMapAction::CreateOutputFile(CompilerInstance &CI, HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); CI.getFrontendOpts().OutputFile = - HS.getModuleFileName(CI.getLangOpts().CurrentModule, ModuleMapFile, - /*UsePrebuiltPath=*/false); + HS.getCachedModuleFileName(CI.getLangOpts().CurrentModule, + ModuleMapFile); } // We use createOutputFile here because this is exposed via libclang, and we @@ -591,7 +597,7 @@ void PrintPreambleAction::ExecuteAction() { auto Buffer = CI.getFileManager().getBufferForFile(getCurrentFile()); if (Buffer) { unsigned Preamble = - Lexer::ComputePreamble((*Buffer)->getBuffer(), CI.getLangOpts()).first; + Lexer::ComputePreamble((*Buffer)->getBuffer(), CI.getLangOpts()).Size; llvm::outs().write((*Buffer)->getBufferStart(), Preamble); } } diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index 1d7c8a0c871b..8c6faced76ac 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -213,7 +213,6 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, case llvm::Triple::FreeBSD: case llvm::Triple::NetBSD: case llvm::Triple::OpenBSD: - case llvm::Triple::Bitrig: case llvm::Triple::NaCl: case llvm::Triple::PS4: case llvm::Triple::ELFIAMCU: diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index 92d61369b40f..d39890494323 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -14,6 +14,7 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/MacroBuilder.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/SyncScope.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Version.h" #include "clang/Frontend/FrontendDiagnostic.h" @@ -109,9 +110,11 @@ static void AddImplicitIncludePCH(MacroBuilder &Builder, Preprocessor &PP, /// PickFP - This is used to pick a value based on the FP semantics of the /// specified FP model. template <typename T> -static T PickFP(const llvm::fltSemantics *Sem, T IEEESingleVal, +static T PickFP(const llvm::fltSemantics *Sem, T IEEEHalfVal, T IEEESingleVal, T IEEEDoubleVal, T X87DoubleExtendedVal, T PPCDoubleDoubleVal, T IEEEQuadVal) { + if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::IEEEhalf()) + return IEEEHalfVal; if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::IEEEsingle()) return IEEESingleVal; if (Sem == (const llvm::fltSemantics*)&llvm::APFloat::IEEEdouble()) @@ -127,26 +130,26 @@ static T PickFP(const llvm::fltSemantics *Sem, T IEEESingleVal, static void DefineFloatMacros(MacroBuilder &Builder, StringRef Prefix, const llvm::fltSemantics *Sem, StringRef Ext) { const char *DenormMin, *Epsilon, *Max, *Min; - DenormMin = PickFP(Sem, "1.40129846e-45", "4.9406564584124654e-324", - "3.64519953188247460253e-4951", + DenormMin = PickFP(Sem, "5.9604644775390625e-8", "1.40129846e-45", + "4.9406564584124654e-324", "3.64519953188247460253e-4951", "4.94065645841246544176568792868221e-324", "6.47517511943802511092443895822764655e-4966"); - int Digits = PickFP(Sem, 6, 15, 18, 31, 33); - int DecimalDigits = PickFP(Sem, 9, 17, 21, 33, 36); - Epsilon = PickFP(Sem, "1.19209290e-7", "2.2204460492503131e-16", - "1.08420217248550443401e-19", + int Digits = PickFP(Sem, 3, 6, 15, 18, 31, 33); + int DecimalDigits = PickFP(Sem, 5, 9, 17, 21, 33, 36); + Epsilon = PickFP(Sem, "9.765625e-4", "1.19209290e-7", + "2.2204460492503131e-16", "1.08420217248550443401e-19", "4.94065645841246544176568792868221e-324", "1.92592994438723585305597794258492732e-34"); - int MantissaDigits = PickFP(Sem, 24, 53, 64, 106, 113); - int Min10Exp = PickFP(Sem, -37, -307, -4931, -291, -4931); - int Max10Exp = PickFP(Sem, 38, 308, 4932, 308, 4932); - int MinExp = PickFP(Sem, -125, -1021, -16381, -968, -16381); - int MaxExp = PickFP(Sem, 128, 1024, 16384, 1024, 16384); - Min = PickFP(Sem, "1.17549435e-38", "2.2250738585072014e-308", + int MantissaDigits = PickFP(Sem, 11, 24, 53, 64, 106, 113); + int Min10Exp = PickFP(Sem, -13, -37, -307, -4931, -291, -4931); + int Max10Exp = PickFP(Sem, 4, 38, 308, 4932, 308, 4932); + int MinExp = PickFP(Sem, -14, -125, -1021, -16381, -968, -16381); + int MaxExp = PickFP(Sem, 15, 128, 1024, 16384, 1024, 16384); + Min = PickFP(Sem, "6.103515625e-5", "1.17549435e-38", "2.2250738585072014e-308", "3.36210314311209350626e-4932", "2.00416836000897277799610805135016e-292", "3.36210314311209350626267781732175260e-4932"); - Max = PickFP(Sem, "3.40282347e+38", "1.7976931348623157e+308", + Max = PickFP(Sem, "6.5504e+4", "3.40282347e+38", "1.7976931348623157e+308", "1.18973149535723176502e+4932", "1.79769313486231580793728971405301e+308", "1.18973149535723176508575932662800702e+4932"); @@ -190,7 +193,7 @@ static void DefineTypeSize(const Twine &MacroName, unsigned TypeWidth, /// the width, suffix, and signedness of the given type static void DefineTypeSize(const Twine &MacroName, TargetInfo::IntType Ty, const TargetInfo &TI, MacroBuilder &Builder) { - DefineTypeSize(MacroName, TI.getTypeWidth(Ty), TI.getTypeConstantSuffix(Ty), + DefineTypeSize(MacroName, TI.getTypeWidth(Ty), TI.getTypeConstantSuffix(Ty), TI.isTypeSigned(Ty), Builder); } @@ -300,25 +303,25 @@ static const char *getLockFreeValue(unsigned TypeWidth, unsigned TypeAlign, /// \brief Add definitions required for a smooth interaction between /// Objective-C++ automated reference counting and libstdc++ (4.2). -static void AddObjCXXARCLibstdcxxDefines(const LangOptions &LangOpts, +static void AddObjCXXARCLibstdcxxDefines(const LangOptions &LangOpts, MacroBuilder &Builder) { Builder.defineMacro("_GLIBCXX_PREDEFINED_OBJC_ARC_IS_SCALAR"); - + std::string Result; { - // Provide specializations for the __is_scalar type trait so that + // Provide specializations for the __is_scalar type trait so that // lifetime-qualified objects are not considered "scalar" types, which // libstdc++ uses as an indicator of the presence of trivial copy, assign, // default-construct, and destruct semantics (none of which hold for // lifetime-qualified objects in ARC). llvm::raw_string_ostream Out(Result); - + Out << "namespace std {\n" << "\n" << "struct __true_type;\n" << "struct __false_type;\n" << "\n"; - + Out << "template<typename _Tp> struct __is_scalar;\n" << "\n"; @@ -330,7 +333,7 @@ static void AddObjCXXARCLibstdcxxDefines(const LangOptions &LangOpts, << "};\n" << "\n"; } - + if (LangOpts.ObjCWeak) { Out << "template<typename _Tp>\n" << "struct __is_scalar<__attribute__((objc_ownership(weak))) _Tp> {\n" @@ -339,7 +342,7 @@ static void AddObjCXXARCLibstdcxxDefines(const LangOptions &LangOpts, << "};\n" << "\n"; } - + if (LangOpts.ObjCAutoRefCount) { Out << "template<typename _Tp>\n" << "struct __is_scalar<__attribute__((objc_ownership(autoreleasing)))" @@ -349,7 +352,7 @@ static void AddObjCXXARCLibstdcxxDefines(const LangOptions &LangOpts, << "};\n" << "\n"; } - + Out << "}\n"; } Builder.append(Result); @@ -367,7 +370,9 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, Builder.defineMacro("__STDC_HOSTED__"); if (!LangOpts.CPlusPlus) { - if (LangOpts.C11) + if (LangOpts.C17) + Builder.defineMacro("__STDC_VERSION__", "201710L"); + else if (LangOpts.C11) Builder.defineMacro("__STDC_VERSION__", "201112L"); else if (LangOpts.C99) Builder.defineMacro("__STDC_VERSION__", "199901L"); @@ -380,7 +385,7 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, // C++17 [cpp.predefined]p1: // The name __cplusplus is defined to the value 201703L when compiling a // C++ translation unit. - else if (LangOpts.CPlusPlus1z) + else if (LangOpts.CPlusPlus17) Builder.defineMacro("__cplusplus", "201703L"); // C++1y [cpp.predefined]p1: // The name __cplusplus is defined to the value 201402L when compiling a @@ -480,12 +485,12 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts, Builder.defineMacro("__cpp_user_defined_literals", "200809"); Builder.defineMacro("__cpp_lambdas", "200907"); Builder.defineMacro("__cpp_constexpr", - LangOpts.CPlusPlus1z ? "201603" : + LangOpts.CPlusPlus17 ? "201603" : LangOpts.CPlusPlus14 ? "201304" : "200704"); Builder.defineMacro("__cpp_range_based_for", - LangOpts.CPlusPlus1z ? "201603" : "200907"); + LangOpts.CPlusPlus17 ? "201603" : "200907"); Builder.defineMacro("__cpp_static_assert", - LangOpts.CPlusPlus1z ? "201411" : "200410"); + LangOpts.CPlusPlus17 ? "201411" : "200410"); Builder.defineMacro("__cpp_decltype", "200707"); Builder.defineMacro("__cpp_attributes", "200809"); Builder.defineMacro("__cpp_rvalue_references", "200610"); @@ -515,7 +520,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts, Builder.defineMacro("__cpp_sized_deallocation", "201309"); // C++17 features. - if (LangOpts.CPlusPlus1z) { + if (LangOpts.CPlusPlus17) { Builder.defineMacro("__cpp_hex_float", "201603"); Builder.defineMacro("__cpp_inline_variables", "201606"); Builder.defineMacro("__cpp_noexcept_function_type", "201510"); @@ -556,7 +561,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI, Builder.defineMacro("__clang_patchlevel__", TOSTR(CLANG_VERSION_PATCHLEVEL)); #undef TOSTR #undef TOSTR2 - Builder.defineMacro("__clang_version__", + Builder.defineMacro("__clang_version__", "\"" CLANG_VERSION_STRING " " + getClangFullRepositoryVersion() + "\""); if (!LangOpts.MSVCCompat) { @@ -576,13 +581,27 @@ static void InitializePredefinedMacros(const TargetInfo &TI, Builder.defineMacro("__ATOMIC_ACQ_REL", "4"); Builder.defineMacro("__ATOMIC_SEQ_CST", "5"); + // Define macros for the OpenCL memory scope. + // The values should match AtomicScopeOpenCLModel::ID enum. + static_assert( + static_cast<unsigned>(AtomicScopeOpenCLModel::WorkGroup) == 1 && + static_cast<unsigned>(AtomicScopeOpenCLModel::Device) == 2 && + static_cast<unsigned>(AtomicScopeOpenCLModel::AllSVMDevices) == 3 && + static_cast<unsigned>(AtomicScopeOpenCLModel::SubGroup) == 4, + "Invalid OpenCL memory scope enum definition"); + Builder.defineMacro("__OPENCL_MEMORY_SCOPE_WORK_ITEM", "0"); + Builder.defineMacro("__OPENCL_MEMORY_SCOPE_WORK_GROUP", "1"); + Builder.defineMacro("__OPENCL_MEMORY_SCOPE_DEVICE", "2"); + Builder.defineMacro("__OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES", "3"); + Builder.defineMacro("__OPENCL_MEMORY_SCOPE_SUB_GROUP", "4"); + // Support for #pragma redefine_extname (Sun compatibility) Builder.defineMacro("__PRAGMA_REDEFINE_EXTNAME", "1"); // As sad as it is, enough software depends on the __VERSION__ for version // checks that it is necessary to report 4.2.1 (the base GCC version we claim // compatibility with) first. - Builder.defineMacro("__VERSION__", "\"4.2.1 Compatible " + + Builder.defineMacro("__VERSION__", "\"4.2.1 Compatible " + Twine(getClangFullCPPVersion()) + "\""); // Initialize language-specific preprocessor defines. @@ -597,7 +616,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI, if (LangOpts.ObjC1) { if (LangOpts.ObjCRuntime.isNonFragile()) { Builder.defineMacro("__OBJC2__"); - + if (LangOpts.ObjCExceptions) Builder.defineMacro("OBJC_ZEROCOST_EXCEPTIONS"); } @@ -660,8 +679,14 @@ static void InitializePredefinedMacros(const TargetInfo &TI, Builder.defineMacro("__EXCEPTIONS"); if (!LangOpts.MSVCCompat && LangOpts.RTTI) Builder.defineMacro("__GXX_RTTI"); + if (LangOpts.SjLjExceptions) Builder.defineMacro("__USING_SJLJ_EXCEPTIONS__"); + else if (LangOpts.SEHExceptions) + Builder.defineMacro("__SEH__"); + else if (LangOpts.DWARFExceptions && + (TI.getTriple().isThumb() || TI.getTriple().isARM())) + Builder.defineMacro("__ARM_DWARF_EH__"); if (LangOpts.Deprecated) Builder.defineMacro("__DEPRECATED"); @@ -728,6 +753,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI, DefineTypeSize("__LONG_MAX__", TargetInfo::SignedLong, TI, Builder); DefineTypeSize("__LONG_LONG_MAX__", TargetInfo::SignedLongLong, TI, Builder); DefineTypeSize("__WCHAR_MAX__", TI.getWCharType(), TI, Builder); + DefineTypeSize("__WINT_MAX__", TI.getWIntType(), TI, Builder); DefineTypeSize("__INTMAX_MAX__", TI.getIntMaxType(), TI, Builder); DefineTypeSize("__SIZE_MAX__", TI.getSizeType(), TI, Builder); @@ -787,9 +813,14 @@ 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"); DefineFloatMacros(Builder, "FLT", &TI.getFloatFormat(), "F"); DefineFloatMacros(Builder, "DBL", &TI.getDoubleFormat(), ""); DefineFloatMacros(Builder, "LDBL", &TI.getLongDoubleFormat(), "L"); + if (TI.hasFloat128Type()) + // FIXME: Switch away from the non-standard "Q" when we can + DefineFloatMacros(Builder, "FLT128", &TI.getFloat128Format(), "Q"); + // Define a __POINTER_WIDTH__ macro for stdint.h. Builder.defineMacro("__POINTER_WIDTH__", @@ -969,6 +1000,11 @@ static void InitializePredefinedMacros(const TargetInfo &TI, Builder.defineMacro("__nullable", "_Nullable"); } + // Add a macro to differentiate between regular iOS/tvOS/watchOS targets and + // the corresponding simulator targets. + if (TI.getTriple().isOSDarwin() && TI.getTriple().isSimulatorEnvironment()) + Builder.defineMacro("__APPLE_EMBEDDED_SIMULATOR__", "1"); + // OpenMP definition // OpenMP 2.2: // In implementations that support a preprocessor, the _OPENMP @@ -1010,6 +1046,10 @@ static void InitializePredefinedMacros(const TargetInfo &TI, LangOpts.OpenCLVersion)) \ Builder.defineMacro(#Ext); #include "clang/Basic/OpenCLExtensions.def" + + auto Arch = TI.getTriple().getArch(); + if (Arch == llvm::Triple::spir || Arch == llvm::Triple::spir64) + Builder.defineMacro("__IMAGE_SUPPORT__"); } if (TI.hasInt128Type() && LangOpts.CPlusPlus && LangOpts.GNUMode) { @@ -1068,7 +1108,7 @@ void clang::InitializePreprocessor( } } } - + // Even with predefines off, some macros are still predefined. // These should all be defined in the preprocessor according to the // current language configuration. @@ -1114,7 +1154,7 @@ void clang::InitializePreprocessor( // Instruct the preprocessor to skip the preamble. PP.setSkipMainFilePreamble(InitOpts.PrecompiledPreambleBytes.first, InitOpts.PrecompiledPreambleBytes.second); - + // Copy PredefinedBuffer into the Preprocessor. PP.setPredefines(Predefines.str()); } diff --git a/lib/Frontend/MultiplexConsumer.cpp b/lib/Frontend/MultiplexConsumer.cpp index 8ef6df5e740d..04a8f6c1cdfb 100644 --- a/lib/Frontend/MultiplexConsumer.cpp +++ b/lib/Frontend/MultiplexConsumer.cpp @@ -116,14 +116,16 @@ public: void ResolvedExceptionSpec(const FunctionDecl *FD) override; void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) override; void ResolvedOperatorDelete(const CXXDestructorDecl *DD, - const FunctionDecl *Delete) override; + const FunctionDecl *Delete, + Expr *ThisArg) override; void CompletedImplicitDefinition(const FunctionDecl *D) override; - void StaticDataMemberInstantiated(const VarDecl *D) override; + void InstantiationRequested(const ValueDecl *D) override; + void VariableDefinitionInstantiated(const VarDecl *D) override; + void FunctionDefinitionInstantiated(const FunctionDecl *D) override; void DefaultArgumentInstantiated(const ParmVarDecl *D) override; void DefaultMemberInitializerInstantiated(const FieldDecl *D) override; void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, const ObjCInterfaceDecl *IFD) override; - void FunctionDefinitionInstantiated(const FunctionDecl *D) override; void DeclarationMarkedUsed(const Decl *D) override; void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override; void DeclarationMarkedOpenMPDeclareTarget(const Decl *D, @@ -183,19 +185,28 @@ void MultiplexASTMutationListener::DeducedReturnType(const FunctionDecl *FD, Listeners[i]->DeducedReturnType(FD, ReturnType); } void MultiplexASTMutationListener::ResolvedOperatorDelete( - const CXXDestructorDecl *DD, const FunctionDecl *Delete) { + const CXXDestructorDecl *DD, const FunctionDecl *Delete, Expr *ThisArg) { for (auto *L : Listeners) - L->ResolvedOperatorDelete(DD, Delete); + L->ResolvedOperatorDelete(DD, Delete, ThisArg); } void MultiplexASTMutationListener::CompletedImplicitDefinition( const FunctionDecl *D) { for (size_t i = 0, e = Listeners.size(); i != e; ++i) Listeners[i]->CompletedImplicitDefinition(D); } -void MultiplexASTMutationListener::StaticDataMemberInstantiated( - const VarDecl *D) { +void MultiplexASTMutationListener::InstantiationRequested(const ValueDecl *D) { + for (size_t i = 0, e = Listeners.size(); i != e; ++i) + Listeners[i]->InstantiationRequested(D); +} +void MultiplexASTMutationListener::VariableDefinitionInstantiated( + const VarDecl *D) { for (size_t i = 0, e = Listeners.size(); i != e; ++i) - Listeners[i]->StaticDataMemberInstantiated(D); + Listeners[i]->VariableDefinitionInstantiated(D); +} +void MultiplexASTMutationListener::FunctionDefinitionInstantiated( + const FunctionDecl *D) { + for (auto &Listener : Listeners) + Listener->FunctionDefinitionInstantiated(D); } void MultiplexASTMutationListener::DefaultArgumentInstantiated( const ParmVarDecl *D) { @@ -213,11 +224,6 @@ void MultiplexASTMutationListener::AddedObjCCategoryToInterface( for (size_t i = 0, e = Listeners.size(); i != e; ++i) Listeners[i]->AddedObjCCategoryToInterface(CatD, IFD); } -void MultiplexASTMutationListener::FunctionDefinitionInstantiated( - const FunctionDecl *D) { - for (auto &Listener : Listeners) - Listener->FunctionDefinitionInstantiated(D); -} void MultiplexASTMutationListener::DeclarationMarkedUsed(const Decl *D) { for (size_t i = 0, e = Listeners.size(); i != e; ++i) Listeners[i]->DeclarationMarkedUsed(D); diff --git a/lib/Frontend/PrecompiledPreamble.cpp b/lib/Frontend/PrecompiledPreamble.cpp index 15b24cbed484..f6964d02b237 100644 --- a/lib/Frontend/PrecompiledPreamble.cpp +++ b/lib/Frontend/PrecompiledPreamble.cpp @@ -24,15 +24,45 @@ #include "clang/Serialization/ASTWriter.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSet.h" +#include "llvm/Config/llvm-config.h" #include "llvm/Support/CrashRecoveryContext.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/MutexGuard.h" +#include "llvm/Support/Process.h" + +#include <utility> using namespace clang; namespace { +StringRef getInMemoryPreamblePath() { +#if defined(LLVM_ON_UNIX) + return "/__clang_tmp/___clang_inmemory_preamble___"; +#elif defined(LLVM_ON_WIN32) + return "C:\\__clang_tmp\\___clang_inmemory_preamble___"; +#else +#warning "Unknown platform. Defaulting to UNIX-style paths for in-memory PCHs" + return "/__clang_tmp/___clang_inmemory_preamble___"; +#endif +} + +IntrusiveRefCntPtr<vfs::FileSystem> +createVFSOverlayForPreamblePCH(StringRef PCHFilename, + std::unique_ptr<llvm::MemoryBuffer> PCHBuffer, + IntrusiveRefCntPtr<vfs::FileSystem> VFS) { + // We want only the PCH file from the real filesystem to be available, + // so we create an in-memory VFS with just that and overlay it on top. + IntrusiveRefCntPtr<vfs::InMemoryFileSystem> PCHFS( + new vfs::InMemoryFileSystem()); + PCHFS->addFile(PCHFilename, 0, std::move(PCHBuffer)); + IntrusiveRefCntPtr<vfs::OverlayFileSystem> Overlay( + new vfs::OverlayFileSystem(VFS)); + Overlay->pushOverlay(PCHFS); + return Overlay; +} + /// Keeps a track of files to be deleted in destructor. class TemporaryFiles { public: @@ -85,23 +115,11 @@ void TemporaryFiles::removeFile(StringRef File) { llvm::sys::fs::remove(File); } -class PreambleMacroCallbacks : public PPCallbacks { -public: - PreambleMacroCallbacks(PreambleCallbacks &Callbacks) : Callbacks(Callbacks) {} - - void MacroDefined(const Token &MacroNameTok, - const MacroDirective *MD) override { - Callbacks.HandleMacroDefined(MacroNameTok, MD); - } - -private: - PreambleCallbacks &Callbacks; -}; - class PrecompilePreambleAction : public ASTFrontendAction { public: - PrecompilePreambleAction(PreambleCallbacks &Callbacks) - : Callbacks(Callbacks) {} + PrecompilePreambleAction(std::string *InMemStorage, + PreambleCallbacks &Callbacks) + : InMemStorage(InMemStorage), Callbacks(Callbacks) {} std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override; @@ -122,6 +140,7 @@ private: friend class PrecompilePreambleConsumer; bool HasEmittedPreamblePCH = false; + std::string *InMemStorage; PreambleCallbacks &Callbacks; }; @@ -163,21 +182,24 @@ private: std::unique_ptr<ASTConsumer> PrecompilePreambleAction::CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) { std::string Sysroot; - std::string OutputFile; - std::unique_ptr<raw_ostream> OS = - GeneratePCHAction::ComputeASTConsumerArguments(CI, InFile, Sysroot, - OutputFile); + if (!GeneratePCHAction::ComputeASTConsumerArguments(CI, Sysroot)) + return nullptr; + + std::unique_ptr<llvm::raw_ostream> OS; + if (InMemStorage) { + OS = llvm::make_unique<llvm::raw_string_ostream>(*InMemStorage); + } else { + std::string OutputFile; + OS = GeneratePCHAction::CreateOutputFile(CI, InFile, OutputFile); + } if (!OS) return nullptr; if (!CI.getFrontendOpts().RelocatablePCH) Sysroot.clear(); - CI.getPreprocessor().addPPCallbacks( - llvm::make_unique<PreambleMacroCallbacks>(Callbacks)); return llvm::make_unique<PrecompilePreambleConsumer>( *this, CI.getPreprocessor(), Sysroot, std::move(OS)); } @@ -194,15 +216,14 @@ template <class T> bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) { PreambleBounds clang::ComputePreambleBounds(const LangOptions &LangOpts, llvm::MemoryBuffer *Buffer, unsigned MaxLines) { - auto Pre = Lexer::ComputePreamble(Buffer->getBuffer(), LangOpts, MaxLines); - return PreambleBounds(Pre.first, Pre.second); + return Lexer::ComputePreamble(Buffer->getBuffer(), LangOpts, MaxLines); } llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build( const CompilerInvocation &Invocation, const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds, DiagnosticsEngine &Diagnostics, IntrusiveRefCntPtr<vfs::FileSystem> VFS, - std::shared_ptr<PCHContainerOperations> PCHContainerOps, + std::shared_ptr<PCHContainerOperations> PCHContainerOps, bool StoreInMemory, PreambleCallbacks &Callbacks) { assert(VFS && "VFS is null"); @@ -214,12 +235,19 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build( PreprocessorOptions &PreprocessorOpts = PreambleInvocation->getPreprocessorOpts(); - // Create a temporary file for the precompiled preamble. In rare - // circumstances, this can fail. - llvm::ErrorOr<PrecompiledPreamble::TempPCHFile> PreamblePCHFile = - PrecompiledPreamble::TempPCHFile::CreateNewPreamblePCHFile(); - if (!PreamblePCHFile) - return BuildPreambleError::CouldntCreateTempFile; + llvm::Optional<TempPCHFile> TempFile; + if (!StoreInMemory) { + // Create a temporary file for the precompiled preamble. In rare + // circumstances, this can fail. + llvm::ErrorOr<PrecompiledPreamble::TempPCHFile> PreamblePCHFile = + PrecompiledPreamble::TempPCHFile::CreateNewPreamblePCHFile(); + if (!PreamblePCHFile) + return BuildPreambleError::CouldntCreateTempFile; + TempFile = std::move(*PreamblePCHFile); + } + + PCHStorage Storage = StoreInMemory ? PCHStorage(InMemoryPreamble()) + : PCHStorage(std::move(*TempFile)); // Save the preamble text for later; we'll need to compare against it for // subsequent reparses. @@ -230,10 +258,12 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build( // Tell the compiler invocation to generate a temporary precompiled header. FrontendOpts.ProgramAction = frontend::GeneratePCH; - // FIXME: Generate the precompiled header into memory? - FrontendOpts.OutputFile = PreamblePCHFile->getFilePath(); + FrontendOpts.OutputFile = StoreInMemory ? getInMemoryPreamblePath() + : Storage.asFile().getFilePath(); PreprocessorOpts.PrecompiledPreambleBytes.first = 0; PreprocessorOpts.PrecompiledPreambleBytes.second = false; + // Inform preprocessor to record conditional stack when building the preamble. + PreprocessorOpts.GeneratePreamble = true; // Create the compiler instance to use for building the precompiled preamble. std::unique_ptr<CompilerInstance> Clang( @@ -301,10 +331,16 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build( } std::unique_ptr<PrecompilePreambleAction> Act; - Act.reset(new PrecompilePreambleAction(Callbacks)); + Act.reset(new PrecompilePreambleAction( + StoreInMemory ? &Storage.asMemory().Data : nullptr, Callbacks)); if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) return BuildPreambleError::BeginSourceFileFailed; + std::unique_ptr<PPCallbacks> DelegatedPPCallbacks = + Callbacks.createPPCallbacks(); + if (DelegatedPPCallbacks) + Clang->getPreprocessor().addPPCallbacks(std::move(DelegatedPPCallbacks)); + Act->Execute(); // Run the callbacks. @@ -335,9 +371,9 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build( } } - return PrecompiledPreamble( - std::move(*PreamblePCHFile), std::move(PreambleBytes), - PreambleEndsAtStartOfLine, std::move(FilesInPreamble)); + return PrecompiledPreamble(std::move(Storage), std::move(PreambleBytes), + PreambleEndsAtStartOfLine, + std::move(FilesInPreamble)); } PreambleBounds PrecompiledPreamble::getBounds() const { @@ -425,27 +461,33 @@ bool PrecompiledPreamble::CanReuse(const CompilerInvocation &Invocation, } void PrecompiledPreamble::AddImplicitPreamble( - CompilerInvocation &CI, llvm::MemoryBuffer *MainFileBuffer) const { + CompilerInvocation &CI, IntrusiveRefCntPtr<vfs::FileSystem> &VFS, + llvm::MemoryBuffer *MainFileBuffer) const { + assert(VFS && "VFS must not be null"); + auto &PreprocessorOpts = CI.getPreprocessorOpts(); + // Remap main file to point to MainFileBuffer. + auto MainFilePath = CI.getFrontendOpts().Inputs[0].getFile(); + PreprocessorOpts.addRemappedFile(MainFilePath, MainFileBuffer); + // Configure ImpicitPCHInclude. PreprocessorOpts.PrecompiledPreambleBytes.first = PreambleBytes.size(); PreprocessorOpts.PrecompiledPreambleBytes.second = PreambleEndsAtStartOfLine; - PreprocessorOpts.ImplicitPCHInclude = PCHFile.getFilePath(); PreprocessorOpts.DisablePCHValidation = true; - // Remap main file to point to MainFileBuffer. - auto MainFilePath = CI.getFrontendOpts().Inputs[0].getFile(); - PreprocessorOpts.addRemappedFile(MainFilePath, MainFileBuffer); + setupPreambleStorage(Storage, PreprocessorOpts, VFS); } PrecompiledPreamble::PrecompiledPreamble( - TempPCHFile PCHFile, std::vector<char> PreambleBytes, + PCHStorage Storage, std::vector<char> PreambleBytes, bool PreambleEndsAtStartOfLine, llvm::StringMap<PreambleFileHash> FilesInPreamble) - : PCHFile(std::move(PCHFile)), FilesInPreamble(FilesInPreamble), + : Storage(std::move(Storage)), FilesInPreamble(std::move(FilesInPreamble)), PreambleBytes(std::move(PreambleBytes)), - PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) {} + PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) { + assert(this->Storage.getKind() != PCHStorage::Kind::Empty); +} llvm::ErrorOr<PrecompiledPreamble::TempPCHFile> PrecompiledPreamble::TempPCHFile::CreateNewPreamblePCHFile() { @@ -462,9 +504,15 @@ llvm::ErrorOr<PrecompiledPreamble::TempPCHFile> PrecompiledPreamble::TempPCHFile::createInSystemTempDir(const Twine &Prefix, StringRef Suffix) { llvm::SmallString<64> File; - auto EC = llvm::sys::fs::createTemporaryFile(Prefix, Suffix, /*ref*/ File); + // Using a version of createTemporaryFile with a file descriptor guarantees + // that we would never get a race condition in a multi-threaded setting (i.e., + // multiple threads getting the same temporary path). + int FD; + auto EC = llvm::sys::fs::createTemporaryFile(Prefix, Suffix, FD, File); if (EC) return EC; + // We only needed to make sure the file exists, close the file right away. + llvm::sys::Process::SafelyCloseFileDescriptor(FD); return TempPCHFile(std::move(File).str()); } @@ -506,6 +554,87 @@ llvm::StringRef PrecompiledPreamble::TempPCHFile::getFilePath() const { return *FilePath; } +PrecompiledPreamble::PCHStorage::PCHStorage(TempPCHFile File) + : StorageKind(Kind::TempFile) { + new (&asFile()) TempPCHFile(std::move(File)); +} + +PrecompiledPreamble::PCHStorage::PCHStorage(InMemoryPreamble Memory) + : StorageKind(Kind::InMemory) { + new (&asMemory()) InMemoryPreamble(std::move(Memory)); +} + +PrecompiledPreamble::PCHStorage::PCHStorage(PCHStorage &&Other) : PCHStorage() { + *this = std::move(Other); +} + +PrecompiledPreamble::PCHStorage &PrecompiledPreamble::PCHStorage:: +operator=(PCHStorage &&Other) { + destroy(); + + StorageKind = Other.StorageKind; + switch (StorageKind) { + case Kind::Empty: + // do nothing; + break; + case Kind::TempFile: + new (&asFile()) TempPCHFile(std::move(Other.asFile())); + break; + case Kind::InMemory: + new (&asMemory()) InMemoryPreamble(std::move(Other.asMemory())); + break; + } + + Other.setEmpty(); + return *this; +} + +PrecompiledPreamble::PCHStorage::~PCHStorage() { destroy(); } + +PrecompiledPreamble::PCHStorage::Kind +PrecompiledPreamble::PCHStorage::getKind() const { + return StorageKind; +} + +PrecompiledPreamble::TempPCHFile &PrecompiledPreamble::PCHStorage::asFile() { + assert(getKind() == Kind::TempFile); + return *reinterpret_cast<TempPCHFile *>(Storage.buffer); +} + +const PrecompiledPreamble::TempPCHFile & +PrecompiledPreamble::PCHStorage::asFile() const { + return const_cast<PCHStorage *>(this)->asFile(); +} + +PrecompiledPreamble::InMemoryPreamble & +PrecompiledPreamble::PCHStorage::asMemory() { + assert(getKind() == Kind::InMemory); + return *reinterpret_cast<InMemoryPreamble *>(Storage.buffer); +} + +const PrecompiledPreamble::InMemoryPreamble & +PrecompiledPreamble::PCHStorage::asMemory() const { + return const_cast<PCHStorage *>(this)->asMemory(); +} + +void PrecompiledPreamble::PCHStorage::destroy() { + switch (StorageKind) { + case Kind::Empty: + return; + case Kind::TempFile: + asFile().~TempPCHFile(); + return; + case Kind::InMemory: + asMemory().~InMemoryPreamble(); + return; + } +} + +void PrecompiledPreamble::PCHStorage::setEmpty() { + destroy(); + StorageKind = Kind::Empty; +} + PrecompiledPreamble::PreambleFileHash PrecompiledPreamble::PreambleFileHash::createForFile(off_t Size, time_t ModTime) { @@ -530,11 +659,47 @@ PrecompiledPreamble::PreambleFileHash::createForMemoryBuffer( return Result; } +void PrecompiledPreamble::setupPreambleStorage( + const PCHStorage &Storage, PreprocessorOptions &PreprocessorOpts, + IntrusiveRefCntPtr<vfs::FileSystem> &VFS) { + if (Storage.getKind() == PCHStorage::Kind::TempFile) { + const TempPCHFile &PCHFile = Storage.asFile(); + PreprocessorOpts.ImplicitPCHInclude = PCHFile.getFilePath(); + + // Make sure we can access the PCH file even if we're using a VFS + IntrusiveRefCntPtr<vfs::FileSystem> RealFS = vfs::getRealFileSystem(); + auto PCHPath = PCHFile.getFilePath(); + if (VFS == RealFS || VFS->exists(PCHPath)) + return; + auto Buf = RealFS->getBufferForFile(PCHPath); + if (!Buf) { + // We can't read the file even from RealFS, this is clearly an error, + // but we'll just leave the current VFS as is and let clang's code + // figure out what to do with missing PCH. + return; + } + + // We have a slight inconsistency here -- we're using the VFS to + // read files, but the PCH was generated in the real file system. + VFS = createVFSOverlayForPreamblePCH(PCHPath, std::move(*Buf), VFS); + } else { + assert(Storage.getKind() == PCHStorage::Kind::InMemory); + // For in-memory preamble, we have to provide a VFS overlay that makes it + // accessible. + StringRef PCHPath = getInMemoryPreamblePath(); + PreprocessorOpts.ImplicitPCHInclude = PCHPath; + + auto Buf = llvm::MemoryBuffer::getMemBuffer(Storage.asMemory().Data); + VFS = createVFSOverlayForPreamblePCH(PCHPath, std::move(Buf), VFS); + } +} + void PreambleCallbacks::AfterExecute(CompilerInstance &CI) {} void PreambleCallbacks::AfterPCHEmitted(ASTWriter &Writer) {} void PreambleCallbacks::HandleTopLevelDecl(DeclGroupRef DG) {} -void PreambleCallbacks::HandleMacroDefined(const Token &MacroNameTok, - const MacroDirective *MD) {} +std::unique_ptr<PPCallbacks> PreambleCallbacks::createPPCallbacks() { + return nullptr; +} std::error_code clang::make_error_code(BuildPreambleError Error) { return std::error_code(static_cast<int>(Error), BuildPreambleErrorCategory()); diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index 914039ad5bb1..2e023294f1e8 100644 --- a/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/lib/Frontend/PrintPreprocessedOutput.cpp @@ -143,6 +143,8 @@ public: ArrayRef<int> Ids) override; void PragmaWarningPush(SourceLocation Loc, int Level) override; void PragmaWarningPop(SourceLocation Loc) override; + void PragmaAssumeNonNullBegin(SourceLocation Loc) override; + void PragmaAssumeNonNullEnd(SourceLocation Loc) override; bool HandleFirstTokOnLine(Token &Tok); @@ -549,6 +551,22 @@ void PrintPPOutputPPCallbacks::PragmaWarningPop(SourceLocation Loc) { setEmittedDirectiveOnThisLine(); } +void PrintPPOutputPPCallbacks:: +PragmaAssumeNonNullBegin(SourceLocation Loc) { + startNewLineIfNeeded(); + MoveToLine(Loc); + OS << "#pragma clang assume_nonnull begin"; + setEmittedDirectiveOnThisLine(); +} + +void PrintPPOutputPPCallbacks:: +PragmaAssumeNonNullEnd(SourceLocation Loc) { + startNewLineIfNeeded(); + MoveToLine(Loc); + OS << "#pragma clang assume_nonnull end"; + setEmittedDirectiveOnThisLine(); +} + /// HandleFirstTokOnLine - When emitting a preprocessed file in -E mode, this /// is called for the first token on each new line. If this really is the start /// of a new logical line, handle it and return true, otherwise return false. @@ -702,6 +720,12 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, // -traditional-cpp the lexer keeps /all/ whitespace, including comments. SourceLocation StartLoc = Tok.getLocation(); Callbacks->MoveToLine(StartLoc.getLocWithOffset(Tok.getLength())); + } else if (Tok.is(tok::eod)) { + // Don't print end of directive tokens, since they are typically newlines + // that mess up our line tracking. These come from unknown pre-processor + // directives or hash-prefixed comments in standalone assembly files. + PP.Lex(Tok); + continue; } else if (Tok.is(tok::annot_module_include)) { // PrintPPOutputPPCallbacks::InclusionDirective handles producing // appropriate output here. Ignore this token entirely. diff --git a/lib/Frontend/Rewrite/FrontendActions.cpp b/lib/Frontend/Rewrite/FrontendActions.cpp index 5efa6aeaf760..4d587048f62d 100644 --- a/lib/Frontend/Rewrite/FrontendActions.cpp +++ b/lib/Frontend/Rewrite/FrontendActions.cpp @@ -154,7 +154,7 @@ bool FixItRecompile::BeginInvocation(CompilerInstance &CI) { return true; } -#ifdef CLANG_ENABLE_OBJC_REWRITER +#if CLANG_ENABLE_OBJC_REWRITER std::unique_ptr<ASTConsumer> RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { diff --git a/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/lib/Frontend/Rewrite/RewriteModernObjC.cpp index 21686b8c78ea..1954b24aedad 100644 --- a/lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ b/lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -31,7 +31,7 @@ #include "llvm/Support/raw_ostream.h" #include <memory> -#ifdef CLANG_ENABLE_OBJC_REWRITER +#if CLANG_ENABLE_OBJC_REWRITER using namespace clang; using llvm::utostr; diff --git a/lib/Frontend/Rewrite/RewriteObjC.cpp b/lib/Frontend/Rewrite/RewriteObjC.cpp index e0d813df70f8..096b81bc3f08 100644 --- a/lib/Frontend/Rewrite/RewriteObjC.cpp +++ b/lib/Frontend/Rewrite/RewriteObjC.cpp @@ -30,7 +30,7 @@ #include "llvm/Support/raw_ostream.h" #include <memory> -#ifdef CLANG_ENABLE_OBJC_REWRITER +#if CLANG_ENABLE_OBJC_REWRITER using namespace clang; using llvm::utostr; diff --git a/lib/Frontend/TextDiagnosticBuffer.cpp b/lib/Frontend/TextDiagnosticBuffer.cpp index d49e983fcd37..288507310baa 100644 --- a/lib/Frontend/TextDiagnosticBuffer.cpp +++ b/lib/Frontend/TextDiagnosticBuffer.cpp @@ -30,34 +30,45 @@ void TextDiagnosticBuffer::HandleDiagnostic(DiagnosticsEngine::Level Level, default: llvm_unreachable( "Diagnostic not handled during diagnostic buffering!"); case DiagnosticsEngine::Note: + All.emplace_back(Level, Notes.size()); Notes.emplace_back(Info.getLocation(), Buf.str()); break; case DiagnosticsEngine::Warning: + All.emplace_back(Level, Warnings.size()); Warnings.emplace_back(Info.getLocation(), Buf.str()); break; case DiagnosticsEngine::Remark: + All.emplace_back(Level, Remarks.size()); Remarks.emplace_back(Info.getLocation(), Buf.str()); break; case DiagnosticsEngine::Error: case DiagnosticsEngine::Fatal: + All.emplace_back(Level, Errors.size()); Errors.emplace_back(Info.getLocation(), Buf.str()); break; } } void TextDiagnosticBuffer::FlushDiagnostics(DiagnosticsEngine &Diags) const { - // FIXME: Flush the diagnostics in order. - for (const_iterator it = err_begin(), ie = err_end(); it != ie; ++it) - Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Error, "%0")) - << it->second; - for (const_iterator it = warn_begin(), ie = warn_end(); it != ie; ++it) - Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Warning, "%0")) - << it->second; - for (const_iterator it = remark_begin(), ie = remark_end(); it != ie; ++it) - Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Remark, "%0")) - << it->second; - for (const_iterator it = note_begin(), ie = note_end(); it != ie; ++it) - Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Note, "%0")) - << it->second; + for (auto it = All.begin(), ie = All.end(); it != ie; ++it) { + auto Diag = Diags.Report(Diags.getCustomDiagID(it->first, "%0")); + switch (it->first) { + default: llvm_unreachable( + "Diagnostic not handled during diagnostic flushing!"); + case DiagnosticsEngine::Note: + Diag << Notes[it->second].second; + break; + case DiagnosticsEngine::Warning: + Diag << Warnings[it->second].second; + break; + case DiagnosticsEngine::Remark: + Diag << Remarks[it->second].second; + break; + case DiagnosticsEngine::Error: + case DiagnosticsEngine::Fatal: + Diag << Errors[it->second].second; + break; + } + } } diff --git a/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp index 427d15ed703a..0df5393a309b 100644 --- a/lib/Frontend/VerifyDiagnosticConsumer.cpp +++ b/lib/Frontend/VerifyDiagnosticConsumer.cpp @@ -229,22 +229,52 @@ public: return true; } - // Return true if string literal is found. - // When true, P marks begin-position of S in content. - bool Search(StringRef S, bool EnsureStartOfWord = false) { + // 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. + // If S is the empty string, then search for any letter instead (makes sense + // with FinishDirectiveToken=true). + // If EnsureStartOfWord, then skip matches that don't start a new word. + // If FinishDirectiveToken, then assume the match is the start of a comment + // directive for -verify, and extend the match to include the entire first + // token of that directive. + bool Search(StringRef S, bool EnsureStartOfWord = false, + bool FinishDirectiveToken = false) { do { - P = std::search(C, End, S.begin(), S.end()); - PEnd = P + S.size(); + if (!S.empty()) { + P = std::search(C, End, S.begin(), S.end()); + PEnd = P + S.size(); + } + else { + P = C; + while (P != End && !isLetter(*P)) + ++P; + PEnd = P + 1; + } if (P == End) break; - if (!EnsureStartOfWord - // Check if string literal starts a new word. - || P == Begin || isWhitespace(P[-1]) - // Or it could be preceded by the start of a comment. - || (P > (Begin + 1) && (P[-1] == '/' || P[-1] == '*') - && P[-2] == '/')) - return true; - // Otherwise, skip and search again. + // If not start of word but required, skip and search again. + if (EnsureStartOfWord + // Check if string literal starts a new word. + && !(P == Begin || isWhitespace(P[-1]) + // Or it could be preceded by the start of a comment. + || (P > (Begin + 1) && (P[-1] == '/' || P[-1] == '*') + && P[-2] == '/'))) + continue; + if (FinishDirectiveToken) { + while (PEnd != End && (isAlphanumeric(*PEnd) + || *PEnd == '-' || *PEnd == '_')) + ++PEnd; + // Put back trailing digits and hyphens to be parsed later as a count + // or count range. Because -verify prefixes must start with letters, + // we know the actual directive we found starts with a letter, so + // we won't put back the entire directive word and thus record an empty + // string. + assert(isLetter(*P) && "-verify prefix must start with a letter"); + while (isDigit(PEnd[-1]) || PEnd[-1] == '-') + --PEnd; + } + return true; } while (Advance()); return false; } @@ -314,37 +344,68 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM, // A single comment may contain multiple directives. bool FoundDirective = false; for (ParseHelper PH(S); !PH.Done();) { - // Search for token: expected - if (!PH.Search("expected", true)) + // Search for the initial directive token. + // If one prefix, save time by searching only for its directives. + // Otherwise, search for any potential directive token and check it later. + const auto &Prefixes = Diags.getDiagnosticOptions().VerifyPrefixes; + if (!(Prefixes.size() == 1 ? PH.Search(*Prefixes.begin(), true, true) + : PH.Search("", true, true))) break; PH.Advance(); - // Next token: - - if (!PH.Next("-")) - continue; - PH.Advance(); + // Default directive kind. + bool RegexKind = false; + 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); - // Next token: { error | warning | note } + // Regex in initial directive token: -re + if (DToken.endswith("-re")) { + RegexKind = true; + KindStr = "regex"; + DToken = DToken.substr(0, DToken.size()-3); + } + + // Type in initial directive token: -{error|warning|note|no-diagnostics} DirectiveList *DL = nullptr; - if (PH.Next("error")) + bool NoDiag = false; + StringRef DType; + if (DToken.endswith(DType="-error")) DL = ED ? &ED->Errors : nullptr; - else if (PH.Next("warning")) + else if (DToken.endswith(DType="-warning")) DL = ED ? &ED->Warnings : nullptr; - else if (PH.Next("remark")) + else if (DToken.endswith(DType="-remark")) DL = ED ? &ED->Remarks : nullptr; - else if (PH.Next("note")) + else if (DToken.endswith(DType="-note")) DL = ED ? &ED->Notes : nullptr; - else if (PH.Next("no-diagnostics")) { + else if (DToken.endswith(DType="-no-diagnostics")) { + NoDiag = true; + if (RegexKind) + continue; + } + else + continue; + DToken = DToken.substr(0, DToken.size()-DType.size()); + + // What's left in DToken is the actual prefix. That might not be a -verify + // prefix even if there is only one -verify prefix (for example, the full + // DToken is foo-bar-warning, but foo is the only -verify prefix). + if (!std::binary_search(Prefixes.begin(), Prefixes.end(), DToken)) + continue; + + if (NoDiag) { if (Status == VerifyDiagnosticConsumer::HasOtherExpectedDirectives) Diags.Report(Pos, diag::err_verify_invalid_no_diags) << /*IsExpectedNoDiagnostics=*/true; else Status = VerifyDiagnosticConsumer::HasExpectedNoDiagnostics; continue; - } else - continue; - PH.Advance(); - + } if (Status == VerifyDiagnosticConsumer::HasExpectedNoDiagnostics) { Diags.Report(Pos, diag::err_verify_invalid_no_diags) << /*IsExpectedNoDiagnostics=*/false; @@ -357,17 +418,6 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM, if (!DL) return true; - // Default directive kind. - bool RegexKind = false; - const char* KindStr = "string"; - - // Next optional token: - - if (PH.Next("-re")) { - PH.Advance(); - RegexKind = true; - KindStr = "regex"; - } - // Next optional token: @ SourceLocation ExpectedLoc; bool MatchAnyLine = false; @@ -416,9 +466,12 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM, MatchAnyLine = true; ExpectedLoc = SM.translateFileLineCol(FE, 1, 1); } + } else if (PH.Next("*")) { + MatchAnyLine = true; + ExpectedLoc = SourceLocation(); } - if (ExpectedLoc.isInvalid()) { + if (ExpectedLoc.isInvalid() && !MatchAnyLine) { Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), diag::err_verify_missing_line) << KindStr; continue; @@ -650,7 +703,10 @@ static unsigned PrintExpected(DiagnosticsEngine &Diags, llvm::raw_svector_ostream OS(Fmt); for (auto *DirPtr : DL) { Directive &D = *DirPtr; - OS << "\n File " << SourceMgr.getFilename(D.DiagnosticLoc); + if (D.DiagnosticLoc.isInvalid()) + OS << "\n File *"; + else + OS << "\n File " << SourceMgr.getFilename(D.DiagnosticLoc); if (D.MatchAnyLine) OS << " Line *"; else @@ -708,7 +764,8 @@ static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr, continue; } - if (!IsFromSameFile(SourceMgr, D.DiagnosticLoc, II->first)) + if (!D.DiagnosticLoc.isInvalid() && + !IsFromSameFile(SourceMgr, D.DiagnosticLoc, II->first)) continue; const std::string &RightText = II->second; |