[clang] 097ce76 - [analyzer] Deprecate FAM analyzer-config, recommend -fstrict-flex-arrays instead

Balazs Benics via cfe-commits cfe-commits at lists.llvm.org
Fri Nov 25 01:25:58 PST 2022


Author: Balazs Benics
Date: 2022-11-25T10:24:56+01:00
New Revision: 097ce7616527b8948b2a69d1300a44f552959a43

URL: https://github.com/llvm/llvm-project/commit/097ce7616527b8948b2a69d1300a44f552959a43
DIFF: https://github.com/llvm/llvm-project/commit/097ce7616527b8948b2a69d1300a44f552959a43.diff

LOG: [analyzer] Deprecate FAM analyzer-config, recommend -fstrict-flex-arrays instead

By default, clang assumes that all trailing array objects could be a
FAM. So, an array of undefined size, size 0, size 1, or even size 42 is
considered as FAMs for optimizations at least.

One needs to override the default behavior by supplying the
`-fstrict-flex-arrays=<N>` flag, with `N > 0` value to reduce the set of
FAM candidates. Value `3` is the most restrictive and `0` is the most
permissive on this scale.

0: all trailing arrays are FAMs
1: only incomplete, zero and one-element arrays are FAMs
2: only incomplete, zero-element arrays are FAMs
3: only incomplete arrays are FAMs

If the user is happy with consdering single-element arrays as FAMs, they
just need to remove the
`consider-single-element-arrays-as-flexible-array-members` from the
command line.
Otherwise, if they don't want to recognize such cases as FAMs, they
should specify `-fstrict-flex-arrays` anyway, which will be picked up by
CSA.

Any use of the deprecated analyzer-config value will trigger a warning
explaining what to use instead.
The `-analyzer-config-help` is updated accordingly.

Depends on D138657

Reviewed By: xazax.hun

Differential Revision: https://reviews.llvm.org/D138659

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/DiagnosticDriverKinds.td
    clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
    clang/lib/Frontend/CompilerInvocation.cpp
    clang/lib/StaticAnalyzer/Core/MemRegion.cpp
    clang/test/Analysis/deprecated-flags-and-options.cpp
    clang/test/Analysis/flexible-array-members.c

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ac7a18303d094..e9280cac12ff2 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -827,6 +827,12 @@ Static Analyzer
   ``scanbuild`` was also updated accordingly.
   Passing these flags will result in a hard error.
 
+- Deprecate the ``consider-single-element-arrays-as-flexible-array-members``
+  analyzer-config option.
+  This option will be still accepted, but a warning will be displayed.
+  This option will be rejected, thus turned into a hard error starting with
+  ``clang-17``. Use ``-fstrict-flex-array=<N>`` instead if necessary.
+
 - Trailing array objects of structs with single elements will be considered
   as flexible-array-members. Use ``-fstrict-flex-array=<N>`` to define
   what should be considered as flexible-array-member if needed.

diff  --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 119ad57466b65..6479518454d5d 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -458,6 +458,10 @@ def warn_analyzer_deprecated_option : Warning<
   "analyzer option '%0' is deprecated. This flag will be removed in %1, and "
   "passing this option will be an error.">,
   InGroup<DeprecatedStaticAnalyzerFlag>;
+def warn_analyzer_deprecated_option_with_alternative : Warning<
+  "analyzer option '%0' is deprecated. This flag will be removed in %1, and "
+  "passing this option will be an error. Use '%2' instead.">,
+  InGroup<DeprecatedStaticAnalyzerFlag>;
 
 def warn_drv_needs_hvx : Warning<
   "%0 requires HVX, use -mhvx/-mhvx= to enable it">,

diff  --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
index 1f22801f1e4ab..acfbcf67b1b9d 100644
--- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
+++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
@@ -331,7 +331,8 @@ ANALYZER_OPTION(
     "consider-single-element-arrays-as-flexible-array-members",
     "Consider single element arrays as flexible array member candidates. "
     "This will prevent the analyzer from assuming that a single element array "
-    "holds a single element.",
+    "holds a single element. [DEPRECATED, removing in clang-17; "
+    "use '-fstrict-flex-arrays=<N>' instead]",
     true)
 
 ANALYZER_OPTION(

diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index a13da5a4e078c..953631955cbbf 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1018,6 +1018,15 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
 
       A->claim();
       Opts.Config[key] = std::string(val);
+
+      // FIXME: Remove this hunk after clang-17 released.
+      constexpr auto SingleFAM =
+          "consider-single-element-arrays-as-flexible-array-members";
+      if (key == SingleFAM) {
+        Diags.Report(diag::warn_analyzer_deprecated_option_with_alternative)
+            << SingleFAM << "clang-17"
+            << "-fstrict-flex-arrays=<N>";
+      }
     }
   }
 

diff  --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index 0b504c3d452d7..289b0a7db5c9c 100644
--- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -790,22 +790,30 @@ DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR,
         return true;
 
       if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
-        const llvm::APInt &Size = CAT->getSize();
-        if (Size.isZero())
-          return true;
-
         using FAMKind = LangOptions::StrictFlexArraysLevelKind;
         const FAMKind StrictFlexArraysLevel =
           Ctx.getLangOpts().getStrictFlexArraysLevel();
-        if (StrictFlexArraysLevel == FAMKind::ZeroOrIncomplete ||
-            StrictFlexArraysLevel == FAMKind::IncompleteOnly)
-          return false;
-
         const AnalyzerOptions &Opts = SVB.getAnalyzerOptions();
-        // FIXME: this option is probably redundant with -fstrict-flex-arrays=1.
-        if (Opts.ShouldConsiderSingleElementArraysAsFlexibleArrayMembers &&
-            Size.isOne())
+        const llvm::APInt &Size = CAT->getSize();
+
+        if (StrictFlexArraysLevel <= FAMKind::ZeroOrIncomplete && Size.isZero())
           return true;
+
+        // The "-fstrict-flex-arrays" should have precedence over
+        // consider-single-element-arrays-as-flexible-array-members
+        // analyzer-config when checking single element arrays.
+        if (StrictFlexArraysLevel == FAMKind::Default) {
+          // FIXME: After clang-17 released, we should remove this branch.
+          if (Opts.ShouldConsiderSingleElementArraysAsFlexibleArrayMembers &&
+              Size.isOne())
+            return true;
+        } else {
+          // -fstrict-flex-arrays was specified, since it's not the default, so
+          // ignore analyzer-config.
+          if (StrictFlexArraysLevel <= FAMKind::OneZeroOrIncomplete &&
+              Size.isOne())
+            return true;
+        }
       }
       return false;
     };

diff  --git a/clang/test/Analysis/deprecated-flags-and-options.cpp b/clang/test/Analysis/deprecated-flags-and-options.cpp
index 23272c1b96688..6fbb3113c829a 100644
--- a/clang/test/Analysis/deprecated-flags-and-options.cpp
+++ b/clang/test/Analysis/deprecated-flags-and-options.cpp
@@ -9,6 +9,15 @@
 // RUN: | FileCheck %s --check-prefixes=DEPRECATED-NESTED-BLOCKS
 // DEPRECATED-NESTED-BLOCKS: error: unknown argument: '-analyzer-opt-analyze-nested-blocks'
 
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -analyzer-config consider-single-element-arrays-as-flexible-array-members=true %s 2>&1 \
+// RUN: | FileCheck %s --check-prefixes=CHECK,DEPRECATED-SINGLE-ELEM-FAM
+// DEPRECATED-SINGLE-ELEM-FAM: warning: analyzer option 'consider-single-element-arrays-as-flexible-array-members' is deprecated. This flag will be removed in clang-17, and passing this option will be an error. Use '-fstrict-flex-arrays=<N>' instead.
+
+// RUN: %clang_analyze_cc1 -analyzer-config-help 2>&1 \
+// RUN:   | FileCheck %s --check-prefixes=CHECK-HELP
+// CHECK-HELP:      [DEPRECATED, removing in clang-17; use '-fstrict-flex-arrays=<N>'
+// CHECK-HELP-NEXT: instead] (default: true)
+
 int empty(int x) {
   // CHECK: warning: Division by zero
   return x ? 0 : 0 / x;

diff  --git a/clang/test/Analysis/flexible-array-members.c b/clang/test/Analysis/flexible-array-members.c
index a139883d0d6bf..dc131c6f1a437 100644
--- a/clang/test/Analysis/flexible-array-members.c
+++ b/clang/test/Analysis/flexible-array-members.c
@@ -1,27 +1,30 @@
+// -fstrict-flex-arrays=2 means that only undefined or zero element arrays are considered as FAMs.
+
 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c90 \
-// RUN:    -analyzer-config consider-single-element-arrays-as-flexible-array-members=false
+// RUN:    -fstrict-flex-arrays=2
 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c99 \
-// RUN:    -analyzer-config consider-single-element-arrays-as-flexible-array-members=false
+// RUN:    -fstrict-flex-arrays=2
 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c11 \
-// RUN:    -analyzer-config consider-single-element-arrays-as-flexible-array-members=false
+// RUN:    -fstrict-flex-arrays=2
 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c17 \
-// RUN:    -analyzer-config consider-single-element-arrays-as-flexible-array-members=false
+// RUN:    -fstrict-flex-arrays=2
 
 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c++98 -x c++ \
-// RUN:    -analyzer-config consider-single-element-arrays-as-flexible-array-members=false
+// RUN:    -fstrict-flex-arrays=2
 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c++03 -x c++ \
-// RUN:    -analyzer-config consider-single-element-arrays-as-flexible-array-members=false
+// RUN:    -fstrict-flex-arrays=2
 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c++11 -x c++ \
-// RUN:    -analyzer-config consider-single-element-arrays-as-flexible-array-members=false
+// RUN:    -fstrict-flex-arrays=2
 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c++14 -x c++ \
-// RUN:    -analyzer-config consider-single-element-arrays-as-flexible-array-members=false
+// RUN:    -fstrict-flex-arrays=2
 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c++17 -x c++ \
-// RUN:    -analyzer-config consider-single-element-arrays-as-flexible-array-members=false
+// RUN:    -fstrict-flex-arrays=2
 
+// By default, -fstrict-flex-arrays=0, which means that even single element arrays are considered as FAMs.
 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c17 \
-// RUN:    -analyzer-config consider-single-element-arrays-as-flexible-array-members=true -DSINGLE_ELEMENT_FAMS
+// RUN:    -DSINGLE_ELEMENT_FAMS
 // RUN: %clang_analyze_cc1 -triple x86_64-linux-gnu -analyzer-checker=core,unix,debug.ExprInspection %s -verify -std=c++17 -x c++ \
-// RUN:    -analyzer-config consider-single-element-arrays-as-flexible-array-members=true -DSINGLE_ELEMENT_FAMS
+// RUN:    -DSINGLE_ELEMENT_FAMS
 
 typedef __typeof(sizeof(int)) size_t;
 size_t clang_analyzer_getExtent(void *);


        


More information about the cfe-commits mailing list