зеркало из https://github.com/microsoft/clang-1.git
PR15757: When we instantiate an inheriting constructor template, also
instantiate the inherited constructor template and mark that as the constructor which the instantiated specialization is inheriting. This fixes a crash-on-valid when trying to compute the exception specification of a specialization of the inheriting constructor. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@182072 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
50fa64d441
Коммит
b5eb3f5bf3
|
@ -94,17 +94,23 @@ namespace clang {
|
|||
/// \brief Add a new outermost level to the multi-level template argument
|
||||
/// list.
|
||||
void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) {
|
||||
TemplateArgumentLists.push_back(ArgList(TemplateArgs->data(),
|
||||
TemplateArgs->size()));
|
||||
addOuterTemplateArguments(ArgList(TemplateArgs->data(),
|
||||
TemplateArgs->size()));
|
||||
}
|
||||
|
||||
/// \brief Add a new outmost level to the multi-level template argument
|
||||
/// list.
|
||||
void addOuterTemplateArguments(const TemplateArgument *Args,
|
||||
unsigned NumArgs) {
|
||||
TemplateArgumentLists.push_back(ArgList(Args, NumArgs));
|
||||
addOuterTemplateArguments(ArgList(Args, NumArgs));
|
||||
}
|
||||
|
||||
|
||||
/// \brief Add a new outmost level to the multi-level template argument
|
||||
/// list.
|
||||
void addOuterTemplateArguments(ArgList Args) {
|
||||
TemplateArgumentLists.push_back(Args);
|
||||
}
|
||||
|
||||
/// \brief Retrieve the innermost template argument list.
|
||||
const ArgList &getInnermost() const {
|
||||
return TemplateArgumentLists.front();
|
||||
|
|
|
@ -1558,10 +1558,36 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
|
|||
Constructor->isExplicit(),
|
||||
Constructor->isInlineSpecified(),
|
||||
false, Constructor->isConstexpr());
|
||||
|
||||
// Claim that the instantiation of a constructor or constructor template
|
||||
// inherits the same constructor that the template does.
|
||||
if (const CXXConstructorDecl *Inh = Constructor->getInheritedConstructor())
|
||||
if (CXXConstructorDecl *Inh = const_cast<CXXConstructorDecl *>(
|
||||
Constructor->getInheritedConstructor())) {
|
||||
// If we're instantiating a specialization of a function template, our
|
||||
// "inherited constructor" will actually itself be a function template.
|
||||
// Instantiate a declaration of it, too.
|
||||
if (FunctionTemplate) {
|
||||
assert(!TemplateParams && Inh->getDescribedFunctionTemplate() &&
|
||||
!Inh->getParent()->isDependentContext() &&
|
||||
"inheriting constructor template in dependent context?");
|
||||
Sema::InstantiatingTemplate Inst(SemaRef, Constructor->getLocation(),
|
||||
Inh);
|
||||
if (Inst)
|
||||
return 0;
|
||||
Sema::ContextRAII SavedContext(SemaRef, Inh->getDeclContext());
|
||||
LocalInstantiationScope LocalScope(SemaRef);
|
||||
|
||||
// Use the same template arguments that we deduced for the inheriting
|
||||
// constructor. There's no way they could be deduced differently.
|
||||
MultiLevelTemplateArgumentList InheritedArgs;
|
||||
InheritedArgs.addOuterTemplateArguments(TemplateArgs.getInnermost());
|
||||
Inh = cast_or_null<CXXConstructorDecl>(
|
||||
SemaRef.SubstDecl(Inh, Inh->getDeclContext(), InheritedArgs));
|
||||
if (!Inh)
|
||||
return 0;
|
||||
}
|
||||
cast<CXXConstructorDecl>(Method)->setInheritedConstructor(Inh);
|
||||
}
|
||||
} else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
|
||||
Method = CXXDestructorDecl::Create(SemaRef.Context, Record,
|
||||
StartLoc, NameInfo, T, TInfo,
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
// RUN: %clang_cc1 -std=c++11 %s -verify
|
||||
|
||||
// expected-no-diagnostics
|
||||
|
||||
namespace PR15757 {
|
||||
struct S {
|
||||
};
|
||||
|
||||
template<typename X, typename Y> struct T {
|
||||
template<typename A> T(X x, A &&a) {}
|
||||
|
||||
template<typename A> explicit T(A &&a)
|
||||
noexcept(noexcept(T(X(), static_cast<A &&>(a))))
|
||||
: T(X(), static_cast<A &&>(a)) {}
|
||||
};
|
||||
|
||||
template<typename X, typename Y> struct U : T<X, Y> {
|
||||
using T<X, Y>::T;
|
||||
};
|
||||
|
||||
U<S, char> foo(char ch) { return U<S, char>(ch); }
|
||||
|
||||
int main() {
|
||||
U<S, int> a(42);
|
||||
U<S, char> b('4');
|
||||
return 0;
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче