1
/* This file is part of KDevelop
2
Copyright 2007 David Nolden <david.nolden.kdevelop@art-master.de>
4
This library is free software; you can redistribute it and/or
5
modify it under the terms of the GNU Library General Public
6
License version 2 as published by the Free Software Foundation.
8
This library is distributed in the hope that it will be useful,
9
but WITHOUT ANY WARRANTY; without even the implied warranty of
10
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
Library General Public License for more details.
13
You should have received a copy of the GNU Library General Public License
14
along with this library; see the file COPYING.LIB. If not, write to
15
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16
Boston, MA 02110-1301, USA.
21
Some mindmapping about how the template-system works:
24
- Simplify: Template-parameters are types
25
- Within template-contexts, do not resolve any types. Instead create "virtual types" that will resolve the types when template-parameters are given.
30
- Searching instantiated template-class:
31
- return virtual declaration
32
- return virtual context (Change template-parameter-context to given template-arguments)
33
- Searching IN instantiated template-class:
34
- When searching local declarations:
35
- Check whether they are already in the instantiated context, if yes return them
36
- If not, Search in non-instantiated context(only for local declarations), then:
37
- Copy & Change returned objects:
38
- Resolve virtual types (DelayedType)
39
- Change parent-context to virtual context
40
- Change internal context, (create virtual, move set parent)
42
- How template-parameters are resolved:
43
- The DUContext's with type DUContext::Template get their template-parameter declarations instantiated and added locally. Then they will be found when resolving virtual types.
48
#ifndef CPPDUCONTEXT_H
49
#define CPPDUCONTEXT_H
51
#include <language/duchain/ducontext.h>
56
#include <language/duchain/abstractfunctiondeclaration.h>
57
#include <language/duchain/declaration.h>
58
#include <language/duchain/duchainlock.h>
59
#include <language/duchain/duchain.h>
60
#include <language/duchain/topducontext.h>
61
#include <language/duchain/classfunctiondeclaration.h>
62
#include <language/duchain/namespacealiasdeclaration.h>
63
#include "typeutils.h"
65
#include "cppduchain.h"
66
#include "templatedeclaration.h"
67
#include "expressionparser.h"
68
#include "cppdebughelper.h"
70
using namespace KDevelop;
73
extern QMutex cppDuContextInstantiationsMutex;
75
///This class breaks up the logic of searching a declaration in C++, so QualifiedIdentifiers as well as AST-based lookup mechanisms can be used for searching
76
class FindDeclaration {
78
FindDeclaration( const DUContext* ctx, const TopDUContext* source, DUContext::SearchFlags flags, const SimpleCursor& position, AbstractType::Ptr dataType = AbstractType::Ptr() ) : m_context(ctx), m_source(source), m_flags(flags), m_position(position), m_dataType(dataType) {
81
void openQualifiedIdentifier( bool isExplicitlyGlobal ) {
82
QualifiedIdentifier i;
83
i.setExplicitlyGlobal( isExplicitlyGlobal );
84
StatePtr s(new State);
89
///Can be used to just append a result that was computed outside. closeQualifiedIdentifier(...) must still be called.
90
void openQualifiedIdentifier( const ExpressionEvaluationResult& result ) {
91
StatePtr s(new State);
92
s->expressionResult = result;
94
foreach(const DeclarationId& decl, result.allDeclarations)
95
s->result << DeclarationPointer( decl.getDeclaration(const_cast<TopDUContext*>(topContext())) );
101
* After this was called, lastDeclarations(..) can be used to retrieve declarations of the qualified identifier.
102
* The DUChain needs to be locked when this is called.
104
void closeQualifiedIdentifier();
106
* The identifier must not have template identifiers, those need to be added using openQualifiedIdentifier(..) and closeQualifiedIdentifier(..)
108
void openIdentifier( const Identifier& identifier ) {
109
m_states.top()->identifier.push(identifier);
112
* When closeIdentifier() is called, the last opened identifier is searched, and can be retrieved using lastDeclarations().
113
* Returns false when the search should be stopped.
114
* The DUChain needs to be locked when this is called.
115
* @param isFinalIdentifier Whether the closed identifier the last one. Needed to know when to apply what search-flags.
117
bool closeIdentifier(bool isFinalIdentifier);
119
///For debugging. Describes the last search context.
120
QString describeLastContext() const {
121
if( m_lastScopeContext ) {
122
return "Context " + m_lastScopeContext->scopeIdentifier(true).toString() + QString(" from %1:%2").arg(m_lastScopeContext->url().str()).arg(m_lastScopeContext->range().start.line);
124
return QString("Global search with top-context %2").arg(topContext()->url().str());
129
* Returns the Declarations found for the last closed qualified identifier.
132
QList<DeclarationPointer> lastDeclarations() const {
133
return m_lastDeclarations;
136
const TopDUContext* topContext() const {
140
uint currentLength() const {
141
return m_states.size();
146
///Uses the instantiation-information from the context of decl as parent of templateArguments.
147
Declaration* instantiateDeclaration( Declaration* decl, const InstantiationInformation& templateArguments ) const;
149
struct State : public KShared {
152
QualifiedIdentifier identifier; //identifier including eventual namespace prefix
153
InstantiationInformation templateParameters;
155
///One of the following is filled
156
QList<DeclarationPointer> result;
157
ExpressionEvaluationResult expressionResult;
160
typedef KSharedPtr<State> StatePtr;
162
QStack<StatePtr> m_states;
163
const DUContext* m_context;
164
const TopDUContext* m_source;
165
DUContext::SearchFlags m_flags;
166
QList<DeclarationPointer> m_lastDeclarations;
167
SimpleCursor m_position;
168
AbstractType::Ptr m_dataType;
170
DUContextPointer m_lastScopeContext; //For debugging, last context in which we searched
174
* This is a du-context template that wraps the c++-specific logic around existing DUContext-derived classes.
175
* In practice this means DUContext and TopDUContext.
177
template<class BaseContext>
178
class CppDUContext : public BaseContext {
181
CppDUContext(Data& data) : BaseContext(data), m_instantiatedFrom(0) {
184
///Parameters will be reached to the base-class
185
template<class Param1, class Param2>
186
CppDUContext( const Param1& p1, const Param2& p2, bool isInstantiationContext ) : BaseContext(p1, p2, isInstantiationContext), m_instantiatedFrom(0) {
187
static_cast<DUChainBase*>(this)->d_func_dynamic()->setClassId(this);
190
///Both parameters will be reached to the base-class. This fits TopDUContext.
191
template<class Param1, class Param2, class Param3>
192
CppDUContext( const Param1& p1, const Param2& p2, const Param3& p3) : BaseContext(p1, p2, p3), m_instantiatedFrom(0) {
193
static_cast<DUChainBase*>(this)->d_func_dynamic()->setClassId(this);
195
template<class Param1, class Param2>
196
CppDUContext( const Param1& p1, const Param2& p2) : BaseContext(p1, p2), m_instantiatedFrom(0) {
197
static_cast<DUChainBase*>(this)->d_func_dynamic()->setClassId(this);
200
///Matches the qualified identifier represented by the search item to the tail of the contexts scope identfier
201
///Also matches searches without template-parameters to fully instantiated contexts
202
///Returns true if they match
203
inline bool matchSearchItem(DUContext::SearchItem::Ptr item, const DUContext* ctx) const {
204
DUContext::SearchItem::PtrList items;
207
if(!item->next.isEmpty())
208
item = item->next[0];
213
while(ctx && !items.isEmpty()) {
214
QualifiedIdentifier localId = ctx->localScopeIdentifier();
216
if(localId.isEmpty())
219
int matchPos = localId.count()-1;
220
while(!items.isEmpty() && matchPos >= 0) {
222
if(items.back()->identifier.templateIdentifiersCount())
223
return false; //Don't match when there is template parameters, as that needs other mechanisms
225
if((!items.back()->identifier.templateIdentifiersCount() && items.back()->identifier.identifier() == localId.at(matchPos).identifier()) ||
226
items.back()->identifier == localId.at(matchPos)) {
228
items.resize(items.size()-1);
237
ctx = ctx->parentContext();
243
///Overridden to take care of templates and other c++ specific things
244
virtual bool findDeclarationsInternal(const DUContext::SearchItem::PtrList& identifiers, const SimpleCursor& position, const AbstractType::Ptr& dataType, DUContext::DeclarationList& ret, const TopDUContext* source, typename BaseContext::SearchFlags basicFlags, uint depth ) const
246
if(this->type() == DUContext::Class && identifiers.count() == 1 &&
247
!(basicFlags & DUContext::NoSelfLookUp) && !(basicFlags & DUContext::OnlyFunctions) && this->localScopeIdentifier().count() &&
248
!identifiers[0]->isExplicitlyGlobal) {
250
//Check whether we're searching for just the name of this context's class. If yes, return this context's owner.
251
if(matchSearchItem(identifiers[0], this)) {
253
Declaration* owner = this->owner();
255
if(basicFlags & DUContext::NoUndefinedTemplateParams) {
256
//If no undefined template parameters are allowed, make sure this template has all parameters assigned.
257
TemplateDeclaration* templateOwner = dynamic_cast<TemplateDeclaration*>(this->owner());
259
if(!templateOwner->instantiatedFrom())
261
DUContext* templateContext = templateOwner->templateContext(source);
262
if(templateContext) {
263
foreach(Declaration* decl, templateContext->localDeclarations()) {
264
if(decl->type<CppTemplateParameterType>()) {
272
ret << this->owner();
278
if( basicFlags & BaseContext::DirectQualifiedLookup ) {
279
//ifDebug( kDebug(9007) << "redirecting findDeclarationsInternal in " << this << "(" << this->scopeIdentifier() <<") for \"" << identifier.toString() << "\""; )
280
//We use DirectQualifiedLookup to signalize that we don't need to do the whole scope-search, template-resolution etc. logic.
281
return BaseContext::findDeclarationsInternal(identifiers, position, dataType, ret, source, basicFlags, depth );
284
FOREACH_ARRAY( const DUContext::SearchItem::Ptr& item, identifiers )
285
foreach( const QualifiedIdentifier& id, item->toList() )
286
if(!findDeclarationsInternal(id, position, dataType, ret, source, basicFlags))
289
// Remove all forward-declarations if there is a real declaration in the list
291
bool haveForwardDeclaration = false;
292
bool haveNonForwardDeclaration = false;
294
for(int a = 0; a < ret.size(); ++a) {
295
if(ret[a]->isForwardDeclaration())
296
haveForwardDeclaration = true;
298
haveNonForwardDeclaration = true;
301
if(haveForwardDeclaration && haveNonForwardDeclaration) {
302
DUContext::DeclarationList oldRet = ret;
304
for(int a = 0; a < oldRet.size(); ++a)
305
if(!oldRet[a]->isForwardDeclaration())
306
ret.append(oldRet[a]);
311
bool findDeclarationsInternal(const QualifiedIdentifier& identifier, const SimpleCursor& position, const AbstractType::Ptr& dataType, DUContext::DeclarationList& ret, const TopDUContext* source, typename BaseContext::SearchFlags basicFlags) const
313
ifDebug( kDebug(9007) << "findDeclarationsInternal in " << this << "(" << this->scopeIdentifier() <<") for \"" << identifier.toString() << "\""; )
315
FindDeclaration find( this, source, basicFlags, position, dataType );
317
find.openQualifiedIdentifier( identifier.explicitlyGlobal() );
319
int idCount = identifier.count();
320
for( int num = 0; num < idCount; num++ )
323
Identifier current = identifier.at(num);
324
current.clearTemplateIdentifiers();
325
find.openIdentifier(current);
329
Identifier currentIdentifier = identifier.at(num);
331
///Step 1: Resolve the template-arguments
332
//Since there may be non-type template-parameters, represent them as ExpressionEvaluationResult's
334
int tempCount = currentIdentifier.templateIdentifiersCount();
335
for( int a = 0; a < tempCount; a++ ) {
336
//Use the already available mechanism for resolving delayed types
337
Cpp::ExpressionEvaluationResult res;
338
IndexedTypeIdentifier i = currentIdentifier.templateIdentifier(a);
339
//If the identifier is empty, it is probably just a mark that a template should be instantiated, but without explicit paremeters.
340
QualifiedIdentifier qid(i.identifier().identifier());
341
if( !qid.isEmpty() ) {
342
DelayedType::Ptr delayed( new DelayedType() );
343
delayed->setIdentifier( i );
345
res.type = Cpp::resolveDelayedTypes( delayed.cast<AbstractType>(), this, source, basicFlags & KDevelop::DUContext::NoUndefinedTemplateParams ? DUContext::NoUndefinedTemplateParams : DUContext::NoSearchFlags )->indexed();
347
if( basicFlags & KDevelop::DUContext::NoUndefinedTemplateParams) {
348
AbstractType::Ptr targetTypePtr = TypeUtils::unAliasedType(TypeUtils::targetType(res.type.abstractType(), 0));
349
if (targetTypePtr.cast<CppTemplateParameterType>() || targetTypePtr.cast<DelayedType>()) {
354
ifDebug( if( !res.isValid() ) kDebug(9007) << "Could not resolve template-parameter \"" << currentIdentifier.templateIdentifier(a).toString() << "\" in \"" << identifier.toString() << "resolved:" << res.toString(); )
357
find.openQualifiedIdentifier( res );
358
find.closeQualifiedIdentifier();
362
if( !find.closeIdentifier( num == idCount-1 ) )
365
find.closeQualifiedIdentifier();
367
foreach( const DeclarationPointer& decl, find.lastDeclarations() )
368
ret.append(decl.data());
373
virtual void findLocalDeclarationsInternal( const Identifier& identifier, const SimpleCursor & position, const AbstractType::Ptr& dataType, DUContext::DeclarationList& ret, const TopDUContext* source, typename BaseContext::SearchFlags flags ) const
375
ifDebug( kDebug(9007) << "findLocalDeclarationsInternal in " << this << "with parent" << this->parentContext() << "(" << this->scopeIdentifier() <<") for \"" << identifier.toString() << "\""; )
376
ifDebug( if( BaseContext::owner() && BaseContext::owner() ) kDebug(9007) << "in declaration: " << "(" << BaseContext::owner()->toString(); )
378
- When searching local declarations:
379
- Check whether they are already in the instantiated context, if yes return them
380
- If not, Search in non-instantiated context(only for local declarations), then:
381
- Copy & Change returned objects:
382
- Resolve virtual types (DelayedType)
383
- Change parent-context to virtual context
384
- Change internal context, (create virtual, move set parent)
387
int retCount = ret.size();
389
BaseContext::findLocalDeclarationsInternal(identifier, position, dataType, ret, source, flags );
391
ifDebug( kDebug(9007) << "basically found:" << ret.count() - retCount << "containing" << BaseContext::localDeclarations().count() << "searching-position" << position.textCursor(); )
393
if( !(flags & DUContext::NoFiltering) ) {
394
//Filter out constructors and if needed unresolved template-params
395
for(int a = 0; a < ret.size(); ) {
397
AbstractType::Ptr retAbstractTypePtr = ret[a]->abstractType();
398
if( ( (flags & KDevelop::DUContext::NoUndefinedTemplateParams) && retAbstractTypePtr.cast<CppTemplateParameterType>() )
399
|| ( (!(flags & BaseContext::OnlyFunctions)) && (dynamic_cast<ClassFunctionDeclaration*>(ret[a]) && static_cast<ClassFunctionDeclaration*>(ret[a])->isConstructor() ) ) ) { //Maybe this filtering should be done in the du-chain?
402
for(int b = a+1; b < ret.size(); ++b)
404
ret.resize(ret.size()-1);
405
//kDebug(9007) << "filtered out 1 declaration";
412
ifDebug( if( BaseContext::owner() && BaseContext::owner() ) kDebug(9007) << "in declaration: " << "(" << BaseContext::owner()->toString(); )
413
ifDebug( kDebug(9007) << "instantiated from:" << m_instantiatedFrom; )
415
if( m_instantiatedFrom && ret.size() == retCount ) {
416
///Search in the context this one was instantiated from
417
DUContext::DeclarationList decls;
418
ifDebug( kDebug(9007) << "searching base"; )
419
m_instantiatedFrom->findLocalDeclarationsInternal( identifier, position, dataType, decls, source, flags );
421
ifDebug( if( BaseContext::owner() && BaseContext::owner() ) kDebug(9007) << "in declaration: " << "(" << BaseContext::owner()->toString(); )
422
ifDebug( kDebug(9007) << "found" << decls.count() << "in base"; )
424
InstantiationInformation memberInstantiationInformation;
425
memberInstantiationInformation.previousInstantiationInformation = m_instantiatedWith;
427
FOREACH_ARRAY( Declaration* decl, decls ) {
428
TemplateDeclaration* templateDecl = dynamic_cast<TemplateDeclaration*>(decl);
430
kDebug() << "problem";
434
DUContext* current = decl->context();
435
while(current != m_instantiatedFrom && current)
437
// The declaration has been propagated up from a sub-context like an enumerator, add more empty instantiation information
438
// so the depth is matched correctly by the information
439
InstantiationInformation i;
440
i.previousInstantiationInformation = memberInstantiationInformation.indexed();
441
memberInstantiationInformation = i;
442
current = current->parentContext();
445
copy = templateDecl->instantiate(memberInstantiationInformation, source);
446
//This can happen in case of explicit specializations
447
// if(copy->context() != this)
448
// kWarning() << "serious problem: Instatiation is in wrong context, should be in this one";
457
virtual void deleteUses() {
458
QMutexLocker l(&cppDuContextInstantiationsMutex);
459
foreach(CppDUContext<BaseContext>* ctx, m_instatiations)
461
BaseContext::deleteUses();
464
virtual bool foundEnough( const DUContext::DeclarationList& decls, DUContext::SearchFlags flags ) const
466
if(flags & DUContext::NoFiltering)
469
if( decls.isEmpty() )
472
if( dynamic_cast<const KDevelop::AbstractFunctionDeclaration*>(decls[0]) && BaseContext::type() != DUContext::Class ) //In classes, one function hides all overloads
473
return false; //Collect overloaded function-declarations
479
* Set the context which this is instantiated from. This context will be strictly attached to that context, and will be deleted once the other is deleted.
481
void setInstantiatedFrom( CppDUContext<BaseContext>* context, const InstantiationInformation& templateArguments )
483
Q_ASSERT(!dynamic_cast<TopDUContext*>(this));
484
if(context && context->m_instantiatedFrom) {
485
setInstantiatedFrom(context->m_instantiatedFrom, templateArguments);
488
QMutexLocker l(&cppDuContextInstantiationsMutex);
490
if( m_instantiatedFrom ) {
491
Q_ASSERT(m_instantiatedFrom->m_instatiations[m_instantiatedWith] == this);
492
m_instantiatedFrom->m_instatiations.remove( m_instantiatedWith );
495
m_instantiatedWith = templateArguments.indexed();
497
//Change the identifier so it contains the template-parameters
498
QualifiedIdentifier totalId = this->localScopeIdentifier();
499
KDevelop::Identifier id;
500
if( !totalId.isEmpty() ) {
505
id.clearTemplateIdentifiers();
506
FOREACH_FUNCTION(const IndexedType& arg, templateArguments.templateParameters) {
507
AbstractType::Ptr type(arg.abstractType());
508
IdentifiedType* identified = dynamic_cast<IdentifiedType*>(type.unsafeData());
510
id.appendTemplateIdentifier( IndexedTypeIdentifier(identified->qualifiedIdentifier()) );
512
id.appendTemplateIdentifier( IndexedTypeIdentifier(type->toString(), true) );
514
id.appendTemplateIdentifier( IndexedTypeIdentifier("no type") );
519
this->setLocalScopeIdentifier(totalId);
522
m_instantiatedFrom = context;
523
Q_ASSERT(m_instantiatedFrom != this);
524
if(m_instantiatedFrom) {
525
if(!m_instantiatedFrom->m_instatiations.contains(m_instantiatedWith)) {
526
m_instantiatedFrom->m_instatiations.insert( m_instantiatedWith, this );
528
kDebug(9007) << "created orphaned instantiation for" << context->m_instatiations[m_instantiatedWith]->scopeIdentifier(true).toString();
529
m_instantiatedFrom = 0;
534
virtual void applyUpwardsAliases(DUContext::SearchItem::PtrList& identifiers, const TopDUContext* source) const
536
BaseContext::applyUpwardsAliases(identifiers, source);
537
///@see Iso C++ 3.4.1 : Unqualified name lookup:
538
///We need to make sure that when leaving a function definition, the namespace components are searched
539
DUContext::ContextType type = BaseContext::type();
541
if(type == DUContext::Function || type == DUContext::Other || type == DUContext::Helper)
543
QualifiedIdentifier prefix = BaseContext::localScopeIdentifier();
544
if(prefix.count() > 1) {
545
prefix = Cpp::namespaceScopeComponentFromContext(prefix, this, source);
547
if(!prefix.isEmpty()) {
548
prefix.setExplicitlyGlobal(true);
550
DUContext::SearchItem::Ptr newItem(new DUContext::SearchItem(prefix));
551
newItem->addToEachNode(identifiers);
553
if(!newItem->next.isEmpty()) //Can happen if the identifier was explicitly global
554
identifiers.insert(0, newItem);
561
* If this returns nonzero value, this context is a instatiation of some other context, and that other context will be returned here.
563
CppDUContext<BaseContext>* instantiatedFrom() const {
564
return m_instantiatedFrom;
567
virtual bool inDUChain() const {
568
///There must be no changes from the moment m_instantiatedFrom is set, because then it can be found as an instantiation by other threads
569
return m_instantiatedFrom || BaseContext::inDUChain();
572
IndexedInstantiationInformation instantiatedWith() const {
573
return m_instantiatedWith;
576
virtual bool shouldSearchInParent(typename BaseContext::SearchFlags flags) const {
577
//If the parent context is a class context, we should even search it from an import
578
return (BaseContext::parentContext() && BaseContext::parentContext()->type() == DUContext::Class) || BaseContext::shouldSearchInParent(flags);
581
virtual DUContext* specialize(IndexedInstantiationInformation specialization, const TopDUContext* topContext, int upDistance) {
582
if(specialization.index() == 0)
585
InstantiationInformation information = specialization.information();
587
//Add empty elements until the specified depth
588
for(int a = 0; a < upDistance; ++a) {
589
InstantiationInformation nextInformation;
590
nextInformation.previousInstantiationInformation = information.indexed();
591
information = nextInformation;
594
return instantiate(information, topContext);
598
///@see TemplateDeclaration::instantiate
599
DUContext* instantiate(InstantiationInformation info, const TopDUContext* source) {
600
if(!info.isValid() || m_instantiatedWith == info.indexed() || !this->parentContext())
603
if(m_instantiatedFrom)
604
return m_instantiatedFrom->instantiate(info, source);
607
typename QHash<IndexedInstantiationInformation, CppDUContext<BaseContext>* >::const_iterator it = m_instatiations.constFind(info.indexed());
608
if(it != m_instatiations.constEnd())
613
TemplateDeclaration* templ = dynamic_cast<TemplateDeclaration*>(this->owner());
615
Declaration* instantiatedDecl = templ->instantiate(info, source);
616
if(!instantiatedDecl)
618
return instantiatedDecl->internalContext();
622
DUContext* surroundingContext = this->parentContext();
623
Q_ASSERT(surroundingContext);
625
//This context does not have an attached declaration, but it needs to be instantiated.
626
CppDUContext<DUContext>* parent = dynamic_cast<CppDUContext<DUContext>* >(this->parentContext());
628
surroundingContext = parent->instantiate(info.previousInstantiationInformation.information(), source);
631
if(!surroundingContext)
634
return instantiateDeclarationAndContext( surroundingContext, source, this, info, 0, 0 );
637
virtual QWidget* createNavigationWidget(Declaration* decl, TopDUContext* topContext, const QString& htmlPrefix, const QString& htmlSuffix) const;
640
Identity = BaseContext::Identity + 50
643
///Duchain must be write-locked
644
void deleteAllInstantiations() {
645
//Specializations will be destroyed the same time this is destroyed
646
CppDUContext<BaseContext>* oldFirst = 0;
647
QMutexLocker l(&cppDuContextInstantiationsMutex);
648
while(!m_instatiations.isEmpty()) {
649
CppDUContext<BaseContext>* first = 0;
650
first = *m_instatiations.begin();
652
Q_ASSERT(first != oldFirst);
656
if(first->isAnonymous()) {
657
Q_ASSERT(first->m_instantiatedFrom == this);
660
Q_ASSERT(first->m_instantiatedFrom == this);
661
first->setInstantiatedFrom(0, InstantiationInformation());
662
Q_ASSERT(first->m_instantiatedFrom == 0);
671
//Overridden to instantiate all not yet instantiated local declarations
672
virtual QVector<Declaration*> localDeclarations(const TopDUContext* source) const {
674
if(m_instantiatedFrom && source && BaseContext::type() != DUContext::Template) {
675
QVector<Declaration*> decls = m_instantiatedFrom->localDeclarations(source);
676
// DUContext::DeclarationList temp;
678
InstantiationInformation inf;
679
inf.previousInstantiationInformation = m_instantiatedWith;
681
foreach( Declaration* baseDecl, decls ) {
682
TemplateDeclaration* tempDecl = dynamic_cast<TemplateDeclaration*>(baseDecl);
684
tempDecl->instantiate(inf, source);
686
kDebug() << "Strange: non-template within template context";
687
KDevVarLengthArray<Declaration*, 40> temp;
688
this->findLocalDeclarationsInternal( baseDecl->identifier(), SimpleCursor::invalid(), AbstractType::Ptr(), temp, source, DUContext::NoFiltering );
693
return BaseContext::localDeclarations(source);
699
if(m_instantiatedFrom)
700
setInstantiatedFrom(0, InstantiationInformation());
702
deleteAllInstantiations();
705
virtual void mergeDeclarationsInternal(QList< QPair<Declaration*, int> >& definitions, const SimpleCursor& position, QHash<const DUContext*, bool>& hadContexts, const TopDUContext* source, bool searchInParents, int currentDepth) const
708
// kDebug() << "checking in" << this->scopeIdentifier(true).toString();
709
if( m_instantiatedFrom )
711
//We need to make sure that all declarations from the specialization-base are instantiated, so they are returned.
713
//This requests all declarations, so they all will be instantiated and instances of them added into this context.
714
//DUContext::mergeDeclarationsInternal will then get them.
716
//Calling localDeclarations() instantiates all not yet instantiated member declarations
717
localDeclarations(source);
719
// kDebug() << "final count of local declarations:" << this->localDeclarations().count();
721
//Instantiate up-propagating child-contexts with the correct same instantiation-information
722
//This for examples makes unnamed enums accessible
723
InstantiationInformation inf;
724
inf.previousInstantiationInformation = m_instantiatedWith;
726
foreach(DUContext* child, m_instantiatedFrom->childContexts()) {
727
// kDebug() << "checking child-context" << child->isPropagateDeclarations();
729
if(child->isPropagateDeclarations())
730
static_cast<CppDUContext<BaseContext>*>(static_cast<CppDUContext<BaseContext>*>(child)->instantiate(inf, source))->mergeDeclarationsInternal(definitions, position, hadContexts, source, searchInParents, currentDepth);
734
BaseContext::mergeDeclarationsInternal(definitions, position, hadContexts, source, searchInParents, currentDepth);
737
CppDUContext<BaseContext>* m_instantiatedFrom;
739
///Every access to m_instatiations must be serialized through instatiationsMutex, because they may be written without a write-lock
740
QHash<IndexedInstantiationInformation, CppDUContext<BaseContext>* > m_instatiations;
741
IndexedInstantiationInformation m_instantiatedWith;
744
///Returns whether the given declaration depends on a missing template-parameter
745
bool isTemplateDependent(Declaration* decl);
746
bool isTemplateDependent(DUContext* context);