zequanwu updated this revision to Diff 264076.
zequanwu added a comment.

Add new warning as subgroup of `Uninitialized`.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D79895/new/

https://reviews.llvm.org/D79895

Files:
  clang/include/clang/Analysis/Analyses/UninitializedValues.h
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Analysis/UninitializedValues.cpp
  clang/lib/Sema/AnalysisBasedWarnings.cpp
  clang/test/SemaCXX/uninit-variables.cpp
  clang/test/SemaCXX/uninitialized.cpp

Index: clang/test/SemaCXX/uninitialized.cpp
===================================================================
--- clang/test/SemaCXX/uninitialized.cpp
+++ clang/test/SemaCXX/uninitialized.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -Wall -Wuninitialized -Wno-unused-value -Wno-unused-lambda-capture -std=c++1z -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wall -Wuninitialized -Wno-unused-value -Wno-unused-lambda-capture -Wno-uninitialized-const-reference -std=c++1z -verify %s
 
 // definitions for std::move
 namespace std {
Index: clang/test/SemaCXX/uninit-variables.cpp
===================================================================
--- clang/test/SemaCXX/uninit-variables.cpp
+++ clang/test/SemaCXX/uninit-variables.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -Wuninitialized -fsyntax-only -fcxx-exceptions %s -verify -std=c++1y
+// RUN: %clang_cc1 -fsyntax-only -Wuninitialized -Wno-uninitialized-const-reference -fsyntax-only -fcxx-exceptions %s -verify -std=c++1y
 
 // Stub out types for 'typeid' to work.
 namespace std { class type_info {}; }
Index: clang/lib/Sema/AnalysisBasedWarnings.cpp
===================================================================
--- clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -834,6 +834,10 @@
     // Carry on to report sometimes-uninitialized branches, if possible,
     // or a 'may be used uninitialized' diagnostic otherwise.
     break;
+  case UninitUse::ConstRefUse:
+    S.Diag(Use.getUser()->getBeginLoc(), diag::warn_uninit_const_reference)
+        << VD->getDeclName() << Use.getUser()->getSourceRange();
+    break;
   }
 
   // Diagnose each branch which leads to a sometimes-uninitialized use.
@@ -1000,8 +1004,11 @@
 
       ContainsReference CR(S.Context, DRE);
       CR.Visit(Initializer);
+      unsigned DiagID = Use.getKind() == UninitUse::ConstRefUse
+                            ? diag::warn_uninit_const_reference
+                            : diag::warn_uninit_self_reference_in_init;
       if (CR.doesContainReference()) {
-        S.Diag(DRE->getBeginLoc(), diag::warn_uninit_self_reference_in_init)
+        S.Diag(DRE->getBeginLoc(), DiagID)
             << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange();
         return true;
       }
@@ -1541,7 +1548,7 @@
       if (!vec->empty() && hasSelfInit && hasAlwaysUninitializedUse(vec))
         DiagnoseUninitializedUse(S, vd,
                                  UninitUse(vd->getInit()->IgnoreParenCasts(),
-                                           /* isAlwaysUninit */ true),
+                                           /* isAlwaysUninit */ true, false),
                                  /* alwaysReportSelfInit */ true);
       else {
         // Sort the uses by their SourceLocations.  While not strictly
@@ -1557,7 +1564,7 @@
 
         for (const auto &U : *vec) {
           // If we have self-init, downgrade all uses to 'may be uninitialized'.
-          UninitUse Use = hasSelfInit ? UninitUse(U.getUser(), false) : U;
+          UninitUse Use = hasSelfInit ? UninitUse(U.getUser(), false, false) : U;
 
           if (DiagnoseUninitializedUse(S, vd, Use))
             // Skip further diagnostics for this variable. We try to warn only
@@ -2184,7 +2191,8 @@
 
   if (!Diags.isIgnored(diag::warn_uninit_var, D->getBeginLoc()) ||
       !Diags.isIgnored(diag::warn_sometimes_uninit_var, D->getBeginLoc()) ||
-      !Diags.isIgnored(diag::warn_maybe_uninit_var, D->getBeginLoc())) {
+      !Diags.isIgnored(diag::warn_maybe_uninit_var, D->getBeginLoc()) ||
+      !Diags.isIgnored(diag::warn_uninit_const_reference, D->getBeginLoc())) {
     if (CFG *cfg = AC.getCFG()) {
       UninitValsDiagReporter reporter(S);
       UninitVariablesAnalysisStats stats;
Index: clang/lib/Analysis/UninitializedValues.cpp
===================================================================
--- clang/lib/Analysis/UninitializedValues.cpp
+++ clang/lib/Analysis/UninitializedValues.cpp
@@ -268,6 +268,7 @@
     Init,
     Use,
     SelfInit,
+    ConstRefUse,
     Ignore
   };
 
@@ -413,14 +414,16 @@
     return;
   }
 
-  // If a value is passed by const pointer or by const reference to a function,
+  // If a value is passed by const pointer to a function,
   // we should not assume that it is initialized by the call, and we
   // conservatively do not assume that it is used.
+  // If a value is passed by const reference to a function,
+  // it should already be initialized.
   for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
        I != E; ++I) {
     if ((*I)->isGLValue()) {
       if ((*I)->getType().isConstQualified())
-        classify((*I), Ignore);
+        classify((*I), ConstRefUse);
     } else if (isPointerToConst((*I)->getType())) {
       const Expr *Ex = stripCasts(DC->getParentASTContext(), *I);
       const auto *UO = dyn_cast<UnaryOperator>(Ex);
@@ -468,7 +471,7 @@
         classification(classification), objCNoRet(ac.getASTContext()),
         handler(handler) {}
 
-  void reportUse(const Expr *ex, const VarDecl *vd);
+  void reportUse(const Expr *ex, const VarDecl *vd, bool ConstRestUse = false);
 
   void VisitBinaryOperator(BinaryOperator *bo);
   void VisitBlockExpr(BlockExpr *be);
@@ -488,8 +491,9 @@
     return ::findVar(ex, cast<DeclContext>(ac.getDecl()));
   }
 
-  UninitUse getUninitUse(const Expr *ex, const VarDecl *vd, Value v) {
-    UninitUse Use(ex, isAlwaysUninit(v));
+  UninitUse getUninitUse(const Expr *ex, const VarDecl *vd, Value v,
+                         bool ConstRefUse) {
+    UninitUse Use(ex, isAlwaysUninit(v), ConstRefUse);
 
     assert(isUninitialized(v));
     if (Use.getKind() == UninitUse::Always)
@@ -661,10 +665,11 @@
 
 } // namespace
 
-void TransferFunctions::reportUse(const Expr *ex, const VarDecl *vd) {
+void TransferFunctions::reportUse(const Expr *ex, const VarDecl *vd,
+                                  bool ConstRefUse) {
   Value v = vals[vd];
   if (isUninitialized(v))
-    handler.handleUseOfUninitVariable(vd, getUninitUse(ex, vd, v));
+    handler.handleUseOfUninitVariable(vd, getUninitUse(ex, vd, v, ConstRefUse));
 }
 
 void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS) {
@@ -736,6 +741,9 @@
   case ClassifyRefs::SelfInit:
       handler.handleSelfInit(cast<VarDecl>(dr->getDecl()));
     break;
+  case ClassifyRefs::ConstRefUse:
+    reportUse(dr, cast<VarDecl>(dr->getDecl()), true);
+    break;
   }
 }
 
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2106,6 +2106,10 @@
   "cannot initialize %select{non-class|reference}0 type %1 with a "
   "parenthesized initializer list">;
 
+def warn_uninit_const_reference : Warning<
+  "variable %0 is uninitialized when passes as a const reference parameter "
+  "here">, InGroup<UninitializedConstReference>, DefaultIgnore;
+
 def warn_unsequenced_mod_mod : Warning<
   "multiple unsequenced modifications to %0">, InGroup<Unsequenced>;
 def warn_unsequenced_mod_use : Warning<
Index: clang/include/clang/Basic/DiagnosticGroups.td
===================================================================
--- clang/include/clang/Basic/DiagnosticGroups.td
+++ clang/include/clang/Basic/DiagnosticGroups.td
@@ -624,8 +624,10 @@
 def UninitializedMaybe : DiagGroup<"conditional-uninitialized">;
 def UninitializedSometimes : DiagGroup<"sometimes-uninitialized">;
 def UninitializedStaticSelfInit : DiagGroup<"static-self-init">;
+def UninitializedConstReference : DiagGroup<"uninitialized-const-reference">;
 def Uninitialized  : DiagGroup<"uninitialized", [UninitializedSometimes,
-                                                 UninitializedStaticSelfInit]>;
+                                                 UninitializedStaticSelfInit,
+                                                 UninitializedConstReference]>;
 def IgnoredPragmaIntrinsic : DiagGroup<"ignored-pragma-intrinsic">;
 // #pragma optimize is often used to avoid to work around MSVC codegen bugs or
 // to disable inlining. It's not completely clear what alternative to suggest
Index: clang/include/clang/Analysis/Analyses/UninitializedValues.h
===================================================================
--- clang/include/clang/Analysis/Analyses/UninitializedValues.h
+++ clang/include/clang/Analysis/Analyses/UninitializedValues.h
@@ -47,13 +47,16 @@
   /// Does this use always see an uninitialized value?
   bool AlwaysUninit;
 
+  /// Is this use a const reference parameter?
+  bool ConstRef;
+
   /// This use is always uninitialized if it occurs after any of these branches
   /// is taken.
   SmallVector<Branch, 2> UninitBranches;
 
 public:
-  UninitUse(const Expr *User, bool AlwaysUninit)
-      : User(User), AlwaysUninit(AlwaysUninit) {}
+  UninitUse(const Expr *User, bool AlwaysUninit, bool ConstRef)
+      : User(User), AlwaysUninit(AlwaysUninit), ConstRef(ConstRef) {}
 
   void addUninitBranch(Branch B) {
     UninitBranches.push_back(B);
@@ -82,12 +85,17 @@
     AfterCall,
 
     /// The use is always uninitialized.
-    Always
+    Always,
+
+    /// The use is uninitialized when passes as const reference parameter to a
+    /// function
+    ConstRefUse
   };
 
   /// Get the kind of uninitialized use.
   Kind getKind() const {
-    return AlwaysUninit ? Always :
+    return ConstRef? ConstRefUse :
+           AlwaysUninit ? Always :
            UninitAfterCall ? AfterCall :
            UninitAfterDecl ? AfterDecl :
            !branch_empty() ? Sometimes : Maybe;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to