[prev in list] [next in list] [prev in thread] [next in thread] 

List:       cfe-commits
Subject:    [cfe-commits] [PATCH] Fix copy-list-initialization in template instantiation.
From:       Olivier Goffart <ogoffart () kde ! org>
Date:       2012-12-10 9:44:37
Message-ID: 4048950.4eguVddmco () gargamel
[Download RAW message or body]

Hi, 

Attached you will find a suggested fix for 
http://llvm.org/bugs/show_bug.cgi?id=14486 and 
http://llvm.org/bugs/show_bug.cgi?id=13470

Regards
-- 
Olivier
["0001-Fix-copy-list-initialization-in-template-instentiati.patch" (0001-Fix-copy-list-initialization-in-template-instentiati.patch)]

From eb748636b150a035c1b8c80ea7ecec27a4b90f22 Mon Sep 17 00:00:00 2001
From: Olivier Goffart <ogoffart@woboq.com>
Date: Sat, 8 Dec 2012 12:35:15 +0100
Subject: [PATCH] Fix copy-list-initialization in template instentiation.

Fix for http://llvm.org/bugs/show_bug.cgi?id=14486

While parsing, Parser::ParseDeclarationAfterDeclaratorAndAttributes
calls Sema::AddInitializerToDecl with the init expresison is an
InitListExpr*. Then InitializationSequence::Perform is called with
SK_ListConstructorCall, which will call PerformConstructorInitialization
As a result, the initializer is now a CXXConstructExpr*, but the
initialisation type is still copy.

Later, while intensiating, TemplateDeclInstantiator::VisitVarDecl also
calls Sema::AddInitializerToDecl with the CXXConstructExpr* and the type
copy, as we lost the information this was a copy-list-initialization,
the code will try to perform a copy by calling the copy constructor.
This is an error if the copy constructor was deleted.

Note: if the CXXConstructExpr only has one argument,
Sema::SubstInitializer will take that argument out, and AddInitializer
will be called with that argument

This patch does 2 things to solve that problem:
1) If we try to add a CXXConstructExpr, th direct initialisation, it
   means the initialisation was already performed. So we need not to
   do the InitializationSequence.
2) We remember that the declaration's init style is VarDecl::ListInit
   As a result, TemplateDeclInstantiator::VisitVarDecl will pass true
   for the DirectInit parametter to AddInitializerToDecl.
   That will cause the kind to be IK_DirectList in the constructor of
   InitializationSequence, we need to generate a constructor call in
   that case too. That is usefull for the cases where we had only one
   argument to the constructor
---
 lib/Sema/SemaDecl.cpp                          | 15 ++++++--
 lib/Sema/SemaInit.cpp                          |  1 +
 test/SemaCXX/cxx0x-initializer-constructor.cpp | 48 ++++++++++++++++++++++++++
 3 files changed, 62 insertions(+), 2 deletions(-)

diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 9dd7779..8b88894 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -6721,8 +6721,12 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
       Init = Result.take();
     }
 
-  // Perform the initialization.
-  if (!VDecl->isInvalidDecl()) {
+  if (VDecl->isInvalidDecl()) {
+  } else if (DirectInit && isa<CXXConstructExpr>(Init)) {
+      //We already have performed the initialisation
+      assert(cast<CXXConstructExpr>(Init)->getType() == DclT);
+  } else {
+    // Perform the initialization.
     InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl);
     InitializationKind Kind
       = DirectInit ?
@@ -6740,6 +6744,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
       Args = CXXDirectInit->getExprs();
       NumArgs = CXXDirectInit->getNumExprs();
     }
+
     InitializationSequence InitSeq(*this, Entity, Kind, Args, NumArgs);
     ExprResult Result = InitSeq.Perform(*this, Entity, Kind,
                                         MultiExprArg(Args, NumArgs), &DclT);
@@ -6748,6 +6753,12 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
       return;
     }
 
+    if (getLangOpts().CPlusPlus0x && !DirectInit && isa<InitListExpr>(Init)
+        && !isa<InitListExpr>(Result.get())) {
+        // Remember this was a copy-list-initialization
+        VDecl->setInitStyle(VarDecl::ListInit);
+    }
+
     Init = Result.takeAs<Expr>();
   }
 
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 48b0d1f..2d56676 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -4150,6 +4150,7 @@ InitializationSequence::InitializationSequence(Sema &S,
     //       source type is the same class as, or a derived class of, the
     //       class of the destination, constructors are considered. [...]
     if (Kind.getKind() == InitializationKind::IK_Direct ||
+        Kind.getKind() == InitializationKind::IK_DirectList ||
         (Kind.getKind() == InitializationKind::IK_Copy &&
          (Context.hasSameUnqualifiedType(SourceType, DestType) ||
           S.IsDerivedFrom(SourceType, DestType))))
diff --git a/test/SemaCXX/cxx0x-initializer-constructor.cpp \
b/test/SemaCXX/cxx0x-initializer-constructor.cpp index a657ec8..44d6228 100644
--- a/test/SemaCXX/cxx0x-initializer-constructor.cpp
+++ b/test/SemaCXX/cxx0x-initializer-constructor.cpp
@@ -320,3 +320,51 @@ namespace rdar11974632 {
 
   Y<int> yi;
 }
+
+namespace PR14486 {
+  struct A {
+      A() {}
+      A(int) {}
+  };
+  struct X {
+    X(const X&) = delete; // expected-note 4 {{marked deleted here}}
+    X(int) {}
+    X(int, int) {}
+    X(const A&) {}
+    explicit X(double) {} // expected-note 2 {{here}}
+    explicit X(double,double) {} // expected-note 2 {{here}}
+  };
+  template<typename T>
+  struct Y {
+    static void f1() {
+      X x1{1.};
+      X x2 = {1};
+      X x3 = {1.}; // expected-error{{chosen constructor is explicit}}
+      X x6 = {1, 1};
+      X x7 = {1., 1.}; // expected-error{{chosen constructor is explicit}}
+      X x8 = 1; //expected-error{{invokes deleted constructor}}
+      X x9 = {A()};
+      X x10{A()};
+      X x11 = {A(0)};
+      X x12{A(0)};
+      X x13 = A(); //expected-error{{invokes deleted constructor}}
+    }
+    static void f2() {
+      T x1{1.};
+      T x2 = {1};
+      T x3 = {1.}; // expected-error{{chosen constructor is explicit}}
+      T x6 = {1, 1};
+      T x7 = {1., 1.}; // expected-error{{chosen constructor is explicit}}
+      T x8 = 1; //expected-error{{invokes deleted constructor}}
+      T x9 = {A()};
+      T x10{A()};
+      T x11 = {A(0)};
+      T x12{A(0)};
+      T x13 = A(); //expected-error{{invokes deleted constructor}}
+    }
+  };
+  void f() {
+      Y<X>::f1();
+      Y<X>::f2(); // expected-note{{requested here}}
+  }
+}
-- 
1.7.12.1



_______________________________________________
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic