[clang] Fix CTAD not work for function-type and array-type arguments. (#78159)

Fixes https://github.com/llvm/llvm-project/issues/51710.

When transforming a constructor into a corresponding deduction guide,
the decayed types (function/array type) were not handled properly which
made clang fail to compile valid code. The patch teaches clang handle
these decayed type in the transformation.
This commit is contained in:
Haojian Wu 2024-01-16 09:54:36 +01:00 committed by GitHub
parent cd263a7ee0
commit f725bb960d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 8 deletions

View File

@ -748,6 +748,8 @@ Bug Fixes in This Version
- Fix an issue where clang cannot find conversion function with template
parameter when instantiation of template class.
Fixes (`#77583 <https://github.com/llvm/llvm-project/issues/77583>`_)
- Fix an issue where CTAD fails for function-type/array-type arguments.
Fixes (`#51710 <https://github.com/llvm/llvm-project/issues/51710>`_)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -2587,15 +2587,15 @@ private:
: ParamTy->isRValueReferenceType() ? VK_XValue
: VK_PRValue);
}
// Handle arrays and functions decay.
auto NewType = NewDI->getType();
if (NewType->isArrayType() || NewType->isFunctionType())
NewType = SemaRef.Context.getDecayedType(NewType);
ParmVarDecl *NewParam = ParmVarDecl::Create(SemaRef.Context, DC,
OldParam->getInnerLocStart(),
OldParam->getLocation(),
OldParam->getIdentifier(),
NewDI->getType(),
NewDI,
OldParam->getStorageClass(),
NewDefArg.get());
ParmVarDecl *NewParam = ParmVarDecl::Create(
SemaRef.Context, DC, OldParam->getInnerLocStart(),
OldParam->getLocation(), OldParam->getIdentifier(), NewType, NewDI,
OldParam->getStorageClass(), NewDefArg.get());
NewParam->setScopeInfo(OldParam->getFunctionScopeDepth(),
OldParam->getFunctionScopeIndex());
SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);

View File

@ -645,4 +645,37 @@ namespace undefined_warnings {
auto test2 = TemplDObj(.0f);
}
}
namespace GH51710 {
template<typename T>
struct A {
A(T f()) {}
A(int f(), T) {}
A(T array[10]) {}
A(int array[10], T) {}
};
template<typename T>
struct B {
B(T array[]) {}
B(int array[], T) {}
};
int foo();
void bar() {
A test1(foo);
A test2(foo, 1);
int array[10];
A test3(array);
A test4(array, 1);
B test5(array);
B test6(array, 1);
}
} // namespace GH51710
#endif