forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/2.6'
This commit is contained in:
@@ -387,8 +387,7 @@ FullySpecifiedType ApplySubstitution::applySubstitution(int index) const
|
||||
} // end of anonymous namespace
|
||||
|
||||
DeprecatedGenTemplateInstance::DeprecatedGenTemplateInstance(QSharedPointer<Control> control, const Substitution &substitution)
|
||||
: _symbol(0),
|
||||
_control(control),
|
||||
: _control(control),
|
||||
_substitution(substitution)
|
||||
{ }
|
||||
|
||||
|
||||
@@ -54,7 +54,6 @@ private:
|
||||
FullySpecifiedType gen(Symbol *symbol);
|
||||
|
||||
private:
|
||||
Symbol *_symbol;
|
||||
QSharedPointer<Control> _control;
|
||||
const Substitution _substitution;
|
||||
};
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "ResolveExpression.h"
|
||||
#include "Overview.h"
|
||||
#include "DeprecatedGenTemplateInstance.h"
|
||||
#include "CppRewriter.h"
|
||||
|
||||
#include <CoreTypes.h>
|
||||
#include <Symbols.h>
|
||||
@@ -382,9 +383,6 @@ QList<Enum *> ClassOrNamespace::enums() const
|
||||
|
||||
QList<Symbol *> ClassOrNamespace::symbols() const
|
||||
{
|
||||
if (_templateId && ! _usings.isEmpty())
|
||||
return _usings.first()->symbols(); // ask to the base implementation
|
||||
|
||||
const_cast<ClassOrNamespace *>(this)->flush();
|
||||
return _symbols;
|
||||
}
|
||||
@@ -418,6 +416,8 @@ QList<LookupItem> ClassOrNamespace::lookup_helper(const Name *name, bool searchI
|
||||
QList<LookupItem> result;
|
||||
|
||||
if (name) {
|
||||
QSet<ClassOrNamespace *> processed;
|
||||
|
||||
if (const QualifiedNameId *q = name->asQualifiedNameId()) {
|
||||
if (! q->base())
|
||||
result = globalNamespace()->find(q->name());
|
||||
@@ -425,10 +425,11 @@ QList<LookupItem> ClassOrNamespace::lookup_helper(const Name *name, bool searchI
|
||||
else if (ClassOrNamespace *binding = lookupType(q->base()))
|
||||
result = binding->find(q->name());
|
||||
|
||||
lookup_helper(name, this, &result, &processed, /*templateId = */ 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QSet<ClassOrNamespace *> processed;
|
||||
ClassOrNamespace *binding = this;
|
||||
do {
|
||||
lookup_helper(name, binding, &result, &processed, /*templateId = */ 0);
|
||||
@@ -608,7 +609,7 @@ ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespace *origin) const
|
||||
ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespace *origin)
|
||||
{
|
||||
Q_ASSERT(name != 0);
|
||||
Q_ASSERT(name->isNameId() || name->isTemplateNameId());
|
||||
@@ -616,21 +617,131 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac
|
||||
const_cast<ClassOrNamespace *>(this)->flush();
|
||||
|
||||
Table::const_iterator it = _classOrNamespaces.find(name);
|
||||
|
||||
if (it == _classOrNamespaces.end())
|
||||
return 0;
|
||||
|
||||
ClassOrNamespace *c = it->second;
|
||||
ClassOrNamespace *reference = it->second;
|
||||
|
||||
if (const TemplateNameId *templId = name->asTemplateNameId()) {
|
||||
ClassOrNamespace *i = _factory->allocClassOrNamespace(c);
|
||||
i->_templateId = templId;
|
||||
i->_instantiationOrigin = origin;
|
||||
i->_usings.append(c);
|
||||
return i;
|
||||
// The reference binding might still be missing some of its base classes in the case they
|
||||
// are templates. We need to collect them now. First, we track the bases which are already
|
||||
// part of the binding so we can identify the missings ones later.
|
||||
|
||||
QSet<const Name *> knownBases;
|
||||
foreach (ClassOrNamespace *con, reference->usings()) {
|
||||
foreach (Symbol *s, con->symbols()) {
|
||||
if (Class *c = s->asClass()) {
|
||||
knownBases.insert(c->name());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
Class *referenceClass = 0;
|
||||
QList<const Name *> missingBases;
|
||||
foreach (Symbol *s, reference->symbols()) {
|
||||
if (Class *clazz = s->asClass()) {
|
||||
for (unsigned i = 0; i < clazz->baseClassCount(); ++i) {
|
||||
BaseClass *baseClass = clazz->baseClassAt(i);
|
||||
if (baseClass->name() && !knownBases.contains(baseClass->name()))
|
||||
missingBases.append(baseClass->name());
|
||||
}
|
||||
referenceClass = clazz;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!referenceClass)
|
||||
return reference;
|
||||
|
||||
// If we are dealling with a template type, more work is required, since we need to
|
||||
// construct all instantiation data.
|
||||
if (const TemplateNameId *templId = name->asTemplateNameId()) {
|
||||
ClassOrNamespace *instantiation = _factory->allocClassOrNamespace(reference);
|
||||
instantiation->_templateId = templId;
|
||||
instantiation->_instantiationOrigin = origin;
|
||||
|
||||
// The instantiation should have all symbols, enums, and usings from the reference.
|
||||
instantiation->_symbols.append(reference->symbols());
|
||||
instantiation->_enums.append(reference->enums());
|
||||
instantiation->_usings.append(reference->usings());
|
||||
|
||||
// It gets a bit complicated if the reference is actually a class template because we
|
||||
// now must worry about dependent names in base classes.
|
||||
if (Template *templ = referenceClass->enclosingTemplate()) {
|
||||
QHash<const Name*, unsigned> templParams;
|
||||
for (unsigned i = 0; i < templ->templateParameterCount(); ++i)
|
||||
templParams.insert(templ->templateParameterAt(i)->name(), i);
|
||||
|
||||
foreach (const Name *baseName, missingBases) {
|
||||
ClassOrNamespace *baseBinding = 0;
|
||||
|
||||
if (const Identifier *nameId = baseName->asNameId()) {
|
||||
// This is the simple case in which a template parameter is itself a base.
|
||||
// Ex.: template <class T> class A : public T {};
|
||||
if (templParams.contains(nameId)) {
|
||||
const FullySpecifiedType &fullType =
|
||||
templId->templateArgumentAt(templParams.value(nameId));
|
||||
if (NamedType *namedType = fullType.type()->asNamedType())
|
||||
baseBinding = lookupType(namedType->name());
|
||||
}
|
||||
} else {
|
||||
SubstitutionMap map;
|
||||
for (unsigned i = 0;
|
||||
i < templ->templateParameterCount() && i < templId->templateArgumentCount();
|
||||
++i) {
|
||||
map.bind(templ->templateParameterAt(i)->name(),
|
||||
templId->templateArgumentAt(i));
|
||||
}
|
||||
SubstitutionEnvironment env;
|
||||
env.enter(&map);
|
||||
|
||||
baseName = rewriteName(baseName, &env, _control.data());
|
||||
|
||||
if (const TemplateNameId *baseTemplId = baseName->asTemplateNameId()) {
|
||||
// Another template that uses the dependent name.
|
||||
// Ex.: template <class T> class A : public B<T> {};
|
||||
if (baseTemplId->identifier() != templId->identifier())
|
||||
baseBinding = nestedType(baseName, origin);
|
||||
} else if (const QualifiedNameId *qBaseName = baseName->asQualifiedNameId()) {
|
||||
// Qualified names in general.
|
||||
// Ex.: template <class T> class A : public B<T>::Type {};
|
||||
ClassOrNamespace *binding = this;
|
||||
if (const Name *qualification = qBaseName->base())
|
||||
binding = lookupType(qualification);
|
||||
baseName = qBaseName->name();
|
||||
|
||||
if (binding)
|
||||
baseBinding = binding->lookupType(baseName);
|
||||
}
|
||||
}
|
||||
|
||||
if (baseBinding)
|
||||
instantiation->addUsing(baseBinding);
|
||||
}
|
||||
}
|
||||
|
||||
return instantiation;
|
||||
}
|
||||
|
||||
// Find the missing bases for regular (non-template) types.
|
||||
// Ex.: class A : public B<Some>::Type {};
|
||||
foreach (const Name *baseName, missingBases) {
|
||||
ClassOrNamespace *binding = this;
|
||||
if (const QualifiedNameId *qBaseName = baseName->asQualifiedNameId()) {
|
||||
if (const Name *qualification = qBaseName->base())
|
||||
binding = lookupType(qualification);
|
||||
baseName = qBaseName->name();
|
||||
}
|
||||
|
||||
if (binding) {
|
||||
ClassOrNamespace * baseBinding = binding->lookupType(baseName);
|
||||
if (baseBinding)
|
||||
reference->addUsing(baseBinding);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return reference;
|
||||
}
|
||||
|
||||
void ClassOrNamespace::flush()
|
||||
@@ -761,6 +872,7 @@ QSharedPointer<Control> CreateBindings::control() const
|
||||
ClassOrNamespace *CreateBindings::allocClassOrNamespace(ClassOrNamespace *parent)
|
||||
{
|
||||
ClassOrNamespace *e = new ClassOrNamespace(this, parent);
|
||||
e->_control = control();
|
||||
_entities.append(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ private:
|
||||
ClassOrNamespace *lookupType_helper(const Name *name, QSet<ClassOrNamespace *> *processed,
|
||||
bool searchInEnclosingScope, ClassOrNamespace *origin);
|
||||
|
||||
ClassOrNamespace *nestedType(const Name *name, ClassOrNamespace *origin) const;
|
||||
ClassOrNamespace *nestedType(const Name *name, ClassOrNamespace *origin);
|
||||
|
||||
private:
|
||||
struct CompareName: std::binary_function<const Name *, const Name *, bool> {
|
||||
@@ -106,6 +106,7 @@ private:
|
||||
Table _classOrNamespaces;
|
||||
QList<Enum *> _enums;
|
||||
QList<Symbol *> _todo;
|
||||
QSharedPointer<Control> _control;
|
||||
|
||||
// it's an instantiation.
|
||||
const TemplateNameId *_templateId;
|
||||
|
||||
@@ -76,6 +76,10 @@ QModelIndex OverviewModel::index(int row, int column, const QModelIndex &parent)
|
||||
Symbol *parentSymbol = static_cast<Symbol *>(parent.internalPointer());
|
||||
Q_ASSERT(parentSymbol);
|
||||
|
||||
if (Template *t = parentSymbol->asTemplate())
|
||||
if (Symbol *templateParentSymbol = t->declaration())
|
||||
parentSymbol = templateParentSymbol;
|
||||
|
||||
Scope *scope = parentSymbol->asScope();
|
||||
Q_ASSERT(scope != 0);
|
||||
return createIndex(row, 0, scope->memberAt(row));
|
||||
@@ -89,6 +93,8 @@ QModelIndex OverviewModel::parent(const QModelIndex &child) const
|
||||
return QModelIndex();
|
||||
|
||||
if (Scope *scope = symbol->enclosingScope()) {
|
||||
if (scope->isTemplate() && scope->enclosingScope())
|
||||
scope = scope->enclosingScope();
|
||||
if (scope->enclosingScope()) {
|
||||
QModelIndex index;
|
||||
if (scope->enclosingScope() && scope->enclosingScope()->enclosingScope()) // the parent doesn't have a parent
|
||||
@@ -113,6 +119,10 @@ int OverviewModel::rowCount(const QModelIndex &parent) const
|
||||
Symbol *parentSymbol = static_cast<Symbol *>(parent.internalPointer());
|
||||
Q_ASSERT(parentSymbol);
|
||||
|
||||
if (Template *t = parentSymbol->asTemplate())
|
||||
if (Symbol *templateParentSymbol = t->declaration())
|
||||
parentSymbol = templateParentSymbol;
|
||||
|
||||
if (Scope *parentScope = parentSymbol->asScope()) {
|
||||
if (!parentScope->isFunction() && !parentScope->isObjCMethod()) {
|
||||
return parentScope->memberCount();
|
||||
@@ -168,6 +178,14 @@ QVariant OverviewModel::data(const QModelIndex &index, int role) const
|
||||
}
|
||||
if (symbol->isObjCPropertyDeclaration())
|
||||
name = QLatin1String("@property ") + name;
|
||||
if (Template *t = symbol->asTemplate())
|
||||
if (Symbol *templateDeclaration = t->declaration()) {
|
||||
QStringList parameters;
|
||||
for (unsigned i = 0; i < t->templateParameterCount(); ++i)
|
||||
parameters.append(_overview.prettyName(t->templateParameterAt(i)->name()));
|
||||
name += QLatin1Char('<') + parameters.join(QLatin1String(", ")) + QLatin1Char('>');
|
||||
symbol = templateDeclaration;
|
||||
}
|
||||
if (symbol->isObjCMethod()) {
|
||||
ObjCMethod *method = symbol->asObjCMethod();
|
||||
if (method->isStatic())
|
||||
|
||||
@@ -405,7 +405,7 @@ void TypePrettyPrinter::prependWordSeparatorSpace()
|
||||
|
||||
const QChar ch = _text.at(0);
|
||||
|
||||
if (ch.isLetterOrNumber())
|
||||
if (ch.isLetterOrNumber() || ch == QLatin1Char('_'))
|
||||
_text.prepend(" ");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
INCLUDEPATH +=$$IDE_SOURCE_TREE/src/libs/3rdparty $$IDE_SOURCE_TREE/src/libs/3rdparty/cplusplus
|
||||
INCLUDEPATH += $$PWD
|
||||
INCLUDEPATH *= $$IDE_SOURCE_TREE/src/libs/3rdparty
|
||||
INCLUDEPATH *= $$IDE_SOURCE_TREE/src/libs/3rdparty/cplusplus
|
||||
INCLUDEPATH *= $$PWD
|
||||
LIBS *= -l$$qtLibraryName(CPlusPlus)
|
||||
|
||||
@@ -1137,9 +1137,9 @@ void Preprocessor::trackExpansionCycles(PPToken *tk)
|
||||
}
|
||||
}
|
||||
|
||||
static void adjustForCommentNewlines(unsigned *currentLine, const PPToken &tk)
|
||||
static void adjustForCommentOrStringNewlines(unsigned *currentLine, const PPToken &tk)
|
||||
{
|
||||
if (tk.is(T_COMMENT) || tk.is(T_DOXY_COMMENT))
|
||||
if (tk.is(T_COMMENT) || tk.is(T_DOXY_COMMENT) || tk.isStringLiteral())
|
||||
(*currentLine) += tk.asByteArrayRef().count('\n');
|
||||
}
|
||||
|
||||
@@ -1147,7 +1147,7 @@ void Preprocessor::synchronizeOutputLines(const PPToken &tk, bool forceLine)
|
||||
{
|
||||
if (m_state.m_expansionStatus != NotExpanding
|
||||
|| (!forceLine && m_env->currentLine == tk.lineno)) {
|
||||
adjustForCommentNewlines(&m_env->currentLine, tk);
|
||||
adjustForCommentOrStringNewlines(&m_env->currentLine, tk);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1164,7 +1164,7 @@ void Preprocessor::synchronizeOutputLines(const PPToken &tk, bool forceLine)
|
||||
}
|
||||
|
||||
m_env->currentLine = tk.lineno;
|
||||
adjustForCommentNewlines(&m_env->currentLine, tk);
|
||||
adjustForCommentOrStringNewlines(&m_env->currentLine, tk);
|
||||
}
|
||||
|
||||
void Preprocessor::removeTrailingOutputLines()
|
||||
@@ -1349,7 +1349,21 @@ void Preprocessor::scanActualArgument(PPToken *tk, QVector<PPToken> *tokens)
|
||||
break;
|
||||
}
|
||||
|
||||
tokens->append(*tk);
|
||||
if (m_keepComments
|
||||
&& (tk->is(T_CPP_COMMENT) || tk->is(T_CPP_DOXY_COMMENT))) {
|
||||
// Even in keep comments mode, we cannot preserve C++ style comments inside the
|
||||
// expansion. We stick with GCC's approach which is to replace them by C style
|
||||
// comments (currently clang just gets rid of them) and transform internals */
|
||||
// into *|.
|
||||
QByteArray text = m_state.m_source.mid(tk->begin() + 2, tk->end() - tk->begin() - 2);
|
||||
const QByteArray &comment = "/*" + text.replace("*/", "*|") + "*/";
|
||||
tokens->append(generateToken(T_COMMENT,
|
||||
comment.constData(), comment.size(),
|
||||
tk->lineno, false));
|
||||
} else {
|
||||
tokens->append(*tk);
|
||||
}
|
||||
|
||||
lex(tk);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user