r182072 - PR15757: When we instantiate an inheriting constructor template, also

Richard Smith richard-llvm at metafoo.co.uk
Thu May 16 19:19:36 PDT 2013


Author: rsmith
Date: Thu May 16 21:19:35 2013
New Revision: 182072

URL: http://llvm.org/viewvc/llvm-project?rev=182072&view=rev
Log:
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.

Added:
    cfe/trunk/test/SemaCXX/cxx11-inheriting-ctors.cpp
Modified:
    cfe/trunk/include/clang/Sema/Template.h
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp

Modified: cfe/trunk/include/clang/Sema/Template.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Template.h?rev=182072&r1=182071&r2=182072&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Template.h (original)
+++ cfe/trunk/include/clang/Sema/Template.h Thu May 16 21:19:35 2013
@@ -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(); 

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=182072&r1=182071&r2=182072&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu May 16 21:19:35 2013
@@ -1558,10 +1558,36 @@ TemplateDeclInstantiator::VisitCXXMethod
                                         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,

Added: cfe/trunk/test/SemaCXX/cxx11-inheriting-ctors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx11-inheriting-ctors.cpp?rev=182072&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx11-inheriting-ctors.cpp (added)
+++ cfe/trunk/test/SemaCXX/cxx11-inheriting-ctors.cpp Thu May 16 21:19:35 2013
@@ -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;
+  }
+}





More information about the cfe-commits mailing list