https://github.com/ziqingluo-90 updated https://github.com/llvm/llvm-project/pull/142722
>From 3bd12ac6bb3c47b5e977cffec019df15a15426fc Mon Sep 17 00:00:00 2001 From: Ziqing Luo <ziq...@udel.edu> Date: Wed, 4 Jun 2025 12:29:53 +0800 Subject: [PATCH 1/2] [StaticAnalyzer] Fix tryExpandAsInteger's failures on macros from PCHs 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 --- .../StaticAnalyzer/Core/CheckerHelpers.cpp | 16 ++++++-- clang/test/Analysis/pch_crash.cpp | 28 ------------- clang/test/Analysis/pch_macro.cpp | 39 +++++++++++++++++++ 3 files changed, 51 insertions(+), 32 deletions(-) delete mode 100644 clang/test/Analysis/pch_crash.cpp create mode 100644 clang/test/Analysis/pch_macro.cpp diff --git a/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp b/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp index 4ed4113919c1d..111af35806dda 100644 --- a/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp @@ -129,11 +129,19 @@ std::optional<int> tryExpandAsInteger(StringRef Macro, const Preprocessor &PP) { // Parse an integer at the end of the macro definition. const Token &T = FilteredTokens.back(); - // FIXME: EOF macro token coming from a PCH file on macOS while marked as - // literal, doesn't contain any literal data - if (!T.isLiteral() || !T.getLiteralData()) + + if (!T.isLiteral()) return std::nullopt; - StringRef ValueStr = StringRef(T.getLiteralData(), T.getLength()); + + bool InvalidSpelling = false; + // `Preprocessor::getSpelling` can get the spelling of the token regardless of + // whether the macro is defined in a PCH or not: + std::string Spelling = PP.getSpelling(T, &InvalidSpelling); + + if (InvalidSpelling) + return std::nullopt; + + StringRef ValueStr(Spelling); llvm::APInt IntValue; constexpr unsigned AutoSenseRadix = 0; if (ValueStr.getAsInteger(AutoSenseRadix, IntValue)) diff --git a/clang/test/Analysis/pch_crash.cpp b/clang/test/Analysis/pch_crash.cpp deleted file mode 100644 index 7ad2cb2d2ab57..0000000000000 --- a/clang/test/Analysis/pch_crash.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// RUN: %clang_cc1 -triple x86_64-apple-macosx10.15.0 -emit-pch -o %t %s -// RUN: %clang_analyze_cc1 -triple x86_64-apple-macosx10.15.0 -include-pch %t \ -// RUN: -analyzer-checker=core,apiModeling -verify %s -// -// RUN: %clang_cc1 -emit-pch -o %t %s -// RUN: %clang_analyze_cc1 -include-pch %t \ -// RUN: -analyzer-checker=core,apiModeling -verify %s - -// expected-no-diagnostics - -#ifndef HEADER -#define HEADER -// Pre-compiled header - -int foo(); - -// Literal data for this macro value will be null -#define EOF -1 - -#else -// Source file - -int test() { - // we need a function call here to initiate erroneous routine - return foo(); // no-crash -} - -#endif diff --git a/clang/test/Analysis/pch_macro.cpp b/clang/test/Analysis/pch_macro.cpp new file mode 100644 index 0000000000000..0cc00cfe0cc17 --- /dev/null +++ b/clang/test/Analysis/pch_macro.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.15.0 -emit-pch -o %t %s +// RUN: %clang_analyze_cc1 -triple x86_64-apple-macosx10.15.0 -include-pch %t \ +// RUN: -analyzer-checker=core,apiModeling,unix.StdCLibraryFunctions -verify %s +// +// RUN: %clang_cc1 -emit-pch -o %t %s +// RUN: %clang_analyze_cc1 -include-pch %t \ +// RUN: -analyzer-checker=core,apiModeling,unix.StdCLibraryFunctions -verify %s + +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER +// Pre-compiled header + +int foo(); + +// Literal data for macro values will be null as they are defined in a PCH +#define EOF -1 +#define AT_FDCWD -2 + +#else +// Source file + +int test() { + // we need a function call here to initiate erroneous routine + return foo(); // no-crash +} + +// Test that StdLibraryFunctionsChecker can obtain the definition of +// AT_FDCWD even if it is from a PCH: +int faccessat(int, const char *, int, int); + +void test_faccessat() { + char fileSystemPath[10] = { 0 }; + + if (0 != faccessat(AT_FDCWD, fileSystemPath, 2, 0x0030)) {} +} + +#endif >From 8893dd5ae0784821c4c82f1c0ed65e25c832eff0 Mon Sep 17 00:00:00 2001 From: Ziqing Luo <ziq...@udel.edu> Date: Thu, 5 Jun 2025 13:14:03 +0800 Subject: [PATCH 2/2] address comments --- .../StaticAnalyzer/Core/CheckerHelpers.cpp | 4 +-- clang/test/Analysis/pch_macro.cpp | 30 +++++++++++-------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp b/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp index 111af35806dda..8b404377186e9 100644 --- a/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerHelpers.cpp @@ -134,14 +134,14 @@ std::optional<int> tryExpandAsInteger(StringRef Macro, const Preprocessor &PP) { return std::nullopt; bool InvalidSpelling = false; + SmallVector<char> Buffer(T.getLength()); // `Preprocessor::getSpelling` can get the spelling of the token regardless of // whether the macro is defined in a PCH or not: - std::string Spelling = PP.getSpelling(T, &InvalidSpelling); + StringRef ValueStr = PP.getSpelling(T, Buffer, &InvalidSpelling); if (InvalidSpelling) return std::nullopt; - StringRef ValueStr(Spelling); llvm::APInt IntValue; constexpr unsigned AutoSenseRadix = 0; if (ValueStr.getAsInteger(AutoSenseRadix, IntValue)) diff --git a/clang/test/Analysis/pch_macro.cpp b/clang/test/Analysis/pch_macro.cpp index 0cc00cfe0cc17..c2eb315418673 100644 --- a/clang/test/Analysis/pch_macro.cpp +++ b/clang/test/Analysis/pch_macro.cpp @@ -1,15 +1,19 @@ -// RUN: %clang_cc1 -triple x86_64-apple-macosx10.15.0 -emit-pch -o %t %s -// RUN: %clang_analyze_cc1 -triple x86_64-apple-macosx10.15.0 -include-pch %t \ -// RUN: -analyzer-checker=core,apiModeling,unix.StdCLibraryFunctions -verify %s +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -x c++ -triple x86_64-apple-macosx10.15.0 -emit-pch -o %t/header.pch %t/header.h +// RUN: %clang_analyze_cc1 -triple x86_64-apple-macosx10.15.0 -include-pch %t/header.pch \ +// RUN: -analyzer-checker=core,apiModeling,unix.StdCLibraryFunctions -verify %t/main.cpp // -// RUN: %clang_cc1 -emit-pch -o %t %s -// RUN: %clang_analyze_cc1 -include-pch %t \ -// RUN: -analyzer-checker=core,apiModeling,unix.StdCLibraryFunctions -verify %s +// RUN: %clang_cc1 -x c++ -emit-pch -o %t/header.pch %t/header.h +// RUN: %clang_analyze_cc1 -include-pch %t/header.pch \ +// RUN: -analyzer-checker=core,apiModeling,unix.StdCLibraryFunctions -verify %t/main.cpp + + +//--- header.h -// expected-no-diagnostics -#ifndef HEADER -#define HEADER // Pre-compiled header int foo(); @@ -18,9 +22,12 @@ int foo(); #define EOF -1 #define AT_FDCWD -2 -#else -// Source file +//--- main.cpp + + +// Source file +// expected-no-diagnostics int test() { // we need a function call here to initiate erroneous routine return foo(); // no-crash @@ -36,4 +43,3 @@ void test_faccessat() { if (0 != faccessat(AT_FDCWD, fileSystemPath, 2, 0x0030)) {} } -#endif _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits