File: | tools/clang/tools/libclang/Indexing.cpp |
Warning: | line 381, column 16 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- CIndexHigh.cpp - Higher level API functions ------------------------===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | ||||
10 | #include "CIndexDiagnostic.h" | |||
11 | #include "CIndexer.h" | |||
12 | #include "CLog.h" | |||
13 | #include "CXCursor.h" | |||
14 | #include "CXIndexDataConsumer.h" | |||
15 | #include "CXSourceLocation.h" | |||
16 | #include "CXString.h" | |||
17 | #include "CXTranslationUnit.h" | |||
18 | #include "clang/AST/ASTConsumer.h" | |||
19 | #include "clang/Frontend/ASTUnit.h" | |||
20 | #include "clang/Frontend/CompilerInstance.h" | |||
21 | #include "clang/Frontend/CompilerInvocation.h" | |||
22 | #include "clang/Frontend/FrontendAction.h" | |||
23 | #include "clang/Frontend/Utils.h" | |||
24 | #include "clang/Index/IndexingAction.h" | |||
25 | #include "clang/Lex/HeaderSearch.h" | |||
26 | #include "clang/Lex/PPCallbacks.h" | |||
27 | #include "clang/Lex/PPConditionalDirectiveRecord.h" | |||
28 | #include "clang/Lex/Preprocessor.h" | |||
29 | #include "clang/Lex/PreprocessorOptions.h" | |||
30 | #include "llvm/Support/CrashRecoveryContext.h" | |||
31 | #include "llvm/Support/MemoryBuffer.h" | |||
32 | #include "llvm/Support/Mutex.h" | |||
33 | #include "llvm/Support/MutexGuard.h" | |||
34 | #include <cstdio> | |||
35 | #include <utility> | |||
36 | ||||
37 | using namespace clang; | |||
38 | using namespace clang::index; | |||
39 | using namespace cxtu; | |||
40 | using namespace cxindex; | |||
41 | ||||
42 | namespace { | |||
43 | ||||
44 | //===----------------------------------------------------------------------===// | |||
45 | // Skip Parsed Bodies | |||
46 | //===----------------------------------------------------------------------===// | |||
47 | ||||
48 | /// \brief A "region" in source code identified by the file/offset of the | |||
49 | /// preprocessor conditional directive that it belongs to. | |||
50 | /// Multiple, non-consecutive ranges can be parts of the same region. | |||
51 | /// | |||
52 | /// As an example of different regions separated by preprocessor directives: | |||
53 | /// | |||
54 | /// \code | |||
55 | /// #1 | |||
56 | /// #ifdef BLAH | |||
57 | /// #2 | |||
58 | /// #ifdef CAKE | |||
59 | /// #3 | |||
60 | /// #endif | |||
61 | /// #2 | |||
62 | /// #endif | |||
63 | /// #1 | |||
64 | /// \endcode | |||
65 | /// | |||
66 | /// There are 3 regions, with non-consecutive parts: | |||
67 | /// #1 is identified as the beginning of the file | |||
68 | /// #2 is identified as the location of "#ifdef BLAH" | |||
69 | /// #3 is identified as the location of "#ifdef CAKE" | |||
70 | /// | |||
71 | class PPRegion { | |||
72 | llvm::sys::fs::UniqueID UniqueID; | |||
73 | time_t ModTime; | |||
74 | unsigned Offset; | |||
75 | public: | |||
76 | PPRegion() : UniqueID(0, 0), ModTime(), Offset() {} | |||
77 | PPRegion(llvm::sys::fs::UniqueID UniqueID, unsigned offset, time_t modTime) | |||
78 | : UniqueID(UniqueID), ModTime(modTime), Offset(offset) {} | |||
79 | ||||
80 | const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; } | |||
81 | unsigned getOffset() const { return Offset; } | |||
82 | time_t getModTime() const { return ModTime; } | |||
83 | ||||
84 | bool isInvalid() const { return *this == PPRegion(); } | |||
85 | ||||
86 | friend bool operator==(const PPRegion &lhs, const PPRegion &rhs) { | |||
87 | return lhs.UniqueID == rhs.UniqueID && lhs.Offset == rhs.Offset && | |||
88 | lhs.ModTime == rhs.ModTime; | |||
89 | } | |||
90 | }; | |||
91 | ||||
92 | typedef llvm::DenseSet<PPRegion> PPRegionSetTy; | |||
93 | ||||
94 | } // end anonymous namespace | |||
95 | ||||
96 | namespace llvm { | |||
97 | template <> struct isPodLike<PPRegion> { | |||
98 | static const bool value = true; | |||
99 | }; | |||
100 | ||||
101 | template <> | |||
102 | struct DenseMapInfo<PPRegion> { | |||
103 | static inline PPRegion getEmptyKey() { | |||
104 | return PPRegion(llvm::sys::fs::UniqueID(0, 0), unsigned(-1), 0); | |||
105 | } | |||
106 | static inline PPRegion getTombstoneKey() { | |||
107 | return PPRegion(llvm::sys::fs::UniqueID(0, 0), unsigned(-2), 0); | |||
108 | } | |||
109 | ||||
110 | static unsigned getHashValue(const PPRegion &S) { | |||
111 | llvm::FoldingSetNodeID ID; | |||
112 | const llvm::sys::fs::UniqueID &UniqueID = S.getUniqueID(); | |||
113 | ID.AddInteger(UniqueID.getFile()); | |||
114 | ID.AddInteger(UniqueID.getDevice()); | |||
115 | ID.AddInteger(S.getOffset()); | |||
116 | ID.AddInteger(S.getModTime()); | |||
117 | return ID.ComputeHash(); | |||
118 | } | |||
119 | ||||
120 | static bool isEqual(const PPRegion &LHS, const PPRegion &RHS) { | |||
121 | return LHS == RHS; | |||
122 | } | |||
123 | }; | |||
124 | } | |||
125 | ||||
126 | namespace { | |||
127 | ||||
128 | class SessionSkipBodyData { | |||
129 | llvm::sys::Mutex Mux; | |||
130 | PPRegionSetTy ParsedRegions; | |||
131 | ||||
132 | public: | |||
133 | SessionSkipBodyData() : Mux(/*recursive=*/false) {} | |||
134 | ~SessionSkipBodyData() { | |||
135 | //llvm::errs() << "RegionData: " << Skipped.size() << " - " << Skipped.getMemorySize() << "\n"; | |||
136 | } | |||
137 | ||||
138 | void copyTo(PPRegionSetTy &Set) { | |||
139 | llvm::MutexGuard MG(Mux); | |||
140 | Set = ParsedRegions; | |||
141 | } | |||
142 | ||||
143 | void update(ArrayRef<PPRegion> Regions) { | |||
144 | llvm::MutexGuard MG(Mux); | |||
145 | ParsedRegions.insert(Regions.begin(), Regions.end()); | |||
146 | } | |||
147 | }; | |||
148 | ||||
149 | class TUSkipBodyControl { | |||
150 | SessionSkipBodyData &SessionData; | |||
151 | PPConditionalDirectiveRecord &PPRec; | |||
152 | Preprocessor &PP; | |||
153 | ||||
154 | PPRegionSetTy ParsedRegions; | |||
155 | SmallVector<PPRegion, 32> NewParsedRegions; | |||
156 | PPRegion LastRegion; | |||
157 | bool LastIsParsed; | |||
158 | ||||
159 | public: | |||
160 | TUSkipBodyControl(SessionSkipBodyData &sessionData, | |||
161 | PPConditionalDirectiveRecord &ppRec, | |||
162 | Preprocessor &pp) | |||
163 | : SessionData(sessionData), PPRec(ppRec), PP(pp) { | |||
164 | SessionData.copyTo(ParsedRegions); | |||
165 | } | |||
166 | ||||
167 | bool isParsed(SourceLocation Loc, FileID FID, const FileEntry *FE) { | |||
168 | PPRegion region = getRegion(Loc, FID, FE); | |||
169 | if (region.isInvalid()) | |||
170 | return false; | |||
171 | ||||
172 | // Check common case, consecutive functions in the same region. | |||
173 | if (LastRegion == region) | |||
174 | return LastIsParsed; | |||
175 | ||||
176 | LastRegion = region; | |||
177 | LastIsParsed = ParsedRegions.count(region); | |||
178 | if (!LastIsParsed) | |||
179 | NewParsedRegions.push_back(region); | |||
180 | return LastIsParsed; | |||
181 | } | |||
182 | ||||
183 | void finished() { | |||
184 | SessionData.update(NewParsedRegions); | |||
185 | } | |||
186 | ||||
187 | private: | |||
188 | PPRegion getRegion(SourceLocation Loc, FileID FID, const FileEntry *FE) { | |||
189 | SourceLocation RegionLoc = PPRec.findConditionalDirectiveRegionLoc(Loc); | |||
190 | if (RegionLoc.isInvalid()) { | |||
191 | if (isParsedOnceInclude(FE)) { | |||
192 | const llvm::sys::fs::UniqueID &ID = FE->getUniqueID(); | |||
193 | return PPRegion(ID, 0, FE->getModificationTime()); | |||
194 | } | |||
195 | return PPRegion(); | |||
196 | } | |||
197 | ||||
198 | const SourceManager &SM = PPRec.getSourceManager(); | |||
199 | assert(RegionLoc.isFileID())(static_cast <bool> (RegionLoc.isFileID()) ? void (0) : __assert_fail ("RegionLoc.isFileID()", "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/tools/libclang/Indexing.cpp" , 199, __extension__ __PRETTY_FUNCTION__)); | |||
200 | FileID RegionFID; | |||
201 | unsigned RegionOffset; | |||
202 | std::tie(RegionFID, RegionOffset) = SM.getDecomposedLoc(RegionLoc); | |||
203 | ||||
204 | if (RegionFID != FID) { | |||
205 | if (isParsedOnceInclude(FE)) { | |||
206 | const llvm::sys::fs::UniqueID &ID = FE->getUniqueID(); | |||
207 | return PPRegion(ID, 0, FE->getModificationTime()); | |||
208 | } | |||
209 | return PPRegion(); | |||
210 | } | |||
211 | ||||
212 | const llvm::sys::fs::UniqueID &ID = FE->getUniqueID(); | |||
213 | return PPRegion(ID, RegionOffset, FE->getModificationTime()); | |||
214 | } | |||
215 | ||||
216 | bool isParsedOnceInclude(const FileEntry *FE) { | |||
217 | return PP.getHeaderSearchInfo().isFileMultipleIncludeGuarded(FE); | |||
218 | } | |||
219 | }; | |||
220 | ||||
221 | //===----------------------------------------------------------------------===// | |||
222 | // IndexPPCallbacks | |||
223 | //===----------------------------------------------------------------------===// | |||
224 | ||||
225 | class IndexPPCallbacks : public PPCallbacks { | |||
226 | Preprocessor &PP; | |||
227 | CXIndexDataConsumer &DataConsumer; | |||
228 | bool IsMainFileEntered; | |||
229 | ||||
230 | public: | |||
231 | IndexPPCallbacks(Preprocessor &PP, CXIndexDataConsumer &dataConsumer) | |||
232 | : PP(PP), DataConsumer(dataConsumer), IsMainFileEntered(false) { } | |||
233 | ||||
234 | void FileChanged(SourceLocation Loc, FileChangeReason Reason, | |||
235 | SrcMgr::CharacteristicKind FileType, FileID PrevFID) override { | |||
236 | if (IsMainFileEntered) | |||
237 | return; | |||
238 | ||||
239 | SourceManager &SM = PP.getSourceManager(); | |||
240 | SourceLocation MainFileLoc = SM.getLocForStartOfFile(SM.getMainFileID()); | |||
241 | ||||
242 | if (Loc == MainFileLoc && Reason == PPCallbacks::EnterFile) { | |||
243 | IsMainFileEntered = true; | |||
244 | DataConsumer.enteredMainFile(SM.getFileEntryForID(SM.getMainFileID())); | |||
245 | } | |||
246 | } | |||
247 | ||||
248 | void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, | |||
249 | StringRef FileName, bool IsAngled, | |||
250 | CharSourceRange FilenameRange, const FileEntry *File, | |||
251 | StringRef SearchPath, StringRef RelativePath, | |||
252 | const Module *Imported) override { | |||
253 | bool isImport = (IncludeTok.is(tok::identifier) && | |||
254 | IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import); | |||
255 | DataConsumer.ppIncludedFile(HashLoc, FileName, File, isImport, IsAngled, | |||
256 | Imported); | |||
257 | } | |||
258 | ||||
259 | /// MacroDefined - This hook is called whenever a macro definition is seen. | |||
260 | void MacroDefined(const Token &Id, const MacroDirective *MD) override {} | |||
261 | ||||
262 | /// MacroUndefined - This hook is called whenever a macro #undef is seen. | |||
263 | /// MI is released immediately following this callback. | |||
264 | void MacroUndefined(const Token &MacroNameTok, | |||
265 | const MacroDefinition &MD, | |||
266 | const MacroDirective *UD) override {} | |||
267 | ||||
268 | /// MacroExpands - This is called by when a macro invocation is found. | |||
269 | void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD, | |||
270 | SourceRange Range, const MacroArgs *Args) override {} | |||
271 | ||||
272 | /// SourceRangeSkipped - This hook is called when a source range is skipped. | |||
273 | /// \param Range The SourceRange that was skipped. The range begins at the | |||
274 | /// #if/#else directive and ends after the #endif/#else directive. | |||
275 | void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override { | |||
276 | } | |||
277 | }; | |||
278 | ||||
279 | //===----------------------------------------------------------------------===// | |||
280 | // IndexingConsumer | |||
281 | //===----------------------------------------------------------------------===// | |||
282 | ||||
283 | class IndexingConsumer : public ASTConsumer { | |||
284 | CXIndexDataConsumer &DataConsumer; | |||
285 | TUSkipBodyControl *SKCtrl; | |||
286 | ||||
287 | public: | |||
288 | IndexingConsumer(CXIndexDataConsumer &dataConsumer, TUSkipBodyControl *skCtrl) | |||
289 | : DataConsumer(dataConsumer), SKCtrl(skCtrl) { } | |||
290 | ||||
291 | // ASTConsumer Implementation | |||
292 | ||||
293 | void Initialize(ASTContext &Context) override { | |||
294 | DataConsumer.setASTContext(Context); | |||
295 | DataConsumer.startedTranslationUnit(); | |||
296 | } | |||
297 | ||||
298 | void HandleTranslationUnit(ASTContext &Ctx) override { | |||
299 | if (SKCtrl) | |||
300 | SKCtrl->finished(); | |||
301 | } | |||
302 | ||||
303 | bool HandleTopLevelDecl(DeclGroupRef DG) override { | |||
304 | return !DataConsumer.shouldAbort(); | |||
305 | } | |||
306 | ||||
307 | bool shouldSkipFunctionBody(Decl *D) override { | |||
308 | if (!SKCtrl) { | |||
309 | // Always skip bodies. | |||
310 | return true; | |||
311 | } | |||
312 | ||||
313 | const SourceManager &SM = DataConsumer.getASTContext().getSourceManager(); | |||
314 | SourceLocation Loc = D->getLocation(); | |||
315 | if (Loc.isMacroID()) | |||
316 | return false; | |||
317 | if (SM.isInSystemHeader(Loc)) | |||
318 | return true; // always skip bodies from system headers. | |||
319 | ||||
320 | FileID FID; | |||
321 | unsigned Offset; | |||
322 | std::tie(FID, Offset) = SM.getDecomposedLoc(Loc); | |||
323 | // Don't skip bodies from main files; this may be revisited. | |||
324 | if (SM.getMainFileID() == FID) | |||
325 | return false; | |||
326 | const FileEntry *FE = SM.getFileEntryForID(FID); | |||
327 | if (!FE) | |||
328 | return false; | |||
329 | ||||
330 | return SKCtrl->isParsed(Loc, FID, FE); | |||
331 | } | |||
332 | }; | |||
333 | ||||
334 | //===----------------------------------------------------------------------===// | |||
335 | // CaptureDiagnosticConsumer | |||
336 | //===----------------------------------------------------------------------===// | |||
337 | ||||
338 | class CaptureDiagnosticConsumer : public DiagnosticConsumer { | |||
339 | SmallVector<StoredDiagnostic, 4> Errors; | |||
340 | public: | |||
341 | ||||
342 | void HandleDiagnostic(DiagnosticsEngine::Level level, | |||
343 | const Diagnostic &Info) override { | |||
344 | if (level >= DiagnosticsEngine::Error) | |||
345 | Errors.push_back(StoredDiagnostic(level, Info)); | |||
346 | } | |||
347 | }; | |||
348 | ||||
349 | //===----------------------------------------------------------------------===// | |||
350 | // IndexingFrontendAction | |||
351 | //===----------------------------------------------------------------------===// | |||
352 | ||||
353 | class IndexingFrontendAction : public ASTFrontendAction { | |||
354 | std::shared_ptr<CXIndexDataConsumer> DataConsumer; | |||
355 | ||||
356 | SessionSkipBodyData *SKData; | |||
357 | std::unique_ptr<TUSkipBodyControl> SKCtrl; | |||
358 | ||||
359 | public: | |||
360 | IndexingFrontendAction(std::shared_ptr<CXIndexDataConsumer> dataConsumer, | |||
361 | SessionSkipBodyData *skData) | |||
362 | : DataConsumer(std::move(dataConsumer)), SKData(skData) {} | |||
363 | ||||
364 | std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, | |||
365 | StringRef InFile) override { | |||
366 | PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); | |||
367 | ||||
368 | if (!PPOpts.ImplicitPCHInclude.empty()) { | |||
| ||||
369 | DataConsumer->importedPCH( | |||
370 | CI.getFileManager().getFile(PPOpts.ImplicitPCHInclude)); | |||
371 | } | |||
372 | ||||
373 | DataConsumer->setASTContext(CI.getASTContext()); | |||
374 | Preprocessor &PP = CI.getPreprocessor(); | |||
375 | PP.addPPCallbacks(llvm::make_unique<IndexPPCallbacks>(PP, *DataConsumer)); | |||
376 | DataConsumer->setPreprocessor(CI.getPreprocessorPtr()); | |||
377 | ||||
378 | if (SKData) { | |||
379 | auto *PPRec = new PPConditionalDirectiveRecord(PP.getSourceManager()); | |||
380 | PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec)); | |||
381 | SKCtrl = llvm::make_unique<TUSkipBodyControl>(*SKData, *PPRec, PP); | |||
| ||||
382 | } | |||
383 | ||||
384 | return llvm::make_unique<IndexingConsumer>(*DataConsumer, SKCtrl.get()); | |||
385 | } | |||
386 | ||||
387 | TranslationUnitKind getTranslationUnitKind() override { | |||
388 | if (DataConsumer->shouldIndexImplicitTemplateInsts()) | |||
389 | return TU_Complete; | |||
390 | else | |||
391 | return TU_Prefix; | |||
392 | } | |||
393 | bool hasCodeCompletionSupport() const override { return false; } | |||
394 | }; | |||
395 | ||||
396 | //===----------------------------------------------------------------------===// | |||
397 | // clang_indexSourceFileUnit Implementation | |||
398 | //===----------------------------------------------------------------------===// | |||
399 | ||||
400 | static IndexingOptions getIndexingOptionsFromCXOptions(unsigned index_options) { | |||
401 | IndexingOptions IdxOpts; | |||
402 | if (index_options & CXIndexOpt_IndexFunctionLocalSymbols) | |||
403 | IdxOpts.IndexFunctionLocals = true; | |||
404 | return IdxOpts; | |||
405 | } | |||
406 | ||||
407 | struct IndexSessionData { | |||
408 | CXIndex CIdx; | |||
409 | std::unique_ptr<SessionSkipBodyData> SkipBodyData; | |||
410 | ||||
411 | explicit IndexSessionData(CXIndex cIdx) | |||
412 | : CIdx(cIdx), SkipBodyData(new SessionSkipBodyData) {} | |||
413 | }; | |||
414 | ||||
415 | } // anonymous namespace | |||
416 | ||||
417 | static CXErrorCode clang_indexSourceFile_Impl( | |||
418 | CXIndexAction cxIdxAction, CXClientData client_data, | |||
419 | IndexerCallbacks *client_index_callbacks, unsigned index_callbacks_size, | |||
420 | unsigned index_options, const char *source_filename, | |||
421 | const char *const *command_line_args, int num_command_line_args, | |||
422 | ArrayRef<CXUnsavedFile> unsaved_files, CXTranslationUnit *out_TU, | |||
423 | unsigned TU_options) { | |||
424 | if (out_TU) | |||
425 | *out_TU = nullptr; | |||
426 | bool requestedToGetTU = (out_TU != nullptr); | |||
427 | ||||
428 | if (!cxIdxAction) { | |||
429 | return CXError_InvalidArguments; | |||
430 | } | |||
431 | if (!client_index_callbacks || index_callbacks_size == 0) { | |||
432 | return CXError_InvalidArguments; | |||
433 | } | |||
434 | ||||
435 | IndexerCallbacks CB; | |||
436 | memset(&CB, 0, sizeof(CB)); | |||
437 | unsigned ClientCBSize = index_callbacks_size < sizeof(CB) | |||
438 | ? index_callbacks_size : sizeof(CB); | |||
439 | memcpy(&CB, client_index_callbacks, ClientCBSize); | |||
440 | ||||
441 | IndexSessionData *IdxSession = static_cast<IndexSessionData *>(cxIdxAction); | |||
442 | CIndexer *CXXIdx = static_cast<CIndexer *>(IdxSession->CIdx); | |||
443 | ||||
444 | if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing)) | |||
445 | setThreadBackgroundPriority(); | |||
446 | ||||
447 | bool CaptureDiagnostics = !Logger::isLoggingEnabled(); | |||
448 | ||||
449 | CaptureDiagnosticConsumer *CaptureDiag = nullptr; | |||
450 | if (CaptureDiagnostics) | |||
451 | CaptureDiag = new CaptureDiagnosticConsumer(); | |||
452 | ||||
453 | // Configure the diagnostics. | |||
454 | IntrusiveRefCntPtr<DiagnosticsEngine> | |||
455 | Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions, | |||
456 | CaptureDiag, | |||
457 | /*ShouldOwnClient=*/true)); | |||
458 | ||||
459 | // Recover resources if we crash before exiting this function. | |||
460 | llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine, | |||
461 | llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> > | |||
462 | DiagCleanup(Diags.get()); | |||
463 | ||||
464 | std::unique_ptr<std::vector<const char *>> Args( | |||
465 | new std::vector<const char *>()); | |||
466 | ||||
467 | // Recover resources if we crash before exiting this method. | |||
468 | llvm::CrashRecoveryContextCleanupRegistrar<std::vector<const char*> > | |||
469 | ArgsCleanup(Args.get()); | |||
470 | ||||
471 | Args->insert(Args->end(), command_line_args, | |||
472 | command_line_args + num_command_line_args); | |||
473 | ||||
474 | // The 'source_filename' argument is optional. If the caller does not | |||
475 | // specify it then it is assumed that the source file is specified | |||
476 | // in the actual argument list. | |||
477 | // Put the source file after command_line_args otherwise if '-x' flag is | |||
478 | // present it will be unused. | |||
479 | if (source_filename) | |||
480 | Args->push_back(source_filename); | |||
481 | ||||
482 | std::shared_ptr<CompilerInvocation> CInvok = | |||
483 | createInvocationFromCommandLine(*Args, Diags); | |||
484 | ||||
485 | if (!CInvok) | |||
486 | return CXError_Failure; | |||
487 | ||||
488 | // Recover resources if we crash before exiting this function. | |||
489 | llvm::CrashRecoveryContextCleanupRegistrar< | |||
490 | std::shared_ptr<CompilerInvocation>, | |||
491 | llvm::CrashRecoveryContextDestructorCleanup< | |||
492 | std::shared_ptr<CompilerInvocation>>> | |||
493 | CInvokCleanup(&CInvok); | |||
494 | ||||
495 | if (CInvok->getFrontendOpts().Inputs.empty()) | |||
496 | return CXError_Failure; | |||
497 | ||||
498 | typedef SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 8> MemBufferOwner; | |||
499 | std::unique_ptr<MemBufferOwner> BufOwner(new MemBufferOwner); | |||
500 | ||||
501 | // Recover resources if we crash before exiting this method. | |||
502 | llvm::CrashRecoveryContextCleanupRegistrar<MemBufferOwner> BufOwnerCleanup( | |||
503 | BufOwner.get()); | |||
504 | ||||
505 | for (auto &UF : unsaved_files) { | |||
506 | std::unique_ptr<llvm::MemoryBuffer> MB = | |||
507 | llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename); | |||
508 | CInvok->getPreprocessorOpts().addRemappedFile(UF.Filename, MB.get()); | |||
509 | BufOwner->push_back(std::move(MB)); | |||
510 | } | |||
511 | ||||
512 | // Since libclang is primarily used by batch tools dealing with | |||
513 | // (often very broken) source code, where spell-checking can have a | |||
514 | // significant negative impact on performance (particularly when | |||
515 | // precompiled headers are involved), we disable it. | |||
516 | CInvok->getLangOpts()->SpellChecking = false; | |||
517 | ||||
518 | if (index_options & CXIndexOpt_SuppressWarnings) | |||
519 | CInvok->getDiagnosticOpts().IgnoreWarnings = true; | |||
520 | ||||
521 | // Make sure to use the raw module format. | |||
522 | CInvok->getHeaderSearchOpts().ModuleFormat = | |||
523 | CXXIdx->getPCHContainerOperations()->getRawReader().getFormat(); | |||
524 | ||||
525 | auto Unit = ASTUnit::create(CInvok, Diags, CaptureDiagnostics, | |||
526 | /*UserFilesAreVolatile=*/true); | |||
527 | if (!Unit) | |||
528 | return CXError_InvalidArguments; | |||
529 | ||||
530 | auto *UPtr = Unit.get(); | |||
531 | std::unique_ptr<CXTUOwner> CXTU( | |||
532 | new CXTUOwner(MakeCXTranslationUnit(CXXIdx, std::move(Unit)))); | |||
533 | ||||
534 | // Recover resources if we crash before exiting this method. | |||
535 | llvm::CrashRecoveryContextCleanupRegistrar<CXTUOwner> | |||
536 | CXTUCleanup(CXTU.get()); | |||
537 | ||||
538 | // Enable the skip-parsed-bodies optimization only for C++; this may be | |||
539 | // revisited. | |||
540 | bool SkipBodies = (index_options & CXIndexOpt_SkipParsedBodiesInSession) && | |||
541 | CInvok->getLangOpts()->CPlusPlus; | |||
542 | if (SkipBodies) | |||
543 | CInvok->getFrontendOpts().SkipFunctionBodies = true; | |||
544 | ||||
545 | auto DataConsumer = | |||
546 | std::make_shared<CXIndexDataConsumer>(client_data, CB, index_options, | |||
547 | CXTU->getTU()); | |||
548 | auto InterAction = llvm::make_unique<IndexingFrontendAction>(DataConsumer, | |||
549 | SkipBodies ? IdxSession->SkipBodyData.get() : nullptr); | |||
550 | std::unique_ptr<FrontendAction> IndexAction; | |||
551 | IndexAction = createIndexingAction(DataConsumer, | |||
552 | getIndexingOptionsFromCXOptions(index_options), | |||
553 | std::move(InterAction)); | |||
554 | ||||
555 | // Recover resources if we crash before exiting this method. | |||
556 | llvm::CrashRecoveryContextCleanupRegistrar<FrontendAction> | |||
557 | IndexActionCleanup(IndexAction.get()); | |||
558 | ||||
559 | bool Persistent = requestedToGetTU; | |||
560 | bool OnlyLocalDecls = false; | |||
561 | bool PrecompilePreamble = false; | |||
562 | bool CreatePreambleOnFirstParse = false; | |||
563 | bool CacheCodeCompletionResults = false; | |||
564 | PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts(); | |||
565 | PPOpts.AllowPCHWithCompilerErrors = true; | |||
566 | ||||
567 | if (requestedToGetTU) { | |||
568 | OnlyLocalDecls = CXXIdx->getOnlyLocalDecls(); | |||
569 | PrecompilePreamble = TU_options & CXTranslationUnit_PrecompiledPreamble; | |||
570 | CreatePreambleOnFirstParse = | |||
571 | TU_options & CXTranslationUnit_CreatePreambleOnFirstParse; | |||
572 | // FIXME: Add a flag for modules. | |||
573 | CacheCodeCompletionResults | |||
574 | = TU_options & CXTranslationUnit_CacheCompletionResults; | |||
575 | } | |||
576 | ||||
577 | if (TU_options & CXTranslationUnit_DetailedPreprocessingRecord) { | |||
578 | PPOpts.DetailedRecord = true; | |||
579 | } | |||
580 | ||||
581 | if (!requestedToGetTU && !CInvok->getLangOpts()->Modules) | |||
582 | PPOpts.DetailedRecord = false; | |||
583 | ||||
584 | // Unless the user specified that they want the preamble on the first parse | |||
585 | // set it up to be created on the first reparse. This makes the first parse | |||
586 | // faster, trading for a slower (first) reparse. | |||
587 | unsigned PrecompilePreambleAfterNParses = | |||
588 | !PrecompilePreamble ? 0 : 2 - CreatePreambleOnFirstParse; | |||
589 | DiagnosticErrorTrap DiagTrap(*Diags); | |||
590 | bool Success = ASTUnit::LoadFromCompilerInvocationAction( | |||
591 | std::move(CInvok), CXXIdx->getPCHContainerOperations(), Diags, | |||
592 | IndexAction.get(), UPtr, Persistent, CXXIdx->getClangResourcesPath(), | |||
593 | OnlyLocalDecls, CaptureDiagnostics, PrecompilePreambleAfterNParses, | |||
594 | CacheCodeCompletionResults, | |||
595 | /*IncludeBriefCommentsInCodeCompletion=*/false, | |||
596 | /*UserFilesAreVolatile=*/true); | |||
597 | if (DiagTrap.hasErrorOccurred() && CXXIdx->getDisplayDiagnostics()) | |||
598 | printDiagsToStderr(UPtr); | |||
599 | ||||
600 | if (isASTReadError(UPtr)) | |||
601 | return CXError_ASTReadError; | |||
602 | ||||
603 | if (!Success) | |||
604 | return CXError_Failure; | |||
605 | ||||
606 | if (out_TU) | |||
607 | *out_TU = CXTU->takeTU(); | |||
608 | ||||
609 | return CXError_Success; | |||
610 | } | |||
611 | ||||
612 | //===----------------------------------------------------------------------===// | |||
613 | // clang_indexTranslationUnit Implementation | |||
614 | //===----------------------------------------------------------------------===// | |||
615 | ||||
616 | static void indexPreprocessingRecord(ASTUnit &Unit, CXIndexDataConsumer &IdxCtx) { | |||
617 | Preprocessor &PP = Unit.getPreprocessor(); | |||
618 | if (!PP.getPreprocessingRecord()) | |||
619 | return; | |||
620 | ||||
621 | // FIXME: Only deserialize inclusion directives. | |||
622 | ||||
623 | bool isModuleFile = Unit.isModuleFile(); | |||
624 | for (PreprocessedEntity *PPE : Unit.getLocalPreprocessingEntities()) { | |||
625 | if (InclusionDirective *ID = dyn_cast<InclusionDirective>(PPE)) { | |||
626 | SourceLocation Loc = ID->getSourceRange().getBegin(); | |||
627 | // Modules have synthetic main files as input, give an invalid location | |||
628 | // if the location points to such a file. | |||
629 | if (isModuleFile && Unit.isInMainFileID(Loc)) | |||
630 | Loc = SourceLocation(); | |||
631 | IdxCtx.ppIncludedFile(Loc, ID->getFileName(), | |||
632 | ID->getFile(), | |||
633 | ID->getKind() == InclusionDirective::Import, | |||
634 | !ID->wasInQuotes(), ID->importedModule()); | |||
635 | } | |||
636 | } | |||
637 | } | |||
638 | ||||
639 | static CXErrorCode clang_indexTranslationUnit_Impl( | |||
640 | CXIndexAction idxAction, CXClientData client_data, | |||
641 | IndexerCallbacks *client_index_callbacks, unsigned index_callbacks_size, | |||
642 | unsigned index_options, CXTranslationUnit TU) { | |||
643 | // Check arguments. | |||
644 | if (isNotUsableTU(TU)) { | |||
645 | LOG_BAD_TU(TU)do { if (clang::cxindex::LogRef Log = clang::cxindex::Logger:: make(__func__)) { *Log << "called with a bad TU: " << TU; } } while(false); | |||
646 | return CXError_InvalidArguments; | |||
647 | } | |||
648 | if (!client_index_callbacks || index_callbacks_size == 0) { | |||
649 | return CXError_InvalidArguments; | |||
650 | } | |||
651 | ||||
652 | CIndexer *CXXIdx = TU->CIdx; | |||
653 | if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing)) | |||
654 | setThreadBackgroundPriority(); | |||
655 | ||||
656 | IndexerCallbacks CB; | |||
657 | memset(&CB, 0, sizeof(CB)); | |||
658 | unsigned ClientCBSize = index_callbacks_size < sizeof(CB) | |||
659 | ? index_callbacks_size : sizeof(CB); | |||
660 | memcpy(&CB, client_index_callbacks, ClientCBSize); | |||
661 | ||||
662 | auto DataConsumer = std::make_shared<CXIndexDataConsumer>(client_data, CB, | |||
663 | index_options, TU); | |||
664 | ||||
665 | ASTUnit *Unit = cxtu::getASTUnit(TU); | |||
666 | if (!Unit) | |||
667 | return CXError_Failure; | |||
668 | ||||
669 | ASTUnit::ConcurrencyCheck Check(*Unit); | |||
670 | ||||
671 | if (const FileEntry *PCHFile = Unit->getPCHFile()) | |||
672 | DataConsumer->importedPCH(PCHFile); | |||
673 | ||||
674 | FileManager &FileMgr = Unit->getFileManager(); | |||
675 | ||||
676 | if (Unit->getOriginalSourceFileName().empty()) | |||
677 | DataConsumer->enteredMainFile(nullptr); | |||
678 | else | |||
679 | DataConsumer->enteredMainFile(FileMgr.getFile(Unit->getOriginalSourceFileName())); | |||
680 | ||||
681 | DataConsumer->setASTContext(Unit->getASTContext()); | |||
682 | DataConsumer->startedTranslationUnit(); | |||
683 | ||||
684 | indexPreprocessingRecord(*Unit, *DataConsumer); | |||
685 | indexASTUnit(*Unit, DataConsumer, getIndexingOptionsFromCXOptions(index_options)); | |||
686 | DataConsumer->indexDiagnostics(); | |||
687 | ||||
688 | return CXError_Success; | |||
689 | } | |||
690 | ||||
691 | //===----------------------------------------------------------------------===// | |||
692 | // libclang public APIs. | |||
693 | //===----------------------------------------------------------------------===// | |||
694 | ||||
695 | int clang_index_isEntityObjCContainerKind(CXIdxEntityKind K) { | |||
696 | return CXIdxEntity_ObjCClass <= K && K <= CXIdxEntity_ObjCCategory; | |||
697 | } | |||
698 | ||||
699 | const CXIdxObjCContainerDeclInfo * | |||
700 | clang_index_getObjCContainerDeclInfo(const CXIdxDeclInfo *DInfo) { | |||
701 | if (!DInfo) | |||
702 | return nullptr; | |||
703 | ||||
704 | const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); | |||
705 | if (const ObjCContainerDeclInfo * | |||
706 | ContInfo = dyn_cast<ObjCContainerDeclInfo>(DI)) | |||
707 | return &ContInfo->ObjCContDeclInfo; | |||
708 | ||||
709 | return nullptr; | |||
710 | } | |||
711 | ||||
712 | const CXIdxObjCInterfaceDeclInfo * | |||
713 | clang_index_getObjCInterfaceDeclInfo(const CXIdxDeclInfo *DInfo) { | |||
714 | if (!DInfo) | |||
715 | return nullptr; | |||
716 | ||||
717 | const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); | |||
718 | if (const ObjCInterfaceDeclInfo * | |||
719 | InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI)) | |||
720 | return &InterInfo->ObjCInterDeclInfo; | |||
721 | ||||
722 | return nullptr; | |||
723 | } | |||
724 | ||||
725 | const CXIdxObjCCategoryDeclInfo * | |||
726 | clang_index_getObjCCategoryDeclInfo(const CXIdxDeclInfo *DInfo){ | |||
727 | if (!DInfo) | |||
728 | return nullptr; | |||
729 | ||||
730 | const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); | |||
731 | if (const ObjCCategoryDeclInfo * | |||
732 | CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI)) | |||
733 | return &CatInfo->ObjCCatDeclInfo; | |||
734 | ||||
735 | return nullptr; | |||
736 | } | |||
737 | ||||
738 | const CXIdxObjCProtocolRefListInfo * | |||
739 | clang_index_getObjCProtocolRefListInfo(const CXIdxDeclInfo *DInfo) { | |||
740 | if (!DInfo) | |||
741 | return nullptr; | |||
742 | ||||
743 | const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); | |||
744 | ||||
745 | if (const ObjCInterfaceDeclInfo * | |||
746 | InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI)) | |||
747 | return InterInfo->ObjCInterDeclInfo.protocols; | |||
748 | ||||
749 | if (const ObjCProtocolDeclInfo * | |||
750 | ProtInfo = dyn_cast<ObjCProtocolDeclInfo>(DI)) | |||
751 | return &ProtInfo->ObjCProtoRefListInfo; | |||
752 | ||||
753 | if (const ObjCCategoryDeclInfo *CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI)) | |||
754 | return CatInfo->ObjCCatDeclInfo.protocols; | |||
755 | ||||
756 | return nullptr; | |||
757 | } | |||
758 | ||||
759 | const CXIdxObjCPropertyDeclInfo * | |||
760 | clang_index_getObjCPropertyDeclInfo(const CXIdxDeclInfo *DInfo) { | |||
761 | if (!DInfo) | |||
762 | return nullptr; | |||
763 | ||||
764 | const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); | |||
765 | if (const ObjCPropertyDeclInfo *PropInfo = dyn_cast<ObjCPropertyDeclInfo>(DI)) | |||
766 | return &PropInfo->ObjCPropDeclInfo; | |||
767 | ||||
768 | return nullptr; | |||
769 | } | |||
770 | ||||
771 | const CXIdxIBOutletCollectionAttrInfo * | |||
772 | clang_index_getIBOutletCollectionAttrInfo(const CXIdxAttrInfo *AInfo) { | |||
773 | if (!AInfo) | |||
774 | return nullptr; | |||
775 | ||||
776 | const AttrInfo *DI = static_cast<const AttrInfo *>(AInfo); | |||
777 | if (const IBOutletCollectionInfo * | |||
778 | IBInfo = dyn_cast<IBOutletCollectionInfo>(DI)) | |||
779 | return &IBInfo->IBCollInfo; | |||
780 | ||||
781 | return nullptr; | |||
782 | } | |||
783 | ||||
784 | const CXIdxCXXClassDeclInfo * | |||
785 | clang_index_getCXXClassDeclInfo(const CXIdxDeclInfo *DInfo) { | |||
786 | if (!DInfo) | |||
787 | return nullptr; | |||
788 | ||||
789 | const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); | |||
790 | if (const CXXClassDeclInfo *ClassInfo = dyn_cast<CXXClassDeclInfo>(DI)) | |||
791 | return &ClassInfo->CXXClassInfo; | |||
792 | ||||
793 | return nullptr; | |||
794 | } | |||
795 | ||||
796 | CXIdxClientContainer | |||
797 | clang_index_getClientContainer(const CXIdxContainerInfo *info) { | |||
798 | if (!info) | |||
799 | return nullptr; | |||
800 | const ContainerInfo *Container = static_cast<const ContainerInfo *>(info); | |||
801 | return Container->IndexCtx->getClientContainerForDC(Container->DC); | |||
802 | } | |||
803 | ||||
804 | void clang_index_setClientContainer(const CXIdxContainerInfo *info, | |||
805 | CXIdxClientContainer client) { | |||
806 | if (!info) | |||
807 | return; | |||
808 | const ContainerInfo *Container = static_cast<const ContainerInfo *>(info); | |||
809 | Container->IndexCtx->addContainerInMap(Container->DC, client); | |||
810 | } | |||
811 | ||||
812 | CXIdxClientEntity clang_index_getClientEntity(const CXIdxEntityInfo *info) { | |||
813 | if (!info) | |||
814 | return nullptr; | |||
815 | const EntityInfo *Entity = static_cast<const EntityInfo *>(info); | |||
816 | return Entity->IndexCtx->getClientEntity(Entity->Dcl); | |||
817 | } | |||
818 | ||||
819 | void clang_index_setClientEntity(const CXIdxEntityInfo *info, | |||
820 | CXIdxClientEntity client) { | |||
821 | if (!info) | |||
822 | return; | |||
823 | const EntityInfo *Entity = static_cast<const EntityInfo *>(info); | |||
824 | Entity->IndexCtx->setClientEntity(Entity->Dcl, client); | |||
825 | } | |||
826 | ||||
827 | CXIndexAction clang_IndexAction_create(CXIndex CIdx) { | |||
828 | return new IndexSessionData(CIdx); | |||
829 | } | |||
830 | ||||
831 | void clang_IndexAction_dispose(CXIndexAction idxAction) { | |||
832 | if (idxAction) | |||
833 | delete static_cast<IndexSessionData *>(idxAction); | |||
834 | } | |||
835 | ||||
836 | int clang_indexSourceFile(CXIndexAction idxAction, | |||
837 | CXClientData client_data, | |||
838 | IndexerCallbacks *index_callbacks, | |||
839 | unsigned index_callbacks_size, | |||
840 | unsigned index_options, | |||
841 | const char *source_filename, | |||
842 | const char * const *command_line_args, | |||
843 | int num_command_line_args, | |||
844 | struct CXUnsavedFile *unsaved_files, | |||
845 | unsigned num_unsaved_files, | |||
846 | CXTranslationUnit *out_TU, | |||
847 | unsigned TU_options) { | |||
848 | SmallVector<const char *, 4> Args; | |||
849 | Args.push_back("clang"); | |||
850 | Args.append(command_line_args, command_line_args + num_command_line_args); | |||
851 | return clang_indexSourceFileFullArgv( | |||
852 | idxAction, client_data, index_callbacks, index_callbacks_size, | |||
853 | index_options, source_filename, Args.data(), Args.size(), unsaved_files, | |||
854 | num_unsaved_files, out_TU, TU_options); | |||
855 | } | |||
856 | ||||
857 | int clang_indexSourceFileFullArgv( | |||
858 | CXIndexAction idxAction, CXClientData client_data, | |||
859 | IndexerCallbacks *index_callbacks, unsigned index_callbacks_size, | |||
860 | unsigned index_options, const char *source_filename, | |||
861 | const char *const *command_line_args, int num_command_line_args, | |||
862 | struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files, | |||
863 | CXTranslationUnit *out_TU, unsigned TU_options) { | |||
864 | LOG_FUNC_SECTIONif (clang::cxindex::LogRef Log = clang::cxindex::Logger::make (__func__)) { | |||
865 | *Log << source_filename << ": "; | |||
866 | for (int i = 0; i != num_command_line_args; ++i) | |||
867 | *Log << command_line_args[i] << " "; | |||
868 | } | |||
869 | ||||
870 | if (num_unsaved_files && !unsaved_files) | |||
871 | return CXError_InvalidArguments; | |||
872 | ||||
873 | CXErrorCode result = CXError_Failure; | |||
874 | auto IndexSourceFileImpl = [=, &result]() { | |||
875 | result = clang_indexSourceFile_Impl( | |||
876 | idxAction, client_data, index_callbacks, index_callbacks_size, | |||
877 | index_options, source_filename, command_line_args, | |||
878 | num_command_line_args, | |||
879 | llvm::makeArrayRef(unsaved_files, num_unsaved_files), out_TU, | |||
880 | TU_options); | |||
881 | }; | |||
882 | ||||
883 | llvm::CrashRecoveryContext CRC; | |||
884 | ||||
885 | if (!RunSafely(CRC, IndexSourceFileImpl)) { | |||
886 | fprintf(stderrstderr, "libclang: crash detected during indexing source file: {\n"); | |||
887 | fprintf(stderrstderr, " 'source_filename' : '%s'\n", source_filename); | |||
888 | fprintf(stderrstderr, " 'command_line_args' : ["); | |||
889 | for (int i = 0; i != num_command_line_args; ++i) { | |||
890 | if (i) | |||
891 | fprintf(stderrstderr, ", "); | |||
892 | fprintf(stderrstderr, "'%s'", command_line_args[i]); | |||
893 | } | |||
894 | fprintf(stderrstderr, "],\n"); | |||
895 | fprintf(stderrstderr, " 'unsaved_files' : ["); | |||
896 | for (unsigned i = 0; i != num_unsaved_files; ++i) { | |||
897 | if (i) | |||
898 | fprintf(stderrstderr, ", "); | |||
899 | fprintf(stderrstderr, "('%s', '...', %ld)", unsaved_files[i].Filename, | |||
900 | unsaved_files[i].Length); | |||
901 | } | |||
902 | fprintf(stderrstderr, "],\n"); | |||
903 | fprintf(stderrstderr, " 'options' : %d,\n", TU_options); | |||
904 | fprintf(stderrstderr, "}\n"); | |||
905 | ||||
906 | return 1; | |||
907 | } else if (getenv("LIBCLANG_RESOURCE_USAGE")) { | |||
908 | if (out_TU) | |||
909 | PrintLibclangResourceUsage(*out_TU); | |||
910 | } | |||
911 | ||||
912 | return result; | |||
913 | } | |||
914 | ||||
915 | int clang_indexTranslationUnit(CXIndexAction idxAction, | |||
916 | CXClientData client_data, | |||
917 | IndexerCallbacks *index_callbacks, | |||
918 | unsigned index_callbacks_size, | |||
919 | unsigned index_options, | |||
920 | CXTranslationUnit TU) { | |||
921 | LOG_FUNC_SECTIONif (clang::cxindex::LogRef Log = clang::cxindex::Logger::make (__func__)) { | |||
922 | *Log << TU; | |||
923 | } | |||
924 | ||||
925 | CXErrorCode result; | |||
926 | auto IndexTranslationUnitImpl = [=, &result]() { | |||
927 | result = clang_indexTranslationUnit_Impl( | |||
928 | idxAction, client_data, index_callbacks, index_callbacks_size, | |||
929 | index_options, TU); | |||
930 | }; | |||
931 | ||||
932 | llvm::CrashRecoveryContext CRC; | |||
933 | ||||
934 | if (!RunSafely(CRC, IndexTranslationUnitImpl)) { | |||
935 | fprintf(stderrstderr, "libclang: crash detected during indexing TU\n"); | |||
936 | ||||
937 | return 1; | |||
938 | } | |||
939 | ||||
940 | return result; | |||
941 | } | |||
942 | ||||
943 | void clang_indexLoc_getFileLocation(CXIdxLoc location, | |||
944 | CXIdxClientFile *indexFile, | |||
945 | CXFile *file, | |||
946 | unsigned *line, | |||
947 | unsigned *column, | |||
948 | unsigned *offset) { | |||
949 | if (indexFile) *indexFile = nullptr; | |||
950 | if (file) *file = nullptr; | |||
951 | if (line) *line = 0; | |||
952 | if (column) *column = 0; | |||
953 | if (offset) *offset = 0; | |||
954 | ||||
955 | SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); | |||
956 | if (!location.ptr_data[0] || Loc.isInvalid()) | |||
957 | return; | |||
958 | ||||
959 | CXIndexDataConsumer &DataConsumer = | |||
960 | *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]); | |||
961 | DataConsumer.translateLoc(Loc, indexFile, file, line, column, offset); | |||
962 | } | |||
963 | ||||
964 | CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) { | |||
965 | SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); | |||
966 | if (!location.ptr_data[0] || Loc.isInvalid()) | |||
967 | return clang_getNullLocation(); | |||
968 | ||||
969 | CXIndexDataConsumer &DataConsumer = | |||
970 | *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]); | |||
971 | return cxloc::translateSourceLocation(DataConsumer.getASTContext(), Loc); | |||
972 | } | |||
973 |
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 */ |