Commit 22019e87 authored by Bill Wendling's avatar Bill Wendling
Browse files

Merging r182072:

------------------------------------------------------------------------
r182072 | rsmith | 2013-05-16 19:19:35 -0700 (Thu, 16 May 2013) | 6 lines

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.

------------------------------------------------------------------------

llvm-svn: 182150
parent 1be7bd1f
Loading
Loading
Loading
Loading
+10 −4
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ 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(),
      addOuterTemplateArguments(ArgList(TemplateArgs->data(),
                                        TemplateArgs->size()));
    }
    
@@ -102,7 +102,13 @@ namespace clang {
    /// 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.
+27 −1
Original line number Diff line number Diff line
@@ -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,
+28 −0
Original line number Diff line number Diff line
// 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;
  }
}