Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions build.bat
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ for %%x in (%*) do (
)

IF "%%x"=="-analysis" (
REM MSBuild passes /c to clang-tidy; do not let /WX make this unused argument fatal.
SET extra_analysis=/p:EnableClangTidyCodeAnalysis=True /p:ClangTidyChecks=clang-analyzer-* /p:ClangTidyAdditionalOptions=-Wno-error=unused-command-line-argument /p:RunCodeAnalysis=True
REM MSBuild passes /c to clang-tidy, which does not compile. Ignore only unused driver arguments.
SET extra_analysis=/p:EnableClangTidyCodeAnalysis=True /p:ClangTidyChecks=clang-analyzer-* /p:ClangTidyAdditionalOptions=-Wno-unused-command-line-argument /p:RunCodeAnalysis=True
)
)

Expand Down
4 changes: 0 additions & 4 deletions shared/libebm/BoosterCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -500,10 +500,6 @@ ErrorEbm BoosterCore::Create(void* const rng,
EBM_ASSERT(1 <= cFeatures); // since our iFeature is valid and index 0 would mean cFeatures == 1
EBM_ASSERT(nullptr != pBoosterCore->m_aFeatures);

// Clang does not seems to understand that iFeature is bound to the legal
// range of m_aFeatures through the check "cFeatures <= iFeature" above
StopClangAnalysis();

const FeatureBoosting* const pInputFeature = &pBoosterCore->m_aFeatures[iFeature];
pTermFeature->m_pFeature = pInputFeature;
pTermFeature->m_cStride = cTensorBins;
Expand Down
3 changes: 3 additions & 0 deletions shared/libebm/CalcInteractionStrength.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,9 @@ EBM_API_BODY ErrorEbm EBM_CALLING_CONVENTION CalcInteractionStrength(Interaction
}
}

// The checked tree-node size and the nonempty tensor make this allocation nonzero.
EBM_ASSERT(0 != cBytes);
ANALYSIS_ASSERT(0 != cBytes);
pTreeNodesTemp = malloc(cBytes);
if(nullptr == pTreeNodesTemp) {
free(aWeights);
Expand Down
2 changes: 2 additions & 0 deletions shared/libebm/CutWinsorized.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,10 @@ EBM_API_BODY ErrorEbm EBM_CALLING_CONVENTION CutWinsorized(
++pHigh;

EBM_ASSERT(aFeatureVals <= pLow && pLow < aFeatureVals + cSamples);
ANALYSIS_ASSERT(aFeatureVals <= pLow && pLow < aFeatureVals + cSamples);
lowCur = *pLow;
EBM_ASSERT(aFeatureVals <= pHigh && pHigh < aFeatureVals + cSamples);
ANALYSIS_ASSERT(aFeatureVals <= pHigh && pHigh < aFeatureVals + cSamples);
highCur = *pHigh;
// since valMin != valMax per above, we know there is a transition SOMEWHERE, which will exit us
} while(LIKELY(lowCur == highCur));
Expand Down
3 changes: 3 additions & 0 deletions shared/libebm/DataSetBoosting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,9 @@ ErrorEbm DataSetBoosting::InitBags(const bool bAllocateCachedTensors,
double weight = double{1};
if(nullptr != pOccurrencesFrom) {
EBM_ASSERT(size_t{0} != cInnerBags);
// InitDataSetBoosting partitions exactly cIncludedSamples across the subsets.
EBM_ASSERT(pOccurrencesFrom < aOccurrencesFrom + cIncludedSamples);
ANALYSIS_ASSERT(pOccurrencesFrom < aOccurrencesFrom + cIncludedSamples);
const uint8_t cOccurrences = *pOccurrencesFrom;
++pOccurrencesFrom;
weight = static_cast<double>(cOccurrences);
Expand Down
6 changes: 4 additions & 2 deletions shared/libebm/GenerateTermUpdate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,9 @@ static ErrorEbm BoostMultiDimensional(BoosterShell* const pBoosterShell,
double* aWeights = nullptr;
double* pGradient = nullptr;
double* pHessian = nullptr;
if(0 != ((TermBoostFlags_PurifyUpdate | TermBoostFlags_PurifyGain) & flags)) {
const bool bPurifyUpdate = 0 != (TermBoostFlags_PurifyUpdate & flags);
const bool bPurifyGain = 0 != (TermBoostFlags_PurifyGain & flags);
if(bPurifyUpdate || bPurifyGain) {
// allocate the biggest tensor that is possible to split into

// TODO: cache this memory allocation so that we don't do it each time
Expand Down Expand Up @@ -537,7 +539,7 @@ static ErrorEbm BoostMultiDimensional(BoosterShell* const pBoosterShell,
EBM_ASSERT(!std::isnan(*pTotalGain));
EBM_ASSERT(0 <= *pTotalGain);

if(0 != (TermBoostFlags_PurifyUpdate & flags) && 0 == (TermBoostFlags_PurifyGain & flags)) {
if(bPurifyUpdate && !bPurifyGain) {
Tensor* const pTensor = pBoosterShell->GetInnerTermUpdate();

size_t cDimensions = pTerm->GetCountDimensions();
Expand Down
2 changes: 2 additions & 0 deletions shared/libebm/PartitionOneDimensionalBoosting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ static ErrorEbm Flatten(BoosterShell* const pBoosterShell,
EBM_ASSERT(nullptr != pBoosterShell);
EBM_ASSERT(iDimension <= k_cDimensionsMax);
EBM_ASSERT(nullptr != apBins);
ANALYSIS_ASSERT(nullptr != apBins);
EBM_ASSERT(nullptr != apBinsEnd);
EBM_ASSERT(apBins < apBinsEnd); // if zero bins then we should have handled elsewhere
EBM_ASSERT(2 <= cSlices); // if there were no cuts then we wouldn't satisfy the minimum gain
Expand Down Expand Up @@ -269,6 +270,7 @@ static ErrorEbm Flatten(BoosterShell* const pBoosterShell,
goto determine_bin;
}
EBM_ASSERT(!bNominal);
ANALYSIS_ASSERT(!bNominal);

iEdge = reinterpret_cast<const void* const*>(ppBinLast) - reinterpret_cast<const void* const*>(apBins) + 1;

Expand Down
3 changes: 3 additions & 0 deletions shared/libebm/Purify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2089,6 +2089,9 @@ EBM_API_BODY ErrorEbm EBM_CALLING_CONVENTION Purify(double tolerance,
++iExclude;
} while(cDimensions != iExclude);

// Nonempty tensors with at least two dimensions have nonempty surfaces.
EBM_ASSERT(0 != cSurfaceBins);
ANALYSIS_ASSERT(0 != cSurfaceBins);
if(IsMultiplyError(cScoresArrayBytes, cSurfaceBins)) {
LOG_0(Trace_Error, "ERROR Purify IsMultiplyError(cScoresArrayBytes, cSurfaceBins)");
return Error_IllegalParamVal;
Expand Down
12 changes: 5 additions & 7 deletions shared/libebm/interpretable_numerics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,11 +378,6 @@ static double StringToFloatWithFixup(const char* const str, const size_t iIdenti
return ret;
}

INLINE_ALWAYS static char* strcpy_NO_WARNINGS(char* const dest, const char* const src) EBM_NOEXCEPT {
StopClangAnalysis();
return strcpy(dest, src);
}

static bool StringToFloatChopped(const char* const pStr,
size_t iTruncateMantissaTextDigitsAfterFirstDigit,
double* const pLowChopOut,
Expand All @@ -406,7 +401,9 @@ static bool StringToFloatChopped(const char* const pStr,
iTruncateMantissaTextDigitsAfterFirstDigit + size_t{3};

memcpy(strTruncated, pStr, iTruncateTextAfter * sizeof(*pStr));
strcpy_NO_WARNINGS(&strTruncated[iTruncateTextAfter], &pStr[k_iExp]);
// FloatToFullString bounds the source; truncation moves its exponent earlier in an equally sized buffer.
// NOLINTNEXTLINE(clang-analyzer-security.insecureAPI.strcpy)
strcpy(&strTruncated[iTruncateTextAfter], &pStr[k_iExp]);

if(PREDICTABLE(nullptr != pLowChopOut)) {
*pLowChopOut = StringToFloatWithFixup(strTruncated, iTruncateTextAfter);
Expand All @@ -419,7 +416,8 @@ static bool StringToFloatChopped(const char* const pStr,
}
while(true) {
ch = *pDigit;
if('.' == ch) {
if(strTruncated + size_t{2} == pDigit) {
EBM_ASSERT('.' == ch);
--pDigit;
start_at_top:;
EBM_ASSERT(strTruncated + size_t{1} == pDigit);
Expand Down
6 changes: 6 additions & 0 deletions shared/libebm/unzoned/unzoned.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,17 @@ extern "C" {

INLINE_ALWAYS static void StopClangAnalysis(void) EBM_NOEXCEPT ANALYZER_NORETURN {}

#if defined(__clang__)
#define ANALYSIS_ASSERT(b) \
do { \
if(!(b)) \
StopClangAnalysis(); \
} while((void)0, 0)
#elif defined(_MSC_VER)
#define ANALYSIS_ASSERT(b) __analysis_assume(b)
#else
#define ANALYSIS_ASSERT(b) ((void)0)
#endif

// Disable this for now. Using fast reciprocals seems to change the results quite a bit
// and make them worse. Also, the reciprocal algorithm is different between Intel and AMD
Expand Down
Loading