File: | tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp |
Warning: | line 892, column 3 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===--- PrintPreprocessedOutput.cpp - Implement the -E mode --------------===// | |||
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 simply runs the preprocessor on the input file and prints out the | |||
11 | // result. This is the traditional behavior of the -E option. | |||
12 | // | |||
13 | //===----------------------------------------------------------------------===// | |||
14 | ||||
15 | #include "clang/Frontend/Utils.h" | |||
16 | #include "clang/Basic/CharInfo.h" | |||
17 | #include "clang/Basic/Diagnostic.h" | |||
18 | #include "clang/Basic/SourceManager.h" | |||
19 | #include "clang/Frontend/PreprocessorOutputOptions.h" | |||
20 | #include "clang/Lex/MacroInfo.h" | |||
21 | #include "clang/Lex/PPCallbacks.h" | |||
22 | #include "clang/Lex/Pragma.h" | |||
23 | #include "clang/Lex/Preprocessor.h" | |||
24 | #include "clang/Lex/TokenConcatenation.h" | |||
25 | #include "llvm/ADT/STLExtras.h" | |||
26 | #include "llvm/ADT/SmallString.h" | |||
27 | #include "llvm/ADT/StringRef.h" | |||
28 | #include "llvm/Support/ErrorHandling.h" | |||
29 | #include "llvm/Support/raw_ostream.h" | |||
30 | #include <cstdio> | |||
31 | using namespace clang; | |||
32 | ||||
33 | /// PrintMacroDefinition - Print a macro definition in a form that will be | |||
34 | /// properly accepted back as a definition. | |||
35 | static void PrintMacroDefinition(const IdentifierInfo &II, const MacroInfo &MI, | |||
36 | Preprocessor &PP, raw_ostream &OS) { | |||
37 | OS << "#define " << II.getName(); | |||
38 | ||||
39 | if (MI.isFunctionLike()) { | |||
40 | OS << '('; | |||
41 | if (!MI.param_empty()) { | |||
42 | MacroInfo::param_iterator AI = MI.param_begin(), E = MI.param_end(); | |||
43 | for (; AI+1 != E; ++AI) { | |||
44 | OS << (*AI)->getName(); | |||
45 | OS << ','; | |||
46 | } | |||
47 | ||||
48 | // Last argument. | |||
49 | if ((*AI)->getName() == "__VA_ARGS__") | |||
50 | OS << "..."; | |||
51 | else | |||
52 | OS << (*AI)->getName(); | |||
53 | } | |||
54 | ||||
55 | if (MI.isGNUVarargs()) | |||
56 | OS << "..."; // #define foo(x...) | |||
57 | ||||
58 | OS << ')'; | |||
59 | } | |||
60 | ||||
61 | // GCC always emits a space, even if the macro body is empty. However, do not | |||
62 | // want to emit two spaces if the first token has a leading space. | |||
63 | if (MI.tokens_empty() || !MI.tokens_begin()->hasLeadingSpace()) | |||
64 | OS << ' '; | |||
65 | ||||
66 | SmallString<128> SpellingBuffer; | |||
67 | for (const auto &T : MI.tokens()) { | |||
68 | if (T.hasLeadingSpace()) | |||
69 | OS << ' '; | |||
70 | ||||
71 | OS << PP.getSpelling(T, SpellingBuffer); | |||
72 | } | |||
73 | } | |||
74 | ||||
75 | //===----------------------------------------------------------------------===// | |||
76 | // Preprocessed token printer | |||
77 | //===----------------------------------------------------------------------===// | |||
78 | ||||
79 | namespace { | |||
80 | class PrintPPOutputPPCallbacks : public PPCallbacks { | |||
81 | Preprocessor &PP; | |||
82 | SourceManager &SM; | |||
83 | TokenConcatenation ConcatInfo; | |||
84 | public: | |||
85 | raw_ostream &OS; | |||
86 | private: | |||
87 | unsigned CurLine; | |||
88 | ||||
89 | bool EmittedTokensOnThisLine; | |||
90 | bool EmittedDirectiveOnThisLine; | |||
91 | SrcMgr::CharacteristicKind FileType; | |||
92 | SmallString<512> CurFilename; | |||
93 | bool Initialized; | |||
94 | bool DisableLineMarkers; | |||
95 | bool DumpDefines; | |||
96 | bool DumpIncludeDirectives; | |||
97 | bool UseLineDirectives; | |||
98 | bool IsFirstFileEntered; | |||
99 | public: | |||
100 | PrintPPOutputPPCallbacks(Preprocessor &pp, raw_ostream &os, bool lineMarkers, | |||
101 | bool defines, bool DumpIncludeDirectives, | |||
102 | bool UseLineDirectives) | |||
103 | : PP(pp), SM(PP.getSourceManager()), ConcatInfo(PP), OS(os), | |||
104 | DisableLineMarkers(lineMarkers), DumpDefines(defines), | |||
105 | DumpIncludeDirectives(DumpIncludeDirectives), | |||
106 | UseLineDirectives(UseLineDirectives) { | |||
107 | CurLine = 0; | |||
108 | CurFilename += "<uninit>"; | |||
109 | EmittedTokensOnThisLine = false; | |||
110 | EmittedDirectiveOnThisLine = false; | |||
111 | FileType = SrcMgr::C_User; | |||
112 | Initialized = false; | |||
113 | IsFirstFileEntered = false; | |||
114 | } | |||
115 | ||||
116 | void setEmittedTokensOnThisLine() { EmittedTokensOnThisLine = true; } | |||
117 | bool hasEmittedTokensOnThisLine() const { return EmittedTokensOnThisLine; } | |||
118 | ||||
119 | void setEmittedDirectiveOnThisLine() { EmittedDirectiveOnThisLine = true; } | |||
120 | bool hasEmittedDirectiveOnThisLine() const { | |||
121 | return EmittedDirectiveOnThisLine; | |||
122 | } | |||
123 | ||||
124 | bool startNewLineIfNeeded(bool ShouldUpdateCurrentLine = true); | |||
125 | ||||
126 | void FileChanged(SourceLocation Loc, FileChangeReason Reason, | |||
127 | SrcMgr::CharacteristicKind FileType, | |||
128 | FileID PrevFID) override; | |||
129 | void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, | |||
130 | StringRef FileName, bool IsAngled, | |||
131 | CharSourceRange FilenameRange, const FileEntry *File, | |||
132 | StringRef SearchPath, StringRef RelativePath, | |||
133 | const Module *Imported) override; | |||
134 | void Ident(SourceLocation Loc, StringRef str) override; | |||
135 | void PragmaMessage(SourceLocation Loc, StringRef Namespace, | |||
136 | PragmaMessageKind Kind, StringRef Str) override; | |||
137 | void PragmaDebug(SourceLocation Loc, StringRef DebugType) override; | |||
138 | void PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) override; | |||
139 | void PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) override; | |||
140 | void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, | |||
141 | diag::Severity Map, StringRef Str) override; | |||
142 | void PragmaWarning(SourceLocation Loc, StringRef WarningSpec, | |||
143 | ArrayRef<int> Ids) override; | |||
144 | void PragmaWarningPush(SourceLocation Loc, int Level) override; | |||
145 | void PragmaWarningPop(SourceLocation Loc) override; | |||
146 | void PragmaAssumeNonNullBegin(SourceLocation Loc) override; | |||
147 | void PragmaAssumeNonNullEnd(SourceLocation Loc) override; | |||
148 | ||||
149 | bool HandleFirstTokOnLine(Token &Tok); | |||
150 | ||||
151 | /// Move to the line of the provided source location. This will | |||
152 | /// return true if the output stream required adjustment or if | |||
153 | /// the requested location is on the first line. | |||
154 | bool MoveToLine(SourceLocation Loc) { | |||
155 | PresumedLoc PLoc = SM.getPresumedLoc(Loc); | |||
156 | if (PLoc.isInvalid()) | |||
157 | return false; | |||
158 | return MoveToLine(PLoc.getLine()) || (PLoc.getLine() == 1); | |||
159 | } | |||
160 | bool MoveToLine(unsigned LineNo); | |||
161 | ||||
162 | bool AvoidConcat(const Token &PrevPrevTok, const Token &PrevTok, | |||
163 | const Token &Tok) { | |||
164 | return ConcatInfo.AvoidConcat(PrevPrevTok, PrevTok, Tok); | |||
165 | } | |||
166 | void WriteLineInfo(unsigned LineNo, const char *Extra=nullptr, | |||
167 | unsigned ExtraLen=0); | |||
168 | bool LineMarkersAreDisabled() const { return DisableLineMarkers; } | |||
169 | void HandleNewlinesInToken(const char *TokStr, unsigned Len); | |||
170 | ||||
171 | /// MacroDefined - This hook is called whenever a macro definition is seen. | |||
172 | void MacroDefined(const Token &MacroNameTok, | |||
173 | const MacroDirective *MD) override; | |||
174 | ||||
175 | /// MacroUndefined - This hook is called whenever a macro #undef is seen. | |||
176 | void MacroUndefined(const Token &MacroNameTok, | |||
177 | const MacroDefinition &MD, | |||
178 | const MacroDirective *Undef) override; | |||
179 | ||||
180 | void BeginModule(const Module *M); | |||
181 | void EndModule(const Module *M); | |||
182 | }; | |||
183 | } // end anonymous namespace | |||
184 | ||||
185 | void PrintPPOutputPPCallbacks::WriteLineInfo(unsigned LineNo, | |||
186 | const char *Extra, | |||
187 | unsigned ExtraLen) { | |||
188 | startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false); | |||
189 | ||||
190 | // Emit #line directives or GNU line markers depending on what mode we're in. | |||
191 | if (UseLineDirectives) { | |||
192 | OS << "#line" << ' ' << LineNo << ' ' << '"'; | |||
193 | OS.write_escaped(CurFilename); | |||
194 | OS << '"'; | |||
195 | } else { | |||
196 | OS << '#' << ' ' << LineNo << ' ' << '"'; | |||
197 | OS.write_escaped(CurFilename); | |||
198 | OS << '"'; | |||
199 | ||||
200 | if (ExtraLen) | |||
201 | OS.write(Extra, ExtraLen); | |||
202 | ||||
203 | if (FileType == SrcMgr::C_System) | |||
204 | OS.write(" 3", 2); | |||
205 | else if (FileType == SrcMgr::C_ExternCSystem) | |||
206 | OS.write(" 3 4", 4); | |||
207 | } | |||
208 | OS << '\n'; | |||
209 | } | |||
210 | ||||
211 | /// MoveToLine - Move the output to the source line specified by the location | |||
212 | /// object. We can do this by emitting some number of \n's, or be emitting a | |||
213 | /// #line directive. This returns false if already at the specified line, true | |||
214 | /// if some newlines were emitted. | |||
215 | bool PrintPPOutputPPCallbacks::MoveToLine(unsigned LineNo) { | |||
216 | // If this line is "close enough" to the original line, just print newlines, | |||
217 | // otherwise print a #line directive. | |||
218 | if (LineNo-CurLine <= 8) { | |||
219 | if (LineNo-CurLine == 1) | |||
220 | OS << '\n'; | |||
221 | else if (LineNo == CurLine) | |||
222 | return false; // Spelling line moved, but expansion line didn't. | |||
223 | else { | |||
224 | const char *NewLines = "\n\n\n\n\n\n\n\n"; | |||
225 | OS.write(NewLines, LineNo-CurLine); | |||
226 | } | |||
227 | } else if (!DisableLineMarkers) { | |||
228 | // Emit a #line or line marker. | |||
229 | WriteLineInfo(LineNo, nullptr, 0); | |||
230 | } else { | |||
231 | // Okay, we're in -P mode, which turns off line markers. However, we still | |||
232 | // need to emit a newline between tokens on different lines. | |||
233 | startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false); | |||
234 | } | |||
235 | ||||
236 | CurLine = LineNo; | |||
237 | return true; | |||
238 | } | |||
239 | ||||
240 | bool | |||
241 | PrintPPOutputPPCallbacks::startNewLineIfNeeded(bool ShouldUpdateCurrentLine) { | |||
242 | if (EmittedTokensOnThisLine || EmittedDirectiveOnThisLine) { | |||
243 | OS << '\n'; | |||
244 | EmittedTokensOnThisLine = false; | |||
245 | EmittedDirectiveOnThisLine = false; | |||
246 | if (ShouldUpdateCurrentLine) | |||
247 | ++CurLine; | |||
248 | return true; | |||
249 | } | |||
250 | ||||
251 | return false; | |||
252 | } | |||
253 | ||||
254 | /// FileChanged - Whenever the preprocessor enters or exits a #include file | |||
255 | /// it invokes this handler. Update our conception of the current source | |||
256 | /// position. | |||
257 | void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc, | |||
258 | FileChangeReason Reason, | |||
259 | SrcMgr::CharacteristicKind NewFileType, | |||
260 | FileID PrevFID) { | |||
261 | // Unless we are exiting a #include, make sure to skip ahead to the line the | |||
262 | // #include directive was at. | |||
263 | SourceManager &SourceMgr = SM; | |||
264 | ||||
265 | PresumedLoc UserLoc = SourceMgr.getPresumedLoc(Loc); | |||
266 | if (UserLoc.isInvalid()) | |||
267 | return; | |||
268 | ||||
269 | unsigned NewLine = UserLoc.getLine(); | |||
270 | ||||
271 | if (Reason == PPCallbacks::EnterFile) { | |||
272 | SourceLocation IncludeLoc = UserLoc.getIncludeLoc(); | |||
273 | if (IncludeLoc.isValid()) | |||
274 | MoveToLine(IncludeLoc); | |||
275 | } else if (Reason == PPCallbacks::SystemHeaderPragma) { | |||
276 | // GCC emits the # directive for this directive on the line AFTER the | |||
277 | // directive and emits a bunch of spaces that aren't needed. This is because | |||
278 | // otherwise we will emit a line marker for THIS line, which requires an | |||
279 | // extra blank line after the directive to avoid making all following lines | |||
280 | // off by one. We can do better by simply incrementing NewLine here. | |||
281 | NewLine += 1; | |||
282 | } | |||
283 | ||||
284 | CurLine = NewLine; | |||
285 | ||||
286 | CurFilename.clear(); | |||
287 | CurFilename += UserLoc.getFilename(); | |||
288 | FileType = NewFileType; | |||
289 | ||||
290 | if (DisableLineMarkers) { | |||
291 | startNewLineIfNeeded(/*ShouldUpdateCurrentLine=*/false); | |||
292 | return; | |||
293 | } | |||
294 | ||||
295 | if (!Initialized) { | |||
296 | WriteLineInfo(CurLine); | |||
297 | Initialized = true; | |||
298 | } | |||
299 | ||||
300 | // Do not emit an enter marker for the main file (which we expect is the first | |||
301 | // entered file). This matches gcc, and improves compatibility with some tools | |||
302 | // which track the # line markers as a way to determine when the preprocessed | |||
303 | // output is in the context of the main file. | |||
304 | if (Reason == PPCallbacks::EnterFile && !IsFirstFileEntered) { | |||
305 | IsFirstFileEntered = true; | |||
306 | return; | |||
307 | } | |||
308 | ||||
309 | switch (Reason) { | |||
310 | case PPCallbacks::EnterFile: | |||
311 | WriteLineInfo(CurLine, " 1", 2); | |||
312 | break; | |||
313 | case PPCallbacks::ExitFile: | |||
314 | WriteLineInfo(CurLine, " 2", 2); | |||
315 | break; | |||
316 | case PPCallbacks::SystemHeaderPragma: | |||
317 | case PPCallbacks::RenameFile: | |||
318 | WriteLineInfo(CurLine); | |||
319 | break; | |||
320 | } | |||
321 | } | |||
322 | ||||
323 | void PrintPPOutputPPCallbacks::InclusionDirective(SourceLocation HashLoc, | |||
324 | const Token &IncludeTok, | |||
325 | StringRef FileName, | |||
326 | bool IsAngled, | |||
327 | CharSourceRange FilenameRange, | |||
328 | const FileEntry *File, | |||
329 | StringRef SearchPath, | |||
330 | StringRef RelativePath, | |||
331 | const Module *Imported) { | |||
332 | // In -dI mode, dump #include directives prior to dumping their content or | |||
333 | // interpretation. | |||
334 | if (DumpIncludeDirectives) { | |||
335 | startNewLineIfNeeded(); | |||
336 | MoveToLine(HashLoc); | |||
337 | const std::string TokenText = PP.getSpelling(IncludeTok); | |||
338 | assert(!TokenText.empty())(static_cast <bool> (!TokenText.empty()) ? void (0) : __assert_fail ("!TokenText.empty()", "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp" , 338, __extension__ __PRETTY_FUNCTION__)); | |||
339 | OS << "#" << TokenText << " " | |||
340 | << (IsAngled ? '<' : '"') << FileName << (IsAngled ? '>' : '"') | |||
341 | << " /* clang -E -dI */"; | |||
342 | setEmittedDirectiveOnThisLine(); | |||
343 | startNewLineIfNeeded(); | |||
344 | } | |||
345 | ||||
346 | // When preprocessing, turn implicit imports into module import pragmas. | |||
347 | if (Imported) { | |||
348 | switch (IncludeTok.getIdentifierInfo()->getPPKeywordID()) { | |||
349 | case tok::pp_include: | |||
350 | case tok::pp_import: | |||
351 | case tok::pp_include_next: | |||
352 | startNewLineIfNeeded(); | |||
353 | MoveToLine(HashLoc); | |||
354 | OS << "#pragma clang module import " << Imported->getFullModuleName(true) | |||
355 | << " /* clang -E: implicit import for " | |||
356 | << "#" << PP.getSpelling(IncludeTok) << " " | |||
357 | << (IsAngled ? '<' : '"') << FileName << (IsAngled ? '>' : '"') | |||
358 | << " */"; | |||
359 | // Since we want a newline after the pragma, but not a #<line>, start a | |||
360 | // new line immediately. | |||
361 | EmittedTokensOnThisLine = true; | |||
362 | startNewLineIfNeeded(); | |||
363 | break; | |||
364 | ||||
365 | case tok::pp___include_macros: | |||
366 | // #__include_macros has no effect on a user of a preprocessed source | |||
367 | // file; the only effect is on preprocessing. | |||
368 | // | |||
369 | // FIXME: That's not *quite* true: it causes the module in question to | |||
370 | // be loaded, which can affect downstream diagnostics. | |||
371 | break; | |||
372 | ||||
373 | default: | |||
374 | llvm_unreachable("unknown include directive kind")::llvm::llvm_unreachable_internal("unknown include directive kind" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp" , 374); | |||
375 | break; | |||
376 | } | |||
377 | } | |||
378 | } | |||
379 | ||||
380 | /// Handle entering the scope of a module during a module compilation. | |||
381 | void PrintPPOutputPPCallbacks::BeginModule(const Module *M) { | |||
382 | startNewLineIfNeeded(); | |||
383 | OS << "#pragma clang module begin " << M->getFullModuleName(true); | |||
384 | setEmittedDirectiveOnThisLine(); | |||
385 | } | |||
386 | ||||
387 | /// Handle leaving the scope of a module during a module compilation. | |||
388 | void PrintPPOutputPPCallbacks::EndModule(const Module *M) { | |||
389 | startNewLineIfNeeded(); | |||
390 | OS << "#pragma clang module end /*" << M->getFullModuleName(true) << "*/"; | |||
391 | setEmittedDirectiveOnThisLine(); | |||
392 | } | |||
393 | ||||
394 | /// Ident - Handle #ident directives when read by the preprocessor. | |||
395 | /// | |||
396 | void PrintPPOutputPPCallbacks::Ident(SourceLocation Loc, StringRef S) { | |||
397 | MoveToLine(Loc); | |||
398 | ||||
399 | OS.write("#ident ", strlen("#ident ")); | |||
400 | OS.write(S.begin(), S.size()); | |||
401 | EmittedTokensOnThisLine = true; | |||
402 | } | |||
403 | ||||
404 | /// MacroDefined - This hook is called whenever a macro definition is seen. | |||
405 | void PrintPPOutputPPCallbacks::MacroDefined(const Token &MacroNameTok, | |||
406 | const MacroDirective *MD) { | |||
407 | const MacroInfo *MI = MD->getMacroInfo(); | |||
408 | // Only print out macro definitions in -dD mode. | |||
409 | if (!DumpDefines || | |||
410 | // Ignore __FILE__ etc. | |||
411 | MI->isBuiltinMacro()) return; | |||
412 | ||||
413 | MoveToLine(MI->getDefinitionLoc()); | |||
414 | PrintMacroDefinition(*MacroNameTok.getIdentifierInfo(), *MI, PP, OS); | |||
415 | setEmittedDirectiveOnThisLine(); | |||
416 | } | |||
417 | ||||
418 | void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok, | |||
419 | const MacroDefinition &MD, | |||
420 | const MacroDirective *Undef) { | |||
421 | // Only print out macro definitions in -dD mode. | |||
422 | if (!DumpDefines) return; | |||
423 | ||||
424 | MoveToLine(MacroNameTok.getLocation()); | |||
425 | OS << "#undef " << MacroNameTok.getIdentifierInfo()->getName(); | |||
426 | setEmittedDirectiveOnThisLine(); | |||
427 | } | |||
428 | ||||
429 | static void outputPrintable(raw_ostream &OS, StringRef Str) { | |||
430 | for (unsigned char Char : Str) { | |||
431 | if (isPrintable(Char) && Char != '\\' && Char != '"') | |||
432 | OS << (char)Char; | |||
433 | else // Output anything hard as an octal escape. | |||
434 | OS << '\\' | |||
435 | << (char)('0' + ((Char >> 6) & 7)) | |||
436 | << (char)('0' + ((Char >> 3) & 7)) | |||
437 | << (char)('0' + ((Char >> 0) & 7)); | |||
438 | } | |||
439 | } | |||
440 | ||||
441 | void PrintPPOutputPPCallbacks::PragmaMessage(SourceLocation Loc, | |||
442 | StringRef Namespace, | |||
443 | PragmaMessageKind Kind, | |||
444 | StringRef Str) { | |||
445 | startNewLineIfNeeded(); | |||
446 | MoveToLine(Loc); | |||
447 | OS << "#pragma "; | |||
448 | if (!Namespace.empty()) | |||
449 | OS << Namespace << ' '; | |||
450 | switch (Kind) { | |||
451 | case PMK_Message: | |||
452 | OS << "message(\""; | |||
453 | break; | |||
454 | case PMK_Warning: | |||
455 | OS << "warning \""; | |||
456 | break; | |||
457 | case PMK_Error: | |||
458 | OS << "error \""; | |||
459 | break; | |||
460 | } | |||
461 | ||||
462 | outputPrintable(OS, Str); | |||
463 | OS << '"'; | |||
464 | if (Kind == PMK_Message) | |||
465 | OS << ')'; | |||
466 | setEmittedDirectiveOnThisLine(); | |||
467 | } | |||
468 | ||||
469 | void PrintPPOutputPPCallbacks::PragmaDebug(SourceLocation Loc, | |||
470 | StringRef DebugType) { | |||
471 | startNewLineIfNeeded(); | |||
472 | MoveToLine(Loc); | |||
473 | ||||
474 | OS << "#pragma clang __debug "; | |||
475 | OS << DebugType; | |||
476 | ||||
477 | setEmittedDirectiveOnThisLine(); | |||
478 | } | |||
479 | ||||
480 | void PrintPPOutputPPCallbacks:: | |||
481 | PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) { | |||
482 | startNewLineIfNeeded(); | |||
483 | MoveToLine(Loc); | |||
484 | OS << "#pragma " << Namespace << " diagnostic push"; | |||
485 | setEmittedDirectiveOnThisLine(); | |||
486 | } | |||
487 | ||||
488 | void PrintPPOutputPPCallbacks:: | |||
489 | PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) { | |||
490 | startNewLineIfNeeded(); | |||
491 | MoveToLine(Loc); | |||
492 | OS << "#pragma " << Namespace << " diagnostic pop"; | |||
493 | setEmittedDirectiveOnThisLine(); | |||
494 | } | |||
495 | ||||
496 | void PrintPPOutputPPCallbacks::PragmaDiagnostic(SourceLocation Loc, | |||
497 | StringRef Namespace, | |||
498 | diag::Severity Map, | |||
499 | StringRef Str) { | |||
500 | startNewLineIfNeeded(); | |||
501 | MoveToLine(Loc); | |||
502 | OS << "#pragma " << Namespace << " diagnostic "; | |||
503 | switch (Map) { | |||
504 | case diag::Severity::Remark: | |||
505 | OS << "remark"; | |||
506 | break; | |||
507 | case diag::Severity::Warning: | |||
508 | OS << "warning"; | |||
509 | break; | |||
510 | case diag::Severity::Error: | |||
511 | OS << "error"; | |||
512 | break; | |||
513 | case diag::Severity::Ignored: | |||
514 | OS << "ignored"; | |||
515 | break; | |||
516 | case diag::Severity::Fatal: | |||
517 | OS << "fatal"; | |||
518 | break; | |||
519 | } | |||
520 | OS << " \"" << Str << '"'; | |||
521 | setEmittedDirectiveOnThisLine(); | |||
522 | } | |||
523 | ||||
524 | void PrintPPOutputPPCallbacks::PragmaWarning(SourceLocation Loc, | |||
525 | StringRef WarningSpec, | |||
526 | ArrayRef<int> Ids) { | |||
527 | startNewLineIfNeeded(); | |||
528 | MoveToLine(Loc); | |||
529 | OS << "#pragma warning(" << WarningSpec << ':'; | |||
530 | for (ArrayRef<int>::iterator I = Ids.begin(), E = Ids.end(); I != E; ++I) | |||
531 | OS << ' ' << *I; | |||
532 | OS << ')'; | |||
533 | setEmittedDirectiveOnThisLine(); | |||
534 | } | |||
535 | ||||
536 | void PrintPPOutputPPCallbacks::PragmaWarningPush(SourceLocation Loc, | |||
537 | int Level) { | |||
538 | startNewLineIfNeeded(); | |||
539 | MoveToLine(Loc); | |||
540 | OS << "#pragma warning(push"; | |||
541 | if (Level >= 0) | |||
542 | OS << ", " << Level; | |||
543 | OS << ')'; | |||
544 | setEmittedDirectiveOnThisLine(); | |||
545 | } | |||
546 | ||||
547 | void PrintPPOutputPPCallbacks::PragmaWarningPop(SourceLocation Loc) { | |||
548 | startNewLineIfNeeded(); | |||
549 | MoveToLine(Loc); | |||
550 | OS << "#pragma warning(pop)"; | |||
551 | setEmittedDirectiveOnThisLine(); | |||
552 | } | |||
553 | ||||
554 | void PrintPPOutputPPCallbacks:: | |||
555 | PragmaAssumeNonNullBegin(SourceLocation Loc) { | |||
556 | startNewLineIfNeeded(); | |||
557 | MoveToLine(Loc); | |||
558 | OS << "#pragma clang assume_nonnull begin"; | |||
559 | setEmittedDirectiveOnThisLine(); | |||
560 | } | |||
561 | ||||
562 | void PrintPPOutputPPCallbacks:: | |||
563 | PragmaAssumeNonNullEnd(SourceLocation Loc) { | |||
564 | startNewLineIfNeeded(); | |||
565 | MoveToLine(Loc); | |||
566 | OS << "#pragma clang assume_nonnull end"; | |||
567 | setEmittedDirectiveOnThisLine(); | |||
568 | } | |||
569 | ||||
570 | /// HandleFirstTokOnLine - When emitting a preprocessed file in -E mode, this | |||
571 | /// is called for the first token on each new line. If this really is the start | |||
572 | /// of a new logical line, handle it and return true, otherwise return false. | |||
573 | /// This may not be the start of a logical line because the "start of line" | |||
574 | /// marker is set for spelling lines, not expansion ones. | |||
575 | bool PrintPPOutputPPCallbacks::HandleFirstTokOnLine(Token &Tok) { | |||
576 | // Figure out what line we went to and insert the appropriate number of | |||
577 | // newline characters. | |||
578 | if (!MoveToLine(Tok.getLocation())) | |||
579 | return false; | |||
580 | ||||
581 | // Print out space characters so that the first token on a line is | |||
582 | // indented for easy reading. | |||
583 | unsigned ColNo = SM.getExpansionColumnNumber(Tok.getLocation()); | |||
584 | ||||
585 | // The first token on a line can have a column number of 1, yet still expect | |||
586 | // leading white space, if a macro expansion in column 1 starts with an empty | |||
587 | // macro argument, or an empty nested macro expansion. In this case, move the | |||
588 | // token to column 2. | |||
589 | if (ColNo == 1 && Tok.hasLeadingSpace()) | |||
590 | ColNo = 2; | |||
591 | ||||
592 | // This hack prevents stuff like: | |||
593 | // #define HASH # | |||
594 | // HASH define foo bar | |||
595 | // From having the # character end up at column 1, which makes it so it | |||
596 | // is not handled as a #define next time through the preprocessor if in | |||
597 | // -fpreprocessed mode. | |||
598 | if (ColNo <= 1 && Tok.is(tok::hash)) | |||
599 | OS << ' '; | |||
600 | ||||
601 | // Otherwise, indent the appropriate number of spaces. | |||
602 | for (; ColNo > 1; --ColNo) | |||
603 | OS << ' '; | |||
604 | ||||
605 | return true; | |||
606 | } | |||
607 | ||||
608 | void PrintPPOutputPPCallbacks::HandleNewlinesInToken(const char *TokStr, | |||
609 | unsigned Len) { | |||
610 | unsigned NumNewlines = 0; | |||
611 | for (; Len; --Len, ++TokStr) { | |||
612 | if (*TokStr != '\n' && | |||
613 | *TokStr != '\r') | |||
614 | continue; | |||
615 | ||||
616 | ++NumNewlines; | |||
617 | ||||
618 | // If we have \n\r or \r\n, skip both and count as one line. | |||
619 | if (Len != 1 && | |||
620 | (TokStr[1] == '\n' || TokStr[1] == '\r') && | |||
621 | TokStr[0] != TokStr[1]) { | |||
622 | ++TokStr; | |||
623 | --Len; | |||
624 | } | |||
625 | } | |||
626 | ||||
627 | if (NumNewlines == 0) return; | |||
628 | ||||
629 | CurLine += NumNewlines; | |||
630 | } | |||
631 | ||||
632 | ||||
633 | namespace { | |||
634 | struct UnknownPragmaHandler : public PragmaHandler { | |||
635 | const char *Prefix; | |||
636 | PrintPPOutputPPCallbacks *Callbacks; | |||
637 | ||||
638 | // Set to true if tokens should be expanded | |||
639 | bool ShouldExpandTokens; | |||
640 | ||||
641 | UnknownPragmaHandler(const char *prefix, PrintPPOutputPPCallbacks *callbacks, | |||
642 | bool RequireTokenExpansion) | |||
643 | : Prefix(prefix), Callbacks(callbacks), | |||
644 | ShouldExpandTokens(RequireTokenExpansion) {} | |||
645 | void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, | |||
646 | Token &PragmaTok) override { | |||
647 | // Figure out what line we went to and insert the appropriate number of | |||
648 | // newline characters. | |||
649 | Callbacks->startNewLineIfNeeded(); | |||
650 | Callbacks->MoveToLine(PragmaTok.getLocation()); | |||
651 | Callbacks->OS.write(Prefix, strlen(Prefix)); | |||
652 | ||||
653 | if (ShouldExpandTokens) { | |||
654 | // The first token does not have expanded macros. Expand them, if | |||
655 | // required. | |||
656 | auto Toks = llvm::make_unique<Token[]>(1); | |||
657 | Toks[0] = PragmaTok; | |||
658 | PP.EnterTokenStream(std::move(Toks), /*NumToks=*/1, | |||
659 | /*DisableMacroExpansion=*/false); | |||
660 | PP.Lex(PragmaTok); | |||
661 | } | |||
662 | Token PrevToken; | |||
663 | Token PrevPrevToken; | |||
664 | PrevToken.startToken(); | |||
665 | PrevPrevToken.startToken(); | |||
666 | ||||
667 | // Read and print all of the pragma tokens. | |||
668 | while (PragmaTok.isNot(tok::eod)) { | |||
669 | if (PragmaTok.hasLeadingSpace() || | |||
670 | Callbacks->AvoidConcat(PrevPrevToken, PrevToken, PragmaTok)) | |||
671 | Callbacks->OS << ' '; | |||
672 | std::string TokSpell = PP.getSpelling(PragmaTok); | |||
673 | Callbacks->OS.write(&TokSpell[0], TokSpell.size()); | |||
674 | ||||
675 | PrevPrevToken = PrevToken; | |||
676 | PrevToken = PragmaTok; | |||
677 | ||||
678 | if (ShouldExpandTokens) | |||
679 | PP.Lex(PragmaTok); | |||
680 | else | |||
681 | PP.LexUnexpandedToken(PragmaTok); | |||
682 | } | |||
683 | Callbacks->setEmittedDirectiveOnThisLine(); | |||
684 | } | |||
685 | }; | |||
686 | } // end anonymous namespace | |||
687 | ||||
688 | ||||
689 | static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, | |||
690 | PrintPPOutputPPCallbacks *Callbacks, | |||
691 | raw_ostream &OS) { | |||
692 | bool DropComments = PP.getLangOpts().TraditionalCPP && | |||
693 | !PP.getCommentRetentionState(); | |||
694 | ||||
695 | char Buffer[256]; | |||
696 | Token PrevPrevTok, PrevTok; | |||
697 | PrevPrevTok.startToken(); | |||
698 | PrevTok.startToken(); | |||
699 | while (1) { | |||
700 | if (Callbacks->hasEmittedDirectiveOnThisLine()) { | |||
701 | Callbacks->startNewLineIfNeeded(); | |||
702 | Callbacks->MoveToLine(Tok.getLocation()); | |||
703 | } | |||
704 | ||||
705 | // If this token is at the start of a line, emit newlines if needed. | |||
706 | if (Tok.isAtStartOfLine() && Callbacks->HandleFirstTokOnLine(Tok)) { | |||
707 | // done. | |||
708 | } else if (Tok.hasLeadingSpace() || | |||
709 | // If we haven't emitted a token on this line yet, PrevTok isn't | |||
710 | // useful to look at and no concatenation could happen anyway. | |||
711 | (Callbacks->hasEmittedTokensOnThisLine() && | |||
712 | // Don't print "-" next to "-", it would form "--". | |||
713 | Callbacks->AvoidConcat(PrevPrevTok, PrevTok, Tok))) { | |||
714 | OS << ' '; | |||
715 | } | |||
716 | ||||
717 | if (DropComments && Tok.is(tok::comment)) { | |||
718 | // Skip comments. Normally the preprocessor does not generate | |||
719 | // tok::comment nodes at all when not keeping comments, but under | |||
720 | // -traditional-cpp the lexer keeps /all/ whitespace, including comments. | |||
721 | SourceLocation StartLoc = Tok.getLocation(); | |||
722 | Callbacks->MoveToLine(StartLoc.getLocWithOffset(Tok.getLength())); | |||
723 | } else if (Tok.is(tok::eod)) { | |||
724 | // Don't print end of directive tokens, since they are typically newlines | |||
725 | // that mess up our line tracking. These come from unknown pre-processor | |||
726 | // directives or hash-prefixed comments in standalone assembly files. | |||
727 | PP.Lex(Tok); | |||
728 | continue; | |||
729 | } else if (Tok.is(tok::annot_module_include)) { | |||
730 | // PrintPPOutputPPCallbacks::InclusionDirective handles producing | |||
731 | // appropriate output here. Ignore this token entirely. | |||
732 | PP.Lex(Tok); | |||
733 | continue; | |||
734 | } else if (Tok.is(tok::annot_module_begin)) { | |||
735 | // FIXME: We retrieve this token after the FileChanged callback, and | |||
736 | // retrieve the module_end token before the FileChanged callback, so | |||
737 | // we render this within the file and render the module end outside the | |||
738 | // file, but this is backwards from the token locations: the module_begin | |||
739 | // token is at the include location (outside the file) and the module_end | |||
740 | // token is at the EOF location (within the file). | |||
741 | Callbacks->BeginModule( | |||
742 | reinterpret_cast<Module *>(Tok.getAnnotationValue())); | |||
743 | PP.Lex(Tok); | |||
744 | continue; | |||
745 | } else if (Tok.is(tok::annot_module_end)) { | |||
746 | Callbacks->EndModule( | |||
747 | reinterpret_cast<Module *>(Tok.getAnnotationValue())); | |||
748 | PP.Lex(Tok); | |||
749 | continue; | |||
750 | } else if (IdentifierInfo *II = Tok.getIdentifierInfo()) { | |||
751 | OS << II->getName(); | |||
752 | } else if (Tok.isLiteral() && !Tok.needsCleaning() && | |||
753 | Tok.getLiteralData()) { | |||
754 | OS.write(Tok.getLiteralData(), Tok.getLength()); | |||
755 | } else if (Tok.getLength() < llvm::array_lengthof(Buffer)) { | |||
756 | const char *TokPtr = Buffer; | |||
757 | unsigned Len = PP.getSpelling(Tok, TokPtr); | |||
758 | OS.write(TokPtr, Len); | |||
759 | ||||
760 | // Tokens that can contain embedded newlines need to adjust our current | |||
761 | // line number. | |||
762 | if (Tok.getKind() == tok::comment || Tok.getKind() == tok::unknown) | |||
763 | Callbacks->HandleNewlinesInToken(TokPtr, Len); | |||
764 | } else { | |||
765 | std::string S = PP.getSpelling(Tok); | |||
766 | OS.write(&S[0], S.size()); | |||
767 | ||||
768 | // Tokens that can contain embedded newlines need to adjust our current | |||
769 | // line number. | |||
770 | if (Tok.getKind() == tok::comment || Tok.getKind() == tok::unknown) | |||
771 | Callbacks->HandleNewlinesInToken(&S[0], S.size()); | |||
772 | } | |||
773 | Callbacks->setEmittedTokensOnThisLine(); | |||
774 | ||||
775 | if (Tok.is(tok::eof)) break; | |||
776 | ||||
777 | PrevPrevTok = PrevTok; | |||
778 | PrevTok = Tok; | |||
779 | PP.Lex(Tok); | |||
780 | } | |||
781 | } | |||
782 | ||||
783 | typedef std::pair<const IdentifierInfo *, MacroInfo *> id_macro_pair; | |||
784 | static int MacroIDCompare(const id_macro_pair *LHS, const id_macro_pair *RHS) { | |||
785 | return LHS->first->getName().compare(RHS->first->getName()); | |||
786 | } | |||
787 | ||||
788 | static void DoPrintMacros(Preprocessor &PP, raw_ostream *OS) { | |||
789 | // Ignore unknown pragmas. | |||
790 | PP.IgnorePragmas(); | |||
791 | ||||
792 | // -dM mode just scans and ignores all tokens in the files, then dumps out | |||
793 | // the macro table at the end. | |||
794 | PP.EnterMainSourceFile(); | |||
795 | ||||
796 | Token Tok; | |||
797 | do PP.Lex(Tok); | |||
798 | while (Tok.isNot(tok::eof)); | |||
799 | ||||
800 | SmallVector<id_macro_pair, 128> MacrosByID; | |||
801 | for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end(); | |||
802 | I != E; ++I) { | |||
803 | auto *MD = I->second.getLatest(); | |||
804 | if (MD && MD->isDefined()) | |||
805 | MacrosByID.push_back(id_macro_pair(I->first, MD->getMacroInfo())); | |||
806 | } | |||
807 | llvm::array_pod_sort(MacrosByID.begin(), MacrosByID.end(), MacroIDCompare); | |||
808 | ||||
809 | for (unsigned i = 0, e = MacrosByID.size(); i != e; ++i) { | |||
810 | MacroInfo &MI = *MacrosByID[i].second; | |||
811 | // Ignore computed macros like __LINE__ and friends. | |||
812 | if (MI.isBuiltinMacro()) continue; | |||
813 | ||||
814 | PrintMacroDefinition(*MacrosByID[i].first, MI, PP, *OS); | |||
815 | *OS << '\n'; | |||
816 | } | |||
817 | } | |||
818 | ||||
819 | /// DoPrintPreprocessedInput - This implements -E mode. | |||
820 | /// | |||
821 | void clang::DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS, | |||
822 | const PreprocessorOutputOptions &Opts) { | |||
823 | // Show macros with no output is handled specially. | |||
824 | if (!Opts.ShowCPP) { | |||
| ||||
825 | assert(Opts.ShowMacros && "Not yet implemented!")(static_cast <bool> (Opts.ShowMacros && "Not yet implemented!" ) ? void (0) : __assert_fail ("Opts.ShowMacros && \"Not yet implemented!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/PrintPreprocessedOutput.cpp" , 825, __extension__ __PRETTY_FUNCTION__)); | |||
826 | DoPrintMacros(PP, OS); | |||
827 | return; | |||
828 | } | |||
829 | ||||
830 | // Inform the preprocessor whether we want it to retain comments or not, due | |||
831 | // to -C or -CC. | |||
832 | PP.SetCommentRetentionState(Opts.ShowComments, Opts.ShowMacroComments); | |||
833 | ||||
834 | PrintPPOutputPPCallbacks *Callbacks = new PrintPPOutputPPCallbacks( | |||
835 | PP, *OS, !Opts.ShowLineMarkers, Opts.ShowMacros, | |||
836 | Opts.ShowIncludeDirectives, Opts.UseLineDirectives); | |||
837 | ||||
838 | // Expand macros in pragmas with -fms-extensions. The assumption is that | |||
839 | // the majority of pragmas in such a file will be Microsoft pragmas. | |||
840 | // Remember the handlers we will add so that we can remove them later. | |||
841 | std::unique_ptr<UnknownPragmaHandler> MicrosoftExtHandler( | |||
842 | new UnknownPragmaHandler( | |||
843 | "#pragma", Callbacks, | |||
844 | /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); | |||
845 | ||||
846 | std::unique_ptr<UnknownPragmaHandler> GCCHandler(new UnknownPragmaHandler( | |||
847 | "#pragma GCC", Callbacks, | |||
848 | /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); | |||
849 | ||||
850 | std::unique_ptr<UnknownPragmaHandler> ClangHandler(new UnknownPragmaHandler( | |||
851 | "#pragma clang", Callbacks, | |||
852 | /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); | |||
853 | ||||
854 | PP.AddPragmaHandler(MicrosoftExtHandler.get()); | |||
855 | PP.AddPragmaHandler("GCC", GCCHandler.get()); | |||
856 | PP.AddPragmaHandler("clang", ClangHandler.get()); | |||
857 | ||||
858 | // The tokens after pragma omp need to be expanded. | |||
859 | // | |||
860 | // OpenMP [2.1, Directive format] | |||
861 | // Preprocessing tokens following the #pragma omp are subject to macro | |||
862 | // replacement. | |||
863 | std::unique_ptr<UnknownPragmaHandler> OpenMPHandler( | |||
864 | new UnknownPragmaHandler("#pragma omp", Callbacks, | |||
865 | /*RequireTokenExpansion=*/true)); | |||
866 | PP.AddPragmaHandler("omp", OpenMPHandler.get()); | |||
867 | ||||
868 | PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks)); | |||
869 | ||||
870 | // After we have configured the preprocessor, enter the main file. | |||
871 | PP.EnterMainSourceFile(); | |||
872 | ||||
873 | // Consume all of the tokens that come from the predefines buffer. Those | |||
874 | // should not be emitted into the output and are guaranteed to be at the | |||
875 | // start. | |||
876 | const SourceManager &SourceMgr = PP.getSourceManager(); | |||
877 | Token Tok; | |||
878 | do { | |||
879 | PP.Lex(Tok); | |||
880 | if (Tok.is(tok::eof) || !Tok.getLocation().isFileID()) | |||
881 | break; | |||
882 | ||||
883 | PresumedLoc PLoc = SourceMgr.getPresumedLoc(Tok.getLocation()); | |||
884 | if (PLoc.isInvalid()) | |||
885 | break; | |||
886 | ||||
887 | if (strcmp(PLoc.getFilename(), "<built-in>")) | |||
888 | break; | |||
889 | } while (true); | |||
890 | ||||
891 | // Read all the preprocessed tokens, printing them out to the stream. | |||
892 | PrintPreprocessedTokens(PP, Tok, Callbacks, *OS); | |||
| ||||
893 | *OS << '\n'; | |||
894 | ||||
895 | // Remove the handlers we just added to leave the preprocessor in a sane state | |||
896 | // so that it can be reused (for example by a clang::Parser instance). | |||
897 | PP.RemovePragmaHandler(MicrosoftExtHandler.get()); | |||
898 | PP.RemovePragmaHandler("GCC", GCCHandler.get()); | |||
899 | PP.RemovePragmaHandler("clang", ClangHandler.get()); | |||
900 | PP.RemovePragmaHandler("omp", OpenMPHandler.get()); | |||
901 | } |
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 */ |