From 087fb7d0b5e08f34b2e28a09c376f66449f30886 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 26 Apr 2010 14:36:57 +0000 Subject: [PATCH] Ensure that we have completed a type before attempting initialization 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 | 87 +++++++++++--------- test/SemaTemplate/default-expr-arguments.cpp | 18 ++++ 2 files changed, 66 insertions(+), 39 deletions(-) diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index c413e67f04..ccd6d5f284 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -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(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(D); - if (ConstructorTmpl) - Constructor = cast( - ConstructorTmpl->getTemplatedDecl()); - else { - Constructor = cast(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(D); if (ConstructorTmpl) - S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, - /*ExplicitArgs*/ 0, - &Initializer, 1, CandidateSet, - SuppressUserConversions); - else - S.AddOverloadCandidate(Constructor, FoundDecl, - &Initializer, 1, CandidateSet, - SuppressUserConversions); - } - } + Constructor = cast( + ConstructorTmpl->getTemplatedDecl()); + else { + Constructor = cast(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(); diff --git a/test/SemaTemplate/default-expr-arguments.cpp b/test/SemaTemplate/default-expr-arguments.cpp index 40b7f2b3cf..7c3525a1fb 100644 --- a/test/SemaTemplate/default-expr-arguments.cpp +++ b/test/SemaTemplate/default-expr-arguments.cpp @@ -188,3 +188,21 @@ template<> void f4(int, int); void f4_test(int i) { f4(i); } + +// Instantiate for initialization +namespace InstForInit { + template + struct Ptr { + typedef T* type; + Ptr(type); + }; + + template + struct Holder { + Holder(int i, Ptr ptr = 0); + }; + + void test_holder(int i) { + Holder h(i); + } +}; -- 2.40.0