diff options
author | Przemyslaw Gorszkowski <pgorszkowski@gmail.com> | 2014-07-11 07:56:15 +0200 |
---|---|---|
committer | Przemyslaw Gorszkowski <pgorszkowski@gmail.com> | 2014-09-09 13:49:31 +0200 |
commit | c228b36ccf92f3a75d7687159d99da496cf5e241 (patch) | |
tree | a4222f1f5aa795903f6b16fd2a3d4fe2821b5c42 /src/libs/cplusplus/ResolveExpression.cpp | |
parent | bf0e0d80aa2cd8fc99c036f0a90c497cf7809520 (diff) | |
download | qt-creator-c228b36ccf92f3a75d7687159d99da496cf5e241.tar.gz |
C++: add support for resolving typedefs for template arguments
Example:
template <typename T>
struct Base { T t; };
struct Foo { int foo; };
void fun() {
typedef Foo TypedefedFoo;
Base<TypedefedFoo> baseFoo;
baseFoo.t.// no code completion
}
Change-Id: I4822693d3fa1ee2e9b0e4cdd28bb9a8d441fb313
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
Diffstat (limited to 'src/libs/cplusplus/ResolveExpression.cpp')
-rw-r--r-- | src/libs/cplusplus/ResolveExpression.cpp | 62 |
1 files changed, 57 insertions, 5 deletions
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 187f11f5f9..f270204a29 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -82,13 +82,46 @@ public: { QSet<Symbol *> visited; _binding = binding; - // Use a hard limit when trying to resolve typedefs. Typedefs in templates can refer to - // each other, each time enhancing the template argument and thus making it impossible to - // use an "alreadyResolved" container. FIXME: We might overcome this by resolving the - // template parameters. + // Use a hard limit when trying to resolve typedefs. + // TODO: Now that template arguments are resolved, use an 'alreadyResolved' container to + // handle recursive typedefs. unsigned maxDepth = 15; for (NamedType *namedTy = 0; maxDepth && (namedTy = getNamedType(*type)); --maxDepth) { - QList<LookupItem> namedTypeItems = getNamedTypeItems(namedTy->name(), *scope, _binding); + NamedType *orgNamedTy = namedTy; + const Name *name = namedTy->name(); + if (const QualifiedNameId *qn = name->asQualifiedNameId()) { + const Name *name = qn->name(); + Scope *templateScope = *scope; + if (const TemplateNameId *templateNameId = name->asTemplateNameId()) { + const TemplateNameId *resolvedTemplateNameId = + resolveTemplateParameters(templateNameId, templateScope, binding); + const QualifiedNameId *resolvedQualifiedNamedId = + _context.bindings()->control()->qualifiedNameId(qn->base(), + resolvedTemplateNameId); + namedTy = _context.bindings()->control()->namedType(resolvedQualifiedNamedId); + } + } else if (const TemplateNameId *templateNameId = name->asTemplateNameId()) { + Scope *templateScope = *scope; + const TemplateNameId *resolvedTemplateNameId = + resolveTemplateParameters(templateNameId, templateScope, binding); + namedTy = _context.bindings()->control()->namedType(resolvedTemplateNameId); + } + + if (namedTy != orgNamedTy) { + if ((*type)->isPointerType()) { + *type = FullySpecifiedType(_context.bindings()->control()->pointerType( + FullySpecifiedType(namedTy))); + } else if (ReferenceType *referenceType = (*type)->asReferenceType()) { + *type = FullySpecifiedType(_context.bindings()->control()->referenceType( + FullySpecifiedType(namedTy), + referenceType->isRvalueReference())); + } else { + *type = FullySpecifiedType(namedTy); + } + name = namedTy->name(); + } + + QList<LookupItem> namedTypeItems = getNamedTypeItems(name, *scope, _binding); if (Q_UNLIKELY(debug)) qDebug() << "-- we have" << namedTypeItems.size() << "candidates"; @@ -99,6 +132,25 @@ public: } private: + const TemplateNameId *resolveTemplateParameters(const TemplateNameId *templateNameId, + Scope *templateScope, + ClassOrNamespace *binding) + { + std::vector<FullySpecifiedType> resolvedTemplateArguments; + const unsigned templArgumentCount = templateNameId->templateArgumentCount(); + for (unsigned i = 0; i < templArgumentCount; ++i) { + FullySpecifiedType resolvedTemplateArgumentType + = templateNameId->templateArgumentAt(i); + resolve(&resolvedTemplateArgumentType, &templateScope, binding); + resolvedTemplateArguments.push_back(resolvedTemplateArgumentType); + } + + return _context.bindings()->control()->templateNameId(templateNameId->identifier(), + templateNameId->isSpecialization(), + &resolvedTemplateArguments[0], + templArgumentCount); + } + NamedType *getNamedType(FullySpecifiedType& type) const { NamedType *namedTy = type->asNamedType(); |