diff --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def index acfbcf67b1b9d..2fc825c2af9c3 100644 --- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def +++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def @@ -326,15 +326,6 @@ ANALYZER_OPTION(bool, ShouldSupportSymbolicIntegerCasts, "Produce cast symbols for integral types.", false) -ANALYZER_OPTION( - bool, ShouldConsiderSingleElementArraysAsFlexibleArrayMembers, - "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. [DEPRECATED, removing in clang-17; " - "use '-fstrict-flex-arrays=' instead]", - true) - ANALYZER_OPTION( bool, ShouldAssumeControlledEnvironment, "assume-controlled-environment", "Whether the analyzed application runs in a controlled environment. " diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index dca8853f1c204..50440e65a6225 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1056,15 +1056,6 @@ 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="; - } } } diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp index 912ba71dd5738..f89e71a4f157b 100644 --- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -805,49 +805,46 @@ DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR, // We currently don't model flexible array members (FAMs), which are: // - int array[]; of IncompleteArrayType // - int array[0]; of ConstantArrayType with size 0 - // - int array[1]; of ConstantArrayType with size 1 (*) - // (*): Consider single element array object members as FAM candidates only - // if the consider-single-element-arrays-as-flexible-array-members - // analyzer option is true. + // - int array[1]; of ConstantArrayType with size 1 // https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html - const auto isFlexibleArrayMemberCandidate = [this, - &SVB](QualType Ty) -> bool { - const ArrayType *AT = Ctx.getAsArrayType(Ty); + const auto isFlexibleArrayMemberCandidate = + [this](const ArrayType *AT) -> bool { if (!AT) return false; - if (isa(AT)) - return true; - if (const auto *CAT = dyn_cast(AT)) { - using FAMKind = LangOptions::StrictFlexArraysLevelKind; - const FAMKind StrictFlexArraysLevel = + auto IsIncompleteArray = [](const ArrayType *AT) { + return isa(AT); + }; + auto IsArrayOfZero = [](const ArrayType *AT) { + const auto *CAT = dyn_cast(AT); + return CAT && CAT->getSize() == 0; + }; + auto IsArrayOfOne = [](const ArrayType *AT) { + const auto *CAT = dyn_cast(AT); + return CAT && CAT->getSize() == 1; + }; + + using FAMKind = LangOptions::StrictFlexArraysLevelKind; + const FAMKind StrictFlexArraysLevel = Ctx.getLangOpts().getStrictFlexArraysLevel(); - const AnalyzerOptions &Opts = SVB.getAnalyzerOptions(); - 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; + + // "Default": Any trailing array member is a FAM. + // Since we cannot tell at this point if this array is a trailing member + // or not, let's just do the same as for "OneZeroOrIncomplete". + if (StrictFlexArraysLevel == FAMKind::Default) + return IsArrayOfOne(AT) || IsArrayOfZero(AT) || IsIncompleteArray(AT); + + if (StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete) + return IsArrayOfOne(AT) || IsArrayOfZero(AT) || IsIncompleteArray(AT); + + if (StrictFlexArraysLevel == FAMKind::ZeroOrIncomplete) + return IsArrayOfZero(AT) || IsIncompleteArray(AT); + + assert(StrictFlexArraysLevel == FAMKind::IncompleteOnly); + return IsIncompleteArray(AT); }; - if (isFlexibleArrayMemberCandidate(Ty)) + if (isFlexibleArrayMemberCandidate(Ctx.getAsArrayType(Ty))) return UnknownVal(); return Size; diff --git a/clang/test/Analysis/analyzer-config.c b/clang/test/Analysis/analyzer-config.c index ed5e6c8cca63c..4fd00068b7d9c 100644 --- a/clang/test/Analysis/analyzer-config.c +++ b/clang/test/Analysis/analyzer-config.c @@ -33,7 +33,6 @@ // CHECK-NEXT: cfg-rich-constructors = true // CHECK-NEXT: cfg-scopes = false // CHECK-NEXT: cfg-temporary-dtors = true -// CHECK-NEXT: consider-single-element-arrays-as-flexible-array-members = true // CHECK-NEXT: core.CallAndMessage:ArgInitializedness = true // CHECK-NEXT: core.CallAndMessage:ArgPointeeInitializedness = false // CHECK-NEXT: core.CallAndMessage:CXXDeallocationArg = true diff --git a/clang/test/Analysis/deprecated-flags-and-options.cpp b/clang/test/Analysis/deprecated-flags-and-options.cpp index 6fbb3113c829a..588e27c4839fe 100644 --- a/clang/test/Analysis/deprecated-flags-and-options.cpp +++ b/clang/test/Analysis/deprecated-flags-and-options.cpp @@ -1,6 +1,3 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core %s 2>&1 \ -// RUN: | FileCheck %s --check-prefixes=CHECK - // RUN: not %clang_analyze_cc1 -analyzer-checker=core -analyzer-store=region %s 2>&1 \ // RUN: | FileCheck %s --check-prefixes=DEPRECATED-STORE // DEPRECATED-STORE: error: unknown argument: '-analyzer-store=region' @@ -9,16 +6,9 @@ // 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=' instead. +// RUN: not %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=DEPRECATED-SINGLE-ELEM-FAM +// DEPRECATED-SINGLE-ELEM-FAM: error: unknown analyzer-config 'consider-single-element-arrays-as-flexible-array-members' -// 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=' -// CHECK-HELP-NEXT: instead] (default: true) -int empty(int x) { - // CHECK: warning: Division by zero - return x ? 0 : 0 / x; -} +void empty() {}