Changeset View
Changeset View
Standalone View
Standalone View
languages/clang/duchain/builder.cpp
Show All 33 Lines | |||||
34 | #include "util/clangtypes.h" | 34 | #include "util/clangtypes.h" | ||
35 | 35 | | |||
36 | #include <util/pushvalue.h> | 36 | #include <util/pushvalue.h> | ||
37 | 37 | | |||
38 | #include <language/duchain/duchainlock.h> | 38 | #include <language/duchain/duchainlock.h> | ||
39 | #include <language/duchain/classdeclaration.h> | 39 | #include <language/duchain/classdeclaration.h> | ||
40 | #include <language/duchain/stringhelpers.h> | 40 | #include <language/duchain/stringhelpers.h> | ||
41 | #include <language/duchain/duchainutils.h> | 41 | #include <language/duchain/duchainutils.h> | ||
42 | #include <language/duchain/problem.h> | ||||
42 | 43 | | |||
43 | #include <language/duchain/types/pointertype.h> | 44 | #include <language/duchain/types/pointertype.h> | ||
44 | #include <language/duchain/types/arraytype.h> | 45 | #include <language/duchain/types/arraytype.h> | ||
45 | #include <language/duchain/types/referencetype.h> | 46 | #include <language/duchain/types/referencetype.h> | ||
46 | #include <language/duchain/types/functiontype.h> | 47 | #include <language/duchain/types/functiontype.h> | ||
47 | #include <language/duchain/types/structuretype.h> | 48 | #include <language/duchain/types/structuretype.h> | ||
48 | #include <language/duchain/types/enumerationtype.h> | 49 | #include <language/duchain/types/enumerationtype.h> | ||
49 | #include <language/duchain/types/enumeratortype.h> | 50 | #include <language/duchain/types/enumeratortype.h> | ||
▲ Show 20 Lines • Show All 191 Lines • ▼ Show 20 Line(s) | |||||
241 | { | 242 | { | ||
242 | typedef ClassMemberDeclaration Type; | 243 | typedef ClassMemberDeclaration Type; | ||
243 | }; | 244 | }; | ||
244 | //END DeclType | 245 | //END DeclType | ||
245 | 246 | | |||
246 | //BEGIN CurrentContext | 247 | //BEGIN CurrentContext | ||
247 | struct CurrentContext | 248 | struct CurrentContext | ||
248 | { | 249 | { | ||
249 | CurrentContext(DUContext* context) | 250 | CurrentContext(DUContext* context, QSet<DUContext*> keepAliveContexts) | ||
250 | : context(context) | 251 | : context(context) | ||
252 | , keepAliveContexts(keepAliveContexts) | ||||
251 | { | 253 | { | ||
252 | DUChainReadLocker lock; | 254 | DUChainReadLocker lock; | ||
253 | previousChildContexts = context->childContexts(); | 255 | previousChildContexts = context->childContexts(); | ||
254 | previousChildDeclarations = context->localDeclarations(); | 256 | previousChildDeclarations = context->localDeclarations(); | ||
255 | } | 257 | } | ||
256 | 258 | | |||
257 | ~CurrentContext() | 259 | ~CurrentContext() | ||
258 | { | 260 | { | ||
259 | DUChainWriteLocker lock; | 261 | DUChainWriteLocker lock; | ||
260 | qDeleteAll(previousChildContexts); | 262 | foreach (auto childContext, previousChildContexts) { | ||
263 | if (!keepAliveContexts.contains(childContext)) { | ||||
264 | delete childContext; | ||||
265 | } | ||||
266 | } | ||||
261 | qDeleteAll(previousChildDeclarations); | 267 | qDeleteAll(previousChildDeclarations); | ||
262 | if (resortChildContexts) { | 268 | if (resortChildContexts) { | ||
263 | context->resortChildContexts(); | 269 | context->resortChildContexts(); | ||
264 | } | 270 | } | ||
265 | if (resortLocalDeclarations) { | 271 | if (resortLocalDeclarations) { | ||
266 | context->resortLocalDeclarations(); | 272 | context->resortLocalDeclarations(); | ||
267 | } | 273 | } | ||
268 | } | 274 | } | ||
269 | 275 | | |||
270 | DUContext* context; | 276 | DUContext* context; | ||
271 | // when updating, this contains child contexts of the current parent context | 277 | // when updating, this contains child contexts of the current parent context | ||
272 | QVector<DUContext*> previousChildContexts; | 278 | QVector<DUContext*> previousChildContexts; | ||
279 | // when updating, this contains contexts that must not be deleted | ||||
280 | QSet<DUContext*> keepAliveContexts; | ||||
273 | // when updating, this contains child declarations of the current parent context | 281 | // when updating, this contains child declarations of the current parent context | ||
274 | QVector<Declaration*> previousChildDeclarations; | 282 | QVector<Declaration*> previousChildDeclarations; | ||
275 | 283 | | |||
276 | bool resortChildContexts = false; | 284 | bool resortChildContexts = false; | ||
277 | bool resortLocalDeclarations = false; | 285 | bool resortLocalDeclarations = false; | ||
278 | }; | 286 | }; | ||
279 | //END CurrentContext | 287 | //END CurrentContext | ||
280 | 288 | | |||
▲ Show 20 Lines • Show All 829 Lines • ▼ Show 20 Line(s) | 1107 | { | |||
1110 | QScopedPointer<CurrentContext> helperContext; | 1118 | QScopedPointer<CurrentContext> helperContext; | ||
1111 | if (CursorKindTraits::isClass(CK) || CursorKindTraits::isFunction(CK)) { | 1119 | if (CursorKindTraits::isClass(CK) || CursorKindTraits::isFunction(CK)) { | ||
1112 | const auto lexicalParent = clang_getCursorLexicalParent(cursor); | 1120 | const auto lexicalParent = clang_getCursorLexicalParent(cursor); | ||
1113 | const auto semanticParent = clang_getCursorSemanticParent(cursor); | 1121 | const auto semanticParent = clang_getCursorSemanticParent(cursor); | ||
1114 | const bool isOutOfLine = !clang_equalCursors(lexicalParent, semanticParent); | 1122 | const bool isOutOfLine = !clang_equalCursors(lexicalParent, semanticParent); | ||
1115 | if (isOutOfLine) { | 1123 | if (isOutOfLine) { | ||
1116 | const QString scope = ClangUtils::getScope(cursor); | 1124 | const QString scope = ClangUtils::getScope(cursor); | ||
1117 | auto context = createContext<CK, DUContext::Helper>(cursor, QualifiedIdentifier(scope)); | 1125 | auto context = createContext<CK, DUContext::Helper>(cursor, QualifiedIdentifier(scope)); | ||
1118 | helperContext.reset(new CurrentContext(context)); | 1126 | helperContext.reset(new CurrentContext(context, m_parentContext->keepAliveContexts)); | ||
1119 | } | 1127 | } | ||
1120 | } | 1128 | } | ||
1121 | 1129 | | |||
1122 | // if helperContext is null, this is a no-op | 1130 | // if helperContext is null, this is a no-op | ||
1123 | PushValue<CurrentContext*> pushCurrent(m_parentContext, helperContext.isNull() ? m_parentContext : helperContext.data()); | 1131 | PushValue<CurrentContext*> pushCurrent(m_parentContext, helperContext.isNull() ? m_parentContext : helperContext.data()); | ||
1124 | 1132 | | |||
1125 | if (hasContext) { | 1133 | if (hasContext) { | ||
1126 | auto context = createContext<CK, CursorKindTraits::contextType(CK)>(cursor, QualifiedIdentifier(id)); | 1134 | auto context = createContext<CK, CursorKindTraits::contextType(CK)>(cursor, QualifiedIdentifier(id)); | ||
1127 | createDeclaration<CK, DeclType>(cursor, id, context); | 1135 | createDeclaration<CK, DeclType>(cursor, id, context); | ||
1128 | CurrentContext newParent(context); | 1136 | CurrentContext newParent(context, m_parentContext->keepAliveContexts); | ||
1129 | PushValue<CurrentContext*> pushCurrent(m_parentContext, &newParent); | 1137 | PushValue<CurrentContext*> pushCurrent(m_parentContext, &newParent); | ||
1130 | clang_visitChildren(cursor, &visitCursor, this); | 1138 | clang_visitChildren(cursor, &visitCursor, this); | ||
1131 | return CXChildVisit_Continue; | 1139 | return CXChildVisit_Continue; | ||
1132 | } | 1140 | } | ||
1133 | createDeclaration<CK, DeclType>(cursor, id, nullptr); | 1141 | createDeclaration<CK, DeclType>(cursor, id, nullptr); | ||
1134 | return CXChildVisit_Recurse; | 1142 | return CXChildVisit_Recurse; | ||
1135 | } | 1143 | } | ||
1136 | 1144 | | |||
Show All 21 Lines | 1158 | { | |||
1158 | return CXChildVisit_Recurse; | 1166 | return CXChildVisit_Recurse; | ||
1159 | } | 1167 | } | ||
1160 | 1168 | | |||
1161 | CXChildVisitResult Visitor::buildCompoundStatement(CXCursor cursor) | 1169 | CXChildVisitResult Visitor::buildCompoundStatement(CXCursor cursor) | ||
1162 | { | 1170 | { | ||
1163 | if (m_parentContext->context->type() == DUContext::Function) | 1171 | if (m_parentContext->context->type() == DUContext::Function) | ||
1164 | { | 1172 | { | ||
1165 | auto context = createContext<CXCursor_CompoundStmt, DUContext::Other>(cursor); | 1173 | auto context = createContext<CXCursor_CompoundStmt, DUContext::Other>(cursor); | ||
1166 | CurrentContext newParent(context); | 1174 | CurrentContext newParent(context, m_parentContext->keepAliveContexts); | ||
1167 | PushValue<CurrentContext*> pushCurrent(m_parentContext, &newParent); | 1175 | PushValue<CurrentContext*> pushCurrent(m_parentContext, &newParent); | ||
1168 | clang_visitChildren(cursor, &visitCursor, this); | 1176 | clang_visitChildren(cursor, &visitCursor, this); | ||
1169 | return CXChildVisit_Continue; | 1177 | return CXChildVisit_Continue; | ||
1170 | } | 1178 | } | ||
1171 | return CXChildVisit_Recurse; | 1179 | return CXChildVisit_Recurse; | ||
1172 | } | 1180 | } | ||
1173 | 1181 | | |||
1174 | CXChildVisitResult Visitor::buildCXXBaseSpecifier(CXCursor cursor) | 1182 | CXChildVisitResult Visitor::buildCXXBaseSpecifier(CXCursor cursor) | ||
▲ Show 20 Lines • Show All 152 Lines • ▼ Show 20 Line(s) | |||||
1327 | Visitor::Visitor(CXTranslationUnit tu, CXFile file, | 1335 | Visitor::Visitor(CXTranslationUnit tu, CXFile file, | ||
1328 | const IncludeFileContexts& includes, const bool update) | 1336 | const IncludeFileContexts& includes, const bool update) | ||
1329 | : m_file(file) | 1337 | : m_file(file) | ||
1330 | , m_includes(includes) | 1338 | , m_includes(includes) | ||
1331 | , m_parentContext(nullptr) | 1339 | , m_parentContext(nullptr) | ||
1332 | , m_update(update) | 1340 | , m_update(update) | ||
1333 | { | 1341 | { | ||
1334 | CXCursor tuCursor = clang_getTranslationUnitCursor(tu); | 1342 | CXCursor tuCursor = clang_getTranslationUnitCursor(tu); | ||
1335 | CurrentContext parent(includes[file]); | 1343 | auto top = includes[file]; | ||
1344 | | ||||
1345 | // when updating, this contains child contexts that should be kept alive | ||||
1346 | // even when they are not part of the AST anymore | ||||
1347 | // this is required for some assistants, such as the signature assistant | ||||
1348 | QSet<DUContext*> keepAliveContexts; | ||||
1349 | { | ||||
1350 | DUChainReadLocker lock; | ||||
1351 | foreach (const auto& problem, top->problems()) { | ||||
1352 | const auto& desc = problem->description(); | ||||
1353 | if (desc.startsWith(QLatin1String("Return type of out-of-line definition of '")) | ||||
1354 | && desc.endsWith(QLatin1String("' differs from that in the declaration"))) { | ||||
1355 | auto ctx = top->findContextAt(problem->range().start); | ||||
1356 | // keep the context and its parents alive | ||||
1357 | // this also keeps declarations in this context alive | ||||
1358 | while (ctx) { | ||||
1359 | keepAliveContexts << ctx; | ||||
1360 | ctx = ctx->parentContext(); | ||||
1361 | } | ||||
1362 | } | ||||
1363 | } | ||||
1364 | } | ||||
1365 | | ||||
1366 | CurrentContext parent(top, keepAliveContexts); | ||||
1336 | m_parentContext = &parent; | 1367 | m_parentContext = &parent; | ||
1337 | clang_visitChildren(tuCursor, &visitCursor, this); | 1368 | clang_visitChildren(tuCursor, &visitCursor, this); | ||
1338 | 1369 | | |||
1339 | TopDUContext *top = m_parentContext->context->topContext(); | | |||
1340 | if (m_update) { | 1370 | if (m_update) { | ||
1341 | DUChainWriteLocker lock; | 1371 | DUChainWriteLocker lock; | ||
1342 | top->deleteUsesRecursively(); | 1372 | top->deleteUsesRecursively(); | ||
1343 | } | 1373 | } | ||
1344 | for (const auto &contextUses : m_uses) { | 1374 | for (const auto &contextUses : m_uses) { | ||
1345 | for (const auto &cursor : contextUses.second) { | 1375 | for (const auto &cursor : contextUses.second) { | ||
1346 | auto referenced = referencedCursor(cursor); | 1376 | auto referenced = referencedCursor(cursor); | ||
1347 | if (clang_Cursor_isNull(referenced)) { | 1377 | if (clang_Cursor_isNull(referenced)) { | ||
▲ Show 20 Lines • Show All 131 Lines • Show Last 20 Lines |