]> granicus.if.org Git - clang/commitdiff
Ensure that we have completed a type before attempting initialization
authorDouglas Gregor <dgregor@apple.com>
Mon, 26 Apr 2010 14:36:57 +0000 (14:36 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 26 Apr 2010 14:36:57 +0000 (14:36 +0000)
on that type. Fixes several problems in Boost.Interprocess.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102339 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaInit.cpp
test/SemaTemplate/default-expr-arguments.cpp

index c413e67f042ce2be471deec7772c86ea8b48923c..ccd6d5f28400a8e6aa44aa42ad47c5902212a4bc 100644 (file)
@@ -2620,6 +2620,12 @@ static void TryConstructorInitialization(Sema &S,
   bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct ||
                         Kind.getKind() == InitializationKind::IK_Value ||
                         Kind.getKind() == InitializationKind::IK_Default);
+
+  // The type we're constructing needs to be complete.
+  if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
+    Sequence.SetFailed(InitializationSequence::FK_ConversionFailed);
+    return;
+  }
   
   // The type we're converting to is a class type. Enumerate its constructors
   // to see if one is suitable.
@@ -2806,48 +2812,51 @@ static void TryUserDefinedConversion(Sema &S,
     CXXRecordDecl *DestRecordDecl
       = cast<CXXRecordDecl>(DestRecordType->getDecl());
     
-    DeclarationName ConstructorName
-      = S.Context.DeclarationNames.getCXXConstructorName(
+    // Try to complete the type we're converting to.
+    if (!S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {    
+      DeclarationName ConstructorName
+        = S.Context.DeclarationNames.getCXXConstructorName(
                      S.Context.getCanonicalType(DestType).getUnqualifiedType());
-    DeclContext::lookup_iterator Con, ConEnd;
-    for (llvm::tie(Con, ConEnd) = DestRecordDecl->lookup(ConstructorName);
-         Con != ConEnd; ++Con) {
-      NamedDecl *D = *Con;
-      DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
-      bool SuppressUserConversions = false;
-      
-      // Find the constructor (which may be a template).
-      CXXConstructorDecl *Constructor = 0;
-      FunctionTemplateDecl *ConstructorTmpl
-        = dyn_cast<FunctionTemplateDecl>(D);
-      if (ConstructorTmpl)
-        Constructor = cast<CXXConstructorDecl>(
-                                           ConstructorTmpl->getTemplatedDecl());
-      else {
-        Constructor = cast<CXXConstructorDecl>(D);
-        
-        // If we're performing copy initialization using a copy constructor, we 
-        // suppress user-defined conversions on the arguments.
-        // FIXME: Move constructors?
-        if (Kind.getKind() == InitializationKind::IK_Copy &&
-            Constructor->isCopyConstructor())
-          SuppressUserConversions = true;
+      DeclContext::lookup_iterator Con, ConEnd;
+      for (llvm::tie(Con, ConEnd) = DestRecordDecl->lookup(ConstructorName);
+           Con != ConEnd; ++Con) {
+        NamedDecl *D = *Con;
+        DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
+        bool SuppressUserConversions = false;
         
-      }
-      
-      if (!Constructor->isInvalidDecl() &&
-          Constructor->isConvertingConstructor(AllowExplicit)) {
+        // Find the constructor (which may be a template).
+        CXXConstructorDecl *Constructor = 0;
+        FunctionTemplateDecl *ConstructorTmpl
+          = dyn_cast<FunctionTemplateDecl>(D);
         if (ConstructorTmpl)
-          S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
-                                         /*ExplicitArgs*/ 0,
-                                         &Initializer, 1, CandidateSet,
-                                         SuppressUserConversions);
-        else
-          S.AddOverloadCandidate(Constructor, FoundDecl,
-                                 &Initializer, 1, CandidateSet,
-                                 SuppressUserConversions);
-      }
-    }    
+          Constructor = cast<CXXConstructorDecl>(
+                                           ConstructorTmpl->getTemplatedDecl());
+        else {
+          Constructor = cast<CXXConstructorDecl>(D);
+          
+          // If we're performing copy initialization using a copy constructor, 
+          // we suppress user-defined conversions on the arguments.
+          // FIXME: Move constructors?
+          if (Kind.getKind() == InitializationKind::IK_Copy &&
+              Constructor->isCopyConstructor())
+            SuppressUserConversions = true;
+          
+        }
+        
+        if (!Constructor->isInvalidDecl() &&
+            Constructor->isConvertingConstructor(AllowExplicit)) {
+          if (ConstructorTmpl)
+            S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
+                                           /*ExplicitArgs*/ 0,
+                                           &Initializer, 1, CandidateSet,
+                                           SuppressUserConversions);
+          else
+            S.AddOverloadCandidate(Constructor, FoundDecl,
+                                   &Initializer, 1, CandidateSet,
+                                   SuppressUserConversions);
+        }
+      }    
+    }
   }
 
   SourceLocation DeclLoc = Initializer->getLocStart();
index 40b7f2b3cfac2b556188ebc4373686846a376559..7c3525a1fb15dba5ddd04a5ba8f17dbc044715da 100644 (file)
@@ -188,3 +188,21 @@ template<> void f4<int>(int, int);
 void f4_test(int i) {
   f4(i);
 }
+
+// Instantiate for initialization
+namespace InstForInit {
+  template<typename T>
+  struct Ptr {
+    typedef T* type;
+    Ptr(type);
+  };
+
+  template<typename T>
+  struct Holder {
+    Holder(int i, Ptr<T> ptr = 0);
+  };
+
+  void test_holder(int i) {
+    Holder<int> h(i);
+  }
+};