blob: c88e6c1e1535f6df80df5b296b03a41381f83017 [file] [log] [blame]
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001//===- PathDiagnostic.cpp - Path-Specific Diagnostic Handling -------------===//
Ted Kremenek4fa20c92008-03-27 03:49:32 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Ted Kremenek4fa20c92008-03-27 03:49:32 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the PathDiagnostic-related interfaces.
10//
11//===----------------------------------------------------------------------===//
12
Artem Dergachevf0bb45f2019-09-11 20:54:27 +000013#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek92820d22009-04-06 22:33:35 +000014#include "clang/AST/Decl.h"
Eugene Zelenko9f103a12018-03-08 22:45:13 +000015#include "clang/AST/DeclBase.h"
Jordan Rosea4c0d212012-07-26 20:04:05 +000016#include "clang/AST/DeclCXX.h"
Ted Kremenek92820d22009-04-06 22:33:35 +000017#include "clang/AST/DeclObjC.h"
Kristof Umann3ea74422018-05-25 13:18:38 +000018#include "clang/AST/DeclTemplate.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000019#include "clang/AST/Expr.h"
Benjamin Kramerf3ca26982014-05-10 16:31:55 +000020#include "clang/AST/ExprCXX.h"
Eugene Zelenko9f103a12018-03-08 22:45:13 +000021#include "clang/AST/OperationKinds.h"
Anna Zaks615e3a62011-09-14 17:48:01 +000022#include "clang/AST/ParentMap.h"
Reid Klecknerb36c19b2020-04-06 09:55:33 -070023#include "clang/AST/PrettyPrinter.h"
Eugene Zelenko9f103a12018-03-08 22:45:13 +000024#include "clang/AST/Stmt.h"
25#include "clang/AST/Type.h"
26#include "clang/Analysis/AnalysisDeclContext.h"
27#include "clang/Analysis/CFG.h"
28#include "clang/Analysis/ProgramPoint.h"
29#include "clang/Basic/FileManager.h"
30#include "clang/Basic/LLVM.h"
31#include "clang/Basic/SourceLocation.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000032#include "clang/Basic/SourceManager.h"
Eugene Zelenko9f103a12018-03-08 22:45:13 +000033#include "llvm/ADT/ArrayRef.h"
34#include "llvm/ADT/FoldingSet.h"
35#include "llvm/ADT/None.h"
36#include "llvm/ADT/Optional.h"
37#include "llvm/ADT/STLExtras.h"
Chris Lattner23be0672008-11-19 06:51:40 +000038#include "llvm/ADT/SmallString.h"
Eugene Zelenko9f103a12018-03-08 22:45:13 +000039#include "llvm/ADT/SmallVector.h"
Jordan Rosec102b352012-09-22 01:24:42 +000040#include "llvm/ADT/StringExtras.h"
Eugene Zelenko9f103a12018-03-08 22:45:13 +000041#include "llvm/ADT/StringRef.h"
42#include "llvm/Support/Casting.h"
43#include "llvm/Support/ErrorHandling.h"
Benjamin Kramer444a1302012-12-01 17:12:56 +000044#include "llvm/Support/raw_ostream.h"
Eugene Zelenko9f103a12018-03-08 22:45:13 +000045#include <cassert>
46#include <cstring>
47#include <memory>
48#include <utility>
49#include <vector>
Ted Kremenekbb597cd2009-06-26 00:43:22 +000050
Ted Kremenek4fa20c92008-03-27 03:49:32 +000051using namespace clang;
Ted Kremenek98857c92010-12-23 07:20:52 +000052using namespace ento;
Ted Kremenekb4947e42009-03-10 05:16:17 +000053
Chris Lattner0e62c1c2011-07-23 10:55:15 +000054static StringRef StripTrailingDots(StringRef s) {
55 for (StringRef::size_type i = s.size(); i != 0; --i)
Benjamin Kramer4dab76a2009-12-11 21:09:27 +000056 if (s[i - 1] != '.')
57 return s.substr(0, i);
Eugene Zelenko9f103a12018-03-08 22:45:13 +000058 return {};
Ted Kremeneke9817aa2009-02-26 21:30:32 +000059}
60
Chris Lattner0e62c1c2011-07-23 10:55:15 +000061PathDiagnosticPiece::PathDiagnosticPiece(StringRef s,
Ted Kremenek1f8140d2009-03-02 19:39:50 +000062 Kind k, DisplayHint hint)
Eugene Zelenko9f103a12018-03-08 22:45:13 +000063 : str(StripTrailingDots(s)), kind(k), Hint(hint) {}
Ted Kremenek55f46f62009-03-06 07:53:30 +000064
Ted Kremenek3d46b1c2009-03-26 21:21:35 +000065PathDiagnosticPiece::PathDiagnosticPiece(Kind k, DisplayHint hint)
Eugene Zelenko9f103a12018-03-08 22:45:13 +000066 : kind(k), Hint(hint) {}
Ted Kremenek9d1ce8f2009-03-12 18:41:53 +000067
Eugene Zelenko9f103a12018-03-08 22:45:13 +000068PathDiagnosticPiece::~PathDiagnosticPiece() = default;
69
70PathDiagnosticEventPiece::~PathDiagnosticEventPiece() = default;
71
72PathDiagnosticCallPiece::~PathDiagnosticCallPiece() = default;
73
74PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() = default;
75
76PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() = default;
77
78PathDiagnosticNotePiece::~PathDiagnosticNotePiece() = default;
Ted Kremenek5a10f082012-04-04 18:11:35 +000079
Csaba Dabis1d7ca672019-05-29 19:21:59 +000080PathDiagnosticPopUpPiece::~PathDiagnosticPopUpPiece() = default;
81
Jordan Rose3eb3cd42012-08-03 23:08:54 +000082void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
83 bool ShouldFlattenMacros) const {
David Blaikie0a0c2752017-01-05 17:26:53 +000084 for (auto &Piece : *this) {
Jordan Rose3eb3cd42012-08-03 23:08:54 +000085 switch (Piece->getKind()) {
86 case PathDiagnosticPiece::Call: {
David Blaikie0a0c2752017-01-05 17:26:53 +000087 auto &Call = cast<PathDiagnosticCallPiece>(*Piece);
88 if (auto CallEnter = Call.getCallEnterEvent())
89 Current.push_back(std::move(CallEnter));
90 Call.path.flattenTo(Primary, Primary, ShouldFlattenMacros);
91 if (auto callExit = Call.getCallExitEvent())
92 Current.push_back(std::move(callExit));
Jordan Rose3eb3cd42012-08-03 23:08:54 +000093 break;
94 }
95 case PathDiagnosticPiece::Macro: {
David Blaikie0a0c2752017-01-05 17:26:53 +000096 auto &Macro = cast<PathDiagnosticMacroPiece>(*Piece);
Jordan Rose3eb3cd42012-08-03 23:08:54 +000097 if (ShouldFlattenMacros) {
David Blaikie0a0c2752017-01-05 17:26:53 +000098 Macro.subPieces.flattenTo(Primary, Primary, ShouldFlattenMacros);
Jordan Rose3eb3cd42012-08-03 23:08:54 +000099 } else {
100 Current.push_back(Piece);
101 PathPieces NewPath;
David Blaikie0a0c2752017-01-05 17:26:53 +0000102 Macro.subPieces.flattenTo(Primary, NewPath, ShouldFlattenMacros);
Jordan Rose3eb3cd42012-08-03 23:08:54 +0000103 // FIXME: This probably shouldn't mutate the original path piece.
David Blaikie0a0c2752017-01-05 17:26:53 +0000104 Macro.subPieces = NewPath;
Jordan Rose3eb3cd42012-08-03 23:08:54 +0000105 }
106 break;
107 }
108 case PathDiagnosticPiece::Event:
109 case PathDiagnosticPiece::ControlFlow:
Artem Dergachev8b70c4e2016-10-07 15:23:02 +0000110 case PathDiagnosticPiece::Note:
Csaba Dabis1d7ca672019-05-29 19:21:59 +0000111 case PathDiagnosticPiece::PopUp:
Jordan Rose3eb3cd42012-08-03 23:08:54 +0000112 Current.push_back(Piece);
113 break;
114 }
115 }
116}
117
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000118PathDiagnostic::~PathDiagnostic() = default;
Ted Kremenek3116c4e2012-02-08 04:32:27 +0000119
George Karpenkova5ddd3c2018-01-17 02:59:11 +0000120PathDiagnostic::PathDiagnostic(
Kristof Umann72649422019-09-12 19:09:24 +0000121 StringRef CheckerName, const Decl *declWithIssue, StringRef bugtype,
George Karpenkova5ddd3c2018-01-17 02:59:11 +0000122 StringRef verboseDesc, StringRef shortDesc, StringRef category,
123 PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique,
124 std::unique_ptr<FilesToLineNumsMap> ExecutedLines)
Kristof Umann72649422019-09-12 19:09:24 +0000125 : CheckerName(CheckerName), DeclWithIssue(declWithIssue),
George Karpenkova5ddd3c2018-01-17 02:59:11 +0000126 BugType(StripTrailingDots(bugtype)),
127 VerboseDesc(StripTrailingDots(verboseDesc)),
128 ShortDesc(StripTrailingDots(shortDesc)),
129 Category(StripTrailingDots(category)), UniqueingLoc(LocationToUnique),
130 UniqueingDecl(DeclToUnique), ExecutedLines(std::move(ExecutedLines)),
131 path(pathImpl) {}
Ted Kremenek5b9e7b82009-03-06 07:08:50 +0000132
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000133void PathDiagnosticConsumer::anchor() {}
David Blaikie68e081d2011-12-20 02:48:34 +0000134
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000135PathDiagnosticConsumer::~PathDiagnosticConsumer() {
136 // Delete the contents of the FoldingSet if it isn't empty already.
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000137 for (auto &Diag : Diags)
138 delete &Diag;
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000139}
140
David Blaikiec9950cb2014-08-29 20:06:10 +0000141void PathDiagnosticConsumer::HandlePathDiagnostic(
142 std::unique_ptr<PathDiagnostic> D) {
Ted Kremenek0f70a6f2012-02-28 23:27:39 +0000143 if (!D || D->path.empty())
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000144 return;
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000145
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000146 // We need to flatten the locations (convert Stmt* to locations) because
147 // the referenced statements may be freed by the time the diagnostics
148 // are emitted.
149 D->flattenLocations();
150
Ted Kremenek0f70a6f2012-02-28 23:27:39 +0000151 // If the PathDiagnosticConsumer does not support diagnostics that
152 // cross file boundaries, prune out such diagnostics now.
153 if (!supportsCrossFileDiagnostics()) {
154 // Verify that the entire path is from the same FileID.
155 FileID FID;
David Blaikiec9950cb2014-08-29 20:06:10 +0000156 const SourceManager &SMgr = D->path.front()->getLocation().getManager();
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000157 SmallVector<const PathPieces *, 5> WorkList;
Ted Kremenek0f0cc352012-02-29 23:59:20 +0000158 WorkList.push_back(&D->path);
Anton Yartsev0509d042016-10-06 21:42:21 +0000159 SmallString<128> buf;
160 llvm::raw_svector_ostream warning(buf);
161 warning << "warning: Path diagnostic report is not generated. Current "
162 << "output format does not support diagnostics that cross file "
163 << "boundaries. Refer to --analyzer-output for valid output "
164 << "formats\n";
Ted Kremenek0f70a6f2012-02-28 23:27:39 +0000165
Ted Kremenek0f0cc352012-02-29 23:59:20 +0000166 while (!WorkList.empty()) {
Robert Wilhelm25284cc2013-08-23 16:11:15 +0000167 const PathPieces &path = *WorkList.pop_back_val();
Ted Kremenek0f0cc352012-02-29 23:59:20 +0000168
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000169 for (const auto &I : path) {
170 const PathDiagnosticPiece *piece = I.get();
Ted Kremenek0f0cc352012-02-29 23:59:20 +0000171 FullSourceLoc L = piece->getLocation().asLocation().getExpansionLoc();
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000172
Ted Kremenek0f0cc352012-02-29 23:59:20 +0000173 if (FID.isInvalid()) {
174 FID = SMgr.getFileID(L);
Anton Yartsev0509d042016-10-06 21:42:21 +0000175 } else if (SMgr.getFileID(L) != FID) {
176 llvm::errs() << warning.str();
177 return;
178 }
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000179
Ted Kremenek0f0cc352012-02-29 23:59:20 +0000180 // Check the source ranges.
Ted Kremenek1e602732012-08-16 17:45:29 +0000181 ArrayRef<SourceRange> Ranges = piece->getRanges();
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000182 for (const auto &I : Ranges) {
183 SourceLocation L = SMgr.getExpansionLoc(I.getBegin());
Anton Yartsev0509d042016-10-06 21:42:21 +0000184 if (!L.isFileID() || SMgr.getFileID(L) != FID) {
185 llvm::errs() << warning.str();
186 return;
187 }
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000188 L = SMgr.getExpansionLoc(I.getEnd());
Anton Yartsev0509d042016-10-06 21:42:21 +0000189 if (!L.isFileID() || SMgr.getFileID(L) != FID) {
190 llvm::errs() << warning.str();
191 return;
192 }
Ted Kremenek0f0cc352012-02-29 23:59:20 +0000193 }
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000194
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000195 if (const auto *call = dyn_cast<PathDiagnosticCallPiece>(piece))
Ted Kremenek0f0cc352012-02-29 23:59:20 +0000196 WorkList.push_back(&call->path);
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000197 else if (const auto *macro = dyn_cast<PathDiagnosticMacroPiece>(piece))
Ted Kremenek0f0cc352012-02-29 23:59:20 +0000198 WorkList.push_back(&macro->subPieces);
Ted Kremenek0f70a6f2012-02-28 23:27:39 +0000199 }
200 }
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000201
Ted Kremenek0f70a6f2012-02-28 23:27:39 +0000202 if (FID.isInvalid())
203 return; // FIXME: Emit a warning?
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000204 }
Ted Kremenek0f70a6f2012-02-28 23:27:39 +0000205
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000206 // Profile the node to see if we already have something matching it
207 llvm::FoldingSetNodeID profile;
208 D->Profile(profile);
Craig Topper0dbb7832014-05-27 02:45:47 +0000209 void *InsertPos = nullptr;
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000210
211 if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) {
212 // Keep the PathDiagnostic with the shorter path.
Anna Zaks4bd96c42012-08-03 18:30:20 +0000213 // Note, the enclosing routine is called in deterministic order, so the
Anna Zaks4c03dfd2012-08-02 23:41:05 +0000214 // results will be consistent between runs (no reason to break ties if the
215 // size is the same).
Ted Kremenek60a78202012-02-24 06:00:00 +0000216 const unsigned orig_size = orig->full_size();
217 const unsigned new_size = D->full_size();
Anna Zaks4c03dfd2012-08-02 23:41:05 +0000218 if (orig_size <= new_size)
219 return;
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000220
David Blaikiec9950cb2014-08-29 20:06:10 +0000221 assert(orig != D.get());
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000222 Diags.RemoveNode(orig);
223 delete orig;
224 }
Ahmed Charles9a16beb2014-03-07 19:33:25 +0000225
David Blaikiec9950cb2014-08-29 20:06:10 +0000226 Diags.InsertNode(D.release());
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000227}
228
David Blaikie05785d12013-02-20 22:23:23 +0000229static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y);
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000230
David Blaikie05785d12013-02-20 22:23:23 +0000231static Optional<bool>
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000232compareControlFlow(const PathDiagnosticControlFlowPiece &X,
233 const PathDiagnosticControlFlowPiece &Y) {
234 FullSourceLoc XSL = X.getStartLocation().asLocation();
235 FullSourceLoc YSL = Y.getStartLocation().asLocation();
236 if (XSL != YSL)
237 return XSL.isBeforeInTranslationUnitThan(YSL);
238 FullSourceLoc XEL = X.getEndLocation().asLocation();
239 FullSourceLoc YEL = Y.getEndLocation().asLocation();
240 if (XEL != YEL)
241 return XEL.isBeforeInTranslationUnitThan(YEL);
David Blaikie7a30dc52013-02-21 01:47:18 +0000242 return None;
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000243}
244
David Blaikie05785d12013-02-20 22:23:23 +0000245static Optional<bool> compareMacro(const PathDiagnosticMacroPiece &X,
246 const PathDiagnosticMacroPiece &Y) {
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000247 return comparePath(X.subPieces, Y.subPieces);
248}
249
David Blaikie05785d12013-02-20 22:23:23 +0000250static Optional<bool> compareCall(const PathDiagnosticCallPiece &X,
251 const PathDiagnosticCallPiece &Y) {
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000252 FullSourceLoc X_CEL = X.callEnter.asLocation();
253 FullSourceLoc Y_CEL = Y.callEnter.asLocation();
254 if (X_CEL != Y_CEL)
255 return X_CEL.isBeforeInTranslationUnitThan(Y_CEL);
256 FullSourceLoc X_CEWL = X.callEnterWithin.asLocation();
257 FullSourceLoc Y_CEWL = Y.callEnterWithin.asLocation();
258 if (X_CEWL != Y_CEWL)
259 return X_CEWL.isBeforeInTranslationUnitThan(Y_CEWL);
260 FullSourceLoc X_CRL = X.callReturn.asLocation();
261 FullSourceLoc Y_CRL = Y.callReturn.asLocation();
262 if (X_CRL != Y_CRL)
263 return X_CRL.isBeforeInTranslationUnitThan(Y_CRL);
264 return comparePath(X.path, Y.path);
265}
266
David Blaikie05785d12013-02-20 22:23:23 +0000267static Optional<bool> comparePiece(const PathDiagnosticPiece &X,
268 const PathDiagnosticPiece &Y) {
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000269 if (X.getKind() != Y.getKind())
270 return X.getKind() < Y.getKind();
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000271
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000272 FullSourceLoc XL = X.getLocation().asLocation();
273 FullSourceLoc YL = Y.getLocation().asLocation();
274 if (XL != YL)
275 return XL.isBeforeInTranslationUnitThan(YL);
276
277 if (X.getString() != Y.getString())
278 return X.getString() < Y.getString();
279
280 if (X.getRanges().size() != Y.getRanges().size())
281 return X.getRanges().size() < Y.getRanges().size();
282
Ted Kremenek54fd0792012-09-10 19:02:33 +0000283 const SourceManager &SM = XL.getManager();
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000284
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000285 for (unsigned i = 0, n = X.getRanges().size(); i < n; ++i) {
286 SourceRange XR = X.getRanges()[i];
287 SourceRange YR = Y.getRanges()[i];
288 if (XR != YR) {
289 if (XR.getBegin() != YR.getBegin())
Ted Kremenek54fd0792012-09-10 19:02:33 +0000290 return SM.isBeforeInTranslationUnit(XR.getBegin(), YR.getBegin());
291 return SM.isBeforeInTranslationUnit(XR.getEnd(), YR.getEnd());
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000292 }
293 }
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000294
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000295 switch (X.getKind()) {
Artem Dergachev8b70c4e2016-10-07 15:23:02 +0000296 case PathDiagnosticPiece::ControlFlow:
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000297 return compareControlFlow(cast<PathDiagnosticControlFlowPiece>(X),
298 cast<PathDiagnosticControlFlowPiece>(Y));
Artem Dergachev8b70c4e2016-10-07 15:23:02 +0000299 case PathDiagnosticPiece::Macro:
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000300 return compareMacro(cast<PathDiagnosticMacroPiece>(X),
301 cast<PathDiagnosticMacroPiece>(Y));
Artem Dergachev8b70c4e2016-10-07 15:23:02 +0000302 case PathDiagnosticPiece::Call:
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000303 return compareCall(cast<PathDiagnosticCallPiece>(X),
304 cast<PathDiagnosticCallPiece>(Y));
Csaba Dabis1d7ca672019-05-29 19:21:59 +0000305 case PathDiagnosticPiece::Event:
306 case PathDiagnosticPiece::Note:
307 case PathDiagnosticPiece::PopUp:
308 return None;
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000309 }
310 llvm_unreachable("all cases handled");
311}
312
David Blaikie05785d12013-02-20 22:23:23 +0000313static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y) {
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000314 if (X.size() != Y.size())
315 return X.size() < Y.size();
Ted Kremenek518e7812013-04-29 22:38:22 +0000316
Ted Kremenekeba09fa2013-04-29 23:12:59 +0000317 PathPieces::const_iterator X_I = X.begin(), X_end = X.end();
318 PathPieces::const_iterator Y_I = Y.begin(), Y_end = Y.end();
Ted Kremenek518e7812013-04-29 22:38:22 +0000319
320 for ( ; X_I != X_end && Y_I != Y_end; ++X_I, ++Y_I) {
Ted Kremenekeba09fa2013-04-29 23:12:59 +0000321 Optional<bool> b = comparePiece(**X_I, **Y_I);
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000322 if (b.hasValue())
323 return b.getValue();
324 }
Ted Kremenek518e7812013-04-29 22:38:22 +0000325
David Blaikie7a30dc52013-02-21 01:47:18 +0000326 return None;
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000327}
328
Ilya Biryukov8b9b3bd2018-03-01 14:54:16 +0000329static bool compareCrossTUSourceLocs(FullSourceLoc XL, FullSourceLoc YL) {
330 std::pair<FileID, unsigned> XOffs = XL.getDecomposedLoc();
331 std::pair<FileID, unsigned> YOffs = YL.getDecomposedLoc();
332 const SourceManager &SM = XL.getManager();
333 std::pair<bool, bool> InSameTU = SM.isInTheSameTranslationUnit(XOffs, YOffs);
334 if (InSameTU.first)
335 return XL.isBeforeInTranslationUnitThan(YL);
Rafael Stahl67676e92018-07-04 14:12:58 +0000336 const FileEntry *XFE = SM.getFileEntryForID(XL.getSpellingLoc().getFileID());
337 const FileEntry *YFE = SM.getFileEntryForID(YL.getSpellingLoc().getFileID());
Ilya Biryukov8b9b3bd2018-03-01 14:54:16 +0000338 if (!XFE || !YFE)
339 return XFE && !YFE;
Rafael Stahl67676e92018-07-04 14:12:58 +0000340 int NameCmp = XFE->getName().compare(YFE->getName());
341 if (NameCmp != 0)
342 return NameCmp == -1;
343 // Last resort: Compare raw file IDs that are possibly expansions.
344 return XL.getFileID() < YL.getFileID();
Ilya Biryukov8b9b3bd2018-03-01 14:54:16 +0000345}
346
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000347static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y) {
348 FullSourceLoc XL = X.getLocation().asLocation();
349 FullSourceLoc YL = Y.getLocation().asLocation();
350 if (XL != YL)
Ilya Biryukov8b9b3bd2018-03-01 14:54:16 +0000351 return compareCrossTUSourceLocs(XL, YL);
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000352 if (X.getBugType() != Y.getBugType())
353 return X.getBugType() < Y.getBugType();
354 if (X.getCategory() != Y.getCategory())
355 return X.getCategory() < Y.getCategory();
356 if (X.getVerboseDescription() != Y.getVerboseDescription())
357 return X.getVerboseDescription() < Y.getVerboseDescription();
358 if (X.getShortDescription() != Y.getShortDescription())
359 return X.getShortDescription() < Y.getShortDescription();
360 if (X.getDeclWithIssue() != Y.getDeclWithIssue()) {
361 const Decl *XD = X.getDeclWithIssue();
362 if (!XD)
363 return true;
364 const Decl *YD = Y.getDeclWithIssue();
365 if (!YD)
366 return false;
367 SourceLocation XDL = XD->getLocation();
368 SourceLocation YDL = YD->getLocation();
Ted Kremeneka0fa5d62012-09-10 19:07:56 +0000369 if (XDL != YDL) {
370 const SourceManager &SM = XL.getManager();
Ilya Biryukov8b9b3bd2018-03-01 14:54:16 +0000371 return compareCrossTUSourceLocs(FullSourceLoc(XDL, SM),
372 FullSourceLoc(YDL, SM));
Ted Kremeneka0fa5d62012-09-10 19:07:56 +0000373 }
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000374 }
375 PathDiagnostic::meta_iterator XI = X.meta_begin(), XE = X.meta_end();
376 PathDiagnostic::meta_iterator YI = Y.meta_begin(), YE = Y.meta_end();
377 if (XE - XI != YE - YI)
378 return (XE - XI) < (YE - YI);
379 for ( ; XI != XE ; ++XI, ++YI) {
380 if (*XI != *YI)
381 return (*XI) < (*YI);
382 }
David Blaikie05785d12013-02-20 22:23:23 +0000383 Optional<bool> b = comparePath(X.path, Y.path);
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000384 assert(b.hasValue());
385 return b.getValue();
386}
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000387
Ted Kremenek9bf9af92012-08-16 17:45:23 +0000388void PathDiagnosticConsumer::FlushDiagnostics(
389 PathDiagnosticConsumer::FilesMade *Files) {
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000390 if (flushed)
391 return;
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000392
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000393 flushed = true;
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000394
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000395 std::vector<const PathDiagnostic *> BatchDiags;
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000396 for (const auto &D : Diags)
397 BatchDiags.push_back(&D);
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000398
399 // Sort the diagnostics so that they are always emitted in a deterministic
400 // order.
Benjamin Kramer5caa50e2015-03-14 12:39:22 +0000401 int (*Comp)(const PathDiagnostic *const *, const PathDiagnostic *const *) =
402 [](const PathDiagnostic *const *X, const PathDiagnostic *const *Y) {
403 assert(*X != *Y && "PathDiagnostics not uniqued!");
404 if (compare(**X, **Y))
405 return -1;
406 assert(compare(**Y, **X) && "Not a total order!");
407 return 1;
408 };
409 array_pod_sort(BatchDiags.begin(), BatchDiags.end(), Comp);
Benjamin Kramerbbdd7642014-03-01 14:48:57 +0000410
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000411 FlushDiagnosticsImpl(BatchDiags, Files);
412
413 // Delete the flushed diagnostics.
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000414 for (const auto D : BatchDiags)
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000415 delete D;
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000416
Ted Kremenekb0d1c702012-09-08 04:26:37 +0000417 // Clear out the FoldingSet.
418 Diags.clear();
Ted Kremenek996bfab2011-08-27 21:39:14 +0000419}
420
Chandler Carruth7ff07722014-05-03 10:39:05 +0000421PathDiagnosticConsumer::FilesMade::~FilesMade() {
Benjamin Kramerb474c042015-03-22 18:16:22 +0000422 for (PDFileEntry &Entry : Set)
Chandler Carruth7ff07722014-05-03 10:39:05 +0000423 Entry.~PDFileEntry();
424}
425
Ted Kremenek5bc38ba2012-08-24 19:35:19 +0000426void PathDiagnosticConsumer::FilesMade::addDiagnostic(const PathDiagnostic &PD,
427 StringRef ConsumerName,
428 StringRef FileName) {
429 llvm::FoldingSetNodeID NodeID;
Jordan Rosecc0b1bf2012-08-31 00:36:26 +0000430 NodeID.Add(PD);
Ted Kremenek5bc38ba2012-08-24 19:35:19 +0000431 void *InsertPos;
Benjamin Kramerb474c042015-03-22 18:16:22 +0000432 PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
Ted Kremenek5bc38ba2012-08-24 19:35:19 +0000433 if (!Entry) {
434 Entry = Alloc.Allocate<PDFileEntry>();
435 Entry = new (Entry) PDFileEntry(NodeID);
Benjamin Kramerb474c042015-03-22 18:16:22 +0000436 Set.InsertNode(Entry, InsertPos);
Ted Kremenek5bc38ba2012-08-24 19:35:19 +0000437 }
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000438
Ted Kremenek5bc38ba2012-08-24 19:35:19 +0000439 // Allocate persistent storage for the file name.
440 char *FileName_cstr = (char*) Alloc.Allocate(FileName.size(), 1);
441 memcpy(FileName_cstr, FileName.data(), FileName.size());
442
443 Entry->files.push_back(std::make_pair(ConsumerName,
444 StringRef(FileName_cstr,
445 FileName.size())));
446}
447
448PathDiagnosticConsumer::PDFileEntry::ConsumerFiles *
449PathDiagnosticConsumer::FilesMade::getFiles(const PathDiagnostic &PD) {
450 llvm::FoldingSetNodeID NodeID;
Jordan Rosecc0b1bf2012-08-31 00:36:26 +0000451 NodeID.Add(PD);
Ted Kremenek5bc38ba2012-08-24 19:35:19 +0000452 void *InsertPos;
Benjamin Kramerb474c042015-03-22 18:16:22 +0000453 PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
Ted Kremenek5bc38ba2012-08-24 19:35:19 +0000454 if (!Entry)
Craig Topper0dbb7832014-05-27 02:45:47 +0000455 return nullptr;
Ted Kremenek5bc38ba2012-08-24 19:35:19 +0000456 return &Entry->files;
457}
458
Ted Kremenekbade06e2009-03-26 21:39:39 +0000459//===----------------------------------------------------------------------===//
460// PathDiagnosticLocation methods.
461//===----------------------------------------------------------------------===//
462
Artem Dergachev6b85f8e2019-09-11 20:54:21 +0000463SourceLocation PathDiagnosticLocation::getValidSourceLocation(
464 const Stmt *S, LocationOrAnalysisDeclContext LAC, bool UseEndOfStatement) {
465 SourceLocation L = UseEndOfStatement ? S->getEndLoc() : S->getBeginLoc();
466 assert(!LAC.isNull() &&
467 "A valid LocationContext or AnalysisDeclContext should be passed to "
468 "PathDiagnosticLocation upon creation.");
Anna Zaksefd182d2011-09-16 19:18:30 +0000469
470 // S might be a temporary statement that does not have a location in the
Jordan Rosea4c0d212012-07-26 20:04:05 +0000471 // source code, so find an enclosing statement and use its location.
Anna Zaksde03d722011-09-20 16:37:36 +0000472 if (!L.isValid()) {
Jordan Rose25bc20f2012-07-26 20:04:30 +0000473 AnalysisDeclContext *ADC;
Anna Zaks83128bc2011-09-20 18:23:52 +0000474 if (LAC.is<const LocationContext*>())
Jordan Rose25bc20f2012-07-26 20:04:30 +0000475 ADC = LAC.get<const LocationContext*>()->getAnalysisDeclContext();
Anna Zaks83128bc2011-09-20 18:23:52 +0000476 else
Jordan Rose25bc20f2012-07-26 20:04:30 +0000477 ADC = LAC.get<AnalysisDeclContext*>();
Anna Zaksde03d722011-09-20 16:37:36 +0000478
Jordan Rose25bc20f2012-07-26 20:04:30 +0000479 ParentMap &PM = ADC->getParentMap();
480
481 const Stmt *Parent = S;
482 do {
483 Parent = PM.getParent(Parent);
484
485 // In rare cases, we have implicit top-level expressions,
486 // such as arguments for implicit member initializers.
487 // In this case, fall back to the start of the body (even if we were
488 // asked for the statement end location).
489 if (!Parent) {
490 const Stmt *Body = ADC->getBody();
491 if (Body)
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000492 L = Body->getBeginLoc();
Jordan Rose25bc20f2012-07-26 20:04:30 +0000493 else
Stephen Kelly1c301dc2018-08-09 21:09:38 +0000494 L = ADC->getDecl()->getEndLoc();
Jordan Rose25bc20f2012-07-26 20:04:30 +0000495 break;
496 }
497
Artem Dergachev6b85f8e2019-09-11 20:54:21 +0000498 L = UseEndOfStatement ? Parent->getEndLoc() : Parent->getBeginLoc();
Jordan Rose25bc20f2012-07-26 20:04:30 +0000499 } while (!L.isValid());
Anna Zaksefd182d2011-09-16 19:18:30 +0000500 }
501
Kristof Umann49628162019-03-14 16:10:29 +0000502 // FIXME: Ironically, this assert actually fails in some cases.
503 //assert(L.isValid());
Anna Zaksefd182d2011-09-16 19:18:30 +0000504 return L;
505}
506
Jordan Rose80880ac2012-08-03 23:08:44 +0000507static PathDiagnosticLocation
508getLocationForCaller(const StackFrameContext *SFC,
509 const LocationContext *CallerCtx,
510 const SourceManager &SM) {
511 const CFGBlock &Block = *SFC->getCallSiteBlock();
512 CFGElement Source = Block[SFC->getIndex()];
513
514 switch (Source.getKind()) {
Jordan Rose80880ac2012-08-03 23:08:44 +0000515 case CFGElement::Statement:
Artem Dergachev41ffb302018-02-08 22:58:15 +0000516 case CFGElement::Constructor:
Artem Dergachev1527dec2018-03-12 23:12:40 +0000517 case CFGElement::CXXRecordTypedCall:
David Blaikie2a01f5d2013-02-21 20:58:29 +0000518 return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(),
Jordan Rose80880ac2012-08-03 23:08:44 +0000519 SM, CallerCtx);
520 case CFGElement::Initializer: {
David Blaikie2a01f5d2013-02-21 20:58:29 +0000521 const CFGInitializer &Init = Source.castAs<CFGInitializer>();
Jordan Rose80880ac2012-08-03 23:08:44 +0000522 return PathDiagnosticLocation(Init.getInitializer()->getInit(),
523 SM, CallerCtx);
524 }
525 case CFGElement::AutomaticObjectDtor: {
David Blaikie2a01f5d2013-02-21 20:58:29 +0000526 const CFGAutomaticObjDtor &Dtor = Source.castAs<CFGAutomaticObjDtor>();
Jordan Rose80880ac2012-08-03 23:08:44 +0000527 return PathDiagnosticLocation::createEnd(Dtor.getTriggerStmt(),
528 SM, CallerCtx);
529 }
Jordan Rosed2f40792013-09-03 17:00:57 +0000530 case CFGElement::DeleteDtor: {
Jordan Rose1417a7b2013-10-31 18:41:15 +0000531 const CFGDeleteDtor &Dtor = Source.castAs<CFGDeleteDtor>();
532 return PathDiagnosticLocation(Dtor.getDeleteExpr(), SM, CallerCtx);
Jordan Rosed2f40792013-09-03 17:00:57 +0000533 }
Jordan Rose80880ac2012-08-03 23:08:44 +0000534 case CFGElement::BaseDtor:
535 case CFGElement::MemberDtor: {
536 const AnalysisDeclContext *CallerInfo = CallerCtx->getAnalysisDeclContext();
537 if (const Stmt *CallerBody = CallerInfo->getBody())
538 return PathDiagnosticLocation::createEnd(CallerBody, SM, CallerCtx);
539 return PathDiagnosticLocation::create(CallerInfo->getDecl(), SM);
540 }
Artem Dergacheve769fb72018-01-18 00:10:21 +0000541 case CFGElement::NewAllocator: {
542 const CFGNewAllocator &Alloc = Source.castAs<CFGNewAllocator>();
543 return PathDiagnosticLocation(Alloc.getAllocatorExpr(), SM, CallerCtx);
544 }
Artem Dergachev60f5aab2018-02-15 19:28:21 +0000545 case CFGElement::TemporaryDtor: {
546 // Temporary destructors are for temporaries. They die immediately at around
547 // the location of CXXBindTemporaryExpr. If they are lifetime-extended,
548 // they'd be dealt with via an AutomaticObjectDtor instead.
549 const auto &Dtor = Source.castAs<CFGTemporaryDtor>();
550 return PathDiagnosticLocation::createEnd(Dtor.getBindTemporaryExpr(), SM,
551 CallerCtx);
552 }
Maxim Ostapenkodebca452018-03-12 12:26:15 +0000553 case CFGElement::ScopeBegin:
554 case CFGElement::ScopeEnd:
555 llvm_unreachable("not yet implemented!");
Peter Szecsi999a25f2017-08-19 11:19:16 +0000556 case CFGElement::LifetimeEnds:
557 case CFGElement::LoopExit:
558 llvm_unreachable("CFGElement kind should not be on callsite!");
Jordan Rose80880ac2012-08-03 23:08:44 +0000559 }
560
561 llvm_unreachable("Unknown CFGElement kind");
562}
563
Anna Zaksefd182d2011-09-16 19:18:30 +0000564PathDiagnosticLocation
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000565PathDiagnosticLocation::createBegin(const Decl *D,
566 const SourceManager &SM) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000567 return PathDiagnosticLocation(D->getBeginLoc(), SM, SingleLocK);
Anna Zaksc29bed32011-09-20 21:38:35 +0000568}
569
570PathDiagnosticLocation
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000571PathDiagnosticLocation::createBegin(const Stmt *S,
572 const SourceManager &SM,
573 LocationOrAnalysisDeclContext LAC) {
Anna Zaks83128bc2011-09-20 18:23:52 +0000574 return PathDiagnosticLocation(getValidSourceLocation(S, LAC),
Anna Zaks745486a2011-09-20 01:51:40 +0000575 SM, SingleLocK);
Anna Zaksefd182d2011-09-16 19:18:30 +0000576}
577
Jordan Rosea4c0d212012-07-26 20:04:05 +0000578PathDiagnosticLocation
579PathDiagnosticLocation::createEnd(const Stmt *S,
580 const SourceManager &SM,
581 LocationOrAnalysisDeclContext LAC) {
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000582 if (const auto *CS = dyn_cast<CompoundStmt>(S))
Jordan Rosea4c0d212012-07-26 20:04:05 +0000583 return createEndBrace(CS, SM);
584 return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true),
585 SM, SingleLocK);
586}
587
Anna Zaksefd182d2011-09-16 19:18:30 +0000588PathDiagnosticLocation
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000589PathDiagnosticLocation::createOperatorLoc(const BinaryOperator *BO,
590 const SourceManager &SM) {
Anna Zaksefd182d2011-09-16 19:18:30 +0000591 return PathDiagnosticLocation(BO->getOperatorLoc(), SM, SingleLocK);
592}
593
594PathDiagnosticLocation
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000595PathDiagnosticLocation::createConditionalColonLoc(
Jordan Rose60bd88d2013-12-10 18:18:06 +0000596 const ConditionalOperator *CO,
597 const SourceManager &SM) {
598 return PathDiagnosticLocation(CO->getColonLoc(), SM, SingleLocK);
599}
600
Jordan Rose60bd88d2013-12-10 18:18:06 +0000601PathDiagnosticLocation
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000602PathDiagnosticLocation::createMemberLoc(const MemberExpr *ME,
603 const SourceManager &SM) {
Kristof Umann49628162019-03-14 16:10:29 +0000604
605 assert(ME->getMemberLoc().isValid() || ME->getBeginLoc().isValid());
606
607 // In some cases, getMemberLoc isn't valid -- in this case we'll return with
608 // some other related valid SourceLocation.
609 if (ME->getMemberLoc().isValid())
610 return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK);
611
612 return PathDiagnosticLocation(ME->getBeginLoc(), SM, SingleLocK);
Anna Zaksc29bed32011-09-20 21:38:35 +0000613}
614
615PathDiagnosticLocation
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000616PathDiagnosticLocation::createBeginBrace(const CompoundStmt *CS,
617 const SourceManager &SM) {
Anna Zaksefd182d2011-09-16 19:18:30 +0000618 SourceLocation L = CS->getLBracLoc();
619 return PathDiagnosticLocation(L, SM, SingleLocK);
620}
621
622PathDiagnosticLocation
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000623PathDiagnosticLocation::createEndBrace(const CompoundStmt *CS,
624 const SourceManager &SM) {
Anna Zaksefd182d2011-09-16 19:18:30 +0000625 SourceLocation L = CS->getRBracLoc();
626 return PathDiagnosticLocation(L, SM, SingleLocK);
627}
628
629PathDiagnosticLocation
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000630PathDiagnosticLocation::createDeclBegin(const LocationContext *LC,
631 const SourceManager &SM) {
Anna Zaksefd182d2011-09-16 19:18:30 +0000632 // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000633 if (const auto *CS = dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
Anna Zaksefd182d2011-09-16 19:18:30 +0000634 if (!CS->body_empty()) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000635 SourceLocation Loc = (*CS->body_begin())->getBeginLoc();
Anna Zaksefd182d2011-09-16 19:18:30 +0000636 return PathDiagnosticLocation(Loc, SM, SingleLocK);
637 }
638
639 return PathDiagnosticLocation();
640}
641
642PathDiagnosticLocation
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000643PathDiagnosticLocation::createDeclEnd(const LocationContext *LC,
644 const SourceManager &SM) {
Anna Zaks921f0492011-09-15 18:56:07 +0000645 SourceLocation L = LC->getDecl()->getBodyRBrace();
Anna Zaksefd182d2011-09-16 19:18:30 +0000646 return PathDiagnosticLocation(L, SM, SingleLocK);
Anna Zaks921f0492011-09-15 18:56:07 +0000647}
648
Anna Zaksde8c5ed2011-09-20 01:38:47 +0000649PathDiagnosticLocation
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000650PathDiagnosticLocation::create(const ProgramPoint& P,
651 const SourceManager &SMng) {
Craig Topper0dbb7832014-05-27 02:45:47 +0000652 const Stmt* S = nullptr;
David Blaikie87396b92013-02-21 22:23:56 +0000653 if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
Anna Zaks921f0492011-09-15 18:56:07 +0000654 const CFGBlock *BSrc = BE->getSrc();
Artem Dergachevef0aab32019-05-24 23:37:11 +0000655 if (BSrc->getTerminator().isVirtualBaseBranch()) {
656 // TODO: VirtualBaseBranches should also appear for destructors.
657 // In this case we should put the diagnostic at the end of decl.
658 return PathDiagnosticLocation::createBegin(
659 P.getLocationContext()->getDecl(), SMng);
660
661 } else {
662 S = BSrc->getTerminatorCondition();
Adam Balogh9ed4b312019-05-28 13:07:09 +0000663 if (!S) {
664 // If the BlockEdge has no terminator condition statement but its
665 // source is the entry of the CFG (e.g. a checker crated the branch at
666 // the beginning of a function), use the function's declaration instead.
667 assert(BSrc == &BSrc->getParent()->getEntry() && "CFGBlock has no "
668 "TerminatorCondition and is not the enrty block of the CFG");
669 return PathDiagnosticLocation::createBegin(
670 P.getLocationContext()->getDecl(), SMng);
671 }
Artem Dergachevef0aab32019-05-24 23:37:11 +0000672 }
David Blaikie87396b92013-02-21 22:23:56 +0000673 } else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) {
Jordan Roseec44ac62012-10-29 17:31:59 +0000674 S = SP->getStmt();
David Blaikie87396b92013-02-21 22:23:56 +0000675 if (P.getAs<PostStmtPurgeDeadSymbols>())
Jordan Rosee37ab502012-11-15 19:11:43 +0000676 return PathDiagnosticLocation::createEnd(S, SMng, P.getLocationContext());
Anna Zaksece622a2013-04-05 00:59:33 +0000677 } else if (Optional<PostInitializer> PIP = P.getAs<PostInitializer>()) {
678 return PathDiagnosticLocation(PIP->getInitializer()->getSourceLocation(),
679 SMng);
Artem Dergachevfc720072019-01-10 23:44:44 +0000680 } else if (Optional<PreImplicitCall> PIC = P.getAs<PreImplicitCall>()) {
681 return PathDiagnosticLocation(PIC->getLocation(), SMng);
David Blaikie87396b92013-02-21 22:23:56 +0000682 } else if (Optional<PostImplicitCall> PIE = P.getAs<PostImplicitCall>()) {
Jordan Rose80880ac2012-08-03 23:08:44 +0000683 return PathDiagnosticLocation(PIE->getLocation(), SMng);
David Blaikie87396b92013-02-21 22:23:56 +0000684 } else if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
Jordan Rose80880ac2012-08-03 23:08:44 +0000685 return getLocationForCaller(CE->getCalleeContext(),
686 CE->getLocationContext(),
687 SMng);
David Blaikie87396b92013-02-21 22:23:56 +0000688 } else if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) {
Jordan Rose80880ac2012-08-03 23:08:44 +0000689 return getLocationForCaller(CEE->getCalleeContext(),
690 CEE->getLocationContext(),
691 SMng);
George Karpenkov2c2d0b62019-01-18 19:24:55 +0000692 } else if (auto CEB = P.getAs<CallExitBegin>()) {
693 if (const ReturnStmt *RS = CEB->getReturnStmt())
694 return PathDiagnosticLocation::createBegin(RS, SMng,
695 CEB->getLocationContext());
696 return PathDiagnosticLocation(
697 CEB->getLocationContext()->getDecl()->getSourceRange().getEnd(), SMng);
Devin Coughlin9a2c14a2017-11-29 18:25:37 +0000698 } else if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) {
Kristof Umannb8ac93c2019-09-18 22:24:26 +0000699 if (Optional<CFGElement> BlockFront = BE->getFirstElement()) {
700 if (auto StmtElt = BlockFront->getAs<CFGStmt>()) {
701 return PathDiagnosticLocation(StmtElt->getStmt()->getBeginLoc(), SMng);
702 } else if (auto NewAllocElt = BlockFront->getAs<CFGNewAllocator>()) {
703 return PathDiagnosticLocation(
704 NewAllocElt->getAllocatorExpr()->getBeginLoc(), SMng);
705 }
706 llvm_unreachable("Unexpected CFG element at front of block");
Devin Coughlin9a2c14a2017-11-29 18:25:37 +0000707 }
Kristof Umannb8ac93c2019-09-18 22:24:26 +0000708
709 return PathDiagnosticLocation(
710 BE->getBlock()->getTerminatorStmt()->getBeginLoc(), SMng);
Csaba Dabis57835bc2019-07-04 00:50:50 +0000711 } else if (Optional<FunctionExitPoint> FE = P.getAs<FunctionExitPoint>()) {
712 return PathDiagnosticLocation(FE->getStmt(), SMng,
713 FE->getLocationContext());
David Blaikie87396b92013-02-21 22:23:56 +0000714 } else {
Jordan Roseec44ac62012-10-29 17:31:59 +0000715 llvm_unreachable("Unexpected ProgramPoint");
716 }
Anna Zaks921f0492011-09-15 18:56:07 +0000717
Anna Zaksde8c5ed2011-09-20 01:38:47 +0000718 return PathDiagnosticLocation(S, SMng, P.getLocationContext());
Anna Zaks921f0492011-09-15 18:56:07 +0000719}
720
Anna Zaksde8c5ed2011-09-20 01:38:47 +0000721PathDiagnosticLocation PathDiagnosticLocation::createSingleLocation(
722 const PathDiagnosticLocation &PDL) {
723 FullSourceLoc L = PDL.asLocation();
724 return PathDiagnosticLocation(L, L.getManager(), SingleLocK);
725}
726
Anna Zaks745486a2011-09-20 01:51:40 +0000727FullSourceLoc
Anna Zaks15ca5e72011-09-21 00:35:58 +0000728 PathDiagnosticLocation::genLocation(SourceLocation L,
Ted Kremenek81ce1c82011-10-24 01:32:45 +0000729 LocationOrAnalysisDeclContext LAC) const {
Ted Kremenek0bb09092009-04-01 06:13:56 +0000730 assert(isValid());
Ted Kremenekc2511652009-03-26 21:42:51 +0000731 // Note that we want a 'switch' here so that the compiler can warn us in
732 // case we add more cases.
Ted Kremenekbade06e2009-03-26 21:39:39 +0000733 switch (K) {
Ted Kremenek92820d22009-04-06 22:33:35 +0000734 case SingleLocK:
735 case RangeK:
Ted Kremenek7c36d902009-03-26 21:42:00 +0000736 break;
Ted Kremenek92820d22009-04-06 22:33:35 +0000737 case StmtK:
Ted Kremenekc07e34c2012-01-10 15:26:13 +0000738 // Defensive checking.
739 if (!S)
740 break;
Anna Zaks83128bc2011-09-20 18:23:52 +0000741 return FullSourceLoc(getValidSourceLocation(S, LAC),
Anna Zaks615e3a62011-09-14 17:48:01 +0000742 const_cast<SourceManager&>(*SM));
Ted Kremenek92820d22009-04-06 22:33:35 +0000743 case DeclK:
Ted Kremenekc07e34c2012-01-10 15:26:13 +0000744 // Defensive checking.
745 if (!D)
746 break;
Ted Kremenek92820d22009-04-06 22:33:35 +0000747 return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
Ted Kremenekbade06e2009-03-26 21:39:39 +0000748 }
Mike Stump11289f42009-09-09 15:08:12 +0000749
Anna Zaksd70da082011-09-20 23:27:32 +0000750 return FullSourceLoc(L, const_cast<SourceManager&>(*SM));
Ted Kremenekbade06e2009-03-26 21:39:39 +0000751}
Ted Kremenek96110d52009-03-26 21:48:17 +0000752
Anna Zaks745486a2011-09-20 01:51:40 +0000753PathDiagnosticRange
Ted Kremenek81ce1c82011-10-24 01:32:45 +0000754 PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const {
Ted Kremenek0bb09092009-04-01 06:13:56 +0000755 assert(isValid());
Ted Kremenek96110d52009-03-26 21:48:17 +0000756 // Note that we want a 'switch' here so that the compiler can warn us in
757 // case we add more cases.
758 switch (K) {
Ted Kremenek92820d22009-04-06 22:33:35 +0000759 case SingleLocK:
Anna Zaks15ca5e72011-09-21 00:35:58 +0000760 return PathDiagnosticRange(SourceRange(Loc,Loc), true);
Ted Kremenek92820d22009-04-06 22:33:35 +0000761 case RangeK:
Ted Kremenek96110d52009-03-26 21:48:17 +0000762 break;
Ted Kremenek22579c42009-04-22 18:03:00 +0000763 case StmtK: {
764 const Stmt *S = asStmt();
765 switch (S->getStmtClass()) {
766 default:
767 break;
Ted Kremenek18665fe2009-05-15 02:05:25 +0000768 case Stmt::DeclStmtClass: {
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000769 const auto *DS = cast<DeclStmt>(S);
Ted Kremenek18665fe2009-05-15 02:05:25 +0000770 if (DS->isSingleDecl()) {
771 // Should always be the case, but we'll be defensive.
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000772 return SourceRange(DS->getBeginLoc(),
Mike Stump11289f42009-09-09 15:08:12 +0000773 DS->getSingleDecl()->getLocation());
Ted Kremenek18665fe2009-05-15 02:05:25 +0000774 }
775 break;
776 }
Ted Kremenek22579c42009-04-22 18:03:00 +0000777 // FIXME: Provide better range information for different
778 // terminators.
779 case Stmt::IfStmtClass:
780 case Stmt::WhileStmtClass:
781 case Stmt::DoStmtClass:
782 case Stmt::ForStmtClass:
783 case Stmt::ChooseExprClass:
784 case Stmt::IndirectGotoStmtClass:
785 case Stmt::SwitchStmtClass:
John McCallc07a0c72011-02-17 10:25:35 +0000786 case Stmt::BinaryConditionalOperatorClass:
Ted Kremenek22579c42009-04-22 18:03:00 +0000787 case Stmt::ConditionalOperatorClass:
788 case Stmt::ObjCForCollectionStmtClass: {
Anna Zaks83128bc2011-09-20 18:23:52 +0000789 SourceLocation L = getValidSourceLocation(S, LAC);
Ted Kremenek22579c42009-04-22 18:03:00 +0000790 return SourceRange(L, L);
791 }
792 }
Anna Zaks15ca5e72011-09-21 00:35:58 +0000793 SourceRange R = S->getSourceRange();
794 if (R.isValid())
795 return R;
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000796 break;
Ted Kremenek22579c42009-04-22 18:03:00 +0000797 }
Ted Kremenek92820d22009-04-06 22:33:35 +0000798 case DeclK:
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000799 if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
Ted Kremenek92820d22009-04-06 22:33:35 +0000800 return MD->getSourceRange();
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000801 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
Argyrios Kyrtzidis0b6a06a2010-07-07 12:24:14 +0000802 if (Stmt *Body = FD->getBody())
803 return Body->getSourceRange();
Douglas Gregore3dcb2d2009-04-18 00:02:19 +0000804 }
Ted Kremenek92820d22009-04-06 22:33:35 +0000805 else {
806 SourceLocation L = D->getLocation();
Ted Kremenek63e29cc2009-04-22 22:26:10 +0000807 return PathDiagnosticRange(SourceRange(L, L), true);
Ted Kremenek92820d22009-04-06 22:33:35 +0000808 }
Ted Kremenek96110d52009-03-26 21:48:17 +0000809 }
Mike Stump11289f42009-09-09 15:08:12 +0000810
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000811 return SourceRange(Loc, Loc);
Ted Kremenek96110d52009-03-26 21:48:17 +0000812}
813
Ted Kremenek92820d22009-04-06 22:33:35 +0000814void PathDiagnosticLocation::flatten() {
815 if (K == StmtK) {
Ted Kremenek92820d22009-04-06 22:33:35 +0000816 K = RangeK;
Craig Topper0dbb7832014-05-27 02:45:47 +0000817 S = nullptr;
818 D = nullptr;
Ted Kremenek92820d22009-04-06 22:33:35 +0000819 }
820 else if (K == DeclK) {
Ted Kremenek92820d22009-04-06 22:33:35 +0000821 K = SingleLocK;
Craig Topper0dbb7832014-05-27 02:45:47 +0000822 S = nullptr;
823 D = nullptr;
Ted Kremenek92820d22009-04-06 22:33:35 +0000824 }
825}
826
Ted Kremenek60a78202012-02-24 06:00:00 +0000827//===----------------------------------------------------------------------===//
828// Manipulation of PathDiagnosticCallPieces.
829//===----------------------------------------------------------------------===//
830
David Blaikie0a0c2752017-01-05 17:26:53 +0000831std::shared_ptr<PathDiagnosticCallPiece>
George Karpenkovc82d4572018-09-28 18:49:41 +0000832PathDiagnosticCallPiece::construct(const CallExitEnd &CE,
Ted Kremenek60a78202012-02-24 06:00:00 +0000833 const SourceManager &SM) {
Anna Zaks7e53bd62012-04-20 21:59:08 +0000834 const Decl *caller = CE.getLocationContext()->getDecl();
Jordan Rosea4c0d212012-07-26 20:04:05 +0000835 PathDiagnosticLocation pos = getLocationForCaller(CE.getCalleeContext(),
836 CE.getLocationContext(),
837 SM);
David Blaikie0a0c2752017-01-05 17:26:53 +0000838 return std::shared_ptr<PathDiagnosticCallPiece>(
839 new PathDiagnosticCallPiece(caller, pos));
Ted Kremenek60a78202012-02-24 06:00:00 +0000840}
841
842PathDiagnosticCallPiece *
Anna Zaksd4e90592012-03-14 18:58:28 +0000843PathDiagnosticCallPiece::construct(PathPieces &path,
844 const Decl *caller) {
David Blaikie0a0c2752017-01-05 17:26:53 +0000845 std::shared_ptr<PathDiagnosticCallPiece> C(
846 new PathDiagnosticCallPiece(path, caller));
Ted Kremenek60a78202012-02-24 06:00:00 +0000847 path.clear();
David Blaikie0a0c2752017-01-05 17:26:53 +0000848 auto *R = C.get();
849 path.push_front(std::move(C));
850 return R;
Ted Kremenek60a78202012-02-24 06:00:00 +0000851}
852
853void PathDiagnosticCallPiece::setCallee(const CallEnter &CE,
854 const SourceManager &SM) {
Jordan Rosea4c0d212012-07-26 20:04:05 +0000855 const StackFrameContext *CalleeCtx = CE.getCalleeContext();
856 Callee = CalleeCtx->getDecl();
857
858 callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM);
859 callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
Artem Dergachevfbe891ee2017-06-05 12:40:03 +0000860
861 // Autosynthesized property accessors are special because we'd never
862 // pop back up to non-autosynthesized code until we leave them.
863 // This is not generally true for autosynthesized callees, which may call
864 // non-autosynthesized callbacks.
865 // Unless set here, the IsCalleeAnAutosynthesizedPropertyAccessor flag
866 // defaults to false.
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000867 if (const auto *MD = dyn_cast<ObjCMethodDecl>(Callee))
Artem Dergachevfbe891ee2017-06-05 12:40:03 +0000868 IsCalleeAnAutosynthesizedPropertyAccessor = (
869 MD->isPropertyAccessor() &&
870 CalleeCtx->getAnalysisDeclContext()->isBodyAutosynthesized());
Ted Kremenek60a78202012-02-24 06:00:00 +0000871}
872
Kristof Umann3ea74422018-05-25 13:18:38 +0000873static void describeTemplateParameters(raw_ostream &Out,
874 const ArrayRef<TemplateArgument> TAList,
875 const LangOptions &LO,
876 StringRef Prefix = StringRef(),
877 StringRef Postfix = StringRef());
878
879static void describeTemplateParameter(raw_ostream &Out,
880 const TemplateArgument &TArg,
881 const LangOptions &LO) {
882
883 if (TArg.getKind() == TemplateArgument::ArgKind::Pack) {
884 describeTemplateParameters(Out, TArg.getPackAsArray(), LO);
885 } else {
886 TArg.print(PrintingPolicy(LO), Out);
887 }
888}
889
890static void describeTemplateParameters(raw_ostream &Out,
891 const ArrayRef<TemplateArgument> TAList,
892 const LangOptions &LO,
893 StringRef Prefix, StringRef Postfix) {
894 if (TAList.empty())
895 return;
896
897 Out << Prefix;
898 for (int I = 0, Last = TAList.size() - 1; I != Last; ++I) {
899 describeTemplateParameter(Out, TAList[I], LO);
900 Out << ", ";
901 }
902 describeTemplateParameter(Out, TAList[TAList.size() - 1], LO);
903 Out << Postfix;
904}
905
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000906static void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
907 StringRef Prefix = StringRef()) {
Jordan Rose1dc39402013-01-18 18:27:21 +0000908 if (!D->getIdentifier())
909 return;
Kristof Umann3ea74422018-05-25 13:18:38 +0000910 Out << Prefix << '\'' << *D;
911 if (const auto T = dyn_cast<ClassTemplateSpecializationDecl>(D))
912 describeTemplateParameters(Out, T->getTemplateArgs().asArray(),
Reid Klecknerb36c19b2020-04-06 09:55:33 -0700913 D->getLangOpts(), "<", ">");
Kristof Umann3ea74422018-05-25 13:18:38 +0000914
915 Out << '\'';
Jordan Rose1dc39402013-01-18 18:27:21 +0000916}
917
Jordan Rosefe856d52013-01-18 18:27:14 +0000918static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
Jordan Rose1dc39402013-01-18 18:27:21 +0000919 bool ExtendedDescription,
Jordan Rosefe856d52013-01-18 18:27:14 +0000920 StringRef Prefix = StringRef()) {
921 if (!D)
922 return false;
923
924 if (isa<BlockDecl>(D)) {
Jordan Rose1dc39402013-01-18 18:27:21 +0000925 if (ExtendedDescription)
Jordan Rosefe856d52013-01-18 18:27:14 +0000926 Out << Prefix << "anonymous block";
Jordan Rose1dc39402013-01-18 18:27:21 +0000927 return ExtendedDescription;
Jordan Rosefe856d52013-01-18 18:27:14 +0000928 }
929
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000930 if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
Jordan Rose1dc39402013-01-18 18:27:21 +0000931 Out << Prefix;
932 if (ExtendedDescription && !MD->isUserProvided()) {
933 if (MD->isExplicitlyDefaulted())
934 Out << "defaulted ";
935 else
936 Out << "implicit ";
937 }
938
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000939 if (const auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
Jordan Rose1dc39402013-01-18 18:27:21 +0000940 if (CD->isDefaultConstructor())
941 Out << "default ";
942 else if (CD->isCopyConstructor())
943 Out << "copy ";
944 else if (CD->isMoveConstructor())
945 Out << "move ";
946
947 Out << "constructor";
948 describeClass(Out, MD->getParent(), " for ");
Jordan Rose1dc39402013-01-18 18:27:21 +0000949 } else if (isa<CXXDestructorDecl>(MD)) {
950 if (!MD->isUserProvided()) {
951 Out << "destructor";
952 describeClass(Out, MD->getParent(), " for ");
953 } else {
954 // Use ~Foo for explicitly-written destructors.
955 Out << "'" << *MD << "'";
956 }
Jordan Rose1dc39402013-01-18 18:27:21 +0000957 } else if (MD->isCopyAssignmentOperator()) {
958 Out << "copy assignment operator";
959 describeClass(Out, MD->getParent(), " for ");
Jordan Rose1dc39402013-01-18 18:27:21 +0000960 } else if (MD->isMoveAssignmentOperator()) {
961 Out << "move assignment operator";
962 describeClass(Out, MD->getParent(), " for ");
Jordan Rose1dc39402013-01-18 18:27:21 +0000963 } else {
964 if (MD->getParent()->getIdentifier())
965 Out << "'" << *MD->getParent() << "::" << *MD << "'";
966 else
967 Out << "'" << *MD << "'";
968 }
Jordan Rosefe856d52013-01-18 18:27:14 +0000969
970 return true;
971 }
972
Kristof Umann3ea74422018-05-25 13:18:38 +0000973 Out << Prefix << '\'' << cast<NamedDecl>(*D);
974
975 // Adding template parameters.
976 if (const auto FD = dyn_cast<FunctionDecl>(D))
977 if (const TemplateArgumentList *TAList =
978 FD->getTemplateSpecializationArgs())
Reid Klecknerb36c19b2020-04-06 09:55:33 -0700979 describeTemplateParameters(Out, TAList->asArray(), FD->getLangOpts(), "<",
980 ">");
Kristof Umann3ea74422018-05-25 13:18:38 +0000981
982 Out << '\'';
Jordan Rosefe856d52013-01-18 18:27:14 +0000983 return true;
984}
985
David Blaikie0a0c2752017-01-05 17:26:53 +0000986std::shared_ptr<PathDiagnosticEventPiece>
Ted Kremenek60a78202012-02-24 06:00:00 +0000987PathDiagnosticCallPiece::getCallEnterEvent() const {
Artem Dergachevfbe891ee2017-06-05 12:40:03 +0000988 // We do not produce call enters and call exits for autosynthesized property
989 // accessors. We do generally produce them for other functions coming from
990 // the body farm because they may call callbacks that bring us back into
991 // visible code.
992 if (!Callee || IsCalleeAnAutosynthesizedPropertyAccessor)
Craig Topper0dbb7832014-05-27 02:45:47 +0000993 return nullptr;
Jordan Rosefe856d52013-01-18 18:27:14 +0000994
Ted Kremenek60a78202012-02-24 06:00:00 +0000995 SmallString<256> buf;
996 llvm::raw_svector_ostream Out(buf);
Jordan Rosefe856d52013-01-18 18:27:14 +0000997
998 Out << "Calling ";
Jordan Rose1dc39402013-01-18 18:27:21 +0000999 describeCodeDecl(Out, Callee, /*ExtendedDescription=*/true);
Jordan Rosefe856d52013-01-18 18:27:14 +00001000
Jordan Rose2d98b972012-11-15 02:07:23 +00001001 assert(callEnter.asLocation().isValid());
David Blaikie0a0c2752017-01-05 17:26:53 +00001002 return std::make_shared<PathDiagnosticEventPiece>(callEnter, Out.str());
Ted Kremenek60a78202012-02-24 06:00:00 +00001003}
1004
David Blaikie0a0c2752017-01-05 17:26:53 +00001005std::shared_ptr<PathDiagnosticEventPiece>
Ted Kremenek04e860d2012-03-06 01:25:01 +00001006PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const {
Jordan Rose2d98b972012-11-15 02:07:23 +00001007 if (!callEnterWithin.asLocation().isValid())
Craig Topper0dbb7832014-05-27 02:45:47 +00001008 return nullptr;
Jordan Rose56138262013-05-24 21:43:11 +00001009 if (Callee->isImplicit() || !Callee->hasBody())
Craig Topper0dbb7832014-05-27 02:45:47 +00001010 return nullptr;
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001011 if (const auto *MD = dyn_cast<CXXMethodDecl>(Callee))
Jordan Rosed8876a72013-01-19 19:52:57 +00001012 if (MD->isDefaulted())
Craig Topper0dbb7832014-05-27 02:45:47 +00001013 return nullptr;
Jordan Rosefe856d52013-01-18 18:27:14 +00001014
Ted Kremenek04e860d2012-03-06 01:25:01 +00001015 SmallString<256> buf;
1016 llvm::raw_svector_ostream Out(buf);
Jordan Rosefe856d52013-01-18 18:27:14 +00001017
1018 Out << "Entered call";
Jordan Rose1dc39402013-01-18 18:27:21 +00001019 describeCodeDecl(Out, Caller, /*ExtendedDescription=*/false, " from ");
Jordan Rosefe856d52013-01-18 18:27:14 +00001020
David Blaikie0a0c2752017-01-05 17:26:53 +00001021 return std::make_shared<PathDiagnosticEventPiece>(callEnterWithin, Out.str());
Ted Kremenek04e860d2012-03-06 01:25:01 +00001022}
1023
David Blaikie0a0c2752017-01-05 17:26:53 +00001024std::shared_ptr<PathDiagnosticEventPiece>
Ted Kremenek60a78202012-02-24 06:00:00 +00001025PathDiagnosticCallPiece::getCallExitEvent() const {
Artem Dergachevfbe891ee2017-06-05 12:40:03 +00001026 // We do not produce call enters and call exits for autosynthesized property
1027 // accessors. We do generally produce them for other functions coming from
1028 // the body farm because they may call callbacks that bring us back into
1029 // visible code.
1030 if (NoExit || IsCalleeAnAutosynthesizedPropertyAccessor)
Craig Topper0dbb7832014-05-27 02:45:47 +00001031 return nullptr;
Jordan Rosefe856d52013-01-18 18:27:14 +00001032
Ted Kremenek60a78202012-02-24 06:00:00 +00001033 SmallString<256> buf;
1034 llvm::raw_svector_ostream Out(buf);
Jordan Rosefe856d52013-01-18 18:27:14 +00001035
1036 if (!CallStackMessage.empty()) {
Anna Zaksa7f457a2012-03-16 23:44:28 +00001037 Out << CallStackMessage;
Jordan Rosefe856d52013-01-18 18:27:14 +00001038 } else {
Jordan Rose1dc39402013-01-18 18:27:21 +00001039 bool DidDescribe = describeCodeDecl(Out, Callee,
1040 /*ExtendedDescription=*/false,
Jordan Rosefe856d52013-01-18 18:27:14 +00001041 "Returning from ");
1042 if (!DidDescribe)
1043 Out << "Returning to caller";
1044 }
1045
Jordan Rose2d98b972012-11-15 02:07:23 +00001046 assert(callReturn.asLocation().isValid());
David Blaikie0a0c2752017-01-05 17:26:53 +00001047 return std::make_shared<PathDiagnosticEventPiece>(callReturn, Out.str());
Ted Kremenek60a78202012-02-24 06:00:00 +00001048}
1049
1050static void compute_path_size(const PathPieces &pieces, unsigned &size) {
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001051 for (const auto &I : pieces) {
1052 const PathDiagnosticPiece *piece = I.get();
1053 if (const auto *cp = dyn_cast<PathDiagnosticCallPiece>(piece))
Ted Kremenek60a78202012-02-24 06:00:00 +00001054 compute_path_size(cp->path, size);
Ted Kremenek60a78202012-02-24 06:00:00 +00001055 else
1056 ++size;
1057 }
1058}
1059
1060unsigned PathDiagnostic::full_size() {
1061 unsigned size = 0;
1062 compute_path_size(path, size);
1063 return size;
1064}
1065
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001066//===----------------------------------------------------------------------===//
1067// FoldingSet profiling methods.
1068//===----------------------------------------------------------------------===//
Ted Kremenek92820d22009-04-06 22:33:35 +00001069
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001070void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
Anna Zaksb2dfc2b2011-09-20 21:25:00 +00001071 ID.AddInteger(Range.getBegin().getRawEncoding());
1072 ID.AddInteger(Range.getEnd().getRawEncoding());
1073 ID.AddInteger(Loc.getRawEncoding());
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001074}
1075
1076void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1077 ID.AddInteger((unsigned) getKind());
1078 ID.AddString(str);
1079 // FIXME: Add profiling support for code hints.
1080 ID.AddInteger((unsigned) getDisplayHint());
Ted Kremenek1e602732012-08-16 17:45:29 +00001081 ArrayRef<SourceRange> Ranges = getRanges();
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001082 for (const auto &I : Ranges) {
1083 ID.AddInteger(I.getBegin().getRawEncoding());
1084 ID.AddInteger(I.getEnd().getRawEncoding());
Ted Kremenek3a0678e2015-09-08 03:50:52 +00001085 }
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001086}
1087
Ted Kremenek60a78202012-02-24 06:00:00 +00001088void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1089 PathDiagnosticPiece::Profile(ID);
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001090 for (const auto &I : path)
1091 ID.Add(*I);
Ted Kremenek60a78202012-02-24 06:00:00 +00001092}
1093
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001094void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1095 PathDiagnosticPiece::Profile(ID);
1096 ID.Add(Pos);
1097}
1098
1099void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1100 PathDiagnosticPiece::Profile(ID);
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001101 for (const auto &I : *this)
1102 ID.Add(I);
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001103}
1104
1105void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1106 PathDiagnosticSpotPiece::Profile(ID);
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001107 for (const auto &I : subPieces)
1108 ID.Add(*I);
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001109}
1110
Artem Dergachev8b70c4e2016-10-07 15:23:02 +00001111void PathDiagnosticNotePiece::Profile(llvm::FoldingSetNodeID &ID) const {
1112 PathDiagnosticSpotPiece::Profile(ID);
1113}
1114
Csaba Dabis1d7ca672019-05-29 19:21:59 +00001115void PathDiagnosticPopUpPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1116 PathDiagnosticSpotPiece::Profile(ID);
1117}
1118
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001119void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
Jordan Rosecc0b1bf2012-08-31 00:36:26 +00001120 ID.Add(getLocation());
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001121 ID.AddString(BugType);
Jordan Rosecc0b1bf2012-08-31 00:36:26 +00001122 ID.AddString(VerboseDesc);
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001123 ID.AddString(Category);
Ted Kremenek8e4c4262012-01-25 23:47:14 +00001124}
1125
1126void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const {
1127 Profile(ID);
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001128 for (const auto &I : path)
1129 ID.Add(*I);
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001130 for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
1131 ID.AddString(*I);
1132}
Anna Zakscba4f292012-03-16 23:24:20 +00001133
George Karpenkov1cf8cdc2018-06-12 20:51:01 +00001134LLVM_DUMP_METHOD void PathPieces::dump() const {
1135 unsigned index = 0;
1136 for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
1137 llvm::errs() << "[" << index++ << "] ";
1138 (*I)->dump();
1139 llvm::errs() << "\n";
1140 }
1141}
1142
1143LLVM_DUMP_METHOD void PathDiagnosticCallPiece::dump() const {
1144 llvm::errs() << "CALL\n--------------\n";
1145
1146 if (const Stmt *SLoc = getLocation().getStmtOrNull())
1147 SLoc->dump();
1148 else if (const auto *ND = dyn_cast_or_null<NamedDecl>(getCallee()))
1149 llvm::errs() << *ND << "\n";
1150 else
1151 getLocation().dump();
1152}
1153
1154LLVM_DUMP_METHOD void PathDiagnosticEventPiece::dump() const {
1155 llvm::errs() << "EVENT\n--------------\n";
1156 llvm::errs() << getString() << "\n";
1157 llvm::errs() << " ---- at ----\n";
1158 getLocation().dump();
1159}
1160
1161LLVM_DUMP_METHOD void PathDiagnosticControlFlowPiece::dump() const {
1162 llvm::errs() << "CONTROL\n--------------\n";
1163 getStartLocation().dump();
1164 llvm::errs() << " ---- to ----\n";
1165 getEndLocation().dump();
1166}
1167
1168LLVM_DUMP_METHOD void PathDiagnosticMacroPiece::dump() const {
1169 llvm::errs() << "MACRO\n--------------\n";
1170 // FIXME: Print which macro is being invoked.
1171}
1172
1173LLVM_DUMP_METHOD void PathDiagnosticNotePiece::dump() const {
1174 llvm::errs() << "NOTE\n--------------\n";
1175 llvm::errs() << getString() << "\n";
1176 llvm::errs() << " ---- at ----\n";
1177 getLocation().dump();
1178}
1179
Csaba Dabis1d7ca672019-05-29 19:21:59 +00001180LLVM_DUMP_METHOD void PathDiagnosticPopUpPiece::dump() const {
1181 llvm::errs() << "POP-UP\n--------------\n";
1182 llvm::errs() << getString() << "\n";
1183 llvm::errs() << " ---- at ----\n";
1184 getLocation().dump();
1185}
1186
George Karpenkov1cf8cdc2018-06-12 20:51:01 +00001187LLVM_DUMP_METHOD void PathDiagnosticLocation::dump() const {
1188 if (!isValid()) {
1189 llvm::errs() << "<INVALID>\n";
1190 return;
1191 }
1192
1193 switch (K) {
1194 case RangeK:
1195 // FIXME: actually print the range.
1196 llvm::errs() << "<range>\n";
1197 break;
1198 case SingleLocK:
1199 asLocation().dump();
1200 llvm::errs() << "\n";
1201 break;
1202 case StmtK:
1203 if (S)
1204 S->dump();
1205 else
1206 llvm::errs() << "<NULL STMT>\n";
1207 break;
1208 case DeclK:
1209 if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
1210 llvm::errs() << *ND << "\n";
1211 else if (isa<BlockDecl>(D))
1212 // FIXME: Make this nicer.
1213 llvm::errs() << "<block>\n";
1214 else if (D)
1215 llvm::errs() << "<unknown decl>\n";
1216 else
1217 llvm::errs() << "<NULL DECL>\n";
1218 break;
1219 }
1220}