Skip to content

Commit aeac909

Browse files
committed
[CrossTU] Fix plist macro expansion if macro in other file.
Summary: When cross TU analysis is used it is possible that a macro expansion is generated for a macro that is defined (and used) in other than the main translation unit. To get the expansion for it the source location in the original source file and original preprocessor is needed. Reviewers: martong, xazax.hun, Szelethus, ilya-biryukov Reviewed By: Szelethus Subscribers: mgorny, NoQ, ilya-biryukov, rnkovacs, dkrupp, Szelethus, gamesh411, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D64638 llvm-svn: 367006
1 parent c891625 commit aeac909

File tree

6 files changed

+137
-17
lines changed

6 files changed

+137
-17
lines changed

clang/lib/StaticAnalyzer/Core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ add_clang_library(clangStaticAnalyzerCore
5353
clangAnalysis
5454
clangBasic
5555
clangCrossTU
56+
clangFrontend
5657
clangLex
5758
clangRewrite
5859
)

clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "clang/Basic/SourceManager.h"
1616
#include "clang/Basic/Version.h"
1717
#include "clang/CrossTU/CrossTranslationUnit.h"
18+
#include "clang/Frontend/ASTUnit.h"
1819
#include "clang/Lex/Preprocessor.h"
1920
#include "clang/Lex/TokenConcatenation.h"
2021
#include "clang/Rewrite/Core/HTMLRewrite.h"
@@ -75,12 +76,14 @@ class PlistPrinter {
7576
const FIDMap& FM;
7677
AnalyzerOptions &AnOpts;
7778
const Preprocessor &PP;
79+
const cross_tu::CrossTranslationUnitContext &CTU;
7880
llvm::SmallVector<const PathDiagnosticMacroPiece *, 0> MacroPieces;
7981

8082
public:
8183
PlistPrinter(const FIDMap& FM, AnalyzerOptions &AnOpts,
82-
const Preprocessor &PP)
83-
: FM(FM), AnOpts(AnOpts), PP(PP) {
84+
const Preprocessor &PP,
85+
const cross_tu::CrossTranslationUnitContext &CTU)
86+
: FM(FM), AnOpts(AnOpts), PP(PP), CTU(CTU) {
8487
}
8588

8689
void ReportDiag(raw_ostream &o, const PathDiagnosticPiece& P) {
@@ -162,8 +165,8 @@ struct ExpansionInfo {
162165
} // end of anonymous namespace
163166

164167
static void printBugPath(llvm::raw_ostream &o, const FIDMap& FM,
165-
AnalyzerOptions &AnOpts,
166-
const Preprocessor &PP,
168+
AnalyzerOptions &AnOpts, const Preprocessor &PP,
169+
const cross_tu::CrossTranslationUnitContext &CTU,
167170
const PathPieces &Path);
168171

169172
/// Print coverage information to output stream {@code o}.
@@ -174,8 +177,9 @@ static void printCoverage(const PathDiagnostic *D,
174177
FIDMap &FM,
175178
llvm::raw_fd_ostream &o);
176179

177-
static ExpansionInfo getExpandedMacro(SourceLocation MacroLoc,
178-
const Preprocessor &PP);
180+
static ExpansionInfo
181+
getExpandedMacro(SourceLocation MacroLoc, const Preprocessor &PP,
182+
const cross_tu::CrossTranslationUnitContext &CTU);
179183

180184
//===----------------------------------------------------------------------===//
181185
// Methods of PlistPrinter.
@@ -349,7 +353,7 @@ void PlistPrinter::ReportMacroExpansions(raw_ostream &o, unsigned indent) {
349353

350354
for (const PathDiagnosticMacroPiece *P : MacroPieces) {
351355
const SourceManager &SM = PP.getSourceManager();
352-
ExpansionInfo EI = getExpandedMacro(P->getLocation().asLocation(), PP);
356+
ExpansionInfo EI = getExpandedMacro(P->getLocation().asLocation(), PP, CTU);
353357

354358
Indent(o, indent) << "<dict>\n";
355359
++indent;
@@ -471,10 +475,10 @@ static void printCoverage(const PathDiagnostic *D,
471475
}
472476

473477
static void printBugPath(llvm::raw_ostream &o, const FIDMap& FM,
474-
AnalyzerOptions &AnOpts,
475-
const Preprocessor &PP,
478+
AnalyzerOptions &AnOpts, const Preprocessor &PP,
479+
const cross_tu::CrossTranslationUnitContext &CTU,
476480
const PathPieces &Path) {
477-
PlistPrinter Printer(FM, AnOpts, PP);
481+
PlistPrinter Printer(FM, AnOpts, PP, CTU);
478482
assert(std::is_partitioned(
479483
Path.begin(), Path.end(),
480484
[](const std::shared_ptr<PathDiagnosticPiece> &E)
@@ -619,7 +623,7 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
619623
o << " <dict>\n";
620624

621625
const PathDiagnostic *D = *DI;
622-
printBugPath(o, FM, AnOpts, PP, D->path);
626+
printBugPath(o, FM, AnOpts, PP, CTU, D->path);
623627

624628
// Output the bug type and bug category.
625629
o << " <key>description</key>";
@@ -872,17 +876,23 @@ static const MacroInfo *getMacroInfoForLocation(const Preprocessor &PP,
872876
// Definitions of helper functions and methods for expanding macros.
873877
//===----------------------------------------------------------------------===//
874878

875-
static ExpansionInfo getExpandedMacro(SourceLocation MacroLoc,
876-
const Preprocessor &PP) {
879+
static ExpansionInfo
880+
getExpandedMacro(SourceLocation MacroLoc, const Preprocessor &PP,
881+
const cross_tu::CrossTranslationUnitContext &CTU) {
882+
883+
const Preprocessor *PPToUse = &PP;
884+
if (auto LocAndUnit = CTU.getImportedFromSourceLocation(MacroLoc)) {
885+
MacroLoc = LocAndUnit->first;
886+
PPToUse = &LocAndUnit->second->getPreprocessor();
887+
}
877888

878889
llvm::SmallString<200> ExpansionBuf;
879890
llvm::raw_svector_ostream OS(ExpansionBuf);
880-
TokenPrinter Printer(OS, PP);
891+
TokenPrinter Printer(OS, *PPToUse);
881892
llvm::SmallPtrSet<IdentifierInfo*, 8> AlreadyProcessedTokens;
882893

883-
std::string MacroName =
884-
getMacroNameAndPrintExpansion(Printer, MacroLoc, PP, MacroArgMap{},
885-
AlreadyProcessedTokens);
894+
std::string MacroName = getMacroNameAndPrintExpansion(
895+
Printer, MacroLoc, *PPToUse, MacroArgMap{}, AlreadyProcessedTokens);
886896
return { MacroName, OS.str() };
887897
}
888898

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
#include "plist-macros-ctu.h"
3+
4+
#define M *X = (int *)0
5+
6+
void F1(int **X) {
7+
M;
8+
}
9+
10+
#undef M
11+
#define M *Y = (int *)0
12+
13+
void F2(int **Y) {
14+
M;
15+
}
16+
17+
#define M1 *Z = (int *)0
18+
19+
void F3(int **Z) {
20+
M1;
21+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#define M_H *A = (int *)0
2+
void F_H(int **A) {
3+
M_H;
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
c:@F@F1 plist-macros-ctu.c.ast
2+
c:@F@F2 plist-macros-ctu.c.ast
3+
c:@F@F3 plist-macros-ctu.c.ast
4+
c:@F@F_H plist-macros-ctu.c.ast
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// RUN: rm -rf %t && mkdir %t
2+
// RUN: mkdir -p %t/ctudir
3+
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
4+
// RUN: -emit-pch -o %t/ctudir/plist-macros-ctu.c.ast %S/Inputs/plist-macros-ctu.c
5+
// RUN: cp %S/Inputs/plist-macros-with-expansion-ctu.c.externalDefMap.txt %t/ctudir/externalDefMap.txt
6+
7+
// RUN: %clang_analyze_cc1 -analyzer-checker=core \
8+
// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \
9+
// RUN: -analyzer-config ctu-dir=%t/ctudir \
10+
// RUN: -analyzer-config expand-macros=true \
11+
// RUN: -analyzer-output=plist-multi-file -o %t.plist -verify %s
12+
13+
// Check the macro expansions from the plist output here, to make the test more
14+
// understandable.
15+
// RUN: FileCheck --input-file=%t.plist %s
16+
17+
extern void F1(int **);
18+
extern void F2(int **);
19+
extern void F3(int **);
20+
extern void F_H(int **);
21+
22+
void test0() {
23+
int *X;
24+
F3(&X);
25+
*X = 1; // expected-warning{{Dereference of null pointer}}
26+
}
27+
// CHECK: <key>name</key><string>M1</string>
28+
// CHECK-NEXT: <key>expansion</key><string>*Z = (int *)0</string>
29+
30+
31+
void test1() {
32+
int *X;
33+
F1(&X);
34+
*X = 1; // expected-warning{{Dereference of null pointer}}
35+
}
36+
// CHECK: <key>name</key><string>M</string>
37+
// CHECK-NEXT: <key>expansion</key><string>*X = (int *)0</string>
38+
39+
void test2() {
40+
int *X;
41+
F2(&X);
42+
*X = 1; // expected-warning{{Dereference of null pointer}}
43+
}
44+
// CHECK: <key>name</key><string>M</string>
45+
// CHECK-NEXT: <key>expansion</key><string>*Y = (int *)0</string>
46+
47+
#define M F1(&X)
48+
49+
void test3() {
50+
int *X;
51+
M;
52+
*X = 1; // expected-warning{{Dereference of null pointer}}
53+
}
54+
// CHECK: <key>name</key><string>M</string>
55+
// CHECK-NEXT: <key>expansion</key><string>F1(&amp;X)</string>
56+
// CHECK: <key>name</key><string>M</string>
57+
// CHECK-NEXT: <key>expansion</key><string>*X = (int *)0</string>
58+
59+
#undef M
60+
#define M F2(&X)
61+
62+
void test4() {
63+
int *X;
64+
M;
65+
*X = 1; // expected-warning{{Dereference of null pointer}}
66+
}
67+
68+
// CHECK: <key>name</key><string>M</string>
69+
// CHECK-NEXT: <key>expansion</key><string>F2(&amp;X)</string>
70+
// CHECK: <key>name</key><string>M</string>
71+
// CHECK-NEXT: <key>expansion</key><string>*Y = (int *)0</string>
72+
73+
void test_h() {
74+
int *X;
75+
F_H(&X);
76+
*X = 1; // expected-warning{{Dereference of null pointer}}
77+
}
78+
79+
// CHECK: <key>name</key><string>M_H</string>
80+
// CHECK-NEXT: <key>expansion</key><string>*A = (int *)0</string>

0 commit comments

Comments
 (0)