diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-04-24 20:54:38 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-04-24 20:54:38 +0000 |
commit | d1a272204cef9304df3930d94f66713b05db27d6 (patch) | |
tree | 725d0db5d5a84300d024524d465bef8a68cd7ee5 /lib/Sema/SemaInit.cpp | |
parent | 564618f782b9f6d373f789d8cf24943fd345904d (diff) |
When we are performing copy initialization of a class type via its
copy constructor, suppress user-defined conversions on the
argument. Otherwise, we can end up in a recursion loop where the
bind the argument of the copy constructor to another copy constructor call,
whose argument is then a copy constructor call...
Found by Boost.Regex which, alas, still isn't building.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102269 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaInit.cpp')
-rw-r--r-- | lib/Sema/SemaInit.cpp | 39 |
1 files changed, 31 insertions, 8 deletions
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 5c55b56c7d..d552b16399 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -2636,25 +2636,36 @@ static void TryConstructorInitialization(Sema &S, 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 + 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() && (AllowExplicit || !Constructor->isExplicit())) { if (ConstructorTmpl) S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, /*ExplicitArgs*/ 0, - Args, NumArgs, CandidateSet); + Args, NumArgs, CandidateSet, + SuppressUserConversions); else S.AddOverloadCandidate(Constructor, FoundDecl, - Args, NumArgs, CandidateSet); + Args, NumArgs, CandidateSet, + SuppressUserConversions); } } @@ -2803,7 +2814,8 @@ static void TryUserDefinedConversion(Sema &S, 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 @@ -2811,18 +2823,29 @@ static void TryUserDefinedConversion(Sema &S, if (ConstructorTmpl) Constructor = cast<CXXConstructorDecl>( ConstructorTmpl->getTemplatedDecl()); - else + 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); + &Initializer, 1, CandidateSet, + SuppressUserConversions); else S.AddOverloadCandidate(Constructor, FoundDecl, - &Initializer, 1, CandidateSet); + &Initializer, 1, CandidateSet, + SuppressUserConversions); } } } |