]> granicus.if.org Git - clang/commitdiff
PR15757: When we instantiate an inheriting constructor template, also
authorRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 17 May 2013 02:19:35 +0000 (02:19 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 17 May 2013 02:19:35 +0000 (02:19 +0000)
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

include/clang/Sema/Template.h
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaCXX/cxx11-inheriting-ctors.cpp [new file with mode: 0644]

index 6e054c463a910b0c311882ae144b22a68405c376..f9481c6c0c20bd6bf9c4162b9857f2372d376a69 100644 (file)
@@ -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(); 
index ff59cdcbc4240417e1005abe06c983fcdf162f8d..09ddd9db658fab139f8e90869247336e6aea9a52 100644 (file)
@@ -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,
diff --git a/test/SemaCXX/cxx11-inheriting-ctors.cpp b/test/SemaCXX/cxx11-inheriting-ctors.cpp
new file mode 100644 (file)
index 0000000..67d5521
--- /dev/null
@@ -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;
+  }
+}