File: | tools/clang/lib/CodeGen/CodeGenAction.cpp |
Warning: | line 890, column 47 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===--- CodeGenAction.cpp - LLVM Code Generation Frontend Action ---------===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | ||||
10 | #include "clang/CodeGen/CodeGenAction.h" | |||
11 | #include "CodeGenModule.h" | |||
12 | #include "CoverageMappingGen.h" | |||
13 | #include "MacroPPCallbacks.h" | |||
14 | #include "clang/AST/ASTConsumer.h" | |||
15 | #include "clang/AST/ASTContext.h" | |||
16 | #include "clang/AST/DeclCXX.h" | |||
17 | #include "clang/AST/DeclGroup.h" | |||
18 | #include "clang/Basic/FileManager.h" | |||
19 | #include "clang/Basic/SourceManager.h" | |||
20 | #include "clang/Basic/TargetInfo.h" | |||
21 | #include "clang/CodeGen/BackendUtil.h" | |||
22 | #include "clang/CodeGen/ModuleBuilder.h" | |||
23 | #include "clang/Frontend/CompilerInstance.h" | |||
24 | #include "clang/Frontend/FrontendDiagnostic.h" | |||
25 | #include "clang/Lex/Preprocessor.h" | |||
26 | #include "llvm/Bitcode/BitcodeReader.h" | |||
27 | #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" | |||
28 | #include "llvm/IR/DebugInfo.h" | |||
29 | #include "llvm/IR/DiagnosticInfo.h" | |||
30 | #include "llvm/IR/DiagnosticPrinter.h" | |||
31 | #include "llvm/IR/GlobalValue.h" | |||
32 | #include "llvm/IR/LLVMContext.h" | |||
33 | #include "llvm/IR/Module.h" | |||
34 | #include "llvm/IRReader/IRReader.h" | |||
35 | #include "llvm/Linker/Linker.h" | |||
36 | #include "llvm/Pass.h" | |||
37 | #include "llvm/Support/MemoryBuffer.h" | |||
38 | #include "llvm/Support/SourceMgr.h" | |||
39 | #include "llvm/Support/Timer.h" | |||
40 | #include "llvm/Support/ToolOutputFile.h" | |||
41 | #include "llvm/Support/YAMLTraits.h" | |||
42 | #include "llvm/Transforms/IPO/Internalize.h" | |||
43 | ||||
44 | #include <memory> | |||
45 | using namespace clang; | |||
46 | using namespace llvm; | |||
47 | ||||
48 | namespace clang { | |||
49 | class BackendConsumer; | |||
50 | class ClangDiagnosticHandler final : public DiagnosticHandler { | |||
51 | public: | |||
52 | ClangDiagnosticHandler(const CodeGenOptions &CGOpts, BackendConsumer *BCon) | |||
53 | : CodeGenOpts(CGOpts), BackendCon(BCon) {} | |||
54 | ||||
55 | bool handleDiagnostics(const DiagnosticInfo &DI) override; | |||
56 | ||||
57 | bool isAnalysisRemarkEnabled(StringRef PassName) const override { | |||
58 | return (CodeGenOpts.OptimizationRemarkAnalysisPattern && | |||
59 | CodeGenOpts.OptimizationRemarkAnalysisPattern->match(PassName)); | |||
60 | } | |||
61 | bool isMissedOptRemarkEnabled(StringRef PassName) const override { | |||
62 | return (CodeGenOpts.OptimizationRemarkMissedPattern && | |||
63 | CodeGenOpts.OptimizationRemarkMissedPattern->match(PassName)); | |||
64 | } | |||
65 | bool isPassedOptRemarkEnabled(StringRef PassName) const override { | |||
66 | return (CodeGenOpts.OptimizationRemarkPattern && | |||
67 | CodeGenOpts.OptimizationRemarkPattern->match(PassName)); | |||
68 | } | |||
69 | ||||
70 | bool isAnyRemarkEnabled() const override { | |||
71 | return (CodeGenOpts.OptimizationRemarkAnalysisPattern || | |||
72 | CodeGenOpts.OptimizationRemarkMissedPattern || | |||
73 | CodeGenOpts.OptimizationRemarkPattern); | |||
74 | } | |||
75 | ||||
76 | private: | |||
77 | const CodeGenOptions &CodeGenOpts; | |||
78 | BackendConsumer *BackendCon; | |||
79 | }; | |||
80 | ||||
81 | class BackendConsumer : public ASTConsumer { | |||
82 | using LinkModule = CodeGenAction::LinkModule; | |||
83 | ||||
84 | virtual void anchor(); | |||
85 | DiagnosticsEngine &Diags; | |||
86 | BackendAction Action; | |||
87 | const HeaderSearchOptions &HeaderSearchOpts; | |||
88 | const CodeGenOptions &CodeGenOpts; | |||
89 | const TargetOptions &TargetOpts; | |||
90 | const LangOptions &LangOpts; | |||
91 | std::unique_ptr<raw_pwrite_stream> AsmOutStream; | |||
92 | ASTContext *Context; | |||
93 | ||||
94 | Timer LLVMIRGeneration; | |||
95 | unsigned LLVMIRGenerationRefCount; | |||
96 | ||||
97 | /// True if we've finished generating IR. This prevents us from generating | |||
98 | /// additional LLVM IR after emitting output in HandleTranslationUnit. This | |||
99 | /// can happen when Clang plugins trigger additional AST deserialization. | |||
100 | bool IRGenFinished = false; | |||
101 | ||||
102 | std::unique_ptr<CodeGenerator> Gen; | |||
103 | ||||
104 | SmallVector<LinkModule, 4> LinkModules; | |||
105 | ||||
106 | // This is here so that the diagnostic printer knows the module a diagnostic | |||
107 | // refers to. | |||
108 | llvm::Module *CurLinkModule = nullptr; | |||
109 | ||||
110 | public: | |||
111 | BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, | |||
112 | const HeaderSearchOptions &HeaderSearchOpts, | |||
113 | const PreprocessorOptions &PPOpts, | |||
114 | const CodeGenOptions &CodeGenOpts, | |||
115 | const TargetOptions &TargetOpts, | |||
116 | const LangOptions &LangOpts, bool TimePasses, | |||
117 | const std::string &InFile, | |||
118 | SmallVector<LinkModule, 4> LinkModules, | |||
119 | std::unique_ptr<raw_pwrite_stream> OS, LLVMContext &C, | |||
120 | CoverageSourceInfo *CoverageInfo = nullptr) | |||
121 | : Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts), | |||
122 | CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts), | |||
123 | AsmOutStream(std::move(OS)), Context(nullptr), | |||
124 | LLVMIRGeneration("irgen", "LLVM IR Generation Time"), | |||
125 | LLVMIRGenerationRefCount(0), | |||
126 | Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts, | |||
127 | CodeGenOpts, C, CoverageInfo)), | |||
128 | LinkModules(std::move(LinkModules)) { | |||
129 | llvm::TimePassesIsEnabled = TimePasses; | |||
130 | } | |||
131 | llvm::Module *getModule() const { return Gen->GetModule(); } | |||
132 | std::unique_ptr<llvm::Module> takeModule() { | |||
133 | return std::unique_ptr<llvm::Module>(Gen->ReleaseModule()); | |||
134 | } | |||
135 | ||||
136 | CodeGenerator *getCodeGenerator() { return Gen.get(); } | |||
137 | ||||
138 | void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override { | |||
139 | Gen->HandleCXXStaticMemberVarInstantiation(VD); | |||
140 | } | |||
141 | ||||
142 | void Initialize(ASTContext &Ctx) override { | |||
143 | assert(!Context && "initialized multiple times")(static_cast <bool> (!Context && "initialized multiple times" ) ? void (0) : __assert_fail ("!Context && \"initialized multiple times\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/CodeGen/CodeGenAction.cpp" , 143, __extension__ __PRETTY_FUNCTION__)); | |||
144 | ||||
145 | Context = &Ctx; | |||
146 | ||||
147 | if (llvm::TimePassesIsEnabled) | |||
148 | LLVMIRGeneration.startTimer(); | |||
149 | ||||
150 | Gen->Initialize(Ctx); | |||
151 | ||||
152 | if (llvm::TimePassesIsEnabled) | |||
153 | LLVMIRGeneration.stopTimer(); | |||
154 | } | |||
155 | ||||
156 | bool HandleTopLevelDecl(DeclGroupRef D) override { | |||
157 | PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(), | |||
158 | Context->getSourceManager(), | |||
159 | "LLVM IR generation of declaration"); | |||
160 | ||||
161 | // Recurse. | |||
162 | if (llvm::TimePassesIsEnabled) { | |||
163 | LLVMIRGenerationRefCount += 1; | |||
164 | if (LLVMIRGenerationRefCount == 1) | |||
165 | LLVMIRGeneration.startTimer(); | |||
166 | } | |||
167 | ||||
168 | Gen->HandleTopLevelDecl(D); | |||
169 | ||||
170 | if (llvm::TimePassesIsEnabled) { | |||
171 | LLVMIRGenerationRefCount -= 1; | |||
172 | if (LLVMIRGenerationRefCount == 0) | |||
173 | LLVMIRGeneration.stopTimer(); | |||
174 | } | |||
175 | ||||
176 | return true; | |||
177 | } | |||
178 | ||||
179 | void HandleInlineFunctionDefinition(FunctionDecl *D) override { | |||
180 | PrettyStackTraceDecl CrashInfo(D, SourceLocation(), | |||
181 | Context->getSourceManager(), | |||
182 | "LLVM IR generation of inline function"); | |||
183 | if (llvm::TimePassesIsEnabled) | |||
184 | LLVMIRGeneration.startTimer(); | |||
185 | ||||
186 | Gen->HandleInlineFunctionDefinition(D); | |||
187 | ||||
188 | if (llvm::TimePassesIsEnabled) | |||
189 | LLVMIRGeneration.stopTimer(); | |||
190 | } | |||
191 | ||||
192 | void HandleInterestingDecl(DeclGroupRef D) override { | |||
193 | // Ignore interesting decls from the AST reader after IRGen is finished. | |||
194 | if (!IRGenFinished) | |||
195 | HandleTopLevelDecl(D); | |||
196 | } | |||
197 | ||||
198 | // Links each entry in LinkModules into our module. Returns true on error. | |||
199 | bool LinkInModules() { | |||
200 | for (auto &LM : LinkModules) { | |||
201 | if (LM.PropagateAttrs) | |||
202 | for (Function &F : *LM.Module) | |||
203 | Gen->CGM().AddDefaultFnAttrs(F); | |||
204 | ||||
205 | CurLinkModule = LM.Module.get(); | |||
206 | ||||
207 | bool Err; | |||
208 | if (LM.Internalize) { | |||
209 | Err = Linker::linkModules( | |||
210 | *getModule(), std::move(LM.Module), LM.LinkFlags, | |||
211 | [](llvm::Module &M, const llvm::StringSet<> &GVS) { | |||
212 | internalizeModule(M, [&GVS](const llvm::GlobalValue &GV) { | |||
213 | return !GV.hasName() || (GVS.count(GV.getName()) == 0); | |||
214 | }); | |||
215 | }); | |||
216 | } else { | |||
217 | Err = Linker::linkModules(*getModule(), std::move(LM.Module), | |||
218 | LM.LinkFlags); | |||
219 | } | |||
220 | ||||
221 | if (Err) | |||
222 | return true; | |||
223 | } | |||
224 | return false; // success | |||
225 | } | |||
226 | ||||
227 | void HandleTranslationUnit(ASTContext &C) override { | |||
228 | { | |||
229 | PrettyStackTraceString CrashInfo("Per-file LLVM IR generation"); | |||
230 | if (llvm::TimePassesIsEnabled) { | |||
231 | LLVMIRGenerationRefCount += 1; | |||
232 | if (LLVMIRGenerationRefCount == 1) | |||
233 | LLVMIRGeneration.startTimer(); | |||
234 | } | |||
235 | ||||
236 | Gen->HandleTranslationUnit(C); | |||
237 | ||||
238 | if (llvm::TimePassesIsEnabled) { | |||
239 | LLVMIRGenerationRefCount -= 1; | |||
240 | if (LLVMIRGenerationRefCount == 0) | |||
241 | LLVMIRGeneration.stopTimer(); | |||
242 | } | |||
243 | ||||
244 | IRGenFinished = true; | |||
245 | } | |||
246 | ||||
247 | // Silently ignore if we weren't initialized for some reason. | |||
248 | if (!getModule()) | |||
249 | return; | |||
250 | ||||
251 | // Install an inline asm handler so that diagnostics get printed through | |||
252 | // our diagnostics hooks. | |||
253 | LLVMContext &Ctx = getModule()->getContext(); | |||
254 | LLVMContext::InlineAsmDiagHandlerTy OldHandler = | |||
255 | Ctx.getInlineAsmDiagnosticHandler(); | |||
256 | void *OldContext = Ctx.getInlineAsmDiagnosticContext(); | |||
257 | Ctx.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, this); | |||
258 | ||||
259 | std::unique_ptr<DiagnosticHandler> OldDiagnosticHandler = | |||
260 | Ctx.getDiagnosticHandler(); | |||
261 | Ctx.setDiagnosticHandler(llvm::make_unique<ClangDiagnosticHandler>( | |||
262 | CodeGenOpts, this)); | |||
263 | Ctx.setDiagnosticsHotnessRequested(CodeGenOpts.DiagnosticsWithHotness); | |||
264 | if (CodeGenOpts.DiagnosticsHotnessThreshold != 0) | |||
265 | Ctx.setDiagnosticsHotnessThreshold( | |||
266 | CodeGenOpts.DiagnosticsHotnessThreshold); | |||
267 | ||||
268 | std::unique_ptr<llvm::ToolOutputFile> OptRecordFile; | |||
269 | if (!CodeGenOpts.OptRecordFile.empty()) { | |||
270 | std::error_code EC; | |||
271 | OptRecordFile = llvm::make_unique<llvm::ToolOutputFile>( | |||
272 | CodeGenOpts.OptRecordFile, EC, sys::fs::F_None); | |||
273 | if (EC) { | |||
274 | Diags.Report(diag::err_cannot_open_file) << | |||
275 | CodeGenOpts.OptRecordFile << EC.message(); | |||
276 | return; | |||
277 | } | |||
278 | ||||
279 | Ctx.setDiagnosticsOutputFile( | |||
280 | llvm::make_unique<yaml::Output>(OptRecordFile->os())); | |||
281 | ||||
282 | if (CodeGenOpts.getProfileUse() != CodeGenOptions::ProfileNone) | |||
283 | Ctx.setDiagnosticsHotnessRequested(true); | |||
284 | } | |||
285 | ||||
286 | // Link each LinkModule into our module. | |||
287 | if (LinkInModules()) | |||
288 | return; | |||
289 | ||||
290 | EmbedBitcode(getModule(), CodeGenOpts, llvm::MemoryBufferRef()); | |||
291 | ||||
292 | EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, | |||
293 | LangOpts, C.getTargetInfo().getDataLayout(), | |||
294 | getModule(), Action, std::move(AsmOutStream)); | |||
295 | ||||
296 | Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext); | |||
297 | ||||
298 | Ctx.setDiagnosticHandler(std::move(OldDiagnosticHandler)); | |||
299 | ||||
300 | if (OptRecordFile) | |||
301 | OptRecordFile->keep(); | |||
302 | } | |||
303 | ||||
304 | void HandleTagDeclDefinition(TagDecl *D) override { | |||
305 | PrettyStackTraceDecl CrashInfo(D, SourceLocation(), | |||
306 | Context->getSourceManager(), | |||
307 | "LLVM IR generation of declaration"); | |||
308 | Gen->HandleTagDeclDefinition(D); | |||
309 | } | |||
310 | ||||
311 | void HandleTagDeclRequiredDefinition(const TagDecl *D) override { | |||
312 | Gen->HandleTagDeclRequiredDefinition(D); | |||
313 | } | |||
314 | ||||
315 | void CompleteTentativeDefinition(VarDecl *D) override { | |||
316 | Gen->CompleteTentativeDefinition(D); | |||
317 | } | |||
318 | ||||
319 | void AssignInheritanceModel(CXXRecordDecl *RD) override { | |||
320 | Gen->AssignInheritanceModel(RD); | |||
321 | } | |||
322 | ||||
323 | void HandleVTable(CXXRecordDecl *RD) override { | |||
324 | Gen->HandleVTable(RD); | |||
325 | } | |||
326 | ||||
327 | static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context, | |||
328 | unsigned LocCookie) { | |||
329 | SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie); | |||
330 | ((BackendConsumer*)Context)->InlineAsmDiagHandler2(SM, Loc); | |||
331 | } | |||
332 | ||||
333 | /// Get the best possible source location to represent a diagnostic that | |||
334 | /// may have associated debug info. | |||
335 | const FullSourceLoc | |||
336 | getBestLocationFromDebugLoc(const llvm::DiagnosticInfoWithLocationBase &D, | |||
337 | bool &BadDebugInfo, StringRef &Filename, | |||
338 | unsigned &Line, unsigned &Column) const; | |||
339 | ||||
340 | void InlineAsmDiagHandler2(const llvm::SMDiagnostic &, | |||
341 | SourceLocation LocCookie); | |||
342 | ||||
343 | void DiagnosticHandlerImpl(const llvm::DiagnosticInfo &DI); | |||
344 | /// \brief Specialized handler for InlineAsm diagnostic. | |||
345 | /// \return True if the diagnostic has been successfully reported, false | |||
346 | /// otherwise. | |||
347 | bool InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D); | |||
348 | /// \brief Specialized handler for StackSize diagnostic. | |||
349 | /// \return True if the diagnostic has been successfully reported, false | |||
350 | /// otherwise. | |||
351 | bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D); | |||
352 | /// \brief Specialized handler for unsupported backend feature diagnostic. | |||
353 | void UnsupportedDiagHandler(const llvm::DiagnosticInfoUnsupported &D); | |||
354 | /// \brief Specialized handlers for optimization remarks. | |||
355 | /// Note that these handlers only accept remarks and they always handle | |||
356 | /// them. | |||
357 | void EmitOptimizationMessage(const llvm::DiagnosticInfoOptimizationBase &D, | |||
358 | unsigned DiagID); | |||
359 | void | |||
360 | OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationBase &D); | |||
361 | void OptimizationRemarkHandler( | |||
362 | const llvm::OptimizationRemarkAnalysisFPCommute &D); | |||
363 | void OptimizationRemarkHandler( | |||
364 | const llvm::OptimizationRemarkAnalysisAliasing &D); | |||
365 | void OptimizationFailureHandler( | |||
366 | const llvm::DiagnosticInfoOptimizationFailure &D); | |||
367 | }; | |||
368 | ||||
369 | void BackendConsumer::anchor() {} | |||
370 | } | |||
371 | ||||
372 | bool ClangDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) { | |||
373 | BackendCon->DiagnosticHandlerImpl(DI); | |||
374 | return true; | |||
375 | } | |||
376 | ||||
377 | /// ConvertBackendLocation - Convert a location in a temporary llvm::SourceMgr | |||
378 | /// buffer to be a valid FullSourceLoc. | |||
379 | static FullSourceLoc ConvertBackendLocation(const llvm::SMDiagnostic &D, | |||
380 | SourceManager &CSM) { | |||
381 | // Get both the clang and llvm source managers. The location is relative to | |||
382 | // a memory buffer that the LLVM Source Manager is handling, we need to add | |||
383 | // a copy to the Clang source manager. | |||
384 | const llvm::SourceMgr &LSM = *D.getSourceMgr(); | |||
385 | ||||
386 | // We need to copy the underlying LLVM memory buffer because llvm::SourceMgr | |||
387 | // already owns its one and clang::SourceManager wants to own its one. | |||
388 | const MemoryBuffer *LBuf = | |||
389 | LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); | |||
390 | ||||
391 | // Create the copy and transfer ownership to clang::SourceManager. | |||
392 | // TODO: Avoid copying files into memory. | |||
393 | std::unique_ptr<llvm::MemoryBuffer> CBuf = | |||
394 | llvm::MemoryBuffer::getMemBufferCopy(LBuf->getBuffer(), | |||
395 | LBuf->getBufferIdentifier()); | |||
396 | // FIXME: Keep a file ID map instead of creating new IDs for each location. | |||
397 | FileID FID = CSM.createFileID(std::move(CBuf)); | |||
398 | ||||
399 | // Translate the offset into the file. | |||
400 | unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart(); | |||
401 | SourceLocation NewLoc = | |||
402 | CSM.getLocForStartOfFile(FID).getLocWithOffset(Offset); | |||
403 | return FullSourceLoc(NewLoc, CSM); | |||
404 | } | |||
405 | ||||
406 | ||||
407 | /// InlineAsmDiagHandler2 - This function is invoked when the backend hits an | |||
408 | /// error parsing inline asm. The SMDiagnostic indicates the error relative to | |||
409 | /// the temporary memory buffer that the inline asm parser has set up. | |||
410 | void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D, | |||
411 | SourceLocation LocCookie) { | |||
412 | // There are a couple of different kinds of errors we could get here. First, | |||
413 | // we re-format the SMDiagnostic in terms of a clang diagnostic. | |||
414 | ||||
415 | // Strip "error: " off the start of the message string. | |||
416 | StringRef Message = D.getMessage(); | |||
417 | if (Message.startswith("error: ")) | |||
418 | Message = Message.substr(7); | |||
419 | ||||
420 | // If the SMDiagnostic has an inline asm source location, translate it. | |||
421 | FullSourceLoc Loc; | |||
422 | if (D.getLoc() != SMLoc()) | |||
423 | Loc = ConvertBackendLocation(D, Context->getSourceManager()); | |||
424 | ||||
425 | unsigned DiagID; | |||
426 | switch (D.getKind()) { | |||
427 | case llvm::SourceMgr::DK_Error: | |||
428 | DiagID = diag::err_fe_inline_asm; | |||
429 | break; | |||
430 | case llvm::SourceMgr::DK_Warning: | |||
431 | DiagID = diag::warn_fe_inline_asm; | |||
432 | break; | |||
433 | case llvm::SourceMgr::DK_Note: | |||
434 | DiagID = diag::note_fe_inline_asm; | |||
435 | break; | |||
436 | case llvm::SourceMgr::DK_Remark: | |||
437 | llvm_unreachable("remarks unexpected")::llvm::llvm_unreachable_internal("remarks unexpected", "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/CodeGen/CodeGenAction.cpp" , 437); | |||
438 | } | |||
439 | // If this problem has clang-level source location information, report the | |||
440 | // issue in the source with a note showing the instantiated | |||
441 | // code. | |||
442 | if (LocCookie.isValid()) { | |||
443 | Diags.Report(LocCookie, DiagID).AddString(Message); | |||
444 | ||||
445 | if (D.getLoc().isValid()) { | |||
446 | DiagnosticBuilder B = Diags.Report(Loc, diag::note_fe_inline_asm_here); | |||
447 | // Convert the SMDiagnostic ranges into SourceRange and attach them | |||
448 | // to the diagnostic. | |||
449 | for (const std::pair<unsigned, unsigned> &Range : D.getRanges()) { | |||
450 | unsigned Column = D.getColumnNo(); | |||
451 | B << SourceRange(Loc.getLocWithOffset(Range.first - Column), | |||
452 | Loc.getLocWithOffset(Range.second - Column)); | |||
453 | } | |||
454 | } | |||
455 | return; | |||
456 | } | |||
457 | ||||
458 | // Otherwise, report the backend issue as occurring in the generated .s file. | |||
459 | // If Loc is invalid, we still need to report the issue, it just gets no | |||
460 | // location info. | |||
461 | Diags.Report(Loc, DiagID).AddString(Message); | |||
462 | } | |||
463 | ||||
464 | #define ComputeDiagID(Severity, GroupName, DiagID) \ | |||
465 | do { \ | |||
466 | switch (Severity) { \ | |||
467 | case llvm::DS_Error: \ | |||
468 | DiagID = diag::err_fe_##GroupName; \ | |||
469 | break; \ | |||
470 | case llvm::DS_Warning: \ | |||
471 | DiagID = diag::warn_fe_##GroupName; \ | |||
472 | break; \ | |||
473 | case llvm::DS_Remark: \ | |||
474 | llvm_unreachable("'remark' severity not expected")::llvm::llvm_unreachable_internal("'remark' severity not expected" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/CodeGen/CodeGenAction.cpp" , 474); \ | |||
475 | break; \ | |||
476 | case llvm::DS_Note: \ | |||
477 | DiagID = diag::note_fe_##GroupName; \ | |||
478 | break; \ | |||
479 | } \ | |||
480 | } while (false) | |||
481 | ||||
482 | #define ComputeDiagRemarkID(Severity, GroupName, DiagID)do { switch (Severity) { case llvm::DS_Error: DiagID = diag:: err_fe_GroupName; break; case llvm::DS_Warning: DiagID = diag ::warn_fe_GroupName; break; case llvm::DS_Remark: DiagID = diag ::remark_fe_GroupName; break; case llvm::DS_Note: DiagID = diag ::note_fe_GroupName; break; } } while (false) \ | |||
483 | do { \ | |||
484 | switch (Severity) { \ | |||
485 | case llvm::DS_Error: \ | |||
486 | DiagID = diag::err_fe_##GroupName; \ | |||
487 | break; \ | |||
488 | case llvm::DS_Warning: \ | |||
489 | DiagID = diag::warn_fe_##GroupName; \ | |||
490 | break; \ | |||
491 | case llvm::DS_Remark: \ | |||
492 | DiagID = diag::remark_fe_##GroupName; \ | |||
493 | break; \ | |||
494 | case llvm::DS_Note: \ | |||
495 | DiagID = diag::note_fe_##GroupName; \ | |||
496 | break; \ | |||
497 | } \ | |||
498 | } while (false) | |||
499 | ||||
500 | bool | |||
501 | BackendConsumer::InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D) { | |||
502 | unsigned DiagID; | |||
503 | ComputeDiagID(D.getSeverity(), inline_asm, DiagID); | |||
504 | std::string Message = D.getMsgStr().str(); | |||
505 | ||||
506 | // If this problem has clang-level source location information, report the | |||
507 | // issue as being a problem in the source with a note showing the instantiated | |||
508 | // code. | |||
509 | SourceLocation LocCookie = | |||
510 | SourceLocation::getFromRawEncoding(D.getLocCookie()); | |||
511 | if (LocCookie.isValid()) | |||
512 | Diags.Report(LocCookie, DiagID).AddString(Message); | |||
513 | else { | |||
514 | // Otherwise, report the backend diagnostic as occurring in the generated | |||
515 | // .s file. | |||
516 | // If Loc is invalid, we still need to report the diagnostic, it just gets | |||
517 | // no location info. | |||
518 | FullSourceLoc Loc; | |||
519 | Diags.Report(Loc, DiagID).AddString(Message); | |||
520 | } | |||
521 | // We handled all the possible severities. | |||
522 | return true; | |||
523 | } | |||
524 | ||||
525 | bool | |||
526 | BackendConsumer::StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D) { | |||
527 | if (D.getSeverity() != llvm::DS_Warning) | |||
528 | // For now, the only support we have for StackSize diagnostic is warning. | |||
529 | // We do not know how to format other severities. | |||
530 | return false; | |||
531 | ||||
532 | if (const Decl *ND = Gen->GetDeclForMangledName(D.getFunction().getName())) { | |||
533 | // FIXME: Shouldn't need to truncate to uint32_t | |||
534 | Diags.Report(ND->getASTContext().getFullLoc(ND->getLocation()), | |||
535 | diag::warn_fe_frame_larger_than) | |||
536 | << static_cast<uint32_t>(D.getStackSize()) << Decl::castToDeclContext(ND); | |||
537 | return true; | |||
538 | } | |||
539 | ||||
540 | return false; | |||
541 | } | |||
542 | ||||
543 | const FullSourceLoc BackendConsumer::getBestLocationFromDebugLoc( | |||
544 | const llvm::DiagnosticInfoWithLocationBase &D, bool &BadDebugInfo, | |||
545 | StringRef &Filename, unsigned &Line, unsigned &Column) const { | |||
546 | SourceManager &SourceMgr = Context->getSourceManager(); | |||
547 | FileManager &FileMgr = SourceMgr.getFileManager(); | |||
548 | SourceLocation DILoc; | |||
549 | ||||
550 | if (D.isLocationAvailable()) { | |||
551 | D.getLocation(&Filename, &Line, &Column); | |||
552 | const FileEntry *FE = FileMgr.getFile(Filename); | |||
553 | if (FE && Line > 0) { | |||
554 | // If -gcolumn-info was not used, Column will be 0. This upsets the | |||
555 | // source manager, so pass 1 if Column is not set. | |||
556 | DILoc = SourceMgr.translateFileLineCol(FE, Line, Column ? Column : 1); | |||
557 | } | |||
558 | BadDebugInfo = DILoc.isInvalid(); | |||
559 | } | |||
560 | ||||
561 | // If a location isn't available, try to approximate it using the associated | |||
562 | // function definition. We use the definition's right brace to differentiate | |||
563 | // from diagnostics that genuinely relate to the function itself. | |||
564 | FullSourceLoc Loc(DILoc, SourceMgr); | |||
565 | if (Loc.isInvalid()) | |||
566 | if (const Decl *FD = Gen->GetDeclForMangledName(D.getFunction().getName())) | |||
567 | Loc = FD->getASTContext().getFullLoc(FD->getLocation()); | |||
568 | ||||
569 | if (DILoc.isInvalid() && D.isLocationAvailable()) | |||
570 | // If we were not able to translate the file:line:col information | |||
571 | // back to a SourceLocation, at least emit a note stating that | |||
572 | // we could not translate this location. This can happen in the | |||
573 | // case of #line directives. | |||
574 | Diags.Report(Loc, diag::note_fe_backend_invalid_loc) | |||
575 | << Filename << Line << Column; | |||
576 | ||||
577 | return Loc; | |||
578 | } | |||
579 | ||||
580 | void BackendConsumer::UnsupportedDiagHandler( | |||
581 | const llvm::DiagnosticInfoUnsupported &D) { | |||
582 | // We only support errors. | |||
583 | assert(D.getSeverity() == llvm::DS_Error)(static_cast <bool> (D.getSeverity() == llvm::DS_Error) ? void (0) : __assert_fail ("D.getSeverity() == llvm::DS_Error" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/CodeGen/CodeGenAction.cpp" , 583, __extension__ __PRETTY_FUNCTION__)); | |||
584 | ||||
585 | StringRef Filename; | |||
586 | unsigned Line, Column; | |||
587 | bool BadDebugInfo = false; | |||
588 | FullSourceLoc Loc = | |||
589 | getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column); | |||
590 | ||||
591 | Diags.Report(Loc, diag::err_fe_backend_unsupported) << D.getMessage().str(); | |||
592 | ||||
593 | if (BadDebugInfo) | |||
594 | // If we were not able to translate the file:line:col information | |||
595 | // back to a SourceLocation, at least emit a note stating that | |||
596 | // we could not translate this location. This can happen in the | |||
597 | // case of #line directives. | |||
598 | Diags.Report(Loc, diag::note_fe_backend_invalid_loc) | |||
599 | << Filename << Line << Column; | |||
600 | } | |||
601 | ||||
602 | void BackendConsumer::EmitOptimizationMessage( | |||
603 | const llvm::DiagnosticInfoOptimizationBase &D, unsigned DiagID) { | |||
604 | // We only support warnings and remarks. | |||
605 | assert(D.getSeverity() == llvm::DS_Remark ||(static_cast <bool> (D.getSeverity() == llvm::DS_Remark || D.getSeverity() == llvm::DS_Warning) ? void (0) : __assert_fail ("D.getSeverity() == llvm::DS_Remark || D.getSeverity() == llvm::DS_Warning" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/CodeGen/CodeGenAction.cpp" , 606, __extension__ __PRETTY_FUNCTION__)) | |||
606 | D.getSeverity() == llvm::DS_Warning)(static_cast <bool> (D.getSeverity() == llvm::DS_Remark || D.getSeverity() == llvm::DS_Warning) ? void (0) : __assert_fail ("D.getSeverity() == llvm::DS_Remark || D.getSeverity() == llvm::DS_Warning" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/CodeGen/CodeGenAction.cpp" , 606, __extension__ __PRETTY_FUNCTION__)); | |||
607 | ||||
608 | StringRef Filename; | |||
609 | unsigned Line, Column; | |||
610 | bool BadDebugInfo = false; | |||
611 | FullSourceLoc Loc = | |||
612 | getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column); | |||
613 | ||||
614 | std::string Msg; | |||
615 | raw_string_ostream MsgStream(Msg); | |||
616 | MsgStream << D.getMsg(); | |||
617 | ||||
618 | if (D.getHotness()) | |||
619 | MsgStream << " (hotness: " << *D.getHotness() << ")"; | |||
620 | ||||
621 | Diags.Report(Loc, DiagID) | |||
622 | << AddFlagValue(D.getPassName()) | |||
623 | << MsgStream.str(); | |||
624 | ||||
625 | if (BadDebugInfo) | |||
626 | // If we were not able to translate the file:line:col information | |||
627 | // back to a SourceLocation, at least emit a note stating that | |||
628 | // we could not translate this location. This can happen in the | |||
629 | // case of #line directives. | |||
630 | Diags.Report(Loc, diag::note_fe_backend_invalid_loc) | |||
631 | << Filename << Line << Column; | |||
632 | } | |||
633 | ||||
634 | void BackendConsumer::OptimizationRemarkHandler( | |||
635 | const llvm::DiagnosticInfoOptimizationBase &D) { | |||
636 | // Without hotness information, don't show noisy remarks. | |||
637 | if (D.isVerbose() && !D.getHotness()) | |||
638 | return; | |||
639 | ||||
640 | if (D.isPassed()) { | |||
641 | // Optimization remarks are active only if the -Rpass flag has a regular | |||
642 | // expression that matches the name of the pass name in \p D. | |||
643 | if (CodeGenOpts.OptimizationRemarkPattern && | |||
644 | CodeGenOpts.OptimizationRemarkPattern->match(D.getPassName())) | |||
645 | EmitOptimizationMessage(D, diag::remark_fe_backend_optimization_remark); | |||
646 | } else if (D.isMissed()) { | |||
647 | // Missed optimization remarks are active only if the -Rpass-missed | |||
648 | // flag has a regular expression that matches the name of the pass | |||
649 | // name in \p D. | |||
650 | if (CodeGenOpts.OptimizationRemarkMissedPattern && | |||
651 | CodeGenOpts.OptimizationRemarkMissedPattern->match(D.getPassName())) | |||
652 | EmitOptimizationMessage( | |||
653 | D, diag::remark_fe_backend_optimization_remark_missed); | |||
654 | } else { | |||
655 | assert(D.isAnalysis() && "Unknown remark type")(static_cast <bool> (D.isAnalysis() && "Unknown remark type" ) ? void (0) : __assert_fail ("D.isAnalysis() && \"Unknown remark type\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/CodeGen/CodeGenAction.cpp" , 655, __extension__ __PRETTY_FUNCTION__)); | |||
656 | ||||
657 | bool ShouldAlwaysPrint = false; | |||
658 | if (auto *ORA = dyn_cast<llvm::OptimizationRemarkAnalysis>(&D)) | |||
659 | ShouldAlwaysPrint = ORA->shouldAlwaysPrint(); | |||
660 | ||||
661 | if (ShouldAlwaysPrint || | |||
662 | (CodeGenOpts.OptimizationRemarkAnalysisPattern && | |||
663 | CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName()))) | |||
664 | EmitOptimizationMessage( | |||
665 | D, diag::remark_fe_backend_optimization_remark_analysis); | |||
666 | } | |||
667 | } | |||
668 | ||||
669 | void BackendConsumer::OptimizationRemarkHandler( | |||
670 | const llvm::OptimizationRemarkAnalysisFPCommute &D) { | |||
671 | // Optimization analysis remarks are active if the pass name is set to | |||
672 | // llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a | |||
673 | // regular expression that matches the name of the pass name in \p D. | |||
674 | ||||
675 | if (D.shouldAlwaysPrint() || | |||
676 | (CodeGenOpts.OptimizationRemarkAnalysisPattern && | |||
677 | CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName()))) | |||
678 | EmitOptimizationMessage( | |||
679 | D, diag::remark_fe_backend_optimization_remark_analysis_fpcommute); | |||
680 | } | |||
681 | ||||
682 | void BackendConsumer::OptimizationRemarkHandler( | |||
683 | const llvm::OptimizationRemarkAnalysisAliasing &D) { | |||
684 | // Optimization analysis remarks are active if the pass name is set to | |||
685 | // llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a | |||
686 | // regular expression that matches the name of the pass name in \p D. | |||
687 | ||||
688 | if (D.shouldAlwaysPrint() || | |||
689 | (CodeGenOpts.OptimizationRemarkAnalysisPattern && | |||
690 | CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName()))) | |||
691 | EmitOptimizationMessage( | |||
692 | D, diag::remark_fe_backend_optimization_remark_analysis_aliasing); | |||
693 | } | |||
694 | ||||
695 | void BackendConsumer::OptimizationFailureHandler( | |||
696 | const llvm::DiagnosticInfoOptimizationFailure &D) { | |||
697 | EmitOptimizationMessage(D, diag::warn_fe_backend_optimization_failure); | |||
698 | } | |||
699 | ||||
700 | /// \brief This function is invoked when the backend needs | |||
701 | /// to report something to the user. | |||
702 | void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) { | |||
703 | unsigned DiagID = diag::err_fe_inline_asm; | |||
704 | llvm::DiagnosticSeverity Severity = DI.getSeverity(); | |||
705 | // Get the diagnostic ID based. | |||
706 | switch (DI.getKind()) { | |||
707 | case llvm::DK_InlineAsm: | |||
708 | if (InlineAsmDiagHandler(cast<DiagnosticInfoInlineAsm>(DI))) | |||
709 | return; | |||
710 | ComputeDiagID(Severity, inline_asm, DiagID); | |||
711 | break; | |||
712 | case llvm::DK_StackSize: | |||
713 | if (StackSizeDiagHandler(cast<DiagnosticInfoStackSize>(DI))) | |||
714 | return; | |||
715 | ComputeDiagID(Severity, backend_frame_larger_than, DiagID); | |||
716 | break; | |||
717 | case DK_Linker: | |||
718 | assert(CurLinkModule)(static_cast <bool> (CurLinkModule) ? void (0) : __assert_fail ("CurLinkModule", "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/CodeGen/CodeGenAction.cpp" , 718, __extension__ __PRETTY_FUNCTION__)); | |||
719 | // FIXME: stop eating the warnings and notes. | |||
720 | if (Severity != DS_Error) | |||
721 | return; | |||
722 | DiagID = diag::err_fe_cannot_link_module; | |||
723 | break; | |||
724 | case llvm::DK_OptimizationRemark: | |||
725 | // Optimization remarks are always handled completely by this | |||
726 | // handler. There is no generic way of emitting them. | |||
727 | OptimizationRemarkHandler(cast<OptimizationRemark>(DI)); | |||
728 | return; | |||
729 | case llvm::DK_OptimizationRemarkMissed: | |||
730 | // Optimization remarks are always handled completely by this | |||
731 | // handler. There is no generic way of emitting them. | |||
732 | OptimizationRemarkHandler(cast<OptimizationRemarkMissed>(DI)); | |||
733 | return; | |||
734 | case llvm::DK_OptimizationRemarkAnalysis: | |||
735 | // Optimization remarks are always handled completely by this | |||
736 | // handler. There is no generic way of emitting them. | |||
737 | OptimizationRemarkHandler(cast<OptimizationRemarkAnalysis>(DI)); | |||
738 | return; | |||
739 | case llvm::DK_OptimizationRemarkAnalysisFPCommute: | |||
740 | // Optimization remarks are always handled completely by this | |||
741 | // handler. There is no generic way of emitting them. | |||
742 | OptimizationRemarkHandler(cast<OptimizationRemarkAnalysisFPCommute>(DI)); | |||
743 | return; | |||
744 | case llvm::DK_OptimizationRemarkAnalysisAliasing: | |||
745 | // Optimization remarks are always handled completely by this | |||
746 | // handler. There is no generic way of emitting them. | |||
747 | OptimizationRemarkHandler(cast<OptimizationRemarkAnalysisAliasing>(DI)); | |||
748 | return; | |||
749 | case llvm::DK_MachineOptimizationRemark: | |||
750 | // Optimization remarks are always handled completely by this | |||
751 | // handler. There is no generic way of emitting them. | |||
752 | OptimizationRemarkHandler(cast<MachineOptimizationRemark>(DI)); | |||
753 | return; | |||
754 | case llvm::DK_MachineOptimizationRemarkMissed: | |||
755 | // Optimization remarks are always handled completely by this | |||
756 | // handler. There is no generic way of emitting them. | |||
757 | OptimizationRemarkHandler(cast<MachineOptimizationRemarkMissed>(DI)); | |||
758 | return; | |||
759 | case llvm::DK_MachineOptimizationRemarkAnalysis: | |||
760 | // Optimization remarks are always handled completely by this | |||
761 | // handler. There is no generic way of emitting them. | |||
762 | OptimizationRemarkHandler(cast<MachineOptimizationRemarkAnalysis>(DI)); | |||
763 | return; | |||
764 | case llvm::DK_OptimizationFailure: | |||
765 | // Optimization failures are always handled completely by this | |||
766 | // handler. | |||
767 | OptimizationFailureHandler(cast<DiagnosticInfoOptimizationFailure>(DI)); | |||
768 | return; | |||
769 | case llvm::DK_Unsupported: | |||
770 | UnsupportedDiagHandler(cast<DiagnosticInfoUnsupported>(DI)); | |||
771 | return; | |||
772 | default: | |||
773 | // Plugin IDs are not bound to any value as they are set dynamically. | |||
774 | ComputeDiagRemarkID(Severity, backend_plugin, DiagID)do { switch (Severity) { case llvm::DS_Error: DiagID = diag:: err_fe_backend_plugin; break; case llvm::DS_Warning: DiagID = diag::warn_fe_backend_plugin; break; case llvm::DS_Remark: DiagID = diag::remark_fe_backend_plugin; break; case llvm::DS_Note: DiagID = diag::note_fe_backend_plugin; break; } } while (false ); | |||
775 | break; | |||
776 | } | |||
777 | std::string MsgStorage; | |||
778 | { | |||
779 | raw_string_ostream Stream(MsgStorage); | |||
780 | DiagnosticPrinterRawOStream DP(Stream); | |||
781 | DI.print(DP); | |||
782 | } | |||
783 | ||||
784 | if (DiagID == diag::err_fe_cannot_link_module) { | |||
785 | Diags.Report(diag::err_fe_cannot_link_module) | |||
786 | << CurLinkModule->getModuleIdentifier() << MsgStorage; | |||
787 | return; | |||
788 | } | |||
789 | ||||
790 | // Report the backend message using the usual diagnostic mechanism. | |||
791 | FullSourceLoc Loc; | |||
792 | Diags.Report(Loc, DiagID).AddString(MsgStorage); | |||
793 | } | |||
794 | #undef ComputeDiagID | |||
795 | ||||
796 | CodeGenAction::CodeGenAction(unsigned _Act, LLVMContext *_VMContext) | |||
797 | : Act(_Act), VMContext(_VMContext ? _VMContext : new LLVMContext), | |||
798 | OwnsVMContext(!_VMContext) {} | |||
799 | ||||
800 | CodeGenAction::~CodeGenAction() { | |||
801 | TheModule.reset(); | |||
802 | if (OwnsVMContext) | |||
803 | delete VMContext; | |||
804 | } | |||
805 | ||||
806 | bool CodeGenAction::hasIRSupport() const { return true; } | |||
807 | ||||
808 | void CodeGenAction::EndSourceFileAction() { | |||
809 | // If the consumer creation failed, do nothing. | |||
810 | if (!getCompilerInstance().hasASTConsumer()) | |||
811 | return; | |||
812 | ||||
813 | // Steal the module from the consumer. | |||
814 | TheModule = BEConsumer->takeModule(); | |||
815 | } | |||
816 | ||||
817 | std::unique_ptr<llvm::Module> CodeGenAction::takeModule() { | |||
818 | return std::move(TheModule); | |||
819 | } | |||
820 | ||||
821 | llvm::LLVMContext *CodeGenAction::takeLLVMContext() { | |||
822 | OwnsVMContext = false; | |||
823 | return VMContext; | |||
824 | } | |||
825 | ||||
826 | static std::unique_ptr<raw_pwrite_stream> | |||
827 | GetOutputStream(CompilerInstance &CI, StringRef InFile, BackendAction Action) { | |||
828 | switch (Action) { | |||
829 | case Backend_EmitAssembly: | |||
830 | return CI.createDefaultOutputFile(false, InFile, "s"); | |||
831 | case Backend_EmitLL: | |||
832 | return CI.createDefaultOutputFile(false, InFile, "ll"); | |||
833 | case Backend_EmitBC: | |||
834 | return CI.createDefaultOutputFile(true, InFile, "bc"); | |||
835 | case Backend_EmitNothing: | |||
836 | return nullptr; | |||
837 | case Backend_EmitMCNull: | |||
838 | return CI.createNullOutputFile(); | |||
839 | case Backend_EmitObj: | |||
840 | return CI.createDefaultOutputFile(true, InFile, "o"); | |||
841 | } | |||
842 | ||||
843 | llvm_unreachable("Invalid action!")::llvm::llvm_unreachable_internal("Invalid action!", "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/CodeGen/CodeGenAction.cpp" , 843); | |||
844 | } | |||
845 | ||||
846 | std::unique_ptr<ASTConsumer> | |||
847 | CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { | |||
848 | BackendAction BA = static_cast<BackendAction>(Act); | |||
849 | std::unique_ptr<raw_pwrite_stream> OS = CI.takeOutputStream(); | |||
850 | if (!OS) | |||
| ||||
851 | OS = GetOutputStream(CI, InFile, BA); | |||
852 | ||||
853 | if (BA != Backend_EmitNothing && !OS) | |||
854 | return nullptr; | |||
855 | ||||
856 | // Load bitcode modules to link with, if we need to. | |||
857 | if (LinkModules.empty()) | |||
858 | for (const CodeGenOptions::BitcodeFileToLink &F : | |||
859 | CI.getCodeGenOpts().LinkBitcodeFiles) { | |||
860 | auto BCBuf = CI.getFileManager().getBufferForFile(F.Filename); | |||
861 | if (!BCBuf) { | |||
862 | CI.getDiagnostics().Report(diag::err_cannot_open_file) | |||
863 | << F.Filename << BCBuf.getError().message(); | |||
864 | LinkModules.clear(); | |||
865 | return nullptr; | |||
866 | } | |||
867 | ||||
868 | Expected<std::unique_ptr<llvm::Module>> ModuleOrErr = | |||
869 | getOwningLazyBitcodeModule(std::move(*BCBuf), *VMContext); | |||
870 | if (!ModuleOrErr) { | |||
871 | handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) { | |||
872 | CI.getDiagnostics().Report(diag::err_cannot_open_file) | |||
873 | << F.Filename << EIB.message(); | |||
874 | }); | |||
875 | LinkModules.clear(); | |||
876 | return nullptr; | |||
877 | } | |||
878 | LinkModules.push_back({std::move(ModuleOrErr.get()), F.PropagateAttrs, | |||
879 | F.Internalize, F.LinkFlags}); | |||
880 | } | |||
881 | ||||
882 | CoverageSourceInfo *CoverageInfo = nullptr; | |||
883 | // Add the preprocessor callback only when the coverage mapping is generated. | |||
884 | if (CI.getCodeGenOpts().CoverageMapping) { | |||
885 | CoverageInfo = new CoverageSourceInfo; | |||
886 | CI.getPreprocessor().addPPCallbacks( | |||
887 | std::unique_ptr<PPCallbacks>(CoverageInfo)); | |||
888 | } | |||
889 | ||||
890 | std::unique_ptr<BackendConsumer> Result(new BackendConsumer( | |||
| ||||
891 | BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), | |||
892 | CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(), | |||
893 | CI.getLangOpts(), CI.getFrontendOpts().ShowTimers, InFile, | |||
894 | std::move(LinkModules), std::move(OS), *VMContext, CoverageInfo)); | |||
895 | BEConsumer = Result.get(); | |||
896 | ||||
897 | // Enable generating macro debug info only when debug info is not disabled and | |||
898 | // also macro debug info is enabled. | |||
899 | if (CI.getCodeGenOpts().getDebugInfo() != codegenoptions::NoDebugInfo && | |||
900 | CI.getCodeGenOpts().MacroDebugInfo) { | |||
901 | std::unique_ptr<PPCallbacks> Callbacks = | |||
902 | llvm::make_unique<MacroPPCallbacks>(BEConsumer->getCodeGenerator(), | |||
903 | CI.getPreprocessor()); | |||
904 | CI.getPreprocessor().addPPCallbacks(std::move(Callbacks)); | |||
905 | } | |||
906 | ||||
907 | return std::move(Result); | |||
908 | } | |||
909 | ||||
910 | static void BitcodeInlineAsmDiagHandler(const llvm::SMDiagnostic &SM, | |||
911 | void *Context, | |||
912 | unsigned LocCookie) { | |||
913 | SM.print(nullptr, llvm::errs()); | |||
914 | ||||
915 | auto Diags = static_cast<DiagnosticsEngine *>(Context); | |||
916 | unsigned DiagID; | |||
917 | switch (SM.getKind()) { | |||
918 | case llvm::SourceMgr::DK_Error: | |||
919 | DiagID = diag::err_fe_inline_asm; | |||
920 | break; | |||
921 | case llvm::SourceMgr::DK_Warning: | |||
922 | DiagID = diag::warn_fe_inline_asm; | |||
923 | break; | |||
924 | case llvm::SourceMgr::DK_Note: | |||
925 | DiagID = diag::note_fe_inline_asm; | |||
926 | break; | |||
927 | case llvm::SourceMgr::DK_Remark: | |||
928 | llvm_unreachable("remarks unexpected")::llvm::llvm_unreachable_internal("remarks unexpected", "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/CodeGen/CodeGenAction.cpp" , 928); | |||
929 | } | |||
930 | ||||
931 | Diags->Report(DiagID).AddString("cannot compile inline asm"); | |||
932 | } | |||
933 | ||||
934 | std::unique_ptr<llvm::Module> CodeGenAction::loadModule(MemoryBufferRef MBRef) { | |||
935 | CompilerInstance &CI = getCompilerInstance(); | |||
936 | SourceManager &SM = CI.getSourceManager(); | |||
937 | ||||
938 | // For ThinLTO backend invocations, ensure that the context | |||
939 | // merges types based on ODR identifiers. We also need to read | |||
940 | // the correct module out of a multi-module bitcode file. | |||
941 | if (!CI.getCodeGenOpts().ThinLTOIndexFile.empty()) { | |||
942 | VMContext->enableDebugTypeODRUniquing(); | |||
943 | ||||
944 | auto DiagErrors = [&](Error E) -> std::unique_ptr<llvm::Module> { | |||
945 | unsigned DiagID = | |||
946 | CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0"); | |||
947 | handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) { | |||
948 | CI.getDiagnostics().Report(DiagID) << EIB.message(); | |||
949 | }); | |||
950 | return {}; | |||
951 | }; | |||
952 | ||||
953 | Expected<std::vector<BitcodeModule>> BMsOrErr = getBitcodeModuleList(MBRef); | |||
954 | if (!BMsOrErr) | |||
955 | return DiagErrors(BMsOrErr.takeError()); | |||
956 | BitcodeModule *Bm = FindThinLTOModule(*BMsOrErr); | |||
957 | // We have nothing to do if the file contains no ThinLTO module. This is | |||
958 | // possible if ThinLTO compilation was not able to split module. Content of | |||
959 | // the file was already processed by indexing and will be passed to the | |||
960 | // linker using merged object file. | |||
961 | if (!Bm) { | |||
962 | auto M = llvm::make_unique<llvm::Module>("empty", *VMContext); | |||
963 | M->setTargetTriple(CI.getTargetOpts().Triple); | |||
964 | return M; | |||
965 | } | |||
966 | Expected<std::unique_ptr<llvm::Module>> MOrErr = | |||
967 | Bm->parseModule(*VMContext); | |||
968 | if (!MOrErr) | |||
969 | return DiagErrors(MOrErr.takeError()); | |||
970 | return std::move(*MOrErr); | |||
971 | } | |||
972 | ||||
973 | llvm::SMDiagnostic Err; | |||
974 | if (std::unique_ptr<llvm::Module> M = parseIR(MBRef, Err, *VMContext)) | |||
975 | return M; | |||
976 | ||||
977 | // Translate from the diagnostic info to the SourceManager location if | |||
978 | // available. | |||
979 | // TODO: Unify this with ConvertBackendLocation() | |||
980 | SourceLocation Loc; | |||
981 | if (Err.getLineNo() > 0) { | |||
982 | assert(Err.getColumnNo() >= 0)(static_cast <bool> (Err.getColumnNo() >= 0) ? void ( 0) : __assert_fail ("Err.getColumnNo() >= 0", "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/CodeGen/CodeGenAction.cpp" , 982, __extension__ __PRETTY_FUNCTION__)); | |||
983 | Loc = SM.translateFileLineCol(SM.getFileEntryForID(SM.getMainFileID()), | |||
984 | Err.getLineNo(), Err.getColumnNo() + 1); | |||
985 | } | |||
986 | ||||
987 | // Strip off a leading diagnostic code if there is one. | |||
988 | StringRef Msg = Err.getMessage(); | |||
989 | if (Msg.startswith("error: ")) | |||
990 | Msg = Msg.substr(7); | |||
991 | ||||
992 | unsigned DiagID = | |||
993 | CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0"); | |||
994 | ||||
995 | CI.getDiagnostics().Report(Loc, DiagID) << Msg; | |||
996 | return {}; | |||
997 | } | |||
998 | ||||
999 | void CodeGenAction::ExecuteAction() { | |||
1000 | // If this is an IR file, we have to treat it specially. | |||
1001 | if (getCurrentFileKind().getLanguage() == InputKind::LLVM_IR) { | |||
1002 | BackendAction BA = static_cast<BackendAction>(Act); | |||
1003 | CompilerInstance &CI = getCompilerInstance(); | |||
1004 | std::unique_ptr<raw_pwrite_stream> OS = | |||
1005 | GetOutputStream(CI, getCurrentFile(), BA); | |||
1006 | if (BA != Backend_EmitNothing && !OS) | |||
1007 | return; | |||
1008 | ||||
1009 | bool Invalid; | |||
1010 | SourceManager &SM = CI.getSourceManager(); | |||
1011 | FileID FID = SM.getMainFileID(); | |||
1012 | llvm::MemoryBuffer *MainFile = SM.getBuffer(FID, &Invalid); | |||
1013 | if (Invalid) | |||
1014 | return; | |||
1015 | ||||
1016 | TheModule = loadModule(*MainFile); | |||
1017 | if (!TheModule) | |||
1018 | return; | |||
1019 | ||||
1020 | const TargetOptions &TargetOpts = CI.getTargetOpts(); | |||
1021 | if (TheModule->getTargetTriple() != TargetOpts.Triple) { | |||
1022 | CI.getDiagnostics().Report(SourceLocation(), | |||
1023 | diag::warn_fe_override_module) | |||
1024 | << TargetOpts.Triple; | |||
1025 | TheModule->setTargetTriple(TargetOpts.Triple); | |||
1026 | } | |||
1027 | ||||
1028 | EmbedBitcode(TheModule.get(), CI.getCodeGenOpts(), | |||
1029 | MainFile->getMemBufferRef()); | |||
1030 | ||||
1031 | LLVMContext &Ctx = TheModule->getContext(); | |||
1032 | Ctx.setInlineAsmDiagnosticHandler(BitcodeInlineAsmDiagHandler, | |||
1033 | &CI.getDiagnostics()); | |||
1034 | ||||
1035 | EmitBackendOutput(CI.getDiagnostics(), CI.getHeaderSearchOpts(), | |||
1036 | CI.getCodeGenOpts(), TargetOpts, CI.getLangOpts(), | |||
1037 | CI.getTarget().getDataLayout(), TheModule.get(), BA, | |||
1038 | std::move(OS)); | |||
1039 | return; | |||
1040 | } | |||
1041 | ||||
1042 | // Otherwise follow the normal AST path. | |||
1043 | this->ASTFrontendAction::ExecuteAction(); | |||
1044 | } | |||
1045 | ||||
1046 | // | |||
1047 | ||||
1048 | void EmitAssemblyAction::anchor() { } | |||
1049 | EmitAssemblyAction::EmitAssemblyAction(llvm::LLVMContext *_VMContext) | |||
1050 | : CodeGenAction(Backend_EmitAssembly, _VMContext) {} | |||
1051 | ||||
1052 | void EmitBCAction::anchor() { } | |||
1053 | EmitBCAction::EmitBCAction(llvm::LLVMContext *_VMContext) | |||
1054 | : CodeGenAction(Backend_EmitBC, _VMContext) {} | |||
1055 | ||||
1056 | void EmitLLVMAction::anchor() { } | |||
1057 | EmitLLVMAction::EmitLLVMAction(llvm::LLVMContext *_VMContext) | |||
1058 | : CodeGenAction(Backend_EmitLL, _VMContext) {} | |||
1059 | ||||
1060 | void EmitLLVMOnlyAction::anchor() { } | |||
1061 | EmitLLVMOnlyAction::EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext) | |||
1062 | : CodeGenAction(Backend_EmitNothing, _VMContext) {} | |||
1063 | ||||
1064 | void EmitCodeGenOnlyAction::anchor() { } | |||
1065 | EmitCodeGenOnlyAction::EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext) | |||
1066 | : CodeGenAction(Backend_EmitMCNull, _VMContext) {} | |||
1067 | ||||
1068 | void EmitObjAction::anchor() { } | |||
1069 | EmitObjAction::EmitObjAction(llvm::LLVMContext *_VMContext) | |||
1070 | : CodeGenAction(Backend_EmitObj, _VMContext) {} |
1 | // unique_ptr implementation -*- C++ -*- |
2 | |
3 | // Copyright (C) 2008-2017 Free Software Foundation, Inc. |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free |
6 | // software; you can redistribute it and/or modify it under the |
7 | // terms of the GNU General Public License as published by the |
8 | // Free Software Foundation; either version 3, or (at your option) |
9 | // any later version. |
10 | |
11 | // This library is distributed in the hope that it will be useful, |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | // GNU General Public License for more details. |
15 | |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version |
18 | // 3.1, as published by the Free Software Foundation. |
19 | |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
23 | // <http://www.gnu.org/licenses/>. |
24 | |
25 | /** @file bits/unique_ptr.h |
26 | * This is an internal header file, included by other library headers. |
27 | * Do not attempt to use it directly. @headername{memory} |
28 | */ |
29 | |
30 | #ifndef _UNIQUE_PTR_H1 |
31 | #define _UNIQUE_PTR_H1 1 |
32 | |
33 | #include <bits/c++config.h> |
34 | #include <debug/assertions.h> |
35 | #include <type_traits> |
36 | #include <utility> |
37 | #include <tuple> |
38 | #include <bits/stl_function.h> |
39 | #include <bits/functional_hash.h> |
40 | |
41 | namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default"))) |
42 | { |
43 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
44 | |
45 | /** |
46 | * @addtogroup pointer_abstractions |
47 | * @{ |
48 | */ |
49 | |
50 | #if _GLIBCXX_USE_DEPRECATED1 |
51 | template<typename> class auto_ptr; |
52 | #endif |
53 | |
54 | /// Primary template of default_delete, used by unique_ptr |
55 | template<typename _Tp> |
56 | struct default_delete |
57 | { |
58 | /// Default constructor |
59 | constexpr default_delete() noexcept = default; |
60 | |
61 | /** @brief Converting constructor. |
62 | * |
63 | * Allows conversion from a deleter for arrays of another type, @p _Up, |
64 | * only if @p _Up* is convertible to @p _Tp*. |
65 | */ |
66 | template<typename _Up, typename = typename |
67 | enable_if<is_convertible<_Up*, _Tp*>::value>::type> |
68 | default_delete(const default_delete<_Up>&) noexcept { } |
69 | |
70 | /// Calls @c delete @p __ptr |
71 | void |
72 | operator()(_Tp* __ptr) const |
73 | { |
74 | static_assert(!is_void<_Tp>::value, |
75 | "can't delete pointer to incomplete type"); |
76 | static_assert(sizeof(_Tp)>0, |
77 | "can't delete pointer to incomplete type"); |
78 | delete __ptr; |
79 | } |
80 | }; |
81 | |
82 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
83 | // DR 740 - omit specialization for array objects with a compile time length |
84 | /// Specialization for arrays, default_delete. |
85 | template<typename _Tp> |
86 | struct default_delete<_Tp[]> |
87 | { |
88 | public: |
89 | /// Default constructor |
90 | constexpr default_delete() noexcept = default; |
91 | |
92 | /** @brief Converting constructor. |
93 | * |
94 | * Allows conversion from a deleter for arrays of another type, such as |
95 | * a const-qualified version of @p _Tp. |
96 | * |
97 | * Conversions from types derived from @c _Tp are not allowed because |
98 | * it is unsafe to @c delete[] an array of derived types through a |
99 | * pointer to the base type. |
100 | */ |
101 | template<typename _Up, typename = typename |
102 | enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type> |
103 | default_delete(const default_delete<_Up[]>&) noexcept { } |
104 | |
105 | /// Calls @c delete[] @p __ptr |
106 | template<typename _Up> |
107 | typename enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type |
108 | operator()(_Up* __ptr) const |
109 | { |
110 | static_assert(sizeof(_Tp)>0, |
111 | "can't delete pointer to incomplete type"); |
112 | delete [] __ptr; |
113 | } |
114 | }; |
115 | |
116 | template <typename _Tp, typename _Dp> |
117 | class __uniq_ptr_impl |
118 | { |
119 | template <typename _Up, typename _Ep, typename = void> |
120 | struct _Ptr |
121 | { |
122 | using type = _Up*; |
123 | }; |
124 | |
125 | template <typename _Up, typename _Ep> |
126 | struct |
127 | _Ptr<_Up, _Ep, __void_t<typename remove_reference<_Ep>::type::pointer>> |
128 | { |
129 | using type = typename remove_reference<_Ep>::type::pointer; |
130 | }; |
131 | |
132 | public: |
133 | using _DeleterConstraint = enable_if< |
134 | __and_<__not_<is_pointer<_Dp>>, |
135 | is_default_constructible<_Dp>>::value>; |
136 | |
137 | using pointer = typename _Ptr<_Tp, _Dp>::type; |
138 | |
139 | __uniq_ptr_impl() = default; |
140 | __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; } |
141 | |
142 | template<typename _Del> |
143 | __uniq_ptr_impl(pointer __p, _Del&& __d) |
144 | : _M_t(__p, std::forward<_Del>(__d)) { } |
145 | |
146 | pointer& _M_ptr() { return std::get<0>(_M_t); } |
147 | pointer _M_ptr() const { return std::get<0>(_M_t); } |
148 | _Dp& _M_deleter() { return std::get<1>(_M_t); } |
149 | const _Dp& _M_deleter() const { return std::get<1>(_M_t); } |
150 | |
151 | private: |
152 | tuple<pointer, _Dp> _M_t; |
153 | }; |
154 | |
155 | /// 20.7.1.2 unique_ptr for single objects. |
156 | template <typename _Tp, typename _Dp = default_delete<_Tp>> |
157 | class unique_ptr |
158 | { |
159 | template <class _Up> |
160 | using _DeleterConstraint = |
161 | typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; |
162 | |
163 | __uniq_ptr_impl<_Tp, _Dp> _M_t; |
164 | |
165 | public: |
166 | using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; |
167 | using element_type = _Tp; |
168 | using deleter_type = _Dp; |
169 | |
170 | // helper template for detecting a safe conversion from another |
171 | // unique_ptr |
172 | template<typename _Up, typename _Ep> |
173 | using __safe_conversion_up = __and_< |
174 | is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>, |
175 | __not_<is_array<_Up>>, |
176 | __or_<__and_<is_reference<deleter_type>, |
177 | is_same<deleter_type, _Ep>>, |
178 | __and_<__not_<is_reference<deleter_type>>, |
179 | is_convertible<_Ep, deleter_type>> |
180 | > |
181 | >; |
182 | |
183 | // Constructors. |
184 | |
185 | /// Default constructor, creates a unique_ptr that owns nothing. |
186 | template <typename _Up = _Dp, |
187 | typename = _DeleterConstraint<_Up>> |
188 | constexpr unique_ptr() noexcept |
189 | : _M_t() |
190 | { } |
191 | |
192 | /** Takes ownership of a pointer. |
193 | * |
194 | * @param __p A pointer to an object of @c element_type |
195 | * |
196 | * The deleter will be value-initialized. |
197 | */ |
198 | template <typename _Up = _Dp, |
199 | typename = _DeleterConstraint<_Up>> |
200 | explicit |
201 | unique_ptr(pointer __p) noexcept |
202 | : _M_t(__p) |
203 | { } |
204 | |
205 | /** Takes ownership of a pointer. |
206 | * |
207 | * @param __p A pointer to an object of @c element_type |
208 | * @param __d A reference to a deleter. |
209 | * |
210 | * The deleter will be initialized with @p __d |
211 | */ |
212 | unique_ptr(pointer __p, |
213 | typename conditional<is_reference<deleter_type>::value, |
214 | deleter_type, const deleter_type&>::type __d) noexcept |
215 | : _M_t(__p, __d) { } |
216 | |
217 | /** Takes ownership of a pointer. |
218 | * |
219 | * @param __p A pointer to an object of @c element_type |
220 | * @param __d An rvalue reference to a deleter. |
221 | * |
222 | * The deleter will be initialized with @p std::move(__d) |
223 | */ |
224 | unique_ptr(pointer __p, |
225 | typename remove_reference<deleter_type>::type&& __d) noexcept |
226 | : _M_t(std::move(__p), std::move(__d)) |
227 | { static_assert(!std::is_reference<deleter_type>::value, |
228 | "rvalue deleter bound to reference"); } |
229 | |
230 | /// Creates a unique_ptr that owns nothing. |
231 | template <typename _Up = _Dp, |
232 | typename = _DeleterConstraint<_Up>> |
233 | constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { } |
234 | |
235 | // Move constructors. |
236 | |
237 | /// Move constructor. |
238 | unique_ptr(unique_ptr&& __u) noexcept |
239 | : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } |
240 | |
241 | /** @brief Converting constructor from another type |
242 | * |
243 | * Requires that the pointer owned by @p __u is convertible to the |
244 | * type of pointer owned by this object, @p __u does not own an array, |
245 | * and @p __u has a compatible deleter type. |
246 | */ |
247 | template<typename _Up, typename _Ep, typename = _Require< |
248 | __safe_conversion_up<_Up, _Ep>, |
249 | typename conditional<is_reference<_Dp>::value, |
250 | is_same<_Ep, _Dp>, |
251 | is_convertible<_Ep, _Dp>>::type>> |
252 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept |
253 | : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) |
254 | { } |
255 | |
256 | #if _GLIBCXX_USE_DEPRECATED1 |
257 | /// Converting constructor from @c auto_ptr |
258 | template<typename _Up, typename = _Require< |
259 | is_convertible<_Up*, _Tp*>, is_same<_Dp, default_delete<_Tp>>>> |
260 | unique_ptr(auto_ptr<_Up>&& __u) noexcept; |
261 | #endif |
262 | |
263 | /// Destructor, invokes the deleter if the stored pointer is not null. |
264 | ~unique_ptr() noexcept |
265 | { |
266 | auto& __ptr = _M_t._M_ptr(); |
267 | if (__ptr != nullptr) |
268 | get_deleter()(__ptr); |
269 | __ptr = pointer(); |
270 | } |
271 | |
272 | // Assignment. |
273 | |
274 | /** @brief Move assignment operator. |
275 | * |
276 | * @param __u The object to transfer ownership from. |
277 | * |
278 | * Invokes the deleter first if this object owns a pointer. |
279 | */ |
280 | unique_ptr& |
281 | operator=(unique_ptr&& __u) noexcept |
282 | { |
283 | reset(__u.release()); |
284 | get_deleter() = std::forward<deleter_type>(__u.get_deleter()); |
285 | return *this; |
286 | } |
287 | |
288 | /** @brief Assignment from another type. |
289 | * |
290 | * @param __u The object to transfer ownership from, which owns a |
291 | * convertible pointer to a non-array object. |
292 | * |
293 | * Invokes the deleter first if this object owns a pointer. |
294 | */ |
295 | template<typename _Up, typename _Ep> |
296 | typename enable_if< __and_< |
297 | __safe_conversion_up<_Up, _Ep>, |
298 | is_assignable<deleter_type&, _Ep&&> |
299 | >::value, |
300 | unique_ptr&>::type |
301 | operator=(unique_ptr<_Up, _Ep>&& __u) noexcept |
302 | { |
303 | reset(__u.release()); |
304 | get_deleter() = std::forward<_Ep>(__u.get_deleter()); |
305 | return *this; |
306 | } |
307 | |
308 | /// Reset the %unique_ptr to empty, invoking the deleter if necessary. |
309 | unique_ptr& |
310 | operator=(nullptr_t) noexcept |
311 | { |
312 | reset(); |
313 | return *this; |
314 | } |
315 | |
316 | // Observers. |
317 | |
318 | /// Dereference the stored pointer. |
319 | typename add_lvalue_reference<element_type>::type |
320 | operator*() const |
321 | { |
322 | __glibcxx_assert(get() != pointer()); |
323 | return *get(); |
324 | } |
325 | |
326 | /// Return the stored pointer. |
327 | pointer |
328 | operator->() const noexcept |
329 | { |
330 | _GLIBCXX_DEBUG_PEDASSERT(get() != pointer()); |
331 | return get(); |
332 | } |
333 | |
334 | /// Return the stored pointer. |
335 | pointer |
336 | get() const noexcept |
337 | { return _M_t._M_ptr(); } |
338 | |
339 | /// Return a reference to the stored deleter. |
340 | deleter_type& |
341 | get_deleter() noexcept |
342 | { return _M_t._M_deleter(); } |
343 | |
344 | /// Return a reference to the stored deleter. |
345 | const deleter_type& |
346 | get_deleter() const noexcept |
347 | { return _M_t._M_deleter(); } |
348 | |
349 | /// Return @c true if the stored pointer is not null. |
350 | explicit operator bool() const noexcept |
351 | { return get() == pointer() ? false : true; } |
352 | |
353 | // Modifiers. |
354 | |
355 | /// Release ownership of any stored pointer. |
356 | pointer |
357 | release() noexcept |
358 | { |
359 | pointer __p = get(); |
360 | _M_t._M_ptr() = pointer(); |
361 | return __p; |
362 | } |
363 | |
364 | /** @brief Replace the stored pointer. |
365 | * |
366 | * @param __p The new pointer to store. |
367 | * |
368 | * The deleter will be invoked if a pointer is already owned. |
369 | */ |
370 | void |
371 | reset(pointer __p = pointer()) noexcept |
372 | { |
373 | using std::swap; |
374 | swap(_M_t._M_ptr(), __p); |
375 | if (__p != pointer()) |
376 | get_deleter()(__p); |
377 | } |
378 | |
379 | /// Exchange the pointer and deleter with another object. |
380 | void |
381 | swap(unique_ptr& __u) noexcept |
382 | { |
383 | using std::swap; |
384 | swap(_M_t, __u._M_t); |
385 | } |
386 | |
387 | // Disable copy from lvalue. |
388 | unique_ptr(const unique_ptr&) = delete; |
389 | unique_ptr& operator=(const unique_ptr&) = delete; |
390 | }; |
391 | |
392 | /// 20.7.1.3 unique_ptr for array objects with a runtime length |
393 | // [unique.ptr.runtime] |
394 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
395 | // DR 740 - omit specialization for array objects with a compile time length |
396 | template<typename _Tp, typename _Dp> |
397 | class unique_ptr<_Tp[], _Dp> |
398 | { |
399 | template <typename _Up> |
400 | using _DeleterConstraint = |
401 | typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; |
402 | |
403 | __uniq_ptr_impl<_Tp, _Dp> _M_t; |
404 | |
405 | template<typename _Up> |
406 | using __remove_cv = typename remove_cv<_Up>::type; |
407 | |
408 | // like is_base_of<_Tp, _Up> but false if unqualified types are the same |
409 | template<typename _Up> |
410 | using __is_derived_Tp |
411 | = __and_< is_base_of<_Tp, _Up>, |
412 | __not_<is_same<__remove_cv<_Tp>, __remove_cv<_Up>>> >; |
413 | |
414 | public: |
415 | using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; |
416 | using element_type = _Tp; |
417 | using deleter_type = _Dp; |
418 | |
419 | // helper template for detecting a safe conversion from another |
420 | // unique_ptr |
421 | template<typename _Up, typename _Ep, |
422 | typename _Up_up = unique_ptr<_Up, _Ep>, |
423 | typename _Up_element_type = typename _Up_up::element_type> |
424 | using __safe_conversion_up = __and_< |
425 | is_array<_Up>, |
426 | is_same<pointer, element_type*>, |
427 | is_same<typename _Up_up::pointer, _Up_element_type*>, |
428 | is_convertible<_Up_element_type(*)[], element_type(*)[]>, |
429 | __or_<__and_<is_reference<deleter_type>, is_same<deleter_type, _Ep>>, |
430 | __and_<__not_<is_reference<deleter_type>>, |
431 | is_convertible<_Ep, deleter_type>>> |
432 | >; |
433 | |
434 | // helper template for detecting a safe conversion from a raw pointer |
435 | template<typename _Up> |
436 | using __safe_conversion_raw = __and_< |
437 | __or_<__or_<is_same<_Up, pointer>, |
438 | is_same<_Up, nullptr_t>>, |
439 | __and_<is_pointer<_Up>, |
440 | is_same<pointer, element_type*>, |
441 | is_convertible< |
442 | typename remove_pointer<_Up>::type(*)[], |
443 | element_type(*)[]> |
444 | > |
445 | > |
446 | >; |
447 | |
448 | // Constructors. |
449 | |
450 | /// Default constructor, creates a unique_ptr that owns nothing. |
451 | template <typename _Up = _Dp, |
452 | typename = _DeleterConstraint<_Up>> |
453 | constexpr unique_ptr() noexcept |
454 | : _M_t() |
455 | { } |
456 | |
457 | /** Takes ownership of a pointer. |
458 | * |
459 | * @param __p A pointer to an array of a type safely convertible |
460 | * to an array of @c element_type |
461 | * |
462 | * The deleter will be value-initialized. |
463 | */ |
464 | template<typename _Up, |
465 | typename _Vp = _Dp, |
466 | typename = _DeleterConstraint<_Vp>, |
467 | typename = typename enable_if< |
468 | __safe_conversion_raw<_Up>::value, bool>::type> |
469 | explicit |
470 | unique_ptr(_Up __p) noexcept |
471 | : _M_t(__p) |
472 | { } |
473 | |
474 | /** Takes ownership of a pointer. |
475 | * |
476 | * @param __p A pointer to an array of a type safely convertible |
477 | * to an array of @c element_type |
478 | * @param __d A reference to a deleter. |
479 | * |
480 | * The deleter will be initialized with @p __d |
481 | */ |
482 | template<typename _Up, |
483 | typename = typename enable_if< |
484 | __safe_conversion_raw<_Up>::value, bool>::type> |
485 | unique_ptr(_Up __p, |
486 | typename conditional<is_reference<deleter_type>::value, |
487 | deleter_type, const deleter_type&>::type __d) noexcept |
488 | : _M_t(__p, __d) { } |
489 | |
490 | /** Takes ownership of a pointer. |
491 | * |
492 | * @param __p A pointer to an array of a type safely convertible |
493 | * to an array of @c element_type |
494 | * @param __d A reference to a deleter. |
495 | * |
496 | * The deleter will be initialized with @p std::move(__d) |
497 | */ |
498 | template<typename _Up, |
499 | typename = typename enable_if< |
500 | __safe_conversion_raw<_Up>::value, bool>::type> |
501 | unique_ptr(_Up __p, typename |
502 | remove_reference<deleter_type>::type&& __d) noexcept |
503 | : _M_t(std::move(__p), std::move(__d)) |
504 | { static_assert(!is_reference<deleter_type>::value, |
505 | "rvalue deleter bound to reference"); } |
506 | |
507 | /// Move constructor. |
508 | unique_ptr(unique_ptr&& __u) noexcept |
509 | : _M_t(__u.release(), std::forward<deleter_type>(__u.get_deleter())) { } |
510 | |
511 | /// Creates a unique_ptr that owns nothing. |
512 | template <typename _Up = _Dp, |
513 | typename = _DeleterConstraint<_Up>> |
514 | constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { } |
515 | |
516 | template<typename _Up, typename _Ep, |
517 | typename = _Require<__safe_conversion_up<_Up, _Ep>>> |
518 | unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept |
519 | : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) |
520 | { } |
521 | |
522 | /// Destructor, invokes the deleter if the stored pointer is not null. |
523 | ~unique_ptr() |
524 | { |
525 | auto& __ptr = _M_t._M_ptr(); |
526 | if (__ptr != nullptr) |
527 | get_deleter()(__ptr); |
528 | __ptr = pointer(); |
529 | } |
530 | |
531 | // Assignment. |
532 | |
533 | /** @brief Move assignment operator. |
534 | * |
535 | * @param __u The object to transfer ownership from. |
536 | * |
537 | * Invokes the deleter first if this object owns a pointer. |
538 | */ |
539 | unique_ptr& |
540 | operator=(unique_ptr&& __u) noexcept |
541 | { |
542 | reset(__u.release()); |
543 | get_deleter() = std::forward<deleter_type>(__u.get_deleter()); |
544 | return *this; |
545 | } |
546 | |
547 | /** @brief Assignment from another type. |
548 | * |
549 | * @param __u The object to transfer ownership from, which owns a |
550 | * convertible pointer to an array object. |
551 | * |
552 | * Invokes the deleter first if this object owns a pointer. |
553 | */ |
554 | template<typename _Up, typename _Ep> |
555 | typename |
556 | enable_if<__and_<__safe_conversion_up<_Up, _Ep>, |
557 | is_assignable<deleter_type&, _Ep&&> |
558 | >::value, |
559 | unique_ptr&>::type |
560 | operator=(unique_ptr<_Up, _Ep>&& __u) noexcept |
561 | { |
562 | reset(__u.release()); |
563 | get_deleter() = std::forward<_Ep>(__u.get_deleter()); |
564 | return *this; |
565 | } |
566 | |
567 | /// Reset the %unique_ptr to empty, invoking the deleter if necessary. |
568 | unique_ptr& |
569 | operator=(nullptr_t) noexcept |
570 | { |
571 | reset(); |
572 | return *this; |
573 | } |
574 | |
575 | // Observers. |
576 | |
577 | /// Access an element of owned array. |
578 | typename std::add_lvalue_reference<element_type>::type |
579 | operator[](size_t __i) const |
580 | { |
581 | __glibcxx_assert(get() != pointer()); |
582 | return get()[__i]; |
583 | } |
584 | |
585 | /// Return the stored pointer. |
586 | pointer |
587 | get() const noexcept |
588 | { return _M_t._M_ptr(); } |
589 | |
590 | /// Return a reference to the stored deleter. |
591 | deleter_type& |
592 | get_deleter() noexcept |
593 | { return _M_t._M_deleter(); } |
594 | |
595 | /// Return a reference to the stored deleter. |
596 | const deleter_type& |
597 | get_deleter() const noexcept |
598 | { return _M_t._M_deleter(); } |
599 | |
600 | /// Return @c true if the stored pointer is not null. |
601 | explicit operator bool() const noexcept |
602 | { return get() == pointer() ? false : true; } |
603 | |
604 | // Modifiers. |
605 | |
606 | /// Release ownership of any stored pointer. |
607 | pointer |
608 | release() noexcept |
609 | { |
610 | pointer __p = get(); |
611 | _M_t._M_ptr() = pointer(); |
612 | return __p; |
613 | } |
614 | |
615 | /** @brief Replace the stored pointer. |
616 | * |
617 | * @param __p The new pointer to store. |
618 | * |
619 | * The deleter will be invoked if a pointer is already owned. |
620 | */ |
621 | template <typename _Up, |
622 | typename = _Require< |
623 | __or_<is_same<_Up, pointer>, |
624 | __and_<is_same<pointer, element_type*>, |
625 | is_pointer<_Up>, |
626 | is_convertible< |
627 | typename remove_pointer<_Up>::type(*)[], |
628 | element_type(*)[] |
629 | > |
630 | > |
631 | > |
632 | >> |
633 | void |
634 | reset(_Up __p) noexcept |
635 | { |
636 | pointer __ptr = __p; |
637 | using std::swap; |
638 | swap(_M_t._M_ptr(), __ptr); |
639 | if (__ptr != nullptr) |
640 | get_deleter()(__ptr); |
641 | } |
642 | |
643 | void reset(nullptr_t = nullptr) noexcept |
644 | { |
645 | reset(pointer()); |
646 | } |
647 | |
648 | /// Exchange the pointer and deleter with another object. |
649 | void |
650 | swap(unique_ptr& __u) noexcept |
651 | { |
652 | using std::swap; |
653 | swap(_M_t, __u._M_t); |
654 | } |
655 | |
656 | // Disable copy from lvalue. |
657 | unique_ptr(const unique_ptr&) = delete; |
658 | unique_ptr& operator=(const unique_ptr&) = delete; |
659 | }; |
660 | |
661 | template<typename _Tp, typename _Dp> |
662 | inline |
663 | #if __cplusplus201103L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11 |
664 | // Constrained free swap overload, see p0185r1 |
665 | typename enable_if<__is_swappable<_Dp>::value>::type |
666 | #else |
667 | void |
668 | #endif |
669 | swap(unique_ptr<_Tp, _Dp>& __x, |
670 | unique_ptr<_Tp, _Dp>& __y) noexcept |
671 | { __x.swap(__y); } |
672 | |
673 | #if __cplusplus201103L > 201402L || !defined(__STRICT_ANSI__1) // c++1z or gnu++11 |
674 | template<typename _Tp, typename _Dp> |
675 | typename enable_if<!__is_swappable<_Dp>::value>::type |
676 | swap(unique_ptr<_Tp, _Dp>&, |
677 | unique_ptr<_Tp, _Dp>&) = delete; |
678 | #endif |
679 | |
680 | template<typename _Tp, typename _Dp, |
681 | typename _Up, typename _Ep> |
682 | inline bool |
683 | operator==(const unique_ptr<_Tp, _Dp>& __x, |
684 | const unique_ptr<_Up, _Ep>& __y) |
685 | { return __x.get() == __y.get(); } |
686 | |
687 | template<typename _Tp, typename _Dp> |
688 | inline bool |
689 | operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept |
690 | { return !__x; } |
691 | |
692 | template<typename _Tp, typename _Dp> |
693 | inline bool |
694 | operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept |
695 | { return !__x; } |
696 | |
697 | template<typename _Tp, typename _Dp, |
698 | typename _Up, typename _Ep> |
699 | inline bool |
700 | operator!=(const unique_ptr<_Tp, _Dp>& __x, |
701 | const unique_ptr<_Up, _Ep>& __y) |
702 | { return __x.get() != __y.get(); } |
703 | |
704 | template<typename _Tp, typename _Dp> |
705 | inline bool |
706 | operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept |
707 | { return (bool)__x; } |
708 | |
709 | template<typename _Tp, typename _Dp> |
710 | inline bool |
711 | operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept |
712 | { return (bool)__x; } |
713 | |
714 | template<typename _Tp, typename _Dp, |
715 | typename _Up, typename _Ep> |
716 | inline bool |
717 | operator<(const unique_ptr<_Tp, _Dp>& __x, |
718 | const unique_ptr<_Up, _Ep>& __y) |
719 | { |
720 | typedef typename |
721 | std::common_type<typename unique_ptr<_Tp, _Dp>::pointer, |
722 | typename unique_ptr<_Up, _Ep>::pointer>::type _CT; |
723 | return std::less<_CT>()(__x.get(), __y.get()); |
724 | } |
725 | |
726 | template<typename _Tp, typename _Dp> |
727 | inline bool |
728 | operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
729 | { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(), |
730 | nullptr); } |
731 | |
732 | template<typename _Tp, typename _Dp> |
733 | inline bool |
734 | operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
735 | { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr, |
736 | __x.get()); } |
737 | |
738 | template<typename _Tp, typename _Dp, |
739 | typename _Up, typename _Ep> |
740 | inline bool |
741 | operator<=(const unique_ptr<_Tp, _Dp>& __x, |
742 | const unique_ptr<_Up, _Ep>& __y) |
743 | { return !(__y < __x); } |
744 | |
745 | template<typename _Tp, typename _Dp> |
746 | inline bool |
747 | operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
748 | { return !(nullptr < __x); } |
749 | |
750 | template<typename _Tp, typename _Dp> |
751 | inline bool |
752 | operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
753 | { return !(__x < nullptr); } |
754 | |
755 | template<typename _Tp, typename _Dp, |
756 | typename _Up, typename _Ep> |
757 | inline bool |
758 | operator>(const unique_ptr<_Tp, _Dp>& __x, |
759 | const unique_ptr<_Up, _Ep>& __y) |
760 | { return (__y < __x); } |
761 | |
762 | template<typename _Tp, typename _Dp> |
763 | inline bool |
764 | operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
765 | { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr, |
766 | __x.get()); } |
767 | |
768 | template<typename _Tp, typename _Dp> |
769 | inline bool |
770 | operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
771 | { return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(), |
772 | nullptr); } |
773 | |
774 | template<typename _Tp, typename _Dp, |
775 | typename _Up, typename _Ep> |
776 | inline bool |
777 | operator>=(const unique_ptr<_Tp, _Dp>& __x, |
778 | const unique_ptr<_Up, _Ep>& __y) |
779 | { return !(__x < __y); } |
780 | |
781 | template<typename _Tp, typename _Dp> |
782 | inline bool |
783 | operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) |
784 | { return !(__x < nullptr); } |
785 | |
786 | template<typename _Tp, typename _Dp> |
787 | inline bool |
788 | operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) |
789 | { return !(nullptr < __x); } |
790 | |
791 | /// std::hash specialization for unique_ptr. |
792 | template<typename _Tp, typename _Dp> |
793 | struct hash<unique_ptr<_Tp, _Dp>> |
794 | : public __hash_base<size_t, unique_ptr<_Tp, _Dp>>, |
795 | private __poison_hash<typename unique_ptr<_Tp, _Dp>::pointer> |
796 | { |
797 | size_t |
798 | operator()(const unique_ptr<_Tp, _Dp>& __u) const noexcept |
799 | { |
800 | typedef unique_ptr<_Tp, _Dp> _UP; |
801 | return std::hash<typename _UP::pointer>()(__u.get()); |
802 | } |
803 | }; |
804 | |
805 | #if __cplusplus201103L > 201103L |
806 | |
807 | #define __cpp_lib_make_unique 201304 |
808 | |
809 | template<typename _Tp> |
810 | struct _MakeUniq |
811 | { typedef unique_ptr<_Tp> __single_object; }; |
812 | |
813 | template<typename _Tp> |
814 | struct _MakeUniq<_Tp[]> |
815 | { typedef unique_ptr<_Tp[]> __array; }; |
816 | |
817 | template<typename _Tp, size_t _Bound> |
818 | struct _MakeUniq<_Tp[_Bound]> |
819 | { struct __invalid_type { }; }; |
820 | |
821 | /// std::make_unique for single objects |
822 | template<typename _Tp, typename... _Args> |
823 | inline typename _MakeUniq<_Tp>::__single_object |
824 | make_unique(_Args&&... __args) |
825 | { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); } |
826 | |
827 | /// std::make_unique for arrays of unknown bound |
828 | template<typename _Tp> |
829 | inline typename _MakeUniq<_Tp>::__array |
830 | make_unique(size_t __num) |
831 | { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); } |
832 | |
833 | /// Disable std::make_unique for arrays of known bound |
834 | template<typename _Tp, typename... _Args> |
835 | inline typename _MakeUniq<_Tp>::__invalid_type |
836 | make_unique(_Args&&...) = delete; |
837 | #endif |
838 | |
839 | // @} group pointer_abstractions |
840 | |
841 | _GLIBCXX_END_NAMESPACE_VERSION |
842 | } // namespace |
843 | |
844 | #endif /* _UNIQUE_PTR_H */ |