nickdesaulniers created this revision.
nickdesaulniers added reviewers: aaron.ballman, dblaikie.
Herald added a reviewer: jdoerfert.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

While working in SemaStmt, I noticed a bunch of static functions are
passed *this, which is a code smell. Prefer private methods.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D77701

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaStmt.cpp

Index: clang/lib/Sema/SemaStmt.cpp
===================================================================
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -120,12 +120,7 @@
   }
 }
 
-/// Diagnose unused comparisons, both builtin and overloaded operators.
-/// For '==' and '!=', suggest fixits for '=' or '|='.
-///
-/// Adding a cast to void (or other expression wrappers) will prevent the
-/// warning from firing.
-static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) {
+bool Sema::DiagnoseUnusedComparison(const Expr *E) {
   SourceLocation Loc;
   bool CanAssign;
   enum { Equality, Inequality, Relational, ThreeWay } Kind;
@@ -176,43 +171,41 @@
 
   // Suppress warnings when the operator, suspicious as it may be, comes from
   // a macro expansion.
-  if (S.SourceMgr.isMacroBodyExpansion(Loc))
+  if (SourceMgr.isMacroBodyExpansion(Loc))
     return false;
 
-  S.Diag(Loc, diag::warn_unused_comparison)
-    << (unsigned)Kind << E->getSourceRange();
+  Diag(Loc, diag::warn_unused_comparison)
+      << (unsigned)Kind << E->getSourceRange();
 
   // If the LHS is a plausible entity to assign to, provide a fixit hint to
   // correct common typos.
   if (CanAssign) {
     if (Kind == Inequality)
-      S.Diag(Loc, diag::note_inequality_comparison_to_or_assign)
-        << FixItHint::CreateReplacement(Loc, "|=");
+      Diag(Loc, diag::note_inequality_comparison_to_or_assign)
+          << FixItHint::CreateReplacement(Loc, "|=");
     else if (Kind == Equality)
-      S.Diag(Loc, diag::note_equality_comparison_to_assign)
-        << FixItHint::CreateReplacement(Loc, "=");
+      Diag(Loc, diag::note_equality_comparison_to_assign)
+          << FixItHint::CreateReplacement(Loc, "=");
   }
 
   return true;
 }
 
-static bool DiagnoseNoDiscard(Sema &S, const WarnUnusedResultAttr *A,
-                              SourceLocation Loc, SourceRange R1,
-                              SourceRange R2, bool IsCtor) {
+bool Sema::DiagnoseNoDiscard(const WarnUnusedResultAttr *A, SourceLocation Loc,
+                             SourceRange R1, SourceRange R2, bool IsCtor) {
   if (!A)
     return false;
   StringRef Msg = A->getMessage();
 
   if (Msg.empty()) {
     if (IsCtor)
-      return S.Diag(Loc, diag::warn_unused_constructor) << A << R1 << R2;
-    return S.Diag(Loc, diag::warn_unused_result) << A << R1 << R2;
+      return Diag(Loc, diag::warn_unused_constructor) << A << R1 << R2;
+    return Diag(Loc, diag::warn_unused_result) << A << R1 << R2;
   }
 
   if (IsCtor)
-    return S.Diag(Loc, diag::warn_unused_constructor_msg) << A << Msg << R1
-                                                          << R2;
-  return S.Diag(Loc, diag::warn_unused_result_msg) << A << Msg << R1 << R2;
+    return Diag(Loc, diag::warn_unused_constructor_msg) << A << Msg << R1 << R2;
+  return Diag(Loc, diag::warn_unused_result_msg) << A << Msg << R1 << R2;
 }
 
 void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
@@ -269,7 +262,7 @@
   if (const CXXBindTemporaryExpr *TempExpr = dyn_cast<CXXBindTemporaryExpr>(E))
     E = TempExpr->getSubExpr();
 
-  if (DiagnoseUnusedComparison(*this, E))
+  if (DiagnoseUnusedComparison(E))
     return;
 
   E = WarnExpr;
@@ -282,8 +275,8 @@
     if (E->getType()->isVoidType())
       return;
 
-    if (DiagnoseNoDiscard(*this, cast_or_null<WarnUnusedResultAttr>(
-                                     CE->getUnusedResultAttr(Context)),
+    if (DiagnoseNoDiscard(cast_or_null<WarnUnusedResultAttr>(
+                              CE->getUnusedResultAttr(Context)),
                           Loc, R1, R2, /*isCtor=*/false))
       return;
 
@@ -307,14 +300,14 @@
     if (const CXXConstructorDecl *Ctor = CE->getConstructor()) {
       const auto *A = Ctor->getAttr<WarnUnusedResultAttr>();
       A = A ? A : Ctor->getParent()->getAttr<WarnUnusedResultAttr>();
-      if (DiagnoseNoDiscard(*this, A, Loc, R1, R2, /*isCtor=*/true))
+      if (DiagnoseNoDiscard(A, Loc, R1, R2, /*isCtor=*/true))
         return;
     }
   } else if (const auto *ILE = dyn_cast<InitListExpr>(E)) {
     if (const TagDecl *TD = ILE->getType()->getAsTagDecl()) {
 
-      if (DiagnoseNoDiscard(*this, TD->getAttr<WarnUnusedResultAttr>(), Loc, R1,
-                            R2, /*isCtor=*/false))
+      if (DiagnoseNoDiscard(TD->getAttr<WarnUnusedResultAttr>(), Loc, R1, R2,
+                            /*isCtor=*/false))
         return;
     }
   } else if (ShouldSuppress)
@@ -328,8 +321,8 @@
     }
     const ObjCMethodDecl *MD = ME->getMethodDecl();
     if (MD) {
-      if (DiagnoseNoDiscard(*this, MD->getAttr<WarnUnusedResultAttr>(), Loc, R1,
-                            R2, /*isCtor=*/false))
+      if (DiagnoseNoDiscard(MD->getAttr<WarnUnusedResultAttr>(), Loc, R1, R2,
+                            /*isCtor=*/false))
         return;
     }
   } else if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
@@ -762,12 +755,10 @@
   Val.setIsSigned(IsSigned);
 }
 
-/// Check the specified case value is in range for the given unpromoted switch
-/// type.
-static void checkCaseValue(Sema &S, SourceLocation Loc, const llvm::APSInt &Val,
-                           unsigned UnpromotedWidth, bool UnpromotedSign) {
+void Sema::CheckCaseValue(SourceLocation Loc, const llvm::APSInt &Val,
+                          unsigned UnpromotedWidth, bool UnpromotedSign) {
   // In C++11 onwards, this is checked by the language rules.
-  if (S.getLangOpts().CPlusPlus11)
+  if (getLangOpts().CPlusPlus11)
     return;
 
   // If the case value was signed and negative and the switch expression is
@@ -781,21 +772,16 @@
     // type versus "switch expression cannot have this value". Use proper
     // IntRange checking rather than just looking at the unpromoted type here.
     if (ConvVal != Val)
-      S.Diag(Loc, diag::warn_case_value_overflow) << Val.toString(10)
-                                                  << ConvVal.toString(10);
+      Diag(Loc, diag::warn_case_value_overflow)
+          << Val.toString(10) << ConvVal.toString(10);
   }
 }
 
-typedef SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64> EnumValsTy;
-
-/// Returns true if we should emit a diagnostic about this case expression not
-/// being a part of the enum used in the switch controlling expression.
-static bool ShouldDiagnoseSwitchCaseNotInEnum(const Sema &S,
-                                              const EnumDecl *ED,
-                                              const Expr *CaseExpr,
-                                              EnumValsTy::iterator &EI,
-                                              EnumValsTy::iterator &EIEnd,
-                                              const llvm::APSInt &Val) {
+bool Sema::ShouldDiagnoseSwitchCaseNotInEnum(const EnumDecl *ED,
+                                             const Expr *CaseExpr,
+                                             EnumValsTy::iterator &EI,
+                                             EnumValsTy::iterator &EIEnd,
+                                             const llvm::APSInt &Val) {
   if (!ED->isClosed())
     return false;
 
@@ -803,15 +789,15 @@
           dyn_cast<DeclRefExpr>(CaseExpr->IgnoreParenImpCasts())) {
     if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
       QualType VarType = VD->getType();
-      QualType EnumType = S.Context.getTypeDeclType(ED);
+      QualType EnumType = Context.getTypeDeclType(ED);
       if (VD->hasGlobalStorage() && VarType.isConstQualified() &&
-          S.Context.hasSameUnqualifiedType(EnumType, VarType))
+          Context.hasSameUnqualifiedType(EnumType, VarType))
         return false;
     }
   }
 
   if (ED->hasAttr<FlagEnumAttr>())
-    return !S.IsValueInFlagEnum(ED, Val, false);
+    return !IsValueInFlagEnum(ED, Val, false);
 
   while (EI != EIEnd && EI->first < Val)
     EI++;
@@ -822,8 +808,7 @@
   return true;
 }
 
-static void checkEnumTypesInSwitchStmt(Sema &S, const Expr *Cond,
-                                       const Expr *Case) {
+void Sema::CheckEnumTypesInSwitchStmt(const Expr *Cond, const Expr *Case) {
   QualType CondType = Cond->getType();
   QualType CaseType = Case->getType();
 
@@ -840,10 +825,10 @@
       !CaseEnumType->getDecl()->getTypedefNameForAnonDecl())
     return;
 
-  if (S.Context.hasSameUnqualifiedType(CondType, CaseType))
+  if (Context.hasSameUnqualifiedType(CondType, CaseType))
     return;
 
-  S.Diag(Case->getExprLoc(), diag::warn_comparison_of_mixed_enum_types_switch)
+  Diag(Case->getExprLoc(), diag::warn_comparison_of_mixed_enum_types_switch)
       << CondType << CaseType << Cond->getSourceRange()
       << Case->getSourceRange();
 }
@@ -941,12 +926,11 @@
 
       // Check the unconverted value is within the range of possible values of
       // the switch expression.
-      checkCaseValue(*this, Lo->getBeginLoc(), LoVal, CondWidthBeforePromotion,
+      CheckCaseValue(Lo->getBeginLoc(), LoVal, CondWidthBeforePromotion,
                      CondIsSignedBeforePromotion);
 
       // FIXME: This duplicates the check performed for warn_not_in_enum below.
-      checkEnumTypesInSwitchStmt(*this, CondExprBeforePromotion,
-                                 LoBeforePromotion);
+      CheckEnumTypesInSwitchStmt(CondExprBeforePromotion, LoBeforePromotion);
 
       // Convert the value to the same width/sign as the condition.
       AdjustAPSInt(LoVal, CondWidth, CondIsSigned);
@@ -1044,8 +1028,8 @@
 
         // Check the unconverted value is within the range of possible values of
         // the switch expression.
-        checkCaseValue(*this, Hi->getBeginLoc(), HiVal,
-                       CondWidthBeforePromotion, CondIsSignedBeforePromotion);
+        CheckCaseValue(Hi->getBeginLoc(), HiVal, CondWidthBeforePromotion,
+                       CondIsSignedBeforePromotion);
 
         // Convert the value to the same width/sign as the condition.
         AdjustAPSInt(HiVal, CondWidth, CondIsSigned);
@@ -1155,7 +1139,7 @@
       for (CaseValsTy::const_iterator CI = CaseVals.begin();
           CI != CaseVals.end(); CI++) {
         Expr *CaseExpr = CI->second->getLHS();
-        if (ShouldDiagnoseSwitchCaseNotInEnum(*this, ED, CaseExpr, EI, EIEnd,
+        if (ShouldDiagnoseSwitchCaseNotInEnum(ED, CaseExpr, EI, EIEnd,
                                               CI->first))
           Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)
             << CondTypeBeforePromotion;
@@ -1166,7 +1150,7 @@
       for (CaseRangesTy::const_iterator RI = CaseRanges.begin();
           RI != CaseRanges.end(); RI++) {
         Expr *CaseExpr = RI->second->getLHS();
-        if (ShouldDiagnoseSwitchCaseNotInEnum(*this, ED, CaseExpr, EI, EIEnd,
+        if (ShouldDiagnoseSwitchCaseNotInEnum(ED, CaseExpr, EI, EIEnd,
                                               RI->first))
           Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)
             << CondTypeBeforePromotion;
@@ -1176,8 +1160,7 @@
         AdjustAPSInt(Hi, CondWidth, CondIsSigned);
 
         CaseExpr = RI->second->getRHS();
-        if (ShouldDiagnoseSwitchCaseNotInEnum(*this, ED, CaseExpr, EI, EIEnd,
-                                              Hi))
+        if (ShouldDiagnoseSwitchCaseNotInEnum(ED, CaseExpr, EI, EIEnd, Hi))
           Diag(CaseExpr->getExprLoc(), diag::warn_not_in_enum)
             << CondTypeBeforePromotion;
       }
@@ -2058,20 +2041,19 @@
     << BEF << IsTemplate << Description << E->getType();
 }
 
-/// Build a variable declaration for a for-range statement.
-VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc,
-                              QualType Type, StringRef Name) {
-  DeclContext *DC = SemaRef.CurContext;
-  IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
-  TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
-  VarDecl *Decl = VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type,
-                                  TInfo, SC_None);
+} // namespace
+
+VarDecl *Sema::BuildForRangeVarDecl(SourceLocation Loc, QualType Type,
+                                    StringRef Name) {
+  DeclContext *DC = CurContext;
+  IdentifierInfo *II = &PP.getIdentifierTable().get(Name);
+  TypeSourceInfo *TInfo = Context.getTrivialTypeSourceInfo(Type, Loc);
+  VarDecl *Decl =
+      VarDecl::Create(Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
   Decl->setImplicit();
   return Decl;
 }
 
-}
-
 static bool ObjCEnumerationCollection(Expr *Collection) {
   return !Collection->isTypeDependent()
           && Collection->getType()->getAs<ObjCObjectPointerType>() != nullptr;
@@ -2137,9 +2119,9 @@
   // Divide by 2, since the variables are in the inner scope (loop body).
   const auto DepthStr = std::to_string(S->getDepth() / 2);
   SourceLocation RangeLoc = Range->getBeginLoc();
-  VarDecl *RangeVar = BuildForRangeVarDecl(*this, RangeLoc,
-                                           Context.getAutoRRefDeductType(),
-                                           std::string("__range") + DepthStr);
+  VarDecl *RangeVar =
+      BuildForRangeVarDecl(RangeLoc, Context.getAutoRRefDeductType(),
+                           std::string("__range") + DepthStr);
   if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc,
                             diag::err_for_range_deduction_failure)) {
     LoopVar->setInvalidDecl();
@@ -2432,9 +2414,9 @@
     // Build auto __begin = begin-expr, __end = end-expr.
     // Divide by 2, since the variables are in the inner scope (loop body).
     const auto DepthStr = std::to_string(S->getDepth() / 2);
-    VarDecl *BeginVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType,
+    VarDecl *BeginVar = BuildForRangeVarDecl(ColonLoc, AutoType,
                                              std::string("__begin") + DepthStr);
-    VarDecl *EndVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType,
+    VarDecl *EndVar = BuildForRangeVarDecl(ColonLoc, AutoType,
                                            std::string("__end") + DepthStr);
 
     // Build begin-expr and end-expr and attach to __begin and __end variables.
@@ -2702,16 +2684,8 @@
   return S;
 }
 
-// Warn when the loop variable is a const reference that creates a copy.
-// Suggest using the non-reference type for copies.  If a copy can be prevented
-// suggest the const reference type that would do so.
-// For instance, given "for (const &Foo : Range)", suggest
-// "for (const Foo : Range)" to denote a copy is made for the loop.  If
-// possible, also suggest "for (const &Bar : Range)" if this type prevents
-// the copy altogether.
-static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef,
-                                                    const VarDecl *VD,
-                                                    QualType RangeInitType) {
+void Sema::DiagnoseForRangeReferenceVariableCopies(const VarDecl *VD,
+                                                   QualType RangeInitType) {
   const Expr *InitExpr = VD->getInit();
   if (!InitExpr)
     return;
@@ -2748,7 +2722,7 @@
 
   QualType ReferenceReturnType;
   if (isa<UnaryOperator>(E)) {
-    ReferenceReturnType = SemaRef.Context.getLValueReferenceType(E->getType());
+    ReferenceReturnType = Context.getLValueReferenceType(E->getType());
   } else {
     const CXXOperatorCallExpr *Call = cast<CXXOperatorCallExpr>(E);
     const FunctionDecl *FD = Call->getDirectCallee();
@@ -2761,14 +2735,14 @@
     // Loop variable creates a temporary.  Suggest either to go with
     // non-reference loop variable to indicate a copy is made, or
     // the correct type to bind a const reference.
-    SemaRef.Diag(VD->getLocation(),
-                 diag::warn_for_range_const_ref_binds_temp_built_from_ref)
+    Diag(VD->getLocation(),
+         diag::warn_for_range_const_ref_binds_temp_built_from_ref)
         << VD << VariableType << ReferenceReturnType;
     QualType NonReferenceType = VariableType.getNonReferenceType();
     NonReferenceType.removeLocalConst();
     QualType NewReferenceType =
-        SemaRef.Context.getLValueReferenceType(E->getType().withConst());
-    SemaRef.Diag(VD->getBeginLoc(), diag::note_use_type_or_non_reference)
+        Context.getLValueReferenceType(E->getType().withConst());
+    Diag(VD->getBeginLoc(), diag::note_use_type_or_non_reference)
         << NonReferenceType << NewReferenceType << VD->getSourceRange()
         << FixItHint::CreateRemoval(VD->getTypeSpecEndLoc());
   } else if (!VariableType->isRValueReferenceType()) {
@@ -2776,11 +2750,11 @@
     // Suggest removing the reference from the loop variable.
     // If the type is a rvalue reference do not warn since that changes the
     // semantic of the code.
-    SemaRef.Diag(VD->getLocation(), diag::warn_for_range_ref_binds_ret_temp)
+    Diag(VD->getLocation(), diag::warn_for_range_ref_binds_ret_temp)
         << VD << RangeInitType;
     QualType NonReferenceType = VariableType.getNonReferenceType();
     NonReferenceType.removeLocalConst();
-    SemaRef.Diag(VD->getBeginLoc(), diag::note_use_non_reference_type)
+    Diag(VD->getBeginLoc(), diag::note_use_non_reference_type)
         << NonReferenceType << VD->getSourceRange()
         << FixItHint::CreateRemoval(VD->getTypeSpecEndLoc());
   }
@@ -2795,17 +2769,11 @@
   return false;
 }
 
-// Warns when the loop variable can be changed to a reference type to
-// prevent a copy.  For instance, if given "for (const Foo x : Range)" suggest
-// "for (const Foo &x : Range)" if this form does not make a copy.
-static void DiagnoseForRangeConstVariableCopies(Sema &SemaRef,
-                                                const VarDecl *VD) {
+void Sema::DiagnoseForRangeConstVariableCopies(const VarDecl *VD) {
   const Expr *InitExpr = VD->getInit();
   if (!InitExpr)
     return;
 
-  QualType VariableType = VD->getType();
-
   if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(InitExpr)) {
     if (!CE->getConstructor()->isCopyConstructor())
       return;
@@ -2819,44 +2787,30 @@
   // Small trivially copyable types are cheap to copy. Do not emit the
   // diagnostic for these instances. 64 bytes is a common size of a cache line.
   // (The function `getTypeSize` returns the size in bits.)
-  ASTContext &Ctx = SemaRef.Context;
-  if (Ctx.getTypeSize(VariableType) <= 64 * 8 &&
-      (VariableType.isTriviallyCopyableType(Ctx) ||
+  QualType VariableType = VD->getType();
+  if (Context.getTypeSize(VariableType) <= 64 * 8 &&
+      (VariableType.isTriviallyCopyableType(Context) ||
        hasTrivialABIAttr(VariableType)))
     return;
 
   // Suggest changing from a const variable to a const reference variable
   // if doing so will prevent a copy.
-  SemaRef.Diag(VD->getLocation(), diag::warn_for_range_copy)
-      << VD << VariableType;
-  SemaRef.Diag(VD->getBeginLoc(), diag::note_use_reference_type)
-      << SemaRef.Context.getLValueReferenceType(VariableType)
-      << VD->getSourceRange()
+  Diag(VD->getLocation(), diag::warn_for_range_copy) << VD << VariableType;
+  Diag(VD->getBeginLoc(), diag::note_use_reference_type)
+      << Context.getLValueReferenceType(VariableType) << VD->getSourceRange()
       << FixItHint::CreateInsertion(VD->getLocation(), "&");
 }
 
-/// DiagnoseForRangeVariableCopies - Diagnose three cases and fixes for them.
-/// 1) for (const foo &x : foos) where foos only returns a copy.  Suggest
-///    using "const foo x" to show that a copy is made
-/// 2) for (const bar &x : foos) where bar is a temporary initialized by bar.
-///    Suggest either "const bar x" to keep the copying or "const foo& x" to
-///    prevent the copy.
-/// 3) for (const foo x : foos) where x is constructed from a reference foo.
-///    Suggest "const foo &x" to prevent the copy.
-static void DiagnoseForRangeVariableCopies(Sema &SemaRef,
-                                           const CXXForRangeStmt *ForStmt) {
-  if (SemaRef.inTemplateInstantiation())
+void Sema::DiagnoseForRangeVariableCopies(const CXXForRangeStmt *ForStmt) {
+  if (inTemplateInstantiation())
     return;
 
-  if (SemaRef.Diags.isIgnored(
-          diag::warn_for_range_const_ref_binds_temp_built_from_ref,
-          ForStmt->getBeginLoc()) &&
-      SemaRef.Diags.isIgnored(diag::warn_for_range_ref_binds_ret_temp,
-                              ForStmt->getBeginLoc()) &&
-      SemaRef.Diags.isIgnored(diag::warn_for_range_copy,
-                              ForStmt->getBeginLoc())) {
+  if (Diags.isIgnored(diag::warn_for_range_const_ref_binds_temp_built_from_ref,
+                      ForStmt->getBeginLoc()) &&
+      Diags.isIgnored(diag::warn_for_range_ref_binds_ret_temp,
+                      ForStmt->getBeginLoc()) &&
+      Diags.isIgnored(diag::warn_for_range_copy, ForStmt->getBeginLoc()))
     return;
-  }
 
   const VarDecl *VD = ForStmt->getLoopVariable();
   if (!VD)
@@ -2875,10 +2829,10 @@
     return;
 
   if (VariableType->isReferenceType()) {
-    DiagnoseForRangeReferenceVariableCopies(SemaRef, VD,
+    DiagnoseForRangeReferenceVariableCopies(VD,
                                             ForStmt->getRangeInit()->getType());
   } else if (VariableType.isConstQualified()) {
-    DiagnoseForRangeConstVariableCopies(SemaRef, VD);
+    DiagnoseForRangeConstVariableCopies(VD);
   }
 }
 
@@ -2899,7 +2853,7 @@
   DiagnoseEmptyStmtBody(ForStmt->getRParenLoc(), B,
                         diag::warn_empty_range_based_for_body);
 
-  DiagnoseForRangeVariableCopies(*this, ForStmt);
+  DiagnoseForRangeVariableCopies(ForStmt);
 
   return S;
 }
@@ -2939,11 +2893,11 @@
   return new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E);
 }
 
-static void CheckJumpOutOfSEHFinally(Sema &S, SourceLocation Loc,
-                                     const Scope &DestScope) {
-  if (!S.CurrentSEHFinally.empty() &&
-      DestScope.Contains(*S.CurrentSEHFinally.back())) {
-    S.Diag(Loc, diag::warn_jump_out_of_seh_finally);
+void Sema::CheckJumpOutOfSEHFinally(SourceLocation Loc,
+                                    const Scope &DestScope) {
+  if (!CurrentSEHFinally.empty() &&
+      DestScope.Contains(*CurrentSEHFinally.back())) {
+    Diag(Loc, diag::warn_jump_out_of_seh_finally);
   }
 }
 
@@ -2954,7 +2908,7 @@
     // C99 6.8.6.2p1: A break shall appear only in or as a loop body.
     return StmtError(Diag(ContinueLoc, diag::err_continue_not_in_loop));
   }
-  CheckJumpOutOfSEHFinally(*this, ContinueLoc, *S);
+  CheckJumpOutOfSEHFinally(ContinueLoc, *S);
 
   return new (Context) ContinueStmt(ContinueLoc);
 }
@@ -2969,7 +2923,7 @@
   if (S->isOpenMPLoopScope())
     return StmtError(Diag(BreakLoc, diag::err_omp_loop_cannot_use_stmt)
                      << "break");
-  CheckJumpOutOfSEHFinally(*this, BreakLoc, *S);
+  CheckJumpOutOfSEHFinally(BreakLoc, *S);
 
   return new (Context) BreakStmt(BreakLoc);
 }
@@ -3054,29 +3008,11 @@
   return true;
 }
 
-/// Try to perform the initialization of a potentially-movable value,
-/// which is the operand to a return or throw statement.
-///
-/// This routine implements C++14 [class.copy]p32, which attempts to treat
-/// returned lvalues as rvalues in certain cases (to prefer move construction),
-/// then falls back to treating them as lvalues if that failed.
-///
-/// \param ConvertingConstructorsOnly If true, follow [class.copy]p32 and reject
-/// resolutions that find non-constructors, such as derived-to-base conversions
-/// or `operator T()&&` member functions. If false, do consider such
-/// conversion sequences.
-///
-/// \param Res We will fill this in if move-initialization was possible.
-/// If move-initialization is not possible, such that we must fall back to
-/// treating the operand as an lvalue, we will leave Res in its original
-/// invalid state.
-static void TryMoveInitialization(Sema& S,
-                                  const InitializedEntity &Entity,
-                                  const VarDecl *NRVOCandidate,
-                                  QualType ResultType,
-                                  Expr *&Value,
-                                  bool ConvertingConstructorsOnly,
-                                  ExprResult &Res) {
+void Sema::TryMoveInitialization(const InitializedEntity &Entity,
+                                 const VarDecl *NRVOCandidate,
+                                 QualType ResultType, Expr *&Value,
+                                 bool ConvertingConstructorsOnly,
+                                 ExprResult &Res) {
   ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, Value->getType(),
                             CK_NoOp, Value, VK_XValue);
 
@@ -3085,7 +3021,7 @@
   InitializationKind Kind = InitializationKind::CreateCopy(
       Value->getBeginLoc(), Value->getBeginLoc());
 
-  InitializationSequence Seq(S, Entity, Kind, InitExpr);
+  InitializationSequence Seq(*this, Entity, Kind, InitExpr);
 
   if (!Seq)
     return;
@@ -3108,8 +3044,8 @@
             FD->getParamDecl(0)->getType()->getAs<RValueReferenceType>();
         if (!RRefType)
           break;
-        if (!S.Context.hasSameUnqualifiedType(RRefType->getPointeeType(),
-                                              NRVOCandidate->getType()))
+        if (!Context.hasSameUnqualifiedType(RRefType->getPointeeType(),
+                                            NRVOCandidate->getType()))
           break;
       } else {
         continue;
@@ -3133,12 +3069,12 @@
 
     // Promote "AsRvalue" to the heap, since we now need this
     // expression node to persist.
-    Value = ImplicitCastExpr::Create(S.Context, Value->getType(), CK_NoOp,
-                                     Value, nullptr, VK_XValue);
+    Value = ImplicitCastExpr::Create(Context, Value->getType(), CK_NoOp, Value,
+                                     nullptr, VK_XValue);
 
     // Complete type-checking the initialization of the return type
     // using the constructor we found.
-    Res = Seq.Perform(S, Entity, Kind, Value);
+    Res = Seq.Perform(*this, Entity, Kind, Value);
   }
 }
 
@@ -3180,8 +3116,8 @@
     }
 
     if (NRVOCandidate) {
-      TryMoveInitialization(*this, Entity, NRVOCandidate, ResultType, Value,
-                            true, Res);
+      TryMoveInitialization(Entity, NRVOCandidate, ResultType, Value, true,
+                            Res);
     }
 
     if (!Res.isInvalid() && AffectedByCWG1579) {
@@ -3225,7 +3161,7 @@
         } else {
           ExprResult FakeRes = ExprError();
           Expr *FakeValue = Value;
-          TryMoveInitialization(*this, Entity, FakeNRVOCandidate, ResultType,
+          TryMoveInitialization(Entity, FakeNRVOCandidate, ResultType,
                                 FakeValue, false, FakeRes);
           if (!FakeRes.isInvalid()) {
             bool IsThrow =
@@ -3601,7 +3537,7 @@
     CurScope->setNoNRVO();
   }
 
-  CheckJumpOutOfSEHFinally(*this, ReturnLoc, *CurScope->getFnParent());
+  CheckJumpOutOfSEHFinally(ReturnLoc, *CurScope->getFnParent());
 
   return R;
 }
@@ -4248,7 +4184,7 @@
     SEHTryParent = SEHTryParent->getParent();
   if (!SEHTryParent)
     return StmtError(Diag(Loc, diag::err_ms___leave_not_in___try));
-  CheckJumpOutOfSEHFinally(*this, Loc, *SEHTryParent);
+  CheckJumpOutOfSEHFinally(Loc, *SEHTryParent);
 
   return new (Context) SEHLeaveStmt(Loc);
 }
@@ -4301,23 +4237,23 @@
   return RD;
 }
 
-static bool
-buildCapturedStmtCaptureList(Sema &S, CapturedRegionScopeInfo *RSI,
-                             SmallVectorImpl<CapturedStmt::Capture> &Captures,
-                             SmallVectorImpl<Expr *> &CaptureInits) {
+bool Sema::BuildCapturedStmtCaptureList(
+    CapturedRegionScopeInfo *RSI,
+    SmallVectorImpl<CapturedStmt::Capture> &Captures,
+    SmallVectorImpl<Expr *> &CaptureInits) {
   for (const sema::Capture &Cap : RSI->Captures) {
     if (Cap.isInvalid())
       continue;
 
     // Form the initializer for the capture.
-    ExprResult Init = S.BuildCaptureInit(Cap, Cap.getLocation(),
-                                         RSI->CapRegionKind == CR_OpenMP);
+    ExprResult Init = BuildCaptureInit(Cap, Cap.getLocation(),
+                                       RSI->CapRegionKind == CR_OpenMP);
 
     // FIXME: Bail out now if the capture is not used and the initializer has
     // no side-effects.
 
     // Create a field for this capture.
-    FieldDecl *Field = S.BuildCaptureField(RSI->TheRecordDecl, Cap);
+    FieldDecl *Field = BuildCaptureField(RSI->TheRecordDecl, Cap);
 
     // Add the capture to our list of captures.
     if (Cap.isThisCapture()) {
@@ -4329,8 +4265,8 @@
     } else {
       assert(Cap.isVariableCapture() && "unknown kind of capture");
 
-      if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP)
-        S.setOpenMPCaptureKind(Field, Cap.getVariable(), RSI->OpenMPLevel);
+      if (getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP)
+        setOpenMPCaptureKind(Field, Cap.getVariable(), RSI->OpenMPLevel);
 
       Captures.push_back(CapturedStmt::Capture(Cap.getLocation(),
                                                Cap.isReferenceCapture()
@@ -4457,7 +4393,7 @@
 
   SmallVector<CapturedStmt::Capture, 4> Captures;
   SmallVector<Expr *, 4> CaptureInits;
-  if (buildCapturedStmtCaptureList(*this, RSI, Captures, CaptureInits))
+  if (BuildCapturedStmtCaptureList(RSI, Captures, CaptureInits))
     return StmtError();
 
   CapturedDecl *CD = RSI->TheCapturedDecl;
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -3101,6 +3101,26 @@
   bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType);
   bool isSameOrCompatibleFunctionType(CanQualType Param, CanQualType Arg);
 
+  /// Try to perform the initialization of a potentially-movable value,
+  /// which is the operand to a return or throw statement.
+  ///
+  /// This routine implements C++14 [class.copy]p32, which attempts to treat
+  /// returned lvalues as rvalues in certain cases (to prefer move
+  /// construction), then falls back to treating them as lvalues if that failed.
+  ///
+  /// \param ConvertingConstructorsOnly If true, follow [class.copy]p32 and
+  /// reject resolutions that find non-constructors, such as derived-to-base
+  /// conversions or `operator T()&&` member functions. If false, do consider
+  /// such conversion sequences.
+  ///
+  /// \param Res We will fill this in if move-initialization was possible.
+  /// If move-initialization is not possible, such that we must fall back to
+  /// treating the operand as an lvalue, we will leave Res in its original
+  /// invalid state.
+  void TryMoveInitialization(const InitializedEntity &Entity,
+                             const VarDecl *NRVOCandidate, QualType ResultType,
+                             Expr *&Value, bool ConvertingConstructorsOnly,
+                             ExprResult &Res);
   ExprResult PerformMoveOrCopyInitialization(const InitializedEntity &Entity,
                                              const VarDecl *NRVOCandidate,
                                              QualType ResultType,
@@ -4306,9 +4326,23 @@
                          Stmt *InitStmt,
                          ConditionResult Cond, Stmt *ThenVal,
                          SourceLocation ElseLoc, Stmt *ElseVal);
+  /// Check the specified case value is in range for the given unpromoted switch
+  /// type.
+  void CheckCaseValue(SourceLocation Loc, const llvm::APSInt &Val,
+                      unsigned UnpromotedWidth, bool UnpromotedSign);
   StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
                                     Stmt *InitStmt,
                                     ConditionResult Cond);
+  using EnumValsTy =
+      SmallVector<std::pair<llvm::APSInt, EnumConstantDecl *>, 64>;
+  /// Returns true if we should emit a diagnostic about this case expression not
+  /// being a part of the enum used in the switch controlling expression.
+  bool ShouldDiagnoseSwitchCaseNotInEnum(const EnumDecl *ED,
+                                         const Expr *CaseExpr,
+                                         EnumValsTy::iterator &EI,
+                                         EnumValsTy::iterator &EIEnd,
+                                         const llvm::APSInt &Val);
+  void CheckEnumTypesInSwitchStmt(const Expr *Cond, const Expr *Case);
   StmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
                                            Stmt *Switch, Stmt *Body);
   StmtResult ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond,
@@ -4329,6 +4363,14 @@
   StmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc,
                                         Stmt *First, Expr *collection,
                                         SourceLocation RParenLoc);
+  // Warn when the loop variable is a const reference that creates a copy.
+  // Suggest using the non-reference type for copies.  If a copy can be
+  // prevented suggest the const reference type that would do so. For instance,
+  // given "for (const &Foo : Range)", suggest "for (const Foo : Range)" to
+  // denote a copy is made for the loop.  If possible, also suggest "for (const
+  // &Bar : Range)" if this type prevents the copy altogether.
+  void DiagnoseForRangeReferenceVariableCopies(const VarDecl *VD,
+                                               QualType RangeInitType);
   StmtResult FinishObjCForCollectionStmt(Stmt *ForCollection, Stmt *Body);
 
   enum BuildForRangeKind {
@@ -4342,6 +4384,9 @@
     BFRK_Check
   };
 
+  /// Build a variable declaration for a for-range statement.
+  VarDecl *BuildForRangeVarDecl(SourceLocation Loc, QualType Type,
+                                StringRef Name);
   StmtResult ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,
                                   SourceLocation CoawaitLoc,
                                   Stmt *InitStmt,
@@ -4358,6 +4403,19 @@
                                   Stmt *LoopVarDecl,
                                   SourceLocation RParenLoc,
                                   BuildForRangeKind Kind);
+  // Warns when the loop variable can be changed to a reference type to prevent
+  // a copy.  For instance, if given "for (const Foo x : Range)" suggest
+  // "for (const Foo &x : Range)" if this form does not make a copy.
+  void DiagnoseForRangeConstVariableCopies(const VarDecl *VD);
+  /// DiagnoseForRangeVariableCopies - Diagnose three cases and fixes for them.
+  /// 1) for (const foo &x : foos) where foos only returns a copy.  Suggest
+  ///    using "const foo x" to show that a copy is made
+  /// 2) for (const bar &x : foos) where bar is a temporary initialized by bar.
+  ///    Suggest either "const bar x" to keep the copying or "const foo& x" to
+  ///    prevent the copy.
+  /// 3) for (const foo x : foos) where x is constructed from a reference foo.
+  ///    Suggest "const foo &x" to prevent the copy.
+  void DiagnoseForRangeVariableCopies(const CXXForRangeStmt *ForStmt);
   StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body);
 
   StmtResult ActOnGotoStmt(SourceLocation GotoLoc,
@@ -4366,9 +4424,14 @@
   StmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc,
                                    SourceLocation StarLoc,
                                    Expr *DestExp);
+  void CheckJumpOutOfSEHFinally(SourceLocation Loc, const Scope &DestScope);
   StmtResult ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope);
   StmtResult ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope);
 
+  bool
+  BuildCapturedStmtCaptureList(sema::CapturedRegionScopeInfo *RSI,
+                               SmallVectorImpl<CapturedStmt::Capture> &Captures,
+                               SmallVectorImpl<Expr *> &CaptureInits);
   void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
                                 CapturedRegionKind Kind, unsigned NumParams);
   typedef std::pair<StringRef, QualType> CapturedParamNameType;
@@ -4490,6 +4553,14 @@
   /// of it.
   void MarkUnusedFileScopedDecl(const DeclaratorDecl *D);
 
+  /// Diagnose unused comparisons, both builtin and overloaded operators.
+  /// For '==' and '!=', suggest fixits for '=' or '|='.
+  ///
+  /// Adding a cast to void (or other expression wrappers) will prevent the
+  /// warning from firing.
+  bool DiagnoseUnusedComparison(const Expr *E);
+  bool DiagnoseNoDiscard(const WarnUnusedResultAttr *A, SourceLocation Loc,
+                         SourceRange R1, SourceRange R2, bool IsCtor);
   /// DiagnoseUnusedExprResult - If the statement passed in is an expression
   /// whose result is unused, warn.
   void DiagnoseUnusedExprResult(const Stmt *S);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to