diff options
Diffstat (limited to 'lib/Sema/SemaStmt.cpp')
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 41 |
1 files changed, 25 insertions, 16 deletions
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 1e37bb00c4..fd30a5360e 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -437,32 +437,35 @@ static bool CheckCXXSwitchCondition(Sema &S, SourceLocation SwitchLoc, << CondExpr->getSourceRange())) return true; - llvm::SmallVector<CXXConversionDecl *, 4> ViableConversions; - llvm::SmallVector<CXXConversionDecl *, 4> ExplicitConversions; + UnresolvedSet<4> ViableConversions; + UnresolvedSet<4> ExplicitConversions; if (const RecordType *RecordTy = CondType->getAs<RecordType>()) { const UnresolvedSetImpl *Conversions = cast<CXXRecordDecl>(RecordTy->getDecl()) ->getVisibleConversionFunctions(); for (UnresolvedSetImpl::iterator I = Conversions->begin(), E = Conversions->end(); I != E; ++I) { - if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(*I)) + if (CXXConversionDecl *Conversion + = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) if (Conversion->getConversionType().getNonReferenceType() ->isIntegralType()) { if (Conversion->isExplicit()) - ExplicitConversions.push_back(Conversion); + ExplicitConversions.addDecl(I.getDecl(), I.getAccess()); else - ViableConversions.push_back(Conversion); + ViableConversions.addDecl(I.getDecl(), I.getAccess()); } } switch (ViableConversions.size()) { case 0: if (ExplicitConversions.size() == 1) { + DeclAccessPair Found = ExplicitConversions[0]; + CXXConversionDecl *Conversion = + cast<CXXConversionDecl>(Found->getUnderlyingDecl()); // The user probably meant to invoke the given explicit // conversion; use it. QualType ConvTy - = ExplicitConversions[0]->getConversionType() - .getNonReferenceType(); + = Conversion->getConversionType().getNonReferenceType(); std::string TypeStr; ConvTy.getAsStringInternal(TypeStr, S.Context.PrintingPolicy); @@ -473,8 +476,7 @@ static bool CheckCXXSwitchCondition(Sema &S, SourceLocation SwitchLoc, << CodeModificationHint::CreateInsertion( S.PP.getLocForEndOfToken(CondExpr->getLocEnd()), ")"); - S.Diag(ExplicitConversions[0]->getLocation(), - diag::note_switch_conversion) + S.Diag(Conversion->getLocation(), diag::note_switch_conversion) << ConvTy->isEnumeralType() << ConvTy; // If we aren't in a SFINAE context, build a call to the @@ -482,25 +484,32 @@ static bool CheckCXXSwitchCondition(Sema &S, SourceLocation SwitchLoc, if (S.isSFINAEContext()) return true; - CondExpr = S.BuildCXXMemberCallExpr(CondExpr, ExplicitConversions[0]); + S.CheckMemberOperatorAccess(CondExpr->getExprLoc(), + CondExpr, 0, Found); + CondExpr = S.BuildCXXMemberCallExpr(CondExpr, Found, Conversion); } // We'll complain below about a non-integral condition type. break; - case 1: + case 1: { // Apply this conversion. - CondExpr = S.BuildCXXMemberCallExpr(CondExpr, ViableConversions[0]); + DeclAccessPair Found = ViableConversions[0]; + S.CheckMemberOperatorAccess(CondExpr->getExprLoc(), + CondExpr, 0, Found); + CondExpr = S.BuildCXXMemberCallExpr(CondExpr, Found, + cast<CXXConversionDecl>(Found->getUnderlyingDecl())); break; + } default: S.Diag(SwitchLoc, diag::err_switch_multiple_conversions) << CondType << CondExpr->getSourceRange(); for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) { - QualType ConvTy - = ViableConversions[I]->getConversionType().getNonReferenceType(); - S.Diag(ViableConversions[I]->getLocation(), - diag::note_switch_conversion) + CXXConversionDecl *Conv + = cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl()); + QualType ConvTy = Conv->getConversionType().getNonReferenceType(); + S.Diag(Conv->getLocation(), diag::note_switch_conversion) << ConvTy->isEnumeralType() << ConvTy; } return true; |