diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index c3e168c1e7362f..736a88782e1dcf 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -11649,19 +11649,30 @@ static void CheckBoolLikeConversion(Sema &S, Expr *E, SourceLocation CC) { CheckImplicitConversion(S, E->IgnoreParenImpCasts(), S.Context.BoolTy, CC); } -/// AnalyzeImplicitConversions - Find and report any interesting -/// implicit conversions in the given expression. There are a couple -/// of competing diagnostics here, -Wconversion and -Wsign-compare. -static void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC, - bool IsListInit/*= false*/) { +namespace { +struct AnalyzeImplicitConversionsWorkItem { + Expr *E; + SourceLocation CC; + bool IsListInit; +}; +} + +/// Data recursive variant of AnalyzeImplicitConversions. Subexpressions +/// that should be visited are added to WorkList. +static void AnalyzeImplicitConversions( + Sema &S, AnalyzeImplicitConversionsWorkItem Item, + llvm::SmallVectorImpl &WorkList) { + Expr *OrigE = Item.E; + SourceLocation CC = Item.CC; + QualType T = OrigE->getType(); Expr *E = OrigE->IgnoreParenImpCasts(); // Propagate whether we are in a C++ list initialization expression. // If so, we do not issue warnings for implicit int-float conversion // precision loss, because C++11 narrowing already handles it. - IsListInit = - IsListInit || (isa(OrigE) && S.getLangOpts().CPlusPlus); + bool IsListInit = Item.IsListInit || + (isa(OrigE) && S.getLangOpts().CPlusPlus); if (E->isTypeDependent() || E->isValueDependent()) return; @@ -11707,7 +11718,7 @@ static void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC, // FIXME: Use a more uniform representation for this. for (auto *SE : POE->semantics()) if (auto *OVE = dyn_cast(SE)) - AnalyzeImplicitConversions(S, OVE->getSourceExpr(), CC, IsListInit); + WorkList.push_back({OVE->getSourceExpr(), CC, IsListInit}); } // Skip past explicit casts. @@ -11715,7 +11726,8 @@ static void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC, E = CE->getSubExpr()->IgnoreParenImpCasts(); if (!CE->getType()->isVoidType() && E->getType()->isAtomicType()) S.Diag(E->getBeginLoc(), diag::warn_atomic_implicit_seq_cst); - return AnalyzeImplicitConversions(S, E, CC, IsListInit); + WorkList.push_back({E, CC, IsListInit}); + return; } if (BinaryOperator *BO = dyn_cast(E)) { @@ -11754,7 +11766,7 @@ static void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC, // Ignore checking string literals that are in logical and operators. // This is a common pattern for asserts. continue; - AnalyzeImplicitConversions(S, ChildExpr, CC, IsListInit); + WorkList.push_back({ChildExpr, CC, IsListInit}); } if (BO && BO->isLogicalOp()) { @@ -11778,6 +11790,17 @@ static void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC, } } +/// AnalyzeImplicitConversions - Find and report any interesting +/// implicit conversions in the given expression. There are a couple +/// of competing diagnostics here, -Wconversion and -Wsign-compare. +static void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC, + bool IsListInit/*= false*/) { + llvm::SmallVector WorkList; + WorkList.push_back({OrigE, CC, IsListInit}); + while (!WorkList.empty()) + AnalyzeImplicitConversions(S, WorkList.pop_back_val(), WorkList); +} + /// Diagnose integer type and any valid implicit conversion to it. static bool checkOpenCLEnqueueIntType(Sema &S, Expr *E, const QualType &IntT) { // Taking into account implicit conversions,