diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
commit | 486754660bb926339aefcf012a3f848592babb8b (patch) | |
tree | ecdbc446c9876f4f120f701c243373cd3cb43db3 /lib/Frontend | |
parent | 55e6d896ad333f07bb3b1ba487df214fc268a4ab (diff) | |
download | src-486754660bb926339aefcf012a3f848592babb8b.tar.gz src-486754660bb926339aefcf012a3f848592babb8b.zip |
Vendor import of clang trunk r338150:vendor/clang/clang-trunk-r338150
Notes
Notes:
svn path=/vendor/clang/dist/; revision=336815
svn path=/vendor/clang/clang-trunk-r338150/; revision=336816; tag=vendor/clang/clang-trunk-r338150
Diffstat (limited to 'lib/Frontend')
35 files changed, 1798 insertions, 1027 deletions
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp index 7dc475e26f76..b67c019baed8 100644 --- a/lib/Frontend/ASTConsumers.cpp +++ b/lib/Frontend/ASTConsumers.cpp @@ -87,9 +87,10 @@ namespace { << DC->getPrimaryContext() << "\n"; } else Out << "Not a DeclContext\n"; - } else if (OutputKind == Print) - D->print(Out, /*Indentation=*/0, /*PrintInstantiation=*/true); - else if (OutputKind != None) + } else if (OutputKind == Print) { + PrintingPolicy Policy(D->getASTContext().getLangOpts()); + D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true); + } else if (OutputKind != None) D->dump(Out, OutputKind == DumpFull); } @@ -138,12 +139,14 @@ clang::CreateASTPrinter(std::unique_ptr<raw_ostream> Out, FilterString); } -std::unique_ptr<ASTConsumer> clang::CreateASTDumper(StringRef FilterString, - bool DumpDecls, - bool Deserialize, - bool DumpLookups) { +std::unique_ptr<ASTConsumer> +clang::CreateASTDumper(std::unique_ptr<raw_ostream> Out, + StringRef FilterString, + bool DumpDecls, + bool Deserialize, + bool DumpLookups) { assert((DumpDecls || Deserialize || DumpLookups) && "nothing to dump"); - return llvm::make_unique<ASTPrinter>(nullptr, + return llvm::make_unique<ASTPrinter>(std::move(Out), Deserialize ? ASTPrinter::DumpFull : DumpDecls ? ASTPrinter::Dump : ASTPrinter::None, diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp index 354527db7bad..6ec0e2a98c1b 100644 --- a/lib/Frontend/ASTMerge.cpp +++ b/lib/Frontend/ASTMerge.cpp @@ -1,4 +1,4 @@ -//===-- ASTMerge.cpp - AST Merging Frontent Action --------------*- C++ -*-===// +//===-- ASTMerge.cpp - AST Merging Frontend Action --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 1160df15a920..e4c313fed30f 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -1,4 +1,4 @@ -//===--- ASTUnit.cpp - ASTUnit utility --------------------------*- C++ -*-===// +//===- ASTUnit.cpp - ASTUnit utility --------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -14,45 +14,99 @@ #include "clang/Frontend/ASTUnit.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/DeclVisitor.h" -#include "clang/AST/StmtVisitor.h" +#include "clang/AST/CommentCommandTraits.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclGroup.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/DeclarationName.h" +#include "clang/AST/ExternalASTSource.h" +#include "clang/AST/PrettyPrinter.h" +#include "clang/AST/Type.h" #include "clang/AST/TypeOrdering.h" #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" #include "clang/Basic/MemoryBufferCache.h" +#include "clang/Basic/Module.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TargetOptions.h" #include "clang/Basic/VirtualFileSystem.h" #include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/CompilerInvocation.h" +#include "clang/Frontend/FrontendAction.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/FrontendOptions.h" #include "clang/Frontend/MultiplexConsumer.h" +#include "clang/Frontend/PCHContainerOperations.h" +#include "clang/Frontend/PrecompiledPreamble.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/HeaderSearchOptions.h" +#include "clang/Lex/Lexer.h" +#include "clang/Lex/PPCallbacks.h" +#include "clang/Lex/PreprocessingRecord.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/PreprocessorOptions.h" +#include "clang/Lex/Token.h" +#include "clang/Sema/CodeCompleteConsumer.h" +#include "clang/Sema/CodeCompleteOptions.h" #include "clang/Sema/Sema.h" +#include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ASTWriter.h" +#include "clang/Serialization/ContinuousRangeMap.h" +#include "clang/Serialization/Module.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" +#include "llvm/ADT/Twine.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Bitcode/BitstreamWriter.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/CrashRecoveryContext.h" -#include "llvm/Support/Host.h" +#include "llvm/Support/DJB.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Mutex.h" -#include "llvm/Support/MutexGuard.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> #include <atomic> +#include <cassert> +#include <cstdint> #include <cstdio> #include <cstdlib> +#include <memory> +#include <string> +#include <tuple> +#include <utility> +#include <vector> using namespace clang; using llvm::TimeRecord; namespace { + class SimpleTimer { bool WantTiming; TimeRecord Start; @@ -64,11 +118,6 @@ namespace { Start = TimeRecord::getCurrentTime(); } - void setOutput(const Twine &Output) { - if (WantTiming) - this->Output = Output.str(); - } - ~SimpleTimer() { if (WantTiming) { TimeRecord Elapsed = TimeRecord::getCurrentTime(); @@ -78,29 +127,37 @@ namespace { llvm::errs() << '\n'; } } + + void setOutput(const Twine &Output) { + if (WantTiming) + this->Output = Output.str(); + } }; - template <class T> - std::unique_ptr<T> valueOrNull(llvm::ErrorOr<std::unique_ptr<T>> Val) { - if (!Val) - return nullptr; - return std::move(*Val); - } +} // namespace - template <class T> - bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) { - if (!Val) - return false; - Output = std::move(*Val); - return true; - } +template <class T> +static std::unique_ptr<T> valueOrNull(llvm::ErrorOr<std::unique_ptr<T>> Val) { + if (!Val) + return nullptr; + return std::move(*Val); +} + +template <class T> +static bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) { + if (!Val) + return false; + Output = std::move(*Val); + return true; +} -/// \brief Get a source buffer for \p MainFilePath, handling all file-to-file +/// Get a source buffer for \p MainFilePath, handling all file-to-file /// and file-to-buffer remappings inside \p Invocation. static std::unique_ptr<llvm::MemoryBuffer> getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation, vfs::FileSystem *VFS, - StringRef FilePath) { + StringRef FilePath, + bool isVolatile) { const auto &PreprocessorOpts = Invocation.getPreprocessorOpts(); // Try to determine if the main file has been remapped, either from the @@ -120,7 +177,7 @@ getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation, llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID(); if (MainFileID == MID) { // We found a remapping. Try to load the resulting, remapped source. - BufferOwner = valueOrNull(VFS->getBufferForFile(RF.second)); + BufferOwner = valueOrNull(VFS->getBufferForFile(RF.second, -1, true, isVolatile)); if (!BufferOwner) return nullptr; } @@ -145,7 +202,7 @@ getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation, // If the main source file was not remapped, load it now. if (!Buffer && !BufferOwner) { - BufferOwner = valueOrNull(VFS->getBufferForFile(FilePath)); + BufferOwner = valueOrNull(VFS->getBufferForFile(FilePath, -1, true, isVolatile)); if (!BufferOwner) return nullptr; } @@ -156,7 +213,6 @@ getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation, return nullptr; return llvm::MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(), FilePath); } -} struct ASTUnit::ASTWriterData { SmallString<128> Buffer; @@ -171,32 +227,22 @@ void ASTUnit::clearFileLevelDecls() { llvm::DeleteContainerSeconds(FileDecls); } -/// \brief After failing to build a precompiled preamble (due to +/// After failing to build a precompiled preamble (due to /// errors in the source that occurs in the preamble), the number of /// reparses during which we'll skip even trying to precompile the /// preamble. const unsigned DefaultPreambleRebuildInterval = 5; -/// \brief Tracks the number of ASTUnit objects that are currently active. +/// Tracks the number of ASTUnit objects that are currently active. /// /// Used for debugging purposes only. static std::atomic<unsigned> ActiveASTUnitObjects; ASTUnit::ASTUnit(bool _MainFileIsAST) - : Reader(nullptr), HadModuleLoaderFatalFailure(false), - OnlyLocalDecls(false), CaptureDiagnostics(false), - MainFileIsAST(_MainFileIsAST), - TUKind(TU_Complete), WantTiming(getenv("LIBCLANG_TIMING")), - OwnsRemappedFileBuffers(true), - NumStoredDiagnosticsFromDriver(0), - PreambleRebuildCounter(0), - NumWarningsInPreamble(0), - ShouldCacheCodeCompletionResults(false), - IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(false), - CompletionCacheTopLevelHashValue(0), - PreambleTopLevelHashValue(0), - CurrentTopLevelHashValue(0), - UnsafeToFree(false) { + : MainFileIsAST(_MainFileIsAST), WantTiming(getenv("LIBCLANG_TIMING")), + ShouldCacheCodeCompletionResults(false), + IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(false), + UnsafeToFree(false) { if (getenv("LIBCLANG_OBJTRACKING")) fprintf(stderr, "+++ %u translation units\n", ++ActiveASTUnitObjects); } @@ -219,8 +265,8 @@ ASTUnit::~ASTUnit() { delete RB.second; } - ClearCachedCompletionResults(); - + ClearCachedCompletionResults(); + if (getenv("LIBCLANG_OBJTRACKING")) fprintf(stderr, "--- %u translation units\n", --ActiveASTUnitObjects); } @@ -229,20 +275,26 @@ void ASTUnit::setPreprocessor(std::shared_ptr<Preprocessor> PP) { this->PP = std::move(PP); } -/// \brief Determine the set of code-completion contexts in which this +void ASTUnit::enableSourceFileDiagnostics() { + assert(getDiagnostics().getClient() && Ctx && + "Bad context for source file"); + getDiagnostics().getClient()->BeginSourceFile(Ctx->getLangOpts(), PP.get()); +} + +/// Determine the set of code-completion contexts in which this /// declaration should be shown. static unsigned getDeclShowContexts(const NamedDecl *ND, const LangOptions &LangOpts, bool &IsNestedNameSpecifier) { IsNestedNameSpecifier = false; - + if (isa<UsingShadowDecl>(ND)) - ND = dyn_cast<NamedDecl>(ND->getUnderlyingDecl()); + ND = ND->getUnderlyingDecl(); if (!ND) return 0; - + uint64_t Contexts = 0; - if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) || + if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) || isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND) || isa<TypeAliasTemplateDecl>(ND)) { // Types can appear in these contexts. @@ -257,12 +309,12 @@ static unsigned getDeclShowContexts(const NamedDecl *ND, // In C++, types can appear in expressions contexts (for functional casts). if (LangOpts.CPlusPlus) Contexts |= (1LL << CodeCompletionContext::CCC_Expression); - + // In Objective-C, message sends can send interfaces. In Objective-C++, // all types are available due to functional casts. if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND)) Contexts |= (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver); - + // In Objective-C, you can only be a subclass of another Objective-C class if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) { // Objective-C interfaces can be used in a class property expression. @@ -274,16 +326,16 @@ static unsigned getDeclShowContexts(const NamedDecl *ND, // Deal with tag names. if (isa<EnumDecl>(ND)) { Contexts |= (1LL << CodeCompletionContext::CCC_EnumTag); - + // Part of the nested-name-specifier in C++0x. if (LangOpts.CPlusPlus11) IsNestedNameSpecifier = true; - } else if (const RecordDecl *Record = dyn_cast<RecordDecl>(ND)) { + } else if (const auto *Record = dyn_cast<RecordDecl>(ND)) { if (Record->isUnion()) Contexts |= (1LL << CodeCompletionContext::CCC_UnionTag); else Contexts |= (1LL << CodeCompletionContext::CCC_ClassOrStructTag); - + if (LangOpts.CPlusPlus) IsNestedNameSpecifier = true; } else if (isa<ClassTemplateDecl>(ND)) @@ -300,37 +352,37 @@ static unsigned getDeclShowContexts(const NamedDecl *ND, Contexts = (1LL << CodeCompletionContext::CCC_ObjCCategoryName); } else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) { Contexts = (1LL << CodeCompletionContext::CCC_Namespace); - + // Part of the nested-name-specifier. IsNestedNameSpecifier = true; } - + return Contexts; } void ASTUnit::CacheCodeCompletionResults() { if (!TheSema) return; - + SimpleTimer Timer(WantTiming); Timer.setOutput("Cache global code completions for " + getMainFileName()); // Clear out the previous results. ClearCachedCompletionResults(); - + // Gather the set of global code completions. - typedef CodeCompletionResult Result; + using Result = CodeCompletionResult; SmallVector<Result, 8> Results; CachedCompletionAllocator = std::make_shared<GlobalCodeCompletionAllocator>(); CodeCompletionTUInfo CCTUInfo(CachedCompletionAllocator); TheSema->GatherGlobalCodeCompletions(*CachedCompletionAllocator, CCTUInfo, Results); - + // Translate global code completions into cached completions. llvm::DenseMap<CanQualType, unsigned> CompletionTypes; CodeCompletionContext CCContext(CodeCompletionContext::CCC_TopLevel); - for (Result &R : Results) { + for (auto &R : Results) { switch (R.Kind) { case Result::RK_Declaration: { bool IsNestedNameSpecifier = false; @@ -344,7 +396,7 @@ void ASTUnit::CacheCodeCompletionResults() { CachedResult.Kind = R.CursorKind; CachedResult.Availability = R.Availability; - // Keep track of the type of this completion in an ASTContext-agnostic + // Keep track of the type of this completion in an ASTContext-agnostic // way. QualType UsageType = getDeclUsageType(*Ctx, R.Declaration); if (UsageType.isNull()) { @@ -356,7 +408,7 @@ void ASTUnit::CacheCodeCompletionResults() { CachedResult.TypeClass = getSimplifiedTypeClass(CanUsageType); // Determine whether we have already seen this type. If so, we save - // ourselves the work of formatting the type string by using the + // ourselves the work of formatting the type string by using the // temporary, CanQualType-based hash table to find the associated value. unsigned &TypeValue = CompletionTypes[CanUsageType]; if (TypeValue == 0) { @@ -364,12 +416,12 @@ void ASTUnit::CacheCodeCompletionResults() { CachedCompletionTypes[QualType(CanUsageType).getAsString()] = TypeValue; } - + CachedResult.Type = TypeValue; } - + CachedCompletionResults.push_back(CachedResult); - + /// Handle nested-name-specifiers in C++. if (TheSema->Context.getLangOpts().CPlusPlus && IsNestedNameSpecifier && !R.StartsNestedNameSpecifier) { @@ -392,10 +444,10 @@ void ASTUnit::CacheCodeCompletionResults() { isa<NamespaceAliasDecl>(R.Declaration)) NNSContexts |= (1LL << CodeCompletionContext::CCC_Namespace); - if (unsigned RemainingContexts + if (unsigned RemainingContexts = NNSContexts & ~CachedResult.ShowInContexts) { - // If there any contexts where this completion can be a - // nested-name-specifier but isn't already an option, create a + // If there any contexts where this completion can be a + // nested-name-specifier but isn't already an option, create a // nested-name-specifier completion. R.StartsNestedNameSpecifier = true; CachedResult.Completion = R.CreateCodeCompletionString( @@ -410,13 +462,13 @@ void ASTUnit::CacheCodeCompletionResults() { } break; } - + case Result::RK_Keyword: case Result::RK_Pattern: // Ignore keywords and patterns; we don't care, since they are so // easily regenerated. break; - + case Result::RK_Macro: { CachedCodeCompletionResult CachedResult; CachedResult.Completion = R.CreateCodeCompletionString( @@ -446,7 +498,7 @@ void ASTUnit::CacheCodeCompletionResults() { } } } - + // Save the current top-level hash value. CompletionCacheTopLevelHashValue = CurrentTopLevelHashValue; } @@ -459,7 +511,7 @@ void ASTUnit::ClearCachedCompletionResults() { namespace { -/// \brief Gathers information from ASTReader that will be used to initialize +/// Gathers information from ASTReader that will be used to initialize /// a Preprocessor. class ASTInfoCollector : public ASTReaderListener { Preprocessor &PP; @@ -470,8 +522,8 @@ class ASTInfoCollector : public ASTReaderListener { std::shared_ptr<TargetOptions> &TargetOpts; IntrusiveRefCntPtr<TargetInfo> &Target; unsigned &Counter; + bool InitializedLanguage = false; - bool InitializedLanguage; public: ASTInfoCollector(Preprocessor &PP, ASTContext *Context, HeaderSearchOptions &HSOpts, PreprocessorOptions &PPOpts, @@ -480,30 +532,29 @@ public: IntrusiveRefCntPtr<TargetInfo> &Target, unsigned &Counter) : PP(PP), Context(Context), HSOpts(HSOpts), PPOpts(PPOpts), LangOpt(LangOpt), TargetOpts(TargetOpts), Target(Target), - Counter(Counter), InitializedLanguage(false) {} + Counter(Counter) {} bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain, bool AllowCompatibleDifferences) override { if (InitializedLanguage) return false; - + LangOpt = LangOpts; InitializedLanguage = true; - + updated(); return false; } - virtual bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, - StringRef SpecificModuleCachePath, - bool Complain) override { + bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, + StringRef SpecificModuleCachePath, + bool Complain) override { this->HSOpts = HSOpts; return false; } - virtual bool - ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain, - std::string &SuggestedPredefines) override { + bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain, + std::string &SuggestedPredefines) override { this->PPOpts = PPOpts; return false; } @@ -557,19 +608,18 @@ private: } }; - /// \brief Diagnostic consumer that saves each diagnostic it is given. +/// Diagnostic consumer that saves each diagnostic it is given. class StoredDiagnosticConsumer : public DiagnosticConsumer { SmallVectorImpl<StoredDiagnostic> *StoredDiags; SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags; - const LangOptions *LangOpts; - SourceManager *SourceMgr; + const LangOptions *LangOpts = nullptr; + SourceManager *SourceMgr = nullptr; public: StoredDiagnosticConsumer( SmallVectorImpl<StoredDiagnostic> *StoredDiags, SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags) - : StoredDiags(StoredDiags), StandaloneDiags(StandaloneDiags), - LangOpts(nullptr), SourceMgr(nullptr) { + : StoredDiags(StoredDiags), StandaloneDiags(StandaloneDiags) { assert((StoredDiags || StandaloneDiags) && "No output collections were passed to StoredDiagnosticConsumer."); } @@ -585,20 +635,20 @@ public: const Diagnostic &Info) override; }; -/// \brief RAII object that optionally captures diagnostics, if +/// RAII object that optionally captures diagnostics, if /// there is no diagnostic client to capture them already. class CaptureDroppedDiagnostics { DiagnosticsEngine &Diags; StoredDiagnosticConsumer Client; - DiagnosticConsumer *PreviousClient; + DiagnosticConsumer *PreviousClient = nullptr; std::unique_ptr<DiagnosticConsumer> OwningPreviousClient; public: - CaptureDroppedDiagnostics(bool RequestCapture, DiagnosticsEngine &Diags, - SmallVectorImpl<StoredDiagnostic> *StoredDiags, - SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags) - : Diags(Diags), Client(StoredDiags, StandaloneDiags), PreviousClient(nullptr) - { + CaptureDroppedDiagnostics( + bool RequestCapture, DiagnosticsEngine &Diags, + SmallVectorImpl<StoredDiagnostic> *StoredDiags, + SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags) + : Diags(Diags), Client(StoredDiags, StandaloneDiags) { if (RequestCapture || Diags.getClient() == nullptr) { OwningPreviousClient = Diags.takeClient(); PreviousClient = Diags.getClient(); @@ -612,7 +662,7 @@ public: } }; -} // anonymous namespace +} // namespace static ASTUnit::StandaloneDiagnostic makeStandaloneDiagnostic(const LangOptions &LangOpts, @@ -634,7 +684,7 @@ void StoredDiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level Level, } if (StandaloneDiags) { - llvm::Optional<StoredDiagnostic> StoredDiag = llvm::None; + llvm::Optional<StoredDiagnostic> StoredDiag = None; if (!ResultDiag) { StoredDiag.emplace(Level, Info); ResultDiag = StoredDiag.getPointer(); @@ -664,7 +714,7 @@ ASTDeserializationListener *ASTUnit::getDeserializationListener() { std::unique_ptr<llvm::MemoryBuffer> ASTUnit::getBufferForFile(StringRef Filename, std::string *ErrorStr) { assert(FileMgr); - auto Buffer = FileMgr->getBufferForFile(Filename); + auto Buffer = FileMgr->getBufferForFile(Filename, UserFilesAreVolatile); if (Buffer) return std::move(*Buffer); if (ErrorStr) @@ -672,7 +722,7 @@ ASTUnit::getBufferForFile(StringRef Filename, std::string *ErrorStr) { return nullptr; } -/// \brief Configure the diagnostics object for use with ASTUnit. +/// Configure the diagnostics object for use with ASTUnit. void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags, ASTUnit &AST, bool CaptureDiagnostics) { assert(Diags.get() && "no DiagnosticsEngine was provided"); @@ -693,7 +743,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> ASTUnitCleanup(AST.get()); llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine, - llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> > + llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>> DiagCleanup(Diags.get()); ConfigureDiags(Diags, *AST, CaptureDiagnostics); @@ -741,7 +791,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( bool disableValid = false; if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION")) disableValid = true; - AST->Reader = new ASTReader(PP, AST->Ctx.get(), PCHContainerRdr, { }, + AST->Reader = new ASTReader(PP, AST->Ctx.get(), PCHContainerRdr, {}, /*isysroot=*/"", /*DisableValidation=*/disableValid, AllowPCHWithCompilerErrors); @@ -794,20 +844,20 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( return AST; } -namespace { - -/// \brief Add the given macro to the hash of all top-level entities. -void AddDefinedMacroToHash(const Token &MacroNameTok, unsigned &Hash) { - Hash = llvm::HashString(MacroNameTok.getIdentifierInfo()->getName(), Hash); +/// Add the given macro to the hash of all top-level entities. +static void AddDefinedMacroToHash(const Token &MacroNameTok, unsigned &Hash) { + Hash = llvm::djbHash(MacroNameTok.getIdentifierInfo()->getName(), Hash); } -/// \brief Preprocessor callback class that updates a hash value with the names +namespace { + +/// Preprocessor callback class that updates a hash value with the names /// of all macros that have been defined by the translation unit. class MacroDefinitionTrackerPPCallbacks : public PPCallbacks { unsigned &Hash; - + public: - explicit MacroDefinitionTrackerPPCallbacks(unsigned &Hash) : Hash(Hash) { } + explicit MacroDefinitionTrackerPPCallbacks(unsigned &Hash) : Hash(Hash) {} void MacroDefined(const Token &MacroNameTok, const MacroDirective *MD) override { @@ -815,55 +865,59 @@ public: } }; -/// \brief Add the given declaration to the hash of all top-level entities. -void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) { +} // namespace + +/// Add the given declaration to the hash of all top-level entities. +static void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) { if (!D) return; - + DeclContext *DC = D->getDeclContext(); if (!DC) return; - + if (!(DC->isTranslationUnit() || DC->getLookupParent()->isTranslationUnit())) return; - if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) { - if (EnumDecl *EnumD = dyn_cast<EnumDecl>(D)) { + if (const auto *ND = dyn_cast<NamedDecl>(D)) { + if (const auto *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 (const auto *EI : EnumD->enumerators()) { if (EI->getIdentifier()) - Hash = llvm::HashString(EI->getIdentifier()->getName(), Hash); + Hash = llvm::djbHash(EI->getIdentifier()->getName(), Hash); } } } if (ND->getIdentifier()) - Hash = llvm::HashString(ND->getIdentifier()->getName(), Hash); + Hash = llvm::djbHash(ND->getIdentifier()->getName(), Hash); else if (DeclarationName Name = ND->getDeclName()) { std::string NameStr = Name.getAsString(); - Hash = llvm::HashString(NameStr, Hash); + Hash = llvm::djbHash(NameStr, Hash); } return; } - if (ImportDecl *ImportD = dyn_cast<ImportDecl>(D)) { - if (Module *Mod = ImportD->getImportedModule()) { + if (const auto *ImportD = dyn_cast<ImportDecl>(D)) { + if (const Module *Mod = ImportD->getImportedModule()) { std::string ModName = Mod->getFullModuleName(); - Hash = llvm::HashString(ModName, Hash); + Hash = llvm::djbHash(ModName, Hash); } return; } } +namespace { + class TopLevelDeclTrackerConsumer : public ASTConsumer { ASTUnit &Unit; unsigned &Hash; - + public: TopLevelDeclTrackerConsumer(ASTUnit &_Unit, unsigned &Hash) - : Unit(_Unit), Hash(Hash) { + : Unit(_Unit), Hash(Hash) { Hash = 0; } @@ -886,14 +940,14 @@ public: void handleFileLevelDecl(Decl *D) { Unit.addFileLevelDecl(D); - if (NamespaceDecl *NSD = dyn_cast<NamespaceDecl>(D)) { + if (auto *NSD = dyn_cast<NamespaceDecl>(D)) { for (auto *I : NSD->decls()) handleFileLevelDecl(I); } } bool HandleTopLevelDecl(DeclGroupRef D) override { - for (Decl *TopLevelDecl : D) + for (auto *TopLevelDecl : D) handleTopLevelDecl(TopLevelDecl); return true; } @@ -902,7 +956,7 @@ public: void HandleInterestingDecl(DeclGroupRef) override {} void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override { - for (Decl *TopLevelDecl : D) + for (auto *TopLevelDecl : D) handleTopLevelDecl(TopLevelDecl); } @@ -932,8 +986,9 @@ public: TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {} bool hasCodeCompletionSupport() const override { return false; } + TranslationUnitKind getTranslationUnitKind() override { - return Unit.getTranslationUnitKind(); + return Unit.getTranslationUnitKind(); } }; @@ -949,7 +1004,7 @@ public: void AfterPCHEmitted(ASTWriter &Writer) override { TopLevelDeclIDs.reserve(TopLevelDecls.size()); - for (Decl *D : TopLevelDecls) { + for (const auto *D : TopLevelDecls) { // Invalid top-level decls may not have been serialized. if (D->isInvalidDecl()) continue; @@ -958,7 +1013,7 @@ public: } void HandleTopLevelDecl(DeclGroupRef DG) override { - for (Decl *D : DG) { + for (auto *D : DG) { // FIXME: Currently ObjC method declarations are incorrectly being // reported as top-level declarations, even though their DeclContext // is the containing ObjC @interface/@implementation. This is a @@ -981,7 +1036,7 @@ private: llvm::SmallVector<ASTUnit::StandaloneDiagnostic, 4> PreambleDiags; }; -} // anonymous namespace +} // namespace static bool isNonDriverDiag(const StoredDiagnostic &StoredDiag) { return StoredDiag.getLocation().isValid(); @@ -1004,7 +1059,7 @@ static void checkAndSanitizeDiags(SmallVectorImpl<StoredDiagnostic> & // been careful to make sure that the source manager's state // before and after are identical, so that we can reuse the source // location itself. - for (StoredDiagnostic &SD : StoredDiagnostics) { + for (auto &SD : StoredDiagnostics) { if (SD.getLocation().isValid()) { FullSourceLoc Loc(SD.getLocation(), SM); SD.setLocation(Loc); @@ -1052,11 +1107,11 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, Clang->setInvocation(CCInvocation); OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile(); - + // Set up diagnostics, capturing any diagnostics that would // otherwise be dropped. Clang->setDiagnostics(&getDiagnostics()); - + // Create the target instance. Clang->setTarget(TargetInfo::CreateTargetInfo( Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); @@ -1068,7 +1123,7 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, // FIXME: We shouldn't need to do this, the target should be immutable once // created. This complexity should be lifted elsewhere. Clang->getTarget().adjust(Clang->getLangOpts()); - + assert(Clang->getFrontendOpts().Inputs.size() == 1 && "Invocation must have exactly one source file!"); assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == @@ -1097,10 +1152,10 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, // Create a file manager object to provide access to and cache the filesystem. Clang->setFileManager(&getFileManager()); - + // Create the source manager. Clang->setSourceManager(&getSourceManager()); - + // If the main file has been overridden due to the use of a preamble, // make that override happen and introduce the preamble. if (OverrideMainBuffer) { @@ -1135,7 +1190,7 @@ bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, goto error; transferASTDataFromCompilerInstance(*Clang); - + Act->EndSourceFile(); FailedParseDiagnostics.clear(); @@ -1192,22 +1247,22 @@ makeStandaloneDiagnostic(const LangOptions &LangOpts, if (OutDiag.Filename.empty()) return OutDiag; OutDiag.LocOffset = SM.getFileOffset(FileLoc); - for (const CharSourceRange &Range : InDiag.getRanges()) + for (const auto &Range : InDiag.getRanges()) OutDiag.Ranges.push_back(makeStandaloneRange(Range, SM, LangOpts)); - for (const FixItHint &FixIt : InDiag.getFixIts()) + for (const auto &FixIt : InDiag.getFixIts()) OutDiag.FixIts.push_back(makeStandaloneFixIt(SM, LangOpts, FixIt)); return OutDiag; } -/// \brief Attempt to build or re-use a precompiled preamble when (re-)parsing +/// Attempt to build or re-use a precompiled preamble when (re-)parsing /// the source file. /// /// This routine will compute the preamble of the main source file. If a -/// non-trivial preamble is found, it will precompile that preamble into a +/// non-trivial preamble is found, it will precompile that preamble into a /// precompiled header so that the precompiled preamble can be used to reduce /// reparsing time. If a precompiled preamble has already been constructed, -/// this routine will determine if it is still valid and, if so, avoid +/// this routine will determine if it is still valid and, if so, avoid /// rebuilding the precompiled preamble. /// /// \param AllowRebuild When true (the default), this routine is @@ -1223,15 +1278,14 @@ makeStandaloneDiagnostic(const LangOptions &LangOpts, std::unique_ptr<llvm::MemoryBuffer> ASTUnit::getMainBufferWithPrecompiledPreamble( std::shared_ptr<PCHContainerOperations> PCHContainerOps, - const CompilerInvocation &PreambleInvocationIn, + CompilerInvocation &PreambleInvocationIn, IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool AllowRebuild, unsigned MaxLines) { - auto MainFilePath = PreambleInvocationIn.getFrontendOpts().Inputs[0].getFile(); std::unique_ptr<llvm::MemoryBuffer> MainFileBuffer = getBufferForFileHandlingRemapping(PreambleInvocationIn, VFS.get(), - MainFilePath); + MainFilePath, UserFilesAreVolatile); if (!MainFileBuffer) return nullptr; @@ -1259,6 +1313,7 @@ ASTUnit::getMainBufferWithPrecompiledPreamble( Preamble.reset(); PreambleDiagnostics.clear(); TopLevelDeclsInPreamble.clear(); + PreambleSrcLocCache.clear(); PreambleRebuildCounter = 1; } } @@ -1290,9 +1345,18 @@ ASTUnit::getMainBufferWithPrecompiledPreamble( SimpleTimer PreambleTimer(WantTiming); PreambleTimer.setOutput("Precompiling preamble"); + const bool PreviousSkipFunctionBodies = + PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies; + if (SkipFunctionBodies == SkipFunctionBodiesScope::Preamble) + PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies = true; + llvm::ErrorOr<PrecompiledPreamble> NewPreamble = PrecompiledPreamble::Build( PreambleInvocationIn, MainFileBuffer.get(), Bounds, *Diagnostics, VFS, PCHContainerOps, /*StoreInMemory=*/false, Callbacks); + + PreambleInvocationIn.getFrontendOpts().SkipFunctionBodies = + PreviousSkipFunctionBodies; + if (NewPreamble) { Preamble = std::move(*NewPreamble); PreambleRebuildCounter = 1; @@ -1306,7 +1370,6 @@ ASTUnit::getMainBufferWithPrecompiledPreamble( case BuildPreambleError::CouldntCreateTargetInfo: case BuildPreambleError::BeginSourceFileFailed: case BuildPreambleError::CouldntEmitPCH: - case BuildPreambleError::CouldntCreateVFSOverlay: // These erros are more likely to repeat, retry after some period. PreambleRebuildCounter = DefaultPreambleRebuildInterval; return nullptr; @@ -1344,7 +1407,7 @@ void ASTUnit::RealizeTopLevelDeclsFromPreamble() { std::vector<Decl *> Resolved; Resolved.reserve(TopLevelDeclsInPreamble.size()); ExternalASTSource &Source = *getASTContext().getExternalSource(); - for (serialization::DeclID TopLevelDecl : TopLevelDeclsInPreamble) { + for (const auto TopLevelDecl : TopLevelDeclsInPreamble) { // Resolve the declaration ID to an actual declaration, possibly // deserializing the declaration in the process. if (Decl *D = Source.GetExternalDecl(TopLevelDecl)) @@ -1388,12 +1451,12 @@ StringRef ASTUnit::getMainFileName() const { return FE->getName(); } - return StringRef(); + return {}; } StringRef ASTUnit::getASTFileName() const { if (!isMainFileAST()) - return StringRef(); + return {}; serialization::ModuleFile & Mod = Reader->getModuleManager().getPrimaryModule(); @@ -1408,8 +1471,6 @@ ASTUnit::create(std::shared_ptr<CompilerInvocation> CI, ConfigureDiags(Diags, *AST, CaptureDiagnostics); IntrusiveRefCntPtr<vfs::FileSystem> VFS = createVFSFromCompilerInvocation(*CI, *Diags); - if (!VFS) - return nullptr; AST->Diagnostics = Diags; AST->FileSystemOpts = CI->getFileSystemOpts(); AST->Invocation = std::move(CI); @@ -1442,7 +1503,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction( if (!AST) return nullptr; } - + if (!ResourceFilesPath.empty()) { // Override the resources path. CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath; @@ -1460,7 +1521,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction( llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> ASTUnitCleanup(OwnAST.get()); llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine, - llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> > + llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>> DiagCleanup(Diags.get()); // We'll manage file buffers ourselves. @@ -1478,11 +1539,11 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction( Clang->setInvocation(std::move(CI)); AST->OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile(); - + // Set up diagnostics, capturing any diagnostics that would // otherwise be dropped. Clang->setDiagnostics(&AST->getDiagnostics()); - + // Create the target instance. Clang->setTarget(TargetInfo::CreateTargetInfo( Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); @@ -1494,7 +1555,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction( // FIXME: We shouldn't need to do this, the target should be immutable once // created. This complexity should be lifted elsewhere. Clang->getTarget().adjust(Clang->getLangOpts()); - + assert(Clang->getFrontendOpts().Inputs.size() == 1 && "Invocation must have exactly one source file!"); assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == @@ -1512,7 +1573,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction( // Create a file manager object to provide access to and cache the filesystem. Clang->setFileManager(&AST->getFileManager()); - + // Create the source manager. Clang->setSourceManager(&AST->getSourceManager()); @@ -1558,7 +1619,7 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction( // Steal the created target, context, and preprocessor. AST->transferASTDataFromCompilerInstance(*Clang); - + Act->EndSourceFile(); if (OwnAST) @@ -1623,12 +1684,12 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation( AST->FileSystemOpts = FileMgr->getFileSystemOpts(); AST->FileMgr = FileMgr; AST->UserFilesAreVolatile = UserFilesAreVolatile; - + // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> ASTUnitCleanup(AST.get()); llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine, - llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> > + llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>> DiagCleanup(Diags.get()); if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps), @@ -1646,7 +1707,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine( ArrayRef<RemappedFile> RemappedFiles, bool RemappedFilesKeepOriginalName, unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind, bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion, - bool AllowPCHWithCompilerErrors, bool SkipFunctionBodies, + bool AllowPCHWithCompilerErrors, SkipFunctionBodiesScope SkipFunctionBodies, bool SingleFileParse, bool UserFilesAreVolatile, bool ForSerialization, llvm::Optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST, IntrusiveRefCntPtr<vfs::FileSystem> VFS) { @@ -1657,11 +1718,10 @@ ASTUnit *ASTUnit::LoadFromCommandLine( std::shared_ptr<CompilerInvocation> CI; { - CaptureDroppedDiagnostics Capture(CaptureDiagnostics, *Diags, &StoredDiagnostics, nullptr); - CI = clang::createInvocationFromCommandLine( + CI = createInvocationFromCommandLine( llvm::makeArrayRef(ArgBegin, ArgEnd), Diags, VFS); if (!CI) return nullptr; @@ -1676,11 +1736,12 @@ ASTUnit *ASTUnit::LoadFromCommandLine( PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName; PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors; PPOpts.SingleFileParseMode = SingleFileParse; - + // Override the resources path. CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath; - CI->getFrontendOpts().SkipFunctionBodies = SkipFunctionBodies; + CI->getFrontendOpts().SkipFunctionBodies = + SkipFunctionBodies == SkipFunctionBodiesScope::PreambleAndMainFile; if (ModuleFormat) CI->getHeaderSearchOpts().ModuleFormat = ModuleFormat.getValue(); @@ -1688,14 +1749,14 @@ ASTUnit *ASTUnit::LoadFromCommandLine( // Create the AST unit. std::unique_ptr<ASTUnit> AST; AST.reset(new ASTUnit(false)); + AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size(); + AST->StoredDiagnostics.swap(StoredDiagnostics); ConfigureDiags(Diags, *AST, CaptureDiagnostics); AST->Diagnostics = Diags; AST->FileSystemOpts = CI->getFileSystemOpts(); if (!VFS) VFS = vfs::getRealFileSystem(); VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS); - if (!VFS) - return nullptr; AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS); AST->PCMCache = new MemoryBufferCache; AST->OnlyLocalDecls = OnlyLocalDecls; @@ -1705,9 +1766,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine( AST->IncludeBriefCommentsInCodeCompletion = IncludeBriefCommentsInCodeCompletion; AST->UserFilesAreVolatile = UserFilesAreVolatile; - AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size(); - AST->StoredDiagnostics.swap(StoredDiagnostics); AST->Invocation = CI; + AST->SkipFunctionBodies = SkipFunctionBodies; if (ForSerialization) AST->WriterData.reset(new ASTWriterData(*AST->PCMCache)); // Zero out now to ease cleanup during crash recovery. @@ -1745,7 +1805,7 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, } clearFileLevelDecls(); - + SimpleTimer ParsingTimer(WantTiming); ParsingTimer.setOutput("Reparsing " + getMainFileName()); @@ -1767,7 +1827,6 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS); - // Clear out the diagnostics state. FileMgr.reset(); getDiagnostics().Reset(); @@ -1779,7 +1838,7 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, bool Result = Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS); - // If we're caching global code-completion results, and the top-level + // If we're caching global code-completion results, and the top-level // declarations have changed, clear out the code-completion cache. if (!Result && ShouldCacheCodeCompletionResults && CurrentTopLevelHashValue != CompletionCacheTopLevelHashValue) @@ -1788,7 +1847,7 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, // We now need to clear out the completion info related to this translation // unit; it'll be recreated if necessary. CCTUInfo.reset(); - + return Result; } @@ -1810,23 +1869,23 @@ void ASTUnit::ResetForParse() { //----------------------------------------------------------------------------// namespace { - /// \brief Code completion consumer that combines the cached code-completion + + /// Code completion consumer that combines the cached code-completion /// results from an ASTUnit with the code-completion results provided to it, - /// then passes the result on to + /// then passes the result on to class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer { uint64_t NormalContexts; ASTUnit &AST; CodeCompleteConsumer &Next; - + public: AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next, const CodeCompleteOptions &CodeCompleteOpts) - : CodeCompleteConsumer(CodeCompleteOpts, Next.isOutputBinary()), - AST(AST), Next(Next) - { + : CodeCompleteConsumer(CodeCompleteOpts, Next.isOutputBinary()), + AST(AST), Next(Next) { // Compute the set of contexts in which we will look when we don't have // any information about the specific context. - NormalContexts + NormalContexts = (1LL << CodeCompletionContext::CCC_TopLevel) | (1LL << CodeCompletionContext::CCC_ObjCInterface) | (1LL << CodeCompletionContext::CCC_ObjCImplementation) @@ -1865,9 +1924,10 @@ namespace { return Next.getCodeCompletionTUInfo(); } }; -} // anonymous namespace -/// \brief Helper function that computes which global names are hidden by the +} // namespace + +/// Helper function that computes which global names are hidden by the /// local code-completion results. static void CalculateHiddenNames(const CodeCompletionContext &Context, CodeCompletionResult *Results, @@ -1895,13 +1955,13 @@ static void CalculateHiddenNames(const CodeCompletionContext &Context, case CodeCompletionContext::CCC_ParenthesizedExpression: case CodeCompletionContext::CCC_ObjCInterfaceName: break; - + case CodeCompletionContext::CCC_EnumTag: case CodeCompletionContext::CCC_UnionTag: case CodeCompletionContext::CCC_ClassOrStructTag: OnlyTagNames = true; break; - + case CodeCompletionContext::CCC_ObjCProtocolName: case CodeCompletionContext::CCC_MacroName: case CodeCompletionContext::CCC_MacroNameUse: @@ -1919,12 +1979,12 @@ static void CalculateHiddenNames(const CodeCompletionContext &Context, // be hidden. return; } - - typedef CodeCompletionResult Result; + + using Result = CodeCompletionResult; for (unsigned I = 0; I != NumResults; ++I) { if (Results[I].Kind != Result::RK_Declaration) continue; - + unsigned IDNS = Results[I].Declaration->getUnderlyingDecl()->getIdentifierNamespace(); @@ -1932,17 +1992,17 @@ static void CalculateHiddenNames(const CodeCompletionContext &Context, if (OnlyTagNames) Hiding = (IDNS & Decl::IDNS_Tag); else { - unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member | + unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member | Decl::IDNS_Namespace | Decl::IDNS_Ordinary | Decl::IDNS_NonMemberOperator); if (Ctx.getLangOpts().CPlusPlus) HiddenIDNS |= Decl::IDNS_Tag; Hiding = (IDNS & HiddenIDNS); } - + if (!Hiding) continue; - + DeclarationName Name = Results[I].Declaration->getDeclName(); if (IdentifierInfo *Identifier = Name.getAsIdentifierInfo()) HiddenNames.insert(Identifier->getName()); @@ -1954,7 +2014,7 @@ static void CalculateHiddenNames(const CodeCompletionContext &Context, void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context, CodeCompletionResult *Results, - unsigned NumResults) { + unsigned NumResults) { // Merge the results we were given with the results we cached. bool AddedResult = false; uint64_t InContexts = @@ -1962,31 +2022,31 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S, ? NormalContexts : (1LL << Context.getKind()); // Contains the set of names that are hidden by "local" completion results. llvm::StringSet<llvm::BumpPtrAllocator> HiddenNames; - typedef CodeCompletionResult Result; + using Result = CodeCompletionResult; SmallVector<Result, 8> AllResults; - for (ASTUnit::cached_completion_iterator + for (ASTUnit::cached_completion_iterator C = AST.cached_completion_begin(), CEnd = AST.cached_completion_end(); C != CEnd; ++C) { - // If the context we are in matches any of the contexts we are + // If the context we are in matches any of the contexts we are // interested in, we'll add this result. if ((C->ShowInContexts & InContexts) == 0) continue; - + // If we haven't added any results previously, do so now. if (!AddedResult) { - CalculateHiddenNames(Context, Results, NumResults, S.Context, + CalculateHiddenNames(Context, Results, NumResults, S.Context, HiddenNames); AllResults.insert(AllResults.end(), Results, Results + NumResults); AddedResult = true; } - + // Determine whether this global completion result is hidden by a local // completion result. If so, skip it. if (C->Kind != CXCursor_MacroDefinition && HiddenNames.count(C->Completion->getTypedText())) continue; - + // Adjust priority based on similar type classes. unsigned Priority = C->Priority; CodeCompletionString *Completion = C->Completion; @@ -1994,7 +2054,7 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S, if (C->Kind == CXCursor_MacroDefinition) { Priority = getMacroUsagePriority(C->Completion->getTypedText(), S.getLangOpts(), - Context.getPreferredType()->isAnyPointerType()); + Context.getPreferredType()->isAnyPointerType()); } else if (C->Type) { CanQualType Expected = S.Context.getCanonicalType( @@ -2013,7 +2073,7 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S, } } } - + // Adjust the completion string, if required. if (C->Kind == CXCursor_MacroDefinition && Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) { @@ -2025,18 +2085,18 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S, Priority = CCP_CodePattern; Completion = Builder.TakeString(); } - + AllResults.push_back(Result(Completion, Priority, C->Kind, C->Availability)); } - + // If we did not add any cached completion results, just forward the // results we were given to the next consumer. if (!AddedResult) { Next.ProcessCodeCompleteResults(S, Context, Results, NumResults); return; } - + Next.ProcessCodeCompleteResults(S, Context, AllResults.data(), AllResults.size()); } @@ -2068,6 +2128,8 @@ void ASTUnit::CodeComplete( CodeCompleteOpts.IncludeCodePatterns = IncludeCodePatterns; CodeCompleteOpts.IncludeGlobals = CachedCompletionResults.empty(); CodeCompleteOpts.IncludeBriefComments = IncludeBriefComments; + CodeCompleteOpts.LoadExternal = Consumer.loadExternal(); + CodeCompleteOpts.IncludeFixIts = Consumer.includeFixIts(); assert(IncludeBriefComments == this->IncludeBriefCommentsInCodeCompletion); @@ -2092,11 +2154,11 @@ void ASTUnit::CodeComplete( auto &Inv = *CCInvocation; Clang->setInvocation(std::move(CCInvocation)); OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile(); - + // Set up diagnostics, capturing any diagnostics produced. Clang->setDiagnostics(&Diag); - CaptureDroppedDiagnostics Capture(true, - Clang->getDiagnostics(), + CaptureDroppedDiagnostics Capture(true, + Clang->getDiagnostics(), &StoredDiagnostics, nullptr); ProcessWarningOptions(Diag, Inv.getDiagnosticOpts()); @@ -2107,13 +2169,13 @@ void ASTUnit::CodeComplete( Clang->setInvocation(nullptr); return; } - + // Inform the target of the language options. // // FIXME: We shouldn't need to do this, the target should be immutable once // created. This complexity should be lifted elsewhere. Clang->getTarget().adjust(Clang->getLangOpts()); - + assert(Clang->getFrontendOpts().Inputs.size() == 1 && "Invocation must have exactly one source file!"); assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == @@ -2122,7 +2184,7 @@ void ASTUnit::CodeComplete( assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() != InputKind::LLVM_IR && "IR inputs not support here!"); - + // Use the source and file managers that we were given. Clang->setFileManager(&FileMgr); Clang->setSourceManager(&SourceMgr); @@ -2209,7 +2271,7 @@ bool ASTUnit::Save(StringRef File) { if (llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath)) return true; - // FIXME: Can we somehow regenerate the stat cache here, or do we need to + // FIXME: Can we somehow regenerate the stat cache here, or do we need to // unconditionally create a stat cache when we parse the file? llvm::raw_fd_ostream Out(fd, /*shouldClose=*/true); @@ -2257,7 +2319,7 @@ bool ASTUnit::serialize(raw_ostream &OS) { return serializeUnit(Writer, Buffer, getSema(), hasErrors, OS); } -typedef ContinuousRangeMap<unsigned, int, 2> SLocRemap; +using SLocRemap = ContinuousRangeMap<unsigned, int, 2>; void ASTUnit::TranslateStoredDiagnostics( FileManager &FileMgr, @@ -2271,7 +2333,7 @@ void ASTUnit::TranslateStoredDiagnostics( SmallVector<StoredDiagnostic, 4> Result; Result.reserve(Diags.size()); - for (const StandaloneDiagnostic &SD : Diags) { + for (const auto &SD : Diags) { // Rebuild the StoredDiagnostic. if (SD.Filename.empty()) continue; @@ -2303,7 +2365,7 @@ void ASTUnit::TranslateStoredDiagnostics( SmallVector<FixItHint, 2> FixIts; FixIts.reserve(SD.FixIts.size()); - for (const StandaloneFixIt &FixIt : SD.FixIts) { + for (const auto &FixIt : SD.FixIts) { FixIts.push_back(FixItHint()); FixItHint &FH = FixIts.back(); FH.CodeToInsert = FixIt.CodeToInsert; @@ -2312,7 +2374,7 @@ void ASTUnit::TranslateStoredDiagnostics( FH.RemoveRange = CharSourceRange::getCharRange(BL, EL); } - Result.push_back(StoredDiagnostic(SD.Level, SD.ID, + Result.push_back(StoredDiagnostic(SD.Level, SD.ID, SD.Message, Loc, Ranges, FixIts)); } Result.swap(Out); @@ -2320,7 +2382,7 @@ void ASTUnit::TranslateStoredDiagnostics( void ASTUnit::addFileLevelDecl(Decl *D) { assert(D); - + // We only care about local declarations. if (D->isFromASTFile()) return; @@ -2397,7 +2459,7 @@ void ASTUnit::findFileRegionDecls(FileID File, unsigned Offset, unsigned Length, std::make_pair(Offset + Length, (Decl *)nullptr), llvm::less_first()); if (EndIt != LocDecls.end()) ++EndIt; - + for (LocDeclsTy::iterator DIt = BeginIt; DIt != EndIt; ++DIt) Decls.push_back(DIt->second); } @@ -2416,7 +2478,7 @@ SourceLocation ASTUnit::getLocation(const FileEntry *File, return SM.getMacroArgExpandedLocation(FileLoc.getLocWithOffset(Offset)); } -/// \brief If \arg Loc is a loaded location from the preamble, returns +/// If \arg Loc is a loaded location from the preamble, returns /// the corresponding local location of the main file, otherwise it returns /// \arg Loc. SourceLocation ASTUnit::mapLocationFromPreamble(SourceLocation Loc) const { @@ -2437,7 +2499,7 @@ SourceLocation ASTUnit::mapLocationFromPreamble(SourceLocation Loc) const { return Loc; } -/// \brief If \arg Loc is a local location of the main file but inside the +/// If \arg Loc is a local location of the main file but inside the /// preamble chunk, returns the corresponding loaded location from the /// preamble, otherwise it returns \arg Loc. SourceLocation ASTUnit::mapLocationToPreamble(SourceLocation Loc) const { @@ -2462,10 +2524,10 @@ bool ASTUnit::isInPreambleFileID(SourceLocation Loc) const { FileID FID; if (SourceMgr) FID = SourceMgr->getPreambleFileID(); - + if (Loc.isInvalid() || FID.isInvalid()) return false; - + return SourceMgr->isInFileID(Loc, FID); } @@ -2473,10 +2535,10 @@ bool ASTUnit::isInMainFileID(SourceLocation Loc) const { FileID FID; if (SourceMgr) FID = SourceMgr->getMainFileID(); - + if (Loc.isInvalid() || FID.isInvalid()) return false; - + return SourceMgr->isInFileID(Loc, FID); } @@ -2484,9 +2546,9 @@ SourceLocation ASTUnit::getEndOfPreambleFileID() const { FileID FID; if (SourceMgr) FID = SourceMgr->getPreambleFileID(); - + if (FID.isInvalid()) - return SourceLocation(); + return {}; return SourceMgr->getLocForEndOfFile(FID); } @@ -2495,10 +2557,10 @@ SourceLocation ASTUnit::getStartOfMainFileID() const { FileID FID; if (SourceMgr) FID = SourceMgr->getMainFileID(); - + if (FID.isInvalid()) - return SourceLocation(); - + return {}; + return SourceMgr->getLocForStartOfFile(FID); } @@ -2521,7 +2583,7 @@ bool ASTUnit::visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn) { if (isMainFileAST()) { serialization::ModuleFile & Mod = Reader->getModuleManager().getPrimaryModule(); - for (const Decl *D : Reader->getModuleFileLevelDecls(Mod)) { + for (const auto *D : Reader->getModuleFileLevelDecls(Mod)) { if (!Fn(context, D)) return false; } diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt index ba3bd7d28c70..6161b46a9dc5 100644 --- a/lib/Frontend/CMakeLists.txt +++ b/lib/Frontend/CMakeLists.txt @@ -29,6 +29,7 @@ add_clang_library(clangFrontend FrontendAction.cpp FrontendActions.cpp FrontendOptions.cpp + FrontendTiming.cpp HeaderIncludeGen.cpp InitHeaderSearch.cpp InitPreprocessor.cpp diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp index 72e8f68dc051..c4504a14456d 100644 --- a/lib/Frontend/CacheTokens.cpp +++ b/lib/Frontend/CacheTokens.cpp @@ -21,8 +21,8 @@ #include "clang/Lex/Lexer.h" #include "clang/Lex/PTHManager.h" #include "clang/Lex/Preprocessor.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" +#include "llvm/Support/DJB.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" @@ -88,7 +88,7 @@ public: void EmitData(raw_ostream& Out) { using namespace llvm::support; - endian::Writer<little> LE(Out); + endian::Writer LE(Out, little); switch (Kind) { case IsFE: { // Emit stat information. @@ -128,14 +128,14 @@ public: typedef unsigned offset_type; static hash_value_type ComputeHash(PTHEntryKeyVariant V) { - return llvm::HashString(V.getString()); + return llvm::djbHash(V.getString()); } static std::pair<unsigned,unsigned> EmitKeyDataLength(raw_ostream& Out, PTHEntryKeyVariant V, const PTHEntry& E) { using namespace llvm::support; - endian::Writer<little> LE(Out); + endian::Writer LE(Out, little); unsigned n = V.getString().size() + 1 + 1; LE.write<uint16_t>(n); @@ -149,7 +149,7 @@ public: static void EmitKey(raw_ostream& Out, PTHEntryKeyVariant V, unsigned n){ using namespace llvm::support; // Emit the entry kind. - endian::Writer<little>(Out).write<uint8_t>((unsigned)V.getKind()); + Out << char(V.getKind()); // Emit the string. Out.write(V.getString().data(), n - 1); } @@ -157,7 +157,7 @@ public: static void EmitData(raw_ostream& Out, PTHEntryKeyVariant V, const PTHEntry& E, unsigned) { using namespace llvm::support; - endian::Writer<little> LE(Out); + endian::Writer LE(Out, little); // For file entries emit the offsets into the PTH file for token data // and the preprocessor blocks table. @@ -205,18 +205,17 @@ class PTHWriter { void EmitToken(const Token& T); void Emit8(uint32_t V) { - using namespace llvm::support; - endian::Writer<little>(Out).write<uint8_t>(V); + Out << char(V); } void Emit16(uint32_t V) { using namespace llvm::support; - endian::Writer<little>(Out).write<uint16_t>(V); + endian::write<uint16_t>(Out, V, little); } void Emit32(uint32_t V) { using namespace llvm::support; - endian::Writer<little>(Out).write<uint32_t>(V); + endian::write<uint32_t>(Out, V, little); } void EmitBuf(const char *Ptr, unsigned NumBytes) { @@ -225,7 +224,7 @@ class PTHWriter { void EmitString(StringRef V) { using namespace llvm::support; - endian::Writer<little>(Out).write<uint16_t>(V.size()); + endian::write<uint16_t>(Out, V.size(), little); EmitBuf(V.data(), V.size()); } @@ -299,7 +298,7 @@ PTHEntry PTHWriter::LexTokens(Lexer& L) { // Pad 0's so that we emit tokens to a 4-byte alignment. // This speed up reading them back in. using namespace llvm::support; - endian::Writer<little> LE(Out); + endian::Writer LE(Out, little); uint32_t TokenOff = Out.tell(); for (uint64_t N = llvm::OffsetToAlignment(TokenOff, 4); N; --N, ++TokenOff) LE.write<uint8_t>(0); @@ -625,14 +624,14 @@ public: typedef unsigned offset_type; static hash_value_type ComputeHash(PTHIdKey* key) { - return llvm::HashString(key->II->getName()); + return llvm::djbHash(key->II->getName()); } static std::pair<unsigned,unsigned> EmitKeyDataLength(raw_ostream& Out, const PTHIdKey* key, uint32_t) { using namespace llvm::support; unsigned n = key->II->getLength() + 1; - endian::Writer<little>(Out).write<uint16_t>(n); + endian::write<uint16_t>(Out, n, little); return std::make_pair(n, sizeof(uint32_t)); } @@ -646,7 +645,7 @@ public: static void EmitData(raw_ostream& Out, PTHIdKey*, uint32_t pID, unsigned) { using namespace llvm::support; - endian::Writer<little>(Out).write<uint32_t>(pID); + endian::write<uint32_t>(Out, pID, little); } }; } // end anonymous namespace @@ -662,7 +661,8 @@ std::pair<Offset,Offset> PTHWriter::EmitIdentifierTable() { // (2) a map from (IdentifierInfo*, Offset)* -> persistent IDs // Note that we use 'calloc', so all the bytes are 0. - PTHIdKey *IIDMap = (PTHIdKey*)calloc(idcount, sizeof(PTHIdKey)); + PTHIdKey *IIDMap = static_cast<PTHIdKey*>( + llvm::safe_calloc(idcount, sizeof(PTHIdKey))); // Create the hashtable. llvm::OnDiskChainedHashTableGenerator<PTHIdentifierTableTrait> IIOffMap; diff --git a/lib/Frontend/CodeGenOptions.cpp b/lib/Frontend/CodeGenOptions.cpp index 50bb9f951be4..84a39f2d570d 100644 --- a/lib/Frontend/CodeGenOptions.cpp +++ b/lib/Frontend/CodeGenOptions.cpp @@ -17,7 +17,7 @@ CodeGenOptions::CodeGenOptions() { #define ENUM_CODEGENOPT(Name, Type, Bits, Default) set##Name(Default); #include "clang/Frontend/CodeGenOptions.def" - RelocationModel = "pic"; + RelocationModel = llvm::Reloc::PIC_; memcpy(CoverageVersion, "402*", 4); } diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 7208177aa012..155ead4ac8e8 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -16,6 +16,7 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/MemoryBufferCache.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/Stack.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Version.h" #include "clang/Config/config.h" @@ -302,11 +303,9 @@ CompilerInstance::createDiagnostics(DiagnosticOptions *Opts, FileManager *CompilerInstance::createFileManager() { if (!hasVirtualFileSystem()) { - if (IntrusiveRefCntPtr<vfs::FileSystem> VFS = - createVFSFromCompilerInvocation(getInvocation(), getDiagnostics())) - setVirtualFileSystem(VFS); - else - return nullptr; + IntrusiveRefCntPtr<vfs::FileSystem> VFS = + createVFSFromCompilerInvocation(getInvocation(), getDiagnostics()); + setVirtualFileSystem(VFS); } FileMgr = new FileManager(getFileSystemOpts(), VirtualFileSystem); return FileMgr.get(); @@ -464,7 +463,7 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) { /*ShowDepth=*/false); } - if (DepOpts.PrintShowIncludes) { + if (DepOpts.ShowIncludesDest != ShowIncludesDestination::None) { AttachHeaderIncludeGen(*PP, DepOpts, /*ShowAllHeaders=*/true, /*OutputPath=*/"", /*ShowDepth=*/true, /*MSStyle=*/true); @@ -854,36 +853,7 @@ bool CompilerInstance::InitializeSourceManager( // Figure out where to get and map in the main file. if (InputFile != "-") { - const FileEntry *File; - if (Opts.FindPchSource.empty()) { - File = FileMgr.getFile(InputFile, /*OpenFile=*/true); - } else { - // When building a pch file in clang-cl mode, the .h file is built as if - // it was included by a cc file. Since the driver doesn't know about - // all include search directories, the frontend must search the input - // file through HeaderSearch here, as if it had been included by the - // cc file at Opts.FindPchSource. - const FileEntry *FindFile = FileMgr.getFile(Opts.FindPchSource); - if (!FindFile) { - Diags.Report(diag::err_fe_error_reading) << Opts.FindPchSource; - return false; - } - const DirectoryLookup *UnusedCurDir; - SmallVector<std::pair<const FileEntry *, const DirectoryEntry *>, 16> - Includers; - Includers.push_back(std::make_pair(FindFile, FindFile->getDir())); - File = HS->LookupFile(InputFile, SourceLocation(), /*isAngled=*/false, - /*FromDir=*/nullptr, - /*CurDir=*/UnusedCurDir, Includers, - /*SearchPath=*/nullptr, - /*RelativePath=*/nullptr, - /*RequestingModule=*/nullptr, - /*SuggestedModule=*/nullptr, /*IsMapped=*/nullptr, - /*SkipCache=*/true); - // Also add the header to /showIncludes output. - if (File) - DepOpts.ShowIncludesPretendHeader = File->getName(); - } + const FileEntry *File = FileMgr.getFile(InputFile, /*OpenFile=*/true); if (!File) { Diags.Report(diag::err_fe_error_reading) << InputFile; return false; @@ -1044,7 +1014,7 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { return !getDiagnostics().getClient()->getNumErrors(); } -/// \brief Determine the appropriate source input kind based on language +/// Determine the appropriate source input kind based on language /// options. static InputKind::Language getLanguageFromOptions(const LangOptions &LangOpts) { if (LangOpts.OpenCL) @@ -1056,7 +1026,7 @@ static InputKind::Language getLanguageFromOptions(const LangOptions &LangOpts) { return LangOpts.CPlusPlus ? InputKind::CXX : InputKind::C; } -/// \brief Compile a module file for the given module, using the options +/// Compile a module file for the given module, using the options /// provided by the importing compiler instance. Returns true if the module /// was built without errors. static bool @@ -1090,6 +1060,10 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc, }), PPOpts.Macros.end()); + // If the original compiler invocation had -fmodule-name, pass it through. + Invocation->getLangOpts()->ModuleName = + ImportingInstance.getInvocation().getLangOpts()->ModuleName; + // Note the name of the module we're building. Invocation->getLangOpts()->CurrentModule = ModuleName; @@ -1162,14 +1136,13 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc, // Execute the action to actually build the module in-place. Use a separate // thread so that we get a stack large enough. - const unsigned ThreadStackSize = 8 << 20; llvm::CrashRecoveryContext CRC; CRC.RunSafelyOnThread( [&]() { GenerateModuleFromModuleMapAction Action; Instance.ExecuteAction(Action); }, - ThreadStackSize); + DesiredStackSize); PostBuildStep(Instance); @@ -1186,7 +1159,20 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc, return !Instance.getDiagnostics().hasErrorOccurred(); } -/// \brief Compile a module file for the given module, using the options +static const FileEntry *getPublicModuleMap(const FileEntry *File, + FileManager &FileMgr) { + StringRef Filename = llvm::sys::path::filename(File->getName()); + SmallString<128> PublicFilename(File->getDir()->getName()); + if (Filename == "module_private.map") + llvm::sys::path::append(PublicFilename, "module.map"); + else if (Filename == "module.private.modulemap") + llvm::sys::path::append(PublicFilename, "module.modulemap"); + else + return nullptr; + return FileMgr.getFile(PublicFilename); +} + +/// Compile a module file for the given module, using the options /// provided by the importing compiler instance. Returns true if the module /// was built without errors. static bool compileModuleImpl(CompilerInstance &ImportingInstance, @@ -1202,6 +1188,13 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance, bool Result; if (const FileEntry *ModuleMapFile = ModMap.getContainingModuleMapFile(Module)) { + // Canonicalize compilation to start with the public module map. This is + // vital for submodules declarations in the private module maps to be + // correctly parsed when depending on a top level module in the public one. + if (const FileEntry *PublicMMFile = getPublicModuleMap( + ModuleMapFile, ImportingInstance.getFileManager())) + ModuleMapFile = PublicMMFile; + // Use the module map where this module resides. Result = compileModuleImpl( ImportingInstance, ImportLoc, Module->getTopLevelModuleName(), @@ -1298,7 +1291,7 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance, // case of timeout, build it ourselves. Diags.Report(ModuleNameLoc, diag::remark_module_lock_timeout) << Module->Name; - // Clear the lock file so that future invokations can make progress. + // Clear the lock file so that future invocations can make progress. Locked.unsafeRemoveLockFile(); continue; } @@ -1328,7 +1321,7 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance, } } -/// \brief Diagnose differences between the current definition of the given +/// Diagnose differences between the current definition of the given /// configuration macro and the definition provided on the command line. static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro, Module *Mod, SourceLocation ImportLoc) { @@ -1386,13 +1379,13 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro, } } -/// \brief Write a new timestamp file with the given path. +/// Write a new timestamp file with the given path. static void writeTimestampFile(StringRef TimestampFile) { std::error_code EC; llvm::raw_fd_ostream Out(TimestampFile.str(), EC, llvm::sys::fs::F_None); } -/// \brief Prune the module cache of modules that haven't been accessed in +/// Prune the module cache of modules that haven't been accessed in /// a long time. static void pruneModuleCache(const HeaderSearchOptions &HSOpts) { struct stat StatBuf; @@ -1580,15 +1573,22 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) { if (!ModuleManager) createModuleManager(); + // If -Wmodule-file-config-mismatch is mapped as an error or worse, allow the + // ASTReader to diagnose it, since it can produce better errors that we can. + bool ConfigMismatchIsRecoverable = + getDiagnostics().getDiagnosticLevel(diag::warn_module_config_mismatch, + SourceLocation()) + <= DiagnosticsEngine::Warning; + auto Listener = llvm::make_unique<ReadModuleNames>(*this); auto &ListenerRef = *Listener; ASTReader::ListenerScope ReadModuleNamesListener(*ModuleManager, std::move(Listener)); // Try to load the module file. - switch (ModuleManager->ReadAST(FileName, serialization::MK_ExplicitModule, - SourceLocation(), - ASTReader::ARR_ConfigurationMismatch)) { + switch (ModuleManager->ReadAST( + FileName, serialization::MK_ExplicitModule, SourceLocation(), + ConfigMismatchIsRecoverable ? ASTReader::ARR_ConfigurationMismatch : 0)) { case ASTReader::Success: // We successfully loaded the module file; remember the set of provided // modules so that we don't try to load implicit modules for them. @@ -1653,8 +1653,10 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, // Retrieve the cached top-level module. Module = Known->second; } else if (ModuleName == getLangOpts().CurrentModule) { - // This is the module we're building. - Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); + // This is the module we're building. + Module = PP->getHeaderSearchInfo().lookupModule( + ModuleName, /*AllowSearch*/ true, + /*AllowExtraModuleMapSearch*/ !IsInclusionDirective); /// FIXME: perhaps we should (a) look for a module using the module name // to file map (PrebuiltModuleFiles) and (b) diagnose if still not found? //if (Module == nullptr) { @@ -1666,7 +1668,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first; } else { // Search for a module with the given name. - Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); + Module = PP->getHeaderSearchInfo().lookupModule(ModuleName, true, + !IsInclusionDirective); HeaderSearchOptions &HSOpts = PP->getHeaderSearchInfo().getHeaderSearchOpts(); @@ -1743,7 +1746,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, ImportLoc, ARRFlags)) { case ASTReader::Success: { if (Source != ModuleCache && !Module) { - Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); + Module = PP->getHeaderSearchInfo().lookupModule(ModuleName, true, + !IsInclusionDirective); if (!Module || !Module->getASTFile() || FileMgr->getFile(ModuleFileName) != Module->getASTFile()) { // Error out if Module does not refer to the file in the prebuilt @@ -1859,6 +1863,40 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, for (unsigned I = 1, N = Path.size(); I != N; ++I) { StringRef Name = Path[I].first->getName(); clang::Module *Sub = Module->findSubmodule(Name); + + // If the user is requesting Foo.Private and it doesn't exist, try to + // match Foo_Private and emit a warning asking for the user to write + // @import Foo_Private instead. FIXME: remove this when existing clients + // migrate off of Foo.Private syntax. + if (!Sub && PP->getLangOpts().ImplicitModules && Name == "Private" && + Module == Module->getTopLevelModule()) { + SmallString<128> PrivateModule(Module->Name); + PrivateModule.append("_Private"); + + SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> PrivPath; + auto &II = PP->getIdentifierTable().get( + PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID()); + PrivPath.push_back(std::make_pair(&II, Path[0].second)); + + if (PP->getHeaderSearchInfo().lookupModule(PrivateModule, true, + !IsInclusionDirective)) + Sub = + loadModule(ImportLoc, PrivPath, Visibility, IsInclusionDirective); + if (Sub) { + MapPrivateSubModToTopLevel = true; + if (!getDiagnostics().isIgnored( + diag::warn_no_priv_submodule_use_toplevel, ImportLoc)) { + getDiagnostics().Report(Path[I].second, + diag::warn_no_priv_submodule_use_toplevel) + << Path[I].first << Module->getFullModuleName() << PrivateModule + << SourceRange(Path[0].second, Path[I].second) + << FixItHint::CreateReplacement(SourceRange(Path[0].second), + PrivateModule); + getDiagnostics().Report(Sub->DefinitionLoc, + diag::note_private_top_level_defined); + } + } + } if (!Sub) { // Attempt to perform typo correction to find a module name that works. @@ -1894,39 +1932,6 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, } } - // If the user is requesting Foo.Private and it doesn't exist, try to - // match Foo_Private and emit a warning asking for the user to write - // @import Foo_Private instead. FIXME: remove this when existing clients - // migrate off of Foo.Private syntax. - if (!Sub && PP->getLangOpts().ImplicitModules && Name == "Private" && - Module == Module->getTopLevelModule()) { - SmallString<128> PrivateModule(Module->Name); - PrivateModule.append("_Private"); - - SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> PrivPath; - auto &II = PP->getIdentifierTable().get( - PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID()); - PrivPath.push_back(std::make_pair(&II, Path[0].second)); - - if (PP->getHeaderSearchInfo().lookupModule(PrivateModule)) - Sub = - loadModule(ImportLoc, PrivPath, Visibility, IsInclusionDirective); - if (Sub) { - MapPrivateSubModToTopLevel = true; - if (!getDiagnostics().isIgnored( - diag::warn_no_priv_submodule_use_toplevel, ImportLoc)) { - getDiagnostics().Report(Path[I].second, - diag::warn_no_priv_submodule_use_toplevel) - << Path[I].first << Module->getFullModuleName() << PrivateModule - << SourceRange(Path[0].second, Path[I].second) - << FixItHint::CreateReplacement(SourceRange(Path[0].second), - PrivateModule); - getDiagnostics().Report(Sub->DefinitionLoc, - diag::note_private_top_level_defined); - } - } - } - if (!Sub) { // No submodule by this name. Complain, and don't look for further // submodules. @@ -1977,6 +1982,12 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, Module, ImportLoc); } + // Resolve any remaining module using export_as for this one. + getPreprocessor() + .getHeaderSearchInfo() + .getModuleMap() + .resolveLinkAsDependencies(TopModule); + LastModuleImportLoc = ImportLoc; LastModuleImportResult = ModuleLoadResult(Module); return LastModuleImportResult; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 2e8a737de4e4..78e6babd0251 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1,4 +1,4 @@ -//===--- CompilerInvocation.cpp -------------------------------------------===// +//===- CompilerInvocation.cpp ---------------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -10,54 +10,99 @@ #include "clang/Frontend/CompilerInvocation.h" #include "TestModuleFileExtension.h" #include "clang/Basic/Builtins.h" -#include "clang/Basic/FileManager.h" +#include "clang/Basic/CharInfo.h" +#include "clang/Basic/CommentOptions.h" +#include "clang/Basic/DebugInfoOptions.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticOptions.h" +#include "clang/Basic/FileSystemOptions.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/ObjCRuntime.h" +#include "clang/Basic/Sanitizers.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/TargetOptions.h" #include "clang/Basic/Version.h" +#include "clang/Basic/VirtualFileSystem.h" +#include "clang/Basic/Visibility.h" +#include "clang/Basic/XRayInstr.h" #include "clang/Config/config.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" -#include "clang/Driver/Util.h" +#include "clang/Frontend/CodeGenOptions.h" +#include "clang/Frontend/CommandLineSourceLoc.h" +#include "clang/Frontend/DependencyOutputOptions.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Frontend/FrontendOptions.h" #include "clang/Frontend/LangStandard.h" +#include "clang/Frontend/MigratorOptions.h" +#include "clang/Frontend/PreprocessorOutputOptions.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/PreprocessorOptions.h" -#include "clang/Serialization/ASTReader.h" +#include "clang/Sema/CodeCompleteOptions.h" #include "clang/Serialization/ModuleFileExtension.h" +#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/CachedHashString.h" #include "llvm/ADT/Hashing.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" +#include "llvm/ADT/Twine.h" #include "llvm/Linker/Linker.h" +#include "llvm/MC/MCTargetOptions.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" +#include "llvm/Option/OptSpecifier.h" #include "llvm/Option/OptTable.h" #include "llvm/Option/Option.h" #include "llvm/ProfileData/InstrProfReader.h" #include "llvm/Support/CodeGen.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ErrorOr.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" +#include "llvm/Support/Regex.h" +#include "llvm/Support/VersionTuple.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetOptions.h" -#include "llvm/Support/ScopedPrinter.h" +#include <algorithm> #include <atomic> +#include <cassert> +#include <cstddef> +#include <cstring> #include <memory> -#include <sys/stat.h> -#include <system_error> +#include <string> +#include <tuple> +#include <utility> +#include <vector> + using namespace clang; +using namespace driver; +using namespace options; +using namespace llvm::opt; //===----------------------------------------------------------------------===// // Initialization. //===----------------------------------------------------------------------===// CompilerInvocationBase::CompilerInvocationBase() - : LangOpts(new LangOptions()), TargetOpts(new TargetOptions()), - DiagnosticOpts(new DiagnosticOptions()), - HeaderSearchOpts(new HeaderSearchOptions()), - PreprocessorOpts(new PreprocessorOptions()) {} + : LangOpts(new LangOptions()), TargetOpts(new TargetOptions()), + DiagnosticOpts(new DiagnosticOptions()), + HeaderSearchOpts(new HeaderSearchOptions()), + PreprocessorOpts(new PreprocessorOptions()) {} CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &X) : LangOpts(new LangOptions(*X.getLangOpts())), @@ -66,18 +111,12 @@ CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &X) HeaderSearchOpts(new HeaderSearchOptions(X.getHeaderSearchOpts())), PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())) {} -CompilerInvocationBase::~CompilerInvocationBase() {} +CompilerInvocationBase::~CompilerInvocationBase() = default; //===----------------------------------------------------------------------===// // Deserialization (from args) //===----------------------------------------------------------------------===// -using namespace clang::driver; -using namespace clang::driver::options; -using namespace llvm::opt; - -// - static unsigned getOptimizationLevel(ArgList &Args, InputKind IK, DiagnosticsEngine &Diags) { unsigned DefaultOpt = 0; @@ -91,7 +130,7 @@ static unsigned getOptimizationLevel(ArgList &Args, InputKind IK, if (A->getOption().matches(options::OPT_Ofast)) return 3; - assert (A->getOption().matches(options::OPT_O)); + assert(A->getOption().matches(options::OPT_O)); StringRef S(A->getValue()); if (S == "s" || S == "z" || S.empty()) @@ -125,7 +164,7 @@ static unsigned getOptimizationLevelSize(ArgList &Args) { static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group, OptSpecifier GroupWithValue, std::vector<std::string> &Diagnostics) { - for (Arg *A : Args.filtered(Group)) { + for (auto *A : Args.filtered(Group)) { if (A->getOption().getKind() == Option::FlagClass) { // The argument is a pure flag (such as OPT_Wall or OPT_Wdeprecated). Add // its name (minus the "W" or "R" at the beginning) to the warning list. @@ -135,7 +174,7 @@ static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group, Diagnostics.push_back(A->getOption().getName().drop_front(1).rtrim("=-")); } else { // Otherwise, add its value (for OPT_W_Joined and similar). - for (const char *Arg : A->getValues()) + for (const auto *Arg : A->getValues()) Diagnostics.emplace_back(Arg); } } @@ -157,7 +196,6 @@ static void getAllNoBuiltinFuncValues(ArgList &Args, static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags) { - using namespace options; bool Success = true; if (Arg *A = Args.getLastArg(OPT_analyzer_store)) { StringRef Name = A->getValue(); @@ -273,31 +311,31 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, StringRef checkerList = A->getValue(); SmallVector<StringRef, 4> checkers; checkerList.split(checkers, ","); - for (StringRef checker : checkers) + for (auto checker : checkers) Opts.CheckersControlList.emplace_back(checker, enable); } // Go through the analyzer configuration options. - for (const Arg *A : Args.filtered(OPT_analyzer_config)) { + for (const auto *A : Args.filtered(OPT_analyzer_config)) { A->claim(); // We can have a list of comma separated config names, e.g: // '-analyzer-config key1=val1,key2=val2' StringRef configList = A->getValue(); SmallVector<StringRef, 4> configVals; configList.split(configVals, ","); - for (unsigned i = 0, e = configVals.size(); i != e; ++i) { + for (const auto &configVal : configVals) { StringRef key, val; - std::tie(key, val) = configVals[i].split("="); + std::tie(key, val) = configVal.split("="); if (val.empty()) { Diags.Report(SourceLocation(), - diag::err_analyzer_config_no_value) << configVals[i]; + diag::err_analyzer_config_no_value) << configVal; Success = false; break; } if (val.find('=') != StringRef::npos) { Diags.Report(SourceLocation(), diag::err_analyzer_config_multiple_values) - << configVals[i]; + << configVal; Success = false; break; } @@ -305,6 +343,14 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, } } + llvm::raw_string_ostream os(Opts.FullCompilerInvocation); + for (unsigned i = 0; i < Args.getNumInputArgStrings(); ++i) { + if (i != 0) + os << " "; + os << Args.getArgString(i); + } + os.flush(); + return Success; } @@ -330,18 +376,26 @@ static StringRef getCodeModel(ArgList &Args, DiagnosticsEngine &Diags) { return "default"; } -static StringRef getRelocModel(ArgList &Args, DiagnosticsEngine &Diags) { +static llvm::Reloc::Model getRelocModel(ArgList &Args, + DiagnosticsEngine &Diags) { if (Arg *A = Args.getLastArg(OPT_mrelocation_model)) { StringRef Value = A->getValue(); - if (Value == "static" || Value == "pic" || Value == "ropi" || - Value == "rwpi" || Value == "ropi-rwpi" || Value == "dynamic-no-pic") - return Value; + auto RM = llvm::StringSwitch<llvm::Optional<llvm::Reloc::Model>>(Value) + .Case("static", llvm::Reloc::Static) + .Case("pic", llvm::Reloc::PIC_) + .Case("ropi", llvm::Reloc::ROPI) + .Case("rwpi", llvm::Reloc::RWPI) + .Case("ropi-rwpi", llvm::Reloc::ROPI_RWPI) + .Case("dynamic-no-pic", llvm::Reloc::DynamicNoPIC) + .Default(None); + if (RM.hasValue()) + return *RM; Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Value; } - return "pic"; + return llvm::Reloc::PIC_; } -/// \brief Create a new Regex instance out of the string value in \p RpassArg. +/// Create a new Regex instance out of the string value in \p RpassArg. /// It returns a pointer to the newly generated Regex instance. static std::shared_ptr<llvm::Regex> GenerateOptimizationRemarkRegex(DiagnosticsEngine &Diags, ArgList &Args, @@ -392,6 +446,25 @@ static void parseSanitizerKinds(StringRef FlagName, } } +static void parseXRayInstrumentationBundle(StringRef FlagName, StringRef Bundle, + ArgList &Args, DiagnosticsEngine &D, + XRayInstrSet &S) { + llvm::SmallVector<StringRef, 2> BundleParts; + llvm::SplitString(Bundle, BundleParts, ","); + for (const auto B : BundleParts) { + auto Mask = parseXRayInstrValue(B); + if (Mask == XRayInstrKind::None) + if (B != "none") + D.Report(diag::err_drv_invalid_value) << FlagName << Bundle; + else + S.Mask = Mask; + else if (Mask == XRayInstrKind::All) + S.Mask = Mask; + else + S.set(Mask, true); + } +} + // Set the profile kind for fprofile-instrument. static void setPGOInstrumentor(CodeGenOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags) { @@ -409,8 +482,7 @@ static void setPGOInstrumentor(CodeGenOptions &Opts, ArgList &Args, << S; return; } - CodeGenOptions::ProfileInstrKind Instrumentor = - static_cast<CodeGenOptions::ProfileInstrKind>(I); + auto Instrumentor = static_cast<CodeGenOptions::ProfileInstrKind>(I); Opts.setProfileInstr(Instrumentor); } @@ -434,8 +506,8 @@ static void setPGOUseInstrumentor(CodeGenOptions &Opts, static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, DiagnosticsEngine &Diags, - const TargetOptions &TargetOpts) { - using namespace options; + const TargetOptions &TargetOpts, + const FrontendOptions &FrontendOpts) { bool Success = true; llvm::Triple Triple = llvm::Triple(TargetOpts.Triple); @@ -474,7 +546,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.ExperimentalNewPassManager = Args.hasFlag( OPT_fexperimental_new_pass_manager, OPT_fno_experimental_new_pass_manager, - /* Default */ false); + /* Default */ ENABLE_EXPERIMENTAL_NEW_PASS_MANAGER); Opts.DebugPassManager = Args.hasFlag(OPT_fdebug_pass_manager, OPT_fno_debug_pass_manager, @@ -529,6 +601,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.DebugTypeExtRefs = Args.hasArg(OPT_dwarf_ext_refs); Opts.DebugExplicitImport = Args.hasArg(OPT_dwarf_explicit_import); Opts.DebugFwdTemplateParams = Args.hasArg(OPT_debug_forward_template_params); + Opts.EmbedSource = Args.hasArg(OPT_gembed_source); for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) Opts.DebugPrefixMap.insert(StringRef(Arg).split('=')); @@ -552,7 +625,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Args.hasFlag(OPT_ffine_grained_bitfield_accesses, OPT_fno_fine_grained_bitfield_accesses, false); Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags); - Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants); + Opts.MergeAllConstants = Args.hasArg(OPT_fmerge_all_constants); Opts.NoCommon = Args.hasArg(OPT_fno_common); Opts.NoImplicitFloat = Args.hasArg(OPT_no_implicit_float); Opts.OptimizeSize = getOptimizationLevelSize(Args); @@ -580,33 +653,6 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, if (!Opts.ProfileInstrumentUsePath.empty()) setPGOUseInstrumentor(Opts, Opts.ProfileInstrumentUsePath); - if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) { - Opts.setClangABICompat(CodeGenOptions::ClangABI::Latest); - - StringRef Ver = A->getValue(); - std::pair<StringRef, StringRef> VerParts = Ver.split('.'); - unsigned Major, Minor = 0; - - // Check the version number is valid: either 3.x (0 <= x <= 9) or - // y or y.0 (4 <= y <= current version). - if (!VerParts.first.startswith("0") && - !VerParts.first.getAsInteger(10, Major) && - 3 <= Major && Major <= CLANG_VERSION_MAJOR && - (Major == 3 ? VerParts.second.size() == 1 && - !VerParts.second.getAsInteger(10, Minor) - : VerParts.first.size() == Ver.size() || - VerParts.second == "0")) { - // Got a valid version number. - if (Major == 3 && Minor <= 8) - Opts.setClangABICompat(CodeGenOptions::ClangABI::Ver3_8); - else if (Major <= 4) - Opts.setClangABICompat(CodeGenOptions::ClangABI::Ver4); - } else if (Ver != "latest") { - Diags.Report(diag::err_drv_invalid_value) - << A->getAsString(Args) << A->getValue(); - } - } - Opts.CoverageMapping = Args.hasFlag(OPT_fcoverage_mapping, OPT_fno_coverage_mapping, false); Opts.DumpCoverageMapping = Args.hasArg(OPT_dump_coverage_mapping); @@ -615,6 +661,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new); Opts.ObjCAutoRefCountExceptions = Args.hasArg(OPT_fobjc_arc_exceptions); Opts.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit); + Opts.RegisterGlobalDtorsWithAtExit = + Args.hasArg(OPT_fregister_global_dtors_with_atexit); Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases); Opts.CodeModel = getCodeModel(Args, Diags); Opts.DebugPass = Args.getLastArgValue(OPT_mdebug_pass); @@ -623,6 +671,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.DisableFree = Args.hasArg(OPT_disable_free); Opts.DiscardValueNames = Args.hasArg(OPT_discard_value_names); Opts.DisableTailCalls = Args.hasArg(OPT_mdisable_tail_calls); + Opts.NoEscapingBlockTailCalls = + Args.hasArg(OPT_fno_escaping_block_tail_calls); Opts.FloatABI = Args.getLastArgValue(OPT_mfloat_abi); Opts.LessPreciseFPMAD = Args.hasArg(OPT_cl_mad_enable) || Args.hasArg(OPT_cl_unsafe_math_optimizations) || @@ -640,14 +690,20 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Args.hasArg(OPT_cl_unsafe_math_optimizations) || Args.hasArg(OPT_cl_fast_relaxed_math)); Opts.Reassociate = Args.hasArg(OPT_mreassociate); - Opts.FlushDenorm = Args.hasArg(OPT_cl_denorms_are_zero); + Opts.FlushDenorm = Args.hasArg(OPT_cl_denorms_are_zero) || + (Args.hasArg(OPT_fcuda_is_device) && + Args.hasArg(OPT_fcuda_flush_denormals_to_zero)); Opts.CorrectlyRoundedDivSqrt = Args.hasArg(OPT_cl_fp32_correctly_rounded_divide_sqrt); + Opts.UniformWGSize = + Args.hasArg(OPT_cl_uniform_work_group_size); Opts.Reciprocals = Args.getAllArgValues(OPT_mrecip_EQ); Opts.ReciprocalMath = Args.hasArg(OPT_freciprocal_math); Opts.NoTrappingMath = Args.hasArg(OPT_fno_trapping_math); + Opts.StrictFloatCastOverflow = + !Args.hasArg(OPT_fno_strict_float_cast_overflow); + Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss); - Opts.BackendOptions = Args.getAllArgValues(OPT_backend_option); Opts.NumRegisterParameters = getLastArgIntValue(Args, OPT_mregparm, 0, Diags); Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack); Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings); @@ -665,6 +721,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.StrictEnums = Args.hasArg(OPT_fstrict_enums); Opts.StrictReturn = !Args.hasArg(OPT_fno_strict_return); Opts.StrictVTablePointers = Args.hasArg(OPT_fstrict_vtable_pointers); + Opts.ForceEmitVTables = Args.hasArg(OPT_fforce_emit_vtables); Opts.UnsafeFPMath = Args.hasArg(OPT_menable_unsafe_fp_math) || Args.hasArg(OPT_cl_unsafe_math_optimizations) || Args.hasArg(OPT_cl_fast_relaxed_math); @@ -682,6 +739,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, OPT_fno_function_sections, false); Opts.DataSections = Args.hasFlag(OPT_fdata_sections, OPT_fno_data_sections, false); + Opts.StackSizeSection = + Args.hasFlag(OPT_fstack_size_section, OPT_fno_stack_size_section, false); Opts.UniqueSectionNames = Args.hasFlag(OPT_funique_section_names, OPT_fno_unique_section_names, true); @@ -689,14 +748,16 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.NoUseJumpTables = Args.hasArg(OPT_fno_jump_tables); + Opts.NullPointerIsValid = Args.hasArg(OPT_fno_delete_null_pointer_checks); + Opts.ProfileSampleAccurate = Args.hasArg(OPT_fprofile_sample_accurate); Opts.PrepareForLTO = Args.hasArg(OPT_flto, OPT_flto_EQ); - Opts.EmitSummaryIndex = false; + Opts.PrepareForThinLTO = false; if (Arg *A = Args.getLastArg(OPT_flto_EQ)) { StringRef S = A->getValue(); if (S == "thin") - Opts.EmitSummaryIndex = true; + Opts.PrepareForThinLTO = true; else if (S != "full") Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << S; } @@ -707,6 +768,12 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, << A->getAsString(Args) << "-x ir"; Opts.ThinLTOIndexFile = Args.getLastArgValue(OPT_fthinlto_index_EQ); } + if (Arg *A = Args.getLastArg(OPT_save_temps_EQ)) + Opts.SaveTempsFilePrefix = + llvm::StringSwitch<std::string>(A->getValue()) + .Case("obj", FrontendOpts.OutputFile) + .Default(llvm::sys::path::filename(FrontendOpts.OutputFile).str()); + Opts.ThinLinkBitcodeFile = Args.getLastArgValue(OPT_fthin_link_bitcode_EQ); Opts.MSVolatile = Args.hasArg(OPT_fms_volatile); @@ -719,6 +786,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name); Opts.VerifyModule = !Args.hasArg(OPT_disable_llvm_verifier); + Opts.ControlFlowGuard = Args.hasArg(OPT_cfguard); + Opts.DisableGCov = Args.hasArg(OPT_test_coverage); Opts.EmitGcovArcs = Args.hasArg(OPT_femit_coverage_data); Opts.EmitGcovNotes = Args.hasArg(OPT_femit_coverage_notes); @@ -741,7 +810,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, } } } - // Handle -fembed-bitcode option. + // Handle -fembed-bitcode option. if (Arg *A = Args.getLastArg(OPT_fembed_bitcode_EQ)) { StringRef Name = A->getValue(); unsigned Model = llvm::StringSwitch<unsigned>(Name) @@ -787,15 +856,44 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Args.hasArg(OPT_finstrument_functions_after_inlining); Opts.InstrumentFunctionEntryBare = Args.hasArg(OPT_finstrument_function_entry_bare); - Opts.XRayInstrumentFunctions = Args.hasArg(OPT_fxray_instrument); + + Opts.XRayInstrumentFunctions = + Args.hasArg(OPT_fxray_instrument); Opts.XRayAlwaysEmitCustomEvents = Args.hasArg(OPT_fxray_always_emit_customevents); + Opts.XRayAlwaysEmitTypedEvents = + Args.hasArg(OPT_fxray_always_emit_typedevents); Opts.XRayInstructionThreshold = getLastArgIntValue(Args, OPT_fxray_instruction_threshold_EQ, 200, Diags); + + auto XRayInstrBundles = + Args.getAllArgValues(OPT_fxray_instrumentation_bundle); + if (XRayInstrBundles.empty()) + Opts.XRayInstrumentationBundle.Mask = XRayInstrKind::All; + else + for (const auto &A : XRayInstrBundles) + parseXRayInstrumentationBundle("-fxray-instrumentation-bundle=", A, Args, + Diags, Opts.XRayInstrumentationBundle); + Opts.InstrumentForProfiling = Args.hasArg(OPT_pg); Opts.CallFEntry = Args.hasArg(OPT_mfentry); Opts.EmitOpenCLArgMetadata = Args.hasArg(OPT_cl_kernel_arg_info); + if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) { + StringRef Name = A->getValue(); + if (Name == "full") { + Opts.CFProtectionReturn = 1; + Opts.CFProtectionBranch = 1; + } else if (Name == "return") + Opts.CFProtectionReturn = 1; + else if (Name == "branch") + Opts.CFProtectionBranch = 1; + else if (Name != "none") { + Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; + Success = false; + } + } + if (const Arg *A = Args.getLastArg(OPT_compress_debug_sections, OPT_compress_debug_sections_EQ)) { if (A->getOption().getID() == OPT_compress_debug_sections) { @@ -813,7 +911,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations); Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir); - for (auto A : Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_cuda_bitcode)) { + for (auto *A : + Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_cuda_bitcode)) { CodeGenOptions::BitcodeFileToLink F; F.Filename = A->getValue(); if (A->getOption().matches(OPT_mlink_cuda_bitcode)) { @@ -855,6 +954,13 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.SanitizeCfiICallGeneralizePointers = Args.hasArg(OPT_fsanitize_cfi_icall_generalize_pointers); Opts.SanitizeStats = Args.hasArg(OPT_fsanitize_stats); + if (Arg *A = Args.getLastArg( + OPT_fsanitize_address_poison_class_member_array_new_cookie, + OPT_fno_sanitize_address_poison_class_member_array_new_cookie)) { + Opts.SanitizeAddressPoisonClassMemberArrayNewCookie = + A->getOption().getID() == + OPT_fsanitize_address_poison_class_member_array_new_cookie; + } if (Arg *A = Args.getLastArg(OPT_fsanitize_address_use_after_scope, OPT_fno_sanitize_address_use_after_scope)) { Opts.SanitizeAddressUseAfterScope = @@ -879,6 +985,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.StackProbeSize = StackProbeSize; } + Opts.NoStackArgProbe = Args.hasArg(OPT_mno_stack_arg_probe); + if (Arg *A = Args.getLastArg(OPT_fobjc_dispatch_method_EQ)) { StringRef Name = A->getValue(); unsigned Method = llvm::StringSwitch<unsigned>(Name) @@ -895,8 +1003,12 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, } } - Opts.EmulatedTLS = - Args.hasFlag(OPT_femulated_tls, OPT_fno_emulated_tls, false); + if (Args.getLastArg(OPT_femulated_tls) || + Args.getLastArg(OPT_fno_emulated_tls)) { + Opts.ExplicitEmulatedTLS = true; + Opts.EmulatedTLS = + Args.hasFlag(OPT_femulated_tls, OPT_fno_emulated_tls, false); + } if (Arg *A = Args.getLastArg(OPT_ftlsmodel_EQ)) { StringRef Name = A->getValue(); @@ -967,7 +1079,9 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, bool UsingProfile = UsingSampleProfile || (Opts.getProfileUse() != CodeGenOptions::ProfileNone); - if (Opts.DiagnosticsWithHotness && !UsingProfile) + if (Opts.DiagnosticsWithHotness && !UsingProfile && + // An IR file will contain PGO as metadata + IK.getLanguage() != InputKind::LLVM_IR) Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo) << "-fdiagnostics-show-hotness"; @@ -999,20 +1113,23 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Args.getAllArgValues(OPT_fsanitize_trap_EQ), Diags, Opts.SanitizeTrap); - Opts.CudaGpuBinaryFileNames = - Args.getAllArgValues(OPT_fcuda_include_gpubinary); + Opts.CudaGpuBinaryFileName = + Args.getLastArgValue(OPT_fcuda_include_gpubinary); Opts.Backchain = Args.hasArg(OPT_mbackchain); Opts.EmitCheckPathComponentsToStrip = getLastArgIntValue( Args, OPT_fsanitize_undefined_strip_path_components_EQ, 0, Diags); + Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true); + + Opts.Addrsig = Args.hasArg(OPT_faddrsig); + return Success; } static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts, ArgList &Args) { - using namespace options; Opts.OutputFile = Args.getLastArgValue(OPT_dependency_file); Opts.Targets = Args.getAllArgValues(OPT_MT); Opts.IncludeSystemHeaders = Args.hasArg(OPT_sys_header_deps); @@ -1021,7 +1138,17 @@ 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); + if (Args.hasArg(OPT_show_includes)) { + // Writing both /showIncludes and preprocessor output to stdout + // would produce interleaved output, so use stderr for /showIncludes. + // This behaves the same as cl.exe, when /E, /EP or /P are passed. + if (Args.hasArg(options::OPT_E) || Args.hasArg(options::OPT_P)) + Opts.ShowIncludesDest = ShowIncludesDestination::Stderr; + else + Opts.ShowIncludesDest = ShowIncludesDestination::Stdout; + } else { + Opts.ShowIncludesDest = ShowIncludesDestination::None; + } Opts.DOTOutputFile = Args.getLastArgValue(OPT_dependency_dot); Opts.ModuleDependencyOutputDir = Args.getLastArgValue(OPT_module_dependency_dir); @@ -1032,7 +1159,7 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts, // we let make / ninja to know about this implicit dependency. Opts.ExtraDeps = Args.getAllArgValues(OPT_fdepfile_entry); // Only the -fmodule-file=<file> form. - for (const Arg *A : Args.filtered(OPT_fmodule_file)) { + for (const auto *A : Args.filtered(OPT_fmodule_file)) { StringRef Val = A->getValue(); if (Val.find('=') == StringRef::npos) Opts.ExtraDeps.push_back(Val); @@ -1049,7 +1176,7 @@ static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) { Colors_Off, Colors_Auto } ShowColors = DefaultColor ? Colors_Auto : Colors_Off; - for (Arg *A : Args) { + for (auto *A : Args) { const Option &O = A->getOption(); if (O.matches(options::OPT_fcolor_diagnostics) || O.matches(options::OPT_fdiagnostics_color)) { @@ -1095,7 +1222,6 @@ static bool checkVerifyPrefixes(const std::vector<std::string> &VerifyPrefixes, bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, DiagnosticsEngine *Diags, bool DefaultDiagColor, bool DefaultShowOpt) { - using namespace options; bool Success = true; Opts.DiagnosticLogFile = Args.getLastArgValue(OPT_diagnostic_log_file); @@ -1190,7 +1316,7 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, Success = false; } else - std::sort(Opts.VerifyPrefixes.begin(), Opts.VerifyPrefixes.end()); + llvm::sort(Opts.VerifyPrefixes.begin(), Opts.VerifyPrefixes.end()); DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None; Success &= parseDiagnosticLevelMask("-verify-ignore-unexpected=", Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ), @@ -1262,7 +1388,6 @@ static bool parseTestModuleFileExtensionArg(StringRef Arg, static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags, bool &IsHeaderFile) { - using namespace options; Opts.ProgramAction = frontend::ParseSyntaxOnly; if (const Arg *A = Args.getLastArg(OPT_Action_Group)) { switch (A->getOption().getID()) { @@ -1278,6 +1403,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::ASTPrint; break; case OPT_ast_view: Opts.ProgramAction = frontend::ASTView; break; + case OPT_compiler_options_dump: + Opts.ProgramAction = frontend::DumpCompilerOptions; break; case OPT_dump_raw_tokens: Opts.ProgramAction = frontend::DumpRawTokens; break; case OPT_dump_tokens: @@ -1323,6 +1450,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::PrintPreamble; break; case OPT_E: Opts.ProgramAction = frontend::PrintPreprocessedInput; break; + case OPT_templight_dump: + Opts.ProgramAction = frontend::TemplightDump; break; case OPT_rewrite_macros: Opts.ProgramAction = frontend::RewriteMacros; break; case OPT_rewrite_objc: @@ -1344,7 +1473,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ActionName = A->getValue(); } Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin); - for (const Arg *AA : Args.filtered(OPT_plugin_arg)) + for (const auto *AA : Args.filtered(OPT_plugin_arg)) Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1)); for (const std::string &Arg : @@ -1397,7 +1526,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.GenerateGlobalModuleIndex = Opts.UseGlobalModuleIndex; Opts.ModuleMapFiles = Args.getAllArgValues(OPT_fmodule_map_file); // Only the -fmodule-file=<file> form. - for (const Arg *A : Args.filtered(OPT_fmodule_file)) { + for (const auto *A : Args.filtered(OPT_fmodule_file)) { StringRef Val = A->getValue(); if (Val.find('=') == StringRef::npos) Opts.ModuleFiles.push_back(Val); @@ -1416,12 +1545,13 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, = !Args.hasArg(OPT_no_code_completion_ns_level_decls); Opts.CodeCompleteOpts.IncludeBriefComments = Args.hasArg(OPT_code_completion_brief_comments); + Opts.CodeCompleteOpts.IncludeFixIts + = Args.hasArg(OPT_code_completion_with_fixits); Opts.OverrideRecordLayoutsFile = Args.getLastArgValue(OPT_foverride_record_layout_EQ); Opts.AuxTriple = llvm::Triple::normalize(Args.getLastArgValue(OPT_aux_triple)); - Opts.FindPchSource = Args.getLastArgValue(OPT_find_pch_source_EQ); Opts.StatsFile = Args.getLastArgValue(OPT_stats_file); if (const Arg *A = Args.getLastArg(OPT_arcmt_check, @@ -1502,6 +1632,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, .Case("c", InputKind::C) .Case("cl", InputKind::OpenCL) .Case("cuda", InputKind::CUDA) + .Case("hip", InputKind::HIP) .Case("c++", InputKind::CXX) .Case("objective-c", InputKind::ObjC) .Case("objective-c++", InputKind::ObjCXX) @@ -1585,7 +1716,6 @@ std::string CompilerInvocation::GetResourcesPath(const char *Argv0, static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, const std::string &WorkingDir) { - using namespace options; Opts.Sysroot = Args.getLastArgValue(OPT_isysroot, "/"); Opts.Verbose = Args.hasArg(OPT_v); Opts.UseBuiltinIncludes = !Args.hasArg(OPT_nobuiltininc); @@ -1608,12 +1738,12 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, Opts.ModuleUserBuildPath = Args.getLastArgValue(OPT_fmodules_user_build_path); // Only the -fmodule-file=<name>=<file> form. - for (const Arg *A : Args.filtered(OPT_fmodule_file)) { + for (const auto *A : Args.filtered(OPT_fmodule_file)) { StringRef Val = A->getValue(); if (Val.find('=') != StringRef::npos) Opts.PrebuiltModuleFiles.insert(Val.split('=')); } - for (const Arg *A : Args.filtered(OPT_fprebuilt_module_path)) + for (const auto *A : Args.filtered(OPT_fprebuilt_module_path)) Opts.AddPrebuiltModulePath(A->getValue()); Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash); Opts.ModulesHashContent = Args.hasArg(OPT_fmodules_hash_content); @@ -1634,7 +1764,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, if (const Arg *A = Args.getLastArg(OPT_fmodule_format_EQ)) Opts.ModuleFormat = A->getValue(); - for (const Arg *A : Args.filtered(OPT_fmodules_ignore_macro)) { + for (const auto *A : Args.filtered(OPT_fmodules_ignore_macro)) { StringRef MacroDef = A->getValue(); Opts.ModulesIgnoreMacros.insert( llvm::CachedHashString(MacroDef.split('=').first)); @@ -1644,7 +1774,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, bool IsIndexHeaderMap = false; bool IsSysrootSpecified = Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot); - for (const Arg *A : Args.filtered(OPT_I, OPT_F, OPT_index_header_map)) { + for (const auto *A : Args.filtered(OPT_I, OPT_F, OPT_index_header_map)) { if (A->getOption().matches(OPT_index_header_map)) { // -index-header-map applies to the next -I or -F. IsIndexHeaderMap = true; @@ -1671,7 +1801,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, // Add -iprefix/-iwithprefix/-iwithprefixbefore options. StringRef Prefix = ""; // FIXME: This isn't the correct default prefix. - for (const Arg *A : + for (const auto *A : Args.filtered(OPT_iprefix, OPT_iwithprefix, OPT_iwithprefixbefore)) { if (A->getOption().matches(OPT_iprefix)) Prefix = A->getValue(); @@ -1681,31 +1811,31 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, Opts.AddPath(Prefix.str() + A->getValue(), frontend::Angled, false, true); } - for (const Arg *A : Args.filtered(OPT_idirafter)) + for (const auto *A : Args.filtered(OPT_idirafter)) Opts.AddPath(A->getValue(), frontend::After, false, true); - for (const Arg *A : Args.filtered(OPT_iquote)) + for (const auto *A : Args.filtered(OPT_iquote)) Opts.AddPath(A->getValue(), frontend::Quoted, false, true); - for (const Arg *A : Args.filtered(OPT_isystem, OPT_iwithsysroot)) + for (const auto *A : Args.filtered(OPT_isystem, OPT_iwithsysroot)) Opts.AddPath(A->getValue(), frontend::System, false, !A->getOption().matches(OPT_iwithsysroot)); - for (const Arg *A : Args.filtered(OPT_iframework)) + for (const auto *A : Args.filtered(OPT_iframework)) Opts.AddPath(A->getValue(), frontend::System, true, true); - for (const Arg *A : Args.filtered(OPT_iframeworkwithsysroot)) + for (const auto *A : Args.filtered(OPT_iframeworkwithsysroot)) Opts.AddPath(A->getValue(), frontend::System, /*IsFramework=*/true, /*IgnoreSysRoot=*/false); // Add the paths for the various language specific isystem flags. - for (const Arg *A : Args.filtered(OPT_c_isystem)) + for (const auto *A : Args.filtered(OPT_c_isystem)) Opts.AddPath(A->getValue(), frontend::CSystem, false, true); - for (const Arg *A : Args.filtered(OPT_cxx_isystem)) + for (const auto *A : Args.filtered(OPT_cxx_isystem)) Opts.AddPath(A->getValue(), frontend::CXXSystem, false, true); - for (const Arg *A : Args.filtered(OPT_objc_isystem)) + for (const auto *A : Args.filtered(OPT_objc_isystem)) Opts.AddPath(A->getValue(), frontend::ObjCSystem, false,true); - for (const Arg *A : Args.filtered(OPT_objcxx_isystem)) + for (const auto *A : Args.filtered(OPT_objcxx_isystem)) Opts.AddPath(A->getValue(), frontend::ObjCXXSystem, false, true); // Add the internal paths from a driver that detects standard include paths. - for (const Arg *A : + for (const auto *A : Args.filtered(OPT_internal_isystem, OPT_internal_externc_isystem)) { frontend::IncludeDirGroup Group = frontend::System; if (A->getOption().matches(OPT_internal_externc_isystem)) @@ -1714,12 +1844,12 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, } // Add the path prefixes which are implicitly treated as being system headers. - for (const Arg *A : + for (const auto *A : Args.filtered(OPT_system_header_prefix, OPT_no_system_header_prefix)) Opts.AddSystemHeaderPrefix( A->getValue(), A->getOption().matches(OPT_system_header_prefix)); - for (const Arg *A : Args.filtered(OPT_ivfsoverlay)) + for (const auto *A : Args.filtered(OPT_ivfsoverlay)) Opts.AddVFSOverlayFile(A->getValue()); } @@ -1754,22 +1884,37 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, break; case InputKind::Asm: case InputKind::C: +#if defined(CLANG_DEFAULT_STD_C) + LangStd = CLANG_DEFAULT_STD_C; +#else // The PS4 uses C99 as the default C standard. if (T.isPS4()) LangStd = LangStandard::lang_gnu99; else LangStd = LangStandard::lang_gnu11; +#endif break; case InputKind::ObjC: +#if defined(CLANG_DEFAULT_STD_C) + LangStd = CLANG_DEFAULT_STD_C; +#else LangStd = LangStandard::lang_gnu11; +#endif break; case InputKind::CXX: case InputKind::ObjCXX: +#if defined(CLANG_DEFAULT_STD_CXX) + LangStd = CLANG_DEFAULT_STD_CXX; +#else LangStd = LangStandard::lang_gnucxx14; +#endif break; case InputKind::RenderScript: LangStd = LangStandard::lang_c99; break; + case InputKind::HIP: + LangStd = LangStandard::lang_hip; + break; } } @@ -1799,6 +1944,8 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, Opts.OpenCLVersion = 120; else if (LangStd == LangStandard::lang_opencl20) Opts.OpenCLVersion = 200; + else if (LangStd == LangStandard::lang_openclcpp) + Opts.OpenCLCPlusPlusVersion = 100; // OpenCL has some additional defaults. if (Opts.OpenCL) { @@ -1808,13 +1955,15 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, Opts.setDefaultFPContractMode(LangOptions::FPC_On); Opts.NativeHalfType = 1; Opts.NativeHalfArgsAndReturns = 1; + Opts.OpenCLCPlusPlus = Opts.CPlusPlus; // Include default header file for OpenCL. if (Opts.IncludeDefaultHeader) { PPOpts.Includes.push_back("opencl-c.h"); } } - Opts.CUDA = IK.getLanguage() == InputKind::CUDA; + Opts.HIP = IK.getLanguage() == InputKind::HIP; + Opts.CUDA = IK.getLanguage() == InputKind::CUDA || Opts.HIP; if (Opts.CUDA) // Set default FP_CONTRACT to FAST. Opts.setDefaultFPContractMode(LangOptions::FPC_Fast); @@ -1885,6 +2034,10 @@ static bool IsInputCompatibleWithStandard(InputKind IK, return S.getLanguage() == InputKind::CUDA || S.getLanguage() == InputKind::CXX; + case InputKind::HIP: + return S.getLanguage() == InputKind::CXX || + S.getLanguage() == InputKind::HIP; + case InputKind::Asm: // Accept (and ignore) all -std= values. // FIXME: The -std= value is not ignored; it affects the tokenization @@ -1912,6 +2065,8 @@ static const StringRef GetInputKindName(InputKind IK) { return "CUDA"; case InputKind::RenderScript: return "RenderScript"; + case InputKind::HIP: + return "HIP"; case InputKind::Asm: return "Asm"; @@ -1975,6 +2130,12 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, } } + if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) { + StringRef Name = A->getValue(); + if (Name == "full" || Name == "branch") { + Opts.CFProtectionBranch = 1; + } + } // -cl-std only applies for OpenCL language standards. // Override the -std option in this case. if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) { @@ -1984,6 +2145,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, .Cases("cl1.1", "CL1.1", LangStandard::lang_opencl11) .Cases("cl1.2", "CL1.2", LangStandard::lang_opencl12) .Cases("cl2.0", "CL2.0", LangStandard::lang_opencl20) + .Case("c++", LangStandard::lang_openclcpp) .Default(LangStandard::lang_unspecified); if (OpenCLLangStd == LangStandard::lang_unspecified) { @@ -2004,11 +2166,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, // this option was added for compatibility with OpenCL 1.0. if (Args.getLastArg(OPT_cl_strict_aliasing) && Opts.OpenCLVersion > 100) { - std::string VerSpec = llvm::to_string(Opts.OpenCLVersion / 100) + - std::string(".") + - llvm::to_string((Opts.OpenCLVersion % 100) / 10); Diags.Report(diag::warn_option_invalid_ocl_version) - << VerSpec << Args.getLastArg(OPT_cl_strict_aliasing)->getAsString(Args); + << Opts.getOpenCLVersionTuple().getAsString() + << Args.getLastArg(OPT_cl_strict_aliasing)->getAsString(Args); } // We abuse '-f[no-]gnu-keywords' to force overriding all GNU-extension @@ -2019,6 +2179,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.GNUKeywords = Args.hasFlag(OPT_fgnu_keywords, OPT_fno_gnu_keywords, Opts.GNUKeywords); + Opts.Digraphs = Args.hasFlag(OPT_fdigraphs, OPT_fno_digraphs, Opts.Digraphs); + if (Args.hasArg(OPT_fno_operator_names)) Opts.CXXOperatorNames = 0; @@ -2031,12 +2193,11 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, if (Args.hasArg(OPT_fno_cuda_host_device_constexpr)) Opts.CUDAHostDeviceConstexpr = 0; - if (Opts.CUDAIsDevice && Args.hasArg(OPT_fcuda_flush_denormals_to_zero)) - Opts.CUDADeviceFlushDenormalsToZero = 1; - if (Opts.CUDAIsDevice && Args.hasArg(OPT_fcuda_approx_transcendentals)) Opts.CUDADeviceApproxTranscendentals = 1; + Opts.CUDARelocatableDeviceCode = Args.hasArg(OPT_fcuda_rdc); + if (Opts.ObjC1) { if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) { StringRef value = arg->getValue(); @@ -2177,12 +2338,27 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.ObjCExceptions = Args.hasArg(OPT_fobjc_exceptions); Opts.CXXExceptions = Args.hasArg(OPT_fcxx_exceptions); + // -ffixed-point + Opts.FixedPoint = + Args.hasFlag(OPT_ffixed_point, OPT_fno_fixed_point, /*Default=*/false) && + !Opts.CPlusPlus; + Opts.PaddingOnUnsignedFixedPoint = + Args.hasFlag(OPT_fpadding_on_unsigned_fixed_point, + OPT_fno_padding_on_unsigned_fixed_point, + /*Default=*/false) && + Opts.FixedPoint; + // Handle exception personalities Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions, options::OPT_fseh_exceptions, options::OPT_fdwarf_exceptions); if (A) { const Option &Opt = A->getOption(); + llvm::Triple T(TargetOpts.Triple); + if (T.isWindowsMSVCEnvironment()) + Diags.Report(diag::err_fe_invalid_exception_model) + << Opt.getName() << T.str(); + Opts.SjLjExceptions = Opt.matches(options::OPT_fsjlj_exceptions); Opts.SEHExceptions = Opt.matches(options::OPT_fseh_exceptions); Opts.DWARFExceptions = Opt.matches(options::OPT_fdwarf_exceptions); @@ -2194,7 +2370,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.RTTI = Opts.CPlusPlus && !Args.hasArg(OPT_fno_rtti); Opts.RTTIData = Opts.RTTI && !Args.hasArg(OPT_fno_rtti_data); Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL - && Opts.OpenCLVersion >= 200); + && Opts.OpenCLVersion == 200); Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional); Opts.CoroutinesTS = Args.hasArg(OPT_fcoroutines_ts); @@ -2219,6 +2395,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.ImplicitModules = !Args.hasArg(OPT_fno_implicit_modules); Opts.CharIsSigned = Opts.OpenCL || !Args.hasArg(OPT_fno_signed_char); Opts.WChar = Opts.CPlusPlus && !Args.hasArg(OPT_fno_wchar); + Opts.Char8 = Args.hasArg(OPT_fchar8__t); if (const Arg *A = Args.getLastArg(OPT_fwchar_type_EQ)) { Opts.WCharSize = llvm::StringSwitch<unsigned>(A->getValue()) .Case("char", 1) @@ -2297,10 +2474,11 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.DebuggerCastResultToId = Args.hasArg(OPT_fdebugger_cast_result_to_id); Opts.DebuggerObjCLiteral = Args.hasArg(OPT_fdebugger_objc_literal); Opts.ApplePragmaPack = Args.hasArg(OPT_fapple_pragma_pack); - Opts.CurrentModule = Args.getLastArgValue(OPT_fmodule_name_EQ); + Opts.ModuleName = Args.getLastArgValue(OPT_fmodule_name_EQ); + Opts.CurrentModule = Opts.ModuleName; Opts.AppExt = Args.hasArg(OPT_fapplication_extension); Opts.ModuleFeatures = Args.getAllArgValues(OPT_fmodule_feature); - std::sort(Opts.ModuleFeatures.begin(), Opts.ModuleFeatures.end()); + llvm::sort(Opts.ModuleFeatures.begin(), Opts.ModuleFeatures.end()); Opts.NativeHalfType |= Args.hasArg(OPT_fnative_half_type); Opts.NativeHalfArgsAndReturns |= Args.hasArg(OPT_fnative_half_arguments_and_returns); // Enable HalfArgsAndReturns if present in Args or if NativeHalfArgsAndReturns @@ -2407,16 +2585,25 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, // Check if -fopenmp is specified. Opts.OpenMP = Args.hasArg(options::OPT_fopenmp) ? 1 : 0; + // Check if -fopenmp-simd is specified. + bool IsSimdSpecified = + Args.hasFlag(options::OPT_fopenmp_simd, options::OPT_fno_openmp_simd, + /*Default=*/false); + Opts.OpenMPSimd = !Opts.OpenMP && IsSimdSpecified; Opts.OpenMPUseTLS = Opts.OpenMP && !Args.hasArg(options::OPT_fnoopenmp_use_tls); Opts.OpenMPIsDevice = Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_is_device); + bool IsTargetSpecified = + Opts.OpenMPIsDevice || Args.hasArg(options::OPT_fopenmp_targets_EQ); - if (Opts.OpenMP) { - int Version = - getLastArgIntValue(Args, OPT_fopenmp_version_EQ, Opts.OpenMP, Diags); - if (Version != 0) + if (Opts.OpenMP || Opts.OpenMPSimd) { + if (int Version = getLastArgIntValue( + Args, OPT_fopenmp_version_EQ, + (IsSimdSpecified || IsTargetSpecified) ? 45 : Opts.OpenMP, Diags)) Opts.OpenMP = Version; + else if (IsSimdSpecified || IsTargetSpecified) + Opts.OpenMP = 45; // Provide diagnostic when a given target is not expected to be an OpenMP // device or host. if (!Opts.OpenMPIsDevice) { @@ -2426,7 +2613,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, // Add unsupported host targets here: case llvm::Triple::nvptx: case llvm::Triple::nvptx64: - Diags.Report(clang::diag::err_drv_omp_host_target_not_supported) + Diags.Report(diag::err_drv_omp_host_target_not_supported) << TargetOpts.Triple; break; } @@ -2435,7 +2622,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, // Set the flag to prevent the implementation from emitting device exception // handling code for those requiring so. - if (Opts.OpenMPIsDevice && T.isNVPTX()) { + Opts.OpenMPHostCXXExceptions = Opts.Exceptions && Opts.CXXExceptions; + if ((Opts.OpenMPIsDevice && T.isNVPTX()) || Opts.OpenCLCPlusPlus) { Opts.Exceptions = 0; Opts.CXXExceptions = 0; } @@ -2454,7 +2642,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, TT.getArch() == llvm::Triple::nvptx64 || TT.getArch() == llvm::Triple::x86 || TT.getArch() == llvm::Triple::x86_64)) - Diags.Report(clang::diag::err_drv_invalid_omp_target) << A->getValue(i); + Diags.Report(diag::err_drv_invalid_omp_target) << A->getValue(i); else Opts.OMPTargetTriples.push_back(TT); } @@ -2465,10 +2653,14 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, if (Arg *A = Args.getLastArg(options::OPT_fopenmp_host_ir_file_path)) { Opts.OMPHostIRFile = A->getValue(); if (!llvm::sys::fs::exists(Opts.OMPHostIRFile)) - Diags.Report(clang::diag::err_drv_omp_host_ir_file_not_found) + Diags.Report(diag::err_drv_omp_host_ir_file_not_found) << Opts.OMPHostIRFile; } + // set CUDA mode for OpenMP target NVPTX if specified in options + Opts.OpenMPCUDAMode = Opts.OpenMPIsDevice && T.isNVPTX() && + Args.hasArg(options::OPT_fopenmp_cuda_mode); + // Record whether the __DEPRECATED define was requested. Opts.Deprecated = Args.hasFlag(OPT_fdeprecated_macro, OPT_fno_deprecated_macro, @@ -2543,14 +2735,55 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Args.hasFlag(OPT_fxray_always_emit_customevents, OPT_fnoxray_always_emit_customevents, false); + // -fxray-always-emit-typedevents + Opts.XRayAlwaysEmitTypedEvents = + Args.hasFlag(OPT_fxray_always_emit_typedevents, + OPT_fnoxray_always_emit_customevents, false); + // -fxray-{always,never}-instrument= filenames. Opts.XRayAlwaysInstrumentFiles = Args.getAllArgValues(OPT_fxray_always_instrument); Opts.XRayNeverInstrumentFiles = Args.getAllArgValues(OPT_fxray_never_instrument); + Opts.XRayAttrListFiles = Args.getAllArgValues(OPT_fxray_attr_list); + + // -fforce-emit-vtables + Opts.ForceEmitVTables = Args.hasArg(OPT_fforce_emit_vtables); // -fallow-editor-placeholders Opts.AllowEditorPlaceholders = Args.hasArg(OPT_fallow_editor_placeholders); + + if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) { + Opts.setClangABICompat(LangOptions::ClangABI::Latest); + + StringRef Ver = A->getValue(); + std::pair<StringRef, StringRef> VerParts = Ver.split('.'); + unsigned Major, Minor = 0; + + // Check the version number is valid: either 3.x (0 <= x <= 9) or + // y or y.0 (4 <= y <= current version). + if (!VerParts.first.startswith("0") && + !VerParts.first.getAsInteger(10, Major) && + 3 <= Major && Major <= CLANG_VERSION_MAJOR && + (Major == 3 ? VerParts.second.size() == 1 && + !VerParts.second.getAsInteger(10, Minor) + : VerParts.first.size() == Ver.size() || + VerParts.second == "0")) { + // Got a valid version number. + if (Major == 3 && Minor <= 8) + Opts.setClangABICompat(LangOptions::ClangABI::Ver3_8); + else if (Major <= 4) + Opts.setClangABICompat(LangOptions::ClangABI::Ver4); + else if (Major <= 6) + Opts.setClangABICompat(LangOptions::ClangABI::Ver6); + } else if (Ver != "latest") { + Diags.Report(diag::err_drv_invalid_value) + << A->getAsString(Args) << A->getValue(); + } + } + + Opts.CompleteMemberPointers = Args.hasArg(OPT_fcomplete_member_pointers); + Opts.BuildingPCHWithObjectFile = Args.hasArg(OPT_building_pch_with_obj); } static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { @@ -2579,9 +2812,11 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { case frontend::RewriteObjC: case frontend::RewriteTest: case frontend::RunAnalysis: + case frontend::TemplightDump: case frontend::MigrateSource: return false; + case frontend::DumpCompilerOptions: case frontend::DumpRawTokens: case frontend::DumpTokens: case frontend::InitOnly: @@ -2595,12 +2830,11 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { } static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, - FileManager &FileMgr, DiagnosticsEngine &Diags, frontend::ActionKind Action) { - using namespace options; Opts.ImplicitPCHInclude = Args.getLastArgValue(OPT_include_pch); Opts.ImplicitPTHInclude = Args.getLastArgValue(OPT_include_pth); + Opts.PCHThroughHeader = Args.getLastArgValue(OPT_pch_through_header_EQ); if (const Arg *A = Args.getLastArg(OPT_token_cache)) Opts.TokenCache = A->getValue(); else @@ -2611,7 +2845,7 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, Opts.AllowPCHWithCompilerErrors = Args.hasArg(OPT_fallow_pch_with_errors); Opts.DumpDeserializedPCHDecls = Args.hasArg(OPT_dump_deserialized_pch_decls); - for (const Arg *A : Args.filtered(OPT_error_on_deserialized_pch_decl)) + for (const auto *A : Args.filtered(OPT_error_on_deserialized_pch_decl)) Opts.DeserializedPCHDeclsToErrorOn.insert(A->getValue()); if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) { @@ -2630,8 +2864,19 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, } } + // Add the __CET__ macro if a CFProtection option is set. + if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) { + StringRef Name = A->getValue(); + if (Name == "branch") + Opts.addMacroDef("__CET__=1"); + else if (Name == "return") + Opts.addMacroDef("__CET__=2"); + else if (Name == "full") + Opts.addMacroDef("__CET__=3"); + } + // Add macros from the command line. - for (const Arg *A : Args.filtered(OPT_D, OPT_U)) { + for (const auto *A : Args.filtered(OPT_D, OPT_U)) { if (A->getOption().matches(OPT_D)) Opts.addMacroDef(A->getValue()); else @@ -2641,13 +2886,13 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, Opts.MacroIncludes = Args.getAllArgValues(OPT_imacros); // Add the ordered list of -includes. - for (const Arg *A : Args.filtered(OPT_include)) + for (const auto *A : Args.filtered(OPT_include)) Opts.Includes.emplace_back(A->getValue()); - for (const Arg *A : Args.filtered(OPT_chain_include)) + for (const auto *A : Args.filtered(OPT_chain_include)) Opts.ChainedIncludes.emplace_back(A->getValue()); - for (const Arg *A : Args.filtered(OPT_remap_file)) { + for (const auto *A : Args.filtered(OPT_remap_file)) { std::pair<StringRef, StringRef> Split = StringRef(A->getValue()).split(';'); if (Split.second.empty()) { @@ -2681,8 +2926,6 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, ArgList &Args, frontend::ActionKind Action) { - using namespace options; - if (isStrictlyPreprocessorAction(Action)) Opts.ShowCPP = !Args.hasArg(OPT_dM); else @@ -2700,7 +2943,6 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args, DiagnosticsEngine &Diags) { - using namespace options; Opts.ABI = Args.getLastArgValue(OPT_target_abi); if (Arg *A = Args.getLastArg(OPT_meabi)) { StringRef Value = A->getValue(); @@ -2720,11 +2962,15 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args, 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)); + Opts.Triple = Args.getLastArgValue(OPT_triple); // Use the default target triple if unspecified. if (Opts.Triple.empty()) Opts.Triple = llvm::sys::getDefaultTargetTriple(); + Opts.Triple = llvm::Triple::normalize(Opts.Triple); Opts.OpenCLExtensionsAsWritten = Args.getAllArgValues(OPT_cl_ext_EQ); + Opts.ForceEnableInt128 = Args.hasArg(OPT_fforce_enable_int128); + Opts.NVPTXUseShortPointers = Args.hasFlag( + options::OPT_fcuda_short_ptr, options::OPT_fno_cuda_short_ptr, false); } bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, @@ -2750,8 +2996,14 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, } // Issue errors on unknown arguments. - for (const Arg *A : Args.filtered(OPT_UNKNOWN)) { - Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(Args); + for (const auto *A : Args.filtered(OPT_UNKNOWN)) { + auto ArgString = A->getAsString(Args); + std::string Nearest; + if (Opts->findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1) + Diags.Report(diag::err_drv_unknown_argument) << ArgString; + else + Diags.Report(diag::err_drv_unknown_argument_with_suggestion) + << ArgString << Nearest; Success = false; } @@ -2768,7 +3020,7 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, LangOpts.IsHeaderFile); ParseTargetArgs(Res.getTargetOpts(), Args, Diags); Success &= ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags, - Res.getTargetOpts()); + Res.getTargetOpts(), Res.getFrontendOpts()); ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, Res.getFileSystemOpts().WorkingDir); if (DashX.getFormat() == InputKind::Precompiled || @@ -2793,6 +3045,9 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, LangOpts.ObjCExceptions = 1; } + LangOpts.FunctionAlignment = + getLastArgIntValue(Args, OPT_function_alignment, 0, Diags); + if (LangOpts.CUDA) { // During CUDA device-side compilation, the aux triple is the // triple used for host compilation. @@ -2811,12 +3066,7 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, !LangOpts.Sanitize.has(SanitizerKind::Address) && !LangOpts.Sanitize.has(SanitizerKind::Memory); - // FIXME: ParsePreprocessorArgs uses the FileManager to read the contents of - // PCH file and find the original header name. Remove the need to do that in - // ParsePreprocessorArgs and remove the FileManager - // parameters from the function and the "FileManager.h" #include. - FileManager FileMgr(Res.getFileSystemOpts()); - ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, FileMgr, Diags, + ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, Diags, Res.getFrontendOpts().ProgramAction); ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args, Res.getFrontendOpts().ProgramAction); @@ -2864,29 +3114,26 @@ std::string CompilerInvocation::getModuleHash() const { // Extend the signature with the target options. code = hash_combine(code, TargetOpts->Triple, TargetOpts->CPU, TargetOpts->ABI); - for (unsigned i = 0, n = TargetOpts->FeaturesAsWritten.size(); i != n; ++i) - code = hash_combine(code, TargetOpts->FeaturesAsWritten[i]); + for (const auto &FeatureAsWritten : TargetOpts->FeaturesAsWritten) + code = hash_combine(code, FeatureAsWritten); // Extend the signature with preprocessor options. const PreprocessorOptions &ppOpts = getPreprocessorOpts(); const HeaderSearchOptions &hsOpts = getHeaderSearchOpts(); code = hash_combine(code, ppOpts.UsePredefines, ppOpts.DetailedRecord); - for (std::vector<std::pair<std::string, bool/*isUndef*/>>::const_iterator - I = getPreprocessorOpts().Macros.begin(), - IEnd = getPreprocessorOpts().Macros.end(); - I != IEnd; ++I) { + for (const auto &I : getPreprocessorOpts().Macros) { // If we're supposed to ignore this macro for the purposes of modules, // don't put it into the hash. if (!hsOpts.ModulesIgnoreMacros.empty()) { // Check whether we're ignoring this macro. - StringRef MacroDef = I->first; + StringRef MacroDef = I.first; if (hsOpts.ModulesIgnoreMacros.count( llvm::CachedHashString(MacroDef.split('=').first))) continue; } - code = hash_combine(code, I->first, I->second); + code = hash_combine(code, I.first, I.second); } // Extend the signature with the sysroot and other header search options. @@ -2919,8 +3166,6 @@ std::string CompilerInvocation::getModuleHash() const { return llvm::APInt(64, code).toString(36, /*Signed=*/false); } -namespace clang { - template<typename IntTy> static IntTy getLastArgIntValueImpl(const ArgList &Args, OptSpecifier Id, IntTy Default, @@ -2936,6 +3181,7 @@ static IntTy getLastArgIntValueImpl(const ArgList &Args, OptSpecifier Id, return Res; } +namespace clang { // Declared in clang/Frontend/Utils.h. int getLastArgIntValue(const ArgList &Args, OptSpecifier Id, int Default, @@ -2980,22 +3226,22 @@ createVFSFromCompilerInvocation(const CompilerInvocation &CI, IntrusiveRefCntPtr<vfs::OverlayFileSystem> Overlay( new vfs::OverlayFileSystem(BaseFS)); // earlier vfs files are on the bottom - for (const std::string &File : CI.getHeaderSearchOpts().VFSOverlayFiles) { + for (const auto &File : CI.getHeaderSearchOpts().VFSOverlayFiles) { llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer = BaseFS->getBufferForFile(File); if (!Buffer) { Diags.Report(diag::err_missing_vfs_overlay_file) << File; - return IntrusiveRefCntPtr<vfs::FileSystem>(); + continue; } IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getVFSFromYAML( std::move(Buffer.get()), /*DiagHandler*/ nullptr, File); - if (!FS.get()) { + if (FS) + Overlay->pushOverlay(FS); + else Diags.Report(diag::err_invalid_vfs_overlay) << File; - return IntrusiveRefCntPtr<vfs::FileSystem>(); - } - Overlay->pushOverlay(FS); } return Overlay; } -} // end namespace clang + +} // namespace clang diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp index 561eb9c4a316..f89722eeb9ed 100644 --- a/lib/Frontend/DependencyFile.cpp +++ b/lib/Frontend/DependencyFile.cpp @@ -63,7 +63,8 @@ struct DepCollectorPPCallbacks : public PPCallbacks { StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File, StringRef SearchPath, StringRef RelativePath, - const Module *Imported) override { + const Module *Imported, + SrcMgr::CharacteristicKind FileType) override { if (!File) DepCollector.maybeAddDependency(FileName, /*FromModule*/false, /*IsSystem*/false, /*IsModuleFile*/false, @@ -162,6 +163,7 @@ class DFGImpl : public PPCallbacks { bool SeenMissingHeader; bool IncludeModuleFiles; DependencyOutputFormat OutputFormat; + unsigned InputFileIndex; private: bool FileMatchesDepCriteria(const char *Filename, @@ -176,26 +178,33 @@ public: AddMissingHeaderDeps(Opts.AddMissingHeaderDeps), SeenMissingHeader(false), IncludeModuleFiles(Opts.IncludeModuleFiles), - OutputFormat(Opts.OutputFormat) { + OutputFormat(Opts.OutputFormat), + InputFileIndex(0) { for (const auto &ExtraDep : Opts.ExtraDeps) { - AddFilename(ExtraDep); + if (AddFilename(ExtraDep)) + ++InputFileIndex; } } void FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType, FileID PrevFID) override; + + void FileSkipped(const FileEntry &SkippedFile, const Token &FilenameTok, + SrcMgr::CharacteristicKind FileType) override; + void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File, StringRef SearchPath, StringRef RelativePath, - const Module *Imported) override; + const Module *Imported, + SrcMgr::CharacteristicKind FileType) override; void EndOfMainFile() override { OutputDependencyFile(); } - void AddFilename(StringRef Filename); + bool AddFilename(StringRef Filename); bool includeSystemHeaders() const { return IncludeSystemHeaders; } bool includeModuleFiles() const { return IncludeModuleFiles; } }; @@ -291,6 +300,16 @@ void DFGImpl::FileChanged(SourceLocation Loc, AddFilename(llvm::sys::path::remove_leading_dotslash(Filename)); } +void DFGImpl::FileSkipped(const FileEntry &SkippedFile, + const Token &FilenameTok, + SrcMgr::CharacteristicKind FileType) { + StringRef Filename = SkippedFile.getName(); + if (!FileMatchesDepCriteria(Filename.data(), FileType)) + return; + + AddFilename(llvm::sys::path::remove_leading_dotslash(Filename)); +} + void DFGImpl::InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, @@ -299,7 +318,8 @@ void DFGImpl::InclusionDirective(SourceLocation HashLoc, const FileEntry *File, StringRef SearchPath, StringRef RelativePath, - const Module *Imported) { + const Module *Imported, + SrcMgr::CharacteristicKind FileType) { if (!File) { if (AddMissingHeaderDeps) AddFilename(FileName); @@ -308,9 +328,12 @@ void DFGImpl::InclusionDirective(SourceLocation HashLoc, } } -void DFGImpl::AddFilename(StringRef Filename) { - if (FilesSet.insert(Filename).second) +bool DFGImpl::AddFilename(StringRef Filename) { + if (FilesSet.insert(Filename).second) { Files.push_back(Filename); + return true; + } + return false; } /// Print the filename, with escaping or quoting that accommodates the three @@ -446,8 +469,10 @@ void DFGImpl::OutputDependencyFile() { // Create phony targets if requested. if (PhonyTarget && !Files.empty()) { - // Skip the first entry, this is always the input file itself. - for (auto I = Files.begin() + 1, E = Files.end(); I != E; ++I) { + unsigned Index = 0; + for (auto I = Files.begin(), E = Files.end(); I != E; ++I) { + if (Index++ == InputFileIndex) + continue; OS << '\n'; PrintFilename(OS, *I, OutputFormat); OS << ":\n"; diff --git a/lib/Frontend/DependencyGraph.cpp b/lib/Frontend/DependencyGraph.cpp index 67a977e38be2..660f664447ab 100644 --- a/lib/Frontend/DependencyGraph.cpp +++ b/lib/Frontend/DependencyGraph.cpp @@ -50,7 +50,8 @@ public: StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File, StringRef SearchPath, StringRef RelativePath, - const Module *Imported) override; + const Module *Imported, + SrcMgr::CharacteristicKind FileType) override; void EndOfMainFile() override { OutputGraphFile(); @@ -65,15 +66,17 @@ void clang::AttachDependencyGraphGen(Preprocessor &PP, StringRef OutputFile, SysRoot)); } -void DependencyGraphCallback::InclusionDirective(SourceLocation HashLoc, - const Token &IncludeTok, - StringRef FileName, - bool IsAngled, - CharSourceRange FilenameRange, - const FileEntry *File, - StringRef SearchPath, - StringRef RelativePath, - const Module *Imported) { +void DependencyGraphCallback::InclusionDirective( + SourceLocation HashLoc, + const Token &IncludeTok, + StringRef FileName, + bool IsAngled, + CharSourceRange FilenameRange, + const FileEntry *File, + StringRef SearchPath, + StringRef RelativePath, + const Module *Imported, + SrcMgr::CharacteristicKind FileType) { if (!File) return; diff --git a/lib/Frontend/DiagnosticRenderer.cpp b/lib/Frontend/DiagnosticRenderer.cpp index e3263843e29b..fb0a92d1f8c6 100644 --- a/lib/Frontend/DiagnosticRenderer.cpp +++ b/lib/Frontend/DiagnosticRenderer.cpp @@ -1,4 +1,4 @@ -//===--- DiagnosticRenderer.cpp - Diagnostic Pretty-Printing --------------===// +//===- DiagnosticRenderer.cpp - Diagnostic Pretty-Printing ----------------===// // // The LLVM Compiler Infrastructure // @@ -8,24 +8,34 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/DiagnosticRenderer.h" +#include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticOptions.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Edit/Commit.h" #include "clang/Edit/EditedSource.h" #include "clang/Edit/EditsReceiver.h" #include "clang/Lex/Lexer.h" -#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/SmallString.h" -#include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> +#include <cassert> +#include <iterator> +#include <utility> + using namespace clang; DiagnosticRenderer::DiagnosticRenderer(const LangOptions &LangOpts, DiagnosticOptions *DiagOpts) - : LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {} + : LangOpts(LangOpts), DiagOpts(DiagOpts), LastLevel() {} -DiagnosticRenderer::~DiagnosticRenderer() {} +DiagnosticRenderer::~DiagnosticRenderer() = default; namespace { @@ -34,24 +44,24 @@ class FixitReceiver : public edit::EditsReceiver { public: FixitReceiver(SmallVectorImpl<FixItHint> &MergedFixits) - : MergedFixits(MergedFixits) { } + : MergedFixits(MergedFixits) {} + void insert(SourceLocation loc, StringRef text) override { MergedFixits.push_back(FixItHint::CreateInsertion(loc, text)); } + void replace(CharSourceRange range, StringRef text) override { MergedFixits.push_back(FixItHint::CreateReplacement(range, text)); } }; -} +} // namespace static void mergeFixits(ArrayRef<FixItHint> FixItHints, const SourceManager &SM, const LangOptions &LangOpts, SmallVectorImpl<FixItHint> &MergedFixits) { edit::Commit commit(SM, LangOpts); - for (ArrayRef<FixItHint>::const_iterator - I = FixItHints.begin(), E = FixItHints.end(); I != E; ++I) { - const FixItHint &Hint = *I; + for (const auto &Hint : FixItHints) if (Hint.CodeToInsert.empty()) { if (Hint.InsertFromRange.isValid()) commit.insertFromRange(Hint.RemoveRange.getBegin(), @@ -67,7 +77,6 @@ static void mergeFixits(ArrayRef<FixItHint> FixItHints, commit.insert(Hint.RemoveRange.getBegin(), Hint.CodeToInsert, /*afterToken=*/false, Hint.BeforePreviousInsertions); } - } edit::EditedSource Editor(SM, LangOpts); if (Editor.commit(commit)) { @@ -100,11 +109,9 @@ void DiagnosticRenderer::emitDiagnostic(FullSourceLoc Loc, FixItHints = MergedFixits; } - for (ArrayRef<FixItHint>::const_iterator I = FixItHints.begin(), - E = FixItHints.end(); - I != E; ++I) - if (I->RemoveRange.isValid()) - MutableRanges.push_back(I->RemoveRange); + for (const auto &Hint : FixItHints) + if (Hint.RemoveRange.isValid()) + MutableRanges.push_back(Hint.RemoveRange); FullSourceLoc UnexpandedLoc = Loc; @@ -134,7 +141,6 @@ void DiagnosticRenderer::emitDiagnostic(FullSourceLoc Loc, endDiagnostic(D, Level); } - void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) { emitDiagnostic(Diag.getLocation(), Diag.getLevel(), Diag.getMessage(), Diag.getRanges(), Diag.getFixIts(), @@ -146,7 +152,7 @@ void DiagnosticRenderer::emitBasicNote(StringRef Message) { Message, None, DiagOrStoredDiag()); } -/// \brief Prints an include stack when appropriate for a particular +/// Prints an include stack when appropriate for a particular /// diagnostic level and location. /// /// This routine handles all the logic of suppressing particular include @@ -180,7 +186,7 @@ void DiagnosticRenderer::emitIncludeStack(FullSourceLoc Loc, PresumedLoc PLoc, } } -/// \brief Helper to recursivly walk up the include stack and print each layer +/// Helper to recursively walk up the include stack and print each layer /// on the way back down. void DiagnosticRenderer::emitIncludeStackRecursively(FullSourceLoc Loc) { if (Loc.isInvalid()) { @@ -210,7 +216,7 @@ void DiagnosticRenderer::emitIncludeStackRecursively(FullSourceLoc Loc) { emitIncludeLocation(Loc, PLoc); } -/// \brief Emit the module import stack associated with the current location. +/// Emit the module import stack associated with the current location. void DiagnosticRenderer::emitImportStack(FullSourceLoc Loc) { if (Loc.isInvalid()) { emitModuleBuildStack(Loc.getManager()); @@ -221,7 +227,7 @@ void DiagnosticRenderer::emitImportStack(FullSourceLoc Loc) { emitImportStackRecursively(NextImportLoc.first, NextImportLoc.second); } -/// \brief Helper to recursivly walk up the import stack and print each layer +/// Helper to recursively walk up the import stack and print each layer /// on the way back down. void DiagnosticRenderer::emitImportStackRecursively(FullSourceLoc Loc, StringRef ModuleName) { @@ -239,14 +245,14 @@ void DiagnosticRenderer::emitImportStackRecursively(FullSourceLoc Loc, emitImportLocation(Loc, PLoc, ModuleName); } -/// \brief Emit the module build stack, for cases where a module is (re-)built +/// Emit the module build stack, for cases where a module is (re-)built /// on demand. void DiagnosticRenderer::emitModuleBuildStack(const SourceManager &SM) { ModuleBuildStack Stack = SM.getModuleBuildStack(); - for (unsigned I = 0, N = Stack.size(); I != N; ++I) { - emitBuildingModuleLocation(Stack[I].second, Stack[I].second.getPresumedLoc( - DiagOpts->ShowPresumedLoc), - Stack[I].first); + for (const auto &I : Stack) { + emitBuildingModuleLocation(I.second, I.second.getPresumedLoc( + DiagOpts->ShowPresumedLoc), + I.first); } } @@ -256,41 +262,54 @@ static SourceLocation retrieveMacroLocation(SourceLocation Loc, FileID MacroFileID, FileID CaretFileID, const SmallVectorImpl<FileID> &CommonArgExpansions, - bool IsBegin, const SourceManager *SM) { + bool IsBegin, const SourceManager *SM, + bool &IsTokenRange) { assert(SM->getFileID(Loc) == MacroFileID); if (MacroFileID == CaretFileID) return Loc; if (!Loc.isMacroID()) - return SourceLocation(); + return {}; - SourceLocation MacroLocation, MacroArgLocation; + CharSourceRange MacroRange, MacroArgRange; if (SM->isMacroArgExpansion(Loc)) { // Only look at the immediate spelling location of this macro argument if // the other location in the source range is also present in that expansion. if (std::binary_search(CommonArgExpansions.begin(), CommonArgExpansions.end(), MacroFileID)) - MacroLocation = SM->getImmediateSpellingLoc(Loc); - MacroArgLocation = IsBegin ? SM->getImmediateExpansionRange(Loc).first - : SM->getImmediateExpansionRange(Loc).second; + MacroRange = + CharSourceRange(SM->getImmediateSpellingLoc(Loc), IsTokenRange); + MacroArgRange = SM->getImmediateExpansionRange(Loc); } else { - MacroLocation = IsBegin ? SM->getImmediateExpansionRange(Loc).first - : SM->getImmediateExpansionRange(Loc).second; - MacroArgLocation = SM->getImmediateSpellingLoc(Loc); + MacroRange = SM->getImmediateExpansionRange(Loc); + MacroArgRange = + CharSourceRange(SM->getImmediateSpellingLoc(Loc), IsTokenRange); } + SourceLocation MacroLocation = + IsBegin ? MacroRange.getBegin() : MacroRange.getEnd(); if (MacroLocation.isValid()) { MacroFileID = SM->getFileID(MacroLocation); + bool TokenRange = IsBegin ? IsTokenRange : MacroRange.isTokenRange(); MacroLocation = retrieveMacroLocation(MacroLocation, MacroFileID, CaretFileID, - CommonArgExpansions, IsBegin, SM); - if (MacroLocation.isValid()) + CommonArgExpansions, IsBegin, SM, TokenRange); + if (MacroLocation.isValid()) { + IsTokenRange = TokenRange; return MacroLocation; + } } + // If we moved the end of the range to an expansion location, we now have + // a range of the same kind as the expansion range. + if (!IsBegin) + IsTokenRange = MacroArgRange.isTokenRange(); + + SourceLocation MacroArgLocation = + IsBegin ? MacroArgRange.getBegin() : MacroArgRange.getEnd(); MacroFileID = SM->getFileID(MacroArgLocation); return retrieveMacroLocation(MacroArgLocation, MacroFileID, CaretFileID, - CommonArgExpansions, IsBegin, SM); + CommonArgExpansions, IsBegin, SM, IsTokenRange); } /// Walk up the chain of macro expansions and collect the FileIDs identifying the @@ -304,7 +323,7 @@ static void getMacroArgExpansionFileIDs(SourceLocation Loc, Loc = SM->getImmediateSpellingLoc(Loc); } else { auto ExpRange = SM->getImmediateExpansionRange(Loc); - Loc = IsBegin ? ExpRange.first : ExpRange.second; + Loc = IsBegin ? ExpRange.getBegin() : ExpRange.getEnd(); } } } @@ -318,8 +337,8 @@ static void computeCommonMacroArgExpansionFileIDs( SmallVector<FileID, 4> EndArgExpansions; getMacroArgExpansionFileIDs(Begin, BeginArgExpansions, /*IsBegin=*/true, SM); getMacroArgExpansionFileIDs(End, EndArgExpansions, /*IsBegin=*/false, SM); - std::sort(BeginArgExpansions.begin(), BeginArgExpansions.end()); - std::sort(EndArgExpansions.begin(), EndArgExpansions.end()); + llvm::sort(BeginArgExpansions.begin(), BeginArgExpansions.end()); + llvm::sort(EndArgExpansions.begin(), EndArgExpansions.end()); std::set_intersection(BeginArgExpansions.begin(), BeginArgExpansions.end(), EndArgExpansions.begin(), EndArgExpansions.end(), std::back_inserter(CommonArgExpansions)); @@ -342,11 +361,12 @@ mapDiagnosticRanges(FullSourceLoc CaretLoc, ArrayRef<CharSourceRange> Ranges, const SourceManager *SM = &CaretLoc.getManager(); - for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { - if (I->isInvalid()) continue; + for (const auto &Range : Ranges) { + if (Range.isInvalid()) + continue; - SourceLocation Begin = I->getBegin(), End = I->getEnd(); - bool IsTokenRange = I->isTokenRange(); + SourceLocation Begin = Range.getBegin(), End = Range.getEnd(); + bool IsTokenRange = Range.isTokenRange(); FileID BeginFileID = SM->getFileID(Begin); FileID EndFileID = SM->getFileID(End); @@ -357,14 +377,16 @@ mapDiagnosticRanges(FullSourceLoc CaretLoc, ArrayRef<CharSourceRange> Ranges, llvm::SmallDenseMap<FileID, SourceLocation> BeginLocsMap; while (Begin.isMacroID() && BeginFileID != EndFileID) { BeginLocsMap[BeginFileID] = Begin; - Begin = SM->getImmediateExpansionRange(Begin).first; + Begin = SM->getImmediateExpansionRange(Begin).getBegin(); BeginFileID = SM->getFileID(Begin); } // Then, crawl the expansion chain for the end of the range. if (BeginFileID != EndFileID) { while (End.isMacroID() && !BeginLocsMap.count(EndFileID)) { - End = SM->getImmediateExpansionRange(End).second; + auto Exp = SM->getImmediateExpansionRange(End); + IsTokenRange = Exp.isTokenRange(); + End = Exp.getEnd(); EndFileID = SM->getFileID(End); } if (End.isMacroID()) { @@ -377,9 +399,11 @@ mapDiagnosticRanges(FullSourceLoc CaretLoc, ArrayRef<CharSourceRange> Ranges, SmallVector<FileID, 4> CommonArgExpansions; computeCommonMacroArgExpansionFileIDs(Begin, End, SM, CommonArgExpansions); Begin = retrieveMacroLocation(Begin, BeginFileID, CaretLocFileID, - CommonArgExpansions, /*IsBegin=*/true, SM); + CommonArgExpansions, /*IsBegin=*/true, SM, + IsTokenRange); End = retrieveMacroLocation(End, BeginFileID, CaretLocFileID, - CommonArgExpansions, /*IsBegin=*/false, SM); + CommonArgExpansions, /*IsBegin=*/false, SM, + IsTokenRange); if (Begin.isInvalid() || End.isInvalid()) continue; // Return the spelling location of the beginning and end of the range. @@ -400,7 +424,7 @@ void DiagnosticRenderer::emitCaret(FullSourceLoc Loc, emitCodeContext(Loc, Level, SpellingRanges, Hints); } -/// \brief A helper function for emitMacroExpansion to print the +/// A helper function for emitMacroExpansion to print the /// macro expansion message void DiagnosticRenderer::emitSingleMacroExpansion( FullSourceLoc Loc, DiagnosticsEngine::Level Level, @@ -441,7 +465,7 @@ static bool checkLocForMacroArgExpansion(SourceLocation Loc, } /// Check if all the locations in the range have the same macro argument -/// expansion, and that that expansion starts with ArgumentLoc. +/// expansion, and that the expansion starts with ArgumentLoc. static bool checkRangeForMacroArgExpansion(CharSourceRange Range, const SourceManager &SM, SourceLocation ArgumentLoc) { @@ -466,8 +490,9 @@ static bool checkRangesForMacroArgExpansion(FullSourceLoc Loc, /// Count all valid ranges. unsigned ValidCount = 0; - for (auto I : Ranges) - if (I.isValid()) ValidCount++; + for (const auto &Range : Ranges) + if (Range.isValid()) + ValidCount++; if (ValidCount > SpellingRanges.size()) return false; @@ -480,15 +505,14 @@ static bool checkRangesForMacroArgExpansion(FullSourceLoc Loc, if (!Loc.isMacroArgExpansion(&ArgumentLoc)) return false; - for (auto I = SpellingRanges.begin(), E = SpellingRanges.end(); I != E; ++I) { - if (!checkRangeForMacroArgExpansion(*I, Loc.getManager(), ArgumentLoc)) + for (const auto &Range : SpellingRanges) + if (!checkRangeForMacroArgExpansion(Range, Loc.getManager(), ArgumentLoc)) return false; - } return true; } -/// \brief Recursively emit notes for each macro expansion and caret +/// Recursively emit notes for each macro expansion and caret /// diagnostics where appropriate. /// /// Walks up the macro expansion stack printing expansion notes, the code @@ -504,29 +528,31 @@ void DiagnosticRenderer::emitMacroExpansions(FullSourceLoc Loc, ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Hints) { assert(Loc.isValid() && "must have a valid source location here"); + const SourceManager &SM = Loc.getManager(); + SourceLocation L = Loc; // Produce a stack of macro backtraces. - SmallVector<FullSourceLoc, 8> LocationStack; + SmallVector<SourceLocation, 8> LocationStack; unsigned IgnoredEnd = 0; - while (Loc.isMacroID()) { + while (L.isMacroID()) { // If this is the expansion of a macro argument, point the caret at the // use of the argument in the definition of the macro, not the expansion. - if (Loc.isMacroArgExpansion()) - LocationStack.push_back(Loc.getImmediateExpansionRange().first); + if (SM.isMacroArgExpansion(L)) + LocationStack.push_back(SM.getImmediateExpansionRange(L).getBegin()); else - LocationStack.push_back(Loc); + LocationStack.push_back(L); - if (checkRangesForMacroArgExpansion(Loc, Ranges)) + if (checkRangesForMacroArgExpansion(FullSourceLoc(L, SM), Ranges)) IgnoredEnd = LocationStack.size(); - Loc = Loc.getImmediateMacroCallerLoc(); + L = SM.getImmediateMacroCallerLoc(L); // Once the location no longer points into a macro, try stepping through // the last found location. This sometimes produces additional useful // backtraces. - if (Loc.isFileID()) - Loc = LocationStack.back().getImmediateMacroCallerLoc(); - assert(Loc.isValid() && "must have a valid source location here"); + if (L.isFileID()) + L = SM.getImmediateMacroCallerLoc(LocationStack.back()); + assert(L.isValid() && "must have a valid source location here"); } LocationStack.erase(LocationStack.begin(), @@ -537,7 +563,7 @@ void DiagnosticRenderer::emitMacroExpansions(FullSourceLoc Loc, if (MacroDepth <= MacroLimit || MacroLimit == 0) { for (auto I = LocationStack.rbegin(), E = LocationStack.rend(); I != E; ++I) - emitSingleMacroExpansion(*I, Level, Ranges); + emitSingleMacroExpansion(FullSourceLoc(*I, SM), Level, Ranges); return; } @@ -547,7 +573,7 @@ void DiagnosticRenderer::emitMacroExpansions(FullSourceLoc Loc, for (auto I = LocationStack.rbegin(), E = LocationStack.rbegin() + MacroStartMessages; I != E; ++I) - emitSingleMacroExpansion(*I, Level, Ranges); + emitSingleMacroExpansion(FullSourceLoc(*I, SM), Level, Ranges); SmallString<200> MessageStorage; llvm::raw_svector_ostream Message(MessageStorage); @@ -559,10 +585,10 @@ void DiagnosticRenderer::emitMacroExpansions(FullSourceLoc Loc, for (auto I = LocationStack.rend() - MacroEndMessages, E = LocationStack.rend(); I != E; ++I) - emitSingleMacroExpansion(*I, Level, Ranges); + emitSingleMacroExpansion(FullSourceLoc(*I, SM), Level, Ranges); } -DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {} +DiagnosticNoteRenderer::~DiagnosticNoteRenderer() = default; void DiagnosticNoteRenderer::emitIncludeLocation(FullSourceLoc Loc, PresumedLoc PLoc) { diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp index 12226b231417..a5929424e52a 100644 --- a/lib/Frontend/FrontendAction.cpp +++ b/lib/Frontend/FrontendAction.cpp @@ -79,7 +79,7 @@ public: } }; -/// \brief Dumps deserialized declarations. +/// Dumps deserialized declarations. class DeserializedDeclsDumper : public DelegatingDeserializationListener { public: explicit DeserializedDeclsDumper(ASTDeserializationListener *Previous, @@ -88,15 +88,17 @@ public: void DeclRead(serialization::DeclID ID, const Decl *D) override { llvm::outs() << "PCH DECL: " << D->getDeclKindName(); - if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) - llvm::outs() << " - " << *ND; + if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) { + llvm::outs() << " - "; + ND->printQualifiedName(llvm::outs()); + } llvm::outs() << "\n"; DelegatingDeserializationListener::DeclRead(ID, D); } }; -/// \brief Checks deserialized declarations and emits error if a name +/// Checks deserialized declarations and emits error if a name /// matches one given in command-line using -error-on-deserialized-decl. class DeserializedDeclsChecker : public DelegatingDeserializationListener { ASTContext &Ctx; @@ -153,6 +155,10 @@ FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI, if (FrontendPluginRegistry::begin() == FrontendPluginRegistry::end()) return Consumer; + // If this is a code completion run, avoid invoking the plugin consumers + if (CI.hasCodeCompletionConsumer()) + return Consumer; + // Collect the list of plugins that go before the main action (in Consumers) // or after it (in AfterConsumers) std::vector<std::unique_ptr<ASTConsumer>> Consumers; @@ -282,7 +288,7 @@ static void addHeaderInclude(StringRef HeaderName, Includes += "}\n"; } -/// \brief Collect the set of header includes needed to construct the given +/// Collect the set of header includes needed to construct the given /// module and update the TopHeaders file set of the module. /// /// \param Module The module we're collecting includes from. @@ -760,6 +766,22 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, if (!BeginSourceFileAction(CI)) goto failure; + // If we were asked to load any module map files, do so now. + for (const auto &Filename : CI.getFrontendOpts().ModuleMapFiles) { + if (auto *File = CI.getFileManager().getFile(Filename)) + CI.getPreprocessor().getHeaderSearchInfo().loadModuleMapFile( + File, /*IsSystem*/false); + else + CI.getDiagnostics().Report(diag::err_module_map_not_found) << Filename; + } + + // Add a module declaration scope so that modules from -fmodule-map-file + // arguments may shadow modules found implicitly in search paths. + CI.getPreprocessor() + .getHeaderSearchInfo() + .getModuleMap() + .finishModuleDeclarationScope(); + // Create the AST context and consumer unless this is a preprocessor only // action. if (!usesPreprocessorOnly()) { @@ -849,15 +871,6 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, "doesn't support modules"); } - // If we were asked to load any module map files, do so now. - for (const auto &Filename : CI.getFrontendOpts().ModuleMapFiles) { - if (auto *File = CI.getFileManager().getFile(Filename)) - CI.getPreprocessor().getHeaderSearchInfo().loadModuleMapFile( - File, /*IsSystem*/false); - else - CI.getDiagnostics().Report(diag::err_module_map_not_found) << Filename; - } - // If we were asked to load any module files, do so now. for (const auto &ModuleFile : CI.getFrontendOpts().ModuleFiles) if (!CI.loadModuleFile(ModuleFile)) diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index ffa5b410d2d8..9344e673c7ac 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -18,17 +18,36 @@ #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/PreprocessorOptions.h" +#include "clang/Sema/TemplateInstCallback.h" #include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ASTWriter.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/YAMLTraits.h" #include <memory> #include <system_error> using namespace clang; +namespace { +CodeCompleteConsumer *GetCodeCompletionConsumer(CompilerInstance &CI) { + return CI.hasCodeCompletionConsumer() ? &CI.getCodeCompletionConsumer() + : nullptr; +} + +void EnsureSemaIsCreated(CompilerInstance &CI, FrontendAction &Action) { + if (Action.hasCodeCompletionSupport() && + !CI.getFrontendOpts().CodeCompletionAt.FileName.empty()) + CI.createCodeCompletionConsumer(); + + if (!CI.hasSema()) + CI.createSema(Action.getTranslationUnitKind(), + GetCodeCompletionConsumer(CI)); +} +} // namespace + //===----------------------------------------------------------------------===// // Custom Actions //===----------------------------------------------------------------------===// @@ -55,7 +74,8 @@ ASTPrintAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { std::unique_ptr<ASTConsumer> ASTDumpAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - return CreateASTDumper(CI.getFrontendOpts().ASTDumpFilter, + return CreateASTDumper(nullptr /*Dump to stdout.*/, + CI.getFrontendOpts().ASTDumpFilter, CI.getFrontendOpts().ASTDumpDecls, CI.getFrontendOpts().ASTDumpAll, CI.getFrontendOpts().ASTDumpLookups); @@ -92,14 +112,14 @@ GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { if (!CI.getFrontendOpts().RelocatablePCH) Sysroot.clear(); + const auto &FrontendOpts = CI.getFrontendOpts(); auto Buffer = std::make_shared<PCHBuffer>(); std::vector<std::unique_ptr<ASTConsumer>> Consumers; Consumers.push_back(llvm::make_unique<PCHGenerator>( CI.getPreprocessor(), OutputFile, Sysroot, - Buffer, CI.getFrontendOpts().ModuleFileExtensions, - /*AllowASTWithErrors*/CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, - /*IncludeTimestamps*/ - +CI.getFrontendOpts().IncludeTimestamps)); + Buffer, FrontendOpts.ModuleFileExtensions, + CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, + FrontendOpts.IncludeTimestamps)); Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator( CI, InFile, OutputFile, std::move(OS), Buffer)); @@ -262,7 +282,141 @@ void VerifyPCHAction::ExecuteAction() { } namespace { - /// \brief AST reader listener that dumps module information for a module +struct TemplightEntry { + std::string Name; + std::string Kind; + std::string Event; + std::string DefinitionLocation; + std::string PointOfInstantiation; +}; +} // namespace + +namespace llvm { +namespace yaml { +template <> struct MappingTraits<TemplightEntry> { + static void mapping(IO &io, TemplightEntry &fields) { + io.mapRequired("name", fields.Name); + io.mapRequired("kind", fields.Kind); + io.mapRequired("event", fields.Event); + io.mapRequired("orig", fields.DefinitionLocation); + io.mapRequired("poi", fields.PointOfInstantiation); + } +}; +} // namespace yaml +} // namespace llvm + +namespace { +class DefaultTemplateInstCallback : public TemplateInstantiationCallback { + using CodeSynthesisContext = Sema::CodeSynthesisContext; + +public: + void initialize(const Sema &) override {} + + void finalize(const Sema &) override {} + + void atTemplateBegin(const Sema &TheSema, + const CodeSynthesisContext &Inst) override { + displayTemplightEntry<true>(llvm::outs(), TheSema, Inst); + } + + void atTemplateEnd(const Sema &TheSema, + const CodeSynthesisContext &Inst) override { + displayTemplightEntry<false>(llvm::outs(), TheSema, Inst); + } + +private: + static std::string toString(CodeSynthesisContext::SynthesisKind Kind) { + switch (Kind) { + case CodeSynthesisContext::TemplateInstantiation: + return "TemplateInstantiation"; + case CodeSynthesisContext::DefaultTemplateArgumentInstantiation: + return "DefaultTemplateArgumentInstantiation"; + case CodeSynthesisContext::DefaultFunctionArgumentInstantiation: + return "DefaultFunctionArgumentInstantiation"; + case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution: + return "ExplicitTemplateArgumentSubstitution"; + case CodeSynthesisContext::DeducedTemplateArgumentSubstitution: + return "DeducedTemplateArgumentSubstitution"; + case CodeSynthesisContext::PriorTemplateArgumentSubstitution: + return "PriorTemplateArgumentSubstitution"; + case CodeSynthesisContext::DefaultTemplateArgumentChecking: + return "DefaultTemplateArgumentChecking"; + case CodeSynthesisContext::ExceptionSpecInstantiation: + return "ExceptionSpecInstantiation"; + case CodeSynthesisContext::DeclaringSpecialMember: + return "DeclaringSpecialMember"; + case CodeSynthesisContext::DefiningSynthesizedFunction: + return "DefiningSynthesizedFunction"; + case CodeSynthesisContext::Memoization: + return "Memoization"; + } + return ""; + } + + template <bool BeginInstantiation> + static void displayTemplightEntry(llvm::raw_ostream &Out, const Sema &TheSema, + const CodeSynthesisContext &Inst) { + std::string YAML; + { + llvm::raw_string_ostream OS(YAML); + llvm::yaml::Output YO(OS); + TemplightEntry Entry = + getTemplightEntry<BeginInstantiation>(TheSema, Inst); + llvm::yaml::EmptyContext Context; + llvm::yaml::yamlize(YO, Entry, true, Context); + } + Out << "---" << YAML << "\n"; + } + + template <bool BeginInstantiation> + static TemplightEntry getTemplightEntry(const Sema &TheSema, + const CodeSynthesisContext &Inst) { + TemplightEntry Entry; + Entry.Kind = toString(Inst.Kind); + Entry.Event = BeginInstantiation ? "Begin" : "End"; + if (auto *NamedTemplate = dyn_cast_or_null<NamedDecl>(Inst.Entity)) { + llvm::raw_string_ostream OS(Entry.Name); + NamedTemplate->getNameForDiagnostic(OS, TheSema.getLangOpts(), true); + const PresumedLoc DefLoc = + TheSema.getSourceManager().getPresumedLoc(Inst.Entity->getLocation()); + if(!DefLoc.isInvalid()) + Entry.DefinitionLocation = std::string(DefLoc.getFilename()) + ":" + + std::to_string(DefLoc.getLine()) + ":" + + std::to_string(DefLoc.getColumn()); + } + const PresumedLoc PoiLoc = + TheSema.getSourceManager().getPresumedLoc(Inst.PointOfInstantiation); + if (!PoiLoc.isInvalid()) { + Entry.PointOfInstantiation = std::string(PoiLoc.getFilename()) + ":" + + std::to_string(PoiLoc.getLine()) + ":" + + std::to_string(PoiLoc.getColumn()); + } + return Entry; + } +}; +} // namespace + +std::unique_ptr<ASTConsumer> +TemplightDumpAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { + return llvm::make_unique<ASTConsumer>(); +} + +void TemplightDumpAction::ExecuteAction() { + CompilerInstance &CI = getCompilerInstance(); + + // This part is normally done by ASTFrontEndAction, but needs to happen + // before Templight observers can be created + // FIXME: Move the truncation aspect of this into Sema, we delayed this till + // here so the source manager would be initialized. + EnsureSemaIsCreated(CI, *this); + + CI.getSema().TemplateInstCallbacks.push_back( + llvm::make_unique<DefaultTemplateInstCallback>()); + ASTFrontendAction::ExecuteAction(); +} + +namespace { + /// AST reader listener that dumps module information for a module /// file. class DumpModuleInfoListener : public ASTReaderListener { llvm::raw_ostream &Out; @@ -406,6 +560,45 @@ namespace { Out << "\n"; } + + /// Tells the \c ASTReaderListener that we want to receive the + /// input files of the AST file via \c visitInputFile. + bool needsInputFileVisitation() override { return true; } + + /// Tells the \c ASTReaderListener that we want to receive the + /// input files of the AST file via \c visitInputFile. + bool needsSystemInputFileVisitation() override { return true; } + + /// Indicates that the AST file contains particular input file. + /// + /// \returns true to continue receiving the next input file, false to stop. + bool visitInputFile(StringRef Filename, bool isSystem, + bool isOverridden, bool isExplicitModule) override { + + Out.indent(2) << "Input file: " << Filename; + + if (isSystem || isOverridden || isExplicitModule) { + Out << " ["; + if (isSystem) { + Out << "System"; + if (isOverridden || isExplicitModule) + Out << ", "; + } + if (isOverridden) { + Out << "Overridden"; + if (isExplicitModule) + Out << ", "; + } + if (isExplicitModule) + Out << "ExplicitModule"; + + Out << "]"; + } + + Out << "\n"; + + return true; + } #undef DUMP_BOOLEAN }; } @@ -579,6 +772,7 @@ void PrintPreambleAction::ExecuteAction() { case InputKind::ObjCXX: case InputKind::OpenCL: case InputKind::CUDA: + case InputKind::HIP: break; case InputKind::Unknown: @@ -601,3 +795,51 @@ void PrintPreambleAction::ExecuteAction() { llvm::outs().write((*Buffer)->getBufferStart(), Preamble); } } + +void DumpCompilerOptionsAction::ExecuteAction() { + CompilerInstance &CI = getCompilerInstance(); + std::unique_ptr<raw_ostream> OSP = + CI.createDefaultOutputFile(false, getCurrentFile()); + if (!OSP) + return; + + raw_ostream &OS = *OSP; + const Preprocessor &PP = CI.getPreprocessor(); + const LangOptions &LangOpts = PP.getLangOpts(); + + // FIXME: Rather than manually format the JSON (which is awkward due to + // needing to remove trailing commas), this should make use of a JSON library. + // FIXME: Instead of printing enums as an integral value and specifying the + // type as a separate field, use introspection to print the enumerator. + + OS << "{\n"; + OS << "\n\"features\" : [\n"; + { + llvm::SmallString<128> Str; +#define FEATURE(Name, Predicate) \ + ("\t{\"" #Name "\" : " + llvm::Twine(Predicate ? "true" : "false") + "},\n") \ + .toVector(Str); +#include "clang/Basic/Features.def" +#undef FEATURE + // Remove the newline and comma from the last entry to ensure this remains + // valid JSON. + OS << Str.substr(0, Str.size() - 2); + } + OS << "\n],\n"; + + OS << "\n\"extensions\" : [\n"; + { + llvm::SmallString<128> Str; +#define EXTENSION(Name, Predicate) \ + ("\t{\"" #Name "\" : " + llvm::Twine(Predicate ? "true" : "false") + "},\n") \ + .toVector(Str); +#include "clang/Basic/Features.def" +#undef EXTENSION + // Remove the newline and comma from the last entry to ensure this remains + // valid JSON. + OS << Str.substr(0, Str.size() - 2); + } + OS << "\n]\n"; + + OS << "}"; +} diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp index dca434588fb1..0744d447e816 100644 --- a/lib/Frontend/FrontendOptions.cpp +++ b/lib/Frontend/FrontendOptions.cpp @@ -1,4 +1,4 @@ -//===--- FrontendOptions.cpp ----------------------------------------------===// +//===- FrontendOptions.cpp ------------------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -9,6 +9,7 @@ #include "clang/Frontend/FrontendOptions.h" #include "llvm/ADT/StringSwitch.h" + using namespace clang; InputKind FrontendOptions::getInputKindForExtension(StringRef Extension) { diff --git a/lib/Frontend/FrontendTiming.cpp b/lib/Frontend/FrontendTiming.cpp new file mode 100644 index 000000000000..9ea7347e7797 --- /dev/null +++ b/lib/Frontend/FrontendTiming.cpp @@ -0,0 +1,20 @@ +//===- FronendTiming.cpp - Implements Frontend timing utils --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file keps implementation of frontend timing utils. +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/Utils.h" + +namespace clang { + +bool FrontendTimesIsEnabled = false; + +} diff --git a/lib/Frontend/HeaderIncludeGen.cpp b/lib/Frontend/HeaderIncludeGen.cpp index 5bff4ecd0b46..9dc107c9d546 100644 --- a/lib/Frontend/HeaderIncludeGen.cpp +++ b/lib/Frontend/HeaderIncludeGen.cpp @@ -80,9 +80,23 @@ void clang::AttachHeaderIncludeGen(Preprocessor &PP, const DependencyOutputOptions &DepOpts, bool ShowAllHeaders, StringRef OutputPath, bool ShowDepth, bool MSStyle) { - raw_ostream *OutputFile = MSStyle ? &llvm::outs() : &llvm::errs(); + raw_ostream *OutputFile = &llvm::errs(); bool OwnsOutputFile = false; + // Choose output stream, when printing in cl.exe /showIncludes style. + if (MSStyle) { + switch (DepOpts.ShowIncludesDest) { + default: + llvm_unreachable("Invalid destination for /showIncludes output!"); + case ShowIncludesDestination::Stderr: + OutputFile = &llvm::errs(); + break; + case ShowIncludesDestination::Stdout: + OutputFile = &llvm::outs(); + break; + } + } + // Open the output file, if used. if (!OutputPath.empty()) { std::error_code EC; diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index 8c6faced76ac..8a70404629d3 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -14,6 +14,7 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/LangOptions.h" #include "clang/Config/config.h" // C_INCLUDE_DIRS +#include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderMap.h" #include "clang/Lex/HeaderSearch.h" @@ -55,11 +56,13 @@ public: /// AddPath - Add the specified path to the specified group list, prefixing /// the sysroot if used. - void AddPath(const Twine &Path, IncludeDirGroup Group, bool isFramework); + /// Returns true if the path exists, false if it was ignored. + bool AddPath(const Twine &Path, IncludeDirGroup Group, bool isFramework); /// AddUnmappedPath - Add the specified path to the specified group list, /// without performing any sysroot remapping. - void AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, + /// Returns true if the path exists, false if it was ignored. + bool AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, bool isFramework); /// AddSystemHeaderPrefix - Add the specified prefix to the system header @@ -70,10 +73,9 @@ public: /// AddGnuCPlusPlusIncludePaths - Add the necessary paths to support a gnu /// libstdc++. - void AddGnuCPlusPlusIncludePaths(StringRef Base, - StringRef ArchDir, - StringRef Dir32, - StringRef Dir64, + /// Returns true if the \p Base path was found, false if it does not exist. + bool AddGnuCPlusPlusIncludePaths(StringRef Base, StringRef ArchDir, + StringRef Dir32, StringRef Dir64, const llvm::Triple &triple); /// AddMinGWCPlusPlusIncludePaths - Add the necessary paths to support a MinGW @@ -88,7 +90,8 @@ public: // AddDefaultCPlusPlusIncludePaths - Add paths that should be searched when // compiling c++. - void AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, + void AddDefaultCPlusPlusIncludePaths(const LangOptions &LangOpts, + const llvm::Triple &triple, const HeaderSearchOptions &HSOpts); /// AddDefaultSystemIncludePaths - Adds the default system include paths so @@ -105,14 +108,14 @@ public: } // end anonymous namespace. static bool CanPrefixSysroot(StringRef Path) { -#if defined(LLVM_ON_WIN32) +#if defined(_WIN32) return !Path.empty() && llvm::sys::path::is_separator(Path[0]); #else return llvm::sys::path::is_absolute(Path); #endif } -void InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group, +bool InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group, bool isFramework) { // Add the path with sysroot prepended, if desired and this is a system header // group. @@ -120,15 +123,14 @@ void InitHeaderSearch::AddPath(const Twine &Path, IncludeDirGroup Group, SmallString<256> MappedPathStorage; StringRef MappedPathStr = Path.toStringRef(MappedPathStorage); if (CanPrefixSysroot(MappedPathStr)) { - AddUnmappedPath(IncludeSysroot + Path, Group, isFramework); - return; + return AddUnmappedPath(IncludeSysroot + Path, Group, isFramework); } } - AddUnmappedPath(Path, Group, isFramework); + return AddUnmappedPath(Path, Group, isFramework); } -void InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, +bool InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, bool isFramework) { assert(!Path.isTriviallyEmpty() && "can't handle empty path here"); @@ -150,7 +152,7 @@ void InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, if (const DirectoryEntry *DE = FM.getDirectory(MappedPathStr)) { IncludePath.push_back( std::make_pair(Group, DirectoryLookup(DE, Type, isFramework))); - return; + return true; } // Check to see if this is an apple-style headermap (which are not allowed to @@ -162,7 +164,7 @@ void InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, IncludePath.push_back( std::make_pair(Group, DirectoryLookup(HM, Type, Group == IndexHeaderMap))); - return; + return true; } } } @@ -170,15 +172,16 @@ void InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, if (Verbose) llvm::errs() << "ignoring nonexistent directory \"" << MappedPathStr << "\"\n"; + return false; } -void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef Base, +bool InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef Base, StringRef ArchDir, StringRef Dir32, StringRef Dir64, const llvm::Triple &triple) { // Add the base dir - AddPath(Base, CXXSystem, false); + bool IsBaseFound = AddPath(Base, CXXSystem, false); // Add the multilib dirs llvm::Triple::ArchType arch = triple.getArch(); @@ -190,6 +193,7 @@ void InitHeaderSearch::AddGnuCPlusPlusIncludePaths(StringRef Base, // Add the backward dir AddPath(Base + "/backward", CXXSystem, false); + return IsBaseFound; } void InitHeaderSearch::AddMinGWCPlusPlusIncludePaths(StringRef Base, @@ -216,6 +220,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, case llvm::Triple::NaCl: case llvm::Triple::PS4: case llvm::Triple::ELFIAMCU: + case llvm::Triple::Fuchsia: break; case llvm::Triple::Win32: if (triple.getEnvironment() != llvm::Triple::Cygnus) @@ -255,6 +260,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, switch (os) { case llvm::Triple::Linux: + case llvm::Triple::Solaris: llvm_unreachable("Include management is handled in the driver."); case llvm::Triple::CloudABI: { @@ -321,6 +327,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, case llvm::Triple::RTEMS: case llvm::Triple::NaCl: case llvm::Triple::ELFIAMCU: + case llvm::Triple::Fuchsia: break; case llvm::Triple::PS4: { // <isysroot> gets prepended later in AddPath(). @@ -351,51 +358,61 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, } } -void InitHeaderSearch:: -AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, const HeaderSearchOptions &HSOpts) { +void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths( + const LangOptions &LangOpts, const llvm::Triple &triple, + const HeaderSearchOptions &HSOpts) { llvm::Triple::OSType os = triple.getOS(); // FIXME: temporary hack: hard-coded paths. if (triple.isOSDarwin()) { + bool IsBaseFound = true; switch (triple.getArch()) { default: break; case llvm::Triple::ppc: case llvm::Triple::ppc64: - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", - "powerpc-apple-darwin10", "", "ppc64", - triple); - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0", - "powerpc-apple-darwin10", "", "ppc64", - triple); + IsBaseFound = AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", + "powerpc-apple-darwin10", "", + "ppc64", triple); + IsBaseFound |= AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0", + "powerpc-apple-darwin10", "", + "ppc64", triple); break; case llvm::Triple::x86: case llvm::Triple::x86_64: - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", - "i686-apple-darwin10", "", "x86_64", triple); - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.0.0", - "i686-apple-darwin8", "", "", triple); + IsBaseFound = AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", + "i686-apple-darwin10", "", + "x86_64", triple); + IsBaseFound |= AddGnuCPlusPlusIncludePaths( + "/usr/include/c++/4.0.0", "i686-apple-darwin8", "", "", triple); break; case llvm::Triple::arm: case llvm::Triple::thumb: - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", - "arm-apple-darwin10", "v7", "", triple); - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", - "arm-apple-darwin10", "v6", "", triple); + IsBaseFound = AddGnuCPlusPlusIncludePaths( + "/usr/include/c++/4.2.1", "arm-apple-darwin10", "v7", "", triple); + IsBaseFound |= AddGnuCPlusPlusIncludePaths( + "/usr/include/c++/4.2.1", "arm-apple-darwin10", "v6", "", triple); break; case llvm::Triple::aarch64: - AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1", - "arm64-apple-darwin10", "", "", triple); + IsBaseFound = AddGnuCPlusPlusIncludePaths( + "/usr/include/c++/4.2.1", "arm64-apple-darwin10", "", "", triple); break; } + // Warn when compiling pure C++ / Objective-C++ only. + if (!IsBaseFound && + !(LangOpts.CUDA || LangOpts.OpenCL || LangOpts.RenderScript)) { + Headers.getDiags().Report(SourceLocation(), + diag::warn_stdlibcxx_not_found); + } return; } switch (os) { case llvm::Triple::Linux: + case llvm::Triple::Solaris: llvm_unreachable("Include management is handled in the driver."); break; case llvm::Triple::Win32: @@ -443,6 +460,7 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang, break; // Everything else continues to use this routine's logic. case llvm::Triple::Linux: + case llvm::Triple::Solaris: return; case llvm::Triple::Win32: @@ -452,8 +470,8 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang, break; } - if (Lang.CPlusPlus && HSOpts.UseStandardCXXIncludes && - HSOpts.UseStandardSystemIncludes) { + if (Lang.CPlusPlus && !Lang.AsmPreprocessor && + HSOpts.UseStandardCXXIncludes && HSOpts.UseStandardSystemIncludes) { if (HSOpts.UseLibcxx) { if (triple.isOSDarwin()) { // On Darwin, libc++ may be installed alongside the compiler in @@ -473,7 +491,7 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang, } AddPath("/usr/include/c++/v1", CXXSystem, false); } else { - AddDefaultCPlusPlusIncludePaths(triple, HSOpts); + AddDefaultCPlusPlusIncludePaths(Lang, triple, HSOpts); } } diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index d39890494323..e3f4f92b9d1e 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -93,7 +93,7 @@ static void AddImplicitIncludePTH(MacroBuilder &Builder, Preprocessor &PP, AddImplicitInclude(Builder, OriginalFile); } -/// \brief Add an implicit \#include using the original file used to generate +/// Add an implicit \#include using the original file used to generate /// a PCH file. static void AddImplicitIncludePCH(MacroBuilder &Builder, Preprocessor &PP, const PCHContainerReader &PCHContainerRdr, @@ -301,7 +301,7 @@ static const char *getLockFreeValue(unsigned TypeWidth, unsigned TypeAlign, return "1"; // "sometimes lock free" } -/// \brief Add definitions required for a smooth interaction between +/// Add definitions required for a smooth interaction between /// Objective-C++ automated reference counting and libstdc++ (4.2). static void AddObjCXXARCLibstdcxxDefines(const LangOptions &LangOpts, MacroBuilder &Builder) { @@ -426,45 +426,59 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, // OpenCL v1.0/1.1 s6.9, v1.2/2.0 s6.10: Preprocessor Directives and Macros. if (LangOpts.OpenCL) { - // OpenCL v1.0 and v1.1 do not have a predefined macro to indicate the - // language standard with which the program is compiled. __OPENCL_VERSION__ - // is for the OpenCL version supported by the OpenCL device, which is not - // necessarily the language standard with which the program is compiled. - // A shared OpenCL header file requires a macro to indicate the language - // standard. As a workaround, __OPENCL_C_VERSION__ is defined for - // OpenCL v1.0 and v1.1. - switch (LangOpts.OpenCLVersion) { - case 100: - Builder.defineMacro("__OPENCL_C_VERSION__", "100"); - break; - case 110: - Builder.defineMacro("__OPENCL_C_VERSION__", "110"); - break; - case 120: - Builder.defineMacro("__OPENCL_C_VERSION__", "120"); - break; - case 200: - Builder.defineMacro("__OPENCL_C_VERSION__", "200"); - break; - default: - llvm_unreachable("Unsupported OpenCL version"); - } - Builder.defineMacro("CL_VERSION_1_0", "100"); - Builder.defineMacro("CL_VERSION_1_1", "110"); - Builder.defineMacro("CL_VERSION_1_2", "120"); - Builder.defineMacro("CL_VERSION_2_0", "200"); + if (LangOpts.CPlusPlus) { + if (LangOpts.OpenCLCPlusPlusVersion == 100) + Builder.defineMacro("__OPENCL_CPP_VERSION__", "100"); + else + llvm_unreachable("Unsupported OpenCL C++ version"); + Builder.defineMacro("__CL_CPP_VERSION_1_0__", "100"); + } else { + // OpenCL v1.0 and v1.1 do not have a predefined macro to indicate the + // language standard with which the program is compiled. __OPENCL_VERSION__ + // is for the OpenCL version supported by the OpenCL device, which is not + // necessarily the language standard with which the program is compiled. + // A shared OpenCL header file requires a macro to indicate the language + // standard. As a workaround, __OPENCL_C_VERSION__ is defined for + // OpenCL v1.0 and v1.1. + switch (LangOpts.OpenCLVersion) { + case 100: + Builder.defineMacro("__OPENCL_C_VERSION__", "100"); + break; + case 110: + Builder.defineMacro("__OPENCL_C_VERSION__", "110"); + break; + case 120: + Builder.defineMacro("__OPENCL_C_VERSION__", "120"); + break; + case 200: + Builder.defineMacro("__OPENCL_C_VERSION__", "200"); + break; + default: + llvm_unreachable("Unsupported OpenCL version"); + } + Builder.defineMacro("CL_VERSION_1_0", "100"); + Builder.defineMacro("CL_VERSION_1_1", "110"); + Builder.defineMacro("CL_VERSION_1_2", "120"); + Builder.defineMacro("CL_VERSION_2_0", "200"); - if (TI.isLittleEndian()) - Builder.defineMacro("__ENDIAN_LITTLE__"); + if (TI.isLittleEndian()) + Builder.defineMacro("__ENDIAN_LITTLE__"); - if (LangOpts.FastRelaxedMath) - Builder.defineMacro("__FAST_RELAXED_MATH__"); + if (LangOpts.FastRelaxedMath) + Builder.defineMacro("__FAST_RELAXED_MATH__"); + } } // Not "standard" per se, but available even with the -undef flag. if (LangOpts.AsmPreprocessor) Builder.defineMacro("__ASSEMBLER__"); - if (LangOpts.CUDA) + if (LangOpts.CUDA && !LangOpts.HIP) Builder.defineMacro("__CUDA__"); + if (LangOpts.HIP) { + Builder.defineMacro("__HIP__"); + Builder.defineMacro("__HIPCC__"); + if (LangOpts.CUDAIsDevice) + Builder.defineMacro("__HIP_DEVICE_COMPILE__"); + } } /// Initialize the predefined C++ language feature test macros defined in @@ -473,78 +487,86 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts, MacroBuilder &Builder) { // C++98 features. if (LangOpts.RTTI) - Builder.defineMacro("__cpp_rtti", "199711"); + Builder.defineMacro("__cpp_rtti", "199711L"); if (LangOpts.CXXExceptions) - Builder.defineMacro("__cpp_exceptions", "199711"); + Builder.defineMacro("__cpp_exceptions", "199711L"); // 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_unicode_characters", "200704L"); + Builder.defineMacro("__cpp_raw_strings", "200710L"); + Builder.defineMacro("__cpp_unicode_literals", "200710L"); + Builder.defineMacro("__cpp_user_defined_literals", "200809L"); + Builder.defineMacro("__cpp_lambdas", "200907L"); Builder.defineMacro("__cpp_constexpr", - LangOpts.CPlusPlus17 ? "201603" : - LangOpts.CPlusPlus14 ? "201304" : "200704"); + LangOpts.CPlusPlus17 ? "201603L" : + LangOpts.CPlusPlus14 ? "201304L" : "200704"); Builder.defineMacro("__cpp_range_based_for", - LangOpts.CPlusPlus17 ? "201603" : "200907"); + LangOpts.CPlusPlus17 ? "201603L" : "200907"); Builder.defineMacro("__cpp_static_assert", - LangOpts.CPlusPlus17 ? "201411" : "200410"); - Builder.defineMacro("__cpp_decltype", "200707"); - Builder.defineMacro("__cpp_attributes", "200809"); - Builder.defineMacro("__cpp_rvalue_references", "200610"); - Builder.defineMacro("__cpp_variadic_templates", "200704"); - Builder.defineMacro("__cpp_initializer_lists", "200806"); - Builder.defineMacro("__cpp_delegating_constructors", "200604"); - Builder.defineMacro("__cpp_nsdmi", "200809"); - Builder.defineMacro("__cpp_inheriting_constructors", "201511"); - Builder.defineMacro("__cpp_ref_qualifiers", "200710"); - Builder.defineMacro("__cpp_alias_templates", "200704"); + LangOpts.CPlusPlus17 ? "201411L" : "200410"); + Builder.defineMacro("__cpp_decltype", "200707L"); + Builder.defineMacro("__cpp_attributes", "200809L"); + Builder.defineMacro("__cpp_rvalue_references", "200610L"); + Builder.defineMacro("__cpp_variadic_templates", "200704L"); + Builder.defineMacro("__cpp_initializer_lists", "200806L"); + Builder.defineMacro("__cpp_delegating_constructors", "200604L"); + Builder.defineMacro("__cpp_nsdmi", "200809L"); + Builder.defineMacro("__cpp_inheriting_constructors", "201511L"); + Builder.defineMacro("__cpp_ref_qualifiers", "200710L"); + Builder.defineMacro("__cpp_alias_templates", "200704L"); } if (LangOpts.ThreadsafeStatics) - Builder.defineMacro("__cpp_threadsafe_static_init", "200806"); + Builder.defineMacro("__cpp_threadsafe_static_init", "200806L"); // C++14 features. if (LangOpts.CPlusPlus14) { - Builder.defineMacro("__cpp_binary_literals", "201304"); - Builder.defineMacro("__cpp_digit_separators", "201309"); - 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"); + Builder.defineMacro("__cpp_binary_literals", "201304L"); + Builder.defineMacro("__cpp_digit_separators", "201309L"); + Builder.defineMacro("__cpp_init_captures", "201304L"); + Builder.defineMacro("__cpp_generic_lambdas", "201304L"); + Builder.defineMacro("__cpp_decltype_auto", "201304L"); + Builder.defineMacro("__cpp_return_type_deduction", "201304L"); + Builder.defineMacro("__cpp_aggregate_nsdmi", "201304L"); + Builder.defineMacro("__cpp_variable_templates", "201304L"); } if (LangOpts.SizedDeallocation) - Builder.defineMacro("__cpp_sized_deallocation", "201309"); + Builder.defineMacro("__cpp_sized_deallocation", "201309L"); // C++17 features. if (LangOpts.CPlusPlus17) { - Builder.defineMacro("__cpp_hex_float", "201603"); - Builder.defineMacro("__cpp_inline_variables", "201606"); - Builder.defineMacro("__cpp_noexcept_function_type", "201510"); - Builder.defineMacro("__cpp_capture_star_this", "201603"); - Builder.defineMacro("__cpp_if_constexpr", "201606"); - Builder.defineMacro("__cpp_deduction_guides", "201611"); - Builder.defineMacro("__cpp_template_auto", "201606"); - Builder.defineMacro("__cpp_namespace_attributes", "201411"); - Builder.defineMacro("__cpp_enumerator_attributes", "201411"); - Builder.defineMacro("__cpp_nested_namespace_definitions", "201411"); - Builder.defineMacro("__cpp_variadic_using", "201611"); - Builder.defineMacro("__cpp_aggregate_bases", "201603"); - Builder.defineMacro("__cpp_structured_bindings", "201606"); - Builder.defineMacro("__cpp_nontype_template_args", "201411"); - Builder.defineMacro("__cpp_fold_expressions", "201603"); + Builder.defineMacro("__cpp_hex_float", "201603L"); + Builder.defineMacro("__cpp_inline_variables", "201606L"); + Builder.defineMacro("__cpp_noexcept_function_type", "201510L"); + Builder.defineMacro("__cpp_capture_star_this", "201603L"); + Builder.defineMacro("__cpp_if_constexpr", "201606L"); + Builder.defineMacro("__cpp_deduction_guides", "201703L"); + Builder.defineMacro("__cpp_template_auto", "201606L"); // (old name) + Builder.defineMacro("__cpp_namespace_attributes", "201411L"); + Builder.defineMacro("__cpp_enumerator_attributes", "201411L"); + Builder.defineMacro("__cpp_nested_namespace_definitions", "201411L"); + Builder.defineMacro("__cpp_variadic_using", "201611L"); + Builder.defineMacro("__cpp_aggregate_bases", "201603L"); + Builder.defineMacro("__cpp_structured_bindings", "201606L"); + Builder.defineMacro("__cpp_nontype_template_args", "201411L"); + Builder.defineMacro("__cpp_fold_expressions", "201603L"); + Builder.defineMacro("__cpp_guaranteed_copy_elision", "201606L"); + Builder.defineMacro("__cpp_nontype_template_parameter_auto", "201606L"); } if (LangOpts.AlignedAllocation) - Builder.defineMacro("__cpp_aligned_new", "201606"); + Builder.defineMacro("__cpp_aligned_new", "201606L"); + if (LangOpts.RelaxedTemplateTemplateArgs) + Builder.defineMacro("__cpp_template_template_args", "201611L"); // TS features. if (LangOpts.ConceptsTS) - Builder.defineMacro("__cpp_experimental_concepts", "1"); + Builder.defineMacro("__cpp_experimental_concepts", "1L"); if (LangOpts.CoroutinesTS) Builder.defineMacro("__cpp_coroutines", "201703L"); + + // Potential future breaking changes. + if (LangOpts.Char8) + Builder.defineMacro("__cpp_char8_t", "201803L"); } static void InitializePredefinedMacros(const TargetInfo &TI, @@ -627,6 +649,19 @@ static void InitializePredefinedMacros(const TargetInfo &TI, if (LangOpts.ObjCRuntime.isNeXTFamily()) Builder.defineMacro("__NEXT_RUNTIME__"); + if (LangOpts.ObjCRuntime.getKind() == ObjCRuntime::GNUstep) { + auto version = LangOpts.ObjCRuntime.getVersion(); + std::string versionString = "1"; + // Don't rely on the tuple argument, because we can be asked to target + // later ABIs than we actually support, so clamp these values to those + // currently supported + if (version >= VersionTuple(2, 0)) + Builder.defineMacro("__OBJC_GNUSTEP_RUNTIME_ABI__", "20"); + else + Builder.defineMacro("__OBJC_GNUSTEP_RUNTIME_ABI__", + "1" + Twine(std::min(8U, version.getMinor().getValueOr(0)))); + } + if (LangOpts.ObjCRuntime.getKind() == ObjCRuntime::ObjFW) { VersionTuple tuple = LangOpts.ObjCRuntime.getVersion(); @@ -817,10 +852,6 @@ static void InitializePredefinedMacros(const TargetInfo &TI, DefineFloatMacros(Builder, "FLT", &TI.getFloatFormat(), "F"); DefineFloatMacros(Builder, "DBL", &TI.getDoubleFormat(), ""); DefineFloatMacros(Builder, "LDBL", &TI.getLongDoubleFormat(), "L"); - if (TI.hasFloat128Type()) - // FIXME: Switch away from the non-standard "Q" when we can - DefineFloatMacros(Builder, "FLT128", &TI.getFloat128Format(), "Q"); - // Define a __POINTER_WIDTH__ macro for stdint.h. Builder.defineMacro("__POINTER_WIDTH__", @@ -929,6 +960,8 @@ static void InitializePredefinedMacros(const TargetInfo &TI, InlineWidthBits)); DEFINE_LOCK_FREE_MACRO(BOOL, Bool); DEFINE_LOCK_FREE_MACRO(CHAR, Char); + if (LangOpts.Char8) + DEFINE_LOCK_FREE_MACRO(CHAR8_T, Char); // Treat char8_t like char. DEFINE_LOCK_FREE_MACRO(CHAR16_T, Char16); DEFINE_LOCK_FREE_MACRO(CHAR32_T, Char32); DEFINE_LOCK_FREE_MACRO(WCHAR_T, WChar); @@ -1011,23 +1044,25 @@ static void InitializePredefinedMacros(const TargetInfo &TI, // macro name is defined to have the decimal value yyyymm where // yyyy and mm are the year and the month designations of the // version of the OpenMP API that the implementation support. - switch (LangOpts.OpenMP) { - case 0: - break; - case 40: - Builder.defineMacro("_OPENMP", "201307"); - break; - case 45: - Builder.defineMacro("_OPENMP", "201511"); - break; - default: - // Default version is OpenMP 3.1 - Builder.defineMacro("_OPENMP", "201107"); - break; + if (!LangOpts.OpenMPSimd) { + switch (LangOpts.OpenMP) { + case 0: + break; + case 40: + Builder.defineMacro("_OPENMP", "201307"); + break; + case 45: + Builder.defineMacro("_OPENMP", "201511"); + break; + default: + // Default version is OpenMP 3.1 + Builder.defineMacro("_OPENMP", "201107"); + break; + } } // CUDA device path compilaton - if (LangOpts.CUDAIsDevice) { + if (LangOpts.CUDAIsDevice && !LangOpts.HIP) { // The CUDA_ARCH value is set for the GPU target specified in the NVPTX // backend's target defines. Builder.defineMacro("__CUDA_ARCH__"); diff --git a/lib/Frontend/LayoutOverrideSource.cpp b/lib/Frontend/LayoutOverrideSource.cpp index 06e9a7dc50b4..93e07eb81f72 100644 --- a/lib/Frontend/LayoutOverrideSource.cpp +++ b/lib/Frontend/LayoutOverrideSource.cpp @@ -15,7 +15,7 @@ using namespace clang; -/// \brief Parse a simple identifier. +/// Parse a simple identifier. static std::string parseName(StringRef S) { if (S.empty() || !isIdentifierHead(S[0])) return ""; diff --git a/lib/Frontend/ModuleDependencyCollector.cpp b/lib/Frontend/ModuleDependencyCollector.cpp index ede12aab6e69..25cad8be6d00 100644 --- a/lib/Frontend/ModuleDependencyCollector.cpp +++ b/lib/Frontend/ModuleDependencyCollector.cpp @@ -16,6 +16,7 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Serialization/ASTReader.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/Config/llvm-config.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" @@ -49,7 +50,8 @@ struct ModuleDependencyPPCallbacks : public PPCallbacks { StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File, StringRef SearchPath, StringRef RelativePath, - const Module *Imported) override { + const Module *Imported, + SrcMgr::CharacteristicKind FileType) override { if (!File) return; Collector.addFile(File->getName()); @@ -135,7 +137,7 @@ static bool isCaseSensitivePath(StringRef Path) { // Change path to all upper case and ask for its real path, if the latter // exists and is equal to Path, it's not case sensitive. Default to case - // sensitive in the absense of realpath, since this is what the VFSWriter + // sensitive in the absence of realpath, since this is what the VFSWriter // already expects when sensitivity isn't setup. for (auto &C : Path) UpperDest.push_back(toUppercase(C)); diff --git a/lib/Frontend/MultiplexConsumer.cpp b/lib/Frontend/MultiplexConsumer.cpp index 04a8f6c1cdfb..df36c88ec38e 100644 --- a/lib/Frontend/MultiplexConsumer.cpp +++ b/lib/Frontend/MultiplexConsumer.cpp @@ -16,35 +16,11 @@ #include "clang/Frontend/MultiplexConsumer.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/DeclGroup.h" -#include "clang/Serialization/ASTDeserializationListener.h" using namespace clang; namespace clang { -// This ASTDeserializationListener forwards its notifications to a set of -// child listeners. -class MultiplexASTDeserializationListener - : public ASTDeserializationListener { -public: - // Does NOT take ownership of the elements in L. - MultiplexASTDeserializationListener( - const std::vector<ASTDeserializationListener*>& L); - void ReaderInitialized(ASTReader *Reader) override; - void IdentifierRead(serialization::IdentID ID, - IdentifierInfo *II) override; - void MacroRead(serialization::MacroID ID, MacroInfo *MI) override; - void TypeRead(serialization::TypeIdx Idx, QualType T) override; - void DeclRead(serialization::DeclID ID, const Decl *D) override; - void SelectorRead(serialization::SelectorID iD, Selector Sel) override; - void MacroDefinitionRead(serialization::PreprocessedEntityID, - MacroDefinitionRecord *MD) override; - void ModuleRead(serialization::SubmoduleID ID, Module *Mod) override; - -private: - std::vector<ASTDeserializationListener *> Listeners; -}; - MultiplexASTDeserializationListener::MultiplexASTDeserializationListener( const std::vector<ASTDeserializationListener*>& L) : Listeners(L) { diff --git a/lib/Frontend/PCHContainerOperations.cpp b/lib/Frontend/PCHContainerOperations.cpp index eebebf327a19..340e8ce63ff4 100644 --- a/lib/Frontend/PCHContainerOperations.cpp +++ b/lib/Frontend/PCHContainerOperations.cpp @@ -25,7 +25,7 @@ PCHContainerReader::~PCHContainerReader() {} namespace { -/// \brief A PCHContainerGenerator that writes out the PCH to a flat file. +/// A PCHContainerGenerator that writes out the PCH to a flat file. class RawPCHContainerGenerator : public ASTConsumer { std::shared_ptr<PCHBuffer> Buffer; std::unique_ptr<raw_pwrite_stream> OS; diff --git a/lib/Frontend/PrecompiledPreamble.cpp b/lib/Frontend/PrecompiledPreamble.cpp index 7e1323fd83bb..30ae2db26d86 100644 --- a/lib/Frontend/PrecompiledPreamble.cpp +++ b/lib/Frontend/PrecompiledPreamble.cpp @@ -40,7 +40,7 @@ namespace { StringRef getInMemoryPreamblePath() { #if defined(LLVM_ON_UNIX) return "/__clang_tmp/___clang_inmemory_preamble___"; -#elif defined(LLVM_ON_WIN32) +#elif defined(_WIN32) return "C:\\__clang_tmp\\___clang_inmemory_preamble___"; #else #warning "Unknown platform. Defaulting to UNIX-style paths for in-memory PCHs" @@ -63,6 +63,16 @@ createVFSOverlayForPreamblePCH(StringRef PCHFilename, return Overlay; } +class PreambleDependencyCollector : public DependencyCollector { +public: + // We want to collect all dependencies for correctness. Avoiding the real + // system dependencies (e.g. stl from /usr/lib) would probably be a good idea, + // but there is no way to distinguish between those and the ones that can be + // spuriously added by '-isystem' (e.g. to suppress warnings from those + // headers). + bool needSystemDependencies() override { return true; } +}; + /// Keeps a track of files to be deleted in destructor. class TemporaryFiles { public: @@ -303,8 +313,6 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build( VFS = createVFSFromCompilerInvocation(Clang->getInvocation(), Diagnostics, VFS); - if (!VFS) - return BuildPreambleError::CouldntCreateVFSOverlay; // Create a file manager object to provide access to and cache the filesystem. Clang->setFileManager(new FileManager(Clang->getFileSystemOpts(), VFS)); @@ -313,7 +321,7 @@ llvm::ErrorOr<PrecompiledPreamble> PrecompiledPreamble::Build( Clang->setSourceManager( new SourceManager(Diagnostics, Clang->getFileManager())); - auto PreambleDepCollector = std::make_shared<DependencyCollector>(); + auto PreambleDepCollector = std::make_shared<PreambleDependencyCollector>(); Clang->addDependencyCollector(PreambleDepCollector); // Remap the main source file to the preamble buffer. @@ -485,20 +493,15 @@ bool PrecompiledPreamble::CanReuse(const CompilerInvocation &Invocation, void PrecompiledPreamble::AddImplicitPreamble( CompilerInvocation &CI, IntrusiveRefCntPtr<vfs::FileSystem> &VFS, llvm::MemoryBuffer *MainFileBuffer) const { - assert(VFS && "VFS must not be null"); - - auto &PreprocessorOpts = CI.getPreprocessorOpts(); - - // Remap main file to point to MainFileBuffer. - auto MainFilePath = CI.getFrontendOpts().Inputs[0].getFile(); - PreprocessorOpts.addRemappedFile(MainFilePath, MainFileBuffer); - - // Configure ImpicitPCHInclude. - PreprocessorOpts.PrecompiledPreambleBytes.first = PreambleBytes.size(); - PreprocessorOpts.PrecompiledPreambleBytes.second = PreambleEndsAtStartOfLine; - PreprocessorOpts.DisablePCHValidation = true; + PreambleBounds Bounds(PreambleBytes.size(), PreambleEndsAtStartOfLine); + configurePreamble(Bounds, CI, VFS, MainFileBuffer); +} - setupPreambleStorage(Storage, PreprocessorOpts, VFS); +void PrecompiledPreamble::OverridePreamble( + CompilerInvocation &CI, IntrusiveRefCntPtr<vfs::FileSystem> &VFS, + llvm::MemoryBuffer *MainFileBuffer) const { + auto Bounds = ComputePreambleBounds(*CI.getLangOpts(), MainFileBuffer, 0); + configurePreamble(Bounds, CI, VFS, MainFileBuffer); } PrecompiledPreamble::PrecompiledPreamble( @@ -681,6 +684,27 @@ PrecompiledPreamble::PreambleFileHash::createForMemoryBuffer( return Result; } +void PrecompiledPreamble::configurePreamble( + PreambleBounds Bounds, CompilerInvocation &CI, + IntrusiveRefCntPtr<vfs::FileSystem> &VFS, + llvm::MemoryBuffer *MainFileBuffer) const { + assert(VFS); + + auto &PreprocessorOpts = CI.getPreprocessorOpts(); + + // Remap main file to point to MainFileBuffer. + auto MainFilePath = CI.getFrontendOpts().Inputs[0].getFile(); + PreprocessorOpts.addRemappedFile(MainFilePath, MainFileBuffer); + + // Configure ImpicitPCHInclude. + PreprocessorOpts.PrecompiledPreambleBytes.first = Bounds.Size; + PreprocessorOpts.PrecompiledPreambleBytes.second = + Bounds.PreambleEndsAtStartOfLine; + PreprocessorOpts.DisablePCHValidation = true; + + setupPreambleStorage(Storage, PreprocessorOpts, VFS); +} + void PrecompiledPreamble::setupPreambleStorage( const PCHStorage &Storage, PreprocessorOptions &PreprocessorOpts, IntrusiveRefCntPtr<vfs::FileSystem> &VFS) { @@ -740,8 +764,6 @@ std::string BuildPreambleErrorCategory::message(int condition) const { return "Could not create temporary file for PCH"; case BuildPreambleError::CouldntCreateTargetInfo: return "CreateTargetInfo() return null"; - case BuildPreambleError::CouldntCreateVFSOverlay: - return "Could not create VFS Overlay"; case BuildPreambleError::BeginSourceFileFailed: return "BeginSourceFile() return an error"; case BuildPreambleError::CouldntEmitPCH: diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index 2e023294f1e8..1b35b32656e7 100644 --- a/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/lib/Frontend/PrintPreprocessedOutput.cpp @@ -130,7 +130,8 @@ public: StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File, StringRef SearchPath, StringRef RelativePath, - const Module *Imported) override; + const Module *Imported, + SrcMgr::CharacteristicKind FileType) override; void Ident(SourceLocation Loc, StringRef str) override; void PragmaMessage(SourceLocation Loc, StringRef Namespace, PragmaMessageKind Kind, StringRef Str) override; @@ -320,15 +321,17 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc, } } -void PrintPPOutputPPCallbacks::InclusionDirective(SourceLocation HashLoc, - const Token &IncludeTok, - StringRef FileName, - bool IsAngled, - CharSourceRange FilenameRange, - const FileEntry *File, - StringRef SearchPath, - StringRef RelativePath, - const Module *Imported) { +void PrintPPOutputPPCallbacks::InclusionDirective( + SourceLocation HashLoc, + const Token &IncludeTok, + StringRef FileName, + bool IsAngled, + CharSourceRange FilenameRange, + const FileEntry *File, + StringRef SearchPath, + StringRef RelativePath, + const Module *Imported, + SrcMgr::CharacteristicKind FileType) { // In -dI mode, dump #include directives prior to dumping their content or // interpretation. if (DumpIncludeDirectives) { @@ -752,7 +755,7 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, } else if (Tok.isLiteral() && !Tok.needsCleaning() && Tok.getLiteralData()) { OS.write(Tok.getLiteralData(), Tok.getLength()); - } else if (Tok.getLength() < 256) { + } else if (Tok.getLength() < llvm::array_lengthof(Buffer)) { const char *TokPtr = Buffer; unsigned Len = PP.getSpelling(Tok, TokPtr); OS.write(TokPtr, Len); diff --git a/lib/Frontend/Rewrite/FixItRewriter.cpp b/lib/Frontend/Rewrite/FixItRewriter.cpp index dc787ac9557c..64785e301236 100644 --- a/lib/Frontend/Rewrite/FixItRewriter.cpp +++ b/lib/Frontend/Rewrite/FixItRewriter.cpp @@ -1,4 +1,4 @@ -//===--- FixItRewriter.cpp - Fix-It Rewriter Diagnostic Client --*- C++ -*-===// +//===- FixItRewriter.cpp - Fix-It Rewriter Diagnostic Client --------------===// // // The LLVM Compiler Infrastructure // @@ -14,28 +14,32 @@ //===----------------------------------------------------------------------===// #include "clang/Rewrite/Frontend/FixItRewriter.h" +#include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Edit/Commit.h" #include "clang/Edit/EditsReceiver.h" #include "clang/Frontend/FrontendDiagnostic.h" -#include "llvm/Support/Path.h" +#include "clang/Rewrite/Core/RewriteBuffer.h" +#include "clang/Rewrite/Core/Rewriter.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/raw_ostream.h" #include <cstdio> #include <memory> +#include <string> +#include <system_error> +#include <utility> using namespace clang; FixItRewriter::FixItRewriter(DiagnosticsEngine &Diags, SourceManager &SourceMgr, const LangOptions &LangOpts, FixItOptions *FixItOpts) - : Diags(Diags), - Editor(SourceMgr, LangOpts), - Rewrite(SourceMgr, LangOpts), - FixItOpts(FixItOpts), - NumFailures(0), - PrevDiagSilenced(false) { + : Diags(Diags), Editor(SourceMgr, LangOpts), Rewrite(SourceMgr, LangOpts), + FixItOpts(FixItOpts) { Owner = Diags.takeClient(); Client = Diags.getClient(); Diags.setClient(this, false); @@ -59,20 +63,21 @@ class RewritesReceiver : public edit::EditsReceiver { Rewriter &Rewrite; public: - RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { } + RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) {} void insert(SourceLocation loc, StringRef text) override { Rewrite.InsertText(loc, text); } + void replace(CharSourceRange range, StringRef text) override { Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text); } }; -} +} // namespace bool FixItRewriter::WriteFixedFiles( - std::vector<std::pair<std::string, std::string> > *RewrittenFiles) { + std::vector<std::pair<std::string, std::string>> *RewrittenFiles) { if (NumFailures > 0 && !FixItOpts->FixWhatYouCan) { Diag(FullSourceLoc(), diag::warn_fixit_no_changes); return true; @@ -189,7 +194,7 @@ void FixItRewriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, Diag(Info.getLocation(), diag::note_fixit_applied); } -/// \brief Emit a diagnostic via the adapted diagnostic client. +/// Emit a diagnostic via the adapted diagnostic client. void FixItRewriter::Diag(SourceLocation Loc, unsigned DiagID) { // When producing this diagnostic, we temporarily bypass ourselves, // clear out any current diagnostic, and let the downstream client @@ -200,4 +205,4 @@ void FixItRewriter::Diag(SourceLocation Loc, unsigned DiagID) { Diags.setClient(this, false); } -FixItOptions::~FixItOptions() {} +FixItOptions::~FixItOptions() = default; diff --git a/lib/Frontend/Rewrite/HTMLPrint.cpp b/lib/Frontend/Rewrite/HTMLPrint.cpp index 11e431de0a31..34ee9673cc54 100644 --- a/lib/Frontend/Rewrite/HTMLPrint.cpp +++ b/lib/Frontend/Rewrite/HTMLPrint.cpp @@ -86,8 +86,7 @@ void HTMLPrinter::HandleTranslationUnit(ASTContext &Ctx) { // Emit the HTML. const RewriteBuffer &RewriteBuf = R.getEditBuffer(FID); - char *Buffer = (char*)malloc(RewriteBuf.size()); - std::copy(RewriteBuf.begin(), RewriteBuf.end(), Buffer); - Out->write(Buffer, RewriteBuf.size()); - free(Buffer); + std::unique_ptr<char[]> Buffer(new char[RewriteBuf.size()]); + std::copy(RewriteBuf.begin(), RewriteBuf.end(), Buffer.get()); + Out->write(Buffer.get(), RewriteBuf.size()); } diff --git a/lib/Frontend/Rewrite/InclusionRewriter.cpp b/lib/Frontend/Rewrite/InclusionRewriter.cpp index e0477069b340..1631eccd7013 100644 --- a/lib/Frontend/Rewrite/InclusionRewriter.cpp +++ b/lib/Frontend/Rewrite/InclusionRewriter.cpp @@ -32,8 +32,10 @@ class InclusionRewriter : public PPCallbacks { struct IncludedFile { FileID Id; SrcMgr::CharacteristicKind FileType; - IncludedFile(FileID Id, SrcMgr::CharacteristicKind FileType) - : Id(Id), FileType(FileType) {} + const DirectoryLookup *DirLookup; + IncludedFile(FileID Id, SrcMgr::CharacteristicKind FileType, + const DirectoryLookup *DirLookup) + : Id(Id), FileType(FileType), DirLookup(DirLookup) {} }; Preprocessor &PP; ///< Used to find inclusion directives. SourceManager &SM; ///< Used to read and manage source files. @@ -54,7 +56,8 @@ class InclusionRewriter : public PPCallbacks { public: InclusionRewriter(Preprocessor &PP, raw_ostream &OS, bool ShowLineMarkers, bool UseLineDirectives); - void Process(FileID FileId, SrcMgr::CharacteristicKind FileType); + void Process(FileID FileId, SrcMgr::CharacteristicKind FileType, + const DirectoryLookup *DirLookup); void setPredefinesBuffer(const llvm::MemoryBuffer *Buf) { PredefinesBuffer = Buf; } @@ -74,7 +77,8 @@ private: StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File, StringRef SearchPath, StringRef RelativePath, - const Module *Imported) override; + const Module *Imported, + SrcMgr::CharacteristicKind FileType) override; void WriteLineInfo(StringRef Filename, int Line, SrcMgr::CharacteristicKind FileType, StringRef Extra = StringRef()); @@ -156,8 +160,9 @@ void InclusionRewriter::FileChanged(SourceLocation Loc, // we didn't reach this file (eg: the main file) via an inclusion directive return; FileID Id = FullSourceLoc(Loc, SM).getFileID(); - auto P = FileIncludes.insert(std::make_pair( - LastInclusionLocation.getRawEncoding(), IncludedFile(Id, NewFileType))); + auto P = FileIncludes.insert( + std::make_pair(LastInclusionLocation.getRawEncoding(), + IncludedFile(Id, NewFileType, PP.GetCurDirLookup()))); (void)P; assert(P.second && "Unexpected revisitation of the same include directive"); LastInclusionLocation = SourceLocation(); @@ -188,7 +193,8 @@ void InclusionRewriter::InclusionDirective(SourceLocation HashLoc, const FileEntry * /*File*/, StringRef /*SearchPath*/, StringRef /*RelativePath*/, - const Module *Imported) { + const Module *Imported, + SrcMgr::CharacteristicKind FileType){ if (Imported) { auto P = ModuleIncludes.insert( std::make_pair(HashLoc.getRawEncoding(), Imported)); @@ -408,7 +414,7 @@ bool InclusionRewriter::HandleHasInclude( Includers.push_back(std::make_pair(FileEnt, FileEnt->getDir())); // FIXME: Why don't we call PP.LookupFile here? const FileEntry *File = PP.getHeaderSearchInfo().LookupFile( - Filename, SourceLocation(), isAngled, nullptr, CurDir, Includers, nullptr, + Filename, SourceLocation(), isAngled, Lookup, CurDir, Includers, nullptr, nullptr, nullptr, nullptr, nullptr); FileExists = File != nullptr; @@ -418,7 +424,8 @@ bool InclusionRewriter::HandleHasInclude( /// Use a raw lexer to analyze \p FileId, incrementally copying parts of it /// and including content of included files recursively. void InclusionRewriter::Process(FileID FileId, - SrcMgr::CharacteristicKind FileType) { + SrcMgr::CharacteristicKind FileType, + const DirectoryLookup *DirLookup) { bool Invalid; const MemoryBuffer &FromFile = *SM.getBuffer(FileId, &Invalid); assert(!Invalid && "Attempting to process invalid inclusion"); @@ -475,7 +482,7 @@ void InclusionRewriter::Process(FileID FileId, << Mod->getFullModuleName(true) << "\n"; // Include and recursively process the file. - Process(Inc->Id, Inc->FileType); + Process(Inc->Id, Inc->FileType, Inc->DirLookup); if (Mod) OS << "#pragma clang module end /*" @@ -532,11 +539,10 @@ void InclusionRewriter::Process(FileID FileId, // Rewrite __has_include_next(x) } else if (RawToken.getIdentifierInfo()->isStr( "__has_include_next")) { - const DirectoryLookup *Lookup = PP.GetCurDirLookup(); - if (Lookup) - ++Lookup; + if (DirLookup) + ++DirLookup; - if (!HandleHasInclude(FileId, RawLex, Lookup, RawToken, + if (!HandleHasInclude(FileId, RawLex, DirLookup, RawToken, HasFile)) continue; } else { @@ -621,7 +627,7 @@ void clang::RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS, Rewrite->handleModuleBegin(Tok); } while (Tok.isNot(tok::eof)); Rewrite->setPredefinesBuffer(SM.getBuffer(PP.getPredefinesFileID())); - Rewrite->Process(PP.getPredefinesFileID(), SrcMgr::C_User); - Rewrite->Process(SM.getMainFileID(), SrcMgr::C_User); + Rewrite->Process(PP.getPredefinesFileID(), SrcMgr::C_User, nullptr); + Rewrite->Process(SM.getMainFileID(), SrcMgr::C_User, nullptr); OS->flush(); } diff --git a/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/lib/Frontend/Rewrite/RewriteModernObjC.cpp index 1954b24aedad..52b979c85f15 100644 --- a/lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ b/lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -1714,7 +1714,7 @@ Stmt *RewriteModernObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, else { DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement()); elementName = DR->getDecl()->getName(); - ValueDecl *VD = cast<ValueDecl>(DR->getDecl()); + ValueDecl *VD = DR->getDecl(); if (VD->getType()->isObjCQualifiedIdType() || VD->getType()->isObjCQualifiedInterfaceType()) // Simply use 'id' for all qualified types. @@ -2590,7 +2590,7 @@ Stmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf, Context->getPointerType(DRE->getType()), VK_RValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); // cast to NSConstantString * CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(), CK_CPointerToObjCPointerCast, Unop); @@ -3295,7 +3295,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp, SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); SuperRep = NoTypeInfoCStyleCastExpr(Context, Context->getPointerType(superType), CK_BitCast, SuperRep); @@ -3313,7 +3313,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp, SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); } MsgExprs.push_back(SuperRep); break; @@ -3389,7 +3389,7 @@ Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp, SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); SuperRep = NoTypeInfoCStyleCastExpr(Context, Context->getPointerType(superType), CK_BitCast, SuperRep); @@ -4720,7 +4720,7 @@ Stmt *RewriteModernObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) { return DRE; Expr *Exp = new (Context) UnaryOperator(DRE, UO_Deref, DRE->getType(), VK_LValue, OK_Ordinary, - DRE->getLocation()); + DRE->getLocation(), false); // Need parens to enforce precedence. ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), Exp); @@ -5314,7 +5314,7 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp, UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_RValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); InitExprs.push_back(DescRefExpr); // Add initializers for any closure decl refs. @@ -5332,7 +5332,8 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp, QualType QT = (*I)->getType(); QT = Context->getPointerType(QT); Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue, - OK_Ordinary, SourceLocation()); + OK_Ordinary, SourceLocation(), + false); } } else if (isTopLevelBlockPointerType((*I)->getType())) { FD = SynthBlockInitFunctionDecl((*I)->getName()); @@ -5348,7 +5349,8 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp, QualType QT = (*I)->getType(); QT = Context->getPointerType(QT); Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue, - OK_Ordinary, SourceLocation()); + OK_Ordinary, SourceLocation(), + false); } } @@ -5388,7 +5390,8 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp, if (!isNestedCapturedVar) Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, Context->getPointerType(Exp->getType()), - VK_RValue, OK_Ordinary, SourceLocation()); + VK_RValue, OK_Ordinary, SourceLocation(), + false); Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp); InitExprs.push_back(Exp); } @@ -5414,7 +5417,7 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp, NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf, Context->getPointerType(NewRep->getType()), - VK_RValue, OK_Ordinary, SourceLocation()); + VK_RValue, OK_Ordinary, SourceLocation(), false); NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast, NewRep); // Put Paren around the call. @@ -6744,9 +6747,9 @@ static void Write_IvarOffsetVar(RewriteModernObjC &RewriteObj, if (Ivar->getAccessControl() == ObjCIvarDecl::Private || Ivar->getAccessControl() == ObjCIvarDecl::Package || Class->getVisibility() == HiddenVisibility) - Visibility shoud be: HiddenVisibility; + Visibility should be: HiddenVisibility; else - Visibility shoud be: DefaultVisibility; + Visibility should be: DefaultVisibility; */ Result += "\n"; @@ -7558,7 +7561,7 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { Expr *Exp = new (Context) UnaryOperator(castExpr, UO_Deref, IvarT, VK_LValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); PE = new (Context) ParenExpr(OldRange.getBegin(), OldRange.getEnd(), Exp); diff --git a/lib/Frontend/Rewrite/RewriteObjC.cpp b/lib/Frontend/Rewrite/RewriteObjC.cpp index 096b81bc3f08..9938f89eb869 100644 --- a/lib/Frontend/Rewrite/RewriteObjC.cpp +++ b/lib/Frontend/Rewrite/RewriteObjC.cpp @@ -1502,7 +1502,7 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, else { DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement()); elementName = DR->getDecl()->getName(); - ValueDecl *VD = cast<ValueDecl>(DR->getDecl()); + ValueDecl *VD = DR->getDecl(); if (VD->getType()->isObjCQualifiedIdType() || VD->getType()->isObjCQualifiedInterfaceType()) // Simply use 'id' for all qualified types. @@ -2511,7 +2511,7 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf, Context->getPointerType(DRE->getType()), VK_RValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); // cast to NSConstantString * CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(), CK_CPointerToObjCPointerCast, Unop); @@ -2712,7 +2712,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); SuperRep = NoTypeInfoCStyleCastExpr(Context, Context->getPointerType(superType), CK_BitCast, SuperRep); @@ -2730,7 +2730,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); } MsgExprs.push_back(SuperRep); break; @@ -2806,7 +2806,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, Context->getPointerType(SuperRep->getType()), VK_RValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); SuperRep = NoTypeInfoCStyleCastExpr(Context, Context->getPointerType(superType), CK_BitCast, SuperRep); @@ -3045,7 +3045,7 @@ Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) { VK_LValue, SourceLocation()); Expr *DerefExpr = new (Context) UnaryOperator(DRE, UO_AddrOf, Context->getPointerType(DRE->getType()), - VK_RValue, OK_Ordinary, SourceLocation()); + VK_RValue, OK_Ordinary, SourceLocation(), false); CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(), CK_BitCast, DerefExpr); @@ -3875,7 +3875,7 @@ Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) { return DRE; Expr *Exp = new (Context) UnaryOperator(DRE, UO_Deref, DRE->getType(), VK_LValue, OK_Ordinary, - DRE->getLocation()); + DRE->getLocation(), false); // Need parens to enforce precedence. ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), Exp); @@ -4438,7 +4438,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_RValue, OK_Ordinary, - SourceLocation()); + SourceLocation(), false); InitExprs.push_back(DescRefExpr); // Add initializers for any closure decl refs. @@ -4456,7 +4456,8 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, QualType QT = (*I)->getType(); QT = Context->getPointerType(QT); Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue, - OK_Ordinary, SourceLocation()); + OK_Ordinary, SourceLocation(), + false); } } else if (isTopLevelBlockPointerType((*I)->getType())) { FD = SynthBlockInitFunctionDecl((*I)->getName()); @@ -4472,7 +4473,8 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, QualType QT = (*I)->getType(); QT = Context->getPointerType(QT); Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue, - OK_Ordinary, SourceLocation()); + OK_Ordinary, SourceLocation(), + false); } } InitExprs.push_back(Exp); @@ -4509,9 +4511,9 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, // captured nested byref variable has its address passed. Do not take // its address again. if (!isNestedCapturedVar) - Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, - Context->getPointerType(Exp->getType()), - VK_RValue, OK_Ordinary, SourceLocation()); + Exp = new (Context) UnaryOperator( + Exp, UO_AddrOf, Context->getPointerType(Exp->getType()), VK_RValue, + OK_Ordinary, SourceLocation(), false); Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp); InitExprs.push_back(Exp); } @@ -4529,7 +4531,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, FType, VK_LValue, SourceLocation()); NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf, Context->getPointerType(NewRep->getType()), - VK_RValue, OK_Ordinary, SourceLocation()); + VK_RValue, OK_Ordinary, SourceLocation(), false); NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast, NewRep); BlockDeclRefs.clear(); diff --git a/lib/Frontend/SerializedDiagnosticPrinter.cpp b/lib/Frontend/SerializedDiagnosticPrinter.cpp index 7666fe10b381..ca60c4812f72 100644 --- a/lib/Frontend/SerializedDiagnosticPrinter.cpp +++ b/lib/Frontend/SerializedDiagnosticPrinter.cpp @@ -162,131 +162,131 @@ public: void finish() override; private: - /// \brief Build a DiagnosticsEngine to emit diagnostics about the diagnostics + /// Build a DiagnosticsEngine to emit diagnostics about the diagnostics DiagnosticsEngine *getMetaDiags(); - /// \brief Remove old copies of the serialized diagnostics. This is necessary + /// Remove old copies of the serialized diagnostics. This is necessary /// so that we can detect when subprocesses write diagnostics that we should /// merge into our own. void RemoveOldDiagnostics(); - /// \brief Emit the preamble for the serialized diagnostics. + /// Emit the preamble for the serialized diagnostics. void EmitPreamble(); - /// \brief Emit the BLOCKINFO block. + /// Emit the BLOCKINFO block. void EmitBlockInfoBlock(); - /// \brief Emit the META data block. + /// Emit the META data block. void EmitMetaBlock(); - /// \brief Start a DIAG block. + /// Start a DIAG block. void EnterDiagBlock(); - /// \brief End a DIAG block. + /// End a DIAG block. void ExitDiagBlock(); - /// \brief Emit a DIAG record. + /// Emit a DIAG record. void EmitDiagnosticMessage(FullSourceLoc Loc, PresumedLoc PLoc, DiagnosticsEngine::Level Level, StringRef Message, DiagOrStoredDiag D); - /// \brief Emit FIXIT and SOURCE_RANGE records for a diagnostic. + /// Emit FIXIT and SOURCE_RANGE records for a diagnostic. void EmitCodeContext(SmallVectorImpl<CharSourceRange> &Ranges, ArrayRef<FixItHint> Hints, const SourceManager &SM); - /// \brief Emit a record for a CharSourceRange. + /// Emit a record for a CharSourceRange. void EmitCharSourceRange(CharSourceRange R, const SourceManager &SM); - /// \brief Emit the string information for the category. + /// Emit the string information for the category. unsigned getEmitCategory(unsigned category = 0); - /// \brief Emit the string information for diagnostic flags. + /// Emit the string information for diagnostic flags. unsigned getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel, unsigned DiagID = 0); unsigned getEmitDiagnosticFlag(StringRef DiagName); - /// \brief Emit (lazily) the file string and retrieved the file identifier. + /// Emit (lazily) the file string and retrieved the file identifier. unsigned getEmitFile(const char *Filename); - /// \brief Add SourceLocation information the specified record. + /// Add SourceLocation information the specified record. void AddLocToRecord(FullSourceLoc Loc, PresumedLoc PLoc, RecordDataImpl &Record, unsigned TokSize = 0); - /// \brief Add SourceLocation information the specified record. + /// Add SourceLocation information the specified record. void AddLocToRecord(FullSourceLoc Loc, RecordDataImpl &Record, unsigned TokSize = 0) { AddLocToRecord(Loc, Loc.hasManager() ? Loc.getPresumedLoc() : PresumedLoc(), Record, TokSize); } - /// \brief Add CharSourceRange information the specified record. + /// Add CharSourceRange information the specified record. void AddCharSourceRangeToRecord(CharSourceRange R, RecordDataImpl &Record, const SourceManager &SM); - /// \brief Language options, which can differ from one clone of this client + /// Language options, which can differ from one clone of this client /// to another. const LangOptions *LangOpts; - /// \brief Whether this is the original instance (rather than one of its + /// Whether this is the original instance (rather than one of its /// clones), responsible for writing the file at the end. bool OriginalInstance; - /// \brief Whether this instance should aggregate diagnostics that are + /// Whether this instance should aggregate diagnostics that are /// generated from child processes. bool MergeChildRecords; - /// \brief State that is shared among the various clones of this diagnostic + /// State that is shared among the various clones of this diagnostic /// consumer. struct SharedState { SharedState(StringRef File, DiagnosticOptions *Diags) : DiagOpts(Diags), Stream(Buffer), OutputFile(File.str()), EmittedAnyDiagBlocks(false) {} - /// \brief Diagnostic options. + /// Diagnostic options. IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; - /// \brief The byte buffer for the serialized content. + /// The byte buffer for the serialized content. SmallString<1024> Buffer; - /// \brief The BitStreamWriter for the serialized diagnostics. + /// The BitStreamWriter for the serialized diagnostics. llvm::BitstreamWriter Stream; - /// \brief The name of the diagnostics file. + /// The name of the diagnostics file. std::string OutputFile; - /// \brief The set of constructed record abbreviations. + /// The set of constructed record abbreviations. AbbreviationMap Abbrevs; - /// \brief A utility buffer for constructing record content. + /// A utility buffer for constructing record content. RecordData Record; - /// \brief A text buffer for rendering diagnostic text. + /// A text buffer for rendering diagnostic text. SmallString<256> diagBuf; - /// \brief The collection of diagnostic categories used. + /// The collection of diagnostic categories used. llvm::DenseSet<unsigned> Categories; - /// \brief The collection of files used. + /// The collection of files used. llvm::DenseMap<const char *, unsigned> Files; typedef llvm::DenseMap<const void *, std::pair<unsigned, StringRef> > DiagFlagsTy; - /// \brief Map for uniquing strings. + /// Map for uniquing strings. DiagFlagsTy DiagFlags; - /// \brief Whether we have already started emission of any DIAG blocks. Once + /// Whether we have already started emission of any DIAG blocks. Once /// this becomes \c true, we never close a DIAG block until we know that we're /// starting another one or we're done. bool EmittedAnyDiagBlocks; - /// \brief Engine for emitting diagnostics about the diagnostics. + /// Engine for emitting diagnostics about the diagnostics. std::unique_ptr<DiagnosticsEngine> MetaDiagnostics; }; - /// \brief State shared among the various clones of this diagnostic consumer. + /// State shared among the various clones of this diagnostic consumer. std::shared_ptr<SharedState> State; }; } // end anonymous namespace @@ -305,7 +305,7 @@ create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords) { // Serialization methods. //===----------------------------------------------------------------------===// -/// \brief Emits a block ID in the BLOCKINFO block. +/// Emits a block ID in the BLOCKINFO block. static void EmitBlockID(unsigned ID, const char *Name, llvm::BitstreamWriter &Stream, RecordDataImpl &Record) { @@ -325,7 +325,7 @@ static void EmitBlockID(unsigned ID, const char *Name, Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record); } -/// \brief Emits a record ID in the BLOCKINFO block. +/// Emits a record ID in the BLOCKINFO block. static void EmitRecordID(unsigned ID, const char *Name, llvm::BitstreamWriter &Stream, RecordDataImpl &Record){ @@ -395,7 +395,7 @@ void SDiagsWriter::EmitCharSourceRange(CharSourceRange R, State->Record); } -/// \brief Emits the preamble of the diagnostics file. +/// Emits the preamble of the diagnostics file. void SDiagsWriter::EmitPreamble() { // Emit the file header. State->Stream.Emit((unsigned)'D', 8); @@ -462,7 +462,7 @@ void SDiagsWriter::EmitBlockInfoBlock() { Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Diagnostc text. Abbrevs.set(RECORD_DIAG, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev)); - // Emit abbrevation for RECORD_CATEGORY. + // Emit abbreviation for RECORD_CATEGORY. Abbrev = std::make_shared<BitCodeAbbrev>(); Abbrev->Add(BitCodeAbbrevOp(RECORD_CATEGORY)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Category ID. @@ -470,7 +470,7 @@ void SDiagsWriter::EmitBlockInfoBlock() { Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Category text. Abbrevs.set(RECORD_CATEGORY, Stream.EmitBlockInfoAbbrev(BLOCK_DIAG, Abbrev)); - // Emit abbrevation for RECORD_SOURCE_RANGE. + // Emit abbreviation for RECORD_SOURCE_RANGE. Abbrev = std::make_shared<BitCodeAbbrev>(); Abbrev->Add(BitCodeAbbrevOp(RECORD_SOURCE_RANGE)); AddRangeLocationAbbrev(*Abbrev); diff --git a/lib/Frontend/SerializedDiagnosticReader.cpp b/lib/Frontend/SerializedDiagnosticReader.cpp index 08b7087fbad6..458717819c41 100644 --- a/lib/Frontend/SerializedDiagnosticReader.cpp +++ b/lib/Frontend/SerializedDiagnosticReader.cpp @@ -1,4 +1,4 @@ -//===--- SerializedDiagnosticReader.cpp - Reads diagnostics ---------------===// +//===- SerializedDiagnosticReader.cpp - Reads diagnostics -----------------===// // // The LLVM Compiler Infrastructure // @@ -9,11 +9,22 @@ #include "clang/Frontend/SerializedDiagnosticReader.h" #include "clang/Basic/FileManager.h" +#include "clang/Basic/FileSystemOptions.h" #include "clang/Frontend/SerializedDiagnostics.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Bitcode/BitCodes.h" +#include "llvm/Bitcode/BitstreamReader.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ErrorOr.h" #include "llvm/Support/ManagedStatic.h" +#include <cstdint> +#include <system_error> using namespace clang; -using namespace clang::serialized_diags; +using namespace serialized_diags; std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) { // Open the diagnostics file. @@ -44,13 +55,12 @@ std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) { std::error_code EC; switch (Stream.ReadSubBlockID()) { - case llvm::bitc::BLOCKINFO_BLOCK_ID: { + case llvm::bitc::BLOCKINFO_BLOCK_ID: BlockInfo = Stream.ReadBlockInfoBlock(); if (!BlockInfo) return SDError::MalformedBlockInfoBlock; Stream.setBlockInfo(&*BlockInfo); continue; - } case BLOCK_META: if ((EC = readMetaBlock(Stream))) return EC; @@ -65,7 +75,7 @@ std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) { continue; } } - return std::error_code(); + return {}; } enum class SerializedDiagnosticReader::Cursor { @@ -132,7 +142,7 @@ SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) { case Cursor::BlockEnd: if (!VersionChecked) return SDError::MissingVersion; - return std::error_code(); + return {}; } SmallVector<uint64_t, 1> Record; @@ -176,7 +186,7 @@ SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) { case Cursor::BlockEnd: if ((EC = visitEndOfDiagnostic())) return EC; - return std::error_code(); + return {}; case Cursor::Record: break; } @@ -253,12 +263,14 @@ SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) { } namespace { + class SDErrorCategoryType final : public std::error_category { const char *name() const noexcept override { return "clang.serialized_diags"; } + std::string message(int IE) const override { - SDError E = static_cast<SDError>(IE); + auto E = static_cast<SDError>(IE); switch (E) { case SDError::CouldNotLoad: return "Failed to open diagnostics file"; @@ -290,7 +302,8 @@ class SDErrorCategoryType final : public std::error_category { llvm_unreachable("Unknown error type!"); } }; -} + +} // namespace static llvm::ManagedStatic<SDErrorCategoryType> ErrorCategory; const std::error_category &clang::serialized_diags::SDErrorCategory() { diff --git a/lib/Frontend/TextDiagnostic.cpp b/lib/Frontend/TextDiagnostic.cpp index 6a72b00c602b..85cd019005da 100644 --- a/lib/Frontend/TextDiagnostic.cpp +++ b/lib/Frontend/TextDiagnostic.cpp @@ -42,7 +42,7 @@ static const enum raw_ostream::Colors fatalColor = raw_ostream::RED; static const enum raw_ostream::Colors savedColor = raw_ostream::SAVEDCOLOR; -/// \brief Add highlights to differences in template strings. +/// Add highlights to differences in template strings. static void applyTemplateHighlighting(raw_ostream &OS, StringRef Str, bool &Normal, bool Bold) { while (1) { @@ -63,7 +63,7 @@ static void applyTemplateHighlighting(raw_ostream &OS, StringRef Str, } } -/// \brief Number of spaces to indent when word-wrapping. +/// Number of spaces to indent when word-wrapping. const unsigned WordWrapIndentation = 6; static int bytesSincePreviousTabOrLineBegin(StringRef SourceLine, size_t i) { @@ -76,7 +76,7 @@ static int bytesSincePreviousTabOrLineBegin(StringRef SourceLine, size_t i) { return bytes; } -/// \brief returns a printable representation of first item from input range +/// returns a printable representation of first item from input range /// /// This function returns a printable representation of the next item in a line /// of source. If the next byte begins a valid and printable character, that @@ -269,14 +269,14 @@ struct SourceColumnMap { int columns() const { return m_byteToColumn.back(); } int bytes() const { return m_columnToByte.back(); } - /// \brief Map a byte to the column which it is at the start of, or return -1 + /// Map a byte to the column which it is at the start of, or return -1 /// if it is not at the start of a column (for a UTF-8 trailing byte). int byteToColumn(int n) const { assert(0<=n && n<static_cast<int>(m_byteToColumn.size())); return m_byteToColumn[n]; } - /// \brief Map a byte to the first column which contains it. + /// Map a byte to the first column which contains it. int byteToContainingColumn(int N) const { assert(0 <= N && N < static_cast<int>(m_byteToColumn.size())); while (m_byteToColumn[N] == -1) @@ -284,7 +284,7 @@ struct SourceColumnMap { return m_byteToColumn[N]; } - /// \brief Map a column to the byte which starts the column, or return -1 if + /// Map a column to the byte which starts the column, or return -1 if /// the column the second or subsequent column of an expanded tab or similar /// multi-column entity. int columnToByte(int n) const { @@ -292,14 +292,14 @@ struct SourceColumnMap { return m_columnToByte[n]; } - /// \brief Map from a byte index to the next byte which starts a column. + /// Map from a byte index to the next byte which starts a column. int startOfNextColumn(int N) const { assert(0 <= N && N < static_cast<int>(m_byteToColumn.size() - 1)); while (byteToColumn(++N) == -1) {} return N; } - /// \brief Map from a byte index to the previous byte which starts a column. + /// Map from a byte index to the previous byte which starts a column. int startOfPreviousColumn(int N) const { assert(0 < N && N < static_cast<int>(m_byteToColumn.size())); while (byteToColumn(--N) == -1) {} @@ -317,7 +317,7 @@ private: }; } // end anonymous namespace -/// \brief When the source code line we want to print is too long for +/// When the source code line we want to print is too long for /// the terminal, select the "interesting" region. static void selectInterestingSourceRegion(std::string &SourceLine, std::string &CaretLine, @@ -507,7 +507,7 @@ static void selectInterestingSourceRegion(std::string &SourceLine, } } -/// \brief Skip over whitespace in the string, starting at the given +/// Skip over whitespace in the string, starting at the given /// index. /// /// \returns The index of the first non-whitespace character that is @@ -519,7 +519,7 @@ static unsigned skipWhitespace(unsigned Idx, StringRef Str, unsigned Length) { return Idx; } -/// \brief If the given character is the start of some kind of +/// If the given character is the start of some kind of /// balanced punctuation (e.g., quotes or parentheses), return the /// character that will terminate the punctuation. /// @@ -539,7 +539,7 @@ static inline char findMatchingPunctuation(char c) { return 0; } -/// \brief Find the end of the word starting at the given offset +/// Find the end of the word starting at the given offset /// within a string. /// /// \returns the index pointing one character past the end of the @@ -596,7 +596,7 @@ static unsigned findEndOfWord(unsigned Start, StringRef Str, return findEndOfWord(Start + 1, Str, Length, Column + 1, Columns); } -/// \brief Print the given string to a stream, word-wrapping it to +/// Print the given string to a stream, word-wrapping it to /// some number of columns in the process. /// /// \param OS the stream to which the word-wrapping string will be @@ -777,7 +777,7 @@ void TextDiagnostic::emitFilename(StringRef Filename, const SourceManager &SM) { OS << Filename; } -/// \brief Print out the file/line/column information and include trace. +/// Print out the file/line/column information and include trace. /// /// This method handlen the emission of the diagnostic location information. /// This includes extracting as much location information as is present for @@ -852,23 +852,14 @@ void TextDiagnostic::emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, // Ignore invalid ranges. if (!RI->isValid()) continue; - FullSourceLoc B = - FullSourceLoc(RI->getBegin(), Loc.getManager()).getExpansionLoc(); - FullSourceLoc E = - FullSourceLoc(RI->getEnd(), Loc.getManager()).getExpansionLoc(); + auto &SM = Loc.getManager(); + SourceLocation B = SM.getExpansionLoc(RI->getBegin()); + CharSourceRange ERange = SM.getExpansionRange(RI->getEnd()); + SourceLocation E = ERange.getEnd(); + bool IsTokenRange = ERange.isTokenRange(); - // If the End location and the start location are the same and are a - // macro location, then the range was something that came from a - // macro expansion or _Pragma. If this is an object-like macro, the - // best we can do is to highlight the range. If this is a - // function-like macro, we'd also like to highlight the arguments. - if (B == E && RI->getEnd().isMacroID()) - E = FullSourceLoc(RI->getEnd(), Loc.getManager()) - .getExpansionRange() - .second; - - std::pair<FileID, unsigned> BInfo = B.getDecomposedLoc(); - std::pair<FileID, unsigned> EInfo = E.getDecomposedLoc(); + std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(B); + std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(E); // If the start or end of the range is in another file, just discard // it. @@ -878,11 +869,14 @@ void TextDiagnostic::emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, // Add in the length of the token, so that we cover multi-char // tokens. unsigned TokSize = 0; - if (RI->isTokenRange()) - TokSize = Lexer::MeasureTokenLength(E, E.getManager(), LangOpts); - - OS << '{' << B.getLineNumber() << ':' << B.getColumnNumber() << '-' - << E.getLineNumber() << ':' << (E.getColumnNumber() + TokSize) << '}'; + if (IsTokenRange) + TokSize = Lexer::MeasureTokenLength(E, SM, LangOpts); + + FullSourceLoc BF(B, SM), EF(E, SM); + OS << '{' + << BF.getLineNumber() << ':' << BF.getColumnNumber() << '-' + << EF.getLineNumber() << ':' << (EF.getColumnNumber() + TokSize) + << '}'; PrintedRange = true; } @@ -919,7 +913,7 @@ void TextDiagnostic::emitBuildingModuleLocation(FullSourceLoc Loc, OS << "While building module '" << ModuleName << "':\n"; } -/// \brief Find the suitable set of lines to show to include a set of ranges. +/// Find the suitable set of lines to show to include a set of ranges. static llvm::Optional<std::pair<unsigned, unsigned>> findLinesForRange(const CharSourceRange &R, FileID FID, const SourceManager &SM) { @@ -969,7 +963,7 @@ maybeAddRange(std::pair<unsigned, unsigned> A, std::pair<unsigned, unsigned> B, return A; } -/// \brief Highlight a SourceRange (with ~'s) for any characters on LineNo. +/// Highlight a SourceRange (with ~'s) for any characters on LineNo. static void highlightRange(const CharSourceRange &R, unsigned LineNo, FileID FID, const SourceColumnMap &map, @@ -1116,7 +1110,7 @@ static std::string buildFixItInsertionLine(FileID FID, return FixItInsertionLine; } -/// \brief Emit a code snippet and caret line. +/// Emit a code snippet and caret line. /// /// This routine emits a single line's code snippet and caret line.. /// diff --git a/lib/Frontend/TextDiagnosticBuffer.cpp b/lib/Frontend/TextDiagnosticBuffer.cpp index 288507310baa..44bb2bc29bc0 100644 --- a/lib/Frontend/TextDiagnosticBuffer.cpp +++ b/lib/Frontend/TextDiagnosticBuffer.cpp @@ -1,4 +1,4 @@ -//===--- TextDiagnosticBuffer.cpp - Buffer Text Diagnostics ---------------===// +//===- TextDiagnosticBuffer.cpp - Buffer Text Diagnostics -----------------===// // // The LLVM Compiler Infrastructure // @@ -12,13 +12,15 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/TextDiagnosticBuffer.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/LLVM.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/ErrorHandling.h" + using namespace clang; /// HandleDiagnostic - Store the errors, warnings, and notes that are /// reported. -/// void TextDiagnosticBuffer::HandleDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info) { // Default implementation (Warnings/errors count). @@ -50,25 +52,24 @@ void TextDiagnosticBuffer::HandleDiagnostic(DiagnosticsEngine::Level Level, } void TextDiagnosticBuffer::FlushDiagnostics(DiagnosticsEngine &Diags) const { - for (auto it = All.begin(), ie = All.end(); it != ie; ++it) { - auto Diag = Diags.Report(Diags.getCustomDiagID(it->first, "%0")); - switch (it->first) { + for (const auto &I : All) { + auto Diag = Diags.Report(Diags.getCustomDiagID(I.first, "%0")); + switch (I.first) { default: llvm_unreachable( "Diagnostic not handled during diagnostic flushing!"); case DiagnosticsEngine::Note: - Diag << Notes[it->second].second; + Diag << Notes[I.second].second; break; case DiagnosticsEngine::Warning: - Diag << Warnings[it->second].second; + Diag << Warnings[I.second].second; break; case DiagnosticsEngine::Remark: - Diag << Remarks[it->second].second; + Diag << Remarks[I.second].second; break; case DiagnosticsEngine::Error: case DiagnosticsEngine::Fatal: - Diag << Errors[it->second].second; + Diag << Errors[I.second].second; break; } } } - diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp index 5dd3252d5b1e..a37382c116ae 100644 --- a/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/lib/Frontend/TextDiagnosticPrinter.cpp @@ -44,7 +44,7 @@ void TextDiagnosticPrinter::EndSourceFile() { TextDiag.reset(); } -/// \brief Print any diagnostic option information to a raw_ostream. +/// Print any diagnostic option information to a raw_ostream. /// /// This implements all of the logic for adding diagnostic options to a message /// (via OS). Each relevant option is comma separated and all are enclosed in diff --git a/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp index 0df5393a309b..21933f474ff5 100644 --- a/lib/Frontend/VerifyDiagnosticConsumer.cpp +++ b/lib/Frontend/VerifyDiagnosticConsumer.cpp @@ -1,4 +1,4 @@ -//===---- VerifyDiagnosticConsumer.cpp - Verifying Diagnostic Client ------===// +//===- VerifyDiagnosticConsumer.cpp - Verifying Diagnostic Client ---------===// // // The LLVM Compiler Infrastructure // @@ -13,27 +13,48 @@ #include "clang/Frontend/VerifyDiagnosticConsumer.h" #include "clang/Basic/CharInfo.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/FileManager.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/TokenKinds.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/TextDiagnosticBuffer.h" #include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/Lexer.h" +#include "clang/Lex/PPCallbacks.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Lex/Token.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Regex.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cassert> +#include <cstddef> +#include <cstring> +#include <iterator> +#include <memory> +#include <string> +#include <utility> +#include <vector> using namespace clang; -typedef VerifyDiagnosticConsumer::Directive Directive; -typedef VerifyDiagnosticConsumer::DirectiveList DirectiveList; -typedef VerifyDiagnosticConsumer::ExpectedData ExpectedData; + +using Directive = VerifyDiagnosticConsumer::Directive; +using DirectiveList = VerifyDiagnosticConsumer::DirectiveList; +using ExpectedData = VerifyDiagnosticConsumer::ExpectedData; VerifyDiagnosticConsumer::VerifyDiagnosticConsumer(DiagnosticsEngine &Diags_) - : Diags(Diags_), - PrimaryClient(Diags.getClient()), PrimaryClientOwner(Diags.takeClient()), - Buffer(new TextDiagnosticBuffer()), CurrentPreprocessor(nullptr), - LangOpts(nullptr), SrcManager(nullptr), ActiveSourceFiles(0), - Status(HasNoDirectives) -{ + : Diags(Diags_), PrimaryClient(Diags.getClient()), + PrimaryClientOwner(Diags.takeClient()), + Buffer(new TextDiagnosticBuffer()), Status(HasNoDirectives) { if (Diags.hasSourceManager()) setSourceManager(Diags.getSourceManager()); } @@ -48,16 +69,18 @@ VerifyDiagnosticConsumer::~VerifyDiagnosticConsumer() { } #ifndef NDEBUG + namespace { + class VerifyFileTracker : public PPCallbacks { VerifyDiagnosticConsumer &Verify; SourceManager &SM; public: VerifyFileTracker(VerifyDiagnosticConsumer &Verify, SourceManager &SM) - : Verify(Verify), SM(SM) { } + : Verify(Verify), SM(SM) {} - /// \brief Hook into the preprocessor and update the list of parsed + /// Hook into the preprocessor and update the list of parsed /// files when the preprocessor indicates a new file is entered. void FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType, @@ -66,7 +89,9 @@ public: VerifyDiagnosticConsumer::IsParsed); } }; -} // End anonymous namespace. + +} // namespace + #endif // DiagnosticConsumer interface. @@ -79,10 +104,10 @@ void VerifyDiagnosticConsumer::BeginSourceFile(const LangOptions &LangOpts, CurrentPreprocessor = PP; this->LangOpts = &LangOpts; setSourceManager(PP->getSourceManager()); - const_cast<Preprocessor*>(PP)->addCommentHandler(this); + const_cast<Preprocessor *>(PP)->addCommentHandler(this); #ifndef NDEBUG // Debug build tracks parsed files. - const_cast<Preprocessor*>(PP)->addPPCallbacks( + const_cast<Preprocessor *>(PP)->addPPCallbacks( llvm::make_unique<VerifyFileTracker>(*this, *SrcManager)); #endif } @@ -99,7 +124,8 @@ void VerifyDiagnosticConsumer::EndSourceFile() { // Detach comment handler once last active source file completed. if (--ActiveSourceFiles == 0) { if (CurrentPreprocessor) - const_cast<Preprocessor*>(CurrentPreprocessor)->removeCommentHandler(this); + const_cast<Preprocessor *>(CurrentPreprocessor)-> + removeCommentHandler(this); // Check diagnostics once last file completed. CheckDiagnostics(); @@ -152,19 +178,18 @@ void VerifyDiagnosticConsumer::HandleDiagnostic( // Checking diagnostics implementation. //===----------------------------------------------------------------------===// -typedef TextDiagnosticBuffer::DiagList DiagList; -typedef TextDiagnosticBuffer::const_iterator const_diag_iterator; +using DiagList = TextDiagnosticBuffer::DiagList; +using const_diag_iterator = TextDiagnosticBuffer::const_iterator; namespace { /// StandardDirective - Directive with string matching. -/// class StandardDirective : public Directive { public: StandardDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc, bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max) - : Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max) { } + : Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max) {} bool isValid(std::string &Error) override { // all strings are considered valid; even empty ones @@ -177,14 +202,13 @@ public: }; /// RegexDirective - Directive with regular-expression matching. -/// class RegexDirective : public Directive { public: RegexDirective(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc, bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max, StringRef RegexStr) - : Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max), - Regex(RegexStr) { } + : Directive(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max), + Regex(RegexStr) {} bool isValid(std::string &Error) override { return Regex.isValid(Error); @@ -202,7 +226,7 @@ class ParseHelper { public: ParseHelper(StringRef S) - : Begin(S.begin()), End(S.end()), C(Begin), P(Begin), PEnd(nullptr) {} + : Begin(S.begin()), End(S.end()), C(Begin), P(Begin) {} // Return true if string literal is next. bool Next(StringRef S) { @@ -210,7 +234,7 @@ public: PEnd = C + S.size(); if (PEnd > End) return false; - return !memcmp(P, S.data(), S.size()); + return memcmp(P, S.data(), S.size()) == 0; } // Return true if number is next. @@ -321,16 +345,23 @@ public: return !(C < End); } - const char * const Begin; // beginning of expected content - const char * const End; // end of expected content (1-past) - const char *C; // position of next char in content + // Beginning of expected content. + const char * const Begin; + + // End of expected content (1-past). + const char * const End; + + // Position of next char in content. + const char *C; + const char *P; private: - const char *PEnd; // previous next/search subject end (1-past) + // Previous next/search subject end (1-past). + const char *PEnd = nullptr; }; -} // namespace anonymous +} // anonymous /// ParseDirective - Go through the comment and see if it indicates expected /// diagnostics. If so, then put them in the appropriate directive list. @@ -625,7 +656,7 @@ bool VerifyDiagnosticConsumer::HandleComment(Preprocessor &PP, } #ifndef NDEBUG -/// \brief Lex the specified source file to determine whether it contains +/// Lex the specified source file to determine whether it contains /// any expected-* directives. As a Lexer is used rather than a full-blown /// Preprocessor, directives inside skipped #if blocks will still be found. /// @@ -663,7 +694,7 @@ static bool findDirectives(SourceManager &SM, FileID FID, } #endif // !NDEBUG -/// \brief Takes a list of diagnostics that have been generated but not matched +/// Takes a list of diagnostics that have been generated but not matched /// by an expected-* directive and produces a diagnostic to the user from this. static unsigned PrintUnexpected(DiagnosticsEngine &Diags, SourceManager *SourceMgr, const_diag_iterator diag_begin, @@ -691,7 +722,7 @@ static unsigned PrintUnexpected(DiagnosticsEngine &Diags, SourceManager *SourceM return std::distance(diag_begin, diag_end); } -/// \brief Takes a list of diagnostics that were expected to have been generated +/// Takes a list of diagnostics that were expected to have been generated /// but were not and produces a diagnostic to the user from this. static unsigned PrintExpected(DiagnosticsEngine &Diags, SourceManager &SourceMgr, @@ -701,21 +732,20 @@ static unsigned PrintExpected(DiagnosticsEngine &Diags, SmallString<256> Fmt; llvm::raw_svector_ostream OS(Fmt); - for (auto *DirPtr : DL) { - Directive &D = *DirPtr; - if (D.DiagnosticLoc.isInvalid()) + for (const auto *D : DL) { + if (D->DiagnosticLoc.isInvalid()) OS << "\n File *"; else - OS << "\n File " << SourceMgr.getFilename(D.DiagnosticLoc); - if (D.MatchAnyLine) + OS << "\n File " << SourceMgr.getFilename(D->DiagnosticLoc); + if (D->MatchAnyLine) OS << " Line *"; else - OS << " Line " << SourceMgr.getPresumedLineNumber(D.DiagnosticLoc); - if (D.DirectiveLoc != D.DiagnosticLoc) + OS << " Line " << SourceMgr.getPresumedLineNumber(D->DiagnosticLoc); + if (D->DirectiveLoc != D->DiagnosticLoc) OS << " (directive at " - << SourceMgr.getFilename(D.DirectiveLoc) << ':' - << SourceMgr.getPresumedLineNumber(D.DirectiveLoc) << ')'; - OS << ": " << D.Text; + << SourceMgr.getFilename(D->DirectiveLoc) << ':' + << SourceMgr.getPresumedLineNumber(D->DirectiveLoc) << ')'; + OS << ": " << D->Text; } Diags.Report(diag::err_verify_inconsistent_diags).setForceEmit() @@ -723,7 +753,7 @@ static unsigned PrintExpected(DiagnosticsEngine &Diags, return DL.size(); } -/// \brief Determine whether two source locations come from the same file. +/// Determine whether two source locations come from the same file. static bool IsFromSameFile(SourceManager &SM, SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc) { while (DiagnosticLoc.isMacroID()) @@ -741,7 +771,6 @@ static bool IsFromSameFile(SourceManager &SM, SourceLocation DirectiveLoc, /// CheckLists - Compare expected to seen diagnostic lists and return the /// the difference between them. -/// static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr, const char *Label, DirectiveList &Left, @@ -792,7 +821,6 @@ static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr, /// CheckResults - This compares the expected results to those that /// were actually reported. It emits any discrepencies. Return "true" if there /// were problems. Return "false" otherwise. -/// static unsigned CheckResults(DiagnosticsEngine &Diags, SourceManager &SourceMgr, const TextDiagnosticBuffer &Buffer, ExpectedData &ED) { @@ -875,19 +903,16 @@ void VerifyDiagnosticConsumer::CheckDiagnostics() { // this file is being parsed separately from the main file, in which // case consider moving the directives to the correct place, if this // is applicable. - if (UnparsedFiles.size() > 0) { + if (!UnparsedFiles.empty()) { // Generate a cache of parsed FileEntry pointers for alias lookups. llvm::SmallPtrSet<const FileEntry *, 8> ParsedFileCache; - for (ParsedFilesMap::iterator I = ParsedFiles.begin(), - End = ParsedFiles.end(); I != End; ++I) { - if (const FileEntry *FE = I->second) + for (const auto &I : ParsedFiles) + if (const FileEntry *FE = I.second) ParsedFileCache.insert(FE); - } // Iterate through list of unparsed files. - for (UnparsedFilesMap::iterator I = UnparsedFiles.begin(), - End = UnparsedFiles.end(); I != End; ++I) { - const UnparsedFileStatus &Status = I->second; + for (const auto &I : UnparsedFiles) { + const UnparsedFileStatus &Status = I.second; const FileEntry *FE = Status.getFile(); // Skip files that have been parsed via an alias. |