File: | tools/clang/lib/Frontend/DependencyFile.cpp |
Warning: | line 248, column 7 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===--- DependencyFile.cpp - Generate dependency file --------------------===// | |||
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 | // This code generates dependency files. | |||
11 | // | |||
12 | //===----------------------------------------------------------------------===// | |||
13 | ||||
14 | #include "clang/Frontend/Utils.h" | |||
15 | #include "clang/Basic/FileManager.h" | |||
16 | #include "clang/Basic/SourceManager.h" | |||
17 | #include "clang/Frontend/DependencyOutputOptions.h" | |||
18 | #include "clang/Frontend/FrontendDiagnostic.h" | |||
19 | #include "clang/Lex/DirectoryLookup.h" | |||
20 | #include "clang/Lex/LexDiagnostic.h" | |||
21 | #include "clang/Lex/ModuleMap.h" | |||
22 | #include "clang/Lex/PPCallbacks.h" | |||
23 | #include "clang/Lex/Preprocessor.h" | |||
24 | #include "clang/Serialization/ASTReader.h" | |||
25 | #include "llvm/ADT/StringSet.h" | |||
26 | #include "llvm/ADT/StringSwitch.h" | |||
27 | #include "llvm/Support/FileSystem.h" | |||
28 | #include "llvm/Support/Path.h" | |||
29 | #include "llvm/Support/raw_ostream.h" | |||
30 | ||||
31 | using namespace clang; | |||
32 | ||||
33 | namespace { | |||
34 | struct DepCollectorPPCallbacks : public PPCallbacks { | |||
35 | DependencyCollector &DepCollector; | |||
36 | SourceManager &SM; | |||
37 | DepCollectorPPCallbacks(DependencyCollector &L, SourceManager &SM) | |||
38 | : DepCollector(L), SM(SM) { } | |||
39 | ||||
40 | void FileChanged(SourceLocation Loc, FileChangeReason Reason, | |||
41 | SrcMgr::CharacteristicKind FileType, | |||
42 | FileID PrevFID) override { | |||
43 | if (Reason != PPCallbacks::EnterFile) | |||
44 | return; | |||
45 | ||||
46 | // Dependency generation really does want to go all the way to the | |||
47 | // file entry for a source location to find out what is depended on. | |||
48 | // We do not want #line markers to affect dependency generation! | |||
49 | const FileEntry *FE = | |||
50 | SM.getFileEntryForID(SM.getFileID(SM.getExpansionLoc(Loc))); | |||
51 | if (!FE) | |||
52 | return; | |||
53 | ||||
54 | StringRef Filename = | |||
55 | llvm::sys::path::remove_leading_dotslash(FE->getName()); | |||
56 | ||||
57 | DepCollector.maybeAddDependency(Filename, /*FromModule*/false, | |||
58 | isSystem(FileType), | |||
59 | /*IsModuleFile*/false, /*IsMissing*/false); | |||
60 | } | |||
61 | ||||
62 | void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, | |||
63 | StringRef FileName, bool IsAngled, | |||
64 | CharSourceRange FilenameRange, const FileEntry *File, | |||
65 | StringRef SearchPath, StringRef RelativePath, | |||
66 | const Module *Imported) override { | |||
67 | if (!File) | |||
68 | DepCollector.maybeAddDependency(FileName, /*FromModule*/false, | |||
69 | /*IsSystem*/false, /*IsModuleFile*/false, | |||
70 | /*IsMissing*/true); | |||
71 | // Files that actually exist are handled by FileChanged. | |||
72 | } | |||
73 | ||||
74 | void EndOfMainFile() override { | |||
75 | DepCollector.finishedMainFile(); | |||
76 | } | |||
77 | }; | |||
78 | ||||
79 | struct DepCollectorMMCallbacks : public ModuleMapCallbacks { | |||
80 | DependencyCollector &DepCollector; | |||
81 | DepCollectorMMCallbacks(DependencyCollector &DC) : DepCollector(DC) {} | |||
82 | ||||
83 | void moduleMapFileRead(SourceLocation Loc, const FileEntry &Entry, | |||
84 | bool IsSystem) override { | |||
85 | StringRef Filename = Entry.getName(); | |||
86 | DepCollector.maybeAddDependency(Filename, /*FromModule*/false, | |||
87 | /*IsSystem*/IsSystem, | |||
88 | /*IsModuleFile*/false, | |||
89 | /*IsMissing*/false); | |||
90 | } | |||
91 | }; | |||
92 | ||||
93 | struct DepCollectorASTListener : public ASTReaderListener { | |||
94 | DependencyCollector &DepCollector; | |||
95 | DepCollectorASTListener(DependencyCollector &L) : DepCollector(L) { } | |||
96 | bool needsInputFileVisitation() override { return true; } | |||
97 | bool needsSystemInputFileVisitation() override { | |||
98 | return DepCollector.needSystemDependencies(); | |||
99 | } | |||
100 | void visitModuleFile(StringRef Filename, | |||
101 | serialization::ModuleKind Kind) override { | |||
102 | DepCollector.maybeAddDependency(Filename, /*FromModule*/true, | |||
103 | /*IsSystem*/false, /*IsModuleFile*/true, | |||
104 | /*IsMissing*/false); | |||
105 | } | |||
106 | bool visitInputFile(StringRef Filename, bool IsSystem, | |||
107 | bool IsOverridden, bool IsExplicitModule) override { | |||
108 | if (IsOverridden || IsExplicitModule) | |||
109 | return true; | |||
110 | ||||
111 | DepCollector.maybeAddDependency(Filename, /*FromModule*/true, IsSystem, | |||
112 | /*IsModuleFile*/false, /*IsMissing*/false); | |||
113 | return true; | |||
114 | } | |||
115 | }; | |||
116 | } // end anonymous namespace | |||
117 | ||||
118 | void DependencyCollector::maybeAddDependency(StringRef Filename, bool FromModule, | |||
119 | bool IsSystem, bool IsModuleFile, | |||
120 | bool IsMissing) { | |||
121 | if (Seen.insert(Filename).second && | |||
122 | sawDependency(Filename, FromModule, IsSystem, IsModuleFile, IsMissing)) | |||
123 | Dependencies.push_back(Filename); | |||
124 | } | |||
125 | ||||
126 | static bool isSpecialFilename(StringRef Filename) { | |||
127 | return llvm::StringSwitch<bool>(Filename) | |||
128 | .Case("<built-in>", true) | |||
129 | .Case("<stdin>", true) | |||
130 | .Default(false); | |||
131 | } | |||
132 | ||||
133 | bool DependencyCollector::sawDependency(StringRef Filename, bool FromModule, | |||
134 | bool IsSystem, bool IsModuleFile, | |||
135 | bool IsMissing) { | |||
136 | return !isSpecialFilename(Filename) && | |||
137 | (needSystemDependencies() || !IsSystem); | |||
138 | } | |||
139 | ||||
140 | DependencyCollector::~DependencyCollector() { } | |||
141 | void DependencyCollector::attachToPreprocessor(Preprocessor &PP) { | |||
142 | PP.addPPCallbacks( | |||
143 | llvm::make_unique<DepCollectorPPCallbacks>(*this, PP.getSourceManager())); | |||
144 | PP.getHeaderSearchInfo().getModuleMap().addModuleMapCallbacks( | |||
145 | llvm::make_unique<DepCollectorMMCallbacks>(*this)); | |||
146 | } | |||
147 | void DependencyCollector::attachToASTReader(ASTReader &R) { | |||
148 | R.addListener(llvm::make_unique<DepCollectorASTListener>(*this)); | |||
149 | } | |||
150 | ||||
151 | namespace { | |||
152 | /// Private implementation for DependencyFileGenerator | |||
153 | class DFGImpl : public PPCallbacks { | |||
154 | std::vector<std::string> Files; | |||
155 | llvm::StringSet<> FilesSet; | |||
156 | const Preprocessor *PP; | |||
157 | std::string OutputFile; | |||
158 | std::vector<std::string> Targets; | |||
159 | bool IncludeSystemHeaders; | |||
160 | bool PhonyTarget; | |||
161 | bool AddMissingHeaderDeps; | |||
162 | bool SeenMissingHeader; | |||
163 | bool IncludeModuleFiles; | |||
164 | DependencyOutputFormat OutputFormat; | |||
165 | ||||
166 | private: | |||
167 | bool FileMatchesDepCriteria(const char *Filename, | |||
168 | SrcMgr::CharacteristicKind FileType); | |||
169 | void OutputDependencyFile(); | |||
170 | ||||
171 | public: | |||
172 | DFGImpl(const Preprocessor *_PP, const DependencyOutputOptions &Opts) | |||
173 | : PP(_PP), OutputFile(Opts.OutputFile), Targets(Opts.Targets), | |||
174 | IncludeSystemHeaders(Opts.IncludeSystemHeaders), | |||
175 | PhonyTarget(Opts.UsePhonyTargets), | |||
176 | AddMissingHeaderDeps(Opts.AddMissingHeaderDeps), | |||
177 | SeenMissingHeader(false), | |||
178 | IncludeModuleFiles(Opts.IncludeModuleFiles), | |||
179 | OutputFormat(Opts.OutputFormat) { | |||
180 | for (const auto &ExtraDep : Opts.ExtraDeps) { | |||
181 | AddFilename(ExtraDep); | |||
182 | } | |||
183 | } | |||
184 | ||||
185 | void FileChanged(SourceLocation Loc, FileChangeReason Reason, | |||
186 | SrcMgr::CharacteristicKind FileType, | |||
187 | FileID PrevFID) override; | |||
188 | void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, | |||
189 | StringRef FileName, bool IsAngled, | |||
190 | CharSourceRange FilenameRange, const FileEntry *File, | |||
191 | StringRef SearchPath, StringRef RelativePath, | |||
192 | const Module *Imported) override; | |||
193 | ||||
194 | void EndOfMainFile() override { | |||
195 | OutputDependencyFile(); | |||
196 | } | |||
197 | ||||
198 | void AddFilename(StringRef Filename); | |||
199 | bool includeSystemHeaders() const { return IncludeSystemHeaders; } | |||
200 | bool includeModuleFiles() const { return IncludeModuleFiles; } | |||
201 | }; | |||
202 | ||||
203 | class DFGMMCallback : public ModuleMapCallbacks { | |||
204 | DFGImpl &Parent; | |||
205 | public: | |||
206 | DFGMMCallback(DFGImpl &Parent) : Parent(Parent) {} | |||
207 | void moduleMapFileRead(SourceLocation Loc, const FileEntry &Entry, | |||
208 | bool IsSystem) override { | |||
209 | if (!IsSystem || Parent.includeSystemHeaders()) | |||
210 | Parent.AddFilename(Entry.getName()); | |||
211 | } | |||
212 | }; | |||
213 | ||||
214 | class DFGASTReaderListener : public ASTReaderListener { | |||
215 | DFGImpl &Parent; | |||
216 | public: | |||
217 | DFGASTReaderListener(DFGImpl &Parent) | |||
218 | : Parent(Parent) { } | |||
219 | bool needsInputFileVisitation() override { return true; } | |||
220 | bool needsSystemInputFileVisitation() override { | |||
221 | return Parent.includeSystemHeaders(); | |||
222 | } | |||
223 | void visitModuleFile(StringRef Filename, | |||
224 | serialization::ModuleKind Kind) override; | |||
225 | bool visitInputFile(StringRef Filename, bool isSystem, | |||
226 | bool isOverridden, bool isExplicitModule) override; | |||
227 | }; | |||
228 | } | |||
229 | ||||
230 | DependencyFileGenerator::DependencyFileGenerator(void *Impl) | |||
231 | : Impl(Impl) { } | |||
232 | ||||
233 | DependencyFileGenerator *DependencyFileGenerator::CreateAndAttachToPreprocessor( | |||
234 | clang::Preprocessor &PP, const clang::DependencyOutputOptions &Opts) { | |||
235 | ||||
236 | if (Opts.Targets.empty()) { | |||
| ||||
237 | PP.getDiagnostics().Report(diag::err_fe_dependency_file_requires_MT); | |||
238 | return nullptr; | |||
239 | } | |||
240 | ||||
241 | // Disable the "file not found" diagnostic if the -MG option was given. | |||
242 | if (Opts.AddMissingHeaderDeps) | |||
243 | PP.SetSuppressIncludeNotFoundError(true); | |||
244 | ||||
245 | DFGImpl *Callback = new DFGImpl(&PP, Opts); | |||
246 | PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callback)); | |||
247 | PP.getHeaderSearchInfo().getModuleMap().addModuleMapCallbacks( | |||
248 | llvm::make_unique<DFGMMCallback>(*Callback)); | |||
| ||||
249 | return new DependencyFileGenerator(Callback); | |||
250 | } | |||
251 | ||||
252 | void DependencyFileGenerator::AttachToASTReader(ASTReader &R) { | |||
253 | DFGImpl *I = reinterpret_cast<DFGImpl *>(Impl); | |||
254 | assert(I && "missing implementation")(static_cast <bool> (I && "missing implementation" ) ? void (0) : __assert_fail ("I && \"missing implementation\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/DependencyFile.cpp" , 254, __extension__ __PRETTY_FUNCTION__)); | |||
255 | R.addListener(llvm::make_unique<DFGASTReaderListener>(*I)); | |||
256 | } | |||
257 | ||||
258 | /// FileMatchesDepCriteria - Determine whether the given Filename should be | |||
259 | /// considered as a dependency. | |||
260 | bool DFGImpl::FileMatchesDepCriteria(const char *Filename, | |||
261 | SrcMgr::CharacteristicKind FileType) { | |||
262 | if (isSpecialFilename(Filename)) | |||
263 | return false; | |||
264 | ||||
265 | if (IncludeSystemHeaders) | |||
266 | return true; | |||
267 | ||||
268 | return !isSystem(FileType); | |||
269 | } | |||
270 | ||||
271 | void DFGImpl::FileChanged(SourceLocation Loc, | |||
272 | FileChangeReason Reason, | |||
273 | SrcMgr::CharacteristicKind FileType, | |||
274 | FileID PrevFID) { | |||
275 | if (Reason != PPCallbacks::EnterFile) | |||
276 | return; | |||
277 | ||||
278 | // Dependency generation really does want to go all the way to the | |||
279 | // file entry for a source location to find out what is depended on. | |||
280 | // We do not want #line markers to affect dependency generation! | |||
281 | SourceManager &SM = PP->getSourceManager(); | |||
282 | ||||
283 | const FileEntry *FE = | |||
284 | SM.getFileEntryForID(SM.getFileID(SM.getExpansionLoc(Loc))); | |||
285 | if (!FE) return; | |||
286 | ||||
287 | StringRef Filename = FE->getName(); | |||
288 | if (!FileMatchesDepCriteria(Filename.data(), FileType)) | |||
289 | return; | |||
290 | ||||
291 | AddFilename(llvm::sys::path::remove_leading_dotslash(Filename)); | |||
292 | } | |||
293 | ||||
294 | void DFGImpl::InclusionDirective(SourceLocation HashLoc, | |||
295 | const Token &IncludeTok, | |||
296 | StringRef FileName, | |||
297 | bool IsAngled, | |||
298 | CharSourceRange FilenameRange, | |||
299 | const FileEntry *File, | |||
300 | StringRef SearchPath, | |||
301 | StringRef RelativePath, | |||
302 | const Module *Imported) { | |||
303 | if (!File) { | |||
304 | if (AddMissingHeaderDeps) | |||
305 | AddFilename(FileName); | |||
306 | else | |||
307 | SeenMissingHeader = true; | |||
308 | } | |||
309 | } | |||
310 | ||||
311 | void DFGImpl::AddFilename(StringRef Filename) { | |||
312 | if (FilesSet.insert(Filename).second) | |||
313 | Files.push_back(Filename); | |||
314 | } | |||
315 | ||||
316 | /// Print the filename, with escaping or quoting that accommodates the three | |||
317 | /// most likely tools that use dependency files: GNU Make, BSD Make, and | |||
318 | /// NMake/Jom. | |||
319 | /// | |||
320 | /// BSD Make is the simplest case: It does no escaping at all. This means | |||
321 | /// characters that are normally delimiters, i.e. space and # (the comment | |||
322 | /// character) simply aren't supported in filenames. | |||
323 | /// | |||
324 | /// GNU Make does allow space and # in filenames, but to avoid being treated | |||
325 | /// as a delimiter or comment, these must be escaped with a backslash. Because | |||
326 | /// backslash is itself the escape character, if a backslash appears in a | |||
327 | /// filename, it should be escaped as well. (As a special case, $ is escaped | |||
328 | /// as $$, which is the normal Make way to handle the $ character.) | |||
329 | /// For compatibility with BSD Make and historical practice, if GNU Make | |||
330 | /// un-escapes characters in a filename but doesn't find a match, it will | |||
331 | /// retry with the unmodified original string. | |||
332 | /// | |||
333 | /// GCC tries to accommodate both Make formats by escaping any space or # | |||
334 | /// characters in the original filename, but not escaping backslashes. The | |||
335 | /// apparent intent is so that filenames with backslashes will be handled | |||
336 | /// correctly by BSD Make, and by GNU Make in its fallback mode of using the | |||
337 | /// unmodified original string; filenames with # or space characters aren't | |||
338 | /// supported by BSD Make at all, but will be handled correctly by GNU Make | |||
339 | /// due to the escaping. | |||
340 | /// | |||
341 | /// A corner case that GCC gets only partly right is when the original filename | |||
342 | /// has a backslash immediately followed by space or #. GNU Make would expect | |||
343 | /// this backslash to be escaped; however GCC escapes the original backslash | |||
344 | /// only when followed by space, not #. It will therefore take a dependency | |||
345 | /// from a directive such as | |||
346 | /// #include "a\ b\#c.h" | |||
347 | /// and emit it as | |||
348 | /// a\\\ b\\#c.h | |||
349 | /// which GNU Make will interpret as | |||
350 | /// a\ b\ | |||
351 | /// followed by a comment. Failing to find this file, it will fall back to the | |||
352 | /// original string, which probably doesn't exist either; in any case it won't | |||
353 | /// find | |||
354 | /// a\ b\#c.h | |||
355 | /// which is the actual filename specified by the include directive. | |||
356 | /// | |||
357 | /// Clang does what GCC does, rather than what GNU Make expects. | |||
358 | /// | |||
359 | /// NMake/Jom has a different set of scary characters, but wraps filespecs in | |||
360 | /// double-quotes to avoid misinterpreting them; see | |||
361 | /// https://msdn.microsoft.com/en-us/library/dd9y37ha.aspx for NMake info, | |||
362 | /// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx | |||
363 | /// for Windows file-naming info. | |||
364 | static void PrintFilename(raw_ostream &OS, StringRef Filename, | |||
365 | DependencyOutputFormat OutputFormat) { | |||
366 | if (OutputFormat == DependencyOutputFormat::NMake) { | |||
367 | // Add quotes if needed. These are the characters listed as "special" to | |||
368 | // NMake, that are legal in a Windows filespec, and that could cause | |||
369 | // misinterpretation of the dependency string. | |||
370 | if (Filename.find_first_of(" #${}^!") != StringRef::npos) | |||
371 | OS << '\"' << Filename << '\"'; | |||
372 | else | |||
373 | OS << Filename; | |||
374 | return; | |||
375 | } | |||
376 | assert(OutputFormat == DependencyOutputFormat::Make)(static_cast <bool> (OutputFormat == DependencyOutputFormat ::Make) ? void (0) : __assert_fail ("OutputFormat == DependencyOutputFormat::Make" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/DependencyFile.cpp" , 376, __extension__ __PRETTY_FUNCTION__)); | |||
377 | for (unsigned i = 0, e = Filename.size(); i != e; ++i) { | |||
378 | if (Filename[i] == '#') // Handle '#' the broken gcc way. | |||
379 | OS << '\\'; | |||
380 | else if (Filename[i] == ' ') { // Handle space correctly. | |||
381 | OS << '\\'; | |||
382 | unsigned j = i; | |||
383 | while (j > 0 && Filename[--j] == '\\') | |||
384 | OS << '\\'; | |||
385 | } else if (Filename[i] == '$') // $ is escaped by $$. | |||
386 | OS << '$'; | |||
387 | OS << Filename[i]; | |||
388 | } | |||
389 | } | |||
390 | ||||
391 | void DFGImpl::OutputDependencyFile() { | |||
392 | if (SeenMissingHeader) { | |||
393 | llvm::sys::fs::remove(OutputFile); | |||
394 | return; | |||
395 | } | |||
396 | ||||
397 | std::error_code EC; | |||
398 | llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_Text); | |||
399 | if (EC) { | |||
400 | PP->getDiagnostics().Report(diag::err_fe_error_opening) << OutputFile | |||
401 | << EC.message(); | |||
402 | return; | |||
403 | } | |||
404 | ||||
405 | // Write out the dependency targets, trying to avoid overly long | |||
406 | // lines when possible. We try our best to emit exactly the same | |||
407 | // dependency file as GCC (4.2), assuming the included files are the | |||
408 | // same. | |||
409 | const unsigned MaxColumns = 75; | |||
410 | unsigned Columns = 0; | |||
411 | ||||
412 | for (StringRef Target : Targets) { | |||
413 | unsigned N = Target.size(); | |||
414 | if (Columns == 0) { | |||
415 | Columns += N; | |||
416 | } else if (Columns + N + 2 > MaxColumns) { | |||
417 | Columns = N + 2; | |||
418 | OS << " \\\n "; | |||
419 | } else { | |||
420 | Columns += N + 1; | |||
421 | OS << ' '; | |||
422 | } | |||
423 | // Targets already quoted as needed. | |||
424 | OS << Target; | |||
425 | } | |||
426 | ||||
427 | OS << ':'; | |||
428 | Columns += 1; | |||
429 | ||||
430 | // Now add each dependency in the order it was seen, but avoiding | |||
431 | // duplicates. | |||
432 | for (StringRef File : Files) { | |||
433 | // Start a new line if this would exceed the column limit. Make | |||
434 | // sure to leave space for a trailing " \" in case we need to | |||
435 | // break the line on the next iteration. | |||
436 | unsigned N = File.size(); | |||
437 | if (Columns + (N + 1) + 2 > MaxColumns) { | |||
438 | OS << " \\\n "; | |||
439 | Columns = 2; | |||
440 | } | |||
441 | OS << ' '; | |||
442 | PrintFilename(OS, File, OutputFormat); | |||
443 | Columns += N + 1; | |||
444 | } | |||
445 | OS << '\n'; | |||
446 | ||||
447 | // Create phony targets if requested. | |||
448 | if (PhonyTarget && !Files.empty()) { | |||
449 | // Skip the first entry, this is always the input file itself. | |||
450 | for (auto I = Files.begin() + 1, E = Files.end(); I != E; ++I) { | |||
451 | OS << '\n'; | |||
452 | PrintFilename(OS, *I, OutputFormat); | |||
453 | OS << ":\n"; | |||
454 | } | |||
455 | } | |||
456 | } | |||
457 | ||||
458 | bool DFGASTReaderListener::visitInputFile(llvm::StringRef Filename, | |||
459 | bool IsSystem, bool IsOverridden, | |||
460 | bool IsExplicitModule) { | |||
461 | assert(!IsSystem || needsSystemInputFileVisitation())(static_cast <bool> (!IsSystem || needsSystemInputFileVisitation ()) ? void (0) : __assert_fail ("!IsSystem || needsSystemInputFileVisitation()" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/DependencyFile.cpp" , 461, __extension__ __PRETTY_FUNCTION__)); | |||
462 | if (IsOverridden || IsExplicitModule) | |||
463 | return true; | |||
464 | ||||
465 | Parent.AddFilename(Filename); | |||
466 | return true; | |||
467 | } | |||
468 | ||||
469 | void DFGASTReaderListener::visitModuleFile(llvm::StringRef Filename, | |||
470 | serialization::ModuleKind Kind) { | |||
471 | if (Parent.includeModuleFiles()) | |||
472 | Parent.AddFilename(Filename); | |||
473 | } |
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 */ |