forked from qt-creator/qt-creator
C++: fix built-in code model to work with shared_ptr on MSVC 2017
These changes target Find Usages feature to work with shared_ptr. Improve libs/3rdparty/cplusplus and plugins/cplusplus: parse __declspec() attribute, call to variadic function template without specified template arguments, if constexpr, c++11 attributes [[value]], function templates with default parameters, resolve order for function vs template with default parameter, template operator->() with default arguments, template specialization with numeric values, find best partial specialization, fix partial specialization for non-first specialized argument Fixes: QTCREATORBUG-7866 Fixes: QTCREATORBUG-20781 Fixes: QTCREATORBUG-22857 Fixes: QTCREATORBUG-17825 Change-Id: I31a080f7729edfb2ee9650f1aff48daeba5a673b Reviewed-by: Christian Kandeler <christian.kandeler@qt.io> Reviewed-by: Nikolai Kosjar <pinaceae.pinus@gmail.com>
This commit is contained in:
@@ -257,9 +257,9 @@ public:
|
||||
|
||||
void visit(const TemplateNameId *name) override
|
||||
{
|
||||
QVarLengthArray<FullySpecifiedType, 8> args(name->templateArgumentCount());
|
||||
QVarLengthArray<TemplateArgument, 8> args(name->templateArgumentCount());
|
||||
for (int i = 0; i < name->templateArgumentCount(); ++i)
|
||||
args[i] = rewrite->rewriteType(name->templateArgumentAt(i));
|
||||
args[i] = rewrite->rewriteType(name->templateArgumentAt(i).type());
|
||||
temps.append(control()->templateNameId(identifier(name->identifier()), name->isSpecialization(),
|
||||
args.data(), args.size()));
|
||||
}
|
||||
|
||||
@@ -242,9 +242,9 @@ private:
|
||||
|
||||
void visit(const TemplateNameId *name) override
|
||||
{
|
||||
QVarLengthArray<FullySpecifiedType, 8> arguments(name->templateArgumentCount());
|
||||
QVarLengthArray<TemplateArgument, 8> arguments(name->templateArgumentCount());
|
||||
for (int i = 0; i < name->templateArgumentCount(); ++i) {
|
||||
FullySpecifiedType argTy = name->templateArgumentAt(i);
|
||||
FullySpecifiedType argTy = name->templateArgumentAt(i).type();
|
||||
arguments[i] = q->apply(argTy);
|
||||
}
|
||||
|
||||
@@ -265,10 +265,10 @@ private:
|
||||
return id;
|
||||
|
||||
} else if (const TemplateNameId *templId = name->asTemplateNameId()) {
|
||||
QVarLengthArray<FullySpecifiedType, 8> arguments(templId->templateArgumentCount());
|
||||
QVarLengthArray<TemplateArgument, 8> arguments(templId->templateArgumentCount());
|
||||
for (int templateArgIndex = 0; templateArgIndex < templId->templateArgumentCount();
|
||||
++templateArgIndex) {
|
||||
FullySpecifiedType argTy = templId->templateArgumentAt(templateArgIndex);
|
||||
FullySpecifiedType argTy = templId->templateArgumentAt(templateArgIndex).type();
|
||||
arguments[templateArgIndex] = q->apply(argTy);
|
||||
}
|
||||
const Identifier *id = control()->identifier(templId->identifier()->chars(),
|
||||
@@ -404,7 +404,7 @@ FullySpecifiedType DeprecatedGenTemplateInstance::instantiate(const Name *classN
|
||||
DeprecatedGenTemplateInstance::Substitution subst;
|
||||
|
||||
for (int i = 0; i < templId->templateArgumentCount(); ++i) {
|
||||
FullySpecifiedType templArgTy = templId->templateArgumentAt(i);
|
||||
FullySpecifiedType templArgTy = templId->templateArgumentAt(i).type();
|
||||
|
||||
if (i < templ->templateParameterCount()) {
|
||||
const Name *templArgName = templ->templateParameterAt(i)->name();
|
||||
|
||||
@@ -1978,6 +1978,22 @@ bool FindUsages::visit(GnuAttributeSpecifierAST *ast)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FindUsages::visit(MsvcDeclspecSpecifierAST *ast)
|
||||
{
|
||||
for (GnuAttributeListAST *it = ast->attribute_list; it; it = it->next) {
|
||||
this->attribute(it->value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FindUsages::visit(StdAttributeSpecifierAST *ast)
|
||||
{
|
||||
for (GnuAttributeListAST *it = ast->attribute_list; it; it = it->next) {
|
||||
this->attribute(it->value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FindUsages::visit(TypeofSpecifierAST *ast)
|
||||
{
|
||||
// unsigned typeof_token = ast->typeof_token;
|
||||
|
||||
@@ -254,6 +254,8 @@ protected:
|
||||
// SpecifierAST
|
||||
virtual bool visit(SimpleSpecifierAST *ast);
|
||||
virtual bool visit(GnuAttributeSpecifierAST *ast);
|
||||
virtual bool visit(MsvcDeclspecSpecifierAST *ast);
|
||||
virtual bool visit(StdAttributeSpecifierAST *ast);
|
||||
virtual bool visit(TypeofSpecifierAST *ast);
|
||||
virtual bool visit(DecltypeSpecifierAST *ast);
|
||||
virtual bool visit(ClassSpecifierAST *ast);
|
||||
|
||||
@@ -773,6 +773,10 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
|
||||
LookupItem item;
|
||||
item.setDeclaration(s);
|
||||
item.setBinding(binding);
|
||||
|
||||
if (Symbol *inst = instantiateTemplateFunction(name, s->asTemplate()))
|
||||
item.setType(inst->type());
|
||||
|
||||
result->append(item);
|
||||
}
|
||||
|
||||
@@ -811,15 +815,8 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
|
||||
item.setType(ty); // override the type.
|
||||
}
|
||||
|
||||
// instantiate function template
|
||||
if (name->isTemplateNameId() && s->isTemplate() && s->asTemplate()->declaration()
|
||||
&& s->asTemplate()->declaration()->isFunction()) {
|
||||
const TemplateNameId *instantiation = name->asTemplateNameId();
|
||||
Template *specialization = s->asTemplate();
|
||||
Symbol *instantiatedFunctionTemplate = instantiateTemplateFunction(instantiation,
|
||||
specialization);
|
||||
item.setType(instantiatedFunctionTemplate->type()); // override the type.
|
||||
}
|
||||
if (Symbol *inst = instantiateTemplateFunction(name, s->asTemplate()))
|
||||
item.setType(inst->type());
|
||||
|
||||
result->append(item);
|
||||
}
|
||||
@@ -1026,22 +1023,22 @@ ClassOrNamespace *ClassOrNamespace::findSpecialization(const TemplateNameId *tem
|
||||
// and initialization(in future it should be more clever)
|
||||
if (specializationTemplateArgumentCount == initializationTemplateArgumentCount) {
|
||||
for (int i = 0; i < initializationTemplateArgumentCount; ++i) {
|
||||
const FullySpecifiedType &specializationTemplateArgument
|
||||
const TemplateArgument &specializationTemplateArgument
|
||||
= specializationNameId->templateArgumentAt(i);
|
||||
const FullySpecifiedType &initializationTemplateArgument
|
||||
const TemplateArgument &initializationTemplateArgument
|
||||
= templId->templateArgumentAt(i);
|
||||
PointerType *specPointer
|
||||
= specializationTemplateArgument.type()->asPointerType();
|
||||
= specializationTemplateArgument.type().type()->asPointerType();
|
||||
// specialization and initialization argument have to be a pointer
|
||||
// additionally type of pointer argument of specialization has to be namedType
|
||||
if (specPointer && initializationTemplateArgument.type()->isPointerType()
|
||||
if (specPointer && initializationTemplateArgument.type().type()->isPointerType()
|
||||
&& specPointer->elementType().type()->isNamedType()) {
|
||||
return cit->second;
|
||||
}
|
||||
|
||||
ArrayType *specArray
|
||||
= specializationTemplateArgument.type()->asArrayType();
|
||||
if (specArray && initializationTemplateArgument.type()->isArrayType()) {
|
||||
= specializationTemplateArgument.type().type()->asArrayType();
|
||||
if (specArray && initializationTemplateArgument.type().type()->isArrayType()) {
|
||||
if (const NamedType *argumentNamedType
|
||||
= specArray->elementType().type()->asNamedType()) {
|
||||
if (const Name *argumentName = argumentNamedType->name()) {
|
||||
@@ -1142,7 +1139,33 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name,
|
||||
= findSpecialization(templId, specializations);
|
||||
if (specializationWithPointer)
|
||||
reference = specializationWithPointer;
|
||||
// TODO: find the best specialization(probably partial) for this instantiation
|
||||
|
||||
int maximumArgumentsMatched = 0;
|
||||
|
||||
for (const std::pair<const TemplateNameId *, ClassOrNamespace *> &p :
|
||||
specializations) {
|
||||
const TemplateNameId *templateSpecialization = p.first;
|
||||
ClassOrNamespace *specializationClassOrNamespace = p.second;
|
||||
|
||||
const int argumentCountOfInitialization = templId->templateArgumentCount();
|
||||
const int argumentCountOfSpecialization =
|
||||
templateSpecialization->templateArgumentCount();
|
||||
|
||||
int argumentsMatched = 0;
|
||||
for (int i = 0;
|
||||
i < argumentCountOfInitialization && i < argumentCountOfSpecialization;
|
||||
++i) {
|
||||
if (templId->templateArgumentAt(i) ==
|
||||
templateSpecialization->templateArgumentAt(i)) {
|
||||
argumentsMatched++;
|
||||
}
|
||||
}
|
||||
|
||||
if (argumentsMatched > maximumArgumentsMatched) {
|
||||
reference = specializationClassOrNamespace;
|
||||
maximumArgumentsMatched = argumentsMatched;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1227,12 +1250,39 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name,
|
||||
if (!name)
|
||||
continue;
|
||||
|
||||
FullySpecifiedType ty = (i < argumentCountOfInitialization) ?
|
||||
templId->templateArgumentAt(i):
|
||||
int argumentPositionInReferenceClass=i;
|
||||
|
||||
if (referenceClass->name() && referenceClass->name()->asTemplateNameId()) {
|
||||
argumentPositionInReferenceClass=-1;
|
||||
const TemplateNameId* refTemp = referenceClass->name()->asTemplateNameId();
|
||||
for (int argPos=0; argPos < refTemp->templateArgumentCount(); argPos++) {
|
||||
const Type* argType = refTemp->templateArgumentAt(argPos).type().type();
|
||||
if (argType->asNamedType()
|
||||
&& argType->asNamedType()->name() == name) {
|
||||
argumentPositionInReferenceClass = argPos;
|
||||
break;
|
||||
}
|
||||
if (argType->asPointerType()
|
||||
&& argType->asPointerType()->elementType().type()->asNamedType()
|
||||
&& argType->asPointerType()->elementType().type()
|
||||
->asNamedType()->name() == name) {
|
||||
argumentPositionInReferenceClass = argPos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (argumentPositionInReferenceClass < 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FullySpecifiedType ty = (argumentPositionInReferenceClass < argumentCountOfInitialization) ?
|
||||
templId->templateArgumentAt(argumentPositionInReferenceClass).type():
|
||||
cloner.type(tParam->type(), &subst);
|
||||
|
||||
if (i < templSpecArgumentCount
|
||||
&& templSpecId->templateArgumentAt(i)->isPointerType()) {
|
||||
&& templSpecId->templateArgumentAt(i).type()->isPointerType()) {
|
||||
if (PointerType *pointerType = ty->asPointerType())
|
||||
ty = pointerType->elementType();
|
||||
}
|
||||
@@ -1281,7 +1331,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name,
|
||||
const int parameterIndex = templParams.value(nameId);
|
||||
if (parameterIndex < argumentCountOfInitialization) {
|
||||
const FullySpecifiedType &fullType =
|
||||
templId->templateArgumentAt(parameterIndex);
|
||||
templId->templateArgumentAt(parameterIndex).type();
|
||||
if (fullType.isValid()) {
|
||||
if (NamedType *namedType = fullType.type()->asNamedType())
|
||||
baseBinding = lookupType(namedType->name());
|
||||
@@ -1300,7 +1350,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name,
|
||||
for (int i = 0; i < argumentCountOfSpecialization; ++i) {
|
||||
const Name *name = templateSpecialization->templateParameterAt(i)->name();
|
||||
FullySpecifiedType ty = (i < argumentCountOfInitialization) ?
|
||||
templId->templateArgumentAt(i):
|
||||
templId->templateArgumentAt(i).type():
|
||||
templateSpecialization->templateParameterAt(i)->type();
|
||||
|
||||
map.bind(name, ty);
|
||||
@@ -1927,10 +1977,28 @@ bool CreateBindings::visit(ObjCMethod *)
|
||||
return false;
|
||||
}
|
||||
|
||||
Symbol *CreateBindings::instantiateTemplateFunction(const TemplateNameId *instantiation,
|
||||
Symbol *CreateBindings::instantiateTemplateFunction(const Name *instantiationName,
|
||||
Template *specialization) const
|
||||
{
|
||||
const int argumentCountOfInitialization = instantiation->templateArgumentCount();
|
||||
if (!specialization || !specialization->declaration()
|
||||
|| !specialization->declaration()->isFunction())
|
||||
return nullptr;
|
||||
|
||||
int argumentCountOfInstantiation = 0;
|
||||
const TemplateNameId *instantiation = nullptr;
|
||||
if (instantiationName->isTemplateNameId()) {
|
||||
instantiation = instantiationName->asTemplateNameId();
|
||||
argumentCountOfInstantiation = instantiation->templateArgumentCount();
|
||||
} else {
|
||||
// no template arguments passed in function call
|
||||
// check if all template parameters have default arguments (only check first parameter)
|
||||
if (specialization->templateParameterCount() == 0)
|
||||
return nullptr;
|
||||
TypenameArgument *parameter = specialization->templateParameterAt(0)->asTypenameArgument();
|
||||
if (!parameter || !parameter->type().isValid())
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const int argumentCountOfSpecialization = specialization->templateParameterCount();
|
||||
|
||||
Clone cloner(_control.data());
|
||||
@@ -1944,8 +2012,8 @@ Symbol *CreateBindings::instantiateTemplateFunction(const TemplateNameId *instan
|
||||
if (!name)
|
||||
continue;
|
||||
|
||||
FullySpecifiedType ty = (i < argumentCountOfInitialization) ?
|
||||
instantiation->templateArgumentAt(i):
|
||||
FullySpecifiedType ty = (i < argumentCountOfInstantiation) ?
|
||||
instantiation->templateArgumentAt(i).type():
|
||||
cloner.type(tParam->type(), &subst);
|
||||
|
||||
subst.bind(cloner.name(name, &subst), ty);
|
||||
|
||||
@@ -266,7 +266,7 @@ protected:
|
||||
virtual bool visit(ObjCMethod *);
|
||||
|
||||
private:
|
||||
Symbol *instantiateTemplateFunction(const TemplateNameId *instantiation,
|
||||
Symbol *instantiateTemplateFunction(const Name *instantiationName,
|
||||
Template *specialization) const;
|
||||
|
||||
Snapshot _snapshot;
|
||||
|
||||
@@ -80,7 +80,7 @@ void NamePrettyPrinter::visit(const TemplateNameId *name)
|
||||
if (index != 0)
|
||||
_name += QLatin1String(", ");
|
||||
|
||||
FullySpecifiedType argTy = name->templateArgumentAt(index);
|
||||
FullySpecifiedType argTy = name->templateArgumentAt(index).type();
|
||||
QString arg = overview()->prettyType(argTy);
|
||||
if (arg.isEmpty())
|
||||
_name += QString::fromLatin1("_Tp%1").arg(index + 1);
|
||||
|
||||
@@ -918,6 +918,13 @@ bool ResolveExpression::visit(CallAST *ast)
|
||||
}
|
||||
}
|
||||
|
||||
if (_results.size()>1){
|
||||
// move functions with known bindings to begin of results list
|
||||
std::stable_partition(_results.begin(), _results.end(), [](const LookupItem &item) -> bool {
|
||||
return item.binding();
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1109,11 +1116,23 @@ ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &bas
|
||||
continue;
|
||||
Scope *functionScope = overload->enclosingScope();
|
||||
|
||||
if (overload->type()->isFunctionType()) {
|
||||
FullySpecifiedType overloadType = r.type();
|
||||
if (! overloadType.isValid())
|
||||
overloadType = overload->type();
|
||||
|
||||
Function *instantiatedFunction = nullptr;
|
||||
|
||||
if (overloadType->isFunctionType()) {
|
||||
FullySpecifiedType overloadTy
|
||||
= instantiate(binding->templateId(), overload);
|
||||
Function *instantiatedFunction = overloadTy->asFunctionType();
|
||||
Q_ASSERT(instantiatedFunction != nullptr);
|
||||
instantiatedFunction = overloadTy->asFunctionType();
|
||||
} else if (overloadType->isTemplateType()
|
||||
&& overloadType->asTemplateType()->declaration()
|
||||
&& overloadType->asTemplateType()->declaration()->isFunction()) {
|
||||
instantiatedFunction = overloadType->asTemplateType()->declaration()->asFunction();
|
||||
}
|
||||
|
||||
if (instantiatedFunction != nullptr) {
|
||||
|
||||
FullySpecifiedType retTy
|
||||
= instantiatedFunction->returnType().simplified();
|
||||
|
||||
Reference in New Issue
Block a user