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:
Volodymyr Zibarov
2020-05-14 23:07:05 +03:00
parent be97943372
commit 9ee693ee22
43 changed files with 1198 additions and 58 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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