Skip to content

Commit 8094454

Browse files
[StaticAnalyzer] Fix tryExpandAsInteger's failures on PCH macros (#142722)
The function `tryExpandAsInteger` attempts to extract an integer from a macro definition. Previously, the attempt would fail when the macro is from a PCH, because the function tried to access the text buffer of the source file, which does not exist in case of PCHs. The fix uses `Preprocessor::getSpelling`, which works in either cases. rdar://151403070 --------- Co-authored-by: Balazs Benics <[email protected]>
1 parent 9b992f2 commit 8094454

File tree

3 files changed

+62
-32
lines changed

3 files changed

+62
-32
lines changed

clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,19 @@ std::optional<int> tryExpandAsInteger(StringRef Macro, const Preprocessor &PP) {
129129

130130
// Parse an integer at the end of the macro definition.
131131
const Token &T = FilteredTokens.back();
132-
// FIXME: EOF macro token coming from a PCH file on macOS while marked as
133-
// literal, doesn't contain any literal data
134-
if (!T.isLiteral() || !T.getLiteralData())
132+
133+
if (!T.isLiteral())
135134
return std::nullopt;
136-
StringRef ValueStr = StringRef(T.getLiteralData(), T.getLength());
135+
136+
bool InvalidSpelling = false;
137+
SmallVector<char> Buffer(T.getLength());
138+
// `Preprocessor::getSpelling` can get the spelling of the token regardless of
139+
// whether the macro is defined in a PCH or not:
140+
StringRef ValueStr = PP.getSpelling(T, Buffer, &InvalidSpelling);
141+
142+
if (InvalidSpelling)
143+
return std::nullopt;
144+
137145
llvm::APInt IntValue;
138146
constexpr unsigned AutoSenseRadix = 0;
139147
if (ValueStr.getAsInteger(AutoSenseRadix, IntValue))

clang/test/Analysis/pch_crash.cpp

Lines changed: 0 additions & 28 deletions
This file was deleted.

clang/test/Analysis/pch_macro.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
// RUN: split-file %s %t
4+
5+
// DEFINE: %{emit-pch-action} = \
6+
// DEFINE: %clang_cc1 -x c++ -emit-pch -o %t/header.pch %t/header.h
7+
8+
// DEFINE: %{analyze-action} = \
9+
// DEFINE: %clang_analyze_cc1 -include-pch %t/header.pch \
10+
// DEFINE: -analyzer-checker=core,apiModeling,unix.StdCLibraryFunctions \
11+
// DEFINE: -verify %t/main.cpp
12+
13+
// RUN: %{emit-pch-action} -triple x86_64-apple-macosx10.15.0
14+
// RUN: %{analyze-action} -triple x86_64-apple-macosx10.15.0
15+
// RUN: %{emit-pch-action}
16+
// RUN: %{analyze-action}
17+
18+
19+
//--- header.h
20+
21+
22+
// Pre-compiled header
23+
24+
int foo();
25+
26+
// Literal data for macro values will be null as they are defined in a PCH
27+
#define EOF -1
28+
#define AT_FDCWD -2
29+
30+
31+
//--- main.cpp
32+
33+
34+
// Source file
35+
// expected-no-diagnostics
36+
int test() {
37+
// we need a function call here to initiate erroneous routine
38+
return foo(); // no-crash
39+
}
40+
41+
// Test that StdLibraryFunctionsChecker can obtain the definition of
42+
// AT_FDCWD even if it is from a PCH:
43+
int faccessat(int, const char *, int, int);
44+
45+
void test_faccessat() {
46+
char fileSystemPath[10] = { 0 };
47+
48+
if (0 != faccessat(AT_FDCWD, fileSystemPath, 2, 0x0030)) {}
49+
}
50+

0 commit comments

Comments
 (0)