summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBalazs Keri <1.int32@gmail.com>2019-07-25 10:53:22 +0000
committerBalazs Keri <1.int32@gmail.com>2019-07-25 10:53:22 +0000
commit802ae91fa793b40d0af3e1779c8e46dfc6cc2bc0 (patch)
tree9ffc2933a0fd63707b11c013487f8b402bd6b1f4
parentd50f7341d4d4c33277f73db8c52a6d584ffe2e93 (diff)
downloadclang-802ae91fa793b40d0af3e1779c8e46dfc6cc2bc0.tar.gz
[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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@367006 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/StaticAnalyzer/Core/CMakeLists.txt1
-rw-r--r--lib/StaticAnalyzer/Core/PlistDiagnostics.cpp44
-rw-r--r--test/Analysis/Inputs/plist-macros-ctu.c21
-rw-r--r--test/Analysis/Inputs/plist-macros-ctu.h4
-rw-r--r--test/Analysis/Inputs/plist-macros-with-expansion-ctu.c.externalDefMap.txt4
-rw-r--r--test/Analysis/plist-macros-with-expansion-ctu.c80
6 files changed, 137 insertions, 17 deletions
diff --git a/lib/StaticAnalyzer/Core/CMakeLists.txt b/lib/StaticAnalyzer/Core/CMakeLists.txt
index 942aedd388..0affa8be55 100644
--- a/lib/StaticAnalyzer/Core/CMakeLists.txt
+++ b/lib/StaticAnalyzer/Core/CMakeLists.txt
@@ -53,6 +53,7 @@ add_clang_library(clangStaticAnalyzerCore
clangAnalysis
clangBasic
clangCrossTU
+ clangFrontend
clangLex
clangRewrite
)
diff --git a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
index c7424916be..15b8e0c41c 100644
--- a/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
+++ b/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp
@@ -15,6 +15,7 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Version.h"
#include "clang/CrossTU/CrossTranslationUnit.h"
+#include "clang/Frontend/ASTUnit.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/TokenConcatenation.h"
#include "clang/Rewrite/Core/HTMLRewrite.h"
@@ -75,12 +76,14 @@ class PlistPrinter {
const FIDMap& FM;
AnalyzerOptions &AnOpts;
const Preprocessor &PP;
+ const cross_tu::CrossTranslationUnitContext &CTU;
llvm::SmallVector<const PathDiagnosticMacroPiece *, 0> MacroPieces;
public:
PlistPrinter(const FIDMap& FM, AnalyzerOptions &AnOpts,
- const Preprocessor &PP)
- : FM(FM), AnOpts(AnOpts), PP(PP) {
+ const Preprocessor &PP,
+ const cross_tu::CrossTranslationUnitContext &CTU)
+ : FM(FM), AnOpts(AnOpts), PP(PP), CTU(CTU) {
}
void ReportDiag(raw_ostream &o, const PathDiagnosticPiece& P) {
@@ -162,8 +165,8 @@ struct ExpansionInfo {
} // end of anonymous namespace
static void printBugPath(llvm::raw_ostream &o, const FIDMap& FM,
- AnalyzerOptions &AnOpts,
- const Preprocessor &PP,
+ AnalyzerOptions &AnOpts, const Preprocessor &PP,
+ const cross_tu::CrossTranslationUnitContext &CTU,
const PathPieces &Path);
/// Print coverage information to output stream {@code o}.
@@ -174,8 +177,9 @@ static void printCoverage(const PathDiagnostic *D,
FIDMap &FM,
llvm::raw_fd_ostream &o);
-static ExpansionInfo getExpandedMacro(SourceLocation MacroLoc,
- const Preprocessor &PP);
+static ExpansionInfo
+getExpandedMacro(SourceLocation MacroLoc, const Preprocessor &PP,
+ const cross_tu::CrossTranslationUnitContext &CTU);
//===----------------------------------------------------------------------===//
// Methods of PlistPrinter.
@@ -349,7 +353,7 @@ void PlistPrinter::ReportMacroExpansions(raw_ostream &o, unsigned indent) {
for (const PathDiagnosticMacroPiece *P : MacroPieces) {
const SourceManager &SM = PP.getSourceManager();
- ExpansionInfo EI = getExpandedMacro(P->getLocation().asLocation(), PP);
+ ExpansionInfo EI = getExpandedMacro(P->getLocation().asLocation(), PP, CTU);
Indent(o, indent) << "<dict>\n";
++indent;
@@ -471,10 +475,10 @@ static void printCoverage(const PathDiagnostic *D,
}
static void printBugPath(llvm::raw_ostream &o, const FIDMap& FM,
- AnalyzerOptions &AnOpts,
- const Preprocessor &PP,
+ AnalyzerOptions &AnOpts, const Preprocessor &PP,
+ const cross_tu::CrossTranslationUnitContext &CTU,
const PathPieces &Path) {
- PlistPrinter Printer(FM, AnOpts, PP);
+ PlistPrinter Printer(FM, AnOpts, PP, CTU);
assert(std::is_partitioned(
Path.begin(), Path.end(),
[](const std::shared_ptr<PathDiagnosticPiece> &E)
@@ -619,7 +623,7 @@ void PlistDiagnostics::FlushDiagnosticsImpl(
o << " <dict>\n";
const PathDiagnostic *D = *DI;
- printBugPath(o, FM, AnOpts, PP, D->path);
+ printBugPath(o, FM, AnOpts, PP, CTU, D->path);
// Output the bug type and bug category.
o << " <key>description</key>";
@@ -872,17 +876,23 @@ static const MacroInfo *getMacroInfoForLocation(const Preprocessor &PP,
// Definitions of helper functions and methods for expanding macros.
//===----------------------------------------------------------------------===//
-static ExpansionInfo getExpandedMacro(SourceLocation MacroLoc,
- const Preprocessor &PP) {
+static ExpansionInfo
+getExpandedMacro(SourceLocation MacroLoc, const Preprocessor &PP,
+ const cross_tu::CrossTranslationUnitContext &CTU) {
+
+ const Preprocessor *PPToUse = &PP;
+ if (auto LocAndUnit = CTU.getImportedFromSourceLocation(MacroLoc)) {
+ MacroLoc = LocAndUnit->first;
+ PPToUse = &LocAndUnit->second->getPreprocessor();
+ }
llvm::SmallString<200> ExpansionBuf;
llvm::raw_svector_ostream OS(ExpansionBuf);
- TokenPrinter Printer(OS, PP);
+ TokenPrinter Printer(OS, *PPToUse);
llvm::SmallPtrSet<IdentifierInfo*, 8> AlreadyProcessedTokens;
- std::string MacroName =
- getMacroNameAndPrintExpansion(Printer, MacroLoc, PP, MacroArgMap{},
- AlreadyProcessedTokens);
+ std::string MacroName = getMacroNameAndPrintExpansion(
+ Printer, MacroLoc, *PPToUse, MacroArgMap{}, AlreadyProcessedTokens);
return { MacroName, OS.str() };
}
diff --git a/test/Analysis/Inputs/plist-macros-ctu.c b/test/Analysis/Inputs/plist-macros-ctu.c
new file mode 100644
index 0000000000..f3e374caae
--- /dev/null
+++ b/test/Analysis/Inputs/plist-macros-ctu.c
@@ -0,0 +1,21 @@
+
+#include "plist-macros-ctu.h"
+
+#define M *X = (int *)0
+
+void F1(int **X) {
+ M;
+}
+
+#undef M
+#define M *Y = (int *)0
+
+void F2(int **Y) {
+ M;
+}
+
+#define M1 *Z = (int *)0
+
+void F3(int **Z) {
+ M1;
+}
diff --git a/test/Analysis/Inputs/plist-macros-ctu.h b/test/Analysis/Inputs/plist-macros-ctu.h
new file mode 100644
index 0000000000..0b1b9d7a4f
--- /dev/null
+++ b/test/Analysis/Inputs/plist-macros-ctu.h
@@ -0,0 +1,4 @@
+#define M_H *A = (int *)0
+void F_H(int **A) {
+ M_H;
+}
diff --git a/test/Analysis/Inputs/plist-macros-with-expansion-ctu.c.externalDefMap.txt b/test/Analysis/Inputs/plist-macros-with-expansion-ctu.c.externalDefMap.txt
new file mode 100644
index 0000000000..52214a4189
--- /dev/null
+++ b/test/Analysis/Inputs/plist-macros-with-expansion-ctu.c.externalDefMap.txt
@@ -0,0 +1,4 @@
+c:@F@F1 plist-macros-ctu.c.ast
+c:@F@F2 plist-macros-ctu.c.ast
+c:@F@F3 plist-macros-ctu.c.ast
+c:@F@F_H plist-macros-ctu.c.ast
diff --git a/test/Analysis/plist-macros-with-expansion-ctu.c b/test/Analysis/plist-macros-with-expansion-ctu.c
new file mode 100644
index 0000000000..ff99b619fd
--- /dev/null
+++ b/test/Analysis/plist-macros-with-expansion-ctu.c
@@ -0,0 +1,80 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: mkdir -p %t/ctudir
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu \
+// RUN: -emit-pch -o %t/ctudir/plist-macros-ctu.c.ast %S/Inputs/plist-macros-ctu.c
+// RUN: cp %S/Inputs/plist-macros-with-expansion-ctu.c.externalDefMap.txt %t/ctudir/externalDefMap.txt
+
+// RUN: %clang_analyze_cc1 -analyzer-checker=core \
+// RUN: -analyzer-config experimental-enable-naive-ctu-analysis=true \
+// RUN: -analyzer-config ctu-dir=%t/ctudir \
+// RUN: -analyzer-config expand-macros=true \
+// RUN: -analyzer-output=plist-multi-file -o %t.plist -verify %s
+
+// Check the macro expansions from the plist output here, to make the test more
+// understandable.
+// RUN: FileCheck --input-file=%t.plist %s
+
+extern void F1(int **);
+extern void F2(int **);
+extern void F3(int **);
+extern void F_H(int **);
+
+void test0() {
+ int *X;
+ F3(&X);
+ *X = 1; // expected-warning{{Dereference of null pointer}}
+}
+// CHECK: <key>name</key><string>M1</string>
+// CHECK-NEXT: <key>expansion</key><string>*Z = (int *)0</string>
+
+
+void test1() {
+ int *X;
+ F1(&X);
+ *X = 1; // expected-warning{{Dereference of null pointer}}
+}
+// CHECK: <key>name</key><string>M</string>
+// CHECK-NEXT: <key>expansion</key><string>*X = (int *)0</string>
+
+void test2() {
+ int *X;
+ F2(&X);
+ *X = 1; // expected-warning{{Dereference of null pointer}}
+}
+// CHECK: <key>name</key><string>M</string>
+// CHECK-NEXT: <key>expansion</key><string>*Y = (int *)0</string>
+
+#define M F1(&X)
+
+void test3() {
+ int *X;
+ M;
+ *X = 1; // expected-warning{{Dereference of null pointer}}
+}
+// CHECK: <key>name</key><string>M</string>
+// CHECK-NEXT: <key>expansion</key><string>F1(&amp;X)</string>
+// CHECK: <key>name</key><string>M</string>
+// CHECK-NEXT: <key>expansion</key><string>*X = (int *)0</string>
+
+#undef M
+#define M F2(&X)
+
+void test4() {
+ int *X;
+ M;
+ *X = 1; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>M</string>
+// CHECK-NEXT: <key>expansion</key><string>F2(&amp;X)</string>
+// CHECK: <key>name</key><string>M</string>
+// CHECK-NEXT: <key>expansion</key><string>*Y = (int *)0</string>
+
+void test_h() {
+ int *X;
+ F_H(&X);
+ *X = 1; // expected-warning{{Dereference of null pointer}}
+}
+
+// CHECK: <key>name</key><string>M_H</string>
+// CHECK-NEXT: <key>expansion</key><string>*A = (int *)0</string>