diff --git a/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp b/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp index 8b404377186e9..9cf31af37f116 100644 --- a/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp @@ -142,19 +142,25 @@ std::optional tryExpandAsInteger(StringRef Macro, const Preprocessor &PP) { if (InvalidSpelling) return std::nullopt; - llvm::APInt IntValue; + llvm::APSInt IntValue(0, true); constexpr unsigned AutoSenseRadix = 0; - if (ValueStr.getAsInteger(AutoSenseRadix, IntValue)) + if (ValueStr.getAsInteger(AutoSenseRadix, + static_cast(IntValue))) return std::nullopt; // Parse an optional minus sign. size_t Size = FilteredTokens.size(); if (Size >= 2) { - if (FilteredTokens[Size - 2].is(tok::minus)) + if (FilteredTokens[Size - 2].is(tok::minus)) { + // Make sure there's space for a sign bit + if (IntValue.isSignBitSet()) + IntValue = IntValue.extend(IntValue.getBitWidth() + 1); + IntValue.setIsUnsigned(false); IntValue = -IntValue; + } } - return IntValue.getSExtValue(); + return IntValue.getExtValue(); } OperatorKind operationKindFromOverloadedOperator(OverloadedOperatorKind OOK, diff --git a/clang/test/Analysis/std-c-library-functions-eof-2-rad.c b/clang/test/Analysis/std-c-library-functions-eof-2-rad.c new file mode 100644 index 0000000000000..6ead28b97fbf7 --- /dev/null +++ b/clang/test/Analysis/std-c-library-functions-eof-2-rad.c @@ -0,0 +1,16 @@ +// RUN: %clang_analyze_cc1 -std=c23 -analyzer-checker=core,unix.StdCLibraryFunctions,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s + +void clang_analyzer_eval(int); + +typedef struct FILE FILE; +/// Test that the static analyzer doesn't interpret the most significant bit as the sign bit. +// Unorthodox EOF value with a power of 2 radix +#define EOF (-0b11) + +int getc(FILE *); +void test_getc(FILE *fp) { + int y = getc(fp); + if (y < 0) { + clang_analyzer_eval(y == EOF); // expected-warning{{TRUE}} + } +}