diff options
Diffstat (limited to 'lib/Frontend')
-rw-r--r-- | lib/Frontend/ASTConsumers.cpp | 54 | ||||
-rw-r--r-- | lib/Frontend/ASTUnit.cpp | 294 | ||||
-rw-r--r-- | lib/Frontend/CacheTokens.cpp | 45 | ||||
-rw-r--r-- | lib/Frontend/ChainedIncludesSource.cpp | 6 | ||||
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 219 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 281 | ||||
-rw-r--r-- | lib/Frontend/CreateInvocationFromCommandLine.cpp | 9 | ||||
-rw-r--r-- | lib/Frontend/DependencyFile.cpp | 4 | ||||
-rw-r--r-- | lib/Frontend/FrontendAction.cpp | 12 | ||||
-rw-r--r-- | lib/Frontend/FrontendActions.cpp | 27 | ||||
-rw-r--r-- | lib/Frontend/FrontendOptions.cpp | 1 | ||||
-rw-r--r-- | lib/Frontend/HeaderIncludeGen.cpp | 24 | ||||
-rw-r--r-- | lib/Frontend/InitHeaderSearch.cpp | 47 | ||||
-rw-r--r-- | lib/Frontend/InitPreprocessor.cpp | 76 | ||||
-rw-r--r-- | lib/Frontend/MultiplexConsumer.cpp | 20 | ||||
-rw-r--r-- | lib/Frontend/PrintPreprocessedOutput.cpp | 97 | ||||
-rw-r--r-- | lib/Frontend/TextDiagnostic.cpp | 64 | ||||
-rw-r--r-- | lib/Frontend/TextDiagnosticPrinter.cpp | 3 | ||||
-rw-r--r-- | lib/Frontend/VerifyDiagnosticConsumer.cpp | 8 |
19 files changed, 797 insertions, 494 deletions
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp index 4a63d76..1ef4c18 100644 --- a/lib/Frontend/ASTConsumers.cpp +++ b/lib/Frontend/ASTConsumers.cpp @@ -37,20 +37,15 @@ namespace { public: ASTPrinter(raw_ostream *Out = NULL, bool Dump = false, - StringRef FilterString = "") + StringRef FilterString = "", bool DumpLookups = false) : Out(Out ? *Out : llvm::outs()), Dump(Dump), - FilterString(FilterString) {} + FilterString(FilterString), DumpLookups(DumpLookups) {} virtual void HandleTranslationUnit(ASTContext &Context) { TranslationUnitDecl *D = Context.getTranslationUnitDecl(); - if (FilterString.empty()) { - if (Dump) - D->dump(Out); - else - D->print(Out, /*Indentation=*/0, /*PrintInstantiation=*/true); - return; - } + if (FilterString.empty()) + return print(D); TraverseDecl(D); } @@ -65,10 +60,7 @@ namespace { Out << (Dump ? "Dumping " : "Printing ") << getName(D) << ":\n"; if (ShowColors) Out.resetColor(); - if (Dump) - D->dump(Out); - else - D->print(Out, /*Indentation=*/0, /*PrintInstantiation=*/true); + print(D); Out << "\n"; // Don't traverse child nodes to avoid output duplication. return true; @@ -85,10 +77,22 @@ namespace { bool filterMatches(Decl *D) { return getName(D).find(FilterString) != std::string::npos; } + void print(Decl *D) { + if (DumpLookups) { + if (DeclContext *DC = dyn_cast<DeclContext>(D)) + DC->dumpLookups(Out); + else + Out << "Not a DeclContext\n"; + } else if (Dump) + D->dump(Out); + else + D->print(Out, /*Indentation=*/0, /*PrintInstantiation=*/true); + } raw_ostream &Out; bool Dump; std::string FilterString; + bool DumpLookups; }; class ASTDeclNodeLister : public ASTConsumer, @@ -119,8 +123,8 @@ ASTConsumer *clang::CreateASTPrinter(raw_ostream *Out, return new ASTPrinter(Out, /*Dump=*/ false, FilterString); } -ASTConsumer *clang::CreateASTDumper(StringRef FilterString) { - return new ASTPrinter(0, /*Dump=*/ true, FilterString); +ASTConsumer *clang::CreateASTDumper(StringRef FilterString, bool DumpLookups) { + return new ASTPrinter(0, /*Dump=*/ true, FilterString, DumpLookups); } ASTConsumer *clang::CreateASTDeclNodeLister() { @@ -476,23 +480,3 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, ASTConsumer *clang::CreateDeclContextPrinter() { return new DeclContextPrinter(); } - -//===----------------------------------------------------------------------===// -/// ASTDumperXML - In-depth XML dumping. - -namespace { -class ASTDumpXML : public ASTConsumer { - raw_ostream &OS; - -public: - ASTDumpXML(raw_ostream &OS) : OS(OS) {} - - void HandleTranslationUnit(ASTContext &C) { - C.getTranslationUnitDecl()->dumpXML(OS); - } -}; -} - -ASTConsumer *clang::CreateASTDumperXML(raw_ostream &OS) { - return new ASTDumpXML(OS); -} diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 8bd5172..a8c5876 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -29,6 +29,7 @@ #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/PreprocessorOptions.h" +#include "clang/Sema/Sema.h" #include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ASTWriter.h" #include "llvm/ADT/ArrayRef.h" @@ -83,10 +84,10 @@ namespace { /// \brief The file in which the precompiled preamble is stored. std::string PreambleFile; - /// \brief Temporary files that should be removed when the ASTUnit is + /// \brief Temporary files that should be removed when the ASTUnit is /// destroyed. - SmallVector<llvm::sys::Path, 4> TemporaryFiles; - + SmallVector<std::string, 4> TemporaryFiles; + /// \brief Erase temporary files. void CleanTemporaryFiles(); @@ -165,13 +166,13 @@ static const std::string &getPreambleFile(const ASTUnit *AU) { void OnDiskData::CleanTemporaryFiles() { for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I) - TemporaryFiles[I].eraseFromDisk(); - TemporaryFiles.clear(); + llvm::sys::fs::remove(TemporaryFiles[I]); + TemporaryFiles.clear(); } void OnDiskData::CleanPreambleFile() { if (!PreambleFile.empty()) { - llvm::sys::Path(PreambleFile).eraseFromDisk(); + llvm::sys::fs::remove(PreambleFile); PreambleFile.clear(); } } @@ -200,7 +201,7 @@ void ASTUnit::CleanTemporaryFiles() { getOnDiskData(this).CleanTemporaryFiles(); } -void ASTUnit::addTemporaryFile(const llvm::sys::Path &TempFile) { +void ASTUnit::addTemporaryFile(StringRef TempFile) { getOnDiskData(this).TemporaryFiles.push_back(TempFile); } @@ -216,7 +217,8 @@ const unsigned DefaultPreambleRebuildInterval = 5; static llvm::sys::cas_flag ActiveASTUnitObjects; ASTUnit::ASTUnit(bool _MainFileIsAST) - : Reader(0), OnlyLocalDecls(false), CaptureDiagnostics(false), + : Reader(0), HadModuleLoaderFatalFailure(false), + OnlyLocalDecls(false), CaptureDiagnostics(false), MainFileIsAST(_MainFileIsAST), TUKind(TU_Complete), WantTiming(getenv("LIBCLANG_TIMING")), OwnsRemappedFileBuffers(true), @@ -509,23 +511,19 @@ class ASTInfoCollector : public ASTReaderListener { Preprocessor &PP; ASTContext &Context; LangOptions &LangOpt; - HeaderSearch &HSI; IntrusiveRefCntPtr<TargetOptions> &TargetOpts; IntrusiveRefCntPtr<TargetInfo> &Target; unsigned &Counter; - unsigned NumHeaderInfos; - bool InitializedLanguage; public: ASTInfoCollector(Preprocessor &PP, ASTContext &Context, LangOptions &LangOpt, - HeaderSearch &HSI, IntrusiveRefCntPtr<TargetOptions> &TargetOpts, IntrusiveRefCntPtr<TargetInfo> &Target, unsigned &Counter) - : PP(PP), Context(Context), LangOpt(LangOpt), HSI(HSI), + : PP(PP), Context(Context), LangOpt(LangOpt), TargetOpts(TargetOpts), Target(Target), - Counter(Counter), NumHeaderInfos(0), + Counter(Counter), InitializedLanguage(false) {} virtual bool ReadLanguageOptions(const LangOptions &LangOpts, @@ -554,10 +552,6 @@ public: return false; } - virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID) { - HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++); - } - virtual void ReadCounter(const serialization::ModuleFile &M, unsigned Value) { Counter = Value; } @@ -646,6 +640,12 @@ void StoredDiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level Level, StoredDiags.push_back(StoredDiagnostic(Level, Info)); } +ASTMutationListener *ASTUnit::getASTMutationListener() { + if (WriterData) + return &WriterData->Writer; + return 0; +} + ASTDeserializationListener *ASTUnit::getDeserializationListener() { if (WriterData) return &WriterData->Writer; @@ -707,7 +707,7 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, AST->HSOpts = new HeaderSearchOptions(); AST->HeaderInfo.reset(new HeaderSearch(AST->HSOpts, - AST->getFileManager(), + AST->getSourceManager(), AST->getDiagnostics(), AST->ASTFileLangOpts, /*Target=*/0)); @@ -798,7 +798,7 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, ReaderCleanup(Reader.get()); Reader->setListener(new ASTInfoCollector(*AST->PP, Context, - AST->ASTFileLangOpts, HeaderInfo, + AST->ASTFileLangOpts, AST->TargetOpts, AST->Target, Counter)); @@ -877,6 +877,18 @@ void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) { return; if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) { + if (EnumDecl *EnumD = dyn_cast<EnumDecl>(D)) { + // For an unscoped enum include the enumerators in the hash since they + // enter the top-level namespace. + if (!EnumD->isScoped()) { + for (EnumDecl::enumerator_iterator EI = EnumD->enumerator_begin(), + EE = EnumD->enumerator_end(); EI != EE; ++EI) { + if ((*EI)->getIdentifier()) + Hash = llvm::HashString((*EI)->getIdentifier()->getName(), Hash); + } + } + } + if (ND->getIdentifier()) Hash = llvm::HashString(ND->getIdentifier()->getName(), Hash); else if (DeclarationName Name = ND->getDeclName()) { @@ -884,7 +896,15 @@ void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) { Hash = llvm::HashString(NameStr, Hash); } return; - } + } + + if (ImportDecl *ImportD = dyn_cast<ImportDecl>(D)) { + if (Module *Mod = ImportD->getImportedModule()) { + std::string ModName = Mod->getFullModuleName(); + Hash = llvm::HashString(ModName, Hash); + } + return; + } } class TopLevelDeclTrackerConsumer : public ASTConsumer { @@ -937,6 +957,10 @@ public: handleTopLevelDecl(*it); } + virtual ASTMutationListener *GetASTMutationListener() { + return Unit.getASTMutationListener(); + } + virtual ASTDeserializationListener *GetASTDeserializationListener() { return Unit.getDeserializationListener(); } @@ -963,16 +987,37 @@ public: } }; +class PrecompilePreambleAction : public ASTFrontendAction { + ASTUnit &Unit; + bool HasEmittedPreamblePCH; + +public: + explicit PrecompilePreambleAction(ASTUnit &Unit) + : Unit(Unit), HasEmittedPreamblePCH(false) {} + + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile); + bool hasEmittedPreamblePCH() const { return HasEmittedPreamblePCH; } + void setHasEmittedPreamblePCH() { HasEmittedPreamblePCH = true; } + virtual bool shouldEraseOutputFiles() { return !hasEmittedPreamblePCH(); } + + virtual bool hasCodeCompletionSupport() const { return false; } + virtual bool hasASTFileSupport() const { return false; } + virtual TranslationUnitKind getTranslationUnitKind() { return TU_Prefix; } +}; + class PrecompilePreambleConsumer : public PCHGenerator { ASTUnit &Unit; - unsigned &Hash; + unsigned &Hash; std::vector<Decl *> TopLevelDecls; - + PrecompilePreambleAction *Action; + public: - PrecompilePreambleConsumer(ASTUnit &Unit, const Preprocessor &PP, - StringRef isysroot, raw_ostream *Out) - : PCHGenerator(PP, "", 0, isysroot, Out), Unit(Unit), - Hash(Unit.getCurrentTopLevelHashValue()) { + PrecompilePreambleConsumer(ASTUnit &Unit, PrecompilePreambleAction *Action, + const Preprocessor &PP, StringRef isysroot, + raw_ostream *Out) + : PCHGenerator(PP, "", 0, isysroot, Out, /*AllowASTWithErrors=*/true), + Unit(Unit), Hash(Unit.getCurrentTopLevelHashValue()), Action(Action) { Hash = 0; } @@ -993,48 +1038,42 @@ public: virtual void HandleTranslationUnit(ASTContext &Ctx) { PCHGenerator::HandleTranslationUnit(Ctx); - if (!Unit.getDiagnostics().hasErrorOccurred()) { + if (hasEmittedPCH()) { // Translate the top-level declarations we captured during // parsing into declaration IDs in the precompiled // preamble. This will allow us to deserialize those top-level // declarations when requested. - for (unsigned I = 0, N = TopLevelDecls.size(); I != N; ++I) - Unit.addTopLevelDeclFromPreamble( - getWriter().getDeclID(TopLevelDecls[I])); + for (unsigned I = 0, N = TopLevelDecls.size(); I != N; ++I) { + Decl *D = TopLevelDecls[I]; + // Invalid top-level decls may not have been serialized. + if (D->isInvalidDecl()) + continue; + Unit.addTopLevelDeclFromPreamble(getWriter().getDeclID(D)); + } + + Action->setHasEmittedPreamblePCH(); } } }; -class PrecompilePreambleAction : public ASTFrontendAction { - ASTUnit &Unit; - -public: - explicit PrecompilePreambleAction(ASTUnit &Unit) : Unit(Unit) {} - - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) { - std::string Sysroot; - std::string OutputFile; - raw_ostream *OS = 0; - if (GeneratePCHAction::ComputeASTConsumerArguments(CI, InFile, Sysroot, - OutputFile, - OS)) - return 0; - - if (!CI.getFrontendOpts().RelocatablePCH) - Sysroot.clear(); +} - CI.getPreprocessor().addPPCallbacks( - new MacroDefinitionTrackerPPCallbacks(Unit.getCurrentTopLevelHashValue())); - return new PrecompilePreambleConsumer(Unit, CI.getPreprocessor(), Sysroot, - OS); - } +ASTConsumer *PrecompilePreambleAction::CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) { + std::string Sysroot; + std::string OutputFile; + raw_ostream *OS = 0; + if (GeneratePCHAction::ComputeASTConsumerArguments(CI, InFile, Sysroot, + OutputFile, OS)) + return 0; - virtual bool hasCodeCompletionSupport() const { return false; } - virtual bool hasASTFileSupport() const { return false; } - virtual TranslationUnitKind getTranslationUnitKind() { return TU_Prefix; } -}; + if (!CI.getFrontendOpts().RelocatablePCH) + Sysroot.clear(); + CI.getPreprocessor().addPPCallbacks(new MacroDefinitionTrackerPPCallbacks( + Unit.getCurrentTopLevelHashValue())); + return new PrecompilePreambleConsumer(Unit, this, CI.getPreprocessor(), + Sysroot, OS); } static bool isNonDriverDiag(const StoredDiagnostic &StoredDiag) { @@ -1214,36 +1253,17 @@ error: /// \brief Simple function to retrieve a path for a preamble precompiled header. static std::string GetPreamblePCHPath() { - // FIXME: This is lame; sys::Path should provide this function (in particular, - // it should know how to find the temporary files dir). - // FIXME: This is really lame. I copied this code from the Driver! // FIXME: This is a hack so that we can override the preamble file during // crash-recovery testing, which is the only case where the preamble files - // are not necessarily cleaned up. + // are not necessarily cleaned up. const char *TmpFile = ::getenv("CINDEXTEST_PREAMBLE_FILE"); if (TmpFile) return TmpFile; - - std::string Error; - const char *TmpDir = ::getenv("TMPDIR"); - if (!TmpDir) - TmpDir = ::getenv("TEMP"); - if (!TmpDir) - TmpDir = ::getenv("TMP"); -#ifdef LLVM_ON_WIN32 - if (!TmpDir) - TmpDir = ::getenv("USERPROFILE"); -#endif - if (!TmpDir) - TmpDir = "/tmp"; - llvm::sys::Path P(TmpDir); - P.createDirectoryOnDisk(true); - P.appendComponent("preamble"); - P.appendSuffix("pch"); - if (P.makeUnique(/*reuse_current=*/false, /*ErrMsg*/0)) - return std::string(); - - return P.str(); + + SmallString<128> Path; + llvm::sys::fs::createTemporaryFile("preamble", "pch", Path); + + return Path.str(); } /// \brief Compute the preamble for the main file, providing the source buffer @@ -1260,17 +1280,19 @@ ASTUnit::ComputePreamble(CompilerInvocation &Invocation, // command line (to another file) or directly through the compiler invocation // (to a memory buffer). llvm::MemoryBuffer *Buffer = 0; - llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].getFile()); - if (const llvm::sys::FileStatus *MainFileStatus = MainFilePath.getFileStatus()) { + std::string MainFilePath(FrontendOpts.Inputs[0].getFile()); + llvm::sys::fs::UniqueID MainFileID; + if (!llvm::sys::fs::getUniqueID(MainFilePath, MainFileID)) { // Check whether there is a file-file remapping of the main file for (PreprocessorOptions::remapped_file_iterator M = PreprocessorOpts.remapped_file_begin(), E = PreprocessorOpts.remapped_file_end(); M != E; ++M) { - llvm::sys::PathWithStatus MPath(M->first); - if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) { - if (MainFileStatus->uniqueID == MStatus->uniqueID) { + std::string MPath(M->first); + llvm::sys::fs::UniqueID MID; + if (!llvm::sys::fs::getUniqueID(MPath, MID)) { + if (MainFileID == MID) { // We found a remapping. Try to load the resulting, remapped source. if (CreatedBuffer) { delete Buffer; @@ -1293,10 +1315,11 @@ ASTUnit::ComputePreamble(CompilerInvocation &Invocation, E = PreprocessorOpts.remapped_file_buffer_end(); M != E; ++M) { - llvm::sys::PathWithStatus MPath(M->first); - if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) { - if (MainFileStatus->uniqueID == MStatus->uniqueID) { - // We found a remapping. + std::string MPath(M->first); + llvm::sys::fs::UniqueID MID; + if (!llvm::sys::fs::getUniqueID(MPath, MID)) { + if (MainFileID == MID) { + // We found a remapping. if (CreatedBuffer) { delete Buffer; CreatedBuffer = false; @@ -1411,16 +1434,16 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( REnd = PreprocessorOpts.remapped_file_end(); !AnyFileChanged && R != REnd; ++R) { - struct stat StatBuf; - if (FileMgr->getNoncachedStatValue(R->second, StatBuf)) { + llvm::sys::fs::file_status Status; + if (FileMgr->getNoncachedStatValue(R->second, Status)) { // If we can't stat the file we're remapping to, assume that something // horrible happened. AnyFileChanged = true; break; } - - OverriddenFiles[R->first] = std::make_pair(StatBuf.st_size, - StatBuf.st_mtime); + + OverriddenFiles[R->first] = std::make_pair( + Status.getSize(), Status.getLastModificationTime().toEpochTime()); } for (PreprocessorOptions::remapped_file_buffer_iterator R = PreprocessorOpts.remapped_file_buffer_begin(), @@ -1449,12 +1472,13 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( } // The file was not remapped; check whether it has changed on disk. - struct stat StatBuf; - if (FileMgr->getNoncachedStatValue(F->first(), StatBuf)) { + llvm::sys::fs::file_status Status; + if (FileMgr->getNoncachedStatValue(F->first(), Status)) { // If we can't stat the file, assume that something horrible happened. AnyFileChanged = true; - } else if (StatBuf.st_size != F->second.first || - StatBuf.st_mtime != F->second.second) + } else if (Status.getSize() != uint64_t(F->second.first) || + Status.getLastModificationTime().toEpochTime() != + uint64_t(F->second.second)) AnyFileChanged = true; } @@ -1541,11 +1565,11 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( memset(const_cast<char*>(PreambleBuffer->getBufferStart()) + Preamble.size(), ' ', PreambleReservedSize - Preamble.size() - 1); const_cast<char*>(PreambleBuffer->getBufferEnd())[-1] = '\n'; - + // Remap the main source file to the preamble buffer. - llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].getFile()); - PreprocessorOpts.addRemappedFile(MainFilePath.str(), PreambleBuffer); - + StringRef MainFilePath = FrontendOpts.Inputs[0].getFile(); + PreprocessorOpts.addRemappedFile(MainFilePath, PreambleBuffer); + // Tell the compiler invocation to generate a temporary precompiled header. FrontendOpts.ProgramAction = frontend::GeneratePCH; // FIXME: Generate the precompiled header into memory? @@ -1570,7 +1594,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(), &Clang->getTargetOpts())); if (!Clang->hasTarget()) { - llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk(); + llvm::sys::fs::remove(FrontendOpts.OutputFile); Preamble.clear(); PreambleRebuildCounter = DefaultPreambleRebuildInterval; PreprocessorOpts.eraseRemappedFile( @@ -1608,7 +1632,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( OwningPtr<PrecompilePreambleAction> Act; Act.reset(new PrecompilePreambleAction(*this)); if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) { - llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk(); + llvm::sys::fs::remove(FrontendOpts.OutputFile); Preamble.clear(); PreambleRebuildCounter = DefaultPreambleRebuildInterval; PreprocessorOpts.eraseRemappedFile( @@ -1619,11 +1643,11 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble( Act->Execute(); Act->EndSourceFile(); - if (Diagnostics->hasErrorOccurred()) { - // There were errors parsing the preamble, so no precompiled header was - // generated. Forget that we even tried. + if (!Act->hasEmittedPreamblePCH()) { + // The preamble PCH failed (e.g. there was a module loading fatal error), + // so no precompiled header was generated. Forget that we even tried. // FIXME: Should we leave a note for ourselves to try again? - llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk(); + llvm::sys::fs::remove(FrontendOpts.OutputFile); Preamble.clear(); TopLevelDeclsInPreamble.clear(); PreambleRebuildCounter = DefaultPreambleRebuildInterval; @@ -1703,6 +1727,7 @@ void ASTUnit::transferASTDataFromCompilerInstance(CompilerInstance &CI) { CI.setFileManager(0); Target = &CI.getTarget(); Reader = CI.getModuleManager(); + HadModuleLoaderFatalFailure = CI.hadModuleLoaderFatalFailure(); } StringRef ASTUnit::getMainFileName() const { @@ -2403,10 +2428,10 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column, // Set up diagnostics, capturing any diagnostics produced. Clang->setDiagnostics(&Diag); - ProcessWarningOptions(Diag, CCInvocation->getDiagnosticOpts()); CaptureDroppedDiagnostics Capture(true, Clang->getDiagnostics(), StoredDiagnostics); + ProcessWarningOptions(Diag, CCInvocation->getDiagnosticOpts()); // Create the target instance. Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(), @@ -2461,16 +2486,19 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column, // preamble. llvm::MemoryBuffer *OverrideMainBuffer = 0; if (!getPreambleFile(this).empty()) { - using llvm::sys::FileStatus; - llvm::sys::PathWithStatus CompleteFilePath(File); - llvm::sys::PathWithStatus MainPath(OriginalSourceFile); - if (const FileStatus *CompleteFileStatus = CompleteFilePath.getFileStatus()) - if (const FileStatus *MainStatus = MainPath.getFileStatus()) - if (CompleteFileStatus->getUniqueID() == MainStatus->getUniqueID() && - Line > 1) + std::string CompleteFilePath(File); + llvm::sys::fs::UniqueID CompleteFileID; + + if (!llvm::sys::fs::getUniqueID(CompleteFilePath, CompleteFileID)) { + std::string MainPath(OriginalSourceFile); + llvm::sys::fs::UniqueID MainID; + if (!llvm::sys::fs::getUniqueID(MainPath, MainID)) { + if (CompleteFileID == MainID && Line > 1) OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(*CCInvocation, false, Line - 1); + } + } } // If the main file has been overridden due to the use of a preamble, @@ -2502,14 +2530,16 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column, } bool ASTUnit::Save(StringRef File) { + if (HadModuleLoaderFatalFailure) + return true; + // Write to a temporary file and later rename it to the actual file, to avoid // possible race conditions. SmallString<128> TempPath; TempPath = File; TempPath += "-%%%%%%%%"; int fd; - if (llvm::sys::fs::unique_file(TempPath.str(), fd, TempPath, - /*makeAbsolute=*/false)) + if (llvm::sys::fs::createUniqueFile(TempPath.str(), fd, TempPath)) return true; // FIXME: Can we somehow regenerate the stat cache here, or do we need to @@ -2627,11 +2657,6 @@ void ASTUnit::TranslateStoredDiagnostics( Result.swap(Out); } -static inline bool compLocDecl(std::pair<unsigned, Decl *> L, - std::pair<unsigned, Decl *> R) { - return L.first < R.first; -} - void ASTUnit::addFileLevelDecl(Decl *D) { assert(D); @@ -2667,8 +2692,8 @@ void ASTUnit::addFileLevelDecl(Decl *D) { return; } - LocDeclsTy::iterator - I = std::upper_bound(Decls->begin(), Decls->end(), LocDecl, compLocDecl); + LocDeclsTy::iterator I = std::upper_bound(Decls->begin(), Decls->end(), + LocDecl, llvm::less_first()); Decls->insert(I, LocDecl); } @@ -2692,9 +2717,9 @@ void ASTUnit::findFileRegionDecls(FileID File, unsigned Offset, unsigned Length, if (LocDecls.empty()) return; - LocDeclsTy::iterator - BeginIt = std::lower_bound(LocDecls.begin(), LocDecls.end(), - std::make_pair(Offset, (Decl*)0), compLocDecl); + LocDeclsTy::iterator BeginIt = + std::lower_bound(LocDecls.begin(), LocDecls.end(), + std::make_pair(Offset, (Decl *)0), llvm::less_first()); if (BeginIt != LocDecls.begin()) --BeginIt; @@ -2705,10 +2730,9 @@ void ASTUnit::findFileRegionDecls(FileID File, unsigned Offset, unsigned Length, BeginIt->second->isTopLevelDeclInObjCContainer()) --BeginIt; - LocDeclsTy::iterator - EndIt = std::upper_bound(LocDecls.begin(), LocDecls.end(), - std::make_pair(Offset+Length, (Decl*)0), - compLocDecl); + LocDeclsTy::iterator EndIt = std::upper_bound( + LocDecls.begin(), LocDecls.end(), + std::make_pair(Offset + Length, (Decl *)0), llvm::less_first()); if (EndIt != LocDecls.end()) ++EndIt; diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp index 3f80a16..0c30b04 100644 --- a/lib/Frontend/CacheTokens.cpp +++ b/lib/Frontend/CacheTokens.cpp @@ -58,16 +58,16 @@ public: class PTHEntryKeyVariant { union { const FileEntry* FE; const char* Path; }; enum { IsFE = 0x1, IsDE = 0x2, IsNoExist = 0x0 } Kind; - struct stat *StatBuf; + FileData *Data; + public: - PTHEntryKeyVariant(const FileEntry *fe) - : FE(fe), Kind(IsFE), StatBuf(0) {} + PTHEntryKeyVariant(const FileEntry *fe) : FE(fe), Kind(IsFE), Data(0) {} - PTHEntryKeyVariant(struct stat* statbuf, const char* path) - : Path(path), Kind(IsDE), StatBuf(new struct stat(*statbuf)) {} + PTHEntryKeyVariant(FileData *Data, const char *path) + : Path(path), Kind(IsDE), Data(new FileData(*Data)) {} - explicit PTHEntryKeyVariant(const char* path) - : Path(path), Kind(IsNoExist), StatBuf(0) {} + explicit PTHEntryKeyVariant(const char *path) + : Path(path), Kind(IsNoExist), Data(0) {} bool isFile() const { return Kind == IsFE; } @@ -79,22 +79,21 @@ public: void EmitData(raw_ostream& Out) { switch (Kind) { - case IsFE: + case IsFE: { // Emit stat information. - ::Emit32(Out, FE->getInode()); - ::Emit32(Out, FE->getDevice()); - ::Emit16(Out, FE->getFileMode()); + llvm::sys::fs::UniqueID UID = FE->getUniqueID(); + ::Emit64(Out, UID.getFile()); + ::Emit64(Out, UID.getDevice()); ::Emit64(Out, FE->getModificationTime()); ::Emit64(Out, FE->getSize()); - break; + } break; case IsDE: // Emit stat information. - ::Emit32(Out, (uint32_t) StatBuf->st_ino); - ::Emit32(Out, (uint32_t) StatBuf->st_dev); - ::Emit16(Out, (uint16_t) StatBuf->st_mode); - ::Emit64(Out, (uint64_t) StatBuf->st_mtime); - ::Emit64(Out, (uint64_t) StatBuf->st_size); - delete StatBuf; + ::Emit64(Out, Data->UniqueID.getFile()); + ::Emit64(Out, Data->UniqueID.getDevice()); + ::Emit64(Out, Data->ModTime); + ::Emit64(Out, Data->Size); + delete Data; break; default: break; @@ -516,18 +515,18 @@ public: StatListener(PTHMap &pm) : PM(pm) {} ~StatListener() {} - LookupResult getStat(const char *Path, struct stat &StatBuf, - bool isFile, int *FileDescriptor) { - LookupResult Result = statChained(Path, StatBuf, isFile, FileDescriptor); + LookupResult getStat(const char *Path, FileData &Data, bool isFile, + int *FileDescriptor) { + LookupResult Result = statChained(Path, Data, isFile, FileDescriptor); if (Result == CacheMissing) // Failed 'stat'. PM.insert(PTHEntryKeyVariant(Path), PTHEntry()); - else if (S_ISDIR(StatBuf.st_mode)) { + else if (Data.IsDirectory) { // Only cache directories with absolute paths. if (llvm::sys::path::is_relative(Path)) return Result; - PM.insert(PTHEntryKeyVariant(&StatBuf, Path), PTHEntry()); + PM.insert(PTHEntryKeyVariant(&Data, Path), PTHEntry()); } return Result; diff --git a/lib/Frontend/ChainedIncludesSource.cpp b/lib/Frontend/ChainedIncludesSource.cpp index cde84ca..442177e 100644 --- a/lib/Frontend/ChainedIncludesSource.cpp +++ b/lib/Frontend/ChainedIncludesSource.cpp @@ -26,9 +26,9 @@ using namespace clang; static ASTReader *createASTReader(CompilerInstance &CI, - StringRef pchFile, - SmallVector<llvm::MemoryBuffer *, 4> &memBufs, - SmallVector<std::string, 4> &bufNames, + StringRef pchFile, + SmallVectorImpl<llvm::MemoryBuffer *> &memBufs, + SmallVectorImpl<std::string> &bufNames, ASTDeserializationListener *deserialListener = 0) { Preprocessor &PP = CI.getPreprocessor(); OwningPtr<ASTReader> Reader; diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index cf856fc..eccb94c 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -111,8 +111,8 @@ static void SetUpDiagnosticLog(DiagnosticOptions *DiagOpts, if (DiagOpts->DiagnosticLogFile != "-") { // Create the output stream. llvm::raw_fd_ostream *FileOS( - new llvm::raw_fd_ostream(DiagOpts->DiagnosticLogFile.c_str(), - ErrorInfo, llvm::raw_fd_ostream::F_Append)); + new llvm::raw_fd_ostream(DiagOpts->DiagnosticLogFile.c_str(), ErrorInfo, + llvm::sys::fs::F_Append)); if (!ErrorInfo.empty()) { Diags.Report(diag::warn_fe_cc_log_diagnostics_failure) << DiagOpts->DiagnosticLogFile << ErrorInfo; @@ -138,8 +138,8 @@ static void SetupSerializedDiagnostics(DiagnosticOptions *DiagOpts, std::string ErrorInfo; OwningPtr<llvm::raw_fd_ostream> OS; OS.reset(new llvm::raw_fd_ostream(OutputFile.str().c_str(), ErrorInfo, - llvm::raw_fd_ostream::F_Binary)); - + llvm::sys::fs::F_Binary)); + if (!ErrorInfo.empty()) { Diags.Report(diag::warn_fe_serialized_diag_failure) << OutputFile << ErrorInfo; @@ -218,7 +218,7 @@ void CompilerInstance::createPreprocessor() { // Create the Preprocessor. HeaderSearch *HeaderInfo = new HeaderSearch(&getHeaderSearchOpts(), - getFileManager(), + getSourceManager(), getDiagnostics(), getLangOpts(), &getTarget()); @@ -259,7 +259,7 @@ void CompilerInstance::createPreprocessor() { AttachDependencyGraphGen(*PP, DepOpts.DOTOutputFile, getHeaderSearchOpts().Sysroot); - + // Handle generating header include information, if requested. if (DepOpts.ShowHeaderIncludes) AttachHeaderIncludeGen(*PP); @@ -270,6 +270,11 @@ void CompilerInstance::createPreprocessor() { AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/true, OutputPath, /*ShowDepth=*/false); } + + if (DepOpts.PrintShowIncludes) { + AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/false, /*OutputPath=*/"", + /*ShowDepth=*/true, /*MSStyle=*/true); + } } // ASTContext @@ -384,7 +389,7 @@ void CompilerInstance::createCodeCompletionConsumer() { } if (CompletionConsumer->isOutputBinary() && - llvm::sys::Program::ChangeStdoutToBinary()) { + llvm::sys::ChangeStdoutToBinary()) { getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary); setCodeCompletionConsumer(0); } @@ -445,7 +450,7 @@ void CompilerInstance::clearOutputFiles(bool EraseFiles) { } } } else if (!it->Filename.empty() && EraseFiles) - llvm::sys::Path(it->Filename).eraseFromDisk(); + llvm::sys::fs::remove(it->Filename); } OutputFiles.clear(); @@ -509,9 +514,8 @@ CompilerInstance::createOutputFile(StringRef OutputPath, } else if (InFile == "-") { OutFile = "-"; } else if (!Extension.empty()) { - llvm::sys::Path Path(InFile); - Path.eraseSuffix(); - Path.appendSuffix(Extension); + SmallString<128> Path(InFile); + llvm::sys::path::replace_extension(Path, Extension); OutFile = Path.str(); } else { OutFile = "-"; @@ -520,47 +524,64 @@ CompilerInstance::createOutputFile(StringRef OutputPath, OwningPtr<llvm::raw_fd_ostream> OS; std::string OSFile; - if (UseTemporary && OutFile != "-") { - // Only create the temporary if the parent directory exists (or create - // missing directories is true) and we can actually write to OutPath, - // otherwise we want to fail early. - SmallString<256> AbsPath(OutputPath); - llvm::sys::fs::make_absolute(AbsPath); - llvm::sys::Path OutPath(AbsPath); - bool ParentExists = false; - if (llvm::sys::fs::exists(llvm::sys::path::parent_path(AbsPath.str()), - ParentExists)) - ParentExists = false; - bool Exists; - if ((CreateMissingDirectories || ParentExists) && - ((llvm::sys::fs::exists(AbsPath.str(), Exists) || !Exists) || - (OutPath.isRegularFile() && OutPath.canWrite()))) { - // Create a temporary file. - SmallString<128> TempPath; - TempPath = OutFile; - TempPath += "-%%%%%%%%"; - int fd; - if (llvm::sys::fs::unique_file(TempPath.str(), fd, TempPath, - /*makeAbsolute=*/false, 0664) - == llvm::errc::success) { - OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true)); - OSFile = TempFile = TempPath.str(); + if (UseTemporary) { + if (OutFile == "-") + UseTemporary = false; + else { + llvm::sys::fs::file_status Status; + llvm::sys::fs::status(OutputPath, Status); + if (llvm::sys::fs::exists(Status)) { + // Fail early if we can't write to the final destination. + if (!llvm::sys::fs::can_write(OutputPath)) + return 0; + + // Don't use a temporary if the output is a special file. This handles + // things like '-o /dev/null' + if (!llvm::sys::fs::is_regular_file(Status)) + UseTemporary = false; } } } + if (UseTemporary) { + // Create a temporary file. + SmallString<128> TempPath; + TempPath = OutFile; + TempPath += "-%%%%%%%%"; + int fd; + llvm::error_code EC = + llvm::sys::fs::createUniqueFile(TempPath.str(), fd, TempPath); + + if (CreateMissingDirectories && + EC == llvm::errc::no_such_file_or_directory) { + StringRef Parent = llvm::sys::path::parent_path(OutputPath); + EC = llvm::sys::fs::create_directories(Parent); + if (!EC) { + EC = llvm::sys::fs::createUniqueFile(TempPath.str(), fd, TempPath); + } + } + + if (!EC) { + OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true)); + OSFile = TempFile = TempPath.str(); + } + // If we failed to create the temporary, fallback to writing to the file + // directly. This handles the corner case where we cannot write to the + // directory, but can write to the file. + } + if (!OS) { OSFile = OutFile; - OS.reset( - new llvm::raw_fd_ostream(OSFile.c_str(), Error, - (Binary ? llvm::raw_fd_ostream::F_Binary : 0))); + OS.reset(new llvm::raw_fd_ostream( + OSFile.c_str(), Error, + (Binary ? llvm::sys::fs::F_Binary : llvm::sys::fs::F_None))); if (!Error.empty()) return 0; } // Make sure the out stream file gets removed if we crash. if (RemoveFileOnSignal) - llvm::sys::RemoveFileOnSignal(llvm::sys::Path(OSFile)); + llvm::sys::RemoveFileOnSignal(OSFile); if (ResultPathName) *ResultPathName = OutFile; @@ -597,7 +618,7 @@ bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input, // Figure out where to get and map in the main file. if (InputFile != "-") { - const FileEntry *File = FileMgr.getFile(InputFile); + const FileEntry *File = FileMgr.getFile(InputFile, /*OpenFile=*/true); if (!File) { Diags.Report(diag::err_fe_error_reading) << InputFile; return false; @@ -605,26 +626,27 @@ bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input, // The natural SourceManager infrastructure can't currently handle named // pipes, but we would at least like to accept them for the main - // file. Detect them here, read them with the more generic MemoryBuffer - // function, and simply override their contents as we do for STDIN. + // file. Detect them here, read them with the volatile flag so FileMgr will + // pick up the correct size, and simply override their contents as we do for + // STDIN. if (File->isNamedPipe()) { - OwningPtr<llvm::MemoryBuffer> MB; - if (llvm::error_code ec = llvm::MemoryBuffer::getFile(InputFile, MB)) { - Diags.Report(diag::err_cannot_open_file) << InputFile << ec.message(); + std::string ErrorStr; + if (llvm::MemoryBuffer *MB = + FileMgr.getBufferForFile(File, &ErrorStr, /*isVolatile=*/true)) { + // Create a new virtual file that will have the correct size. + File = FileMgr.getVirtualFile(InputFile, MB->getBufferSize(), 0); + SourceMgr.overrideFileContents(File, MB); + } else { + Diags.Report(diag::err_cannot_open_file) << InputFile << ErrorStr; return false; } - - // Create a new virtual file that will have the correct size. - File = FileMgr.getVirtualFile(InputFile, MB->getBufferSize(), 0); - SourceMgr.overrideFileContents(File, MB.take()); } SourceMgr.createMainFileID(File, Kind); } else { OwningPtr<llvm::MemoryBuffer> SB; - if (llvm::MemoryBuffer::getSTDIN(SB)) { - // FIXME: Give ec.message() in this diag. - Diags.Report(diag::err_fe_error_reading_stdin); + if (llvm::error_code ec = llvm::MemoryBuffer::getSTDIN(SB)) { + Diags.Report(diag::err_fe_error_reading_stdin) << ec.message(); return false; } const FileEntry *File = FileMgr.getVirtualFile(SB->getBufferIdentifier(), @@ -764,6 +786,11 @@ static void compileModule(CompilerInstance &ImportingInstance, SourceLocation ImportLoc, Module *Module, StringRef ModuleFileName) { + // FIXME: have LockFileManager return an error_code so that we can + // avoid the mkdir when the directory already exists. + StringRef Dir = llvm::sys::path::parent_path(ModuleFileName); + llvm::sys::fs::create_directories(Dir); + llvm::LockFileManager Locked(ModuleFileName); switch (Locked) { case llvm::LockFileManager::LFS_Error: @@ -824,33 +851,6 @@ static void compileModule(CompilerInstance &ImportingInstance, FrontendOpts.Inputs.clear(); InputKind IK = getSourceInputKindFromOptions(*Invocation->getLangOpts()); - // Get or create the module map that we'll use to build this module. - SmallString<128> TempModuleMapFileName; - if (const FileEntry *ModuleMapFile - = ModMap.getContainingModuleMapFile(Module)) { - // Use the module map where this module resides. - FrontendOpts.Inputs.push_back(FrontendInputFile(ModuleMapFile->getName(), - IK)); - } else { - // Create a temporary module map file. - TempModuleMapFileName = Module->Name; - TempModuleMapFileName += "-%%%%%%%%.map"; - int FD; - if (llvm::sys::fs::unique_file(TempModuleMapFileName.str(), FD, - TempModuleMapFileName, - /*makeAbsolute=*/true) - != llvm::errc::success) { - ImportingInstance.getDiagnostics().Report(diag::err_module_map_temp_file) - << TempModuleMapFileName; - return; - } - // Print the module map to this file. - llvm::raw_fd_ostream OS(FD, /*shouldClose=*/true); - Module->print(OS); - FrontendOpts.Inputs.push_back( - FrontendInputFile(TempModuleMapFileName.str().str(), IK)); - } - // Don't free the remapped file buffers; they are owned by our caller. PPOpts.RetainRemappedFileBuffers = true; @@ -877,9 +877,29 @@ static void compileModule(CompilerInstance &ImportingInstance, SourceMgr.pushModuleBuildStack(Module->getTopLevelModuleName(), FullSourceLoc(ImportLoc, ImportingInstance.getSourceManager())); + // Get or create the module map that we'll use to build this module. + std::string InferredModuleMapContent; + if (const FileEntry *ModuleMapFile = + ModMap.getContainingModuleMapFile(Module)) { + // Use the module map where this module resides. + FrontendOpts.Inputs.push_back( + FrontendInputFile(ModuleMapFile->getName(), IK)); + } else { + llvm::raw_string_ostream OS(InferredModuleMapContent); + Module->print(OS); + OS.flush(); + FrontendOpts.Inputs.push_back( + FrontendInputFile("__inferred_module.map", IK)); + + const llvm::MemoryBuffer *ModuleMapBuffer = + llvm::MemoryBuffer::getMemBuffer(InferredModuleMapContent); + ModuleMapFile = Instance.getFileManager().getVirtualFile( + "__inferred_module.map", InferredModuleMapContent.size(), 0); + SourceMgr.overrideFileContents(ModuleMapFile, ModuleMapBuffer); + } // Construct a module-generating action. - GenerateModuleAction CreateModuleAction; + GenerateModuleAction CreateModuleAction(Module->IsSystem); // Execute the action to actually build the module in-place. Use a separate // thread so that we get a stack large enough. @@ -894,8 +914,6 @@ static void compileModule(CompilerInstance &ImportingInstance, // be nice to do this with RemoveFileOnSignal when we can. However, that // doesn't make sense for all clients, so clean this up manually. Instance.clearOutputFiles(/*EraseFiles=*/true); - if (!TempModuleMapFileName.empty()) - llvm::sys::Path(TempModuleMapFileName).eraseFromDisk(); // We've rebuilt a module. If we're allowed to generate or update the global // module index, record that fact in the importing compiler instance. @@ -994,7 +1012,7 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro, static void writeTimestampFile(StringRef TimestampFile) { std::string ErrorInfo; llvm::raw_fd_ostream Out(TimestampFile.str().c_str(), ErrorInfo, - llvm::raw_fd_ostream::F_Binary); + llvm::sys::fs::F_Binary); } /// \brief Prune the module cache of modules that haven't been accessed in @@ -1035,8 +1053,7 @@ static void pruneModuleCache(const HeaderSearchOptions &HSOpts) { Dir(ModuleCachePathNative.str(), EC), DirEnd; Dir != DirEnd && !EC; Dir.increment(EC)) { // If we don't have a directory, there's nothing to look into. - bool IsDirectory; - if (llvm::sys::fs::is_directory(Dir->path(), IsDirectory) || !IsDirectory) + if (!llvm::sys::fs::is_directory(Dir->path())) continue; // Walk all of the files within this directory. @@ -1086,23 +1103,23 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, ModuleIdPath Path, Module::NameVisibilityKind Visibility, bool IsInclusionDirective) { + // Determine what file we're searching from. + StringRef ModuleName = Path[0].first->getName(); + SourceLocation ModuleNameLoc = Path[0].second; + // If we've already handled this import, just return the cached result. // This one-element cache is important to eliminate redundant diagnostics // when both the preprocessor and parser see the same import declaration. if (!ImportLoc.isInvalid() && LastModuleImportLoc == ImportLoc) { // Make the named module visible. - if (LastModuleImportResult) + if (LastModuleImportResult && ModuleName != getLangOpts().CurrentModule) ModuleManager->makeModuleVisible(LastModuleImportResult, Visibility, ImportLoc, /*Complain=*/false); return LastModuleImportResult; } - - // Determine what file we're searching from. - StringRef ModuleName = Path[0].first->getName(); - SourceLocation ModuleNameLoc = Path[0].second; clang::Module *Module = 0; - + // If we don't already have information on this module, load the module now. llvm::DenseMap<const IdentifierInfo *, clang::Module *>::iterator Known = KnownModules.find(Path[0].first); @@ -1164,15 +1181,9 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, case ASTReader::Success: break; - case ASTReader::OutOfDate: { - // The module file is out-of-date. Remove it, then rebuild it. - bool Existed; - llvm::sys::fs::remove(ModuleFileName, Existed); - } - // Fall through to build the module again. - + case ASTReader::OutOfDate: case ASTReader::Missing: { - // The module file is (now) missing. Build it. + // The module file is missing or out-of-date. Build it. // If we don't have a module, we don't know how to build the module file. // Complain and return. @@ -1247,12 +1258,14 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, case ASTReader::VersionMismatch: case ASTReader::ConfigurationMismatch: case ASTReader::HadErrors: + ModuleLoader::HadFatalFailure = true; // FIXME: The ASTReader will already have complained, but can we showhorn // that diagnostic information into a more useful form? KnownModules[Path[0].first] = 0; return ModuleLoadResult(); case ASTReader::Failure: + ModuleLoader::HadFatalFailure = true; // Already complained, but note now that we failed. KnownModules[Path[0].first] = 0; ModuleBuildFailed = true; @@ -1346,11 +1359,11 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, } // Check whether this module is available. - StringRef Feature; - if (!Module->isAvailable(getLangOpts(), getTarget(), Feature)) { + clang::Module::Requirement Requirement; + if (!Module->isAvailable(getLangOpts(), getTarget(), Requirement)) { getDiagnostics().Report(ImportLoc, diag::err_module_unavailable) << Module->getFullModuleName() - << Feature + << Requirement.second << Requirement.first << SourceRange(Path.front().second, Path.back().second); LastModuleImportLoc = ImportLoc; LastModuleImportResult = ModuleLoadResult(); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 42ea96f..8db5cf1 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -11,13 +11,11 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/Version.h" -#include "clang/Driver/Arg.h" -#include "clang/Driver/ArgList.h" #include "clang/Driver/DriverDiagnostic.h" -#include "clang/Driver/OptTable.h" -#include "clang/Driver/Option.h" #include "clang/Driver/Options.h" +#include "clang/Driver/Util.h" #include "clang/Frontend/LangStandard.h" +#include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Serialization/ASTReader.h" #include "llvm/ADT/Hashing.h" @@ -26,10 +24,17 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Option/OptTable.h" +#include "llvm/Option/Option.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" #include "llvm/Support/system_error.h" +#include <sys/stat.h> using namespace clang; //===----------------------------------------------------------------------===// @@ -56,6 +61,7 @@ CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &X) using namespace clang::driver; using namespace clang::driver::options; +using namespace llvm::opt; // @@ -78,7 +84,7 @@ static unsigned getOptimizationLevel(ArgList &Args, InputKind IK, if (S == "s" || S == "z" || S.empty()) return 2; - return Args.getLastArgIntValue(OPT_O, DefaultOpt, Diags); + return getLastArgIntValue(Args, OPT_O, DefaultOpt, Diags); } return DefaultOpt; @@ -162,7 +168,7 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, if (Arg *A = Args.getLastArg(OPT_analyzer_output)) { StringRef Name = A->getValue(); AnalysisDiagClients Value = llvm::StringSwitch<AnalysisDiagClients>(Name) -#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREAT) \ +#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) \ .Case(CMDFLAG, PD_##NAME) #include "clang/StaticAnalyzer/Core/Analyses.def" .Default(NUM_ANALYSIS_DIAG_CLIENTS); @@ -221,11 +227,12 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, Opts.AnalyzeSpecificFunction = Args.getLastArgValue(OPT_analyze_function); Opts.UnoptimizedCFG = Args.hasArg(OPT_analysis_UnoptimizedCFG); Opts.TrimGraph = Args.hasArg(OPT_trim_egraph); - Opts.maxBlockVisitOnPath = Args.getLastArgIntValue(OPT_analyzer_max_loop, 4, Diags); + Opts.maxBlockVisitOnPath = + getLastArgIntValue(Args, OPT_analyzer_max_loop, 4, Diags); Opts.PrintStats = Args.hasArg(OPT_analyzer_stats); Opts.InlineMaxStackDepth = - Args.getLastArgIntValue(OPT_analyzer_inline_max_stack_depth, - Opts.InlineMaxStackDepth, Diags); + getLastArgIntValue(Args, OPT_analyzer_inline_max_stack_depth, + Opts.InlineMaxStackDepth, Diags); Opts.CheckersControlList.clear(); for (arg_iterator it = Args.filtered_begin(OPT_analyzer_checker, @@ -292,14 +299,15 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, using namespace options; bool Success = true; - unsigned OptLevel = getOptimizationLevel(Args, IK, Diags); - if (OptLevel > 3) { - Diags.Report(diag::err_drv_invalid_value) - << Args.getLastArg(OPT_O)->getAsString(Args) << OptLevel; - OptLevel = 3; - Success = false; + Opts.OptimizationLevel = getOptimizationLevel(Args, IK, Diags); + // TODO: This could be done in Driver + unsigned MaxOptLevel = 3; + if (Opts.OptimizationLevel > MaxOptLevel) { + // If the optimization level is not supported, fall back on the default optimization + Diags.Report(diag::warn_drv_optimization_value) + << Args.getLastArg(OPT_O)->getAsString(Args) << "-O" << MaxOptLevel; + Opts.OptimizationLevel = MaxOptLevel; } - Opts.OptimizationLevel = OptLevel; // We must always run at least the always inlining pass. Opts.setInlining( @@ -312,7 +320,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, if (Args.hasArg(OPT_gline_tables_only)) { Opts.setDebugInfo(CodeGenOptions::DebugLineTablesOnly); - } else if (Args.hasArg(OPT_g_Flag)) { + } else if (Args.hasArg(OPT_g_Flag) || Args.hasArg(OPT_gdwarf_2) || + Args.hasArg(OPT_gdwarf_3) || Args.hasArg(OPT_gdwarf_4)) { if (Args.hasFlag(OPT_flimit_debug_info, OPT_fno_limit_debug_info, true)) Opts.setDebugInfo(CodeGenOptions::LimitedDebugInfo); else @@ -320,6 +329,15 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, } Opts.DebugColumnInfo = Args.hasArg(OPT_dwarf_column_info); Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file); + if (Args.hasArg(OPT_gdwarf_2)) + Opts.DwarfVersion = 2; + else if (Args.hasArg(OPT_gdwarf_3)) + Opts.DwarfVersion = 3; + else if (Args.hasArg(OPT_gdwarf_4)) + Opts.DwarfVersion = 4; + else if (Opts.getDebugInfo() != CodeGenOptions::NoDebugInfo) + // Default Dwarf version is 4 if we are generating debug information. + Opts.DwarfVersion = 4; Opts.DisableLLVMOpts = Args.hasArg(OPT_disable_llvm_optzns); Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone); @@ -327,7 +345,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.UseRegisterSizedBitfieldAccess = Args.hasArg( OPT_fuse_register_sized_bitfield_access); Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing); - Opts.StructPathTBAA = Args.hasArg(OPT_struct_path_tbaa); + Opts.StructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa); Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags); Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants); Opts.NoCommon = Args.hasArg(OPT_fno_common); @@ -335,10 +353,13 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.OptimizeSize = getOptimizationLevelSize(Args); Opts.SimplifyLibCalls = !(Args.hasArg(OPT_fno_builtin) || Args.hasArg(OPT_ffreestanding)); - Opts.UnrollLoops = Args.hasArg(OPT_funroll_loops) || - (Opts.OptimizationLevel > 1 && !Opts.OptimizeSize); + Opts.UnrollLoops = + Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops, + (Opts.OptimizationLevel > 1 && !Opts.OptimizeSize)); + Opts.RerollLoops = Args.hasArg(OPT_freroll_loops); Opts.Autolink = !Args.hasArg(OPT_fno_autolink); + Opts.SampleProfileFile = Args.getLastArgValue(OPT_fprofile_sample_use_EQ); Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose); Opts.ObjCAutoRefCountExceptions = Args.hasArg(OPT_fobjc_arc_exceptions); Opts.CUDAIsDevice = Args.hasArg(OPT_fcuda_is_device); @@ -347,6 +368,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.CodeModel = Args.getLastArgValue(OPT_mcode_model); Opts.DebugPass = Args.getLastArgValue(OPT_mdebug_pass); Opts.DisableFPElim = Args.hasArg(OPT_mdisable_fp_elim); + Opts.DisableFree = Args.hasArg(OPT_disable_free); Opts.DisableTailCalls = Args.hasArg(OPT_mdisable_tail_calls); Opts.FloatABI = Args.getLastArgValue(OPT_mfloat_abi); Opts.HiddenWeakVTables = Args.hasArg(OPT_fhidden_weak_vtables); @@ -360,7 +382,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Args.hasArg(OPT_cl_fast_relaxed_math)); Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss); Opts.BackendOptions = Args.getAllArgValues(OPT_backend_option); - Opts.NumRegisterParameters = Args.getLastArgIntValue(OPT_mregparm, 0, Diags); + Opts.NumRegisterParameters = getLastArgIntValue(Args, OPT_mregparm, 0, Diags); Opts.NoGlobalMerge = Args.hasArg(OPT_mno_global_merge); Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack); Opts.EnableSegmentedStacks = Args.hasArg(OPT_split_stacks); @@ -379,8 +401,14 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.TrapFuncName = Args.getLastArgValue(OPT_ftrap_function_EQ); Opts.UseInitArray = Args.hasArg(OPT_fuse_init_array); - Opts.FunctionSections = Args.hasArg(OPT_ffunction_sections); - Opts.DataSections = Args.hasArg(OPT_fdata_sections); + Opts.FunctionSections = Args.hasFlag(OPT_ffunction_sections, + OPT_fno_function_sections, false); + Opts.DataSections = Args.hasFlag(OPT_fdata_sections, + OPT_fno_data_sections, false); + + Opts.VectorizeBB = Args.hasArg(OPT_vectorize_slp_aggressive); + Opts.VectorizeLoop = Args.hasArg(OPT_vectorize_loops); + Opts.VectorizeSLP = Args.hasArg(OPT_vectorize_slp); Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name); Opts.VerifyModule = !Args.hasArg(OPT_disable_llvm_verifier); @@ -419,7 +447,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.SanitizeUndefinedTrapOnError = Args.hasArg(OPT_fsanitize_undefined_trap_on_error); Opts.SSPBufferSize = - Args.getLastArgIntValue(OPT_stack_protector_buffer_size, 8, Diags); + getLastArgIntValue(Args, OPT_stack_protector_buffer_size, 8, Diags); Opts.StackRealignment = Args.hasArg(OPT_mstackrealign); if (Arg *A = Args.getLastArg(OPT_mstack_alignment)) { StringRef Val = A->getValue(); @@ -472,6 +500,17 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val; } + if (Arg *A = Args.getLastArg(OPT_fpcc_struct_return, OPT_freg_struct_return)) { + if (A->getOption().matches(OPT_fpcc_struct_return)) { + Opts.setStructReturnConvention(CodeGenOptions::SRCK_OnStack); + } else { + assert(A->getOption().matches(OPT_freg_struct_return)); + Opts.setStructReturnConvention(CodeGenOptions::SRCK_InRegs); + } + } + + Opts.DependentLibraries = Args.getAllArgValues(OPT_dependent_lib); + return Success; } @@ -485,6 +524,7 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts, Opts.ShowHeaderIncludes = Args.hasArg(OPT_H); Opts.HeaderIncludeOutputFile = Args.getLastArgValue(OPT_header_include_file); Opts.AddMissingHeaderDeps = Args.hasArg(OPT_MG); + Opts.PrintShowIncludes = Args.hasArg(OPT_show_includes); Opts.DOTOutputFile = Args.getLastArgValue(OPT_dependency_dot); } @@ -509,6 +549,8 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, Opts.ShowLocation = !Args.hasArg(OPT_fno_show_source_location); Opts.ShowOptionNames = Args.hasArg(OPT_fdiagnostics_show_option); + llvm::sys::Process::UseANSIEscapeCodes(Args.hasArg(OPT_fansi_escape_codes)); + // Default behavior is to not to show note include stacks. Opts.ShowNoteIncludeStack = false; if (Arg *A = Args.getLastArg(OPT_fdiagnostics_show_note_include_stack, @@ -552,7 +594,10 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, Opts.setFormat(DiagnosticOptions::Clang); else if (Format == "msvc") Opts.setFormat(DiagnosticOptions::Msvc); - else if (Format == "vi") + else if (Format == "msvc-fallback") { + Opts.setFormat(DiagnosticOptions::Msvc); + Opts.CLFallbackMode = true; + } else if (Format == "vi") Opts.setFormat(DiagnosticOptions::Vi); else { Success = false; @@ -568,19 +613,17 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, Opts.VerifyDiagnostics = Args.hasArg(OPT_verify); Opts.ElideType = !Args.hasArg(OPT_fno_elide_type); Opts.ShowTemplateTree = Args.hasArg(OPT_fdiagnostics_show_template_tree); - Opts.ErrorLimit = Args.getLastArgIntValue(OPT_ferror_limit, 0, Diags); - Opts.MacroBacktraceLimit - = Args.getLastArgIntValue(OPT_fmacro_backtrace_limit, + Opts.ErrorLimit = getLastArgIntValue(Args, OPT_ferror_limit, 0, Diags); + Opts.MacroBacktraceLimit = + getLastArgIntValue(Args, OPT_fmacro_backtrace_limit, DiagnosticOptions::DefaultMacroBacktraceLimit, Diags); - Opts.TemplateBacktraceLimit - = Args.getLastArgIntValue(OPT_ftemplate_backtrace_limit, - DiagnosticOptions::DefaultTemplateBacktraceLimit, - Diags); - Opts.ConstexprBacktraceLimit - = Args.getLastArgIntValue(OPT_fconstexpr_backtrace_limit, - DiagnosticOptions::DefaultConstexprBacktraceLimit, - Diags); - Opts.TabStop = Args.getLastArgIntValue(OPT_ftabstop, + Opts.TemplateBacktraceLimit = getLastArgIntValue( + Args, OPT_ftemplate_backtrace_limit, + DiagnosticOptions::DefaultTemplateBacktraceLimit, Diags); + Opts.ConstexprBacktraceLimit = getLastArgIntValue( + Args, OPT_fconstexpr_backtrace_limit, + DiagnosticOptions::DefaultConstexprBacktraceLimit, Diags); + Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop, DiagnosticOptions::DefaultTabStop, Diags); if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) { Opts.TabStop = DiagnosticOptions::DefaultTabStop; @@ -588,7 +631,7 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, Diags->Report(diag::warn_ignoring_ftabstop_value) << Opts.TabStop << DiagnosticOptions::DefaultTabStop; } - Opts.MessageLength = Args.getLastArgIntValue(OPT_fmessage_length, 0, Diags); + Opts.MessageLength = getLastArgIntValue(Args, OPT_fmessage_length, 0, Diags); addWarningArgs(Args, Opts.Warnings); return Success; @@ -610,8 +653,6 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::ASTDeclList; break; case OPT_ast_dump: Opts.ProgramAction = frontend::ASTDump; break; - case OPT_ast_dump_xml: - Opts.ProgramAction = frontend::ASTDumpXML; break; case OPT_ast_print: Opts.ProgramAction = frontend::ASTPrint; break; case OPT_ast_view: @@ -717,6 +758,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.FixAndRecompile = Args.hasArg(OPT_fixit_recompile); Opts.FixToTemporaries = Args.hasArg(OPT_fixit_to_temp); Opts.ASTDumpFilter = Args.getLastArgValue(OPT_ast_dump_filter); + Opts.ASTDumpLookups = Args.hasArg(OPT_ast_dump_lookups); Opts.UseGlobalModuleIndex = !Args.hasArg(OPT_fno_modules_global_index); Opts.GenerateGlobalModuleIndex = Opts.UseGlobalModuleIndex; @@ -758,6 +800,30 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Literals; if (Args.hasArg(OPT_objcmt_migrate_subscripting)) Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Subscripting; + if (Args.hasArg(OPT_objcmt_migrate_property)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Property; + if (Args.hasArg(OPT_objcmt_migrate_readonly_property)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ReadonlyProperty; + if (Args.hasArg(OPT_objcmt_migrate_readwrite_property)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ReadwriteProperty; + if (Args.hasArg(OPT_objcmt_migrate_annotation)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Annotation; + if (Args.hasArg(OPT_objcmt_returns_innerpointer_property)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ReturnsInnerPointerProperty; + if (Args.hasArg(OPT_objcmt_migrate_instancetype)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Instancetype; + if (Args.hasArg(OPT_objcmt_migrate_nsmacros)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_NsMacros; + if (Args.hasArg(OPT_objcmt_migrate_protocol_conformance)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_ProtocolConformance; + if (Args.hasArg(OPT_objcmt_atomic_property)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_AtomicProperty; + if (Args.hasArg(OPT_objcmt_ns_nonatomic_iosonly)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty; + if (Args.hasArg(OPT_objcmt_migrate_all)) + Opts.ObjCMTAction |= FrontendOptions::ObjCMT_MigrateDecls; + + Opts.ObjCMTWhiteListPath = Args.getLastArgValue(OPT_objcmt_white_list_dir_path); if (Opts.ARCMTAction != FrontendOptions::ARCMT_None && Opts.ObjCMTAction != FrontendOptions::ObjCMT_None) { @@ -816,16 +882,14 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, std::string CompilerInvocation::GetResourcesPath(const char *Argv0, void *MainAddr) { - llvm::sys::Path P = llvm::sys::Path::GetMainExecutable(Argv0, MainAddr); + SmallString<128> P(llvm::sys::fs::getMainExecutable(Argv0, MainAddr)); - if (!P.isEmpty()) { - P.eraseComponent(); // Remove /clang from foo/bin/clang - P.eraseComponent(); // Remove /bin from foo/bin + if (!P.empty()) { + llvm::sys::path::remove_filename(P); // Remove /clang from foo/bin/clang + llvm::sys::path::remove_filename(P); // Remove /bin from foo/bin // Get foo/lib/clang/<version>/include - P.appendComponent("lib"); - P.appendComponent("clang"); - P.appendComponent(CLANG_VERSION_STRING); + llvm::sys::path::append(P, "lib", "clang", CLANG_VERSION_STRING); } return P.str(); @@ -843,15 +907,21 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) { Opts.ResourceDir = Args.getLastArgValue(OPT_resource_dir); Opts.ModuleCachePath = Args.getLastArgValue(OPT_fmodules_cache_path); Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash); - Opts.ModuleCachePruneInterval - = Args.getLastArgIntValue(OPT_fmodules_prune_interval, 7*24*60*60); - Opts.ModuleCachePruneAfter - = Args.getLastArgIntValue(OPT_fmodules_prune_after, 31*24*60*60); + // -fmodules implies -fmodule-maps + Opts.ModuleMaps = Args.hasArg(OPT_fmodule_maps) || Args.hasArg(OPT_fmodules); + Opts.ModuleCachePruneInterval = + getLastArgIntValue(Args, OPT_fmodules_prune_interval, 7 * 24 * 60 * 60); + Opts.ModuleCachePruneAfter = + getLastArgIntValue(Args, OPT_fmodules_prune_after, 31 * 24 * 60 * 60); for (arg_iterator it = Args.filtered_begin(OPT_fmodules_ignore_macro), - ie = Args.filtered_end(); it != ie; ++it) { + ie = Args.filtered_end(); + it != ie; ++it) { StringRef MacroDef = (*it)->getValue(); Opts.ModulesIgnoreMacros.insert(MacroDef.split('=').first); } + std::vector<std::string> ModuleMapFiles = + Args.getAllArgValues(OPT_fmodule_map_file); + Opts.ModuleMapFiles.insert(ModuleMapFiles.begin(), ModuleMapFiles.end()); // Add -I..., -F..., and -index-header-map options in order. bool IsIndexHeaderMap = false; @@ -1032,6 +1102,9 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, Opts.Trigraphs = !Opts.GNUMode; Opts.DollarIdents = !Opts.AsmPreprocessor; + + // C++1y onwards has sized global deallocation functions. + Opts.SizedDeallocation = Opts.CPlusPlus1y; } /// Attempt to parse a visibility value out of the given argument. @@ -1157,6 +1230,10 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, if (Args.hasArg(OPT_fno_objc_infer_related_result_type)) Opts.ObjCInferRelatedResultType = 0; + + if (Args.hasArg(OPT_fobjc_subscripting_legacy_runtime)) + Opts.ObjCSubscriptingLegacyRuntime = + (Opts.ObjCRuntime.getKind() == ObjCRuntime::FragileMacOSX); } if (Args.hasArg(OPT_fgnu89_inline)) @@ -1217,7 +1294,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, = Args.hasArg(OPT_fms_extensions) || Args.hasArg(OPT_fms_compatibility); Opts.MicrosoftMode = Args.hasArg(OPT_fms_compatibility); Opts.AsmBlocks = Args.hasArg(OPT_fasm_blocks) || Opts.MicrosoftExt; - Opts.MSCVersion = Args.getLastArgIntValue(OPT_fmsc_version, 0, Diags); + Opts.MSCVersion = getLastArgIntValue(Args, OPT_fmsc_version, 0, Diags); Opts.Borland = Args.hasArg(OPT_fborland_extensions); Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings); Opts.ConstStrings = Args.hasFlag(OPT_fconst_strings, OPT_fno_const_strings, @@ -1236,36 +1313,43 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.Blocks = Args.hasArg(OPT_fblocks); Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional); Opts.Modules = Args.hasArg(OPT_fmodules); - Opts.CharIsSigned = !Args.hasArg(OPT_fno_signed_char); + Opts.ModulesDeclUse = Args.hasArg(OPT_fmodules_decluse); + Opts.CharIsSigned = Opts.OpenCL || !Args.hasArg(OPT_fno_signed_char); Opts.WChar = Opts.CPlusPlus && !Args.hasArg(OPT_fno_wchar); Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar); Opts.ShortEnums = Args.hasArg(OPT_fshort_enums); Opts.Freestanding = Args.hasArg(OPT_ffreestanding); Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; + Opts.NoMathBuiltin = Args.hasArg(OPT_fno_math_builtin); Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new); + Opts.SizedDeallocation |= Args.hasArg(OPT_fsized_deallocation); Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions); Opts.AccessControl = !Args.hasArg(OPT_fno_access_control); Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors); - Opts.MathErrno = Args.hasArg(OPT_fmath_errno); - Opts.InstantiationDepth = Args.getLastArgIntValue(OPT_ftemplate_depth, 256, - Diags); - Opts.ConstexprCallDepth = Args.getLastArgIntValue(OPT_fconstexpr_depth, 512, - Diags); - Opts.BracketDepth = Args.getLastArgIntValue(OPT_fbracket_depth, 256, Diags); + Opts.MathErrno = !Opts.OpenCL && Args.hasArg(OPT_fmath_errno); + Opts.InstantiationDepth = + getLastArgIntValue(Args, OPT_ftemplate_depth, 256, Diags); + Opts.ArrowDepth = + getLastArgIntValue(Args, OPT_foperator_arrow_depth, 256, Diags); + Opts.ConstexprCallDepth = + getLastArgIntValue(Args, OPT_fconstexpr_depth, 512, Diags); + Opts.ConstexprStepLimit = + getLastArgIntValue(Args, OPT_fconstexpr_steps, 1048576, Diags); + Opts.BracketDepth = getLastArgIntValue(Args, OPT_fbracket_depth, 256, Diags); Opts.DelayedTemplateParsing = Args.hasArg(OPT_fdelayed_template_parsing); - Opts.NumLargeByValueCopy = Args.getLastArgIntValue(OPT_Wlarge_by_value_copy_EQ, - 0, Diags); + Opts.NumLargeByValueCopy = + getLastArgIntValue(Args, OPT_Wlarge_by_value_copy_EQ, 0, Diags); Opts.MSBitfields = Args.hasArg(OPT_mms_bitfields); Opts.ObjCConstantStringClass = Args.getLastArgValue(OPT_fconstant_string_class); Opts.ObjCDefaultSynthProperties = - Args.hasArg(OPT_fobjc_default_synthesize_properties); + !Args.hasArg(OPT_disable_objc_default_synthesize_properties); Opts.EncodeExtendedBlockSig = Args.hasArg(OPT_fencode_extended_block_signature); Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls); - Opts.PackStruct = Args.getLastArgIntValue(OPT_fpack_struct_EQ, 0, Diags); - Opts.PICLevel = Args.getLastArgIntValue(OPT_pic_level, 0, Diags); - Opts.PIELevel = Args.getLastArgIntValue(OPT_pie_level, 0, Diags); + Opts.PackStruct = getLastArgIntValue(Args, OPT_fpack_struct_EQ, 0, Diags); + Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags); + Opts.PIELevel = getLastArgIntValue(Args, OPT_pie_level, 0, Diags); Opts.Static = Args.hasArg(OPT_static_define); Opts.DumpRecordLayoutsSimple = Args.hasArg(OPT_fdump_record_layouts_simple); Opts.DumpRecordLayouts = Opts.DumpRecordLayoutsSimple @@ -1285,6 +1369,28 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.ApplePragmaPack = Args.hasArg(OPT_fapple_pragma_pack); Opts.CurrentModule = Args.getLastArgValue(OPT_fmodule_name); + if (Arg *A = Args.getLastArg(OPT_faddress_space_map_mangling_EQ)) { + switch (llvm::StringSwitch<unsigned>(A->getValue()) + .Case("target", LangOptions::ASMM_Target) + .Case("no", LangOptions::ASMM_Off) + .Case("yes", LangOptions::ASMM_On) + .Default(255)) { + default: + Diags.Report(diag::err_drv_invalid_value) + << "-faddress-space-map-mangling=" << A->getValue(); + break; + case LangOptions::ASMM_Target: + Opts.setAddressSpaceMapMangling(LangOptions::ASMM_Target); + break; + case LangOptions::ASMM_On: + Opts.setAddressSpaceMapMangling(LangOptions::ASMM_On); + break; + case LangOptions::ASMM_Off: + Opts.setAddressSpaceMapMangling(LangOptions::ASMM_Off); + break; + } + } + // Check if -fopenmp is specified. Opts.OpenMP = Args.hasArg(OPT_fopenmp); @@ -1310,7 +1416,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.RetainCommentsFromSystemHeaders = Args.hasArg(OPT_fretain_comments_from_system_headers); - unsigned SSP = Args.getLastArgIntValue(OPT_stack_protector, 0, Diags); + unsigned SSP = getLastArgIntValue(Args, OPT_stack_protector, 0, Diags); switch (SSP) { default: Diags.Report(diag::err_drv_invalid_value) @@ -1454,7 +1560,6 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, switch (Action) { case frontend::ASTDeclList: case frontend::ASTDump: - case frontend::ASTDumpXML: case frontend::ASTPrint: case frontend::ASTView: case frontend::EmitAssembly: @@ -1502,6 +1607,7 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) { Opts.ABI = Args.getLastArgValue(OPT_target_abi); Opts.CXXABI = Args.getLastArgValue(OPT_cxx_abi); Opts.CPU = Args.getLastArgValue(OPT_target_cpu); + Opts.FPMath = Args.getLastArgValue(OPT_mfpmath); Opts.FeaturesAsWritten = Args.getAllArgValues(OPT_target_feature); Opts.LinkerVersion = Args.getLastArgValue(OPT_target_linker_version); Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple)); @@ -1521,9 +1627,11 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, // Parse the arguments. OwningPtr<OptTable> Opts(createDriverOptTable()); + const unsigned IncludedFlagsBitmask = options::CC1Option; unsigned MissingArgIndex, MissingArgCount; OwningPtr<InputArgList> Args( - Opts->ParseArgs(ArgBegin, ArgEnd,MissingArgIndex, MissingArgCount)); + Opts->ParseArgs(ArgBegin, ArgEnd, MissingArgIndex, MissingArgCount, + IncludedFlagsBitmask)); // Check for missing argument error. if (MissingArgCount) { @@ -1539,15 +1647,6 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, Success = false; } - // Issue errors on arguments that are not valid for CC1. - for (ArgList::iterator I = Args->begin(), E = Args->end(); - I != E; ++I) { - if (!(*I)->getOption().hasFlag(options::CC1Option)) { - Diags.Report(diag::err_drv_unknown_argument) << (*I)->getAsString(*Args); - Success = false; - } - } - Success = ParseAnalyzerArgs(*Res.getAnalyzerOpts(), *Args, Diags) && Success; Success = ParseMigratorArgs(Res.getMigratorOpts(), *Args) && Success; ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), *Args); @@ -1687,7 +1786,8 @@ std::string CompilerInvocation::getModuleHash() const { hsOpts.UseStandardCXXIncludes, hsOpts.UseLibcxx); - // Darwin-specific hack: if we have a sysroot, use the contents of + // Darwin-specific hack: if we have a sysroot, use the contents and + // modification time of // $sysroot/System/Library/CoreServices/SystemVersion.plist // as part of the module hash. if (!hsOpts.Sysroot.empty()) { @@ -1698,10 +1798,31 @@ std::string CompilerInvocation::getModuleHash() const { llvm::sys::path::append(systemVersionFile, "Library"); llvm::sys::path::append(systemVersionFile, "CoreServices"); llvm::sys::path::append(systemVersionFile, "SystemVersion.plist"); - if (!llvm::MemoryBuffer::getFile(systemVersionFile, buffer)) { + if (!llvm::MemoryBuffer::getFile(systemVersionFile.str(), buffer)) { code = hash_combine(code, buffer.get()->getBuffer()); + + struct stat statBuf; + if (stat(systemVersionFile.c_str(), &statBuf) == 0) + code = hash_combine(code, statBuf.st_mtime); } } return llvm::APInt(64, code).toString(36, /*Signed=*/false); } + +namespace clang { + +// Declared in clang/Frontend/Utils.h. +int getLastArgIntValue(const ArgList &Args, OptSpecifier Id, int Default, + DiagnosticsEngine *Diags) { + int Res = Default; + if (Arg *A = Args.getLastArg(Id)) { + if (StringRef(A->getValue()).getAsInteger(10, Res)) { + if (Diags) + Diags->Report(diag::err_drv_invalid_int_value) << A->getAsString(Args) + << A->getValue(); + } + } + return Res; +} +} diff --git a/lib/Frontend/CreateInvocationFromCommandLine.cpp b/lib/Frontend/CreateInvocationFromCommandLine.cpp index e25eb43..78f39d4 100644 --- a/lib/Frontend/CreateInvocationFromCommandLine.cpp +++ b/lib/Frontend/CreateInvocationFromCommandLine.cpp @@ -13,15 +13,16 @@ #include "clang/Frontend/Utils.h" #include "clang/Basic/DiagnosticOptions.h" -#include "clang/Driver/ArgList.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" #include "clang/Driver/Options.h" #include "clang/Driver/Tool.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "llvm/Option/ArgList.h" #include "llvm/Support/Host.h" using namespace clang; +using namespace llvm::opt; /// createInvocationFromCommandLine - Construct a compiler invocation object for /// a command line argument vector. @@ -55,7 +56,7 @@ clang::createInvocationFromCommandLine(ArrayRef<const char *> ArgList, // Just print the cc1 options if -### was present. if (C->getArgs().hasArg(driver::options::OPT__HASH_HASH_HASH)) { - C->PrintJob(llvm::errs(), C->getJobs(), "\n", true); + C->getJobs().Print(llvm::errs(), "\n", true); return 0; } @@ -65,7 +66,7 @@ clang::createInvocationFromCommandLine(ArrayRef<const char *> ArgList, if (Jobs.size() != 1 || !isa<driver::Command>(*Jobs.begin())) { SmallString<256> Msg; llvm::raw_svector_ostream OS(Msg); - C->PrintJob(OS, C->getJobs(), "; ", true); + Jobs.Print(OS, "; ", true); Diags->Report(diag::err_fe_expected_compiler_job) << OS.str(); return 0; } @@ -76,7 +77,7 @@ clang::createInvocationFromCommandLine(ArrayRef<const char *> ArgList, return 0; } - const driver::ArgStringList &CCArgs = Cmd->getArguments(); + const ArgStringList &CCArgs = Cmd->getArguments(); OwningPtr<CompilerInvocation> CI(new CompilerInvocation()); if (!CompilerInvocation::CreateFromArgs(*CI, const_cast<const char **>(CCArgs.data()), diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp index 628def6..4037af9 100644 --- a/lib/Frontend/DependencyFile.cpp +++ b/lib/Frontend/DependencyFile.cpp @@ -21,6 +21,7 @@ #include "clang/Lex/PPCallbacks.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/StringSet.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" @@ -165,7 +166,8 @@ static void PrintFilename(raw_ostream &OS, StringRef Filename) { void DependencyFileCallback::OutputDependencyFile() { if (SeenMissingHeader) { - llvm::sys::Path(OutputFile).eraseFromDisk(); + bool existed; + llvm::sys::fs::remove(OutputFile, existed); return; } diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp index ece51a3..075fe93 100644 --- a/lib/Frontend/FrontendAction.cpp +++ b/lib/Frontend/FrontendAction.cpp @@ -429,9 +429,9 @@ void FrontendAction::EndSourceFile() { llvm::errs() << "\n"; } - // Cleanup the output streams, and erase the output files if we encountered - // an error. - CI.clearOutputFiles(/*EraseFiles=*/CI.getDiagnostics().hasErrorOccurred()); + // Cleanup the output streams, and erase the output files if instructed by the + // FrontendAction. + CI.clearOutputFiles(/*EraseFiles=*/shouldEraseOutputFiles()); if (isCurrentFileAST()) { CI.takeSema(); @@ -445,12 +445,18 @@ void FrontendAction::EndSourceFile() { setCurrentInput(FrontendInputFile()); } +bool FrontendAction::shouldEraseOutputFiles() { + return getCompilerInstance().getDiagnostics().hasErrorOccurred(); +} + //===----------------------------------------------------------------------===// // Utility Actions //===----------------------------------------------------------------------===// void ASTFrontendAction::ExecuteAction() { CompilerInstance &CI = getCompilerInstance(); + if (!CI.hasPreprocessor()) + return; // FIXME: Move the truncation aspect of this into Sema, we delayed this till // here so the source manager would be initialized. diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index 5c7567f..a3ab1be 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -54,7 +54,8 @@ ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI, ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - return CreateASTDumper(CI.getFrontendOpts().ASTDumpFilter); + return CreateASTDumper(CI.getFrontendOpts().ASTDumpFilter, + CI.getFrontendOpts().ASTDumpLookups); } ASTConsumer *ASTDeclListAction::CreateASTConsumer(CompilerInstance &CI, @@ -62,17 +63,6 @@ ASTConsumer *ASTDeclListAction::CreateASTConsumer(CompilerInstance &CI, return CreateASTDeclNodeLister(); } -ASTConsumer *ASTDumpXMLAction::CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) { - raw_ostream *OS; - if (CI.getFrontendOpts().OutputFile.empty()) - OS = &llvm::outs(); - else - OS = CI.createDefaultOutputFile(false, InFile); - if (!OS) return 0; - return CreateASTDumperXML(*OS); -} - ASTConsumer *ASTViewAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { return CreateASTViewer(); @@ -172,11 +162,12 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts, return; // Add includes for each of these headers. - for (unsigned I = 0, N = Module->Headers.size(); I != N; ++I) { - const FileEntry *Header = Module->Headers[I]; + for (unsigned I = 0, N = Module->NormalHeaders.size(); I != N; ++I) { + const FileEntry *Header = Module->NormalHeaders[I]; Module->addTopHeader(Header); addHeaderInclude(Header, Includes, LangOpts); } + // Note that Module->PrivateHeaders will not be a TopHeader. if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) { Module->addTopHeader(UmbrellaHeader); @@ -231,7 +222,7 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI, // Parse the module map file. HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); - if (HS.loadModuleMapFile(ModuleMap)) + if (HS.loadModuleMapFile(ModuleMap, IsSystem)) return false; if (CI.getLangOpts().CurrentModule.empty()) { @@ -255,11 +246,11 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI, } // Check whether we can build this module at all. - StringRef Feature; - if (!Module->isAvailable(CI.getLangOpts(), CI.getTarget(), Feature)) { + clang::Module::Requirement Requirement; + if (!Module->isAvailable(CI.getLangOpts(), CI.getTarget(), Requirement)) { CI.getDiagnostics().Report(diag::err_module_unavailable) << Module->getFullModuleName() - << Feature; + << Requirement.second << Requirement.first; return false; } diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp index f1823c6..1869d0c 100644 --- a/lib/Frontend/FrontendOptions.cpp +++ b/lib/Frontend/FrontendOptions.cpp @@ -22,7 +22,6 @@ InputKind FrontendOptions::getInputKindForExtension(StringRef Extension) { .Case("mi", IK_PreprocessedObjC) .Cases("mm", "M", IK_ObjCXX) .Case("mii", IK_PreprocessedObjCXX) - .Case("C", IK_CXX) .Cases("C", "cc", "cp", IK_CXX) .Cases("cpp", "CPP", "c++", "cxx", "hpp", IK_CXX) .Case("cl", IK_OpenCL) diff --git a/lib/Frontend/HeaderIncludeGen.cpp b/lib/Frontend/HeaderIncludeGen.cpp index 79920df..237e5b1 100644 --- a/lib/Frontend/HeaderIncludeGen.cpp +++ b/lib/Frontend/HeaderIncludeGen.cpp @@ -24,15 +24,16 @@ class HeaderIncludesCallback : public PPCallbacks { bool OwnsOutputFile; bool ShowAllHeaders; bool ShowDepth; + bool MSStyle; public: HeaderIncludesCallback(const Preprocessor *PP, bool ShowAllHeaders_, raw_ostream *OutputFile_, bool OwnsOutputFile_, - bool ShowDepth_) + bool ShowDepth_, bool MSStyle_) : SM(PP->getSourceManager()), OutputFile(OutputFile_), CurrentIncludeDepth(0), HasProcessedPredefines(false), OwnsOutputFile(OwnsOutputFile_), ShowAllHeaders(ShowAllHeaders_), - ShowDepth(ShowDepth_) {} + ShowDepth(ShowDepth_), MSStyle(MSStyle_) {} ~HeaderIncludesCallback() { if (OwnsOutputFile) @@ -46,7 +47,8 @@ public: } void clang::AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders, - StringRef OutputPath, bool ShowDepth) { + StringRef OutputPath, bool ShowDepth, + bool MSStyle) { raw_ostream *OutputFile = &llvm::errs(); bool OwnsOutputFile = false; @@ -54,7 +56,7 @@ void clang::AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders, if (!OutputPath.empty()) { std::string Error; llvm::raw_fd_ostream *OS = new llvm::raw_fd_ostream( - OutputPath.str().c_str(), Error, llvm::raw_fd_ostream::F_Append); + OutputPath.str().c_str(), Error, llvm::sys::fs::F_Append); if (!Error.empty()) { PP.getDiagnostics().Report( clang::diag::warn_fe_cc_print_header_failure) << Error; @@ -69,7 +71,7 @@ void clang::AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders, PP.addPPCallbacks(new HeaderIncludesCallback(&PP, ShowAllHeaders, OutputFile, OwnsOutputFile, - ShowDepth)); + ShowDepth, MSStyle)); } void HeaderIncludesCallback::FileChanged(SourceLocation Loc, @@ -109,14 +111,20 @@ void HeaderIncludesCallback::FileChanged(SourceLocation Loc, if (ShowHeader && Reason == PPCallbacks::EnterFile) { // Write to a temporary string to avoid unnecessary flushing on errs(). SmallString<512> Filename(UserLoc.getFilename()); - Lexer::Stringify(Filename); + if (!MSStyle) + Lexer::Stringify(Filename); SmallString<256> Msg; + if (MSStyle) + Msg += "Note: including file:"; + if (ShowDepth) { // The main source file is at depth 1, so skip one dot. for (unsigned i = 1; i != CurrentIncludeDepth; ++i) - Msg += '.'; - Msg += ' '; + Msg += MSStyle ? ' ' : '.'; + + if (!MSStyle) + Msg += ' '; } Msg += Filename; Msg += '\n'; diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index f4ca4d49..d144cbb 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -244,8 +244,8 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, if (HSOpts.UseBuiltinIncludes) { // Ignore the sys root, we *always* look for clang headers relative to // supplied path. - llvm::sys::Path P(HSOpts.ResourceDir); - P.appendComponent("include"); + SmallString<128> P = StringRef(HSOpts.ResourceDir); + llvm::sys::path::append(P, "include"); AddUnmappedPath(P.str(), ExternCSystem, false); } @@ -312,15 +312,20 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, break; case llvm::Triple::MinGW32: { // mingw-w64 crt include paths - llvm::sys::Path P(HSOpts.ResourceDir); - P.appendComponent("../../../i686-w64-mingw32/include"); // <sysroot>/i686-w64-mingw32/include + // <sysroot>/i686-w64-mingw32/include + SmallString<128> P = StringRef(HSOpts.ResourceDir); + llvm::sys::path::append(P, "../../../i686-w64-mingw32/include"); AddPath(P.str(), System, false); - P = llvm::sys::Path(HSOpts.ResourceDir); - P.appendComponent("../../../x86_64-w64-mingw32/include"); // <sysroot>/x86_64-w64-mingw32/include + + // <sysroot>/x86_64-w64-mingw32/include + P.resize(HSOpts.ResourceDir.size()); + llvm::sys::path::append(P, "../../../x86_64-w64-mingw32/include"); AddPath(P.str(), System, false); + // mingw.org crt include paths - P = llvm::sys::Path(HSOpts.ResourceDir); - P.appendComponent("../../../include"); // <sysroot>/include + // <sysroot>/include + P.resize(HSOpts.ResourceDir.size()); + llvm::sys::path::append(P, "../../../include"); AddPath(P.str(), System, false); AddPath("/mingw/include", System, false); #if defined(_WIN32) @@ -382,6 +387,7 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, const HeaderSearchOp case llvm::Triple::Cygwin: // Cygwin-1.7 + AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.7.3"); AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.5.3"); AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.4"); // g++-4 / Cygwin-1.5 @@ -402,6 +408,7 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, const HeaderSearchOp // mingw.org C++ include paths AddMinGWCPlusPlusIncludePaths("/mingw/lib/gcc", "mingw32", "4.5.2"); //MSYS #if defined(_WIN32) + AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.8.1"); AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.6.2"); AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.6.1"); AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.5.2"); @@ -468,15 +475,17 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang, if (HSOpts.UseLibcxx) { if (triple.isOSDarwin()) { // On Darwin, libc++ may be installed alongside the compiler in - // lib/c++/v1. - llvm::sys::Path P(HSOpts.ResourceDir); - if (!P.isEmpty()) { - P.eraseComponent(); // Remove version from foo/lib/clang/version - P.eraseComponent(); // Remove clang from foo/lib/clang - - // Get foo/lib/c++/v1 - P.appendComponent("c++"); - P.appendComponent("v1"); + // include/c++/v1. + if (!HSOpts.ResourceDir.empty()) { + // Remove version from foo/lib/clang/version + StringRef NoVer = llvm::sys::path::parent_path(HSOpts.ResourceDir); + // Remove clang from foo/lib/clang + StringRef Lib = llvm::sys::path::parent_path(NoVer); + // Remove lib from foo/lib + SmallString<128> P = llvm::sys::path::parent_path(Lib); + + // Get foo/include/c++/v1 + llvm::sys::path::append(P, "include", "c++", "v1"); AddUnmappedPath(P.str(), CXXSystem, false); } } @@ -686,8 +695,8 @@ void clang::ApplyHeaderSearchOptions(HeaderSearch &HS, if (HSOpts.UseBuiltinIncludes) { // Set up the builtin include directory in the module map. - llvm::sys::Path P(HSOpts.ResourceDir); - P.appendComponent("include"); + SmallString<128> P = StringRef(HSOpts.ResourceDir); + llvm::sys::path::append(P, "include"); if (const DirectoryEntry *Dir = HS.getFileMgr().getDirectory(P.str())) HS.getModuleMap().setBuiltinIncludeDir(Dir); } diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index dc3ab53..c7d2550 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -29,6 +29,12 @@ #include "llvm/Support/Path.h" using namespace clang; +static bool MacroBodyEndsInBackslash(StringRef MacroBody) { + while (!MacroBody.empty() && isWhitespace(MacroBody.back())) + MacroBody = MacroBody.drop_back(); + return !MacroBody.empty() && MacroBody.back() == '\\'; +} + // Append a #define line to Buf for Macro. Macro should be of the form XXX, // in which case we emit "#define XXX 1" or "XXX=Y z W" in which case we emit // "#define XXX Y z W". To get a #define with no value, use "XXX=". @@ -43,7 +49,14 @@ static void DefineBuiltinMacro(MacroBuilder &Builder, StringRef Macro, if (End != StringRef::npos) Diags.Report(diag::warn_fe_macro_contains_embedded_newline) << MacroName; - Builder.defineMacro(MacroName, MacroBody.substr(0, End)); + MacroBody = MacroBody.substr(0, End); + // We handle macro bodies which end in a backslash by appending an extra + // backslash+newline. This makes sure we don't accidentally treat the + // backslash as a line continuation marker. + if (MacroBodyEndsInBackslash(MacroBody)) + Builder.defineMacro(MacroName, Twine(MacroBody) + "\\\n"); + else + Builder.defineMacro(MacroName, MacroBody); } else { // Push "macroname 1". Builder.defineMacro(Macro); @@ -317,6 +330,14 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, Builder.defineMacro("__cplusplus", "199711L"); } + // In C11 these are environment macros. In C++11 they are only defined + // as part of <cuchar>. To prevent breakage when mixing C and C++ + // code, define these macros unconditionally. We can define them + // unconditionally, as Clang always uses UTF-16 and UTF-32 for 16-bit + // and 32-bit character literals. + Builder.defineMacro("__STDC_UTF_16__", "1"); + Builder.defineMacro("__STDC_UTF_32__", "1"); + if (LangOpts.ObjC1) Builder.defineMacro("__OBJC__"); @@ -325,6 +346,38 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, Builder.defineMacro("__ASSEMBLER__"); } +/// Initialize the predefined C++ language feature test macros defined in +/// ISO/IEC JTC1/SC22/WG21 (C++) SD-6: "SG10 Feature Test Recommendations". +static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts, + MacroBuilder &Builder) { + // C++11 features. + if (LangOpts.CPlusPlus11) { + Builder.defineMacro("__cpp_unicode_characters", "200704"); + Builder.defineMacro("__cpp_raw_strings", "200710"); + Builder.defineMacro("__cpp_unicode_literals", "200710"); + Builder.defineMacro("__cpp_user_defined_literals", "200809"); + Builder.defineMacro("__cpp_lambdas", "200907"); + Builder.defineMacro("__cpp_constexpr", + LangOpts.CPlusPlus1y ? "201304" : "200704"); + Builder.defineMacro("__cpp_static_assert", "200410"); + Builder.defineMacro("__cpp_decltype", "200707"); + Builder.defineMacro("__cpp_attributes", "200809"); + Builder.defineMacro("__cpp_rvalue_references", "200610"); + Builder.defineMacro("__cpp_variadic_templates", "200704"); + } + + // C++14 features. + if (LangOpts.CPlusPlus1y) { + Builder.defineMacro("__cpp_binary_literals", "201304"); + Builder.defineMacro("__cpp_init_captures", "201304"); + Builder.defineMacro("__cpp_generic_lambdas", "201304"); + Builder.defineMacro("__cpp_decltype_auto", "201304"); + Builder.defineMacro("__cpp_return_type_deduction", "201304"); + Builder.defineMacro("__cpp_aggregate_nsdmi", "201304"); + Builder.defineMacro("__cpp_variable_templates", "201304"); + } +} + static void InitializePredefinedMacros(const TargetInfo &TI, const LangOptions &LangOpts, const FrontendOptions &FEOpts, @@ -395,12 +448,31 @@ static void InitializePredefinedMacros(const TargetInfo &TI, if (LangOpts.ObjCRuntime.isNeXTFamily()) Builder.defineMacro("__NEXT_RUNTIME__"); + if (LangOpts.ObjCRuntime.getKind() == ObjCRuntime::ObjFW) { + VersionTuple tuple = LangOpts.ObjCRuntime.getVersion(); + + unsigned minor = 0; + if (tuple.getMinor().hasValue()) + minor = tuple.getMinor().getValue(); + + unsigned subminor = 0; + if (tuple.getSubminor().hasValue()) + subminor = tuple.getSubminor().getValue(); + + Builder.defineMacro("__OBJFW_RUNTIME_ABI__", + Twine(tuple.getMajor() * 10000 + minor * 100 + + subminor)); + } + Builder.defineMacro("IBOutlet", "__attribute__((iboutlet))"); Builder.defineMacro("IBOutletCollection(ClassName)", "__attribute__((iboutletcollection(ClassName)))"); Builder.defineMacro("IBAction", "void)__attribute__((ibaction)"); } + if (LangOpts.CPlusPlus) + InitializeCPlusPlusFeatureTestMacros(LangOpts, Builder); + // darwin_constant_cfstrings controls this. This is also dependent // on other things like the runtime I believe. This is set even for C code. if (!LangOpts.NoConstantCFStrings) @@ -484,7 +556,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI, assert(TI.getCharWidth() == 8 && "Only support 8-bit char so far"); Builder.defineMacro("__CHAR_BIT__", "8"); - DefineTypeSize("__SCHAR_MAX__", TI.getCharWidth(), "", true, Builder); + DefineTypeSize("__SCHAR_MAX__", TargetInfo::SignedChar, TI, Builder); DefineTypeSize("__SHRT_MAX__", TargetInfo::SignedShort, TI, Builder); DefineTypeSize("__INT_MAX__", TargetInfo::SignedInt, TI, Builder); DefineTypeSize("__LONG_MAX__", TargetInfo::SignedLong, TI, Builder); diff --git a/lib/Frontend/MultiplexConsumer.cpp b/lib/Frontend/MultiplexConsumer.cpp index ba83580..9cf68a5 100644 --- a/lib/Frontend/MultiplexConsumer.cpp +++ b/lib/Frontend/MultiplexConsumer.cpp @@ -94,8 +94,12 @@ public: virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D); virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, const ClassTemplateSpecializationDecl *D); + virtual void + AddedCXXTemplateSpecialization(const VarTemplateDecl *TD, + const VarTemplateSpecializationDecl *D); virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, const FunctionDecl *D); + virtual void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType); virtual void CompletedImplicitDefinition(const FunctionDecl *D); virtual void StaticDataMemberInstantiated(const VarDecl *D); virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, @@ -103,6 +107,8 @@ public: virtual void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop, const ObjCPropertyDecl *OrigProp, const ObjCCategoryDecl *ClassExt); + void DeclarationMarkedUsed(const Decl *D) LLVM_OVERRIDE; + private: std::vector<ASTMutationListener*> Listeners; }; @@ -134,10 +140,20 @@ void MultiplexASTMutationListener::AddedCXXTemplateSpecialization( Listeners[i]->AddedCXXTemplateSpecialization(TD, D); } void MultiplexASTMutationListener::AddedCXXTemplateSpecialization( + const VarTemplateDecl *TD, const VarTemplateSpecializationDecl *D) { + for (size_t i = 0, e = Listeners.size(); i != e; ++i) + Listeners[i]->AddedCXXTemplateSpecialization(TD, D); +} +void MultiplexASTMutationListener::AddedCXXTemplateSpecialization( const FunctionTemplateDecl *TD, const FunctionDecl *D) { for (size_t i = 0, e = Listeners.size(); i != e; ++i) Listeners[i]->AddedCXXTemplateSpecialization(TD, D); } +void MultiplexASTMutationListener::DeducedReturnType(const FunctionDecl *FD, + QualType ReturnType) { + for (size_t i = 0, e = Listeners.size(); i != e; ++i) + Listeners[i]->DeducedReturnType(FD, ReturnType); +} void MultiplexASTMutationListener::CompletedImplicitDefinition( const FunctionDecl *D) { for (size_t i = 0, e = Listeners.size(); i != e; ++i) @@ -161,6 +177,10 @@ void MultiplexASTMutationListener::AddedObjCPropertyInClassExtension( for (size_t i = 0, e = Listeners.size(); i != e; ++i) Listeners[i]->AddedObjCPropertyInClassExtension(Prop, OrigProp, ClassExt); } +void MultiplexASTMutationListener::DeclarationMarkedUsed(const Decl *D) { + for (size_t i = 0, e = Listeners.size(); i != e; ++i) + Listeners[i]->DeclarationMarkedUsed(D); +} } // end namespace clang diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index 9fd3649..55a66d8 100644 --- a/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/lib/Frontend/PrintPreprocessedOutput.cpp @@ -140,6 +140,9 @@ public: virtual void PragmaCaptured(SourceLocation Loc, StringRef Str); virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, const std::string &Str); + virtual void PragmaDetectMismatch(SourceLocation Loc, + const std::string &Name, + const std::string &Value); virtual void PragmaMessage(SourceLocation Loc, StringRef Namespace, PragmaMessageKind Kind, StringRef Str); virtual void PragmaDebug(SourceLocation Loc, StringRef DebugType); @@ -149,6 +152,10 @@ public: StringRef Namespace); virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, diag::Mapping Map, StringRef Str); + virtual void PragmaWarning(SourceLocation Loc, StringRef WarningSpec, + ArrayRef<int> Ids); + virtual void PragmaWarningPush(SourceLocation Loc, int Level); + virtual void PragmaWarningPop(SourceLocation Loc); bool HandleFirstTokOnLine(Token &Tok); @@ -187,11 +194,11 @@ void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo, // Emit #line directives or GNU line markers depending on what mode we're in. if (UseLineDirective) { OS << "#line" << ' ' << LineNo << ' ' << '"'; - OS.write(CurFilename.data(), CurFilename.size()); + OS.write_escaped(CurFilename); OS << '"'; } else { OS << '#' << ' ' << LineNo << ' ' << '"'; - OS.write(CurFilename.data(), CurFilename.size()); + OS.write_escaped(CurFilename); OS << '"'; if (ExtraLen) @@ -282,7 +289,6 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc, CurFilename.clear(); CurFilename += UserLoc.getFilename(); - Lexer::Stringify(CurFilename); FileType = NewFileType; if (DisableLineMarkers) { @@ -382,16 +388,8 @@ void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok, setEmittedDirectiveOnThisLine(); } -void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc, - const IdentifierInfo *Kind, +static void outputPrintable(llvm::raw_ostream& OS, const std::string &Str) { - startNewLineIfNeeded(); - MoveToLine(Loc); - OS << "#pragma comment(" << Kind->getName(); - - if (!Str.empty()) { - OS << ", \""; - for (unsigned i = 0, e = Str.size(); i != e; ++i) { unsigned char Char = Str[i]; if (isPrintable(Char) && Char != '\\' && Char != '"') @@ -402,6 +400,18 @@ void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc, << (char)('0'+ ((Char >> 3) & 7)) << (char)('0'+ ((Char >> 0) & 7)); } +} + +void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc, + const IdentifierInfo *Kind, + const std::string &Str) { + startNewLineIfNeeded(); + MoveToLine(Loc); + OS << "#pragma comment(" << Kind->getName(); + + if (!Str.empty()) { + OS << ", \""; + outputPrintable(OS, Str); OS << '"'; } @@ -409,6 +419,19 @@ void PrintPPOutputPPCallbacks::PragmaComment(SourceLocation Loc, setEmittedDirectiveOnThisLine(); } +void PrintPPOutputPPCallbacks::PragmaDetectMismatch(SourceLocation Loc, + const std::string &Name, + const std::string &Value) { + startNewLineIfNeeded(); + MoveToLine(Loc); + OS << "#pragma detect_mismatch(\"" << Name << '"'; + outputPrintable(OS, Name); + OS << "\", \""; + outputPrintable(OS, Value); + OS << "\")"; + setEmittedDirectiveOnThisLine(); +} + void PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc, StringRef Namespace, PragmaMessageKind Kind, @@ -430,16 +453,7 @@ void PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc, break; } - for (unsigned i = 0, e = Str.size(); i != e; ++i) { - unsigned char Char = Str[i]; - if (isPrintable(Char) && Char != '\\' && Char != '"') - OS << (char)Char; - else // Output anything hard as an octal escape. - OS << '\\' - << (char)('0'+ ((Char >> 6) & 7)) - << (char)('0'+ ((Char >> 3) & 7)) - << (char)('0'+ ((Char >> 0) & 7)); - } + outputPrintable(OS, Str); OS << '"'; if (Kind == PMK_Message) OS << ')'; @@ -497,6 +511,36 @@ PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, setEmittedDirectiveOnThisLine(); } +void PrintPPOutputPPCallbacks::PragmaWarning(SourceLocation Loc, + StringRef WarningSpec, + ArrayRef<int> Ids) { + startNewLineIfNeeded(); + MoveToLine(Loc); + OS << "#pragma warning(" << WarningSpec << ':'; + for (ArrayRef<int>::iterator I = Ids.begin(), E = Ids.end(); I != E; ++I) + OS << ' ' << *I; + OS << ')'; + setEmittedDirectiveOnThisLine(); +} + +void PrintPPOutputPPCallbacks::PragmaWarningPush(SourceLocation Loc, + int Level) { + startNewLineIfNeeded(); + MoveToLine(Loc); + OS << "#pragma warning(push"; + if (Level >= 0) + OS << ", " << Level; + OS << ')'; + setEmittedDirectiveOnThisLine(); +} + +void PrintPPOutputPPCallbacks::PragmaWarningPop(SourceLocation Loc) { + startNewLineIfNeeded(); + MoveToLine(Loc); + OS << "#pragma warning(pop)"; + 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. @@ -613,6 +657,11 @@ 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::annot_module_include)) { + // PrintPPOutputPPCallbacks::InclusionDirective handles producing + // appropriate output here. Ignore this token entirely. + PP.Lex(Tok); + continue; } else if (IdentifierInfo *II = Tok.getIdentifierInfo()) { OS << II->getName(); } else if (Tok.isLiteral() && !Tok.needsCleaning() && @@ -647,9 +696,7 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, } typedef std::pair<const IdentifierInfo *, MacroInfo *> id_macro_pair; -static int MacroIDCompare(const void* a, const void* b) { - const id_macro_pair *LHS = static_cast<const id_macro_pair*>(a); - const id_macro_pair *RHS = static_cast<const id_macro_pair*>(b); +static int MacroIDCompare(const id_macro_pair *LHS, const id_macro_pair *RHS) { return LHS->first->getName().compare(RHS->first->getName()); } diff --git a/lib/Frontend/TextDiagnostic.cpp b/lib/Frontend/TextDiagnostic.cpp index 1572d0f..a2dc953 100644 --- a/lib/Frontend/TextDiagnostic.cpp +++ b/lib/Frontend/TextDiagnostic.cpp @@ -336,13 +336,10 @@ static void selectInterestingSourceRegion(std::string &SourceLine, if (MaxColumns <= Columns) return; - // no special characters allowed in CaretLine or FixItInsertionLine + // No special characters are allowed in CaretLine. assert(CaretLine.end() == std::find_if(CaretLine.begin(), CaretLine.end(), char_out_of_range(' ','~'))); - assert(FixItInsertionLine.end() == - std::find_if(FixItInsertionLine.begin(), FixItInsertionLine.end(), - char_out_of_range(' ','~'))); // Find the slice that we need to display the full caret line // correctly. @@ -370,8 +367,15 @@ static void selectInterestingSourceRegion(std::string &SourceLine, if (!isWhitespace(FixItInsertionLine[FixItEnd - 1])) break; - CaretStart = std::min(FixItStart, CaretStart); - CaretEnd = std::max(FixItEnd, CaretEnd); + // We can safely use the byte offset FixItStart as the column offset + // because the characters up until FixItStart are all ASCII whitespace + // characters. + unsigned FixItStartCol = FixItStart; + unsigned FixItEndCol + = llvm::sys::locale::columnWidth(FixItInsertionLine.substr(0, FixItEnd)); + + CaretStart = std::min(FixItStartCol, CaretStart); + CaretEnd = std::max(FixItEndCol, CaretEnd); } // CaretEnd may have been set at the middle of a character @@ -689,7 +693,8 @@ TextDiagnostic::emitDiagnosticMessage(SourceLocation Loc, if (DiagOpts->ShowColors) OS.resetColor(); - printDiagnosticLevel(OS, Level, DiagOpts->ShowColors); + printDiagnosticLevel(OS, Level, DiagOpts->ShowColors, + DiagOpts->CLFallbackMode); printDiagnosticMessage(OS, Level, Message, OS.tell() - StartOfLocationInfo, DiagOpts->MessageLength, DiagOpts->ShowColors); @@ -698,7 +703,8 @@ TextDiagnostic::emitDiagnosticMessage(SourceLocation Loc, /*static*/ void TextDiagnostic::printDiagnosticLevel(raw_ostream &OS, DiagnosticsEngine::Level Level, - bool ShowColors) { + bool ShowColors, + bool CLFallbackMode) { if (ShowColors) { // Print diagnostic category in bold and color switch (Level) { @@ -714,12 +720,21 @@ TextDiagnostic::printDiagnosticLevel(raw_ostream &OS, switch (Level) { case DiagnosticsEngine::Ignored: llvm_unreachable("Invalid diagnostic type"); - case DiagnosticsEngine::Note: OS << "note: "; break; - case DiagnosticsEngine::Warning: OS << "warning: "; break; - case DiagnosticsEngine::Error: OS << "error: "; break; - case DiagnosticsEngine::Fatal: OS << "fatal error: "; break; + case DiagnosticsEngine::Note: OS << "note"; break; + case DiagnosticsEngine::Warning: OS << "warning"; break; + case DiagnosticsEngine::Error: OS << "error"; break; + case DiagnosticsEngine::Fatal: OS << "fatal error"; break; } + // In clang-cl /fallback mode, print diagnostics as "error(clang):". This + // makes it more clear whether a message is coming from clang or cl.exe, + // and it prevents MSBuild from concluding that the build failed just because + // there is an "error:" in the output. + if (CLFallbackMode) + OS << "(clang)"; + + OS << ": "; + if (ShowColors) OS.resetColor(); } @@ -774,11 +789,8 @@ void TextDiagnostic::emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc, const FileEntry* FE = SM.getFileEntryForID(FID); if (FE && FE->getName()) { OS << FE->getName(); - if (FE->getDevice() == 0 && FE->getInode() == 0 - && FE->getFileMode() == 0) { - // in PCH is a guess, but a good one: + if (FE->isInPCH()) OS << " (in PCH)"; - } OS << ": "; } } @@ -1023,24 +1035,18 @@ static std::string buildFixItInsertionLine(unsigned LineNo, if (HintCol < PrevHintEndCol) HintCol = PrevHintEndCol + 1; - // FIXME: This function handles multibyte characters in the source, but - // not in the fixits. This assertion is intended to catch unintended - // use of multibyte characters in fixits. If we decide to do this, we'll - // have to track separate byte widths for the source and fixit lines. - assert((size_t)llvm::sys::locale::columnWidth(I->CodeToInsert) == - I->CodeToInsert.size()); - - // This relies on one byte per column in our fixit hints. // This should NOT use HintByteOffset, because the source might have // Unicode characters in earlier columns. - unsigned LastColumnModified = HintCol + I->CodeToInsert.size(); - if (LastColumnModified > FixItInsertionLine.size()) - FixItInsertionLine.resize(LastColumnModified, ' '); + unsigned NewFixItLineSize = FixItInsertionLine.size() + + (HintCol - PrevHintEndCol) + I->CodeToInsert.size(); + if (NewFixItLineSize > FixItInsertionLine.size()) + FixItInsertionLine.resize(NewFixItLineSize, ' '); std::copy(I->CodeToInsert.begin(), I->CodeToInsert.end(), - FixItInsertionLine.begin() + HintCol); + FixItInsertionLine.end() - I->CodeToInsert.size()); - PrevHintEndCol = LastColumnModified; + PrevHintEndCol = + HintCol + llvm::sys::locale::columnWidth(I->CodeToInsert); } else { FixItInsertionLine.clear(); break; diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp index c22798a..994a8f7 100644 --- a/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/lib/Frontend/TextDiagnosticPrinter.cpp @@ -132,7 +132,8 @@ void TextDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level, // diagnostics in a context that lacks language options, a source manager, or // other infrastructure necessary when emitting more rich diagnostics. if (!Info.getLocation().isValid()) { - TextDiagnostic::printDiagnosticLevel(OS, Level, DiagOpts->ShowColors); + TextDiagnostic::printDiagnosticLevel(OS, Level, DiagOpts->ShowColors, + DiagOpts->CLFallbackMode); TextDiagnostic::printDiagnosticMessage(OS, Level, DiagMessageStream.str(), OS.tell() - StartOfLocationInfo, DiagOpts->MessageLength, diff --git a/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp index 46745b6..045e60a 100644 --- a/lib/Frontend/VerifyDiagnosticConsumer.cpp +++ b/lib/Frontend/VerifyDiagnosticConsumer.cpp @@ -371,7 +371,7 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM, // Lookup file via Preprocessor, like a #include. const DirectoryLookup *CurDir; - const FileEntry *FE = PP->LookupFile(Filename, false, NULL, CurDir, + const FileEntry *FE = PP->LookupFile(Pos, Filename, false, NULL, CurDir, NULL, NULL, 0); if (!FE) { Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), @@ -555,7 +555,7 @@ static bool findDirectives(SourceManager &SM, FileID FID, VerifyDiagnosticConsumer::DirectiveStatus Status = VerifyDiagnosticConsumer::HasNoDirectives; while (Tok.isNot(tok::eof)) { - RawLex.Lex(Tok); + RawLex.LexFromRawLexer(Tok); if (!Tok.is(tok::comment)) continue; std::string Comment = RawLex.getSpelling(Tok, SM, LangOpts); @@ -628,11 +628,11 @@ static bool IsFromSameFile(SourceManager &SM, SourceLocation DirectiveLoc, while (DiagnosticLoc.isMacroID()) DiagnosticLoc = SM.getImmediateMacroCallerLoc(DiagnosticLoc); - if (SM.isFromSameFile(DirectiveLoc, DiagnosticLoc)) + if (SM.isWrittenInSameFile(DirectiveLoc, DiagnosticLoc)) return true; const FileEntry *DiagFile = SM.getFileEntryForID(SM.getFileID(DiagnosticLoc)); - if (!DiagFile && SM.isFromMainFile(DirectiveLoc)) + if (!DiagFile && SM.isWrittenInMainFile(DirectiveLoc)) return true; return (DiagFile == SM.getFileEntryForID(SM.getFileID(DirectiveLoc))); |