summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaInit.cpp
diff options
context:
space:
mode:
authorAlex Lorenz <arphaman@gmail.com>2017-05-16 10:23:58 +0000
committerAlex Lorenz <arphaman@gmail.com>2017-05-16 10:23:58 +0000
commitaf473b4213ef00e23a340ec013a827e4c8c96d5b (patch)
treee822938c06b3ef38c535e5657c8482dd9009aed2 /lib/Sema/SemaInit.cpp
parent8c199f23fb6405e08d4f888dfdd141a895ee5413 (diff)
downloadclang-af473b4213ef00e23a340ec013a827e4c8c96d5b.tar.gz
Fix PR 10758: Infinite recursion when dealing with copy-initialization
This commit fixes a bug that's tracked by PR 10758 and duplicates like PR 30343. The bug causes clang to crash with a stack overflow while recursing infinitely trying to perform copy-initialization on a type without a copy constructor but with a constructor that accepts another type that can be constructed using the original type. The commit fixes this bug by detecting the recursive behavior and failing correctly with an appropriate error message. It also tries to provide a meaningful diagnostic note about the constructor which leads to this behavior. rdar://28483944 Differential Revision: https://reviews.llvm.org/D25051 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@303156 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaInit.cpp')
-rw-r--r--lib/Sema/SemaInit.cpp38
1 files changed, 38 insertions, 0 deletions
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 8d19b82c3f..32024cb335 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -8296,8 +8296,46 @@ Sema::PerformCopyInitialization(const InitializedEntity &Entity,
AllowExplicit);
InitializationSequence Seq(*this, Entity, Kind, InitE, TopLevelOfInitList);
+ // Prevent infinite recursion when performing parameter copy-initialization.
+ const bool ShouldTrackCopy =
+ Entity.isParameterKind() && Seq.isConstructorInitialization();
+ if (ShouldTrackCopy) {
+ if (llvm::find(CurrentParameterCopyTypes, Entity.getType()) !=
+ CurrentParameterCopyTypes.end()) {
+ Seq.SetOverloadFailure(
+ InitializationSequence::FK_ConstructorOverloadFailed,
+ OR_No_Viable_Function);
+
+ // Try to give a meaningful diagnostic note for the problematic
+ // constructor.
+ const auto LastStep = Seq.step_end() - 1;
+ assert(LastStep->Kind ==
+ InitializationSequence::SK_ConstructorInitialization);
+ const FunctionDecl *Function = LastStep->Function.Function;
+ auto Candidate =
+ llvm::find_if(Seq.getFailedCandidateSet(),
+ [Function](const OverloadCandidate &Candidate) -> bool {
+ return Candidate.Viable &&
+ Candidate.Function == Function &&
+ Candidate.Conversions.size() > 0;
+ });
+ if (Candidate != Seq.getFailedCandidateSet().end() &&
+ Function->getNumParams() > 0) {
+ Candidate->Viable = false;
+ Candidate->FailureKind = ovl_fail_bad_conversion;
+ Candidate->Conversions[0].setBad(BadConversionSequence::no_conversion,
+ InitE,
+ Function->getParamDecl(0)->getType());
+ }
+ }
+ CurrentParameterCopyTypes.push_back(Entity.getType());
+ }
+
ExprResult Result = Seq.Perform(*this, Entity, Kind, InitE);
+ if (ShouldTrackCopy)
+ CurrentParameterCopyTypes.pop_back();
+
return Result;
}