aboutsummaryrefslogtreecommitdiff
path: root/lib/Frontend
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Frontend')
-rw-r--r--lib/Frontend/ASTConsumers.cpp40
-rw-r--r--lib/Frontend/ASTMerge.cpp10
-rw-r--r--lib/Frontend/ASTUnit.cpp355
-rw-r--r--lib/Frontend/CMakeLists.txt3
-rw-r--r--lib/Frontend/CacheTokens.cpp16
-rw-r--r--lib/Frontend/ChainedIncludesSource.cpp33
-rw-r--r--lib/Frontend/CodeGenOptions.cpp24
-rw-r--r--lib/Frontend/CompilerInstance.cpp268
-rw-r--r--lib/Frontend/CompilerInvocation.cpp207
-rw-r--r--lib/Frontend/CreateInvocationFromCommandLine.cpp6
-rw-r--r--lib/Frontend/DependencyFile.cpp36
-rw-r--r--lib/Frontend/DependencyGraph.cpp13
-rw-r--r--lib/Frontend/DiagnosticRenderer.cpp4
-rw-r--r--lib/Frontend/FrontendAction.cpp80
-rw-r--r--lib/Frontend/FrontendActions.cpp168
-rw-r--r--lib/Frontend/HeaderIncludeGen.cpp20
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp16
-rw-r--r--lib/Frontend/InitPreprocessor.cpp166
-rw-r--r--lib/Frontend/LogDiagnosticPrinter.cpp26
-rw-r--r--lib/Frontend/ModuleDependencyCollector.cpp43
-rw-r--r--lib/Frontend/MultiplexConsumer.cpp117
-rw-r--r--lib/Frontend/PrintPreprocessedOutput.cpp5
-rw-r--r--lib/Frontend/Rewrite/FixItRewriter.cpp26
-rw-r--r--lib/Frontend/Rewrite/FrontendActions.cpp14
-rw-r--r--lib/Frontend/Rewrite/HTMLPrint.cpp11
-rw-r--r--lib/Frontend/Rewrite/InclusionRewriter.cpp153
-rw-r--r--lib/Frontend/Rewrite/RewriteModernObjC.cpp102
-rw-r--r--lib/Frontend/Rewrite/RewriteObjC.cpp102
-rw-r--r--lib/Frontend/SerializedDiagnosticPrinter.cpp257
-rw-r--r--lib/Frontend/SerializedDiagnosticReader.cpp295
-rw-r--r--lib/Frontend/TextDiagnostic.cpp24
-rw-r--r--lib/Frontend/VerifyDiagnosticConsumer.cpp69
32 files changed, 1711 insertions, 998 deletions
diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp
index 54a6d474c18a..f53c614b0a30 100644
--- a/lib/Frontend/ASTConsumers.cpp
+++ b/lib/Frontend/ASTConsumers.cpp
@@ -57,7 +57,8 @@ namespace {
bool ShowColors = Out.has_colors();
if (ShowColors)
Out.changeColor(raw_ostream::BLUE);
- Out << (Dump ? "Dumping " : "Printing ") << getName(D) << ":\n";
+ Out << ((Dump || DumpLookups) ? "Dumping " : "Printing ") << getName(D)
+ << ":\n";
if (ShowColors)
Out.resetColor();
print(D);
@@ -79,9 +80,13 @@ namespace {
}
void print(Decl *D) {
if (DumpLookups) {
- if (DeclContext *DC = dyn_cast<DeclContext>(D))
- DC->dumpLookups(Out);
- else
+ if (DeclContext *DC = dyn_cast<DeclContext>(D)) {
+ if (DC == DC->getPrimaryContext())
+ DC->dumpLookups(Out, Dump);
+ else
+ Out << "Lookup map is in primary DeclContext "
+ << DC->getPrimaryContext() << "\n";
+ } else
Out << "Not a DeclContext\n";
} else if (Dump)
D->dump(Out);
@@ -118,17 +123,21 @@ namespace {
};
} // end anonymous namespace
-ASTConsumer *clang::CreateASTPrinter(raw_ostream *Out,
- StringRef FilterString) {
- return new ASTPrinter(Out, /*Dump=*/ false, FilterString);
+std::unique_ptr<ASTConsumer> clang::CreateASTPrinter(raw_ostream *Out,
+ StringRef FilterString) {
+ return llvm::make_unique<ASTPrinter>(Out, /*Dump=*/false, FilterString);
}
-ASTConsumer *clang::CreateASTDumper(StringRef FilterString, bool DumpLookups) {
- return new ASTPrinter(nullptr, /*Dump=*/true, FilterString, DumpLookups);
+std::unique_ptr<ASTConsumer> clang::CreateASTDumper(StringRef FilterString,
+ bool DumpDecls,
+ bool DumpLookups) {
+ assert((DumpDecls || DumpLookups) && "nothing to dump");
+ return llvm::make_unique<ASTPrinter>(nullptr, DumpDecls, FilterString,
+ DumpLookups);
}
-ASTConsumer *clang::CreateASTDeclNodeLister() {
- return new ASTDeclNodeLister(nullptr);
+std::unique_ptr<ASTConsumer> clang::CreateASTDeclNodeLister() {
+ return llvm::make_unique<ASTDeclNodeLister>(nullptr);
}
//===----------------------------------------------------------------------===//
@@ -164,8 +173,9 @@ void ASTViewer::HandleTopLevelSingleDecl(Decl *D) {
}
}
-
-ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
+std::unique_ptr<ASTConsumer> clang::CreateASTViewer() {
+ return llvm::make_unique<ASTViewer>();
+}
//===----------------------------------------------------------------------===//
/// DeclContextPrinter - Decl and DeclContext Visualization
@@ -475,6 +485,6 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
}
}
}
-ASTConsumer *clang::CreateDeclContextPrinter() {
- return new DeclContextPrinter();
+std::unique_ptr<ASTConsumer> clang::CreateDeclContextPrinter() {
+ return llvm::make_unique<DeclContextPrinter>();
}
diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp
index ff6434c56945..216ac6a16984 100644
--- a/lib/Frontend/ASTMerge.cpp
+++ b/lib/Frontend/ASTMerge.cpp
@@ -16,8 +16,8 @@
using namespace clang;
-ASTConsumer *ASTMergeAction::CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
+std::unique_ptr<ASTConsumer>
+ASTMergeAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
return AdaptedAction->CreateASTConsumer(CI, InFile);
}
@@ -45,8 +45,8 @@ void ASTMergeAction::ExecuteAction() {
new ForwardingDiagnosticConsumer(
*CI.getDiagnostics().getClient()),
/*ShouldOwnClient=*/true));
- ASTUnit *Unit = ASTUnit::LoadFromASTFile(ASTFiles[I], Diags,
- CI.getFileSystemOpts(), false);
+ std::unique_ptr<ASTUnit> Unit = ASTUnit::LoadFromASTFile(
+ ASTFiles[I], Diags, CI.getFileSystemOpts(), false);
if (!Unit)
continue;
@@ -66,8 +66,6 @@ void ASTMergeAction::ExecuteAction() {
Importer.Import(D);
}
-
- delete Unit;
}
AdaptedAction->ExecuteAction();
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index fc44d9f1b4c0..a3998fa351de 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -105,7 +105,8 @@ static llvm::sys::SmartMutex<false> &getOnDiskMutex() {
static void cleanupOnDiskMapAtExit();
-typedef llvm::DenseMap<const ASTUnit *, OnDiskData *> OnDiskDataMap;
+typedef llvm::DenseMap<const ASTUnit *,
+ std::unique_ptr<OnDiskData>> OnDiskDataMap;
static OnDiskDataMap &getOnDiskDataMap() {
static OnDiskDataMap M;
static bool hasRegisteredAtExit = false;
@@ -132,9 +133,9 @@ static OnDiskData &getOnDiskData(const ASTUnit *AU) {
// DenseMap.
llvm::MutexGuard Guard(getOnDiskMutex());
OnDiskDataMap &M = getOnDiskDataMap();
- OnDiskData *&D = M[AU];
+ auto &D = M[AU];
if (!D)
- D = new OnDiskData();
+ D = llvm::make_unique<OnDiskData>();
return *D;
}
@@ -150,7 +151,6 @@ static void removeOnDiskEntry(const ASTUnit *AU) {
OnDiskDataMap::iterator I = M.find(AU);
if (I != M.end()) {
I->second->Cleanup();
- delete I->second;
M.erase(AU);
}
}
@@ -219,8 +219,8 @@ ASTUnit::ASTUnit(bool _MainFileIsAST)
TUKind(TU_Complete), WantTiming(getenv("LIBCLANG_TIMING")),
OwnsRemappedFileBuffers(true),
NumStoredDiagnosticsFromDriver(0),
- PreambleRebuildCounter(0), SavedMainFileBuffer(nullptr),
- PreambleBuffer(nullptr), NumWarningsInPreamble(0),
+ PreambleRebuildCounter(0),
+ NumWarningsInPreamble(0),
ShouldCacheCodeCompletionResults(false),
IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(false),
CompletionCacheTopLevelHashValue(0),
@@ -251,9 +251,6 @@ ASTUnit::~ASTUnit() {
for (const auto &RB : PPOpts.RemappedFileBuffers)
delete RB.second;
}
-
- delete SavedMainFileBuffer;
- delete PreambleBuffer;
ClearCachedCompletionResults();
@@ -511,8 +508,8 @@ public:
: PP(PP), Context(Context), LangOpt(LangOpt), TargetOpts(TargetOpts),
Target(Target), Counter(Counter), InitializedLanguage(false) {}
- bool ReadLanguageOptions(const LangOptions &LangOpts,
- bool Complain) override {
+ bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
+ bool AllowCompatibleDifferences) override {
if (InitializedLanguage)
return false;
@@ -592,6 +589,7 @@ class CaptureDroppedDiagnostics {
DiagnosticsEngine &Diags;
StoredDiagnosticConsumer Client;
DiagnosticConsumer *PreviousClient;
+ std::unique_ptr<DiagnosticConsumer> OwningPreviousClient;
public:
CaptureDroppedDiagnostics(bool RequestCapture, DiagnosticsEngine &Diags,
@@ -599,16 +597,15 @@ public:
: Diags(Diags), Client(StoredDiags), PreviousClient(nullptr)
{
if (RequestCapture || Diags.getClient() == nullptr) {
- PreviousClient = Diags.takeClient();
- Diags.setClient(&Client);
+ OwningPreviousClient = Diags.takeClient();
+ PreviousClient = Diags.getClient();
+ Diags.setClient(&Client, false);
}
}
~CaptureDroppedDiagnostics() {
- if (Diags.getClient() == &Client) {
- Diags.takeClient();
- Diags.setClient(PreviousClient);
- }
+ if (Diags.getClient() == &Client)
+ Diags.setClient(PreviousClient, !!OwningPreviousClient.release());
}
};
@@ -638,38 +635,30 @@ ASTDeserializationListener *ASTUnit::getDeserializationListener() {
return nullptr;
}
-llvm::MemoryBuffer *ASTUnit::getBufferForFile(StringRef Filename,
- std::string *ErrorStr) {
+std::unique_ptr<llvm::MemoryBuffer>
+ASTUnit::getBufferForFile(StringRef Filename, std::string *ErrorStr) {
assert(FileMgr);
- return FileMgr->getBufferForFile(Filename, ErrorStr);
+ auto Buffer = FileMgr->getBufferForFile(Filename);
+ if (Buffer)
+ return std::move(*Buffer);
+ if (ErrorStr)
+ *ErrorStr = Buffer.getError().message();
+ return nullptr;
}
/// \brief Configure the diagnostics object for use with ASTUnit.
-void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> &Diags,
- const char **ArgBegin, const char **ArgEnd,
+void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
ASTUnit &AST, bool CaptureDiagnostics) {
- if (!Diags.get()) {
- // No diagnostics engine was provided, so create our own diagnostics object
- // with the default options.
- DiagnosticConsumer *Client = nullptr;
- if (CaptureDiagnostics)
- Client = new StoredDiagnosticConsumer(AST.StoredDiagnostics);
- Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions(),
- Client,
- /*ShouldOwnClient=*/true);
- } else if (CaptureDiagnostics) {
+ assert(Diags.get() && "no DiagnosticsEngine was provided");
+ if (CaptureDiagnostics)
Diags->setClient(new StoredDiagnosticConsumer(AST.StoredDiagnostics));
- }
}
-ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
- const FileSystemOptions &FileSystemOpts,
- bool OnlyLocalDecls,
- ArrayRef<RemappedFile> RemappedFiles,
- bool CaptureDiagnostics,
- bool AllowPCHWithCompilerErrors,
- bool UserFilesAreVolatile) {
+std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
+ const std::string &Filename, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
+ const FileSystemOptions &FileSystemOpts, bool OnlyLocalDecls,
+ ArrayRef<RemappedFile> RemappedFiles, bool CaptureDiagnostics,
+ bool AllowPCHWithCompilerErrors, bool UserFilesAreVolatile) {
std::unique_ptr<ASTUnit> AST(new ASTUnit(true));
// Recover resources if we crash before exiting this method.
@@ -679,7 +668,7 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
DiagCleanup(Diags.get());
- ConfigureDiags(Diags, nullptr, nullptr, *AST, CaptureDiagnostics);
+ ConfigureDiags(Diags, *AST, CaptureDiagnostics);
AST->OnlyLocalDecls = OnlyLocalDecls;
AST->CaptureDiagnostics = CaptureDiagnostics;
@@ -705,7 +694,7 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
// Gather Info for preprocessor construction later on.
- HeaderSearch &HeaderInfo = *AST->HeaderInfo.get();
+ HeaderSearch &HeaderInfo = *AST->HeaderInfo;
unsigned Counter;
AST->PP =
@@ -728,10 +717,9 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
/*DisableValidation=*/disableValid,
AllowPCHWithCompilerErrors);
- AST->Reader->setListener(new ASTInfoCollector(*AST->PP, Context,
- AST->ASTFileLangOpts,
- AST->TargetOpts, AST->Target,
- Counter));
+ AST->Reader->setListener(llvm::make_unique<ASTInfoCollector>(
+ *AST->PP, Context, AST->ASTFileLangOpts, AST->TargetOpts, AST->Target,
+ Counter));
switch (AST->Reader->ReadAST(Filename, serialization::MK_MainFile,
SourceLocation(), ASTReader::ARR_None)) {
@@ -768,7 +756,7 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
// Tell the diagnostic client that we have started a source file.
AST->getDiagnostics().getClient()->BeginSourceFile(Context.getLangOpts(),&PP);
- return AST.release();
+ return AST;
}
namespace {
@@ -891,12 +879,13 @@ class TopLevelDeclTrackerAction : public ASTFrontendAction {
public:
ASTUnit &Unit;
- ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) override {
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override {
CI.getPreprocessor().addPPCallbacks(
- new MacroDefinitionTrackerPPCallbacks(Unit.getCurrentTopLevelHashValue()));
- return new TopLevelDeclTrackerConsumer(Unit,
- Unit.getCurrentTopLevelHashValue());
+ llvm::make_unique<MacroDefinitionTrackerPPCallbacks>(
+ Unit.getCurrentTopLevelHashValue()));
+ return llvm::make_unique<TopLevelDeclTrackerConsumer>(
+ Unit, Unit.getCurrentTopLevelHashValue());
}
public:
@@ -916,8 +905,8 @@ public:
explicit PrecompilePreambleAction(ASTUnit &Unit)
: Unit(Unit), HasEmittedPreamblePCH(false) {}
- ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) override;
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
bool hasEmittedPreamblePCH() const { return HasEmittedPreamblePCH; }
void setHasEmittedPreamblePCH() { HasEmittedPreamblePCH = true; }
bool shouldEraseOutputFiles() override { return !hasEmittedPreamblePCH(); }
@@ -979,8 +968,9 @@ public:
}
-ASTConsumer *PrecompilePreambleAction::CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
+std::unique_ptr<ASTConsumer>
+PrecompilePreambleAction::CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) {
std::string Sysroot;
std::string OutputFile;
raw_ostream *OS = nullptr;
@@ -991,10 +981,11 @@ ASTConsumer *PrecompilePreambleAction::CreateASTConsumer(CompilerInstance &CI,
if (!CI.getFrontendOpts().RelocatablePCH)
Sysroot.clear();
- CI.getPreprocessor().addPPCallbacks(new MacroDefinitionTrackerPPCallbacks(
- Unit.getCurrentTopLevelHashValue()));
- return new PrecompilePreambleConsumer(Unit, this, CI.getPreprocessor(),
- Sysroot, OS);
+ CI.getPreprocessor().addPPCallbacks(
+ llvm::make_unique<MacroDefinitionTrackerPPCallbacks>(
+ Unit.getCurrentTopLevelHashValue()));
+ return llvm::make_unique<PrecompilePreambleConsumer>(
+ Unit, this, CI.getPreprocessor(), Sysroot, OS);
}
static bool isNonDriverDiag(const StoredDiagnostic &StoredDiag) {
@@ -1031,15 +1022,12 @@ static void checkAndSanitizeDiags(SmallVectorImpl<StoredDiagnostic> &
///
/// \returns True if a failure occurred that causes the ASTUnit not to
/// contain any translation-unit information, false otherwise.
-bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
- delete SavedMainFileBuffer;
- SavedMainFileBuffer = nullptr;
+bool ASTUnit::Parse(std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer) {
+ SavedMainFileBuffer.reset();
- if (!Invocation) {
- delete OverrideMainBuffer;
+ if (!Invocation)
return true;
- }
-
+
// Create the compiler instance to use for building the AST.
std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
@@ -1060,10 +1048,8 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
// Create the target instance.
Clang->setTarget(TargetInfo::CreateTargetInfo(
Clang->getDiagnostics(), Clang->getInvocation().TargetOpts));
- if (!Clang->hasTarget()) {
- delete OverrideMainBuffer;
+ if (!Clang->hasTarget())
return true;
- }
// Inform the target of the language options.
//
@@ -1083,10 +1069,8 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
FileSystemOpts = Clang->getFileSystemOpts();
IntrusiveRefCntPtr<vfs::FileSystem> VFS =
createVFSFromCompilerInvocation(Clang->getInvocation(), getDiagnostics());
- if (!VFS) {
- delete OverrideMainBuffer;
+ if (!VFS)
return true;
- }
FileMgr = new FileManager(FileSystemOpts, VFS);
SourceMgr = new SourceManager(getDiagnostics(), *FileMgr,
UserFilesAreVolatile);
@@ -1115,7 +1099,8 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
// make that override happen and introduce the preamble.
PreprocessorOptions &PreprocessorOpts = Clang->getPreprocessorOpts();
if (OverrideMainBuffer) {
- PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
+ PreprocessorOpts.addRemappedFile(OriginalSourceFile,
+ OverrideMainBuffer.get());
PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size();
PreprocessorOpts.PrecompiledPreambleBytes.second
= PreambleEndsAtStartOfLine;
@@ -1130,7 +1115,7 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
checkAndSanitizeDiags(StoredDiagnostics, getSourceManager());
// Keep track of the override buffer;
- SavedMainFileBuffer = OverrideMainBuffer;
+ SavedMainFileBuffer = std::move(OverrideMainBuffer);
}
std::unique_ptr<TopLevelDeclTrackerAction> Act(
@@ -1143,7 +1128,7 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0]))
goto error;
- if (OverrideMainBuffer) {
+ if (SavedMainFileBuffer) {
std::string ModName = getPreambleFile(this);
TranslateStoredDiagnostics(getFileManager(), getSourceManager(),
PreambleDiagnostics, StoredDiagnostics);
@@ -1162,10 +1147,7 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
error:
// Remove the overridden buffer we used for the preamble.
- if (OverrideMainBuffer) {
- delete OverrideMainBuffer;
- SavedMainFileBuffer = nullptr;
- }
+ SavedMainFileBuffer = nullptr;
// Keep the ownership of the data in the ASTUnit because the client may
// want to see the diagnostics.
@@ -1194,17 +1176,16 @@ static std::string GetPreamblePCHPath() {
/// \brief Compute the preamble for the main file, providing the source buffer
/// that corresponds to the main file along with a pair (bytes, start-of-line)
/// that describes the preamble.
-std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> >
-ASTUnit::ComputePreamble(CompilerInvocation &Invocation,
- unsigned MaxLines, bool &CreatedBuffer) {
+ASTUnit::ComputedPreamble
+ASTUnit::ComputePreamble(CompilerInvocation &Invocation, unsigned MaxLines) {
FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
PreprocessorOptions &PreprocessorOpts = Invocation.getPreprocessorOpts();
- CreatedBuffer = false;
// Try to determine if the main file has been remapped, either from the
// command line (to another file) or directly through the compiler invocation
// (to a memory buffer).
llvm::MemoryBuffer *Buffer = nullptr;
+ std::unique_ptr<llvm::MemoryBuffer> BufferOwner;
std::string MainFilePath(FrontendOpts.Inputs[0].getFile());
llvm::sys::fs::UniqueID MainFileID;
if (!llvm::sys::fs::getUniqueID(MainFilePath, MainFileID)) {
@@ -1215,15 +1196,9 @@ ASTUnit::ComputePreamble(CompilerInvocation &Invocation,
if (!llvm::sys::fs::getUniqueID(MPath, MID)) {
if (MainFileID == MID) {
// We found a remapping. Try to load the resulting, remapped source.
- if (CreatedBuffer) {
- delete Buffer;
- CreatedBuffer = false;
- }
-
- Buffer = getBufferForFile(RF.second);
- if (!Buffer)
- return std::make_pair(nullptr, std::make_pair(0, true));
- CreatedBuffer = true;
+ BufferOwner = getBufferForFile(RF.second);
+ if (!BufferOwner)
+ return ComputedPreamble(nullptr, nullptr, 0, true);
}
}
}
@@ -1236,11 +1211,7 @@ ASTUnit::ComputePreamble(CompilerInvocation &Invocation,
if (!llvm::sys::fs::getUniqueID(MPath, MID)) {
if (MainFileID == MID) {
// We found a remapping.
- if (CreatedBuffer) {
- delete Buffer;
- CreatedBuffer = false;
- }
-
+ BufferOwner.reset();
Buffer = const_cast<llvm::MemoryBuffer *>(RB.second);
}
}
@@ -1248,17 +1219,18 @@ ASTUnit::ComputePreamble(CompilerInvocation &Invocation,
}
// If the main source file was not remapped, load it now.
- if (!Buffer) {
- Buffer = getBufferForFile(FrontendOpts.Inputs[0].getFile());
- if (!Buffer)
- return std::make_pair(nullptr, std::make_pair(0, true));
-
- CreatedBuffer = true;
+ if (!Buffer && !BufferOwner) {
+ BufferOwner = getBufferForFile(FrontendOpts.Inputs[0].getFile());
+ if (!BufferOwner)
+ return ComputedPreamble(nullptr, nullptr, 0, true);
}
-
- return std::make_pair(Buffer, Lexer::ComputePreamble(Buffer,
- *Invocation.getLangOpts(),
- MaxLines));
+
+ if (!Buffer)
+ Buffer = BufferOwner.get();
+ auto Pre = Lexer::ComputePreamble(Buffer->getBuffer(),
+ *Invocation.getLangOpts(), MaxLines);
+ return ComputedPreamble(Buffer, std::move(BufferOwner), Pre.first,
+ Pre.second);
}
ASTUnit::PreambleFileHash
@@ -1300,42 +1272,44 @@ makeStandaloneRange(CharSourceRange Range, const SourceManager &SM,
return std::make_pair(Offset, EndOffset);
}
-static void makeStandaloneFixIt(const SourceManager &SM,
- const LangOptions &LangOpts,
- const FixItHint &InFix,
- ASTUnit::StandaloneFixIt &OutFix) {
+static ASTUnit::StandaloneFixIt makeStandaloneFixIt(const SourceManager &SM,
+ const LangOptions &LangOpts,
+ const FixItHint &InFix) {
+ ASTUnit::StandaloneFixIt OutFix;
OutFix.RemoveRange = makeStandaloneRange(InFix.RemoveRange, SM, LangOpts);
OutFix.InsertFromRange = makeStandaloneRange(InFix.InsertFromRange, SM,
LangOpts);
OutFix.CodeToInsert = InFix.CodeToInsert;
OutFix.BeforePreviousInsertions = InFix.BeforePreviousInsertions;
+ return OutFix;
}
-static void makeStandaloneDiagnostic(const LangOptions &LangOpts,
- const StoredDiagnostic &InDiag,
- ASTUnit::StandaloneDiagnostic &OutDiag) {
+static ASTUnit::StandaloneDiagnostic
+makeStandaloneDiagnostic(const LangOptions &LangOpts,
+ const StoredDiagnostic &InDiag) {
+ ASTUnit::StandaloneDiagnostic OutDiag;
OutDiag.ID = InDiag.getID();
OutDiag.Level = InDiag.getLevel();
OutDiag.Message = InDiag.getMessage();
OutDiag.LocOffset = 0;
if (InDiag.getLocation().isInvalid())
- return;
+ return OutDiag;
const SourceManager &SM = InDiag.getLocation().getManager();
SourceLocation FileLoc = SM.getFileLoc(InDiag.getLocation());
OutDiag.Filename = SM.getFilename(FileLoc);
if (OutDiag.Filename.empty())
- return;
+ return OutDiag;
OutDiag.LocOffset = SM.getFileOffset(FileLoc);
for (StoredDiagnostic::range_iterator
I = InDiag.range_begin(), E = InDiag.range_end(); I != E; ++I) {
OutDiag.Ranges.push_back(makeStandaloneRange(*I, SM, LangOpts));
}
- for (StoredDiagnostic::fixit_iterator
- I = InDiag.fixit_begin(), E = InDiag.fixit_end(); I != E; ++I) {
- ASTUnit::StandaloneFixIt Fix;
- makeStandaloneFixIt(SM, LangOpts, *I, Fix);
- OutDiag.FixIts.push_back(Fix);
- }
+ for (StoredDiagnostic::fixit_iterator I = InDiag.fixit_begin(),
+ E = InDiag.fixit_end();
+ I != E; ++I)
+ OutDiag.FixIts.push_back(makeStandaloneFixIt(SM, LangOpts, *I));
+
+ return OutDiag;
}
/// \brief Attempt to build or re-use a precompiled preamble when (re-)parsing
@@ -1358,27 +1332,20 @@ static void makeStandaloneDiagnostic(const LangOptions &LangOpts,
/// \returns If the precompiled preamble can be used, returns a newly-allocated
/// buffer that should be used in place of the main file when doing so.
/// Otherwise, returns a NULL pointer.
-llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
- const CompilerInvocation &PreambleInvocationIn,
- bool AllowRebuild,
- unsigned MaxLines) {
-
+std::unique_ptr<llvm::MemoryBuffer>
+ASTUnit::getMainBufferWithPrecompiledPreamble(
+ const CompilerInvocation &PreambleInvocationIn, bool AllowRebuild,
+ unsigned MaxLines) {
+
IntrusiveRefCntPtr<CompilerInvocation>
PreambleInvocation(new CompilerInvocation(PreambleInvocationIn));
FrontendOptions &FrontendOpts = PreambleInvocation->getFrontendOpts();
PreprocessorOptions &PreprocessorOpts
= PreambleInvocation->getPreprocessorOpts();
- bool CreatedPreambleBuffer = false;
- std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > NewPreamble
- = ComputePreamble(*PreambleInvocation, MaxLines, CreatedPreambleBuffer);
-
- // If ComputePreamble() Take ownership of the preamble buffer.
- std::unique_ptr<llvm::MemoryBuffer> OwnedPreambleBuffer;
- if (CreatedPreambleBuffer)
- OwnedPreambleBuffer.reset(NewPreamble.first);
+ ComputedPreamble NewPreamble = ComputePreamble(*PreambleInvocation, MaxLines);
- if (!NewPreamble.second.first) {
+ if (!NewPreamble.Size) {
// We couldn't find a preamble in the main source. Clear out the current
// preamble, if we have one. It's obviously no good any more.
Preamble.clear();
@@ -1394,10 +1361,10 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
// preamble now that we did before, and that there's enough space in
// the main-file buffer within the precompiled preamble to fit the
// new main file.
- if (Preamble.size() == NewPreamble.second.first &&
- PreambleEndsAtStartOfLine == NewPreamble.second.second &&
- memcmp(Preamble.getBufferStart(), NewPreamble.first->getBufferStart(),
- NewPreamble.second.first) == 0) {
+ if (Preamble.size() == NewPreamble.Size &&
+ PreambleEndsAtStartOfLine == NewPreamble.PreambleEndsAtStartOfLine &&
+ memcmp(Preamble.getBufferStart(), NewPreamble.Buffer->getBufferStart(),
+ NewPreamble.Size) == 0) {
// The preamble has not changed. We may be able to re-use the precompiled
// preamble.
@@ -1467,7 +1434,7 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
getDiagnostics().setNumWarnings(NumWarningsInPreamble);
return llvm::MemoryBuffer::getMemBufferCopy(
- NewPreamble.first->getBuffer(), FrontendOpts.Inputs[0].getFile());
+ NewPreamble.Buffer->getBuffer(), FrontendOpts.Inputs[0].getFile());
}
}
@@ -1512,19 +1479,16 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
// subsequent reparses.
StringRef MainFilename = FrontendOpts.Inputs[0].getFile();
Preamble.assign(FileMgr->getFile(MainFilename),
- NewPreamble.first->getBufferStart(),
- NewPreamble.first->getBufferStart()
- + NewPreamble.second.first);
- PreambleEndsAtStartOfLine = NewPreamble.second.second;
+ NewPreamble.Buffer->getBufferStart(),
+ NewPreamble.Buffer->getBufferStart() + NewPreamble.Size);
+ PreambleEndsAtStartOfLine = NewPreamble.PreambleEndsAtStartOfLine;
- delete PreambleBuffer;
- PreambleBuffer
- = llvm::MemoryBuffer::getMemBufferCopy(
- NewPreamble.first->getBuffer().slice(0, Preamble.size()), MainFilename);
+ PreambleBuffer = llvm::MemoryBuffer::getMemBufferCopy(
+ NewPreamble.Buffer->getBuffer().slice(0, Preamble.size()), MainFilename);
// Remap the main source file to the preamble buffer.
StringRef MainFilePath = FrontendOpts.Inputs[0].getFile();
- PreprocessorOpts.addRemappedFile(MainFilePath, PreambleBuffer);
+ PreprocessorOpts.addRemappedFile(MainFilePath, PreambleBuffer.get());
// Tell the compiler invocation to generate a temporary precompiled header.
FrontendOpts.ProgramAction = frontend::GeneratePCH;
@@ -1607,13 +1571,11 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
// Transfer any diagnostics generated when parsing the preamble into the set
// of preamble diagnostics.
- for (stored_diag_iterator
- I = stored_diag_afterDriver_begin(),
- E = stored_diag_end(); I != E; ++I) {
- StandaloneDiagnostic Diag;
- makeStandaloneDiagnostic(Clang->getLangOpts(), *I, Diag);
- PreambleDiagnostics.push_back(Diag);
- }
+ for (stored_diag_iterator I = stored_diag_afterDriver_begin(),
+ E = stored_diag_end();
+ I != E; ++I)
+ PreambleDiagnostics.push_back(
+ makeStandaloneDiagnostic(Clang->getLangOpts(), *I));
Act->EndSourceFile();
@@ -1663,8 +1625,8 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
CompletionCacheTopLevelHashValue = 0;
PreambleTopLevelHashValue = CurrentTopLevelHashValue;
}
-
- return llvm::MemoryBuffer::getMemBufferCopy(NewPreamble.first->getBuffer(),
+
+ return llvm::MemoryBuffer::getMemBufferCopy(NewPreamble.Buffer->getBuffer(),
MainFilename);
}
@@ -1688,8 +1650,8 @@ void ASTUnit::transferASTDataFromCompilerInstance(CompilerInstance &CI) {
// created.
assert(CI.hasInvocation() && "missing invocation");
LangOpts = CI.getInvocation().LangOpts;
- TheSema.reset(CI.takeSema());
- Consumer.reset(CI.takeASTConsumer());
+ TheSema = CI.takeSema();
+ Consumer = CI.takeASTConsumer();
if (CI.hasASTContext())
Ctx = &CI.getASTContext();
if (CI.hasPreprocessor())
@@ -1735,7 +1697,7 @@ ASTUnit *ASTUnit::create(CompilerInvocation *CI,
bool UserFilesAreVolatile) {
std::unique_ptr<ASTUnit> AST;
AST.reset(new ASTUnit(false));
- ConfigureDiags(Diags, nullptr, nullptr, *AST, CaptureDiagnostics);
+ ConfigureDiags(Diags, *AST, CaptureDiagnostics);
AST->Diagnostics = Diags;
AST->Invocation = CI;
AST->FileSystemOpts = CI->getFileSystemOpts();
@@ -1862,13 +1824,15 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
if (Persistent && !TrackerAct) {
Clang->getPreprocessor().addPPCallbacks(
- new MacroDefinitionTrackerPPCallbacks(AST->getCurrentTopLevelHashValue()));
- std::vector<ASTConsumer*> Consumers;
+ llvm::make_unique<MacroDefinitionTrackerPPCallbacks>(
+ AST->getCurrentTopLevelHashValue()));
+ std::vector<std::unique_ptr<ASTConsumer>> Consumers;
if (Clang->hasASTConsumer())
Consumers.push_back(Clang->takeASTConsumer());
- Consumers.push_back(new TopLevelDeclTrackerConsumer(*AST,
- AST->getCurrentTopLevelHashValue()));
- Clang->setASTConsumer(new MultiplexConsumer(Consumers));
+ Consumers.push_back(llvm::make_unique<TopLevelDeclTrackerConsumer>(
+ *AST, AST->getCurrentTopLevelHashValue()));
+ Clang->setASTConsumer(
+ llvm::make_unique<MultiplexConsumer>(std::move(Consumers)));
}
if (!Act->Execute()) {
AST->transferASTDataFromCompilerInstance(*Clang);
@@ -1898,11 +1862,10 @@ bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) {
Invocation->getFrontendOpts().DisableFree = false;
ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
- llvm::MemoryBuffer *OverrideMainBuffer = nullptr;
+ std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;
if (PrecompilePreamble) {
PreambleRebuildCounter = 2;
- OverrideMainBuffer
- = getMainBufferWithPrecompiledPreamble(*Invocation);
+ OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(*Invocation);
}
SimpleTimer ParsingTimer(WantTiming);
@@ -1910,9 +1873,9 @@ bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) {
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<llvm::MemoryBuffer>
- MemBufferCleanup(OverrideMainBuffer);
-
- return Parse(OverrideMainBuffer);
+ MemBufferCleanup(OverrideMainBuffer.get());
+
+ return Parse(std::move(OverrideMainBuffer));
}
std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
@@ -1922,7 +1885,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
bool IncludeBriefCommentsInCodeCompletion, bool UserFilesAreVolatile) {
// Create the AST unit.
std::unique_ptr<ASTUnit> AST(new ASTUnit(false));
- ConfigureDiags(Diags, nullptr, nullptr, *AST, CaptureDiagnostics);
+ ConfigureDiags(Diags, *AST, CaptureDiagnostics);
AST->Diagnostics = Diags;
AST->OnlyLocalDecls = OnlyLocalDecls;
AST->CaptureDiagnostics = CaptureDiagnostics;
@@ -1961,11 +1924,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
bool AllowPCHWithCompilerErrors, bool SkipFunctionBodies,
bool UserFilesAreVolatile, bool ForSerialization,
std::unique_ptr<ASTUnit> *ErrAST) {
- if (!Diags.get()) {
- // No diagnostics engine was provided, so create our own diagnostics object
- // with the default options.
- Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions());
- }
+ assert(Diags.get() && "no DiagnosticsEngine was provided");
SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
@@ -2000,9 +1959,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
// Create the AST unit.
std::unique_ptr<ASTUnit> AST;
AST.reset(new ASTUnit(false));
- ConfigureDiags(Diags, ArgBegin, ArgEnd, *AST, CaptureDiagnostics);
+ ConfigureDiags(Diags, *AST, CaptureDiagnostics);
AST->Diagnostics = Diags;
- Diags = nullptr; // Zero out now to ease cleanup during crash recovery.
AST->FileSystemOpts = CI->getFileSystemOpts();
IntrusiveRefCntPtr<vfs::FileSystem> VFS =
createVFSFromCompilerInvocation(*CI, *Diags);
@@ -2021,7 +1979,9 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
AST->Invocation = CI;
if (ForSerialization)
AST->WriterData.reset(new ASTWriterData());
- CI = nullptr; // Zero out now to ease cleanup during crash recovery.
+ // Zero out now to ease cleanup during crash recovery.
+ CI = nullptr;
+ Diags = nullptr;
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
@@ -2062,7 +2022,7 @@ bool ASTUnit::Reparse(ArrayRef<RemappedFile> RemappedFiles) {
// If we have a preamble file lying around, or if we might try to
// build a precompiled preamble, do so now.
- llvm::MemoryBuffer *OverrideMainBuffer = nullptr;
+ std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;
if (!getPreambleFile(this).empty() || PreambleRebuildCounter > 0)
OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(*Invocation);
@@ -2073,8 +2033,8 @@ bool ASTUnit::Reparse(ArrayRef<RemappedFile> RemappedFiles) {
getDiagnostics().setNumWarnings(NumWarningsInPreamble);
// Parse the sources
- bool Result = Parse(OverrideMainBuffer);
-
+ bool Result = Parse(std::move(OverrideMainBuffer));
+
// If we're caching global code-completion results, and the top-level
// declarations have changed, clear out the code-completion cache.
if (!Result && ShouldCacheCodeCompletionResults &&
@@ -2366,6 +2326,10 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
// Set the language options appropriately.
LangOpts = *CCInvocation->getLangOpts();
+ // Spell-checking and warnings are wasteful during code-completion.
+ LangOpts.SpellChecking = false;
+ CCInvocation->getDiagnosticOpts().IgnoreWarnings = true;
+
std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
// Recover resources if we crash before exiting this method.
@@ -2427,7 +2391,7 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
// the use of the precompiled preamble if we're if the completion
// point is within the main file, after the end of the precompiled
// preamble.
- llvm::MemoryBuffer *OverrideMainBuffer = nullptr;
+ std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer;
if (!getPreambleFile(this).empty()) {
std::string CompleteFilePath(File);
llvm::sys::fs::UniqueID CompleteFileID;
@@ -2437,9 +2401,8 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
llvm::sys::fs::UniqueID MainID;
if (!llvm::sys::fs::getUniqueID(MainPath, MainID)) {
if (CompleteFileID == MainID && Line > 1)
- OverrideMainBuffer
- = getMainBufferWithPrecompiledPreamble(*CCInvocation, false,
- Line - 1);
+ OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(
+ *CCInvocation, false, Line - 1);
}
}
}
@@ -2447,14 +2410,15 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
// If the main file has been overridden due to the use of a preamble,
// make that override happen and introduce the preamble.
if (OverrideMainBuffer) {
- PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
+ PreprocessorOpts.addRemappedFile(OriginalSourceFile,
+ OverrideMainBuffer.get());
PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size();
PreprocessorOpts.PrecompiledPreambleBytes.second
= PreambleEndsAtStartOfLine;
PreprocessorOpts.ImplicitPCHInclude = getPreambleFile(this);
PreprocessorOpts.DisablePCHValidation = true;
-
- OwnedBuffers.push_back(OverrideMainBuffer);
+
+ OwnedBuffers.push_back(OverrideMainBuffer.release());
} else {
PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
PreprocessorOpts.PrecompiledPreambleBytes.second = false;
@@ -2821,7 +2785,8 @@ struct PCHLocatorInfo {
static bool PCHLocator(serialization::ModuleFile &M, void *UserData) {
PCHLocatorInfo &Info = *static_cast<PCHLocatorInfo*>(UserData);
switch (M.Kind) {
- case serialization::MK_Module:
+ case serialization::MK_ImplicitModule:
+ case serialization::MK_ExplicitModule:
return true; // skip dependencies.
case serialization::MK_PCH:
Info.Mod = &M;
diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt
index 403cc42927a6..7c5fca54d1e1 100644
--- a/lib/Frontend/CMakeLists.txt
+++ b/lib/Frontend/CMakeLists.txt
@@ -1,6 +1,7 @@
add_subdirectory(Rewrite)
set(LLVM_LINK_COMPONENTS
+ BitReader
Option
Support
)
@@ -12,6 +13,7 @@ add_clang_library(clangFrontend
CacheTokens.cpp
ChainedDiagnosticConsumer.cpp
ChainedIncludesSource.cpp
+ CodeGenOptions.cpp
CompilerInstance.cpp
CompilerInvocation.cpp
CreateInvocationFromCommandLine.cpp
@@ -31,6 +33,7 @@ add_clang_library(clangFrontend
MultiplexConsumer.cpp
PrintPreprocessedOutput.cpp
SerializedDiagnosticPrinter.cpp
+ SerializedDiagnosticReader.cpp
TextDiagnostic.cpp
TextDiagnosticBuffer.cpp
TextDiagnosticPrinter.cpp
diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp
index 14f7027e4687..d909d526b518 100644
--- a/lib/Frontend/CacheTokens.cpp
+++ b/lib/Frontend/CacheTokens.cpp
@@ -270,17 +270,17 @@ void PTHWriter::EmitToken(const Token& T) {
StringRef s(T.getLiteralData(), T.getLength());
// Get the string entry.
- llvm::StringMapEntry<OffsetOpt> *E = &CachedStrs.GetOrCreateValue(s);
+ auto &E = *CachedStrs.insert(std::make_pair(s, OffsetOpt())).first;
// If this is a new string entry, bump the PTH offset.
- if (!E->getValue().hasOffset()) {
- E->getValue().setOffset(CurStrOffset);
- StrEntries.push_back(E);
+ if (!E.second.hasOffset()) {
+ E.second.setOffset(CurStrOffset);
+ StrEntries.push_back(&E);
CurStrOffset += s.size() + 1;
}
// Emit the relative offset into the PTH file for the spelling string.
- Emit32(E->getValue().getOffset());
+ Emit32(E.second.getOffset());
}
// Emit the offset into the original source file of this token so that we
@@ -572,8 +572,10 @@ void clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) {
PTHWriter PW(*OS, PP);
// Install the 'stat' system call listener in the FileManager.
- StatListener *StatCache = new StatListener(PW.getPM());
- PP.getFileManager().addStatCache(StatCache, /*AtBeginning=*/true);
+ auto StatCacheOwner = llvm::make_unique<StatListener>(PW.getPM());
+ StatListener *StatCache = StatCacheOwner.get();
+ PP.getFileManager().addStatCache(std::move(StatCacheOwner),
+ /*AtBeginning=*/true);
// Lex through the entire file. This will populate SourceManager with
// all of the header information.
diff --git a/lib/Frontend/ChainedIncludesSource.cpp b/lib/Frontend/ChainedIncludesSource.cpp
index e6e73ac963fb..cb260b4f4c69 100644
--- a/lib/Frontend/ChainedIncludesSource.cpp
+++ b/lib/Frontend/ChainedIncludesSource.cpp
@@ -74,7 +74,7 @@ protected:
static ASTReader *
createASTReader(CompilerInstance &CI, StringRef pchFile,
- SmallVectorImpl<llvm::MemoryBuffer *> &memBufs,
+ SmallVectorImpl<std::unique_ptr<llvm::MemoryBuffer>> &MemBufs,
SmallVectorImpl<std::string> &bufNames,
ASTDeserializationListener *deserialListener = nullptr) {
Preprocessor &PP = CI.getPreprocessor();
@@ -83,7 +83,7 @@ createASTReader(CompilerInstance &CI, StringRef pchFile,
/*DisableValidation=*/true));
for (unsigned ti = 0; ti < bufNames.size(); ++ti) {
StringRef sr(bufNames[ti]);
- Reader->addInMemoryBuffer(sr, memBufs[ti]);
+ Reader->addInMemoryBuffer(sr, std::move(MemBufs[ti]));
}
Reader->setDeserializationListener(deserialListener);
switch (Reader->ReadAST(pchFile, serialization::MK_PCH, SourceLocation(),
@@ -118,7 +118,7 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
IntrusiveRefCntPtr<ChainedIncludesSource> source(new ChainedIncludesSource());
InputKind IK = CI.getFrontendOpts().Inputs[0].getKind();
- SmallVector<llvm::MemoryBuffer *, 4> serialBufs;
+ SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 4> SerialBufs;
SmallVector<std::string, 4> serialBufNames;
for (unsigned i = 0, e = includes.size(); i != e; ++i) {
@@ -158,12 +158,12 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
SmallVector<char, 256> serialAST;
llvm::raw_svector_ostream OS(serialAST);
- std::unique_ptr<ASTConsumer> consumer;
- consumer.reset(new PCHGenerator(Clang->getPreprocessor(), "-", nullptr,
- /*isysroot=*/"", &OS));
+ auto consumer =
+ llvm::make_unique<PCHGenerator>(Clang->getPreprocessor(), "-", nullptr,
+ /*isysroot=*/"", &OS);
Clang->getASTContext().setASTMutationListener(
consumer->GetASTMutationListener());
- Clang->setASTConsumer(consumer.release());
+ Clang->setASTConsumer(std::move(consumer));
Clang->createSema(TU_Prefix, nullptr);
if (firstInclude) {
@@ -171,20 +171,21 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(),
PP.getLangOpts());
} else {
- assert(!serialBufs.empty());
- SmallVector<llvm::MemoryBuffer *, 4> bufs;
+ assert(!SerialBufs.empty());
+ SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 4> Bufs;
// TODO: Pass through the existing MemoryBuffer instances instead of
// allocating new ones.
- for (auto *SB : serialBufs)
- bufs.push_back(llvm::MemoryBuffer::getMemBuffer(SB->getBuffer()));
+ for (auto &SB : SerialBufs)
+ Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(SB->getBuffer()));
std::string pchName = includes[i-1];
llvm::raw_string_ostream os(pchName);
os << ".pch" << i-1;
serialBufNames.push_back(os.str());
IntrusiveRefCntPtr<ASTReader> Reader;
- Reader = createASTReader(*Clang, pchName, bufs, serialBufNames,
- Clang->getASTConsumer().GetASTDeserializationListener());
+ Reader = createASTReader(
+ *Clang, pchName, Bufs, serialBufNames,
+ Clang->getASTConsumer().GetASTDeserializationListener());
if (!Reader)
return nullptr;
Clang->setModuleManager(Reader);
@@ -196,14 +197,14 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
ParseAST(Clang->getSema());
Clang->getDiagnosticClient().EndSourceFile();
- serialBufs.push_back(llvm::MemoryBuffer::getMemBufferCopy(OS.str()));
+ SerialBufs.push_back(llvm::MemoryBuffer::getMemBufferCopy(OS.str()));
source->CIs.push_back(Clang.release());
}
- assert(!serialBufs.empty());
+ assert(!SerialBufs.empty());
std::string pchName = includes.back() + ".pch-final";
serialBufNames.push_back(pchName);
- Reader = createASTReader(CI, pchName, serialBufs, serialBufNames);
+ Reader = createASTReader(CI, pchName, SerialBufs, serialBufNames);
if (!Reader)
return nullptr;
diff --git a/lib/Frontend/CodeGenOptions.cpp b/lib/Frontend/CodeGenOptions.cpp
new file mode 100644
index 000000000000..75ee47f86806
--- /dev/null
+++ b/lib/Frontend/CodeGenOptions.cpp
@@ -0,0 +1,24 @@
+//===--- CodeGenOptions.cpp -----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/CodeGenOptions.h"
+#include <string.h>
+
+namespace clang {
+
+CodeGenOptions::CodeGenOptions() {
+#define CODEGENOPT(Name, Bits, Default) Name = Default;
+#define ENUM_CODEGENOPT(Name, Type, Bits, Default) set##Name(Default);
+#include "clang/Frontend/CodeGenOptions.def"
+
+ RelocationModel = "pic";
+ memcpy(CoverageVersion, "402*", 4);
+}
+
+} // end namespace clang
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 6af920d9fd78..93a34b722274 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -101,14 +101,18 @@ void CompilerInstance::setSema(Sema *S) {
TheSema.reset(S);
}
-void CompilerInstance::setASTConsumer(ASTConsumer *Value) {
- Consumer.reset(Value);
+void CompilerInstance::setASTConsumer(std::unique_ptr<ASTConsumer> Value) {
+ Consumer = std::move(Value);
}
void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) {
CompletionConsumer.reset(Value);
}
-
+
+std::unique_ptr<Sema> CompilerInstance::takeSema() {
+ return std::move(TheSema);
+}
+
IntrusiveRefCntPtr<ASTReader> CompilerInstance::getModuleManager() const {
return ModuleManager;
}
@@ -130,52 +134,48 @@ void CompilerInstance::setModuleDepCollector(
static void SetUpDiagnosticLog(DiagnosticOptions *DiagOpts,
const CodeGenOptions *CodeGenOpts,
DiagnosticsEngine &Diags) {
- std::string ErrorInfo;
- bool OwnsStream = false;
+ std::error_code EC;
+ std::unique_ptr<raw_ostream> StreamOwner;
raw_ostream *OS = &llvm::errs();
if (DiagOpts->DiagnosticLogFile != "-") {
// Create the output stream.
- llvm::raw_fd_ostream *FileOS(new llvm::raw_fd_ostream(
- DiagOpts->DiagnosticLogFile.c_str(), ErrorInfo,
- llvm::sys::fs::F_Append | llvm::sys::fs::F_Text));
- if (!ErrorInfo.empty()) {
+ auto FileOS = llvm::make_unique<llvm::raw_fd_ostream>(
+ DiagOpts->DiagnosticLogFile, EC,
+ llvm::sys::fs::F_Append | llvm::sys::fs::F_Text);
+ if (EC) {
Diags.Report(diag::warn_fe_cc_log_diagnostics_failure)
- << DiagOpts->DiagnosticLogFile << ErrorInfo;
+ << DiagOpts->DiagnosticLogFile << EC.message();
} else {
FileOS->SetUnbuffered();
FileOS->SetUseAtomicWrites(true);
- OS = FileOS;
- OwnsStream = true;
+ OS = FileOS.get();
+ StreamOwner = std::move(FileOS);
}
}
// Chain in the diagnostic client which will log the diagnostics.
- LogDiagnosticPrinter *Logger = new LogDiagnosticPrinter(*OS, DiagOpts,
- OwnsStream);
+ auto Logger = llvm::make_unique<LogDiagnosticPrinter>(*OS, DiagOpts,
+ std::move(StreamOwner));
if (CodeGenOpts)
Logger->setDwarfDebugFlags(CodeGenOpts->DwarfDebugFlags);
- Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(), Logger));
+ assert(Diags.ownsClient());
+ Diags.setClient(
+ new ChainedDiagnosticConsumer(Diags.takeClient(), std::move(Logger)));
}
static void SetupSerializedDiagnostics(DiagnosticOptions *DiagOpts,
DiagnosticsEngine &Diags,
StringRef OutputFile) {
- std::string ErrorInfo;
- std::unique_ptr<llvm::raw_fd_ostream> OS;
- OS.reset(new llvm::raw_fd_ostream(OutputFile.str().c_str(), ErrorInfo,
- llvm::sys::fs::F_None));
+ auto SerializedConsumer =
+ clang::serialized_diags::create(OutputFile, DiagOpts);
- if (!ErrorInfo.empty()) {
- Diags.Report(diag::warn_fe_serialized_diag_failure)
- << OutputFile << ErrorInfo;
- return;
+ if (Diags.ownsClient()) {
+ Diags.setClient(new ChainedDiagnosticConsumer(
+ Diags.takeClient(), std::move(SerializedConsumer)));
+ } else {
+ Diags.setClient(new ChainedDiagnosticConsumer(
+ Diags.getClient(), std::move(SerializedConsumer)));
}
-
- DiagnosticConsumer *SerializedConsumer =
- clang::serialized_diags::create(OS.release(), DiagOpts);
-
- Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(),
- SerializedConsumer));
}
void CompilerInstance::createDiagnostics(DiagnosticConsumer *Client,
@@ -371,6 +371,14 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/false, /*OutputPath=*/"",
/*ShowDepth=*/true, /*MSStyle=*/true);
}
+
+ // Load all explictly-specified module map files.
+ for (const auto &Filename : getFrontendOpts().ModuleMapFiles) {
+ if (auto *File = getFileManager().getFile(Filename))
+ PP->getHeaderSearchInfo().loadModuleMapFile(File, /*IsSystem*/false);
+ else
+ getDiagnostics().Report(diag::err_module_map_not_found) << Filename;
+ }
}
// ASTContext
@@ -569,17 +577,14 @@ CompilerInstance::createOutputFile(StringRef OutputPath,
StringRef Extension,
bool UseTemporary,
bool CreateMissingDirectories) {
- std::string Error, OutputPathName, TempPathName;
- llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary,
- RemoveFileOnSignal,
- InFile, Extension,
- UseTemporary,
- CreateMissingDirectories,
- &OutputPathName,
- &TempPathName);
+ std::string OutputPathName, TempPathName;
+ std::error_code EC;
+ llvm::raw_fd_ostream *OS = createOutputFile(
+ OutputPath, EC, Binary, RemoveFileOnSignal, InFile, Extension,
+ UseTemporary, CreateMissingDirectories, &OutputPathName, &TempPathName);
if (!OS) {
- getDiagnostics().Report(diag::err_fe_unable_to_open_output)
- << OutputPath << Error;
+ getDiagnostics().Report(diag::err_fe_unable_to_open_output) << OutputPath
+ << EC.message();
return nullptr;
}
@@ -591,17 +596,11 @@ CompilerInstance::createOutputFile(StringRef OutputPath,
return OS;
}
-llvm::raw_fd_ostream *
-CompilerInstance::createOutputFile(StringRef OutputPath,
- std::string &Error,
- bool Binary,
- bool RemoveFileOnSignal,
- StringRef InFile,
- StringRef Extension,
- bool UseTemporary,
- bool CreateMissingDirectories,
- std::string *ResultPathName,
- std::string *TempPathName) {
+llvm::raw_fd_ostream *CompilerInstance::createOutputFile(
+ StringRef OutputPath, std::error_code &Error, bool Binary,
+ bool RemoveFileOnSignal, StringRef InFile, StringRef Extension,
+ bool UseTemporary, bool CreateMissingDirectories,
+ std::string *ResultPathName, std::string *TempPathName) {
assert((!CreateMissingDirectories || UseTemporary) &&
"CreateMissingDirectories is only allowed when using temporary files");
@@ -670,9 +669,9 @@ CompilerInstance::createOutputFile(StringRef OutputPath,
if (!OS) {
OSFile = OutFile;
OS.reset(new llvm::raw_fd_ostream(
- OSFile.c_str(), Error,
+ OSFile, Error,
(Binary ? llvm::sys::fs::F_None : llvm::sys::fs::F_Text)));
- if (!Error.empty())
+ if (Error)
return nullptr;
}
@@ -705,7 +704,8 @@ bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input,
Kind = Input.isSystem() ? SrcMgr::C_System : SrcMgr::C_User;
if (Input.isBuffer()) {
- SourceMgr.setMainFileID(SourceMgr.createFileID(Input.getBuffer(), Kind));
+ SourceMgr.setMainFileID(SourceMgr.createFileID(
+ std::unique_ptr<llvm::MemoryBuffer>(Input.getBuffer()), Kind));
assert(!SourceMgr.getMainFileID().isInvalid() &&
"Couldn't establish MainFileID!");
return true;
@@ -727,14 +727,14 @@ bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input,
// pick up the correct size, and simply override their contents as we do for
// STDIN.
if (File->isNamedPipe()) {
- std::string ErrorStr;
- if (llvm::MemoryBuffer *MB =
- FileMgr.getBufferForFile(File, &ErrorStr, /*isVolatile=*/true)) {
+ auto MB = FileMgr.getBufferForFile(File, /*isVolatile=*/true);
+ if (MB) {
// Create a new virtual file that will have the correct size.
- File = FileMgr.getVirtualFile(InputFile, MB->getBufferSize(), 0);
- SourceMgr.overrideFileContents(File, MB);
+ File = FileMgr.getVirtualFile(InputFile, (*MB)->getBufferSize(), 0);
+ SourceMgr.overrideFileContents(File, std::move(*MB));
} else {
- Diags.Report(diag::err_cannot_open_file) << InputFile << ErrorStr;
+ Diags.Report(diag::err_cannot_open_file) << InputFile
+ << MB.getError().message();
return false;
}
}
@@ -754,7 +754,7 @@ bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input,
SB->getBufferSize(), 0);
SourceMgr.setMainFileID(
SourceMgr.createFileID(File, SourceLocation(), Kind));
- SourceMgr.overrideFileContents(File, SB.release());
+ SourceMgr.overrideFileContents(File, std::move(SB));
}
assert(!SourceMgr.getMainFileID().isInvalid() &&
@@ -802,8 +802,9 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
llvm::EnableStatistics();
for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) {
- // Reset the ID tables if we are reusing the SourceManager.
- if (hasSourceManager())
+ // Reset the ID tables if we are reusing the SourceManager and parsing
+ // regular files.
+ if (hasSourceManager() && !Act.isModelParsingAction())
getSourceManager().clearIDTables();
if (Act.BeginSourceFile(*this, getFrontendOpts().Inputs[i])) {
@@ -951,17 +952,22 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,
FrontendOpts.Inputs.push_back(
FrontendInputFile("__inferred_module.map", IK));
- llvm::MemoryBuffer *ModuleMapBuffer =
+ std::unique_ptr<llvm::MemoryBuffer> ModuleMapBuffer =
llvm::MemoryBuffer::getMemBuffer(InferredModuleMapContent);
ModuleMapFile = Instance.getFileManager().getVirtualFile(
"__inferred_module.map", InferredModuleMapContent.size(), 0);
- SourceMgr.overrideFileContents(ModuleMapFile, ModuleMapBuffer);
+ SourceMgr.overrideFileContents(ModuleMapFile, std::move(ModuleMapBuffer));
}
- // Construct a module-generating action. Passing through Module->ModuleMap is
+ // Construct a module-generating action. Passing through the module map is
// safe because the FileManager is shared between the compiler instances.
- GenerateModuleAction CreateModuleAction(Module->ModuleMap, Module->IsSystem);
-
+ GenerateModuleAction CreateModuleAction(
+ ModMap.getModuleMapFileForUniquing(Module), Module->IsSystem);
+
+ ImportingInstance.getDiagnostics().Report(ImportLoc,
+ diag::remark_module_build)
+ << Module->Name << ModuleFileName;
+
// 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;
@@ -969,6 +975,10 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance,
CRC.RunSafelyOnThread([&]() { Instance.ExecuteAction(CreateModuleAction); },
ThreadStackSize);
+ ImportingInstance.getDiagnostics().Report(ImportLoc,
+ diag::remark_module_build_done)
+ << Module->Name;
+
// Delete the temporary module map file.
// FIXME: Even though we're executing under crash protection, it would still
// be nice to do this with RemoveFileOnSignal when we can. However, that
@@ -988,9 +998,10 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance,
SourceLocation ImportLoc,
SourceLocation ModuleNameLoc, Module *Module,
StringRef ModuleFileName) {
+ DiagnosticsEngine &Diags = ImportingInstance.getDiagnostics();
+
auto diagnoseBuildFailure = [&] {
- ImportingInstance.getDiagnostics().Report(ModuleNameLoc,
- diag::err_module_not_built)
+ Diags.Report(ModuleNameLoc, diag::err_module_not_built)
<< Module->Name << SourceRange(ImportLoc, ModuleNameLoc);
};
@@ -1004,6 +1015,8 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance,
llvm::LockFileManager Locked(ModuleFileName);
switch (Locked) {
case llvm::LockFileManager::LFS_Error:
+ Diags.Report(ModuleNameLoc, diag::err_module_lock_failure)
+ << Module->Name;
return false;
case llvm::LockFileManager::LFS_Owned:
@@ -1027,7 +1040,7 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance,
// Try to read the module file, now that we've compiled it.
ASTReader::ASTReadResult ReadResult =
ImportingInstance.getModuleManager()->ReadAST(
- ModuleFileName, serialization::MK_Module, ImportLoc,
+ ModuleFileName, serialization::MK_ImplicitModule, ImportLoc,
ModuleLoadCapabilities);
if (ReadResult == ASTReader::OutOfDate &&
@@ -1038,6 +1051,10 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance,
continue;
} else if (ReadResult == ASTReader::Missing) {
diagnoseBuildFailure();
+ } else if (ReadResult != ASTReader::Success &&
+ !Diags.hasErrorOccurred()) {
+ // The ASTReader didn't diagnose the error, so conservatively report it.
+ diagnoseBuildFailure();
}
return ReadResult == ASTReader::Success;
}
@@ -1131,9 +1148,8 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro,
/// \brief Write a new timestamp file with the given path.
static void writeTimestampFile(StringRef TimestampFile) {
- std::string ErrorInfo;
- llvm::raw_fd_ostream Out(TimestampFile.str().c_str(), ErrorInfo,
- llvm::sys::fs::F_None);
+ 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
@@ -1251,6 +1267,65 @@ void CompilerInstance::createModuleManager() {
}
}
+bool CompilerInstance::loadModuleFile(StringRef FileName) {
+ // Helper to recursively read the module names for all modules we're adding.
+ // We mark these as known and redirect any attempt to load that module to
+ // the files we were handed.
+ struct ReadModuleNames : ASTReaderListener {
+ CompilerInstance &CI;
+ std::vector<StringRef> ModuleFileStack;
+ bool Failed;
+ bool TopFileIsModule;
+
+ ReadModuleNames(CompilerInstance &CI)
+ : CI(CI), Failed(false), TopFileIsModule(false) {}
+
+ bool needsImportVisitation() const override { return true; }
+
+ void visitImport(StringRef FileName) override {
+ ModuleFileStack.push_back(FileName);
+ if (ASTReader::readASTFileControlBlock(FileName, CI.getFileManager(),
+ *this)) {
+ CI.getDiagnostics().Report(SourceLocation(),
+ diag::err_module_file_not_found)
+ << FileName;
+ // FIXME: Produce a note stack explaining how we got here.
+ Failed = true;
+ }
+ ModuleFileStack.pop_back();
+ }
+
+ void ReadModuleName(StringRef ModuleName) override {
+ if (ModuleFileStack.size() == 1)
+ TopFileIsModule = true;
+
+ auto &ModuleFile = CI.ModuleFileOverrides[ModuleName];
+ if (!ModuleFile.empty() &&
+ CI.getFileManager().getFile(ModuleFile) !=
+ CI.getFileManager().getFile(ModuleFileStack.back()))
+ CI.getDiagnostics().Report(SourceLocation(),
+ diag::err_conflicting_module_files)
+ << ModuleName << ModuleFile << ModuleFileStack.back();
+ ModuleFile = ModuleFileStack.back();
+ }
+ } RMN(*this);
+
+ RMN.visitImport(FileName);
+
+ if (RMN.Failed)
+ return false;
+
+ // If we never found a module name for the top file, then it's not a module,
+ // it's a PCH or preamble or something.
+ if (!RMN.TopFileIsModule) {
+ getDiagnostics().Report(SourceLocation(), diag::err_module_file_not_module)
+ << FileName;
+ return false;
+ }
+
+ return true;
+}
+
ModuleLoadResult
CompilerInstance::loadModule(SourceLocation ImportLoc,
ModuleIdPath Path,
@@ -1265,7 +1340,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
// when both the preprocessor and parser see the same import declaration.
if (!ImportLoc.isInvalid() && LastModuleImportLoc == ImportLoc) {
// Make the named module visible.
- if (LastModuleImportResult && ModuleName != getLangOpts().CurrentModule)
+ if (LastModuleImportResult && ModuleName != getLangOpts().CurrentModule &&
+ ModuleName != getLangOpts().ImplementationOfModule)
ModuleManager->makeModuleVisible(LastModuleImportResult, Visibility,
ImportLoc, /*Complain=*/false);
return LastModuleImportResult;
@@ -1279,7 +1355,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
if (Known != KnownModules.end()) {
// Retrieve the cached top-level module.
Module = Known->second;
- } else if (ModuleName == getLangOpts().CurrentModule) {
+ } else if (ModuleName == getLangOpts().CurrentModule ||
+ ModuleName == getLangOpts().ImplementationOfModule) {
// This is the module we're building.
Module = PP->getHeaderSearchInfo().lookupModule(ModuleName);
Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first;
@@ -1294,8 +1371,12 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
return ModuleLoadResult();
}
+ auto Override = ModuleFileOverrides.find(ModuleName);
+ bool Explicit = Override != ModuleFileOverrides.end();
+
std::string ModuleFileName =
- PP->getHeaderSearchInfo().getModuleFileName(Module);
+ Explicit ? Override->second
+ : PP->getHeaderSearchInfo().getModuleFileName(Module);
// If we don't already have an ASTReader, create one now.
if (!ModuleManager)
@@ -1311,14 +1392,24 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
Listener->attachToASTReader(*ModuleManager);
// Try to load the module file.
- unsigned ARRFlags = ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing;
- switch (ModuleManager->ReadAST(ModuleFileName, serialization::MK_Module,
+ unsigned ARRFlags =
+ Explicit ? 0 : ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing;
+ switch (ModuleManager->ReadAST(ModuleFileName,
+ Explicit ? serialization::MK_ExplicitModule
+ : serialization::MK_ImplicitModule,
ImportLoc, ARRFlags)) {
case ASTReader::Success:
break;
case ASTReader::OutOfDate:
case ASTReader::Missing: {
+ if (Explicit) {
+ // ReadAST has already complained for us.
+ ModuleLoader::HadFatalFailure = true;
+ KnownModules[Path[0].first] = nullptr;
+ return ModuleLoadResult();
+ }
+
// The module file is missing or out-of-date. Build it.
assert(Module && "missing module file");
// Check whether there is a cycle in the module graph.
@@ -1342,9 +1433,6 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
return ModuleLoadResult();
}
- getDiagnostics().Report(ImportLoc, diag::remark_module_build)
- << ModuleName << ModuleFileName;
-
// Check whether we have already attempted to build this module (but
// failed).
if (getPreprocessorOpts().FailedModules &&
@@ -1359,6 +1447,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
// Try to compile and then load the module.
if (!compileAndLoadModule(*this, ImportLoc, ModuleNameLoc, Module,
ModuleFileName)) {
+ assert(getDiagnostics().hasErrorOccurred() &&
+ "undiagnosed error in compileAndLoadModule");
if (getPreprocessorOpts().FailedModules)
getPreprocessorOpts().FailedModules->addFailed(ModuleName);
KnownModules[Path[0].first] = nullptr;
@@ -1448,6 +1538,10 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
Module = Sub;
}
}
+
+ // Don't make the module visible if we are in the implementation.
+ if (ModuleName == getLangOpts().ImplementationOfModule)
+ return ModuleLoadResult(Module, false);
// Make the named module visible, if it's not already part of the module
// we are parsing.
@@ -1468,7 +1562,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
// Check whether this module is available.
clang::Module::Requirement Requirement;
- clang::Module::HeaderDirective MissingHeader;
+ clang::Module::UnresolvedHeaderDirective MissingHeader;
if (!Module->isAvailable(getLangOpts(), getTarget(), Requirement,
MissingHeader)) {
if (MissingHeader.FileNameLoc.isValid()) {
@@ -1497,9 +1591,16 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
Module, ImportLoc);
}
+ // Determine whether we're in the #include buffer for a module. The #includes
+ // in that buffer do not qualify as module imports; they're just an
+ // implementation detail of us building the module.
+ bool IsInModuleIncludes = !getLangOpts().CurrentModule.empty() &&
+ getSourceManager().getFileID(ImportLoc) ==
+ getSourceManager().getMainFileID();
+
// If this module import was due to an inclusion directive, create an
// implicit import declaration to capture it in the AST.
- if (IsInclusionDirective && hasASTContext()) {
+ if (IsInclusionDirective && hasASTContext() && !IsInModuleIncludes) {
TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU,
ImportLoc, Module,
@@ -1602,3 +1703,4 @@ CompilerInstance::lookupMissingImports(StringRef Name,
return false;
}
+void CompilerInstance::resetAndLeakSema() { BuryPointer(takeSema()); }
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index ce61a4653d2e..54025b06557a 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -10,6 +10,7 @@
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/Version.h"
+#include "clang/Config/config.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/Util.h"
@@ -19,8 +20,8 @@
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Serialization/ASTReader.h"
#include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
@@ -215,6 +216,8 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
}
Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help);
+ Opts.DisableAllChecks = Args.hasArg(OPT_analyzer_disable_all_checks);
+
Opts.visualizeExplodedGraphWithGraphViz =
Args.hasArg(OPT_analyzer_viz_egraph_graphviz);
Opts.visualizeExplodedGraphWithUbiGraph =
@@ -322,21 +325,38 @@ GenerateOptimizationRemarkRegex(DiagnosticsEngine &Diags, ArgList &Args,
return Pattern;
}
+static void parseSanitizerKinds(StringRef FlagName,
+ const std::vector<std::string> &Sanitizers,
+ DiagnosticsEngine &Diags, SanitizerSet &S) {
+ for (const auto &Sanitizer : Sanitizers) {
+ SanitizerKind K = llvm::StringSwitch<SanitizerKind>(Sanitizer)
+#define SANITIZER(NAME, ID) .Case(NAME, SanitizerKind::ID)
+#include "clang/Basic/Sanitizers.def"
+ .Default(SanitizerKind::Unknown);
+ if (K == SanitizerKind::Unknown)
+ Diags.Report(diag::err_drv_invalid_value) << FlagName << Sanitizer;
+ else
+ S.set(K, true);
+ }
+}
+
static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
DiagnosticsEngine &Diags,
const TargetOptions &TargetOpts) {
using namespace options;
bool Success = true;
- Opts.OptimizationLevel = getOptimizationLevel(Args, IK, Diags);
+ unsigned OptimizationLevel = getOptimizationLevel(Args, IK, Diags);
// TODO: This could be done in Driver
unsigned MaxOptLevel = 3;
- if (Opts.OptimizationLevel > MaxOptLevel) {
- // If the optimization level is not supported, fall back on the default optimization
+ if (OptimizationLevel > MaxOptLevel) {
+ // If the optimization level is not supported, fall back on the default
+ // optimization
Diags.Report(diag::warn_drv_optimization_value)
<< Args.getLastArg(OPT_O)->getAsString(Args) << "-O" << MaxOptLevel;
- Opts.OptimizationLevel = MaxOptLevel;
+ OptimizationLevel = MaxOptLevel;
}
+ Opts.OptimizationLevel = OptimizationLevel;
// We must always run at least the always inlining pass.
Opts.setInlining(
@@ -399,6 +419,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.SampleProfileFile = Args.getLastArgValue(OPT_fprofile_sample_use_EQ);
Opts.ProfileInstrGenerate = Args.hasArg(OPT_fprofile_instr_generate);
Opts.InstrProfileInput = Args.getLastArgValue(OPT_fprofile_instr_use_EQ);
+ Opts.CoverageMapping = Args.hasArg(OPT_fcoverage_mapping);
+ Opts.DumpCoverageMapping = Args.hasArg(OPT_dump_coverage_mapping);
Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose);
Opts.ObjCAutoRefCountExceptions = Args.hasArg(OPT_fobjc_arc_exceptions);
Opts.CUDAIsDevice = Args.hasArg(OPT_fcuda_is_device);
@@ -413,16 +435,19 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.LessPreciseFPMAD = Args.hasArg(OPT_cl_mad_enable);
Opts.LimitFloatPrecision = Args.getLastArgValue(OPT_mlimit_float_precision);
Opts.NoInfsFPMath = (Args.hasArg(OPT_menable_no_infinities) ||
- Args.hasArg(OPT_cl_finite_math_only)||
+ Args.hasArg(OPT_cl_finite_math_only) ||
Args.hasArg(OPT_cl_fast_relaxed_math));
Opts.NoNaNsFPMath = (Args.hasArg(OPT_menable_no_nans) ||
- Args.hasArg(OPT_cl_finite_math_only)||
+ Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
+ Args.hasArg(OPT_cl_finite_math_only) ||
Args.hasArg(OPT_cl_fast_relaxed_math));
+ Opts.NoSignedZeros = Args.hasArg(OPT_cl_no_signed_zeros);
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.NoGlobalMerge = Args.hasArg(OPT_mno_global_merge);
Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack);
+ Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings);
Opts.EnableSegmentedStacks = Args.hasArg(OPT_split_stacks);
Opts.RelaxAll = Args.hasArg(OPT_mrelax_all);
Opts.OmitLeafFramePointer = Args.hasArg(OPT_momit_leaf_frame_pointer);
@@ -435,6 +460,11 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Args.hasArg(OPT_cl_fast_relaxed_math);
Opts.UnwindTables = Args.hasArg(OPT_munwind_tables);
Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic");
+ Opts.ThreadModel = Args.getLastArgValue(OPT_mthread_model, "posix");
+ if (Opts.ThreadModel != "posix" && Opts.ThreadModel != "single")
+ Diags.Report(diag::err_drv_invalid_value)
+ << Args.getLastArg(OPT_mthread_model)->getAsString(Args)
+ << Opts.ThreadModel;
Opts.TrapFuncName = Args.getLastArgValue(OPT_ftrap_function_EQ);
Opts.UseInitArray = Args.hasArg(OPT_fuse_init_array);
@@ -442,6 +472,7 @@ 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.MergeFunctions = Args.hasArg(OPT_fmerge_functions);
Opts.VectorizeBB = Args.hasArg(OPT_vectorize_slp_aggressive);
Opts.VectorizeLoop = Args.hasArg(OPT_vectorize_loops);
@@ -449,13 +480,12 @@ 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.SanitizeRecover = !Args.hasArg(OPT_fno_sanitize_recover);
Opts.DisableGCov = Args.hasArg(OPT_test_coverage);
Opts.EmitGcovArcs = Args.hasArg(OPT_femit_coverage_data);
Opts.EmitGcovNotes = Args.hasArg(OPT_femit_coverage_notes);
if (Opts.EmitGcovArcs || Opts.EmitGcovNotes) {
- Opts.CoverageFile = Args.getLastArgValue(OPT_coverage_file);
+ Opts.CoverageFile = Args.getLastArgValue(OPT_coverage_file);
Opts.CoverageExtraChecksum = Args.hasArg(OPT_coverage_cfg_checksum);
Opts.CoverageNoFunctionNamesInData =
Args.hasArg(OPT_coverage_no_function_names_in_data);
@@ -477,7 +507,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
Opts.CompressDebugSections = Args.hasArg(OPT_compress_debug_sections);
Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir);
Opts.LinkBitcodeFile = Args.getLastArgValue(OPT_mlink_bitcode_file);
- Opts.SanitizerBlacklistFile = Args.getLastArgValue(OPT_fsanitize_blacklist);
+ Opts.SanitizeCoverage =
+ getLastArgIntValue(Args, OPT_fsanitize_coverage, 0, Diags);
Opts.SanitizeMemoryTrackOrigins =
getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags);
Opts.SanitizeUndefinedTrapOnError =
@@ -566,11 +597,25 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
NeedLocTracking = true;
}
- // If the user requested one of the flags in the -Rpass family, make sure
- // that the backend tracks source location information.
+ // If the user requested to use a sample profile for PGO, then the
+ // backend will need to track source location information so the profile
+ // can be incorporated into the IR.
+ if (!Opts.SampleProfileFile.empty())
+ NeedLocTracking = true;
+
+ // If the user requested a flag that requires source locations available in
+ // the backend, make sure that the backend tracks source location information.
if (NeedLocTracking && Opts.getDebugInfo() == CodeGenOptions::NoDebugInfo)
Opts.setDebugInfo(CodeGenOptions::LocTrackingOnly);
+ Opts.RewriteMapFiles = Args.getAllArgValues(OPT_frewrite_map_file);
+
+ // Parse -fsanitize-recover= arguments.
+ // FIXME: Report unrecoverable sanitizers incorrectly specified here.
+ parseSanitizerKinds("-fsanitize-recover=",
+ Args.getAllArgValues(OPT_fsanitize_recover_EQ), Diags,
+ Opts.SanitizeRecover);
+
return Success;
}
@@ -597,8 +642,9 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
bool Success = true;
Opts.DiagnosticLogFile = Args.getLastArgValue(OPT_diagnostic_log_file);
- Opts.DiagnosticSerializationFile =
- Args.getLastArgValue(OPT_diagnostic_serialized_file);
+ if (Arg *A =
+ Args.getLastArg(OPT_diagnostic_serialized_file, OPT__serialize_diags))
+ Opts.DiagnosticSerializationFile = A->getValue();
Opts.IgnoreWarnings = Args.hasArg(OPT_w);
Opts.NoRewriteMacros = Args.hasArg(OPT_Wno_rewrite_macros);
Opts.Pedantic = Args.hasArg(OPT_pedantic);
@@ -686,6 +732,9 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
Opts.ConstexprBacktraceLimit = getLastArgIntValue(
Args, OPT_fconstexpr_backtrace_limit,
DiagnosticOptions::DefaultConstexprBacktraceLimit, Diags);
+ Opts.SpellCheckingLimit = getLastArgIntValue(
+ Args, OPT_fspell_checking_limit,
+ DiagnosticOptions::DefaultSpellCheckingLimit, Diags);
Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop,
DiagnosticOptions::DefaultTabStop, Diags);
if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {
@@ -716,6 +765,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
case OPT_ast_list:
Opts.ProgramAction = frontend::ASTDeclList; break;
case OPT_ast_dump:
+ case OPT_ast_dump_lookups:
Opts.ProgramAction = frontend::ASTDump; break;
case OPT_ast_print:
Opts.ProgramAction = frontend::ASTPrint; break;
@@ -823,11 +873,14 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.FixOnlyWarnings = Args.hasArg(OPT_fix_only_warnings);
Opts.FixAndRecompile = Args.hasArg(OPT_fixit_recompile);
Opts.FixToTemporaries = Args.hasArg(OPT_fixit_to_temp);
+ Opts.ASTDumpDecls = Args.hasArg(OPT_ast_dump);
Opts.ASTDumpFilter = Args.getLastArgValue(OPT_ast_dump_filter);
Opts.ASTDumpLookups = Args.hasArg(OPT_ast_dump_lookups);
Opts.UseGlobalModuleIndex = !Args.hasArg(OPT_fno_modules_global_index);
Opts.GenerateGlobalModuleIndex = Opts.UseGlobalModuleIndex;
-
+ Opts.ModuleMapFiles = Args.getAllArgValues(OPT_fmodule_map_file);
+ Opts.ModuleFiles = Args.getAllArgValues(OPT_fmodule_file);
+
Opts.CodeCompleteOpts.IncludeMacros
= Args.hasArg(OPT_code_completion_macros);
Opts.CodeCompleteOpts.IncludeCodePatterns
@@ -866,6 +919,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Literals;
if (Args.hasArg(OPT_objcmt_migrate_subscripting))
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Subscripting;
+ if (Args.hasArg(OPT_objcmt_migrate_property_dot_syntax))
+ Opts.ObjCMTAction |= FrontendOptions::ObjCMT_PropertyDotSyntax;
if (Args.hasArg(OPT_objcmt_migrate_property))
Opts.ObjCMTAction |= FrontendOptions::ObjCMT_Property;
if (Args.hasArg(OPT_objcmt_migrate_readonly_property))
@@ -950,14 +1005,19 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
std::string CompilerInvocation::GetResourcesPath(const char *Argv0,
void *MainAddr) {
- SmallString<128> P(llvm::sys::fs::getMainExecutable(Argv0, MainAddr));
-
- if (!P.empty()) {
- llvm::sys::path::remove_filename(P); // Remove /clang from foo/bin/clang
- llvm::sys::path::remove_filename(P); // Remove /bin from foo/bin
-
- // Get foo/lib/clang/<version>/include
- llvm::sys::path::append(P, "lib", "clang", CLANG_VERSION_STRING);
+ std::string ClangExecutable =
+ llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
+ StringRef Dir = llvm::sys::path::parent_path(ClangExecutable);
+
+ // Compute the path to the resource directory.
+ StringRef ClangResourceDir(CLANG_RESOURCE_DIR);
+ SmallString<128> P(Dir);
+ if (ClangResourceDir != "") {
+ llvm::sys::path::append(P, ClangResourceDir);
+ } else {
+ StringRef ClangLibdirSuffix(CLANG_LIBDIR_SUFFIX);
+ llvm::sys::path::append(P, "..", Twine("lib") + ClangLibdirSuffix, "clang",
+ CLANG_VERSION_STRING);
}
return P.str();
@@ -978,6 +1038,7 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash);
// -fmodules implies -fmodule-maps
Opts.ModuleMaps = Args.hasArg(OPT_fmodule_maps) || Args.hasArg(OPT_fmodules);
+ Opts.ModuleMapFileHomeIsCwd = Args.hasArg(OPT_fmodule_map_file_home_is_cwd);
Opts.ModuleCachePruneInterval =
getLastArgIntValue(Args, OPT_fmodules_prune_interval, 7 * 24 * 60 * 60);
Opts.ModuleCachePruneAfter =
@@ -995,9 +1056,6 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
StringRef MacroDef = (*it)->getValue();
Opts.ModulesIgnoreMacros.insert(MacroDef.split('=').first);
}
- std::vector<std::string> ModuleMapFiles =
- Args.getAllArgValues(OPT_fmodule_map_file);
- Opts.ModuleMapFiles.insert(ModuleMapFiles.begin(), ModuleMapFiles.end());
// Add -I..., -F..., and -index-header-map options in order.
bool IsIndexHeaderMap = false;
@@ -1118,7 +1176,7 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
case IK_PreprocessedC:
case IK_ObjC:
case IK_PreprocessedObjC:
- LangStd = LangStandard::lang_gnu99;
+ LangStd = LangStandard::lang_gnu11;
break;
case IK_CXX:
case IK_PreprocessedCXX:
@@ -1135,7 +1193,7 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
Opts.C11 = Std.isC11();
Opts.CPlusPlus = Std.isCPlusPlus();
Opts.CPlusPlus11 = Std.isCPlusPlus11();
- Opts.CPlusPlus1y = Std.isCPlusPlus1y();
+ Opts.CPlusPlus14 = Std.isCPlusPlus14();
Opts.CPlusPlus1z = Std.isCPlusPlus1z();
Opts.Digraphs = Std.hasDigraphs();
Opts.GNUMode = Std.isGNUMode();
@@ -1148,10 +1206,12 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
if (LangStd == LangStandard::lang_opencl)
Opts.OpenCLVersion = 100;
else if (LangStd == LangStandard::lang_opencl11)
- Opts.OpenCLVersion = 110;
+ Opts.OpenCLVersion = 110;
else if (LangStd == LangStandard::lang_opencl12)
Opts.OpenCLVersion = 120;
-
+ else if (LangStd == LangStandard::lang_opencl20)
+ Opts.OpenCLVersion = 200;
+
// OpenCL has some additional defaults.
if (Opts.OpenCL) {
Opts.AltiVec = 0;
@@ -1175,15 +1235,10 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK,
Opts.GNUKeywords = Opts.GNUMode;
Opts.CXXOperatorNames = Opts.CPlusPlus;
- // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs
- // is specified, or -std is set to a conforming mode.
- // Trigraphs are disabled by default in c++1z onwards.
- Opts.Trigraphs = !Opts.GNUMode && !Opts.CPlusPlus1z;
-
Opts.DollarIdents = !Opts.AsmPreprocessor;
- // C++1y onwards has sized global deallocation functions.
- Opts.SizedDeallocation = Opts.CPlusPlus1y;
+ // C++14 onwards has sized global deallocation functions.
+ Opts.SizedDeallocation = Opts.CPlusPlus14;
}
/// Attempt to parse a visibility value out of the given argument.
@@ -1299,6 +1354,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
.Case("CL", LangStandard::lang_opencl)
.Case("CL1.1", LangStandard::lang_opencl11)
.Case("CL1.2", LangStandard::lang_opencl12)
+ .Case("CL2.0", LangStandard::lang_opencl20)
.Default(LangStandard::lang_unspecified);
if (OpenCLLangStd == LangStandard::lang_unspecified) {
@@ -1322,6 +1378,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
if (Args.hasArg(OPT_fno_operator_names))
Opts.CXXOperatorNames = 0;
+ if (Args.hasArg(OPT_fcuda_is_device))
+ Opts.CUDAIsDevice = 1;
+
if (Opts.ObjC1) {
if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) {
StringRef value = arg->getValue();
@@ -1400,17 +1459,22 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
else if (Args.hasArg(OPT_fwrapv))
Opts.setSignedOverflowBehavior(LangOptions::SOB_Defined);
- if (Args.hasArg(OPT_trigraphs))
- Opts.Trigraphs = 1;
+ Opts.MSVCCompat = Args.hasArg(OPT_fms_compatibility);
+ Opts.MicrosoftExt = Opts.MSVCCompat || Args.hasArg(OPT_fms_extensions);
+ Opts.AsmBlocks = Args.hasArg(OPT_fasm_blocks) || Opts.MicrosoftExt;
+ Opts.MSCompatibilityVersion = parseMSCVersion(Args, Diags);
+
+ // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs
+ // is specified, or -std is set to a conforming mode.
+ // Trigraphs are disabled by default in c++1z onwards.
+ Opts.Trigraphs = !Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus1z;
+ Opts.Trigraphs =
+ Args.hasFlag(OPT_ftrigraphs, OPT_fno_trigraphs, Opts.Trigraphs);
Opts.DollarIdents = Args.hasFlag(OPT_fdollars_in_identifiers,
OPT_fno_dollars_in_identifiers,
Opts.DollarIdents);
Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings);
- Opts.MSVCCompat = Args.hasArg(OPT_fms_compatibility);
- Opts.MicrosoftExt = Opts.MSVCCompat || Args.hasArg(OPT_fms_extensions);
- Opts.AsmBlocks = Args.hasArg(OPT_fasm_blocks) || Opts.MicrosoftExt;
- Opts.MSCompatibilityVersion = parseMSCVersion(Args, Diags);
Opts.VtorDispMode = getLastArgIntValue(Args, OPT_vtordisp_mode_EQ, 1, Diags);
Opts.Borland = Args.hasArg(OPT_fborland_extensions);
Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings);
@@ -1438,6 +1502,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
!Args.hasArg(OPT_fno_modules_search_all) &&
Args.hasArg(OPT_fmodules_search_all);
Opts.ModulesErrorRecovery = !Args.hasArg(OPT_fno_modules_error_recovery);
+ Opts.ModulesImplicitMaps = Args.hasFlag(OPT_fmodules_implicit_maps,
+ OPT_fno_modules_implicit_maps, true);
Opts.CharIsSigned = Opts.OpenCL || !Args.hasArg(OPT_fno_signed_char);
Opts.WChar = Opts.CPlusPlus && !Args.hasArg(OPT_fno_wchar);
Opts.ShortWChar = Args.hasFlag(OPT_fshort_wchar, OPT_fno_short_wchar, false);
@@ -1472,6 +1538,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Args.hasArg(OPT_fencode_extended_block_signature);
Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls);
Opts.PackStruct = getLastArgIntValue(Args, OPT_fpack_struct_EQ, 0, Diags);
+ Opts.MaxTypeAlign = getLastArgIntValue(Args, OPT_fmax_type_align_EQ, 0, Diags);
Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags);
Opts.PIELevel = getLastArgIntValue(Args, OPT_pie_level, 0, Diags);
Opts.Static = Args.hasArg(OPT_static_define);
@@ -1492,6 +1559,16 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.DebuggerObjCLiteral = Args.hasArg(OPT_fdebugger_objc_literal);
Opts.ApplePragmaPack = Args.hasArg(OPT_fapple_pragma_pack);
Opts.CurrentModule = Args.getLastArgValue(OPT_fmodule_name);
+ Opts.ImplementationOfModule =
+ Args.getLastArgValue(OPT_fmodule_implementation_of);
+ Opts.NativeHalfType = Opts.NativeHalfType;
+ Opts.HalfArgsAndReturns = Args.hasArg(OPT_fallow_half_arguments_and_returns);
+
+ if (!Opts.CurrentModule.empty() && !Opts.ImplementationOfModule.empty() &&
+ Opts.CurrentModule != Opts.ImplementationOfModule) {
+ Diags.Report(diag::err_conflicting_module_names)
+ << Opts.CurrentModule << Opts.ImplementationOfModule;
+ }
if (Arg *A = Args.getLastArg(OPT_faddress_space_map_mangling_EQ)) {
switch (llvm::StringSwitch<unsigned>(A->getValue())
@@ -1556,8 +1633,11 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
// inlining enabled.
Opts.NoInlineDefine = !Opt || Args.hasArg(OPT_fno_inline);
- Opts.FastMath = Args.hasArg(OPT_ffast_math);
- Opts.FiniteMathOnly = Args.hasArg(OPT_ffinite_math_only);
+ Opts.FastMath = Args.hasArg(OPT_ffast_math) ||
+ Args.hasArg(OPT_cl_fast_relaxed_math);
+ Opts.FiniteMathOnly = Args.hasArg(OPT_ffinite_math_only) ||
+ Args.hasArg(OPT_cl_finite_math_only) ||
+ Args.hasArg(OPT_cl_fast_relaxed_math);
Opts.RetainCommentsFromSystemHeaders =
Args.hasArg(OPT_fretain_comments_from_system_headers);
@@ -1575,35 +1655,12 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
}
// Parse -fsanitize= arguments.
- std::vector<std::string> Sanitizers = Args.getAllArgValues(OPT_fsanitize_EQ);
- for (unsigned I = 0, N = Sanitizers.size(); I != N; ++I) {
- // Since the Opts.Sanitize* values are bitfields, it's a little tricky to
- // efficiently map string values to them. Perform the mapping indirectly:
- // convert strings to enumerated values, then switch over the enum to set
- // the right bitfield value.
- enum Sanitizer {
-#define SANITIZER(NAME, ID) \
- ID,
-#include "clang/Basic/Sanitizers.def"
- Unknown
- };
- switch (llvm::StringSwitch<unsigned>(Sanitizers[I])
-#define SANITIZER(NAME, ID) \
- .Case(NAME, ID)
-#include "clang/Basic/Sanitizers.def"
- .Default(Unknown)) {
-#define SANITIZER(NAME, ID) \
- case ID: \
- Opts.Sanitize.ID = true; \
- break;
-#include "clang/Basic/Sanitizers.def"
-
- case Unknown:
- Diags.Report(diag::err_drv_invalid_value)
- << "-fsanitize=" << Sanitizers[I];
- break;
- }
- }
+ parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ),
+ Diags, Opts.Sanitize);
+ // -fsanitize-address-field-padding=N has to be a LangOpt, parse it here.
+ Opts.SanitizeAddressFieldPadding =
+ getLastArgIntValue(Args, OPT_fsanitize_address_field_padding, 0, Diags);
+ Opts.SanitizerBlacklistFile = Args.getLastArgValue(OPT_fsanitize_blacklist);
}
static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
@@ -2021,7 +2078,7 @@ createVFSFromCompilerInvocation(const CompilerInvocation &CI,
}
IntrusiveRefCntPtr<vfs::FileSystem> FS =
- vfs::getVFSFromYAML(Buffer->release(), /*DiagHandler*/ nullptr);
+ vfs::getVFSFromYAML(std::move(Buffer.get()), /*DiagHandler*/ nullptr);
if (!FS.get()) {
Diags.Report(diag::err_invalid_vfs_overlay) << File;
return IntrusiveRefCntPtr<vfs::FileSystem>();
diff --git a/lib/Frontend/CreateInvocationFromCommandLine.cpp b/lib/Frontend/CreateInvocationFromCommandLine.cpp
index f2f36e4cacb2..4a8a8a029e79 100644
--- a/lib/Frontend/CreateInvocationFromCommandLine.cpp
+++ b/lib/Frontend/CreateInvocationFromCommandLine.cpp
@@ -71,13 +71,13 @@ clang::createInvocationFromCommandLine(ArrayRef<const char *> ArgList,
return nullptr;
}
- const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
- if (StringRef(Cmd->getCreator().getName()) != "clang") {
+ const driver::Command &Cmd = cast<driver::Command>(*Jobs.begin());
+ if (StringRef(Cmd.getCreator().getName()) != "clang") {
Diags->Report(diag::err_fe_expected_clang_command);
return nullptr;
}
- const ArgStringList &CCArgs = Cmd->getArguments();
+ const ArgStringList &CCArgs = Cmd.getArguments();
std::unique_ptr<CompilerInvocation> CI(new CompilerInvocation());
if (!CompilerInvocation::CreateFromArgs(*CI,
const_cast<const char **>(CCArgs.data()),
diff --git a/lib/Frontend/DependencyFile.cpp b/lib/Frontend/DependencyFile.cpp
index 0b9c0d47dc36..6ea8f5193ef7 100644
--- a/lib/Frontend/DependencyFile.cpp
+++ b/lib/Frontend/DependencyFile.cpp
@@ -22,6 +22,7 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Serialization/ASTReader.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
@@ -108,23 +109,32 @@ struct DepCollectorASTListener : public ASTReaderListener {
void DependencyCollector::maybeAddDependency(StringRef Filename, bool FromModule,
bool IsSystem, bool IsModuleFile,
bool IsMissing) {
- if (Seen.insert(Filename) &&
+ if (Seen.insert(Filename).second &&
sawDependency(Filename, FromModule, IsSystem, IsModuleFile, IsMissing))
Dependencies.push_back(Filename);
}
+static bool isSpecialFilename(StringRef Filename) {
+ return llvm::StringSwitch<bool>(Filename)
+ .Case("<built-in>", true)
+ .Case("<stdin>", true)
+ .Default(false);
+}
+
bool DependencyCollector::sawDependency(StringRef Filename, bool FromModule,
bool IsSystem, bool IsModuleFile,
bool IsMissing) {
- return Filename != "<built-in>" && (needSystemDependencies() || !IsSystem);
+ return !isSpecialFilename(Filename) &&
+ (needSystemDependencies() || !IsSystem);
}
DependencyCollector::~DependencyCollector() { }
void DependencyCollector::attachToPreprocessor(Preprocessor &PP) {
- PP.addPPCallbacks(new DepCollectorPPCallbacks(*this, PP.getSourceManager()));
+ PP.addPPCallbacks(
+ llvm::make_unique<DepCollectorPPCallbacks>(*this, PP.getSourceManager()));
}
void DependencyCollector::attachToASTReader(ASTReader &R) {
- R.addListener(new DepCollectorASTListener(*this));
+ R.addListener(llvm::make_unique<DepCollectorASTListener>(*this));
}
namespace {
@@ -203,21 +213,21 @@ DependencyFileGenerator *DependencyFileGenerator::CreateAndAttachToPreprocessor(
PP.SetSuppressIncludeNotFoundError(true);
DFGImpl *Callback = new DFGImpl(&PP, Opts);
- PP.addPPCallbacks(Callback); // PP owns the Callback
+ PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callback));
return new DependencyFileGenerator(Callback);
}
void DependencyFileGenerator::AttachToASTReader(ASTReader &R) {
DFGImpl *I = reinterpret_cast<DFGImpl *>(Impl);
assert(I && "missing implementation");
- R.addListener(new DFGASTReaderListener(*I));
+ R.addListener(llvm::make_unique<DFGASTReaderListener>(*I));
}
/// FileMatchesDepCriteria - Determine whether the given Filename should be
/// considered as a dependency.
bool DFGImpl::FileMatchesDepCriteria(const char *Filename,
SrcMgr::CharacteristicKind FileType) {
- if (strcmp("<built-in>", Filename) == 0)
+ if (isSpecialFilename(Filename))
return false;
if (IncludeSystemHeaders)
@@ -275,7 +285,7 @@ void DFGImpl::InclusionDirective(SourceLocation HashLoc,
}
void DFGImpl::AddFilename(StringRef Filename) {
- if (FilesSet.insert(Filename))
+ if (FilesSet.insert(Filename).second)
Files.push_back(Filename);
}
@@ -297,11 +307,11 @@ void DFGImpl::OutputDependencyFile() {
return;
}
- std::string Err;
- llvm::raw_fd_ostream OS(OutputFile.c_str(), Err, llvm::sys::fs::F_Text);
- if (!Err.empty()) {
- PP->getDiagnostics().Report(diag::err_fe_error_opening)
- << OutputFile << Err;
+ std::error_code EC;
+ llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_Text);
+ if (EC) {
+ PP->getDiagnostics().Report(diag::err_fe_error_opening) << OutputFile
+ << EC.message();
return;
}
diff --git a/lib/Frontend/DependencyGraph.cpp b/lib/Frontend/DependencyGraph.cpp
index 051b7f9e1412..67a977e38be2 100644
--- a/lib/Frontend/DependencyGraph.cpp
+++ b/lib/Frontend/DependencyGraph.cpp
@@ -61,7 +61,8 @@ public:
void clang::AttachDependencyGraphGen(Preprocessor &PP, StringRef OutputFile,
StringRef SysRoot) {
- PP.addPPCallbacks(new DependencyGraphCallback(&PP, OutputFile, SysRoot));
+ PP.addPPCallbacks(llvm::make_unique<DependencyGraphCallback>(&PP, OutputFile,
+ SysRoot));
}
void DependencyGraphCallback::InclusionDirective(SourceLocation HashLoc,
@@ -96,11 +97,11 @@ DependencyGraphCallback::writeNodeReference(raw_ostream &OS,
}
void DependencyGraphCallback::OutputGraphFile() {
- std::string Err;
- llvm::raw_fd_ostream OS(OutputFile.c_str(), Err, llvm::sys::fs::F_Text);
- if (!Err.empty()) {
- PP->getDiagnostics().Report(diag::err_fe_error_opening)
- << OutputFile << Err;
+ std::error_code EC;
+ llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_Text);
+ if (EC) {
+ PP->getDiagnostics().Report(diag::err_fe_error_opening) << OutputFile
+ << EC.message();
return;
}
diff --git a/lib/Frontend/DiagnosticRenderer.cpp b/lib/Frontend/DiagnosticRenderer.cpp
index cff32b852bf4..c63e98dbe4f1 100644
--- a/lib/Frontend/DiagnosticRenderer.cpp
+++ b/lib/Frontend/DiagnosticRenderer.cpp
@@ -193,7 +193,7 @@ void DiagnosticRenderer::emitStoredDiagnostic(StoredDiagnostic &Diag) {
void DiagnosticRenderer::emitBasicNote(StringRef Message) {
emitDiagnosticMessage(
SourceLocation(), PresumedLoc(), DiagnosticsEngine::Note, Message,
- ArrayRef<CharSourceRange>(), nullptr, DiagOrStoredDiag());
+ None, nullptr, DiagOrStoredDiag());
}
/// \brief Prints an include stack when appropriate for a particular
@@ -509,6 +509,6 @@ DiagnosticNoteRenderer::emitBuildingModuleLocation(SourceLocation Loc,
Message << "while building module '" << ModuleName << "' imported from "
<< PLoc.getFilename() << ':' << PLoc.getLine() << ":";
else
- Message << "while building module '" << ModuleName << ":";
+ Message << "while building module '" << ModuleName << "':";
emitNote(Loc, Message.str(), &SM);
}
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
index 791017924d69..c81c81aba4d2 100644
--- a/lib/Frontend/FrontendAction.cpp
+++ b/lib/Frontend/FrontendAction.cpp
@@ -129,14 +129,15 @@ FrontendAction::FrontendAction() : Instance(nullptr) {}
FrontendAction::~FrontendAction() {}
void FrontendAction::setCurrentInput(const FrontendInputFile &CurrentInput,
- ASTUnit *AST) {
+ std::unique_ptr<ASTUnit> AST) {
this->CurrentInput = CurrentInput;
- CurrentASTUnit.reset(AST);
+ CurrentASTUnit = std::move(AST);
}
-ASTConsumer* FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
- ASTConsumer* Consumer = CreateASTConsumer(CI, InFile);
+std::unique_ptr<ASTConsumer>
+FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI,
+ StringRef InFile) {
+ std::unique_ptr<ASTConsumer> Consumer = CreateASTConsumer(CI, InFile);
if (!Consumer)
return nullptr;
@@ -145,7 +146,8 @@ ASTConsumer* FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI,
// Make sure the non-plugin consumer is first, so that plugins can't
// modifiy the AST.
- std::vector<ASTConsumer*> Consumers(1, Consumer);
+ std::vector<std::unique_ptr<ASTConsumer>> Consumers;
+ Consumers.push_back(std::move(Consumer));
for (size_t i = 0, e = CI.getFrontendOpts().AddPluginActions.size();
i != e; ++i) {
@@ -155,16 +157,15 @@ ASTConsumer* FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI,
it = FrontendPluginRegistry::begin(),
ie = FrontendPluginRegistry::end();
it != ie; ++it) {
- if (it->getName() == CI.getFrontendOpts().AddPluginActions[i]) {
- std::unique_ptr<PluginASTAction> P(it->instantiate());
- FrontendAction* c = P.get();
- if (P->ParseArgs(CI, CI.getFrontendOpts().AddPluginArgs[i]))
- Consumers.push_back(c->CreateASTConsumer(CI, InFile));
- }
+ if (it->getName() != CI.getFrontendOpts().AddPluginActions[i])
+ continue;
+ std::unique_ptr<PluginASTAction> P = it->instantiate();
+ if (P->ParseArgs(CI, CI.getFrontendOpts().AddPluginArgs[i]))
+ Consumers.push_back(P->CreateASTConsumer(CI, InFile));
}
}
- return new MultiplexConsumer(Consumers);
+ return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
}
bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
@@ -189,13 +190,12 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics());
- ASTUnit *AST = ASTUnit::LoadFromASTFile(InputFile, Diags,
- CI.getFileSystemOpts());
+ std::unique_ptr<ASTUnit> AST =
+ ASTUnit::LoadFromASTFile(InputFile, Diags, CI.getFileSystemOpts());
+
if (!AST)
goto failure;
- setCurrentInput(Input, AST);
-
// Inform the diagnostic client we are processing a source file.
CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), nullptr);
HasBegunSourceFile = true;
@@ -207,6 +207,8 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
CI.setPreprocessor(&AST->getPreprocessor());
CI.setASTContext(&AST->getASTContext());
+ setCurrentInput(Input, std::move(AST));
+
// Initialize the action.
if (!BeginSourceFileAction(CI, InputFile))
goto failure;
@@ -285,8 +287,10 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
}
}
- // Set up the preprocessor.
- CI.createPreprocessor(getTranslationUnitKind());
+ // Set up the preprocessor if needed. When parsing model files the
+ // preprocessor of the original source is reused.
+ if (!isModelParsingAction())
+ CI.createPreprocessor(getTranslationUnitKind());
// Inform the diagnostic client we are processing a source file.
CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(),
@@ -305,15 +309,19 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
// Create the AST context and consumer unless this is a preprocessor only
// action.
if (!usesPreprocessorOnly()) {
- CI.createASTContext();
+ // Parsing a model file should reuse the existing ASTContext.
+ if (!isModelParsingAction())
+ CI.createASTContext();
- std::unique_ptr<ASTConsumer> Consumer(
- CreateWrappedASTConsumer(CI, InputFile));
+ std::unique_ptr<ASTConsumer> Consumer =
+ CreateWrappedASTConsumer(CI, InputFile);
if (!Consumer)
goto failure;
- CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener());
-
+ // FIXME: should not overwrite ASTMutationListener when parsing model files?
+ if (!isModelParsingAction())
+ CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener());
+
if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) {
// Convert headers to PCH and chain them.
IntrusiveRefCntPtr<ExternalSemaSource> source, FinalReader;
@@ -349,7 +357,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
goto failure;
}
- CI.setASTConsumer(Consumer.release());
+ CI.setASTConsumer(std::move(Consumer));
if (!CI.hasASTConsumer())
goto failure;
}
@@ -375,6 +383,11 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
"doesn't support modules");
}
+ // If we were asked to load any module files, do so now.
+ for (const auto &ModuleFile : CI.getFrontendOpts().ModuleFiles)
+ if (!CI.loadModuleFile(ModuleFile))
+ goto failure;
+
// If there is a layout overrides file, attach an external AST source that
// provides the layouts from that file.
if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() &&
@@ -432,6 +445,10 @@ void FrontendAction::EndSourceFile() {
// Inform the diagnostic client we are done with this source file.
CI.getDiagnosticClient().EndSourceFile();
+ // Inform the preprocessor we are done.
+ if (CI.hasPreprocessor())
+ CI.getPreprocessor().EndSourceFile();
+
// Finalize the action.
EndSourceFileAction();
@@ -444,7 +461,7 @@ void FrontendAction::EndSourceFile() {
CI.resetAndLeakSema();
CI.resetAndLeakASTContext();
}
- BuryPointer(CI.takeASTConsumer());
+ BuryPointer(CI.takeASTConsumer().get());
} else {
if (!isCurrentFileAST()) {
CI.setSema(nullptr);
@@ -453,10 +470,6 @@ void FrontendAction::EndSourceFile() {
CI.setASTConsumer(nullptr);
}
- // Inform the preprocessor we are done.
- if (CI.hasPreprocessor())
- CI.getPreprocessor().EndSourceFile();
-
if (CI.getFrontendOpts().ShowStats) {
llvm::errs() << "\nSTATISTICS FOR '" << getCurrentFile() << "':\n";
CI.getPreprocessor().PrintStats();
@@ -516,14 +529,15 @@ void ASTFrontendAction::ExecuteAction() {
void PluginASTAction::anchor() { }
-ASTConsumer *
+std::unique_ptr<ASTConsumer>
PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) {
llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!");
}
-ASTConsumer *WrapperFrontendAction::CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
+std::unique_ptr<ASTConsumer>
+WrapperFrontendAction::CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) {
return WrappedAction->CreateASTConsumer(CI, InFile);
}
bool WrapperFrontendAction::BeginInvocation(CompilerInstance &CI) {
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index 6dcaf382c3c4..701ef026d49c 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -33,9 +33,9 @@ using namespace clang;
// Custom Actions
//===----------------------------------------------------------------------===//
-ASTConsumer *InitOnlyAction::CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
- return new ASTConsumer();
+std::unique_ptr<ASTConsumer>
+InitOnlyAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
+ return llvm::make_unique<ASTConsumer>();
}
void InitOnlyAction::ExecuteAction() {
@@ -45,36 +45,38 @@ void InitOnlyAction::ExecuteAction() {
// AST Consumer Actions
//===----------------------------------------------------------------------===//
-ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
+std::unique_ptr<ASTConsumer>
+ASTPrintAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
return CreateASTPrinter(OS, CI.getFrontendOpts().ASTDumpFilter);
return nullptr;
}
-ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
+std::unique_ptr<ASTConsumer>
+ASTDumpAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
return CreateASTDumper(CI.getFrontendOpts().ASTDumpFilter,
+ CI.getFrontendOpts().ASTDumpDecls,
CI.getFrontendOpts().ASTDumpLookups);
}
-ASTConsumer *ASTDeclListAction::CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
+std::unique_ptr<ASTConsumer>
+ASTDeclListAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
return CreateASTDeclNodeLister();
}
-ASTConsumer *ASTViewAction::CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
+std::unique_ptr<ASTConsumer>
+ASTViewAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
return CreateASTViewer();
}
-ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
+std::unique_ptr<ASTConsumer>
+DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) {
return CreateDeclContextPrinter();
}
-ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
+std::unique_ptr<ASTConsumer>
+GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
std::string Sysroot;
std::string OutputFile;
raw_ostream *OS = nullptr;
@@ -83,8 +85,8 @@ ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
if (!CI.getFrontendOpts().RelocatablePCH)
Sysroot.clear();
- return new PCHGenerator(CI.getPreprocessor(), OutputFile, nullptr, Sysroot,
- OS);
+ return llvm::make_unique<PCHGenerator>(CI.getPreprocessor(), OutputFile,
+ nullptr, Sysroot, OS);
}
bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
@@ -111,16 +113,17 @@ bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
return false;
}
-ASTConsumer *GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
+std::unique_ptr<ASTConsumer>
+GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) {
std::string Sysroot;
std::string OutputFile;
raw_ostream *OS = nullptr;
if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, OS))
return nullptr;
- return new PCHGenerator(CI.getPreprocessor(), OutputFile, Module,
- Sysroot, OS);
+ return llvm::make_unique<PCHGenerator>(CI.getPreprocessor(), OutputFile,
+ Module, Sysroot, OS);
}
static SmallVectorImpl<char> &
@@ -139,17 +142,9 @@ static std::error_code addHeaderInclude(StringRef HeaderName,
Includes += "#import \"";
else
Includes += "#include \"";
- // Use an absolute path for the include; there's no reason to think that
- // a relative path will work (. might not be on our include path) or that
- // it will find the same file.
- if (llvm::sys::path::is_absolute(HeaderName)) {
- Includes += HeaderName;
- } else {
- SmallString<256> Header = HeaderName;
- if (std::error_code Err = llvm::sys::fs::make_absolute(Header))
- return Err;
- Includes += Header;
- }
+
+ Includes += HeaderName;
+
Includes += "\"\n";
if (IsExternC && LangOpts.CPlusPlus)
Includes += "}\n";
@@ -160,7 +155,16 @@ static std::error_code addHeaderInclude(const FileEntry *Header,
SmallVectorImpl<char> &Includes,
const LangOptions &LangOpts,
bool IsExternC) {
- return addHeaderInclude(Header->getName(), Includes, LangOpts, IsExternC);
+ // Use an absolute path if we don't have a filename as written in the module
+ // map file; this ensures that we will identify the right file independent of
+ // header search paths.
+ if (llvm::sys::path::is_absolute(Header->getName()))
+ return addHeaderInclude(Header->getName(), Includes, LangOpts, IsExternC);
+
+ SmallString<256> AbsName(Header->getName());
+ if (std::error_code Err = llvm::sys::fs::make_absolute(AbsName))
+ return Err;
+ return addHeaderInclude(AbsName, Includes, LangOpts, IsExternC);
}
/// \brief Collect the set of header includes needed to construct the given
@@ -179,16 +183,20 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr,
return std::error_code();
// Add includes for each of these headers.
- for (unsigned I = 0, N = Module->NormalHeaders.size(); I != N; ++I) {
- const FileEntry *Header = Module->NormalHeaders[I];
- Module->addTopHeader(Header);
- if (std::error_code Err =
- addHeaderInclude(Header, Includes, LangOpts, Module->IsExternC))
+ for (Module::Header &H : Module->Headers[Module::HK_Normal]) {
+ Module->addTopHeader(H.Entry);
+ // Use the path as specified in the module map file. We'll look for this
+ // file relative to the module build directory (the directory containing
+ // the module map file) so this will find the same file that we found
+ // while parsing the module map.
+ if (std::error_code Err = addHeaderInclude(H.NameAsWritten, Includes,
+ LangOpts, Module->IsExternC))
return Err;
}
// Note that Module->PrivateHeaders will not be a TopHeader.
if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) {
+ // FIXME: Track the name as written here.
Module->addTopHeader(UmbrellaHeader);
if (Module->Parent) {
// Include the umbrella header for submodules.
@@ -210,25 +218,30 @@ collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr,
.Cases(".h", ".H", ".hh", ".hpp", true)
.Default(false))
continue;
-
+
+ const FileEntry *Header = FileMgr.getFile(Dir->path());
+ // FIXME: This shouldn't happen unless there is a file system race. Is
+ // that worth diagnosing?
+ if (!Header)
+ continue;
+
// If this header is marked 'unavailable' in this module, don't include
// it.
- if (const FileEntry *Header = FileMgr.getFile(Dir->path())) {
- if (ModMap.isHeaderUnavailableInModule(Header, Module))
- continue;
- Module->addTopHeader(Header);
- }
-
+ if (ModMap.isHeaderUnavailableInModule(Header, Module))
+ continue;
+
// Include this header as part of the umbrella directory.
- if (std::error_code Err = addHeaderInclude(Dir->path(), Includes,
- LangOpts, Module->IsExternC))
+ // FIXME: Track the name as written through to here.
+ Module->addTopHeader(Header);
+ if (std::error_code Err =
+ addHeaderInclude(Header, Includes, LangOpts, Module->IsExternC))
return Err;
}
if (EC)
return EC;
}
-
+
// Recurse into submodules.
for (clang::Module::submodule_iterator Sub = Module->submodule_begin(),
SubEnd = Module->submodule_end();
@@ -285,7 +298,7 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
// Check whether we can build this module at all.
clang::Module::Requirement Requirement;
- clang::Module::HeaderDirective MissingHeader;
+ clang::Module::UnresolvedHeaderDirective MissingHeader;
if (!Module->isAvailable(CI.getLangOpts(), CI.getTarget(), Requirement,
MissingHeader)) {
if (MissingHeader.FileNameLoc.isValid()) {
@@ -301,10 +314,12 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
return false;
}
- if (!ModuleMapForUniquing)
+ if (ModuleMapForUniquing && ModuleMapForUniquing != ModuleMap) {
+ Module->IsInferred = true;
+ HS.getModuleMap().setInferredModuleAllowedBy(Module, ModuleMapForUniquing);
+ } else {
ModuleMapForUniquing = ModuleMap;
- Module->ModuleMap = ModuleMapForUniquing;
- assert(Module->ModuleMap && "missing module map file");
+ }
FileManager &FileMgr = CI.getFileManager();
@@ -312,6 +327,7 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
SmallString<256> HeaderContents;
std::error_code Err = std::error_code();
if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader())
+ // FIXME: Track the file name as written.
Err = addHeaderInclude(UmbrellaHeader, HeaderContents, CI.getLangOpts(),
Module->IsExternC);
if (!Err)
@@ -326,11 +342,15 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
return false;
}
- llvm::MemoryBuffer *InputBuffer =
+ // Inform the preprocessor that includes from within the input buffer should
+ // be resolved relative to the build directory of the module map file.
+ CI.getPreprocessor().setMainFileDir(Module->Directory);
+
+ std::unique_ptr<llvm::MemoryBuffer> InputBuffer =
llvm::MemoryBuffer::getMemBufferCopy(HeaderContents,
Module::getModuleInputBufferName());
// Ownership of InputBuffer will be transferred to the SourceManager.
- setCurrentInput(FrontendInputFile(InputBuffer, getCurrentFileKind(),
+ setCurrentInput(FrontendInputFile(InputBuffer.release(), getCurrentFileKind(),
Module->IsSystem));
return true;
}
@@ -363,19 +383,20 @@ bool GenerateModuleAction::ComputeASTConsumerArguments(CompilerInstance &CI,
return false;
}
-ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
- return new ASTConsumer();
+std::unique_ptr<ASTConsumer>
+SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
+ return llvm::make_unique<ASTConsumer>();
}
-ASTConsumer *DumpModuleInfoAction::CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
- return new ASTConsumer();
+std::unique_ptr<ASTConsumer>
+DumpModuleInfoAction::CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) {
+ return llvm::make_unique<ASTConsumer>();
}
-ASTConsumer *VerifyPCHAction::CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
- return new ASTConsumer();
+std::unique_ptr<ASTConsumer>
+VerifyPCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
+ return llvm::make_unique<ASTConsumer>();
}
void VerifyPCHAction::ExecuteAction() {
@@ -425,8 +446,8 @@ namespace {
Out.indent(2) << "Module map file: " << ModuleMapPath << "\n";
}
- bool ReadLanguageOptions(const LangOptions &LangOpts,
- bool Complain) override {
+ bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
+ bool AllowCompatibleDifferences) override {
Out.indent(2) << "Language options:\n";
#define LANGOPT(Name, Bits, Default, Description) \
DUMP_BOOLEAN(LangOpts.Name, Description);
@@ -528,9 +549,9 @@ void DumpModuleInfoAction::ExecuteAction() {
std::unique_ptr<llvm::raw_fd_ostream> OutFile;
StringRef OutputFileName = getCompilerInstance().getFrontendOpts().OutputFile;
if (!OutputFileName.empty() && OutputFileName != "-") {
- std::string ErrorInfo;
- OutFile.reset(new llvm::raw_fd_ostream(OutputFileName.str().c_str(),
- ErrorInfo, llvm::sys::fs::F_Text));
+ std::error_code EC;
+ OutFile.reset(new llvm::raw_fd_ostream(OutputFileName.str(), EC,
+ llvm::sys::fs::F_Text));
}
llvm::raw_ostream &Out = OutFile.get()? *OutFile.get() : llvm::outs();
@@ -675,13 +696,12 @@ void PrintPreambleAction::ExecuteAction() {
// We can't do anything with these.
return;
}
-
+
CompilerInstance &CI = getCompilerInstance();
- llvm::MemoryBuffer *Buffer
- = CI.getFileManager().getBufferForFile(getCurrentFile());
+ auto Buffer = CI.getFileManager().getBufferForFile(getCurrentFile());
if (Buffer) {
- unsigned Preamble = Lexer::ComputePreamble(Buffer, CI.getLangOpts()).first;
- llvm::outs().write(Buffer->getBufferStart(), Preamble);
- delete Buffer;
+ unsigned Preamble =
+ Lexer::ComputePreamble((*Buffer)->getBuffer(), CI.getLangOpts()).first;
+ llvm::outs().write((*Buffer)->getBufferStart(), Preamble);
}
}
diff --git a/lib/Frontend/HeaderIncludeGen.cpp b/lib/Frontend/HeaderIncludeGen.cpp
index a2f5896746af..27011945712a 100644
--- a/lib/Frontend/HeaderIncludeGen.cpp
+++ b/lib/Frontend/HeaderIncludeGen.cpp
@@ -54,13 +54,12 @@ void clang::AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders,
// Open the output file, if used.
if (!OutputPath.empty()) {
- std::string Error;
+ std::error_code EC;
llvm::raw_fd_ostream *OS = new llvm::raw_fd_ostream(
- OutputPath.str().c_str(), Error,
- llvm::sys::fs::F_Append | llvm::sys::fs::F_Text);
- if (!Error.empty()) {
- PP.getDiagnostics().Report(
- clang::diag::warn_fe_cc_print_header_failure) << Error;
+ OutputPath.str(), EC, llvm::sys::fs::F_Append | llvm::sys::fs::F_Text);
+ if (EC) {
+ PP.getDiagnostics().Report(clang::diag::warn_fe_cc_print_header_failure)
+ << EC.message();
delete OS;
} else {
OS->SetUnbuffered();
@@ -70,9 +69,12 @@ void clang::AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders,
}
}
- PP.addPPCallbacks(new HeaderIncludesCallback(&PP, ShowAllHeaders,
- OutputFile, OwnsOutputFile,
- ShowDepth, MSStyle));
+ PP.addPPCallbacks(llvm::make_unique<HeaderIncludesCallback>(&PP,
+ ShowAllHeaders,
+ OutputFile,
+ OwnsOutputFile,
+ ShowDepth,
+ MSStyle));
}
void HeaderIncludesCallback::FileChanged(SourceLocation Loc,
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index d2edc9479f6b..a518a0a27a23 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -380,7 +380,6 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, const HeaderSearchOp
break;
case llvm::Triple::aarch64:
- case llvm::Triple::arm64:
AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.2.1",
"arm64-apple-darwin10", "", "", triple);
break;
@@ -391,7 +390,7 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, const HeaderSearchOp
switch (os) {
case llvm::Triple::Linux:
llvm_unreachable("Include management is handled in the driver.");
-
+ break;
case llvm::Triple::Win32:
switch (triple.getEnvironment()) {
default: llvm_unreachable("Include management is handled in the driver.");
@@ -445,11 +444,6 @@ AddDefaultCPlusPlusIncludePaths(const llvm::Triple &triple, const HeaderSearchOp
case llvm::Triple::Solaris:
AddGnuCPlusPlusIncludePaths("/usr/gcc/4.5/include/c++/4.5.2/",
"i386-pc-solaris2.11", "", "", triple);
- // Solaris - Fall though..
- case llvm::Triple::AuroraUX:
- // AuroraUX
- AddGnuCPlusPlusIncludePaths("/opt/gcc4/include/c++/4.2.4",
- "i386-pc-solaris2.11", "", "", triple);
break;
default:
break;
@@ -473,7 +467,7 @@ void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang,
case llvm::Triple::Win32:
if (triple.getEnvironment() == llvm::Triple::MSVC ||
triple.getEnvironment() == llvm::Triple::Itanium ||
- triple.getObjectFormat() == llvm::Triple::MachO)
+ triple.isOSBinFormatMachO())
return;
break;
}
@@ -535,16 +529,16 @@ static unsigned RemoveDuplicates(std::vector<DirectoryLookup> &SearchList,
if (CurEntry.isNormalDir()) {
// If this isn't the first time we've seen this dir, remove it.
- if (SeenDirs.insert(CurEntry.getDir()))
+ if (SeenDirs.insert(CurEntry.getDir()).second)
continue;
} else if (CurEntry.isFramework()) {
// If this isn't the first time we've seen this framework dir, remove it.
- if (SeenFrameworkDirs.insert(CurEntry.getFrameworkDir()))
+ if (SeenFrameworkDirs.insert(CurEntry.getFrameworkDir()).second)
continue;
} else {
assert(CurEntry.isHeaderMap() && "Not a headermap or normal dir?");
// If this isn't the first time we've seen this headermap, remove it.
- if (SeenHeaderMaps.insert(CurEntry.getHeaderMap()))
+ if (SeenHeaderMaps.insert(CurEntry.getHeaderMap()).second)
continue;
}
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index 7a9d09a5e7ac..f4241a94ae02 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -65,17 +65,14 @@ static void DefineBuiltinMacro(MacroBuilder &Builder, StringRef Macro,
/// AddImplicitInclude - Add an implicit \#include of the specified file to the
/// predefines buffer.
-static void AddImplicitInclude(MacroBuilder &Builder, StringRef File,
- FileManager &FileMgr) {
- Builder.append(Twine("#include \"") +
- HeaderSearch::NormalizeDashIncludePath(File, FileMgr) + "\"");
+/// As these includes are generated by -include arguments the header search
+/// logic is going to search relatively to the current working directory.
+static void AddImplicitInclude(MacroBuilder &Builder, StringRef File) {
+ Builder.append(Twine("#include \"") + File + "\"");
}
-static void AddImplicitIncludeMacros(MacroBuilder &Builder,
- StringRef File,
- FileManager &FileMgr) {
- Builder.append(Twine("#__include_macros \"") +
- HeaderSearch::NormalizeDashIncludePath(File, FileMgr) + "\"");
+static void AddImplicitIncludeMacros(MacroBuilder &Builder, StringRef File) {
+ Builder.append(Twine("#__include_macros \"") + File + "\"");
// Marker token to stop the __include_macros fetch loop.
Builder.append("##"); // ##?
}
@@ -94,7 +91,7 @@ static void AddImplicitIncludePTH(MacroBuilder &Builder, Preprocessor &PP,
return;
}
- AddImplicitInclude(Builder, OriginalFile, PP.getFileManager());
+ AddImplicitInclude(Builder, OriginalFile);
}
/// \brief Add an implicit \#include using the original file used to generate
@@ -107,7 +104,7 @@ static void AddImplicitIncludePCH(MacroBuilder &Builder, Preprocessor &PP,
if (OriginalFile.empty())
return;
- AddImplicitInclude(Builder, OriginalFile, PP.getFileManager());
+ AddImplicitInclude(Builder, OriginalFile);
}
/// PickFP - This is used to pick a value based on the FP semantics of the
@@ -378,7 +375,7 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
// C++1y [cpp.predefined]p1:
// The name __cplusplus is defined to the value 201402L when compiling a
// C++ translation unit.
- else if (LangOpts.CPlusPlus1y)
+ else if (LangOpts.CPlusPlus14)
Builder.defineMacro("__cplusplus", "201402L");
// C++11 [cpp.predefined]p1:
// The name __cplusplus is defined to the value 201103L when compiling a
@@ -412,6 +409,12 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
/// ISO/IEC JTC1/SC22/WG21 (C++) SD-6: "SG10 Feature Test Recommendations".
static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
MacroBuilder &Builder) {
+ // C++98 features.
+ if (LangOpts.RTTI)
+ Builder.defineMacro("__cpp_rtti", "199711");
+ if (LangOpts.CXXExceptions)
+ Builder.defineMacro("__cpp_exceptions", "199711");
+
// C++11 features.
if (LangOpts.CPlusPlus11) {
Builder.defineMacro("__cpp_unicode_characters", "200704");
@@ -420,17 +423,25 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
Builder.defineMacro("__cpp_user_defined_literals", "200809");
Builder.defineMacro("__cpp_lambdas", "200907");
Builder.defineMacro("__cpp_constexpr",
- LangOpts.CPlusPlus1y ? "201304" : "200704");
+ LangOpts.CPlusPlus14 ? "201304" : "200704");
+ Builder.defineMacro("__cpp_range_based_for", "200907");
Builder.defineMacro("__cpp_static_assert", "200410");
Builder.defineMacro("__cpp_decltype", "200707");
Builder.defineMacro("__cpp_attributes", "200809");
Builder.defineMacro("__cpp_rvalue_references", "200610");
Builder.defineMacro("__cpp_variadic_templates", "200704");
+ Builder.defineMacro("__cpp_initializer_lists", "200806");
+ Builder.defineMacro("__cpp_delegating_constructors", "200604");
+ Builder.defineMacro("__cpp_nsdmi", "200809");
+ Builder.defineMacro("__cpp_inheriting_constructors", "200802");
+ Builder.defineMacro("__cpp_ref_qualifiers", "200710");
+ Builder.defineMacro("__cpp_alias_templates", "200704");
}
// C++14 features.
- if (LangOpts.CPlusPlus1y) {
+ 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");
@@ -438,6 +449,8 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
Builder.defineMacro("__cpp_aggregate_nsdmi", "201304");
Builder.defineMacro("__cpp_variable_templates", "201304");
}
+ if (LangOpts.SizedDeallocation)
+ Builder.defineMacro("__cpp_sized_deallocation", "201309");
}
static void InitializePredefinedMacros(const TargetInfo &TI,
@@ -530,6 +543,8 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("IBOutletCollection(ClassName)",
"__attribute__((iboutletcollection(ClassName)))");
Builder.defineMacro("IBAction", "void)__attribute__((ibaction)");
+ Builder.defineMacro("IBInspectable", "");
+ Builder.defineMacro("IB_DESIGNABLE", "");
}
if (LangOpts.CPlusPlus)
@@ -551,7 +566,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("__BLOCKS__");
}
- if (!LangOpts.MSVCCompat && LangOpts.CXXExceptions)
+ if (!LangOpts.MSVCCompat && LangOpts.Exceptions)
Builder.defineMacro("__EXCEPTIONS");
if (!LangOpts.MSVCCompat && LangOpts.RTTI)
Builder.defineMacro("__GXX_RTTI");
@@ -626,12 +641,10 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
DefineTypeSize("__INTMAX_MAX__", TI.getIntMaxType(), TI, Builder);
DefineTypeSize("__SIZE_MAX__", TI.getSizeType(), TI, Builder);
- if (!LangOpts.MSVCCompat) {
- DefineTypeSize("__UINTMAX_MAX__", TI.getUIntMaxType(), TI, Builder);
- DefineTypeSize("__PTRDIFF_MAX__", TI.getPtrDiffType(0), TI, Builder);
- DefineTypeSize("__INTPTR_MAX__", TI.getIntPtrType(), TI, Builder);
- DefineTypeSize("__UINTPTR_MAX__", TI.getUIntPtrType(), TI, Builder);
- }
+ DefineTypeSize("__UINTMAX_MAX__", TI.getUIntMaxType(), TI, Builder);
+ DefineTypeSize("__PTRDIFF_MAX__", TI.getPtrDiffType(0), TI, Builder);
+ DefineTypeSize("__INTPTR_MAX__", TI.getIntPtrType(), TI, Builder);
+ DefineTypeSize("__UINTPTR_MAX__", TI.getUIntPtrType(), TI, Builder);
DefineTypeSizeof("__SIZEOF_DOUBLE__", TI.getDoubleWidth(), TI, Builder);
DefineTypeSizeof("__SIZEOF_FLOAT__", TI.getFloatWidth(), TI, Builder);
@@ -649,7 +662,12 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
TI.getTypeWidth(TI.getWCharType()), TI, Builder);
DefineTypeSizeof("__SIZEOF_WINT_T__",
TI.getTypeWidth(TI.getWIntType()), TI, Builder);
- if (TI.hasInt128Type())
+ // This is a temporary workaround while MIPS64 has not yet fully supported
+ // 128-bit integers. But declaration of int128 type is necessary even though
+ // __SIZEOF_INT128__ is undefined because c++ standard header files like
+ // limits throw error message if __int128 is not available.
+ if (TI.hasInt128Type() && !(TI.getTriple().getArch() == llvm::Triple::mips64el
+ || TI.getTriple().getArch() == llvm::Triple::mips64))
DefineTypeSizeof("__SIZEOF_INT128__", 128, TI, Builder);
DefineType("__INTMAX_TYPE__", TI.getIntMaxType(), Builder);
@@ -679,12 +697,10 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
DefineType("__CHAR16_TYPE__", TI.getChar16Type(), Builder);
DefineType("__CHAR32_TYPE__", TI.getChar32Type(), Builder);
- if (!LangOpts.MSVCCompat) {
- DefineTypeWidth("__UINTMAX_WIDTH__", TI.getUIntMaxType(), TI, Builder);
- DefineType("__UINTPTR_TYPE__", TI.getUIntPtrType(), Builder);
- DefineFmt("__UINTPTR", TI.getUIntPtrType(), TI, Builder);
- DefineTypeWidth("__UINTPTR_WIDTH__", TI.getUIntPtrType(), TI, Builder);
- }
+ DefineTypeWidth("__UINTMAX_WIDTH__", TI.getUIntMaxType(), TI, Builder);
+ DefineType("__UINTPTR_TYPE__", TI.getUIntPtrType(), Builder);
+ DefineFmt("__UINTPTR", TI.getUIntPtrType(), TI, Builder);
+ DefineTypeWidth("__UINTPTR_WIDTH__", TI.getUIntPtrType(), TI, Builder);
DefineFloatMacros(Builder, "FLT", &TI.getFloatFormat(), "F");
DefineFloatMacros(Builder, "DBL", &TI.getDoubleFormat(), "");
@@ -718,54 +734,52 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
if (TI.getLongLongWidth() > TI.getLongWidth())
DefineExactWidthIntType(TargetInfo::SignedLongLong, TI, Builder);
- if (!LangOpts.MSVCCompat) {
- DefineExactWidthIntType(TargetInfo::UnsignedChar, TI, Builder);
- DefineExactWidthIntTypeSize(TargetInfo::UnsignedChar, TI, Builder);
- DefineExactWidthIntTypeSize(TargetInfo::SignedChar, TI, Builder);
-
- if (TI.getShortWidth() > TI.getCharWidth()) {
- DefineExactWidthIntType(TargetInfo::UnsignedShort, TI, Builder);
- DefineExactWidthIntTypeSize(TargetInfo::UnsignedShort, TI, Builder);
- DefineExactWidthIntTypeSize(TargetInfo::SignedShort, TI, Builder);
- }
+ DefineExactWidthIntType(TargetInfo::UnsignedChar, TI, Builder);
+ DefineExactWidthIntTypeSize(TargetInfo::UnsignedChar, TI, Builder);
+ DefineExactWidthIntTypeSize(TargetInfo::SignedChar, TI, Builder);
- if (TI.getIntWidth() > TI.getShortWidth()) {
- DefineExactWidthIntType(TargetInfo::UnsignedInt, TI, Builder);
- DefineExactWidthIntTypeSize(TargetInfo::UnsignedInt, TI, Builder);
- DefineExactWidthIntTypeSize(TargetInfo::SignedInt, TI, Builder);
- }
+ if (TI.getShortWidth() > TI.getCharWidth()) {
+ DefineExactWidthIntType(TargetInfo::UnsignedShort, TI, Builder);
+ DefineExactWidthIntTypeSize(TargetInfo::UnsignedShort, TI, Builder);
+ DefineExactWidthIntTypeSize(TargetInfo::SignedShort, TI, Builder);
+ }
- if (TI.getLongWidth() > TI.getIntWidth()) {
- DefineExactWidthIntType(TargetInfo::UnsignedLong, TI, Builder);
- DefineExactWidthIntTypeSize(TargetInfo::UnsignedLong, TI, Builder);
- DefineExactWidthIntTypeSize(TargetInfo::SignedLong, TI, Builder);
- }
+ if (TI.getIntWidth() > TI.getShortWidth()) {
+ DefineExactWidthIntType(TargetInfo::UnsignedInt, TI, Builder);
+ DefineExactWidthIntTypeSize(TargetInfo::UnsignedInt, TI, Builder);
+ DefineExactWidthIntTypeSize(TargetInfo::SignedInt, TI, Builder);
+ }
- if (TI.getLongLongWidth() > TI.getLongWidth()) {
- DefineExactWidthIntType(TargetInfo::UnsignedLongLong, TI, Builder);
- DefineExactWidthIntTypeSize(TargetInfo::UnsignedLongLong, TI, Builder);
- DefineExactWidthIntTypeSize(TargetInfo::SignedLongLong, TI, Builder);
- }
+ if (TI.getLongWidth() > TI.getIntWidth()) {
+ DefineExactWidthIntType(TargetInfo::UnsignedLong, TI, Builder);
+ DefineExactWidthIntTypeSize(TargetInfo::UnsignedLong, TI, Builder);
+ DefineExactWidthIntTypeSize(TargetInfo::SignedLong, TI, Builder);
+ }
- DefineLeastWidthIntType(8, true, TI, Builder);
- DefineLeastWidthIntType(8, false, TI, Builder);
- DefineLeastWidthIntType(16, true, TI, Builder);
- DefineLeastWidthIntType(16, false, TI, Builder);
- DefineLeastWidthIntType(32, true, TI, Builder);
- DefineLeastWidthIntType(32, false, TI, Builder);
- DefineLeastWidthIntType(64, true, TI, Builder);
- DefineLeastWidthIntType(64, false, TI, Builder);
-
- DefineFastIntType(8, true, TI, Builder);
- DefineFastIntType(8, false, TI, Builder);
- DefineFastIntType(16, true, TI, Builder);
- DefineFastIntType(16, false, TI, Builder);
- DefineFastIntType(32, true, TI, Builder);
- DefineFastIntType(32, false, TI, Builder);
- DefineFastIntType(64, true, TI, Builder);
- DefineFastIntType(64, false, TI, Builder);
+ if (TI.getLongLongWidth() > TI.getLongWidth()) {
+ DefineExactWidthIntType(TargetInfo::UnsignedLongLong, TI, Builder);
+ DefineExactWidthIntTypeSize(TargetInfo::UnsignedLongLong, TI, Builder);
+ DefineExactWidthIntTypeSize(TargetInfo::SignedLongLong, TI, Builder);
}
+ DefineLeastWidthIntType(8, true, TI, Builder);
+ DefineLeastWidthIntType(8, false, TI, Builder);
+ DefineLeastWidthIntType(16, true, TI, Builder);
+ DefineLeastWidthIntType(16, false, TI, Builder);
+ DefineLeastWidthIntType(32, true, TI, Builder);
+ DefineLeastWidthIntType(32, false, TI, Builder);
+ DefineLeastWidthIntType(64, true, TI, Builder);
+ DefineLeastWidthIntType(64, false, TI, Builder);
+
+ DefineFastIntType(8, true, TI, Builder);
+ DefineFastIntType(8, false, TI, Builder);
+ DefineFastIntType(16, true, TI, Builder);
+ DefineFastIntType(16, false, TI, Builder);
+ DefineFastIntType(32, true, TI, Builder);
+ DefineFastIntType(32, false, TI, Builder);
+ DefineFastIntType(64, true, TI, Builder);
+ DefineFastIntType(64, false, TI, Builder);
+
if (const char *Prefix = TI.getUserLabelPrefix())
Builder.defineMacro("__USER_LABEL_PREFIX__", Prefix);
@@ -861,6 +875,13 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
Builder.defineMacro("_OPENMP", "201307");
}
+ // CUDA device path compilaton
+ if (LangOpts.CUDAIsDevice) {
+ // The CUDA_ARCH value is set for the GPU target specified in the NVPTX
+ // backend's target defines.
+ Builder.defineMacro("__CUDA_ARCH__");
+ }
+
// Get other target #defines.
TI.getTargetDefines(LangOpts, Builder);
}
@@ -925,8 +946,7 @@ void clang::InitializePreprocessor(Preprocessor &PP,
// If -imacros are specified, include them now. These are processed before
// any -include directives.
for (unsigned i = 0, e = InitOpts.MacroIncludes.size(); i != e; ++i)
- AddImplicitIncludeMacros(Builder, InitOpts.MacroIncludes[i],
- PP.getFileManager());
+ AddImplicitIncludeMacros(Builder, InitOpts.MacroIncludes[i]);
// Process -include-pch/-include-pth directives.
if (!InitOpts.ImplicitPCHInclude.empty())
@@ -937,7 +957,7 @@ void clang::InitializePreprocessor(Preprocessor &PP,
// Process -include directives.
for (unsigned i = 0, e = InitOpts.Includes.size(); i != e; ++i) {
const std::string &Path = InitOpts.Includes[i];
- AddImplicitInclude(Builder, Path, PP.getFileManager());
+ AddImplicitInclude(Builder, Path);
}
// Exit the command line and go back to <built-in> (2 is LC_LEAVE).
diff --git a/lib/Frontend/LogDiagnosticPrinter.cpp b/lib/Frontend/LogDiagnosticPrinter.cpp
index 19539e0a5eb2..c6a18e0d80d2 100644
--- a/lib/Frontend/LogDiagnosticPrinter.cpp
+++ b/lib/Frontend/LogDiagnosticPrinter.cpp
@@ -18,17 +18,11 @@
using namespace clang;
using namespace markup;
-LogDiagnosticPrinter::LogDiagnosticPrinter(raw_ostream &os,
- DiagnosticOptions *diags,
- bool _OwnsOutputStream)
- : OS(os), LangOpts(nullptr), DiagOpts(diags),
- OwnsOutputStream(_OwnsOutputStream) {
-}
-
-LogDiagnosticPrinter::~LogDiagnosticPrinter() {
- if (OwnsOutputStream)
- delete &OS;
-}
+LogDiagnosticPrinter::LogDiagnosticPrinter(
+ raw_ostream &os, DiagnosticOptions *diags,
+ std::unique_ptr<raw_ostream> StreamOwner)
+ : OS(os), StreamOwner(std::move(StreamOwner)), LangOpts(nullptr),
+ DiagOpts(diags) {}
static StringRef getLevelName(DiagnosticsEngine::Level Level) {
switch (Level) {
@@ -69,6 +63,14 @@ LogDiagnosticPrinter::EmitDiagEntry(llvm::raw_ostream &OS,
<< " ";
EmitString(OS, DE.Message) << '\n';
}
+ OS << " <key>ID</key>\n"
+ << " ";
+ EmitInteger(OS, DE.DiagnosticID) << '\n';
+ if (!DE.WarningOption.empty()) {
+ OS << " <key>WarningOption</key>\n"
+ << " ";
+ EmitString(OS, DE.WarningOption) << '\n';
+ }
OS << " </dict>\n";
}
@@ -128,6 +130,8 @@ void LogDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level,
DE.DiagnosticID = Info.getID();
DE.DiagnosticLevel = Level;
+ DE.WarningOption = DiagnosticIDs::getWarningOptionForDiag(DE.DiagnosticID);
+
// Format the message.
SmallString<100> MessageStr;
Info.FormatDiagnostic(MessageStr);
diff --git a/lib/Frontend/ModuleDependencyCollector.cpp b/lib/Frontend/ModuleDependencyCollector.cpp
index d30f9214f82e..62865e984f65 100644
--- a/lib/Frontend/ModuleDependencyCollector.cpp
+++ b/lib/Frontend/ModuleDependencyCollector.cpp
@@ -13,8 +13,8 @@
#include "clang/Frontend/Utils.h"
#include "clang/Serialization/ASTReader.h"
-#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
@@ -38,7 +38,7 @@ public:
}
void ModuleDependencyCollector::attachToASTReader(ASTReader &R) {
- R.addListener(new ModuleDependencyListener(*this));
+ R.addListener(llvm::make_unique<ModuleDependencyListener>(*this));
}
void ModuleDependencyCollector::writeFileMap() {
@@ -48,49 +48,26 @@ void ModuleDependencyCollector::writeFileMap() {
SmallString<256> Dest = getDest();
llvm::sys::path::append(Dest, "vfs.yaml");
- std::string ErrorInfo;
- llvm::raw_fd_ostream OS(Dest.c_str(), ErrorInfo, llvm::sys::fs::F_Text);
- if (!ErrorInfo.empty()) {
+ std::error_code EC;
+ llvm::raw_fd_ostream OS(Dest, EC, llvm::sys::fs::F_Text);
+ if (EC) {
setHasErrors();
return;
}
VFSWriter.write(OS);
}
-/// Remove traversal (ie, . or ..) from the given absolute path.
-static void removePathTraversal(SmallVectorImpl<char> &Path) {
- using namespace llvm::sys;
- SmallVector<StringRef, 16> ComponentStack;
- StringRef P(Path.data(), Path.size());
-
- // Skip the root path, then look for traversal in the components.
- StringRef Rel = path::relative_path(P);
- for (StringRef C : llvm::make_range(path::begin(Rel), path::end(Rel))) {
- if (C == ".")
- continue;
- if (C == "..") {
- assert(ComponentStack.size() && "Path traverses out of parent");
- ComponentStack.pop_back();
- } else
- ComponentStack.push_back(C);
- }
-
- // The stack is now the path without any directory traversal.
- SmallString<256> Buffer = path::root_path(P);
- for (StringRef C : ComponentStack)
- path::append(Buffer, C);
-
- // Put the result in Path.
- Path.swap(Buffer);
-}
-
std::error_code ModuleDependencyListener::copyToRoot(StringRef Src) {
using namespace llvm::sys;
// We need an absolute path to append to the root.
SmallString<256> AbsoluteSrc = Src;
fs::make_absolute(AbsoluteSrc);
- removePathTraversal(AbsoluteSrc);
+ // Canonicalize to a native path to avoid mixed separator styles.
+ path::native(AbsoluteSrc);
+ // TODO: We probably need to handle .. as well as . in order to have valid
+ // input to the YAMLVFSWriter.
+ FileManager::removeDotPaths(AbsoluteSrc);
// Build the destination path.
SmallString<256> Dest = Collector.getDest();
diff --git a/lib/Frontend/MultiplexConsumer.cpp b/lib/Frontend/MultiplexConsumer.cpp
index 0e933a3f165f..019882833d41 100644
--- a/lib/Frontend/MultiplexConsumer.cpp
+++ b/lib/Frontend/MultiplexConsumer.cpp
@@ -107,6 +107,7 @@ public:
const ObjCPropertyDecl *OrigProp,
const ObjCCategoryDecl *ClassExt) override;
void DeclarationMarkedUsed(const Decl *D) override;
+ void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override;
private:
std::vector<ASTMutationListener*> Listeners;
@@ -180,121 +181,121 @@ void MultiplexASTMutationListener::DeclarationMarkedUsed(const Decl *D) {
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
Listeners[i]->DeclarationMarkedUsed(D);
}
+void MultiplexASTMutationListener::DeclarationMarkedOpenMPThreadPrivate(
+ const Decl *D) {
+ for (size_t i = 0, e = Listeners.size(); i != e; ++i)
+ Listeners[i]->DeclarationMarkedOpenMPThreadPrivate(D);
+}
} // end namespace clang
-MultiplexConsumer::MultiplexConsumer(ArrayRef<ASTConsumer *> C)
- : Consumers(C.begin(), C.end()), MutationListener(),
- DeserializationListener() {
+MultiplexConsumer::MultiplexConsumer(
+ std::vector<std::unique_ptr<ASTConsumer>> C)
+ : Consumers(std::move(C)), MutationListener(), DeserializationListener() {
// Collect the mutation listeners and deserialization listeners of all
// children, and create a multiplex listener each if so.
std::vector<ASTMutationListener*> mutationListeners;
std::vector<ASTDeserializationListener*> serializationListeners;
- for (size_t i = 0, e = Consumers.size(); i != e; ++i) {
- ASTMutationListener* mutationListener =
- Consumers[i]->GetASTMutationListener();
- if (mutationListener)
+ for (auto &Consumer : Consumers) {
+ if (auto *mutationListener = Consumer->GetASTMutationListener())
mutationListeners.push_back(mutationListener);
- ASTDeserializationListener* serializationListener =
- Consumers[i]->GetASTDeserializationListener();
- if (serializationListener)
+ if (auto *serializationListener = Consumer->GetASTDeserializationListener())
serializationListeners.push_back(serializationListener);
}
- if (mutationListeners.size()) {
- MutationListener.reset(new MultiplexASTMutationListener(mutationListeners));
+ if (!mutationListeners.empty()) {
+ MutationListener =
+ llvm::make_unique<MultiplexASTMutationListener>(mutationListeners);
}
- if (serializationListeners.size()) {
- DeserializationListener.reset(
- new MultiplexASTDeserializationListener(serializationListeners));
+ if (!serializationListeners.empty()) {
+ DeserializationListener =
+ llvm::make_unique<MultiplexASTDeserializationListener>(
+ serializationListeners);
}
}
-MultiplexConsumer::~MultiplexConsumer() {
- for (size_t i = 0, e = Consumers.size(); i != e; ++i)
- delete Consumers[i];
-}
+MultiplexConsumer::~MultiplexConsumer() {}
void MultiplexConsumer::Initialize(ASTContext &Context) {
- for (size_t i = 0, e = Consumers.size(); i != e; ++i)
- Consumers[i]->Initialize(Context);
+ for (auto &Consumer : Consumers)
+ Consumer->Initialize(Context);
}
bool MultiplexConsumer::HandleTopLevelDecl(DeclGroupRef D) {
bool Continue = true;
- for (size_t i = 0, e = Consumers.size(); i != e; ++i)
- Continue = Continue && Consumers[i]->HandleTopLevelDecl(D);
+ for (auto &Consumer : Consumers)
+ Continue = Continue && Consumer->HandleTopLevelDecl(D);
return Continue;
}
void MultiplexConsumer::HandleInlineMethodDefinition(CXXMethodDecl *D) {
- for (size_t i = 0, e = Consumers.size(); i != e; ++i)
- Consumers[i]->HandleInlineMethodDefinition(D);
+ for (auto &Consumer : Consumers)
+ Consumer->HandleInlineMethodDefinition(D);
}
-void MultiplexConsumer::HandleCXXStaticMemberVarInstantiation(VarDecl *VD) {
- for (size_t i = 0, e = Consumers.size(); i != e; ++i)
- Consumers[i]->HandleCXXStaticMemberVarInstantiation(VD);
+void MultiplexConsumer::HandleCXXStaticMemberVarInstantiation(VarDecl *VD) {
+ for (auto &Consumer : Consumers)
+ Consumer->HandleCXXStaticMemberVarInstantiation(VD);
}
void MultiplexConsumer::HandleInterestingDecl(DeclGroupRef D) {
- for (size_t i = 0, e = Consumers.size(); i != e; ++i)
- Consumers[i]->HandleInterestingDecl(D);
+ for (auto &Consumer : Consumers)
+ Consumer->HandleInterestingDecl(D);
}
void MultiplexConsumer::HandleTranslationUnit(ASTContext &Ctx) {
- for (size_t i = 0, e = Consumers.size(); i != e; ++i)
- Consumers[i]->HandleTranslationUnit(Ctx);
+ for (auto &Consumer : Consumers)
+ Consumer->HandleTranslationUnit(Ctx);
}
void MultiplexConsumer::HandleTagDeclDefinition(TagDecl *D) {
- for (size_t i = 0, e = Consumers.size(); i != e; ++i)
- Consumers[i]->HandleTagDeclDefinition(D);
+ for (auto &Consumer : Consumers)
+ Consumer->HandleTagDeclDefinition(D);
}
void MultiplexConsumer::HandleTagDeclRequiredDefinition(const TagDecl *D) {
- for (size_t i = 0, e = Consumers.size(); i != e; ++i)
- Consumers[i]->HandleTagDeclRequiredDefinition(D);
+ for (auto &Consumer : Consumers)
+ Consumer->HandleTagDeclRequiredDefinition(D);
}
void MultiplexConsumer::HandleCXXImplicitFunctionInstantiation(FunctionDecl *D){
- for (size_t i = 0, e = Consumers.size(); i != e; ++i)
- Consumers[i]->HandleCXXImplicitFunctionInstantiation(D);
+ for (auto &Consumer : Consumers)
+ Consumer->HandleCXXImplicitFunctionInstantiation(D);
}
void MultiplexConsumer::HandleTopLevelDeclInObjCContainer(DeclGroupRef D) {
- for (size_t i = 0, e = Consumers.size(); i != e; ++i)
- Consumers[i]->HandleTopLevelDeclInObjCContainer(D);
+ for (auto &Consumer : Consumers)
+ Consumer->HandleTopLevelDeclInObjCContainer(D);
}
void MultiplexConsumer::HandleImplicitImportDecl(ImportDecl *D) {
- for (size_t i = 0, e = Consumers.size(); i != e; ++i)
- Consumers[i]->HandleImplicitImportDecl(D);
+ for (auto &Consumer : Consumers)
+ Consumer->HandleImplicitImportDecl(D);
}
void MultiplexConsumer::HandleLinkerOptionPragma(llvm::StringRef Opts) {
- for (size_t i = 0, e = Consumers.size(); i != e; ++i)
- Consumers[i]->HandleLinkerOptionPragma(Opts);
+ for (auto &Consumer : Consumers)
+ Consumer->HandleLinkerOptionPragma(Opts);
}
void MultiplexConsumer::HandleDetectMismatch(llvm::StringRef Name, llvm::StringRef Value) {
- for (size_t i = 0, e = Consumers.size(); i != e; ++i)
- Consumers[i]->HandleDetectMismatch(Name, Value);
+ for (auto &Consumer : Consumers)
+ Consumer->HandleDetectMismatch(Name, Value);
}
void MultiplexConsumer::HandleDependentLibrary(llvm::StringRef Lib) {
- for (size_t i = 0, e = Consumers.size(); i != e; ++i)
- Consumers[i]->HandleDependentLibrary(Lib);
+ for (auto &Consumer : Consumers)
+ Consumer->HandleDependentLibrary(Lib);
}
void MultiplexConsumer::CompleteTentativeDefinition(VarDecl *D) {
- for (size_t i = 0, e = Consumers.size(); i != e; ++i)
- Consumers[i]->CompleteTentativeDefinition(D);
+ for (auto &Consumer : Consumers)
+ Consumer->CompleteTentativeDefinition(D);
}
void MultiplexConsumer::HandleVTable(
CXXRecordDecl *RD, bool DefinitionRequired) {
- for (size_t i = 0, e = Consumers.size(); i != e; ++i)
- Consumers[i]->HandleVTable(RD, DefinitionRequired);
+ for (auto &Consumer : Consumers)
+ Consumer->HandleVTable(RD, DefinitionRequired);
}
ASTMutationListener *MultiplexConsumer::GetASTMutationListener() {
@@ -306,18 +307,18 @@ ASTDeserializationListener *MultiplexConsumer::GetASTDeserializationListener() {
}
void MultiplexConsumer::PrintStats() {
- for (size_t i = 0, e = Consumers.size(); i != e; ++i)
- Consumers[i]->PrintStats();
+ for (auto &Consumer : Consumers)
+ Consumer->PrintStats();
}
void MultiplexConsumer::InitializeSema(Sema &S) {
- for (size_t i = 0, e = Consumers.size(); i != e; ++i)
- if (SemaConsumer *SC = dyn_cast<SemaConsumer>(Consumers[i]))
+ for (auto &Consumer : Consumers)
+ if (SemaConsumer *SC = dyn_cast<SemaConsumer>(Consumer.get()))
SC->InitializeSema(S);
}
void MultiplexConsumer::ForgetSema() {
- for (size_t i = 0, e = Consumers.size(); i != e; ++i)
- if (SemaConsumer *SC = dyn_cast<SemaConsumer>(Consumers[i]))
+ for (auto &Consumer : Consumers)
+ if (SemaConsumer *SC = dyn_cast<SemaConsumer>(Consumer.get()))
SC->ForgetSema();
}
diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp
index 4a6f8dbef928..7c1d9a568831 100644
--- a/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -332,7 +332,10 @@ void PrintPPOutputPPCallbacks::InclusionDirective(SourceLocation HashLoc,
MoveToLine(HashLoc);
OS << "@import " << Imported->getFullModuleName() << ";"
<< " /* clang -E: implicit import for \"" << File->getName() << "\" */";
+ // Since we want a newline after the @import, but not a #<line>, start a new
+ // line immediately.
EmittedTokensOnThisLine = true;
+ startNewLineIfNeeded();
}
}
@@ -724,7 +727,7 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS,
PP.AddPragmaHandler("clang",
new UnknownPragmaHandler("#pragma clang", Callbacks));
- PP.addPPCallbacks(Callbacks);
+ PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks));
// After we have configured the preprocessor, enter the main file.
PP.EnterMainSourceFile();
diff --git a/lib/Frontend/Rewrite/FixItRewriter.cpp b/lib/Frontend/Rewrite/FixItRewriter.cpp
index 8b7af7166c8f..a3e14f9f020e 100644
--- a/lib/Frontend/Rewrite/FixItRewriter.cpp
+++ b/lib/Frontend/Rewrite/FixItRewriter.cpp
@@ -36,14 +36,13 @@ FixItRewriter::FixItRewriter(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
FixItOpts(FixItOpts),
NumFailures(0),
PrevDiagSilenced(false) {
- OwnsClient = Diags.ownsClient();
- Client = Diags.takeClient();
- Diags.setClient(this);
+ Owner = Diags.takeClient();
+ Client = Diags.getClient();
+ Diags.setClient(this, false);
}
FixItRewriter::~FixItRewriter() {
- Diags.takeClient();
- Diags.setClient(Client, OwnsClient);
+ Diags.setClient(Client, Owner.release() != nullptr);
}
bool FixItRewriter::WriteFixedFile(FileID ID, raw_ostream &OS) {
@@ -86,17 +85,16 @@ bool FixItRewriter::WriteFixedFiles(
const FileEntry *Entry = Rewrite.getSourceMgr().getFileEntryForID(I->first);
int fd;
std::string Filename = FixItOpts->RewriteFilename(Entry->getName(), fd);
- std::string Err;
+ std::error_code EC;
std::unique_ptr<llvm::raw_fd_ostream> OS;
if (fd != -1) {
OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true));
} else {
- OS.reset(new llvm::raw_fd_ostream(Filename.c_str(), Err,
- llvm::sys::fs::F_None));
+ OS.reset(new llvm::raw_fd_ostream(Filename, EC, llvm::sys::fs::F_None));
}
- if (!Err.empty()) {
- Diags.Report(clang::diag::err_fe_unable_to_open_output)
- << Filename << Err;
+ if (EC) {
+ Diags.Report(clang::diag::err_fe_unable_to_open_output) << Filename
+ << EC.message();
continue;
}
RewriteBuffer &RewriteBuf = I->second;
@@ -189,12 +187,10 @@ 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
// format the diagnostic.
- Diags.takeClient();
- Diags.setClient(Client);
+ Diags.setClient(Client, false);
Diags.Clear();
Diags.Report(Loc, DiagID);
- Diags.takeClient();
- Diags.setClient(this);
+ Diags.setClient(this, false);
}
FixItOptions::~FixItOptions() {}
diff --git a/lib/Frontend/Rewrite/FrontendActions.cpp b/lib/Frontend/Rewrite/FrontendActions.cpp
index 59fef736f16a..1b5eb2855bea 100644
--- a/lib/Frontend/Rewrite/FrontendActions.cpp
+++ b/lib/Frontend/Rewrite/FrontendActions.cpp
@@ -30,8 +30,8 @@ using namespace clang;
// AST Consumer Actions
//===----------------------------------------------------------------------===//
-ASTConsumer *HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
+std::unique_ptr<ASTConsumer>
+HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
return CreateHTMLPrinter(OS, CI.getPreprocessor());
return nullptr;
@@ -40,9 +40,9 @@ ASTConsumer *HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI,
FixItAction::FixItAction() {}
FixItAction::~FixItAction() {}
-ASTConsumer *FixItAction::CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
- return new ASTConsumer();
+std::unique_ptr<ASTConsumer>
+FixItAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
+ return llvm::make_unique<ASTConsumer>();
}
namespace {
@@ -148,8 +148,8 @@ bool FixItRecompile::BeginInvocation(CompilerInstance &CI) {
#ifdef CLANG_ENABLE_OBJC_REWRITER
-ASTConsumer *RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
+std::unique_ptr<ASTConsumer>
+RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "cpp")) {
if (CI.getLangOpts().ObjCRuntime.isNonFragile())
return CreateModernObjCRewriter(InFile, OS,
diff --git a/lib/Frontend/Rewrite/HTMLPrint.cpp b/lib/Frontend/Rewrite/HTMLPrint.cpp
index 64da05fdde61..22ccfe6936b7 100644
--- a/lib/Frontend/Rewrite/HTMLPrint.cpp
+++ b/lib/Frontend/Rewrite/HTMLPrint.cpp
@@ -47,11 +47,12 @@ namespace {
};
}
-ASTConsumer* clang::CreateHTMLPrinter(raw_ostream *OS,
- Preprocessor &PP,
- bool SyntaxHighlight,
- bool HighlightMacros) {
- return new HTMLPrinter(OS, PP, SyntaxHighlight, HighlightMacros);
+std::unique_ptr<ASTConsumer> clang::CreateHTMLPrinter(raw_ostream *OS,
+ Preprocessor &PP,
+ bool SyntaxHighlight,
+ bool HighlightMacros) {
+ return llvm::make_unique<HTMLPrinter>(OS, PP, SyntaxHighlight,
+ HighlightMacros);
}
void HTMLPrinter::Initialize(ASTContext &context) {
diff --git a/lib/Frontend/Rewrite/InclusionRewriter.cpp b/lib/Frontend/Rewrite/InclusionRewriter.cpp
index aa7017baee26..140055735a99 100644
--- a/lib/Frontend/Rewrite/InclusionRewriter.cpp
+++ b/lib/Frontend/Rewrite/InclusionRewriter.cpp
@@ -40,6 +40,7 @@ class InclusionRewriter : public PPCallbacks {
Preprocessor &PP; ///< Used to find inclusion directives.
SourceManager &SM; ///< Used to read and manage source files.
raw_ostream &OS; ///< The destination stream for rewritten contents.
+ StringRef MainEOL; ///< The line ending marker to use.
const llvm::MemoryBuffer *PredefinesBuffer; ///< The preprocessor predefines.
bool ShowLineMarkers; ///< Show #line markers.
bool UseLineDirective; ///< Use of line directives or line markers.
@@ -54,6 +55,7 @@ public:
void setPredefinesBuffer(const llvm::MemoryBuffer *Buf) {
PredefinesBuffer = Buf;
}
+ void detectMainFileEOL();
private:
void FileChanged(SourceLocation Loc, FileChangeReason Reason,
SrcMgr::CharacteristicKind FileType,
@@ -67,8 +69,8 @@ private:
const Module *Imported) override;
void WriteLineInfo(const char *Filename, int Line,
SrcMgr::CharacteristicKind FileType,
- StringRef EOL, StringRef Extra = StringRef());
- void WriteImplicitModuleImport(const Module *Mod, StringRef EOL);
+ StringRef Extra = StringRef());
+ void WriteImplicitModuleImport(const Module *Mod);
void OutputContentUpTo(const MemoryBuffer &FromFile,
unsigned &WriteFrom, unsigned WriteTo,
StringRef EOL, int &lines,
@@ -88,9 +90,9 @@ private:
/// Initializes an InclusionRewriter with a \p PP source and \p OS destination.
InclusionRewriter::InclusionRewriter(Preprocessor &PP, raw_ostream &OS,
bool ShowLineMarkers)
- : PP(PP), SM(PP.getSourceManager()), OS(OS), PredefinesBuffer(nullptr),
- ShowLineMarkers(ShowLineMarkers),
- LastInsertedFileChange(FileChanges.end()) {
+ : PP(PP), SM(PP.getSourceManager()), OS(OS), MainEOL("\n"),
+ PredefinesBuffer(nullptr), ShowLineMarkers(ShowLineMarkers),
+ LastInsertedFileChange(FileChanges.end()) {
// If we're in microsoft mode, use normal #line instead of line markers.
UseLineDirective = PP.getLangOpts().MicrosoftExt;
}
@@ -101,7 +103,7 @@ InclusionRewriter::InclusionRewriter(Preprocessor &PP, raw_ostream &OS,
/// any \p Extra context specifiers in GNU line directives.
void InclusionRewriter::WriteLineInfo(const char *Filename, int Line,
SrcMgr::CharacteristicKind FileType,
- StringRef EOL, StringRef Extra) {
+ StringRef Extra) {
if (!ShowLineMarkers)
return;
if (UseLineDirective) {
@@ -125,13 +127,12 @@ void InclusionRewriter::WriteLineInfo(const char *Filename, int Line,
// should be treated as being wrapped in an implicit extern "C" block."
OS << " 3 4";
}
- OS << EOL;
+ OS << MainEOL;
}
-void InclusionRewriter::WriteImplicitModuleImport(const Module *Mod,
- StringRef EOL) {
+void InclusionRewriter::WriteImplicitModuleImport(const Module *Mod) {
OS << "@import " << Mod->getFullModuleName() << ";"
- << " /* clang -frewrite-includes: implicit import */" << EOL;
+ << " /* clang -frewrite-includes: implicit import */" << MainEOL;
}
/// FileChanged - Whenever the preprocessor enters or exits a #include file
@@ -197,23 +198,33 @@ InclusionRewriter::FindFileChangeLocation(SourceLocation Loc) const {
/// Detect the likely line ending style of \p FromFile by examining the first
/// newline found within it.
static StringRef DetectEOL(const MemoryBuffer &FromFile) {
- // detect what line endings the file uses, so that added content does not mix
- // the style
+ // Detect what line endings the file uses, so that added content does not mix
+ // the style. We need to check for "\r\n" first because "\n\r" will match
+ // "\r\n\r\n".
const char *Pos = strchr(FromFile.getBufferStart(), '\n');
if (!Pos)
return "\n";
- if (Pos + 1 < FromFile.getBufferEnd() && Pos[1] == '\r')
- return "\n\r";
if (Pos - 1 >= FromFile.getBufferStart() && Pos[-1] == '\r')
return "\r\n";
+ if (Pos + 1 < FromFile.getBufferEnd() && Pos[1] == '\r')
+ return "\n\r";
return "\n";
}
+void InclusionRewriter::detectMainFileEOL() {
+ bool Invalid;
+ const MemoryBuffer &FromFile = *SM.getBuffer(SM.getMainFileID(), &Invalid);
+ assert(!Invalid);
+ if (Invalid)
+ return; // Should never happen, but whatever.
+ MainEOL = DetectEOL(FromFile);
+}
+
/// Writes out bytes from \p FromFile, starting at \p NextToWrite and ending at
/// \p WriteTo - 1.
void InclusionRewriter::OutputContentUpTo(const MemoryBuffer &FromFile,
unsigned &WriteFrom, unsigned WriteTo,
- StringRef EOL, int &Line,
+ StringRef LocalEOL, int &Line,
bool EnsureNewline) {
if (WriteTo <= WriteFrom)
return;
@@ -222,14 +233,37 @@ void InclusionRewriter::OutputContentUpTo(const MemoryBuffer &FromFile,
WriteFrom = WriteTo;
return;
}
- OS.write(FromFile.getBufferStart() + WriteFrom, WriteTo - WriteFrom);
- // count lines manually, it's faster than getPresumedLoc()
- Line += std::count(FromFile.getBufferStart() + WriteFrom,
- FromFile.getBufferStart() + WriteTo, '\n');
- if (EnsureNewline) {
- char LastChar = FromFile.getBufferStart()[WriteTo - 1];
- if (LastChar != '\n' && LastChar != '\r')
- OS << EOL;
+
+ // If we would output half of a line ending, advance one character to output
+ // the whole line ending. All buffers are null terminated, so looking ahead
+ // one byte is safe.
+ if (LocalEOL.size() == 2 &&
+ LocalEOL[0] == (FromFile.getBufferStart() + WriteTo)[-1] &&
+ LocalEOL[1] == (FromFile.getBufferStart() + WriteTo)[0])
+ WriteTo++;
+
+ StringRef TextToWrite(FromFile.getBufferStart() + WriteFrom,
+ WriteTo - WriteFrom);
+
+ if (MainEOL == LocalEOL) {
+ OS << TextToWrite;
+ // count lines manually, it's faster than getPresumedLoc()
+ Line += TextToWrite.count(LocalEOL);
+ if (EnsureNewline && !TextToWrite.endswith(LocalEOL))
+ OS << MainEOL;
+ } else {
+ // Output the file one line at a time, rewriting the line endings as we go.
+ StringRef Rest = TextToWrite;
+ while (!Rest.empty()) {
+ StringRef LineText;
+ std::tie(LineText, Rest) = Rest.split(LocalEOL);
+ OS << LineText;
+ Line++;
+ if (!Rest.empty())
+ OS << MainEOL;
+ }
+ if (TextToWrite.endswith(LocalEOL) || EnsureNewline)
+ OS << MainEOL;
}
WriteFrom = WriteTo;
}
@@ -242,10 +276,11 @@ void InclusionRewriter::OutputContentUpTo(const MemoryBuffer &FromFile,
void InclusionRewriter::CommentOutDirective(Lexer &DirectiveLex,
const Token &StartToken,
const MemoryBuffer &FromFile,
- StringRef EOL,
+ StringRef LocalEOL,
unsigned &NextToWrite, int &Line) {
OutputContentUpTo(FromFile, NextToWrite,
- SM.getFileOffset(StartToken.getLocation()), EOL, Line, false);
+ SM.getFileOffset(StartToken.getLocation()), LocalEOL, Line,
+ false);
Token DirectiveToken;
do {
DirectiveLex.LexFromRawLexer(DirectiveToken);
@@ -254,11 +289,12 @@ void InclusionRewriter::CommentOutDirective(Lexer &DirectiveLex,
// OutputContentUpTo() would not output anything anyway.
return;
}
- OS << "#if 0 /* expanded by -frewrite-includes */" << EOL;
+ OS << "#if 0 /* expanded by -frewrite-includes */" << MainEOL;
OutputContentUpTo(FromFile, NextToWrite,
- SM.getFileOffset(DirectiveToken.getLocation()) + DirectiveToken.getLength(),
- EOL, Line, true);
- OS << "#endif /* expanded by -frewrite-includes */" << EOL;
+ SM.getFileOffset(DirectiveToken.getLocation()) +
+ DirectiveToken.getLength(),
+ LocalEOL, Line, true);
+ OS << "#endif /* expanded by -frewrite-includes */" << MainEOL;
}
/// Find the next identifier in the pragma directive specified by \p RawToken.
@@ -333,10 +369,13 @@ bool InclusionRewriter::HandleHasInclude(
// FIXME: Subframeworks aren't handled here. Do we care?
bool isAngled = PP.GetIncludeFilenameSpelling(Tok.getLocation(), Filename);
const DirectoryLookup *CurDir;
+ const FileEntry *FileEnt = PP.getSourceManager().getFileEntryForID(FileId);
+ SmallVector<std::pair<const FileEntry *, const DirectoryEntry *>, 1>
+ Includers;
+ Includers.push_back(std::make_pair(FileEnt, FileEnt->getDir()));
const FileEntry *File = PP.getHeaderSearchInfo().LookupFile(
- Filename, SourceLocation(), isAngled, nullptr, CurDir,
- PP.getSourceManager().getFileEntryForID(FileId), nullptr, nullptr,
- nullptr, false);
+ Filename, SourceLocation(), isAngled, nullptr, CurDir, Includers, nullptr,
+ nullptr, nullptr, false);
FileExists = File != nullptr;
return true;
@@ -355,13 +394,13 @@ bool InclusionRewriter::Process(FileID FileId,
Lexer RawLex(FileId, &FromFile, PP.getSourceManager(), PP.getLangOpts());
RawLex.SetCommentRetentionState(false);
- StringRef EOL = DetectEOL(FromFile);
+ StringRef LocalEOL = DetectEOL(FromFile);
// Per the GNU docs: "1" indicates entering a new file.
if (FileId == SM.getMainFileID() || FileId == PP.getPredefinesFileID())
- WriteLineInfo(FileName, 1, FileType, EOL, "");
+ WriteLineInfo(FileName, 1, FileType, "");
else
- WriteLineInfo(FileName, 1, FileType, EOL, " 1");
+ WriteLineInfo(FileName, 1, FileType, " 1");
if (SM.getFileIDSize(FileId) == 0)
return false;
@@ -389,15 +428,15 @@ bool InclusionRewriter::Process(FileID FileId,
case tok::pp_include:
case tok::pp_include_next:
case tok::pp_import: {
- CommentOutDirective(RawLex, HashToken, FromFile, EOL, NextToWrite,
+ CommentOutDirective(RawLex, HashToken, FromFile, LocalEOL, NextToWrite,
Line);
if (FileId != PP.getPredefinesFileID())
- WriteLineInfo(FileName, Line - 1, FileType, EOL, "");
+ WriteLineInfo(FileName, Line - 1, FileType, "");
StringRef LineInfoExtra;
if (const FileChange *Change = FindFileChangeLocation(
HashToken.getLocation())) {
if (Change->Mod) {
- WriteImplicitModuleImport(Change->Mod, EOL);
+ WriteImplicitModuleImport(Change->Mod);
// else now include and recursively process the file
} else if (Process(Change->Id, Change->FileType)) {
@@ -410,7 +449,7 @@ bool InclusionRewriter::Process(FileID FileId,
}
// fix up lineinfo (since commented out directive changed line
// numbers) for inclusions that were skipped due to header guards
- WriteLineInfo(FileName, Line, FileType, EOL, LineInfoExtra);
+ WriteLineInfo(FileName, Line, FileType, LineInfoExtra);
break;
}
case tok::pp_pragma: {
@@ -418,17 +457,17 @@ bool InclusionRewriter::Process(FileID FileId,
if (Identifier == "clang" || Identifier == "GCC") {
if (NextIdentifierName(RawLex, RawToken) == "system_header") {
// keep the directive in, commented out
- CommentOutDirective(RawLex, HashToken, FromFile, EOL,
+ CommentOutDirective(RawLex, HashToken, FromFile, LocalEOL,
NextToWrite, Line);
// update our own type
FileType = SM.getFileCharacteristic(RawToken.getLocation());
- WriteLineInfo(FileName, Line, FileType, EOL);
+ WriteLineInfo(FileName, Line, FileType);
}
} else if (Identifier == "once") {
// keep the directive in, commented out
- CommentOutDirective(RawLex, HashToken, FromFile, EOL,
+ CommentOutDirective(RawLex, HashToken, FromFile, LocalEOL,
NextToWrite, Line);
- WriteLineInfo(FileName, Line, FileType, EOL);
+ WriteLineInfo(FileName, Line, FileType);
}
break;
}
@@ -468,12 +507,12 @@ bool InclusionRewriter::Process(FileID FileId,
// Replace the macro with (0) or (1), followed by the commented
// out macro for reference.
OutputContentUpTo(FromFile, NextToWrite, SM.getFileOffset(Loc),
- EOL, Line, false);
+ LocalEOL, Line, false);
OS << '(' << (int) HasFile << ")/*";
OutputContentUpTo(FromFile, NextToWrite,
SM.getFileOffset(RawToken.getLocation()) +
- RawToken.getLength(),
- EOL, Line, false);
+ RawToken.getLength(),
+ LocalEOL, Line, false);
OS << "*/";
}
} while (RawToken.isNot(tok::eod));
@@ -481,8 +520,8 @@ bool InclusionRewriter::Process(FileID FileId,
OutputContentUpTo(FromFile, NextToWrite,
SM.getFileOffset(RawToken.getLocation()) +
RawToken.getLength(),
- EOL, Line, /*EnsureNewLine*/ true);
- WriteLineInfo(FileName, Line, FileType, EOL);
+ LocalEOL, Line, /*EnsureNewline=*/ true);
+ WriteLineInfo(FileName, Line, FileType);
}
break;
}
@@ -497,11 +536,11 @@ bool InclusionRewriter::Process(FileID FileId,
do {
RawLex.LexFromRawLexer(RawToken);
} while (RawToken.isNot(tok::eod) && RawToken.isNot(tok::eof));
- OutputContentUpTo(
- FromFile, NextToWrite,
- SM.getFileOffset(RawToken.getLocation()) + RawToken.getLength(),
- EOL, Line, /*EnsureNewLine*/ true);
- WriteLineInfo(FileName, Line, FileType, EOL);
+ OutputContentUpTo(FromFile, NextToWrite,
+ SM.getFileOffset(RawToken.getLocation()) +
+ RawToken.getLength(),
+ LocalEOL, Line, /*EnsureNewline=*/ true);
+ WriteLineInfo(FileName, Line, FileType);
RawLex.SetKeepWhitespaceMode(false);
}
default:
@@ -513,8 +552,8 @@ bool InclusionRewriter::Process(FileID FileId,
RawLex.LexFromRawLexer(RawToken);
}
OutputContentUpTo(FromFile, NextToWrite,
- SM.getFileOffset(SM.getLocForEndOfFile(FileId)), EOL, Line,
- /*EnsureNewline*/true);
+ SM.getFileOffset(SM.getLocForEndOfFile(FileId)), LocalEOL,
+ Line, /*EnsureNewline=*/true);
return true;
}
@@ -524,7 +563,9 @@ void clang::RewriteIncludesInInput(Preprocessor &PP, raw_ostream *OS,
SourceManager &SM = PP.getSourceManager();
InclusionRewriter *Rewrite = new InclusionRewriter(PP, *OS,
Opts.ShowLineMarkers);
- PP.addPPCallbacks(Rewrite);
+ Rewrite->detectMainFileEOL();
+
+ PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Rewrite));
PP.IgnorePragmas();
// First let the preprocessor process the entire file and call callbacks.
diff --git a/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/lib/Frontend/Rewrite/RewriteModernObjC.cpp
index 3e18a8b415a3..47f8189f2313 100644
--- a/lib/Frontend/Rewrite/RewriteModernObjC.cpp
+++ b/lib/Frontend/Rewrite/RewriteModernObjC.cpp
@@ -249,27 +249,16 @@ namespace {
void HandleTranslationUnit(ASTContext &C) override;
void ReplaceStmt(Stmt *Old, Stmt *New) {
- Stmt *ReplacingStmt = ReplacedNodes[Old];
-
- if (ReplacingStmt)
- return; // We can't rewrite the same node twice.
-
- if (DisableReplaceStmt)
- return;
-
- // If replacement succeeded or warning disabled return with no warning.
- if (!Rewrite.ReplaceStmt(Old, New)) {
- ReplacedNodes[Old] = New;
- return;
- }
- if (SilenceRewriteMacroWarning)
- return;
- Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
- << Old->getSourceRange();
+ ReplaceStmtWithRange(Old, New, Old->getSourceRange());
}
void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {
assert(Old != nullptr && New != nullptr && "Expected non-null Stmt's");
+
+ Stmt *ReplacingStmt = ReplacedNodes[Old];
+ if (ReplacingStmt)
+ return; // We can't rewrite the same node twice.
+
if (DisableReplaceStmt)
return;
@@ -508,7 +497,7 @@ namespace {
void GetBlockDeclRefExprs(Stmt *S);
void GetInnerBlockDeclRefExprs(Stmt *S,
SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,
- llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts);
+ llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts);
// We avoid calling Type::isBlockPointerType(), since it operates on the
// canonical type. We only care if the top-level type is a closure pointer.
@@ -675,14 +664,11 @@ RewriteModernObjC::RewriteModernObjC(std::string inFile, raw_ostream* OS,
"for @try/@finally (code may not execute properly)");
}
-ASTConsumer *clang::CreateModernObjCRewriter(const std::string& InFile,
- raw_ostream* OS,
- DiagnosticsEngine &Diags,
- const LangOptions &LOpts,
- bool SilenceRewriteMacroWarning,
- bool LineInfo) {
- return new RewriteModernObjC(InFile, OS, Diags, LOpts,
- SilenceRewriteMacroWarning, LineInfo);
+std::unique_ptr<ASTConsumer> clang::CreateModernObjCRewriter(
+ const std::string &InFile, raw_ostream *OS, DiagnosticsEngine &Diags,
+ const LangOptions &LOpts, bool SilenceRewriteMacroWarning, bool LineInfo) {
+ return llvm::make_unique<RewriteModernObjC>(
+ InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning, LineInfo);
}
void RewriteModernObjC::InitializeCommon(ASTContext &context) {
@@ -4055,7 +4041,7 @@ void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
ReplaceText(LocStart, endBuf-startBuf, Result);
// Mark this struct as having been generated.
- if (!ObjCSynthesizedStructs.insert(CDecl))
+ if (!ObjCSynthesizedStructs.insert(CDecl).second)
llvm_unreachable("struct already synthesize- RewriteObjCInternalStruct");
}
@@ -4070,9 +4056,7 @@ void RewriteModernObjC::RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl,
return;
llvm::DenseSet<std::pair<const ObjCInterfaceDecl*, unsigned> > GroupSymbolOutput;
- for (llvm::SmallPtrSet<ObjCIvarDecl *, 8>::iterator i = Ivars.begin(),
- e = Ivars.end(); i != e; i++) {
- ObjCIvarDecl *IvarDecl = (*i);
+ for (ObjCIvarDecl *IvarDecl : Ivars) {
const ObjCInterfaceDecl *IDecl = IvarDecl->getContainingInterface();
unsigned GroupNo = 0;
if (IvarDecl->isBitField()) {
@@ -4256,14 +4240,12 @@ std::string RewriteModernObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
S += "(" + StructRef;
S += "*dst, " + StructRef;
S += "*src) {";
- for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
- E = ImportedBlockDecls.end(); I != E; ++I) {
- ValueDecl *VD = (*I);
+ for (ValueDecl *VD : ImportedBlockDecls) {
S += "_Block_object_assign((void*)&dst->";
- S += (*I)->getNameAsString();
+ S += VD->getNameAsString();
S += ", (void*)src->";
- S += (*I)->getNameAsString();
- if (BlockByRefDeclsPtrSet.count((*I)))
+ S += VD->getNameAsString();
+ if (BlockByRefDeclsPtrSet.count(VD))
S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
else if (VD->getType()->isBlockPointerType())
S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
@@ -4277,12 +4259,10 @@ std::string RewriteModernObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
S += "_block_dispose_" + utostr(i);
S += "(" + StructRef;
S += "*src) {";
- for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
- E = ImportedBlockDecls.end(); I != E; ++I) {
- ValueDecl *VD = (*I);
+ for (ValueDecl *VD : ImportedBlockDecls) {
S += "_Block_object_dispose((void*)src->";
- S += (*I)->getNameAsString();
- if (BlockByRefDeclsPtrSet.count((*I)))
+ S += VD->getNameAsString();
+ if (BlockByRefDeclsPtrSet.count(VD))
S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
else if (VD->getType()->isBlockPointerType())
S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
@@ -4583,22 +4563,18 @@ void RewriteModernObjC::GetBlockDeclRefExprs(Stmt *S) {
GetBlockDeclRefExprs(*CI);
}
// Handle specific things.
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
- if (DRE->refersToEnclosingLocal()) {
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))
+ if (DRE->refersToEnclosingVariableOrCapture() ||
+ HasLocalVariableExternalStorage(DRE->getDecl()))
// FIXME: Handle enums.
- if (!isa<FunctionDecl>(DRE->getDecl()))
- BlockDeclRefs.push_back(DRE);
- if (HasLocalVariableExternalStorage(DRE->getDecl()))
- BlockDeclRefs.push_back(DRE);
- }
- }
-
+ BlockDeclRefs.push_back(DRE);
+
return;
}
void RewriteModernObjC::GetInnerBlockDeclRefExprs(Stmt *S,
SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,
- llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts) {
+ llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {
for (Stmt::child_range CI = S->children(); CI; ++CI)
if (*CI) {
if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
@@ -4615,11 +4591,11 @@ void RewriteModernObjC::GetInnerBlockDeclRefExprs(Stmt *S,
}
// Handle specific things.
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
- if (DRE->refersToEnclosingLocal()) {
- if (!isa<FunctionDecl>(DRE->getDecl()) &&
- !InnerContexts.count(DRE->getDecl()->getDeclContext()))
+ if (DRE->refersToEnclosingVariableOrCapture() ||
+ HasLocalVariableExternalStorage(DRE->getDecl())) {
+ if (!InnerContexts.count(DRE->getDecl()->getDeclContext()))
InnerBlockDeclRefs.push_back(DRE);
- if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl()))
+ if (VarDecl *Var = cast<VarDecl>(DRE->getDecl()))
if (Var->isFunctionOrMethodVarDecl())
ImportedLocalExternalDecls.insert(Var);
}
@@ -4796,7 +4772,8 @@ Stmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {
// Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR
// for each DeclRefExp where BYREFVAR is name of the variable.
ValueDecl *VD = DeclRefExp->getDecl();
- bool isArrow = DeclRefExp->refersToEnclosingLocal();
+ bool isArrow = DeclRefExp->refersToEnclosingVariableOrCapture() ||
+ HasLocalVariableExternalStorage(DeclRefExp->getDecl());
FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
@@ -5546,6 +5523,10 @@ Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
VK_RValue, OK_Ordinary, SourceLocation());
NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
NewRep);
+ // Put Paren around the call.
+ NewRep = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
+ NewRep);
+
BlockDeclRefs.clear();
BlockByRefDecls.clear();
BlockByRefDeclsPtrSet.clear();
@@ -5978,10 +5959,9 @@ void RewriteModernObjC::HandleTranslationUnit(ASTContext &C) {
// Here's a great place to add any extra declarations that may be needed.
// Write out meta data for each @protocol(<expr>).
- for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(),
- E = ProtocolExprDecls.end(); I != E; ++I) {
- RewriteObjCProtocolMetaData(*I, Preamble);
- Write_ProtocolExprReferencedMetadata(Context, (*I), Preamble);
+ for (ObjCProtocolDecl *ProtDecl : ProtocolExprDecls) {
+ RewriteObjCProtocolMetaData(ProtDecl, Preamble);
+ Write_ProtocolExprReferencedMetadata(Context, ProtDecl, Preamble);
}
InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false);
@@ -7122,7 +7102,7 @@ void RewriteModernObjC::RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl,
Result += ";\n";
// Mark this protocol as having been generated.
- if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()))
+ if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()).second)
llvm_unreachable("protocol already synthesized");
}
diff --git a/lib/Frontend/Rewrite/RewriteObjC.cpp b/lib/Frontend/Rewrite/RewriteObjC.cpp
index 7a721771759a..519681085f56 100644
--- a/lib/Frontend/Rewrite/RewriteObjC.cpp
+++ b/lib/Frontend/Rewrite/RewriteObjC.cpp
@@ -198,27 +198,16 @@ namespace {
void HandleTranslationUnit(ASTContext &C) override;
void ReplaceStmt(Stmt *Old, Stmt *New) {
- Stmt *ReplacingStmt = ReplacedNodes[Old];
-
- if (ReplacingStmt)
- return; // We can't rewrite the same node twice.
-
- if (DisableReplaceStmt)
- return;
-
- // If replacement succeeded or warning disabled return with no warning.
- if (!Rewrite.ReplaceStmt(Old, New)) {
- ReplacedNodes[Old] = New;
- return;
- }
- if (SilenceRewriteMacroWarning)
- return;
- Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
- << Old->getSourceRange();
+ ReplaceStmtWithRange(Old, New, Old->getSourceRange());
}
void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {
assert(Old != nullptr && New != nullptr && "Expected non-null Stmt's");
+
+ Stmt *ReplacingStmt = ReplacedNodes[Old];
+ if (ReplacingStmt)
+ return; // We can't rewrite the same node twice.
+
if (DisableReplaceStmt)
return;
@@ -332,7 +321,7 @@ namespace {
void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
std::string &Result);
- virtual void Initialize(ASTContext &context) override = 0;
+ void Initialize(ASTContext &context) override = 0;
// Metadata Rewriting.
virtual void RewriteMetaDataIntoBuffer(std::string &Result) = 0;
@@ -413,7 +402,7 @@ namespace {
void GetBlockDeclRefExprs(Stmt *S);
void GetInnerBlockDeclRefExprs(Stmt *S,
SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,
- llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts);
+ llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts);
// We avoid calling Type::isBlockPointerType(), since it operates on the
// canonical type. We only care if the top-level type is a closure pointer.
@@ -524,7 +513,7 @@ namespace {
silenceMacroWarn) {}
~RewriteObjCFragileABI() {}
- virtual void Initialize(ASTContext &context) override;
+ void Initialize(ASTContext &context) override;
// Rewriting metadata
template<typename MethodIterator>
@@ -600,12 +589,12 @@ RewriteObjC::RewriteObjC(std::string inFile, raw_ostream* OS,
"for @try/@finally (code may not execute properly)");
}
-ASTConsumer *clang::CreateObjCRewriter(const std::string& InFile,
- raw_ostream* OS,
- DiagnosticsEngine &Diags,
- const LangOptions &LOpts,
- bool SilenceRewriteMacroWarning) {
- return new RewriteObjCFragileABI(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning);
+std::unique_ptr<ASTConsumer>
+clang::CreateObjCRewriter(const std::string &InFile, raw_ostream *OS,
+ DiagnosticsEngine &Diags, const LangOptions &LOpts,
+ bool SilenceRewriteMacroWarning) {
+ return llvm::make_unique<RewriteObjCFragileABI>(InFile, OS, Diags, LOpts,
+ SilenceRewriteMacroWarning);
}
void RewriteObjC::InitializeCommon(ASTContext &context) {
@@ -3238,7 +3227,7 @@ void RewriteObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
ReplaceText(LocStart, endBuf-startBuf, Result);
}
// Mark this struct as having been generated.
- if (!ObjCSynthesizedStructs.insert(CDecl))
+ if (!ObjCSynthesizedStructs.insert(CDecl).second)
llvm_unreachable("struct already synthesize- SynthesizeObjCInternalStruct");
}
@@ -3382,14 +3371,12 @@ std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
S += "(" + StructRef;
S += "*dst, " + StructRef;
S += "*src) {";
- for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
- E = ImportedBlockDecls.end(); I != E; ++I) {
- ValueDecl *VD = (*I);
+ for (ValueDecl *VD : ImportedBlockDecls) {
S += "_Block_object_assign((void*)&dst->";
- S += (*I)->getNameAsString();
+ S += VD->getNameAsString();
S += ", (void*)src->";
- S += (*I)->getNameAsString();
- if (BlockByRefDeclsPtrSet.count((*I)))
+ S += VD->getNameAsString();
+ if (BlockByRefDeclsPtrSet.count(VD))
S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
else if (VD->getType()->isBlockPointerType())
S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
@@ -3403,12 +3390,10 @@ std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
S += "_block_dispose_" + utostr(i);
S += "(" + StructRef;
S += "*src) {";
- for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(),
- E = ImportedBlockDecls.end(); I != E; ++I) {
- ValueDecl *VD = (*I);
+ for (ValueDecl *VD : ImportedBlockDecls) {
S += "_Block_object_dispose((void*)src->";
- S += (*I)->getNameAsString();
- if (BlockByRefDeclsPtrSet.count((*I)))
+ S += VD->getNameAsString();
+ if (BlockByRefDeclsPtrSet.count(VD))
S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
else if (VD->getType()->isBlockPointerType())
S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
@@ -3686,22 +3671,18 @@ void RewriteObjC::GetBlockDeclRefExprs(Stmt *S) {
GetBlockDeclRefExprs(*CI);
}
// Handle specific things.
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
- if (DRE->refersToEnclosingLocal()) {
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))
+ if (DRE->refersToEnclosingVariableOrCapture() ||
+ HasLocalVariableExternalStorage(DRE->getDecl()))
// FIXME: Handle enums.
- if (!isa<FunctionDecl>(DRE->getDecl()))
- BlockDeclRefs.push_back(DRE);
- if (HasLocalVariableExternalStorage(DRE->getDecl()))
- BlockDeclRefs.push_back(DRE);
- }
- }
-
+ BlockDeclRefs.push_back(DRE);
+
return;
}
void RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S,
SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,
- llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts) {
+ llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {
for (Stmt::child_range CI = S->children(); CI; ++CI)
if (*CI) {
if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
@@ -3718,11 +3699,11 @@ void RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S,
}
// Handle specific things.
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
- if (DRE->refersToEnclosingLocal()) {
- if (!isa<FunctionDecl>(DRE->getDecl()) &&
- !InnerContexts.count(DRE->getDecl()->getDeclContext()))
+ if (DRE->refersToEnclosingVariableOrCapture() ||
+ HasLocalVariableExternalStorage(DRE->getDecl())) {
+ if (!InnerContexts.count(DRE->getDecl()->getDeclContext()))
InnerBlockDeclRefs.push_back(DRE);
- if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl()))
+ if (VarDecl *Var = cast<VarDecl>(DRE->getDecl()))
if (Var->isFunctionOrMethodVarDecl())
ImportedLocalExternalDecls.insert(Var);
}
@@ -3880,7 +3861,8 @@ Stmt *RewriteObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {
// Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR
// for each DeclRefExp where BYREFVAR is name of the variable.
ValueDecl *VD = DeclRefExp->getDecl();
- bool isArrow = DeclRefExp->refersToEnclosingLocal();
+ bool isArrow = DeclRefExp->refersToEnclosingVariableOrCapture() ||
+ HasLocalVariableExternalStorage(DeclRefExp->getDecl());
FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
SourceLocation(),
@@ -4967,9 +4949,8 @@ void RewriteObjC::HandleTranslationUnit(ASTContext &C) {
// Here's a great place to add any extra declarations that may be needed.
// Write out meta data for each @protocol(<expr>).
- for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(),
- E = ProtocolExprDecls.end(); I != E; ++I)
- RewriteObjCProtocolMetaData(*I, "", "", Preamble);
+ for (ObjCProtocolDecl *ProtDecl : ProtocolExprDecls)
+ RewriteObjCProtocolMetaData(ProtDecl, "", "", Preamble);
InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false);
if (ClassImplementation.size() || CategoryImplementation.size())
@@ -5276,7 +5257,7 @@ void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
Result += "};\n";
// Mark this protocol as having been generated.
- if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()))
+ if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()).second)
llvm_unreachable("protocol already synthesized");
}
@@ -5657,12 +5638,11 @@ void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) {
if (ProtocolExprDecls.size()) {
Result += "#pragma section(\".objc_protocol$B\",long,read,write)\n";
Result += "#pragma data_seg(push, \".objc_protocol$B\")\n";
- for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(),
- E = ProtocolExprDecls.end(); I != E; ++I) {
+ for (ObjCProtocolDecl *ProtDecl : ProtocolExprDecls) {
Result += "static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_";
- Result += (*I)->getNameAsString();
+ Result += ProtDecl->getNameAsString();
Result += " = &_OBJC_PROTOCOL_";
- Result += (*I)->getNameAsString();
+ Result += ProtDecl->getNameAsString();
Result += ";\n";
}
Result += "#pragma data_seg(pop)\n\n";
diff --git a/lib/Frontend/SerializedDiagnosticPrinter.cpp b/lib/Frontend/SerializedDiagnosticPrinter.cpp
index 29c58a8ac34e..f701f723a320 100644
--- a/lib/Frontend/SerializedDiagnosticPrinter.cpp
+++ b/lib/Frontend/SerializedDiagnosticPrinter.cpp
@@ -14,6 +14,10 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Version.h"
#include "clang/Frontend/DiagnosticRenderer.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/SerializedDiagnosticReader.h"
+#include "clang/Frontend/SerializedDiagnostics.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallString.h"
@@ -86,20 +90,70 @@ protected:
void endDiagnostic(DiagOrStoredDiag D,
DiagnosticsEngine::Level Level) override;
};
-
+
+typedef llvm::DenseMap<unsigned, unsigned> AbbrevLookup;
+
+class SDiagsMerger : SerializedDiagnosticReader {
+ SDiagsWriter &Writer;
+ AbbrevLookup FileLookup;
+ AbbrevLookup CategoryLookup;
+ AbbrevLookup DiagFlagLookup;
+
+public:
+ SDiagsMerger(SDiagsWriter &Writer)
+ : SerializedDiagnosticReader(), Writer(Writer) {}
+
+ std::error_code mergeRecordsFromFile(const char *File) {
+ return readDiagnostics(File);
+ }
+
+protected:
+ std::error_code visitStartOfDiagnostic() override;
+ std::error_code visitEndOfDiagnostic() override;
+ std::error_code visitCategoryRecord(unsigned ID, StringRef Name) override;
+ std::error_code visitDiagFlagRecord(unsigned ID, StringRef Name) override;
+ std::error_code visitDiagnosticRecord(
+ unsigned Severity, const serialized_diags::Location &Location,
+ unsigned Category, unsigned Flag, StringRef Message) override;
+ std::error_code visitFilenameRecord(unsigned ID, unsigned Size,
+ unsigned Timestamp,
+ StringRef Name) override;
+ std::error_code visitFixitRecord(const serialized_diags::Location &Start,
+ const serialized_diags::Location &End,
+ StringRef CodeToInsert) override;
+ std::error_code
+ visitSourceRangeRecord(const serialized_diags::Location &Start,
+ const serialized_diags::Location &End) override;
+
+private:
+ std::error_code adjustSourceLocFilename(RecordData &Record,
+ unsigned int offset);
+
+ void adjustAbbrevID(RecordData &Record, AbbrevLookup &Lookup,
+ unsigned NewAbbrev);
+
+ void writeRecordWithAbbrev(unsigned ID, RecordData &Record);
+
+ void writeRecordWithBlob(unsigned ID, RecordData &Record, StringRef Blob);
+};
+
class SDiagsWriter : public DiagnosticConsumer {
friend class SDiagsRenderer;
+ friend class SDiagsMerger;
struct SharedState;
explicit SDiagsWriter(IntrusiveRefCntPtr<SharedState> State)
- : LangOpts(nullptr), OriginalInstance(false), State(State) {}
+ : LangOpts(nullptr), OriginalInstance(false), MergeChildRecords(false),
+ State(State) {}
public:
- SDiagsWriter(raw_ostream *os, DiagnosticOptions *diags)
- : LangOpts(nullptr), OriginalInstance(true),
- State(new SharedState(os, diags))
- {
+ SDiagsWriter(StringRef File, DiagnosticOptions *Diags, bool MergeChildRecords)
+ : LangOpts(nullptr), OriginalInstance(true),
+ MergeChildRecords(MergeChildRecords),
+ State(new SharedState(File, Diags)) {
+ if (MergeChildRecords)
+ RemoveOldDiagnostics();
EmitPreamble();
}
@@ -115,6 +169,14 @@ public:
void finish() override;
private:
+ /// \brief Build a DiagnosticsEngine to emit diagnostics about the diagnostics
+ DiagnosticsEngine *getMetaDiags();
+
+ /// \brief 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.
void EmitPreamble();
@@ -152,7 +214,9 @@ private:
/// \brief 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.
unsigned getEmitFile(const char *Filename);
@@ -173,9 +237,6 @@ private:
void AddCharSourceRangeToRecord(CharSourceRange R, RecordDataImpl &Record,
const SourceManager &SM);
- /// \brief The version of the diagnostics file.
- enum { Version = 2 };
-
/// \brief Language options, which can differ from one clone of this client
/// to another.
const LangOptions *LangOpts;
@@ -184,11 +245,16 @@ private:
/// clones), responsible for writing the file at the end.
bool OriginalInstance;
+ /// \brief 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
/// consumer.
struct SharedState : RefCountedBase<SharedState> {
- SharedState(raw_ostream *os, DiagnosticOptions *diags)
- : DiagOpts(diags), Stream(Buffer), OS(os), EmittedAnyDiagBlocks(false) { }
+ SharedState(StringRef File, DiagnosticOptions *Diags)
+ : DiagOpts(Diags), Stream(Buffer), OutputFile(File.str()),
+ EmittedAnyDiagBlocks(false) {}
/// \brief Diagnostic options.
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
@@ -200,7 +266,7 @@ private:
llvm::BitstreamWriter Stream;
/// \brief The name of the diagnostics file.
- std::unique_ptr<raw_ostream> OS;
+ std::string OutputFile;
/// \brief The set of constructed record abbreviations.
AbbreviationMap Abbrevs;
@@ -227,6 +293,9 @@ private:
/// 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.
+ std::unique_ptr<DiagnosticsEngine> MetaDiagnostics;
};
/// \brief State shared among the various clones of this diagnostic consumer.
@@ -236,9 +305,11 @@ private:
namespace clang {
namespace serialized_diags {
-DiagnosticConsumer *create(raw_ostream *OS, DiagnosticOptions *diags) {
- return new SDiagsWriter(OS, diags);
+std::unique_ptr<DiagnosticConsumer>
+create(StringRef OutputFile, DiagnosticOptions *Diags, bool MergeChildRecords) {
+ return llvm::make_unique<SDiagsWriter>(OutputFile, Diags, MergeChildRecords);
}
+
} // end namespace serialized_diags
} // end namespace clang
@@ -465,17 +536,15 @@ void SDiagsWriter::EmitMetaBlock() {
Stream.EnterSubblock(BLOCK_META, 3);
Record.clear();
Record.push_back(RECORD_VERSION);
- Record.push_back(Version);
+ Record.push_back(VersionNumber);
Stream.EmitRecordWithAbbrev(Abbrevs.get(RECORD_VERSION), Record);
Stream.ExitBlock();
}
unsigned SDiagsWriter::getEmitCategory(unsigned int category) {
- if (State->Categories.count(category))
+ if (!State->Categories.insert(category).second)
return category;
-
- State->Categories.insert(category);
-
+
// We use a local version of 'Record' so that we can be generating
// another record when we lazily generate one for the category entry.
RecordData Record;
@@ -495,6 +564,10 @@ unsigned SDiagsWriter::getEmitDiagnosticFlag(DiagnosticsEngine::Level DiagLevel,
return 0; // No flag for notes.
StringRef FlagName = DiagnosticIDs::getWarningOptionForDiag(DiagID);
+ return getEmitDiagnosticFlag(FlagName);
+}
+
+unsigned SDiagsWriter::getEmitDiagnosticFlag(StringRef FlagName) {
if (FlagName.empty())
return 0;
@@ -689,6 +762,40 @@ void SDiagsRenderer::emitNote(SourceLocation Loc, StringRef Message,
Writer.ExitDiagBlock();
}
+DiagnosticsEngine *SDiagsWriter::getMetaDiags() {
+ // FIXME: It's slightly absurd to create a new diagnostics engine here, but
+ // the other options that are available today are worse:
+ //
+ // 1. Teach DiagnosticsConsumers to emit diagnostics to the engine they are a
+ // part of. The DiagnosticsEngine would need to know not to send
+ // diagnostics back to the consumer that failed. This would require us to
+ // rework ChainedDiagnosticsConsumer and teach the engine about multiple
+ // consumers, which is difficult today because most APIs interface with
+ // consumers rather than the engine itself.
+ //
+ // 2. Pass a DiagnosticsEngine to SDiagsWriter on creation - this would need
+ // to be distinct from the engine the writer was being added to and would
+ // normally not be used.
+ if (!State->MetaDiagnostics) {
+ IntrusiveRefCntPtr<DiagnosticIDs> IDs(new DiagnosticIDs());
+ auto Client =
+ new TextDiagnosticPrinter(llvm::errs(), State->DiagOpts.get());
+ State->MetaDiagnostics = llvm::make_unique<DiagnosticsEngine>(
+ IDs, State->DiagOpts.get(), Client);
+ }
+ return State->MetaDiagnostics.get();
+}
+
+void SDiagsWriter::RemoveOldDiagnostics() {
+ if (!llvm::sys::fs::remove(State->OutputFile))
+ return;
+
+ getMetaDiags()->Report(diag::warn_fe_serialized_diag_merge_failure);
+ // Disable merging child records, as whatever is in this file may be
+ // misleading.
+ MergeChildRecords = false;
+}
+
void SDiagsWriter::finish() {
// The original instance is responsible for writing the file.
if (!OriginalInstance)
@@ -698,9 +805,113 @@ void SDiagsWriter::finish() {
if (State->EmittedAnyDiagBlocks)
ExitDiagBlock();
+ if (MergeChildRecords) {
+ if (!State->EmittedAnyDiagBlocks)
+ // We have no diagnostics of our own, so we can just leave the child
+ // process' output alone
+ return;
+
+ if (llvm::sys::fs::exists(State->OutputFile))
+ if (SDiagsMerger(*this).mergeRecordsFromFile(State->OutputFile.c_str()))
+ getMetaDiags()->Report(diag::warn_fe_serialized_diag_merge_failure);
+ }
+
+ std::error_code EC;
+ auto OS = llvm::make_unique<llvm::raw_fd_ostream>(State->OutputFile.c_str(),
+ EC, llvm::sys::fs::F_None);
+ if (EC) {
+ getMetaDiags()->Report(diag::warn_fe_serialized_diag_failure)
+ << State->OutputFile << EC.message();
+ return;
+ }
+
// Write the generated bitstream to "Out".
- State->OS->write((char *)&State->Buffer.front(), State->Buffer.size());
- State->OS->flush();
+ OS->write((char *)&State->Buffer.front(), State->Buffer.size());
+ OS->flush();
+}
+
+std::error_code SDiagsMerger::visitStartOfDiagnostic() {
+ Writer.EnterDiagBlock();
+ return std::error_code();
+}
+
+std::error_code SDiagsMerger::visitEndOfDiagnostic() {
+ Writer.ExitDiagBlock();
+ return std::error_code();
+}
+
+std::error_code
+SDiagsMerger::visitSourceRangeRecord(const serialized_diags::Location &Start,
+ const serialized_diags::Location &End) {
+ RecordData Record;
+ Record.push_back(RECORD_SOURCE_RANGE);
+ Record.push_back(FileLookup[Start.FileID]);
+ Record.push_back(Start.Line);
+ Record.push_back(Start.Col);
+ Record.push_back(Start.Offset);
+ Record.push_back(FileLookup[End.FileID]);
+ Record.push_back(End.Line);
+ Record.push_back(End.Col);
+ Record.push_back(End.Offset);
+
+ Writer.State->Stream.EmitRecordWithAbbrev(
+ Writer.State->Abbrevs.get(RECORD_SOURCE_RANGE), Record);
+ return std::error_code();
+}
+
+std::error_code SDiagsMerger::visitDiagnosticRecord(
+ unsigned Severity, const serialized_diags::Location &Location,
+ unsigned Category, unsigned Flag, StringRef Message) {
+ RecordData MergedRecord;
+ MergedRecord.push_back(RECORD_DIAG);
+ MergedRecord.push_back(Severity);
+ MergedRecord.push_back(FileLookup[Location.FileID]);
+ MergedRecord.push_back(Location.Line);
+ MergedRecord.push_back(Location.Col);
+ MergedRecord.push_back(Location.Offset);
+ MergedRecord.push_back(CategoryLookup[Category]);
+ MergedRecord.push_back(Flag ? DiagFlagLookup[Flag] : 0);
+ MergedRecord.push_back(Message.size());
+
+ Writer.State->Stream.EmitRecordWithBlob(
+ Writer.State->Abbrevs.get(RECORD_DIAG), MergedRecord, Message);
+ return std::error_code();
+}
+
+std::error_code
+SDiagsMerger::visitFixitRecord(const serialized_diags::Location &Start,
+ const serialized_diags::Location &End,
+ StringRef Text) {
+ RecordData Record;
+ Record.push_back(RECORD_FIXIT);
+ Record.push_back(FileLookup[Start.FileID]);
+ Record.push_back(Start.Line);
+ Record.push_back(Start.Col);
+ Record.push_back(Start.Offset);
+ Record.push_back(FileLookup[End.FileID]);
+ Record.push_back(End.Line);
+ Record.push_back(End.Col);
+ Record.push_back(End.Offset);
+ Record.push_back(Text.size());
+
+ Writer.State->Stream.EmitRecordWithBlob(
+ Writer.State->Abbrevs.get(RECORD_FIXIT), Record, Text);
+ return std::error_code();
+}
+
+std::error_code SDiagsMerger::visitFilenameRecord(unsigned ID, unsigned Size,
+ unsigned Timestamp,
+ StringRef Name) {
+ FileLookup[ID] = Writer.getEmitFile(Name.str().c_str());
+ return std::error_code();
+}
+
+std::error_code SDiagsMerger::visitCategoryRecord(unsigned ID, StringRef Name) {
+ CategoryLookup[ID] = Writer.getEmitCategory(ID);
+ return std::error_code();
+}
- State->OS.reset();
+std::error_code SDiagsMerger::visitDiagFlagRecord(unsigned ID, StringRef Name) {
+ DiagFlagLookup[ID] = Writer.getEmitDiagnosticFlag(Name);
+ return std::error_code();
}
diff --git a/lib/Frontend/SerializedDiagnosticReader.cpp b/lib/Frontend/SerializedDiagnosticReader.cpp
new file mode 100644
index 000000000000..0ebbd22af274
--- /dev/null
+++ b/lib/Frontend/SerializedDiagnosticReader.cpp
@@ -0,0 +1,295 @@
+//===--- SerializedDiagnosticReader.cpp - Reads diagnostics ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/SerializedDiagnosticReader.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Frontend/SerializedDiagnostics.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+using namespace clang;
+using namespace clang::serialized_diags;
+
+std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) {
+ // Open the diagnostics file.
+ FileSystemOptions FO;
+ FileManager FileMgr(FO);
+
+ auto Buffer = FileMgr.getBufferForFile(File);
+ if (!Buffer)
+ return SDError::CouldNotLoad;
+
+ llvm::BitstreamReader StreamFile;
+ StreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(),
+ (const unsigned char *)(*Buffer)->getBufferEnd());
+
+ llvm::BitstreamCursor Stream(StreamFile);
+
+ // Sniff for the signature.
+ if (Stream.Read(8) != 'D' ||
+ Stream.Read(8) != 'I' ||
+ Stream.Read(8) != 'A' ||
+ Stream.Read(8) != 'G')
+ return SDError::InvalidSignature;
+
+ // Read the top level blocks.
+ while (!Stream.AtEndOfStream()) {
+ if (Stream.ReadCode() != llvm::bitc::ENTER_SUBBLOCK)
+ return SDError::InvalidDiagnostics;
+
+ std::error_code EC;
+ switch (Stream.ReadSubBlockID()) {
+ case llvm::bitc::BLOCKINFO_BLOCK_ID:
+ if (Stream.ReadBlockInfoBlock())
+ return SDError::MalformedBlockInfoBlock;
+ continue;
+ case BLOCK_META:
+ if ((EC = readMetaBlock(Stream)))
+ return EC;
+ continue;
+ case BLOCK_DIAG:
+ if ((EC = readDiagnosticBlock(Stream)))
+ return EC;
+ continue;
+ default:
+ if (!Stream.SkipBlock())
+ return SDError::MalformedTopLevelBlock;
+ continue;
+ }
+ }
+ return std::error_code();
+}
+
+enum class SerializedDiagnosticReader::Cursor {
+ Record = 1,
+ BlockEnd,
+ BlockBegin
+};
+
+llvm::ErrorOr<SerializedDiagnosticReader::Cursor>
+SerializedDiagnosticReader::skipUntilRecordOrBlock(
+ llvm::BitstreamCursor &Stream, unsigned &BlockOrRecordID) {
+ BlockOrRecordID = 0;
+
+ while (!Stream.AtEndOfStream()) {
+ unsigned Code = Stream.ReadCode();
+
+ switch ((llvm::bitc::FixedAbbrevIDs)Code) {
+ case llvm::bitc::ENTER_SUBBLOCK:
+ BlockOrRecordID = Stream.ReadSubBlockID();
+ return Cursor::BlockBegin;
+
+ case llvm::bitc::END_BLOCK:
+ if (Stream.ReadBlockEnd())
+ return SDError::InvalidDiagnostics;
+ return Cursor::BlockEnd;
+
+ case llvm::bitc::DEFINE_ABBREV:
+ Stream.ReadAbbrevRecord();
+ continue;
+
+ case llvm::bitc::UNABBREV_RECORD:
+ return SDError::UnsupportedConstruct;
+
+ default:
+ // We found a record.
+ BlockOrRecordID = Code;
+ return Cursor::Record;
+ }
+ }
+
+ return SDError::InvalidDiagnostics;
+}
+
+std::error_code
+SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) {
+ if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_META))
+ return SDError::MalformedMetadataBlock;
+
+ bool VersionChecked = false;
+
+ while (true) {
+ unsigned BlockOrCode = 0;
+ llvm::ErrorOr<Cursor> Res = skipUntilRecordOrBlock(Stream, BlockOrCode);
+ if (!Res)
+ Res.getError();
+
+ switch (Res.get()) {
+ case Cursor::Record:
+ break;
+ case Cursor::BlockBegin:
+ if (Stream.SkipBlock())
+ return SDError::MalformedMetadataBlock;
+ case Cursor::BlockEnd:
+ if (!VersionChecked)
+ return SDError::MissingVersion;
+ return std::error_code();
+ }
+
+ SmallVector<uint64_t, 1> Record;
+ unsigned RecordID = Stream.readRecord(BlockOrCode, Record);
+
+ if (RecordID == RECORD_VERSION) {
+ if (Record.size() < 1)
+ return SDError::MissingVersion;
+ if (Record[0] > VersionNumber)
+ return SDError::VersionMismatch;
+ VersionChecked = true;
+ }
+ }
+}
+
+std::error_code
+SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) {
+ if (Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG))
+ return SDError::MalformedDiagnosticBlock;
+
+ std::error_code EC;
+ if ((EC = visitStartOfDiagnostic()))
+ return EC;
+
+ SmallVector<uint64_t, 16> Record;
+ while (true) {
+ unsigned BlockOrCode = 0;
+ llvm::ErrorOr<Cursor> Res = skipUntilRecordOrBlock(Stream, BlockOrCode);
+ if (!Res)
+ Res.getError();
+
+ switch (Res.get()) {
+ case Cursor::BlockBegin:
+ // The only blocks we care about are subdiagnostics.
+ if (BlockOrCode == serialized_diags::BLOCK_DIAG) {
+ if ((EC = readDiagnosticBlock(Stream)))
+ return EC;
+ } else if (!Stream.SkipBlock())
+ return SDError::MalformedSubBlock;
+ continue;
+ case Cursor::BlockEnd:
+ if ((EC = visitEndOfDiagnostic()))
+ return EC;
+ return std::error_code();
+ case Cursor::Record:
+ break;
+ }
+
+ // Read the record.
+ Record.clear();
+ StringRef Blob;
+ unsigned RecID = Stream.readRecord(BlockOrCode, Record, &Blob);
+
+ if (RecID < serialized_diags::RECORD_FIRST ||
+ RecID > serialized_diags::RECORD_LAST)
+ continue;
+
+ switch ((RecordIDs)RecID) {
+ case RECORD_CATEGORY:
+ // A category has ID and name size.
+ if (Record.size() != 2)
+ return SDError::MalformedDiagnosticRecord;
+ if ((EC = visitCategoryRecord(Record[0], Blob)))
+ return EC;
+ continue;
+ case RECORD_DIAG:
+ // A diagnostic has severity, location (4), category, flag, and message
+ // size.
+ if (Record.size() != 8)
+ return SDError::MalformedDiagnosticRecord;
+ if ((EC = visitDiagnosticRecord(
+ Record[0], Location(Record[1], Record[2], Record[3], Record[4]),
+ Record[5], Record[6], Blob)))
+ return EC;
+ continue;
+ case RECORD_DIAG_FLAG:
+ // A diagnostic flag has ID and name size.
+ if (Record.size() != 2)
+ return SDError::MalformedDiagnosticRecord;
+ if ((EC = visitDiagFlagRecord(Record[0], Blob)))
+ return EC;
+ continue;
+ case RECORD_FILENAME:
+ // A filename has ID, size, timestamp, and name size. The size and
+ // timestamp are legacy fields that are always zero these days.
+ if (Record.size() != 4)
+ return SDError::MalformedDiagnosticRecord;
+ if ((EC = visitFilenameRecord(Record[0], Record[1], Record[2], Blob)))
+ return EC;
+ continue;
+ case RECORD_FIXIT:
+ // A fixit has two locations (4 each) and message size.
+ if (Record.size() != 9)
+ return SDError::MalformedDiagnosticRecord;
+ if ((EC = visitFixitRecord(
+ Location(Record[0], Record[1], Record[2], Record[3]),
+ Location(Record[4], Record[5], Record[6], Record[7]), Blob)))
+ return EC;
+ continue;
+ case RECORD_SOURCE_RANGE:
+ // A source range is two locations (4 each).
+ if (Record.size() != 8)
+ return SDError::MalformedDiagnosticRecord;
+ if ((EC = visitSourceRangeRecord(
+ Location(Record[0], Record[1], Record[2], Record[3]),
+ Location(Record[4], Record[5], Record[6], Record[7]))))
+ return EC;
+ continue;
+ case RECORD_VERSION:
+ // A version is just a number.
+ if (Record.size() != 1)
+ return SDError::MalformedDiagnosticRecord;
+ if ((EC = visitVersionRecord(Record[0])))
+ return EC;
+ continue;
+ }
+ }
+}
+
+namespace {
+class SDErrorCategoryType final : public std::error_category {
+ const char *name() const LLVM_NOEXCEPT override {
+ return "clang.serialized_diags";
+ }
+ std::string message(int IE) const override {
+ SDError E = static_cast<SDError>(IE);
+ switch (E) {
+ case SDError::CouldNotLoad:
+ return "Failed to open diagnostics file";
+ case SDError::InvalidSignature:
+ return "Invalid diagnostics signature";
+ case SDError::InvalidDiagnostics:
+ return "Parse error reading diagnostics";
+ case SDError::MalformedTopLevelBlock:
+ return "Malformed block at top-level of diagnostics";
+ case SDError::MalformedSubBlock:
+ return "Malformed sub-block in a diagnostic";
+ case SDError::MalformedBlockInfoBlock:
+ return "Malformed BlockInfo block";
+ case SDError::MalformedMetadataBlock:
+ return "Malformed Metadata block";
+ case SDError::MalformedDiagnosticBlock:
+ return "Malformed Diagnostic block";
+ case SDError::MalformedDiagnosticRecord:
+ return "Malformed Diagnostic record";
+ case SDError::MissingVersion:
+ return "No version provided in diagnostics";
+ case SDError::VersionMismatch:
+ return "Unsupported diagnostics version";
+ case SDError::UnsupportedConstruct:
+ return "Bitcode constructs that are not supported in diagnostics appear";
+ case SDError::HandlerFailed:
+ return "Generic error occurred while handling a record";
+ }
+ llvm_unreachable("Unknown error type!");
+ }
+};
+}
+
+static llvm::ManagedStatic<SDErrorCategoryType> ErrorCategory;
+const std::error_category &clang::serialized_diags::SDErrorCategory() {
+ return *ErrorCategory;
+}
diff --git a/lib/Frontend/TextDiagnostic.cpp b/lib/Frontend/TextDiagnostic.cpp
index 6e6f3dd1bfee..bbc99141f072 100644
--- a/lib/Frontend/TextDiagnostic.cpp
+++ b/lib/Frontend/TextDiagnostic.cpp
@@ -176,7 +176,7 @@ static void expandTabs(std::string &SourceLine, unsigned TabStop) {
/// of the printable representation of the line to the columns those printable
/// characters will appear at (numbering the first column as 0).
///
-/// If a byte 'i' corresponds to muliple columns (e.g. the byte contains a tab
+/// If a byte 'i' corresponds to multiple columns (e.g. the byte contains a tab
/// character) then the array will map that byte to the first column the
/// tab appears at and the next value in the map will have been incremented
/// more than once.
@@ -293,14 +293,14 @@ struct SourceColumnMap {
/// \brief 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_columnToByte.size() - 1));
+ 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.
int startOfPreviousColumn(int N) const {
- assert(0 < N && N < static_cast<int>(m_columnToByte.size()));
+ assert(0 < N && N < static_cast<int>(m_byteToColumn.size()));
while (byteToColumn(--N) == -1) {}
return N;
}
@@ -323,9 +323,10 @@ static void selectInterestingSourceRegion(std::string &SourceLine,
std::string &FixItInsertionLine,
unsigned Columns,
const SourceColumnMap &map) {
- unsigned MaxColumns = std::max<unsigned>(map.columns(),
- std::max(CaretLine.size(),
- FixItInsertionLine.size()));
+ unsigned CaretColumns = CaretLine.size();
+ unsigned FixItColumns = llvm::sys::locale::columnWidth(FixItInsertionLine);
+ unsigned MaxColumns = std::max(static_cast<unsigned>(map.columns()),
+ std::max(CaretColumns, FixItColumns));
// if the number of columns is less than the desired number we're done
if (MaxColumns <= Columns)
return;
@@ -487,7 +488,7 @@ static void selectInterestingSourceRegion(std::string &SourceLine,
// We checked up front that the line needed truncation
assert(FrontColumnsRemoved+ColumnsKept+BackColumnsRemoved > Columns);
- // The line needs some trunctiona, and we'd prefer to keep the front
+ // The line needs some truncation, and we'd prefer to keep the front
// if possible, so remove the back
if (BackColumnsRemoved > strlen(back_ellipse))
SourceLine.replace(SourceEnd, std::string::npos, back_ellipse);
@@ -1110,12 +1111,13 @@ void TextDiagnostic::emitSnippetAndCaret(
// Copy the line of code into an std::string for ease of manipulation.
std::string SourceLine(LineStart, LineEnd);
- // Create a line for the caret that is filled with spaces that is the same
- // length as the line of source code.
- std::string CaretLine(LineEnd-LineStart, ' ');
-
+ // Build the byte to column map.
const SourceColumnMap sourceColMap(SourceLine, DiagOpts->TabStop);
+ // Create a line for the caret that is filled with spaces that is the same
+ // number of columns as the line of source code.
+ std::string CaretLine(sourceColMap.columns(), ' ');
+
// Highlight all of the characters covered by Ranges with ~ characters.
for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(),
E = Ranges.end();
diff --git a/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp
index b50950e9b300..3ff6b18e2199 100644
--- a/lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ b/lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -27,14 +27,13 @@ typedef VerifyDiagnosticConsumer::Directive Directive;
typedef VerifyDiagnosticConsumer::DirectiveList DirectiveList;
typedef VerifyDiagnosticConsumer::ExpectedData ExpectedData;
-VerifyDiagnosticConsumer::VerifyDiagnosticConsumer(DiagnosticsEngine &_Diags)
- : Diags(_Diags),
- PrimaryClient(Diags.getClient()), OwnsPrimaryClient(Diags.ownsClient()),
+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.takeClient();
if (Diags.hasSourceManager())
setSourceManager(Diags.getSourceManager());
}
@@ -43,10 +42,8 @@ VerifyDiagnosticConsumer::~VerifyDiagnosticConsumer() {
assert(!ActiveSourceFiles && "Incomplete parsing of source files!");
assert(!CurrentPreprocessor && "CurrentPreprocessor should be invalid!");
SrcManager = nullptr;
- CheckDiagnostics();
- Diags.takeClient();
- if (OwnsPrimaryClient)
- delete PrimaryClient;
+ CheckDiagnostics();
+ Diags.takeClient().release();
}
#ifndef NDEBUG
@@ -84,8 +81,8 @@ void VerifyDiagnosticConsumer::BeginSourceFile(const LangOptions &LangOpts,
const_cast<Preprocessor*>(PP)->addCommentHandler(this);
#ifndef NDEBUG
// Debug build tracks parsed files.
- VerifyFileTracker *V = new VerifyFileTracker(*this, *SrcManager);
- const_cast<Preprocessor*>(PP)->addPPCallbacks(V);
+ const_cast<Preprocessor*>(PP)->addPPCallbacks(
+ llvm::make_unique<VerifyFileTracker>(*this, *SrcManager));
#endif
}
}
@@ -402,8 +399,9 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
// Lookup file via Preprocessor, like a #include.
const DirectoryLookup *CurDir;
- const FileEntry *FE = PP->LookupFile(Pos, Filename, false, nullptr,
- CurDir, nullptr, nullptr, nullptr);
+ const FileEntry *FE =
+ PP->LookupFile(Pos, Filename, false, nullptr, nullptr, CurDir,
+ nullptr, nullptr, nullptr);
if (!FE) {
Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
diag::err_verify_missing_file) << Filename << KindStr;
@@ -502,13 +500,12 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
}
// Construct new directive.
- std::unique_ptr<Directive> D(
- Directive::create(RegexKind, Pos, ExpectedLoc, MatchAnyLine, Text,
- Min, Max));
+ std::unique_ptr<Directive> D = Directive::create(
+ RegexKind, Pos, ExpectedLoc, MatchAnyLine, Text, Min, Max);
std::string Error;
if (D->isValid(Error)) {
- DL->push_back(D.release());
+ DL->push_back(std::move(D));
FoundDirective = true;
} else {
Diags.Report(Pos.getLocWithOffset(ContentBegin-PH.Begin),
@@ -644,15 +641,16 @@ static unsigned PrintUnexpected(DiagnosticsEngine &Diags, SourceManager *SourceM
/// \brief 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,
- DirectiveList &DL, const char *Kind) {
+static unsigned PrintExpected(DiagnosticsEngine &Diags,
+ SourceManager &SourceMgr,
+ std::vector<Directive *> &DL, const char *Kind) {
if (DL.empty())
return 0;
SmallString<256> Fmt;
llvm::raw_svector_ostream OS(Fmt);
- for (DirectiveList::iterator I = DL.begin(), E = DL.end(); I != E; ++I) {
- Directive &D = **I;
+ for (auto *DirPtr : DL) {
+ Directive &D = *DirPtr;
OS << "\n File " << SourceMgr.getFilename(D.DiagnosticLoc);
if (D.MatchAnyLine)
OS << " Line *";
@@ -694,11 +692,11 @@ static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
DirectiveList &Left,
const_diag_iterator d2_begin,
const_diag_iterator d2_end) {
- DirectiveList LeftOnly;
+ std::vector<Directive *> LeftOnly;
DiagList Right(d2_begin, d2_end);
- for (DirectiveList::iterator I = Left.begin(), E = Left.end(); I != E; ++I) {
- Directive& D = **I;
+ for (auto &Owner : Left) {
+ Directive &D = *Owner;
unsigned LineNo1 = SourceMgr.getPresumedLineNumber(D.DiagnosticLoc);
for (unsigned i = 0; i < D.Max; ++i) {
@@ -720,7 +718,7 @@ static unsigned CheckLists(DiagnosticsEngine &Diags, SourceManager &SourceMgr,
if (II == IE) {
// Not found.
if (i >= D.Min) break;
- LeftOnly.push_back(*I);
+ LeftOnly.push_back(&D);
} else {
// Found. The same cannot be found twice.
Right.erase(II);
@@ -801,8 +799,8 @@ void VerifyDiagnosticConsumer::UpdateParsedFileStatus(SourceManager &SM,
void VerifyDiagnosticConsumer::CheckDiagnostics() {
// Ensure any diagnostics go to the primary client.
- bool OwnsCurClient = Diags.ownsClient();
- DiagnosticConsumer *CurClient = Diags.takeClient();
+ DiagnosticConsumer *CurClient = Diags.getClient();
+ std::unique_ptr<DiagnosticConsumer> Owner = Diags.takeClient();
Diags.setClient(PrimaryClient, false);
#ifndef NDEBUG
@@ -864,20 +862,21 @@ void VerifyDiagnosticConsumer::CheckDiagnostics() {
Buffer->note_end(), "note"));
}
- Diags.takeClient();
- Diags.setClient(CurClient, OwnsCurClient);
+ Diags.setClient(CurClient, Owner.release() != nullptr);
// Reset the buffer, we have processed all the diagnostics in it.
Buffer.reset(new TextDiagnosticBuffer());
ED.Reset();
}
-Directive *Directive::create(bool RegexKind, SourceLocation DirectiveLoc,
- SourceLocation DiagnosticLoc, bool MatchAnyLine,
- StringRef Text, unsigned Min, unsigned Max) {
+std::unique_ptr<Directive> Directive::create(bool RegexKind,
+ SourceLocation DirectiveLoc,
+ SourceLocation DiagnosticLoc,
+ bool MatchAnyLine, StringRef Text,
+ unsigned Min, unsigned Max) {
if (!RegexKind)
- return new StandardDirective(DirectiveLoc, DiagnosticLoc, MatchAnyLine,
- Text, Min, Max);
+ return llvm::make_unique<StandardDirective>(DirectiveLoc, DiagnosticLoc,
+ MatchAnyLine, Text, Min, Max);
// Parse the directive into a regular expression.
std::string RegexStr;
@@ -902,6 +901,6 @@ Directive *Directive::create(bool RegexKind, SourceLocation DirectiveLoc,
}
}
- return new RegexDirective(DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text,
- Min, Max, RegexStr);
+ return llvm::make_unique<RegexDirective>(
+ DirectiveLoc, DiagnosticLoc, MatchAnyLine, Text, Min, Max, RegexStr);
}