Merge remote-tracking branch 'origin/2.6'

This commit is contained in:
Eike Ziller
2012-08-23 15:52:15 +02:00
530 changed files with 9207 additions and 33307 deletions

View File

@@ -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)
{ }

View File

@@ -54,7 +54,6 @@ private:
FullySpecifiedType gen(Symbol *symbol);
private:
Symbol *_symbol;
QSharedPointer<Control> _control;
const Substitution _substitution;
};

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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())

View File

@@ -405,7 +405,7 @@ void TypePrettyPrinter::prependWordSeparatorSpace()
const QChar ch = _text.at(0);
if (ch.isLetterOrNumber())
if (ch.isLetterOrNumber() || ch == QLatin1Char('_'))
_text.prepend(" ");
}

View File

@@ -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)

View File

@@ -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);
}
}