blob: 53235ba076994606f8847bef48b713936f916dbe [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"
Eugene Zelenko9f103a12018-03-08 22:45:13 +000023#include "clang/AST/Stmt.h"
24#include "clang/AST/Type.h"
25#include "clang/Analysis/AnalysisDeclContext.h"
26#include "clang/Analysis/CFG.h"
27#include "clang/Analysis/ProgramPoint.h"
28#include "clang/Basic/FileManager.h"
29#include "clang/Basic/LLVM.h"
30#include "clang/Basic/SourceLocation.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000031#include "clang/Basic/SourceManager.h"
Eugene Zelenko9f103a12018-03-08 22:45:13 +000032#include "llvm/ADT/ArrayRef.h"
33#include "llvm/ADT/FoldingSet.h"
34#include "llvm/ADT/None.h"
35#include "llvm/ADT/Optional.h"
36#include "llvm/ADT/STLExtras.h"
Chris Lattner23be0672008-11-19 06:51:40 +000037#include "llvm/ADT/SmallString.h"
Eugene Zelenko9f103a12018-03-08 22:45:13 +000038#include "llvm/ADT/SmallVector.h"
Jordan Rosec102b352012-09-22 01:24:42 +000039#include "llvm/ADT/StringExtras.h"
Eugene Zelenko9f103a12018-03-08 22:45:13 +000040#include "llvm/ADT/StringRef.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/ErrorHandling.h"
Benjamin Kramer444a1302012-12-01 17:12:56 +000043#include "llvm/Support/raw_ostream.h"
Eugene Zelenko9f103a12018-03-08 22:45:13 +000044#include <cassert>
45#include <cstring>
46#include <memory>
47#include <utility>
48#include <vector>
Ted Kremenekbb597cd2009-06-26 00:43:22 +000049
Ted Kremenek4fa20c92008-03-27 03:49:32 +000050using namespace clang;
Ted Kremenek98857c92010-12-23 07:20:52 +000051using namespace ento;
Ted Kremenekb4947e42009-03-10 05:16:17 +000052
Chris Lattner0e62c1c2011-07-23 10:55:15 +000053static StringRef StripTrailingDots(StringRef s) {
54 for (StringRef::size_type i = s.size(); i != 0; --i)
Benjamin Kramer4dab76a2009-12-11 21:09:27 +000055 if (s[i - 1] != '.')
56 return s.substr(0, i);
Eugene Zelenko9f103a12018-03-08 22:45:13 +000057 return {};
Ted Kremeneke9817aa2009-02-26 21:30:32 +000058}
59
Chris Lattner0e62c1c2011-07-23 10:55:15 +000060PathDiagnosticPiece::PathDiagnosticPiece(StringRef s,
Ted Kremenek1f8140d2009-03-02 19:39:50 +000061 Kind k, DisplayHint hint)
Eugene Zelenko9f103a12018-03-08 22:45:13 +000062 : str(StripTrailingDots(s)), kind(k), Hint(hint) {}
Ted Kremenek55f46f62009-03-06 07:53:30 +000063
Ted Kremenek3d46b1c2009-03-26 21:21:35 +000064PathDiagnosticPiece::PathDiagnosticPiece(Kind k, DisplayHint hint)
Eugene Zelenko9f103a12018-03-08 22:45:13 +000065 : kind(k), Hint(hint) {}
Ted Kremenek9d1ce8f2009-03-12 18:41:53 +000066
Eugene Zelenko9f103a12018-03-08 22:45:13 +000067PathDiagnosticPiece::~PathDiagnosticPiece() = default;
68
69PathDiagnosticEventPiece::~PathDiagnosticEventPiece() = default;
70
71PathDiagnosticCallPiece::~PathDiagnosticCallPiece() = default;
72
73PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() = default;
74
75PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() = default;
76
77PathDiagnosticNotePiece::~PathDiagnosticNotePiece() = default;
Ted Kremenek5a10f082012-04-04 18:11:35 +000078
Csaba Dabis1d7ca672019-05-29 19:21:59 +000079PathDiagnosticPopUpPiece::~PathDiagnosticPopUpPiece() = default;
80
Jordan Rose3eb3cd42012-08-03 23:08:54 +000081void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current,
82 bool ShouldFlattenMacros) const {
David Blaikie0a0c2752017-01-05 17:26:53 +000083 for (auto &Piece : *this) {
Jordan Rose3eb3cd42012-08-03 23:08:54 +000084 switch (Piece->getKind()) {
85 case PathDiagnosticPiece::Call: {
David Blaikie0a0c2752017-01-05 17:26:53 +000086 auto &Call = cast<PathDiagnosticCallPiece>(*Piece);
87 if (auto CallEnter = Call.getCallEnterEvent())
88 Current.push_back(std::move(CallEnter));
89 Call.path.flattenTo(Primary, Primary, ShouldFlattenMacros);
90 if (auto callExit = Call.getCallExitEvent())
91 Current.push_back(std::move(callExit));
Jordan Rose3eb3cd42012-08-03 23:08:54 +000092 break;
93 }
94 case PathDiagnosticPiece::Macro: {
David Blaikie0a0c2752017-01-05 17:26:53 +000095 auto &Macro = cast<PathDiagnosticMacroPiece>(*Piece);
Jordan Rose3eb3cd42012-08-03 23:08:54 +000096 if (ShouldFlattenMacros) {
David Blaikie0a0c2752017-01-05 17:26:53 +000097 Macro.subPieces.flattenTo(Primary, Primary, ShouldFlattenMacros);
Jordan Rose3eb3cd42012-08-03 23:08:54 +000098 } else {
99 Current.push_back(Piece);
100 PathPieces NewPath;
David Blaikie0a0c2752017-01-05 17:26:53 +0000101 Macro.subPieces.flattenTo(Primary, NewPath, ShouldFlattenMacros);
Jordan Rose3eb3cd42012-08-03 23:08:54 +0000102 // FIXME: This probably shouldn't mutate the original path piece.
David Blaikie0a0c2752017-01-05 17:26:53 +0000103 Macro.subPieces = NewPath;
Jordan Rose3eb3cd42012-08-03 23:08:54 +0000104 }
105 break;
106 }
107 case PathDiagnosticPiece::Event:
108 case PathDiagnosticPiece::ControlFlow:
Artem Dergachev8b70c4e2016-10-07 15:23:02 +0000109 case PathDiagnosticPiece::Note:
Csaba Dabis1d7ca672019-05-29 19:21:59 +0000110 case PathDiagnosticPiece::PopUp:
Jordan Rose3eb3cd42012-08-03 23:08:54 +0000111 Current.push_back(Piece);
112 break;
113 }
114 }
115}
116
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000117PathDiagnostic::~PathDiagnostic() = default;
Ted Kremenek3116c4e2012-02-08 04:32:27 +0000118
George Karpenkova5ddd3c2018-01-17 02:59:11 +0000119PathDiagnostic::PathDiagnostic(
Kristof Umann72649422019-09-12 19:09:24 +0000120 StringRef CheckerName, const Decl *declWithIssue, StringRef bugtype,
George Karpenkova5ddd3c2018-01-17 02:59:11 +0000121 StringRef verboseDesc, StringRef shortDesc, StringRef category,
122 PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique,
123 std::unique_ptr<FilesToLineNumsMap> ExecutedLines)
Kristof Umann72649422019-09-12 19:09:24 +0000124 : CheckerName(CheckerName), DeclWithIssue(declWithIssue),
George Karpenkova5ddd3c2018-01-17 02:59:11 +0000125 BugType(StripTrailingDots(bugtype)),
126 VerboseDesc(StripTrailingDots(verboseDesc)),
127 ShortDesc(StripTrailingDots(shortDesc)),
128 Category(StripTrailingDots(category)), UniqueingLoc(LocationToUnique),
129 UniqueingDecl(DeclToUnique), ExecutedLines(std::move(ExecutedLines)),
130 path(pathImpl) {}
Ted Kremenek5b9e7b82009-03-06 07:08:50 +0000131
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000132void PathDiagnosticConsumer::anchor() {}
David Blaikie68e081d2011-12-20 02:48:34 +0000133
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000134PathDiagnosticConsumer::~PathDiagnosticConsumer() {
135 // Delete the contents of the FoldingSet if it isn't empty already.
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000136 for (auto &Diag : Diags)
137 delete &Diag;
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000138}
139
David Blaikiec9950cb2014-08-29 20:06:10 +0000140void PathDiagnosticConsumer::HandlePathDiagnostic(
141 std::unique_ptr<PathDiagnostic> D) {
Ted Kremenek0f70a6f2012-02-28 23:27:39 +0000142 if (!D || D->path.empty())
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000143 return;
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000144
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000145 // We need to flatten the locations (convert Stmt* to locations) because
146 // the referenced statements may be freed by the time the diagnostics
147 // are emitted.
148 D->flattenLocations();
149
Ted Kremenek0f70a6f2012-02-28 23:27:39 +0000150 // If the PathDiagnosticConsumer does not support diagnostics that
151 // cross file boundaries, prune out such diagnostics now.
152 if (!supportsCrossFileDiagnostics()) {
153 // Verify that the entire path is from the same FileID.
154 FileID FID;
David Blaikiec9950cb2014-08-29 20:06:10 +0000155 const SourceManager &SMgr = D->path.front()->getLocation().getManager();
Dmitri Gribenkof8579502013-01-12 19:30:44 +0000156 SmallVector<const PathPieces *, 5> WorkList;
Ted Kremenek0f0cc352012-02-29 23:59:20 +0000157 WorkList.push_back(&D->path);
Anton Yartsev0509d042016-10-06 21:42:21 +0000158 SmallString<128> buf;
159 llvm::raw_svector_ostream warning(buf);
160 warning << "warning: Path diagnostic report is not generated. Current "
161 << "output format does not support diagnostics that cross file "
162 << "boundaries. Refer to --analyzer-output for valid output "
163 << "formats\n";
Ted Kremenek0f70a6f2012-02-28 23:27:39 +0000164
Ted Kremenek0f0cc352012-02-29 23:59:20 +0000165 while (!WorkList.empty()) {
Robert Wilhelm25284cc2013-08-23 16:11:15 +0000166 const PathPieces &path = *WorkList.pop_back_val();
Ted Kremenek0f0cc352012-02-29 23:59:20 +0000167
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000168 for (const auto &I : path) {
169 const PathDiagnosticPiece *piece = I.get();
Ted Kremenek0f0cc352012-02-29 23:59:20 +0000170 FullSourceLoc L = piece->getLocation().asLocation().getExpansionLoc();
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000171
Ted Kremenek0f0cc352012-02-29 23:59:20 +0000172 if (FID.isInvalid()) {
173 FID = SMgr.getFileID(L);
Anton Yartsev0509d042016-10-06 21:42:21 +0000174 } else if (SMgr.getFileID(L) != FID) {
175 llvm::errs() << warning.str();
176 return;
177 }
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000178
Ted Kremenek0f0cc352012-02-29 23:59:20 +0000179 // Check the source ranges.
Ted Kremenek1e602732012-08-16 17:45:29 +0000180 ArrayRef<SourceRange> Ranges = piece->getRanges();
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000181 for (const auto &I : Ranges) {
182 SourceLocation L = SMgr.getExpansionLoc(I.getBegin());
Anton Yartsev0509d042016-10-06 21:42:21 +0000183 if (!L.isFileID() || SMgr.getFileID(L) != FID) {
184 llvm::errs() << warning.str();
185 return;
186 }
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000187 L = SMgr.getExpansionLoc(I.getEnd());
Anton Yartsev0509d042016-10-06 21:42:21 +0000188 if (!L.isFileID() || SMgr.getFileID(L) != FID) {
189 llvm::errs() << warning.str();
190 return;
191 }
Ted Kremenek0f0cc352012-02-29 23:59:20 +0000192 }
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000193
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000194 if (const auto *call = dyn_cast<PathDiagnosticCallPiece>(piece))
Ted Kremenek0f0cc352012-02-29 23:59:20 +0000195 WorkList.push_back(&call->path);
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000196 else if (const auto *macro = dyn_cast<PathDiagnosticMacroPiece>(piece))
Ted Kremenek0f0cc352012-02-29 23:59:20 +0000197 WorkList.push_back(&macro->subPieces);
Ted Kremenek0f70a6f2012-02-28 23:27:39 +0000198 }
199 }
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000200
Ted Kremenek0f70a6f2012-02-28 23:27:39 +0000201 if (FID.isInvalid())
202 return; // FIXME: Emit a warning?
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000203 }
Ted Kremenek0f70a6f2012-02-28 23:27:39 +0000204
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000205 // Profile the node to see if we already have something matching it
206 llvm::FoldingSetNodeID profile;
207 D->Profile(profile);
Craig Topper0dbb7832014-05-27 02:45:47 +0000208 void *InsertPos = nullptr;
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000209
210 if (PathDiagnostic *orig = Diags.FindNodeOrInsertPos(profile, InsertPos)) {
211 // Keep the PathDiagnostic with the shorter path.
Anna Zaks4bd96c42012-08-03 18:30:20 +0000212 // Note, the enclosing routine is called in deterministic order, so the
Anna Zaks4c03dfd2012-08-02 23:41:05 +0000213 // results will be consistent between runs (no reason to break ties if the
214 // size is the same).
Ted Kremenek60a78202012-02-24 06:00:00 +0000215 const unsigned orig_size = orig->full_size();
216 const unsigned new_size = D->full_size();
Anna Zaks4c03dfd2012-08-02 23:41:05 +0000217 if (orig_size <= new_size)
218 return;
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000219
David Blaikiec9950cb2014-08-29 20:06:10 +0000220 assert(orig != D.get());
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000221 Diags.RemoveNode(orig);
222 delete orig;
223 }
Ahmed Charles9a16beb2014-03-07 19:33:25 +0000224
David Blaikiec9950cb2014-08-29 20:06:10 +0000225 Diags.InsertNode(D.release());
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000226}
227
David Blaikie05785d12013-02-20 22:23:23 +0000228static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y);
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000229
David Blaikie05785d12013-02-20 22:23:23 +0000230static Optional<bool>
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000231compareControlFlow(const PathDiagnosticControlFlowPiece &X,
232 const PathDiagnosticControlFlowPiece &Y) {
233 FullSourceLoc XSL = X.getStartLocation().asLocation();
234 FullSourceLoc YSL = Y.getStartLocation().asLocation();
235 if (XSL != YSL)
236 return XSL.isBeforeInTranslationUnitThan(YSL);
237 FullSourceLoc XEL = X.getEndLocation().asLocation();
238 FullSourceLoc YEL = Y.getEndLocation().asLocation();
239 if (XEL != YEL)
240 return XEL.isBeforeInTranslationUnitThan(YEL);
David Blaikie7a30dc52013-02-21 01:47:18 +0000241 return None;
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000242}
243
David Blaikie05785d12013-02-20 22:23:23 +0000244static Optional<bool> compareMacro(const PathDiagnosticMacroPiece &X,
245 const PathDiagnosticMacroPiece &Y) {
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000246 return comparePath(X.subPieces, Y.subPieces);
247}
248
David Blaikie05785d12013-02-20 22:23:23 +0000249static Optional<bool> compareCall(const PathDiagnosticCallPiece &X,
250 const PathDiagnosticCallPiece &Y) {
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000251 FullSourceLoc X_CEL = X.callEnter.asLocation();
252 FullSourceLoc Y_CEL = Y.callEnter.asLocation();
253 if (X_CEL != Y_CEL)
254 return X_CEL.isBeforeInTranslationUnitThan(Y_CEL);
255 FullSourceLoc X_CEWL = X.callEnterWithin.asLocation();
256 FullSourceLoc Y_CEWL = Y.callEnterWithin.asLocation();
257 if (X_CEWL != Y_CEWL)
258 return X_CEWL.isBeforeInTranslationUnitThan(Y_CEWL);
259 FullSourceLoc X_CRL = X.callReturn.asLocation();
260 FullSourceLoc Y_CRL = Y.callReturn.asLocation();
261 if (X_CRL != Y_CRL)
262 return X_CRL.isBeforeInTranslationUnitThan(Y_CRL);
263 return comparePath(X.path, Y.path);
264}
265
David Blaikie05785d12013-02-20 22:23:23 +0000266static Optional<bool> comparePiece(const PathDiagnosticPiece &X,
267 const PathDiagnosticPiece &Y) {
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000268 if (X.getKind() != Y.getKind())
269 return X.getKind() < Y.getKind();
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000270
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000271 FullSourceLoc XL = X.getLocation().asLocation();
272 FullSourceLoc YL = Y.getLocation().asLocation();
273 if (XL != YL)
274 return XL.isBeforeInTranslationUnitThan(YL);
275
276 if (X.getString() != Y.getString())
277 return X.getString() < Y.getString();
278
279 if (X.getRanges().size() != Y.getRanges().size())
280 return X.getRanges().size() < Y.getRanges().size();
281
Ted Kremenek54fd0792012-09-10 19:02:33 +0000282 const SourceManager &SM = XL.getManager();
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000283
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000284 for (unsigned i = 0, n = X.getRanges().size(); i < n; ++i) {
285 SourceRange XR = X.getRanges()[i];
286 SourceRange YR = Y.getRanges()[i];
287 if (XR != YR) {
288 if (XR.getBegin() != YR.getBegin())
Ted Kremenek54fd0792012-09-10 19:02:33 +0000289 return SM.isBeforeInTranslationUnit(XR.getBegin(), YR.getBegin());
290 return SM.isBeforeInTranslationUnit(XR.getEnd(), YR.getEnd());
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000291 }
292 }
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000293
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000294 switch (X.getKind()) {
Artem Dergachev8b70c4e2016-10-07 15:23:02 +0000295 case PathDiagnosticPiece::ControlFlow:
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000296 return compareControlFlow(cast<PathDiagnosticControlFlowPiece>(X),
297 cast<PathDiagnosticControlFlowPiece>(Y));
Artem Dergachev8b70c4e2016-10-07 15:23:02 +0000298 case PathDiagnosticPiece::Macro:
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000299 return compareMacro(cast<PathDiagnosticMacroPiece>(X),
300 cast<PathDiagnosticMacroPiece>(Y));
Artem Dergachev8b70c4e2016-10-07 15:23:02 +0000301 case PathDiagnosticPiece::Call:
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000302 return compareCall(cast<PathDiagnosticCallPiece>(X),
303 cast<PathDiagnosticCallPiece>(Y));
Csaba Dabis1d7ca672019-05-29 19:21:59 +0000304 case PathDiagnosticPiece::Event:
305 case PathDiagnosticPiece::Note:
306 case PathDiagnosticPiece::PopUp:
307 return None;
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000308 }
309 llvm_unreachable("all cases handled");
310}
311
David Blaikie05785d12013-02-20 22:23:23 +0000312static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y) {
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000313 if (X.size() != Y.size())
314 return X.size() < Y.size();
Ted Kremenek518e7812013-04-29 22:38:22 +0000315
Ted Kremenekeba09fa2013-04-29 23:12:59 +0000316 PathPieces::const_iterator X_I = X.begin(), X_end = X.end();
317 PathPieces::const_iterator Y_I = Y.begin(), Y_end = Y.end();
Ted Kremenek518e7812013-04-29 22:38:22 +0000318
319 for ( ; X_I != X_end && Y_I != Y_end; ++X_I, ++Y_I) {
Ted Kremenekeba09fa2013-04-29 23:12:59 +0000320 Optional<bool> b = comparePiece(**X_I, **Y_I);
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000321 if (b.hasValue())
322 return b.getValue();
323 }
Ted Kremenek518e7812013-04-29 22:38:22 +0000324
David Blaikie7a30dc52013-02-21 01:47:18 +0000325 return None;
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000326}
327
Ilya Biryukov8b9b3bd2018-03-01 14:54:16 +0000328static bool compareCrossTUSourceLocs(FullSourceLoc XL, FullSourceLoc YL) {
329 std::pair<FileID, unsigned> XOffs = XL.getDecomposedLoc();
330 std::pair<FileID, unsigned> YOffs = YL.getDecomposedLoc();
331 const SourceManager &SM = XL.getManager();
332 std::pair<bool, bool> InSameTU = SM.isInTheSameTranslationUnit(XOffs, YOffs);
333 if (InSameTU.first)
334 return XL.isBeforeInTranslationUnitThan(YL);
Rafael Stahl67676e92018-07-04 14:12:58 +0000335 const FileEntry *XFE = SM.getFileEntryForID(XL.getSpellingLoc().getFileID());
336 const FileEntry *YFE = SM.getFileEntryForID(YL.getSpellingLoc().getFileID());
Ilya Biryukov8b9b3bd2018-03-01 14:54:16 +0000337 if (!XFE || !YFE)
338 return XFE && !YFE;
Rafael Stahl67676e92018-07-04 14:12:58 +0000339 int NameCmp = XFE->getName().compare(YFE->getName());
340 if (NameCmp != 0)
341 return NameCmp == -1;
342 // Last resort: Compare raw file IDs that are possibly expansions.
343 return XL.getFileID() < YL.getFileID();
Ilya Biryukov8b9b3bd2018-03-01 14:54:16 +0000344}
345
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000346static bool compare(const PathDiagnostic &X, const PathDiagnostic &Y) {
347 FullSourceLoc XL = X.getLocation().asLocation();
348 FullSourceLoc YL = Y.getLocation().asLocation();
349 if (XL != YL)
Ilya Biryukov8b9b3bd2018-03-01 14:54:16 +0000350 return compareCrossTUSourceLocs(XL, YL);
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000351 if (X.getBugType() != Y.getBugType())
352 return X.getBugType() < Y.getBugType();
353 if (X.getCategory() != Y.getCategory())
354 return X.getCategory() < Y.getCategory();
355 if (X.getVerboseDescription() != Y.getVerboseDescription())
356 return X.getVerboseDescription() < Y.getVerboseDescription();
357 if (X.getShortDescription() != Y.getShortDescription())
358 return X.getShortDescription() < Y.getShortDescription();
359 if (X.getDeclWithIssue() != Y.getDeclWithIssue()) {
360 const Decl *XD = X.getDeclWithIssue();
361 if (!XD)
362 return true;
363 const Decl *YD = Y.getDeclWithIssue();
364 if (!YD)
365 return false;
366 SourceLocation XDL = XD->getLocation();
367 SourceLocation YDL = YD->getLocation();
Ted Kremeneka0fa5d62012-09-10 19:07:56 +0000368 if (XDL != YDL) {
369 const SourceManager &SM = XL.getManager();
Ilya Biryukov8b9b3bd2018-03-01 14:54:16 +0000370 return compareCrossTUSourceLocs(FullSourceLoc(XDL, SM),
371 FullSourceLoc(YDL, SM));
Ted Kremeneka0fa5d62012-09-10 19:07:56 +0000372 }
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000373 }
374 PathDiagnostic::meta_iterator XI = X.meta_begin(), XE = X.meta_end();
375 PathDiagnostic::meta_iterator YI = Y.meta_begin(), YE = Y.meta_end();
376 if (XE - XI != YE - YI)
377 return (XE - XI) < (YE - YI);
378 for ( ; XI != XE ; ++XI, ++YI) {
379 if (*XI != *YI)
380 return (*XI) < (*YI);
381 }
David Blaikie05785d12013-02-20 22:23:23 +0000382 Optional<bool> b = comparePath(X.path, Y.path);
Ted Kremenek6c7a5ea2012-09-10 14:50:55 +0000383 assert(b.hasValue());
384 return b.getValue();
385}
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000386
Ted Kremenek9bf9af92012-08-16 17:45:23 +0000387void PathDiagnosticConsumer::FlushDiagnostics(
388 PathDiagnosticConsumer::FilesMade *Files) {
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000389 if (flushed)
390 return;
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000391
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000392 flushed = true;
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000393
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000394 std::vector<const PathDiagnostic *> BatchDiags;
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000395 for (const auto &D : Diags)
396 BatchDiags.push_back(&D);
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000397
398 // Sort the diagnostics so that they are always emitted in a deterministic
399 // order.
Benjamin Kramer5caa50e2015-03-14 12:39:22 +0000400 int (*Comp)(const PathDiagnostic *const *, const PathDiagnostic *const *) =
401 [](const PathDiagnostic *const *X, const PathDiagnostic *const *Y) {
402 assert(*X != *Y && "PathDiagnostics not uniqued!");
403 if (compare(**X, **Y))
404 return -1;
405 assert(compare(**Y, **X) && "Not a total order!");
406 return 1;
407 };
408 array_pod_sort(BatchDiags.begin(), BatchDiags.end(), Comp);
Benjamin Kramerbbdd7642014-03-01 14:48:57 +0000409
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000410 FlushDiagnosticsImpl(BatchDiags, Files);
411
412 // Delete the flushed diagnostics.
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000413 for (const auto D : BatchDiags)
Ted Kremenek8e4c4262012-01-25 23:47:14 +0000414 delete D;
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000415
Ted Kremenekb0d1c702012-09-08 04:26:37 +0000416 // Clear out the FoldingSet.
417 Diags.clear();
Ted Kremenek996bfab2011-08-27 21:39:14 +0000418}
419
Chandler Carruth7ff07722014-05-03 10:39:05 +0000420PathDiagnosticConsumer::FilesMade::~FilesMade() {
Benjamin Kramerb474c042015-03-22 18:16:22 +0000421 for (PDFileEntry &Entry : Set)
Chandler Carruth7ff07722014-05-03 10:39:05 +0000422 Entry.~PDFileEntry();
423}
424
Ted Kremenek5bc38ba2012-08-24 19:35:19 +0000425void PathDiagnosticConsumer::FilesMade::addDiagnostic(const PathDiagnostic &PD,
426 StringRef ConsumerName,
427 StringRef FileName) {
428 llvm::FoldingSetNodeID NodeID;
Jordan Rosecc0b1bf2012-08-31 00:36:26 +0000429 NodeID.Add(PD);
Ted Kremenek5bc38ba2012-08-24 19:35:19 +0000430 void *InsertPos;
Benjamin Kramerb474c042015-03-22 18:16:22 +0000431 PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
Ted Kremenek5bc38ba2012-08-24 19:35:19 +0000432 if (!Entry) {
433 Entry = Alloc.Allocate<PDFileEntry>();
434 Entry = new (Entry) PDFileEntry(NodeID);
Benjamin Kramerb474c042015-03-22 18:16:22 +0000435 Set.InsertNode(Entry, InsertPos);
Ted Kremenek5bc38ba2012-08-24 19:35:19 +0000436 }
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000437
Ted Kremenek5bc38ba2012-08-24 19:35:19 +0000438 // Allocate persistent storage for the file name.
439 char *FileName_cstr = (char*) Alloc.Allocate(FileName.size(), 1);
440 memcpy(FileName_cstr, FileName.data(), FileName.size());
441
442 Entry->files.push_back(std::make_pair(ConsumerName,
443 StringRef(FileName_cstr,
444 FileName.size())));
445}
446
447PathDiagnosticConsumer::PDFileEntry::ConsumerFiles *
448PathDiagnosticConsumer::FilesMade::getFiles(const PathDiagnostic &PD) {
449 llvm::FoldingSetNodeID NodeID;
Jordan Rosecc0b1bf2012-08-31 00:36:26 +0000450 NodeID.Add(PD);
Ted Kremenek5bc38ba2012-08-24 19:35:19 +0000451 void *InsertPos;
Benjamin Kramerb474c042015-03-22 18:16:22 +0000452 PDFileEntry *Entry = Set.FindNodeOrInsertPos(NodeID, InsertPos);
Ted Kremenek5bc38ba2012-08-24 19:35:19 +0000453 if (!Entry)
Craig Topper0dbb7832014-05-27 02:45:47 +0000454 return nullptr;
Ted Kremenek5bc38ba2012-08-24 19:35:19 +0000455 return &Entry->files;
456}
457
Ted Kremenekbade06e2009-03-26 21:39:39 +0000458//===----------------------------------------------------------------------===//
459// PathDiagnosticLocation methods.
460//===----------------------------------------------------------------------===//
461
Artem Dergachev6b85f8e2019-09-11 20:54:21 +0000462SourceLocation PathDiagnosticLocation::getValidSourceLocation(
463 const Stmt *S, LocationOrAnalysisDeclContext LAC, bool UseEndOfStatement) {
464 SourceLocation L = UseEndOfStatement ? S->getEndLoc() : S->getBeginLoc();
465 assert(!LAC.isNull() &&
466 "A valid LocationContext or AnalysisDeclContext should be passed to "
467 "PathDiagnosticLocation upon creation.");
Anna Zaksefd182d2011-09-16 19:18:30 +0000468
469 // S might be a temporary statement that does not have a location in the
Jordan Rosea4c0d212012-07-26 20:04:05 +0000470 // source code, so find an enclosing statement and use its location.
Anna Zaksde03d722011-09-20 16:37:36 +0000471 if (!L.isValid()) {
Jordan Rose25bc20f2012-07-26 20:04:30 +0000472 AnalysisDeclContext *ADC;
Anna Zaks83128bc2011-09-20 18:23:52 +0000473 if (LAC.is<const LocationContext*>())
Jordan Rose25bc20f2012-07-26 20:04:30 +0000474 ADC = LAC.get<const LocationContext*>()->getAnalysisDeclContext();
Anna Zaks83128bc2011-09-20 18:23:52 +0000475 else
Jordan Rose25bc20f2012-07-26 20:04:30 +0000476 ADC = LAC.get<AnalysisDeclContext*>();
Anna Zaksde03d722011-09-20 16:37:36 +0000477
Jordan Rose25bc20f2012-07-26 20:04:30 +0000478 ParentMap &PM = ADC->getParentMap();
479
480 const Stmt *Parent = S;
481 do {
482 Parent = PM.getParent(Parent);
483
484 // In rare cases, we have implicit top-level expressions,
485 // such as arguments for implicit member initializers.
486 // In this case, fall back to the start of the body (even if we were
487 // asked for the statement end location).
488 if (!Parent) {
489 const Stmt *Body = ADC->getBody();
490 if (Body)
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000491 L = Body->getBeginLoc();
Jordan Rose25bc20f2012-07-26 20:04:30 +0000492 else
Stephen Kelly1c301dc2018-08-09 21:09:38 +0000493 L = ADC->getDecl()->getEndLoc();
Jordan Rose25bc20f2012-07-26 20:04:30 +0000494 break;
495 }
496
Artem Dergachev6b85f8e2019-09-11 20:54:21 +0000497 L = UseEndOfStatement ? Parent->getEndLoc() : Parent->getBeginLoc();
Jordan Rose25bc20f2012-07-26 20:04:30 +0000498 } while (!L.isValid());
Anna Zaksefd182d2011-09-16 19:18:30 +0000499 }
500
Kristof Umann49628162019-03-14 16:10:29 +0000501 // FIXME: Ironically, this assert actually fails in some cases.
502 //assert(L.isValid());
Anna Zaksefd182d2011-09-16 19:18:30 +0000503 return L;
504}
505
Jordan Rose80880ac2012-08-03 23:08:44 +0000506static PathDiagnosticLocation
507getLocationForCaller(const StackFrameContext *SFC,
508 const LocationContext *CallerCtx,
509 const SourceManager &SM) {
510 const CFGBlock &Block = *SFC->getCallSiteBlock();
511 CFGElement Source = Block[SFC->getIndex()];
512
513 switch (Source.getKind()) {
Jordan Rose80880ac2012-08-03 23:08:44 +0000514 case CFGElement::Statement:
Artem Dergachev41ffb302018-02-08 22:58:15 +0000515 case CFGElement::Constructor:
Artem Dergachev1527dec2018-03-12 23:12:40 +0000516 case CFGElement::CXXRecordTypedCall:
David Blaikie2a01f5d2013-02-21 20:58:29 +0000517 return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(),
Jordan Rose80880ac2012-08-03 23:08:44 +0000518 SM, CallerCtx);
519 case CFGElement::Initializer: {
David Blaikie2a01f5d2013-02-21 20:58:29 +0000520 const CFGInitializer &Init = Source.castAs<CFGInitializer>();
Jordan Rose80880ac2012-08-03 23:08:44 +0000521 return PathDiagnosticLocation(Init.getInitializer()->getInit(),
522 SM, CallerCtx);
523 }
524 case CFGElement::AutomaticObjectDtor: {
David Blaikie2a01f5d2013-02-21 20:58:29 +0000525 const CFGAutomaticObjDtor &Dtor = Source.castAs<CFGAutomaticObjDtor>();
Jordan Rose80880ac2012-08-03 23:08:44 +0000526 return PathDiagnosticLocation::createEnd(Dtor.getTriggerStmt(),
527 SM, CallerCtx);
528 }
Jordan Rosed2f40792013-09-03 17:00:57 +0000529 case CFGElement::DeleteDtor: {
Jordan Rose1417a7b2013-10-31 18:41:15 +0000530 const CFGDeleteDtor &Dtor = Source.castAs<CFGDeleteDtor>();
531 return PathDiagnosticLocation(Dtor.getDeleteExpr(), SM, CallerCtx);
Jordan Rosed2f40792013-09-03 17:00:57 +0000532 }
Jordan Rose80880ac2012-08-03 23:08:44 +0000533 case CFGElement::BaseDtor:
534 case CFGElement::MemberDtor: {
535 const AnalysisDeclContext *CallerInfo = CallerCtx->getAnalysisDeclContext();
536 if (const Stmt *CallerBody = CallerInfo->getBody())
537 return PathDiagnosticLocation::createEnd(CallerBody, SM, CallerCtx);
538 return PathDiagnosticLocation::create(CallerInfo->getDecl(), SM);
539 }
Artem Dergacheve769fb72018-01-18 00:10:21 +0000540 case CFGElement::NewAllocator: {
541 const CFGNewAllocator &Alloc = Source.castAs<CFGNewAllocator>();
542 return PathDiagnosticLocation(Alloc.getAllocatorExpr(), SM, CallerCtx);
543 }
Artem Dergachev60f5aab2018-02-15 19:28:21 +0000544 case CFGElement::TemporaryDtor: {
545 // Temporary destructors are for temporaries. They die immediately at around
546 // the location of CXXBindTemporaryExpr. If they are lifetime-extended,
547 // they'd be dealt with via an AutomaticObjectDtor instead.
548 const auto &Dtor = Source.castAs<CFGTemporaryDtor>();
549 return PathDiagnosticLocation::createEnd(Dtor.getBindTemporaryExpr(), SM,
550 CallerCtx);
551 }
Maxim Ostapenkodebca452018-03-12 12:26:15 +0000552 case CFGElement::ScopeBegin:
553 case CFGElement::ScopeEnd:
554 llvm_unreachable("not yet implemented!");
Peter Szecsi999a25f2017-08-19 11:19:16 +0000555 case CFGElement::LifetimeEnds:
556 case CFGElement::LoopExit:
557 llvm_unreachable("CFGElement kind should not be on callsite!");
Jordan Rose80880ac2012-08-03 23:08:44 +0000558 }
559
560 llvm_unreachable("Unknown CFGElement kind");
561}
562
Anna Zaksefd182d2011-09-16 19:18:30 +0000563PathDiagnosticLocation
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000564PathDiagnosticLocation::createBegin(const Decl *D,
565 const SourceManager &SM) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000566 return PathDiagnosticLocation(D->getBeginLoc(), SM, SingleLocK);
Anna Zaksc29bed32011-09-20 21:38:35 +0000567}
568
569PathDiagnosticLocation
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000570PathDiagnosticLocation::createBegin(const Stmt *S,
571 const SourceManager &SM,
572 LocationOrAnalysisDeclContext LAC) {
Anna Zaks83128bc2011-09-20 18:23:52 +0000573 return PathDiagnosticLocation(getValidSourceLocation(S, LAC),
Anna Zaks745486a2011-09-20 01:51:40 +0000574 SM, SingleLocK);
Anna Zaksefd182d2011-09-16 19:18:30 +0000575}
576
Jordan Rosea4c0d212012-07-26 20:04:05 +0000577PathDiagnosticLocation
578PathDiagnosticLocation::createEnd(const Stmt *S,
579 const SourceManager &SM,
580 LocationOrAnalysisDeclContext LAC) {
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000581 if (const auto *CS = dyn_cast<CompoundStmt>(S))
Jordan Rosea4c0d212012-07-26 20:04:05 +0000582 return createEndBrace(CS, SM);
583 return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true),
584 SM, SingleLocK);
585}
586
Anna Zaksefd182d2011-09-16 19:18:30 +0000587PathDiagnosticLocation
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000588PathDiagnosticLocation::createOperatorLoc(const BinaryOperator *BO,
589 const SourceManager &SM) {
Anna Zaksefd182d2011-09-16 19:18:30 +0000590 return PathDiagnosticLocation(BO->getOperatorLoc(), SM, SingleLocK);
591}
592
593PathDiagnosticLocation
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000594PathDiagnosticLocation::createConditionalColonLoc(
Jordan Rose60bd88d2013-12-10 18:18:06 +0000595 const ConditionalOperator *CO,
596 const SourceManager &SM) {
597 return PathDiagnosticLocation(CO->getColonLoc(), SM, SingleLocK);
598}
599
Jordan Rose60bd88d2013-12-10 18:18:06 +0000600PathDiagnosticLocation
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000601PathDiagnosticLocation::createMemberLoc(const MemberExpr *ME,
602 const SourceManager &SM) {
Kristof Umann49628162019-03-14 16:10:29 +0000603
604 assert(ME->getMemberLoc().isValid() || ME->getBeginLoc().isValid());
605
606 // In some cases, getMemberLoc isn't valid -- in this case we'll return with
607 // some other related valid SourceLocation.
608 if (ME->getMemberLoc().isValid())
609 return PathDiagnosticLocation(ME->getMemberLoc(), SM, SingleLocK);
610
611 return PathDiagnosticLocation(ME->getBeginLoc(), SM, SingleLocK);
Anna Zaksc29bed32011-09-20 21:38:35 +0000612}
613
614PathDiagnosticLocation
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000615PathDiagnosticLocation::createBeginBrace(const CompoundStmt *CS,
616 const SourceManager &SM) {
Anna Zaksefd182d2011-09-16 19:18:30 +0000617 SourceLocation L = CS->getLBracLoc();
618 return PathDiagnosticLocation(L, SM, SingleLocK);
619}
620
621PathDiagnosticLocation
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000622PathDiagnosticLocation::createEndBrace(const CompoundStmt *CS,
623 const SourceManager &SM) {
Anna Zaksefd182d2011-09-16 19:18:30 +0000624 SourceLocation L = CS->getRBracLoc();
625 return PathDiagnosticLocation(L, SM, SingleLocK);
626}
627
628PathDiagnosticLocation
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000629PathDiagnosticLocation::createDeclBegin(const LocationContext *LC,
630 const SourceManager &SM) {
Anna Zaksefd182d2011-09-16 19:18:30 +0000631 // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000632 if (const auto *CS = dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
Anna Zaksefd182d2011-09-16 19:18:30 +0000633 if (!CS->body_empty()) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000634 SourceLocation Loc = (*CS->body_begin())->getBeginLoc();
Anna Zaksefd182d2011-09-16 19:18:30 +0000635 return PathDiagnosticLocation(Loc, SM, SingleLocK);
636 }
637
638 return PathDiagnosticLocation();
639}
640
641PathDiagnosticLocation
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000642PathDiagnosticLocation::createDeclEnd(const LocationContext *LC,
643 const SourceManager &SM) {
Anna Zaks921f0492011-09-15 18:56:07 +0000644 SourceLocation L = LC->getDecl()->getBodyRBrace();
Anna Zaksefd182d2011-09-16 19:18:30 +0000645 return PathDiagnosticLocation(L, SM, SingleLocK);
Anna Zaks921f0492011-09-15 18:56:07 +0000646}
647
Anna Zaksde8c5ed2011-09-20 01:38:47 +0000648PathDiagnosticLocation
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000649PathDiagnosticLocation::create(const ProgramPoint& P,
650 const SourceManager &SMng) {
Craig Topper0dbb7832014-05-27 02:45:47 +0000651 const Stmt* S = nullptr;
David Blaikie87396b92013-02-21 22:23:56 +0000652 if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
Anna Zaks921f0492011-09-15 18:56:07 +0000653 const CFGBlock *BSrc = BE->getSrc();
Artem Dergachevef0aab32019-05-24 23:37:11 +0000654 if (BSrc->getTerminator().isVirtualBaseBranch()) {
655 // TODO: VirtualBaseBranches should also appear for destructors.
656 // In this case we should put the diagnostic at the end of decl.
657 return PathDiagnosticLocation::createBegin(
658 P.getLocationContext()->getDecl(), SMng);
659
660 } else {
661 S = BSrc->getTerminatorCondition();
Adam Balogh9ed4b312019-05-28 13:07:09 +0000662 if (!S) {
663 // If the BlockEdge has no terminator condition statement but its
664 // source is the entry of the CFG (e.g. a checker crated the branch at
665 // the beginning of a function), use the function's declaration instead.
666 assert(BSrc == &BSrc->getParent()->getEntry() && "CFGBlock has no "
667 "TerminatorCondition and is not the enrty block of the CFG");
668 return PathDiagnosticLocation::createBegin(
669 P.getLocationContext()->getDecl(), SMng);
670 }
Artem Dergachevef0aab32019-05-24 23:37:11 +0000671 }
David Blaikie87396b92013-02-21 22:23:56 +0000672 } else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) {
Jordan Roseec44ac62012-10-29 17:31:59 +0000673 S = SP->getStmt();
David Blaikie87396b92013-02-21 22:23:56 +0000674 if (P.getAs<PostStmtPurgeDeadSymbols>())
Jordan Rosee37ab502012-11-15 19:11:43 +0000675 return PathDiagnosticLocation::createEnd(S, SMng, P.getLocationContext());
Anna Zaksece622a2013-04-05 00:59:33 +0000676 } else if (Optional<PostInitializer> PIP = P.getAs<PostInitializer>()) {
677 return PathDiagnosticLocation(PIP->getInitializer()->getSourceLocation(),
678 SMng);
Artem Dergachevfc720072019-01-10 23:44:44 +0000679 } else if (Optional<PreImplicitCall> PIC = P.getAs<PreImplicitCall>()) {
680 return PathDiagnosticLocation(PIC->getLocation(), SMng);
David Blaikie87396b92013-02-21 22:23:56 +0000681 } else if (Optional<PostImplicitCall> PIE = P.getAs<PostImplicitCall>()) {
Jordan Rose80880ac2012-08-03 23:08:44 +0000682 return PathDiagnosticLocation(PIE->getLocation(), SMng);
David Blaikie87396b92013-02-21 22:23:56 +0000683 } else if (Optional<CallEnter> CE = P.getAs<CallEnter>()) {
Jordan Rose80880ac2012-08-03 23:08:44 +0000684 return getLocationForCaller(CE->getCalleeContext(),
685 CE->getLocationContext(),
686 SMng);
David Blaikie87396b92013-02-21 22:23:56 +0000687 } else if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) {
Jordan Rose80880ac2012-08-03 23:08:44 +0000688 return getLocationForCaller(CEE->getCalleeContext(),
689 CEE->getLocationContext(),
690 SMng);
George Karpenkov2c2d0b62019-01-18 19:24:55 +0000691 } else if (auto CEB = P.getAs<CallExitBegin>()) {
692 if (const ReturnStmt *RS = CEB->getReturnStmt())
693 return PathDiagnosticLocation::createBegin(RS, SMng,
694 CEB->getLocationContext());
695 return PathDiagnosticLocation(
696 CEB->getLocationContext()->getDecl()->getSourceRange().getEnd(), SMng);
Devin Coughlin9a2c14a2017-11-29 18:25:37 +0000697 } else if (Optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) {
Kristof Umannb8ac93c2019-09-18 22:24:26 +0000698 if (Optional<CFGElement> BlockFront = BE->getFirstElement()) {
699 if (auto StmtElt = BlockFront->getAs<CFGStmt>()) {
700 return PathDiagnosticLocation(StmtElt->getStmt()->getBeginLoc(), SMng);
701 } else if (auto NewAllocElt = BlockFront->getAs<CFGNewAllocator>()) {
702 return PathDiagnosticLocation(
703 NewAllocElt->getAllocatorExpr()->getBeginLoc(), SMng);
704 }
705 llvm_unreachable("Unexpected CFG element at front of block");
Devin Coughlin9a2c14a2017-11-29 18:25:37 +0000706 }
Kristof Umannb8ac93c2019-09-18 22:24:26 +0000707
708 return PathDiagnosticLocation(
709 BE->getBlock()->getTerminatorStmt()->getBeginLoc(), SMng);
Csaba Dabis57835bc2019-07-04 00:50:50 +0000710 } else if (Optional<FunctionExitPoint> FE = P.getAs<FunctionExitPoint>()) {
711 return PathDiagnosticLocation(FE->getStmt(), SMng,
712 FE->getLocationContext());
David Blaikie87396b92013-02-21 22:23:56 +0000713 } else {
Jordan Roseec44ac62012-10-29 17:31:59 +0000714 llvm_unreachable("Unexpected ProgramPoint");
715 }
Anna Zaks921f0492011-09-15 18:56:07 +0000716
Anna Zaksde8c5ed2011-09-20 01:38:47 +0000717 return PathDiagnosticLocation(S, SMng, P.getLocationContext());
Anna Zaks921f0492011-09-15 18:56:07 +0000718}
719
Anna Zaksde8c5ed2011-09-20 01:38:47 +0000720PathDiagnosticLocation PathDiagnosticLocation::createSingleLocation(
721 const PathDiagnosticLocation &PDL) {
722 FullSourceLoc L = PDL.asLocation();
723 return PathDiagnosticLocation(L, L.getManager(), SingleLocK);
724}
725
Anna Zaks745486a2011-09-20 01:51:40 +0000726FullSourceLoc
Anna Zaks15ca5e72011-09-21 00:35:58 +0000727 PathDiagnosticLocation::genLocation(SourceLocation L,
Ted Kremenek81ce1c82011-10-24 01:32:45 +0000728 LocationOrAnalysisDeclContext LAC) const {
Ted Kremenek0bb09092009-04-01 06:13:56 +0000729 assert(isValid());
Ted Kremenekc2511652009-03-26 21:42:51 +0000730 // Note that we want a 'switch' here so that the compiler can warn us in
731 // case we add more cases.
Ted Kremenekbade06e2009-03-26 21:39:39 +0000732 switch (K) {
Ted Kremenek92820d22009-04-06 22:33:35 +0000733 case SingleLocK:
734 case RangeK:
Ted Kremenek7c36d902009-03-26 21:42:00 +0000735 break;
Ted Kremenek92820d22009-04-06 22:33:35 +0000736 case StmtK:
Ted Kremenekc07e34c2012-01-10 15:26:13 +0000737 // Defensive checking.
738 if (!S)
739 break;
Anna Zaks83128bc2011-09-20 18:23:52 +0000740 return FullSourceLoc(getValidSourceLocation(S, LAC),
Anna Zaks615e3a62011-09-14 17:48:01 +0000741 const_cast<SourceManager&>(*SM));
Ted Kremenek92820d22009-04-06 22:33:35 +0000742 case DeclK:
Ted Kremenekc07e34c2012-01-10 15:26:13 +0000743 // Defensive checking.
744 if (!D)
745 break;
Ted Kremenek92820d22009-04-06 22:33:35 +0000746 return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
Ted Kremenekbade06e2009-03-26 21:39:39 +0000747 }
Mike Stump11289f42009-09-09 15:08:12 +0000748
Anna Zaksd70da082011-09-20 23:27:32 +0000749 return FullSourceLoc(L, const_cast<SourceManager&>(*SM));
Ted Kremenekbade06e2009-03-26 21:39:39 +0000750}
Ted Kremenek96110d52009-03-26 21:48:17 +0000751
Anna Zaks745486a2011-09-20 01:51:40 +0000752PathDiagnosticRange
Ted Kremenek81ce1c82011-10-24 01:32:45 +0000753 PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const {
Ted Kremenek0bb09092009-04-01 06:13:56 +0000754 assert(isValid());
Ted Kremenek96110d52009-03-26 21:48:17 +0000755 // Note that we want a 'switch' here so that the compiler can warn us in
756 // case we add more cases.
757 switch (K) {
Ted Kremenek92820d22009-04-06 22:33:35 +0000758 case SingleLocK:
Anna Zaks15ca5e72011-09-21 00:35:58 +0000759 return PathDiagnosticRange(SourceRange(Loc,Loc), true);
Ted Kremenek92820d22009-04-06 22:33:35 +0000760 case RangeK:
Ted Kremenek96110d52009-03-26 21:48:17 +0000761 break;
Ted Kremenek22579c42009-04-22 18:03:00 +0000762 case StmtK: {
763 const Stmt *S = asStmt();
764 switch (S->getStmtClass()) {
765 default:
766 break;
Ted Kremenek18665fe2009-05-15 02:05:25 +0000767 case Stmt::DeclStmtClass: {
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000768 const auto *DS = cast<DeclStmt>(S);
Ted Kremenek18665fe2009-05-15 02:05:25 +0000769 if (DS->isSingleDecl()) {
770 // Should always be the case, but we'll be defensive.
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000771 return SourceRange(DS->getBeginLoc(),
Mike Stump11289f42009-09-09 15:08:12 +0000772 DS->getSingleDecl()->getLocation());
Ted Kremenek18665fe2009-05-15 02:05:25 +0000773 }
774 break;
775 }
Ted Kremenek22579c42009-04-22 18:03:00 +0000776 // FIXME: Provide better range information for different
777 // terminators.
778 case Stmt::IfStmtClass:
779 case Stmt::WhileStmtClass:
780 case Stmt::DoStmtClass:
781 case Stmt::ForStmtClass:
782 case Stmt::ChooseExprClass:
783 case Stmt::IndirectGotoStmtClass:
784 case Stmt::SwitchStmtClass:
John McCallc07a0c72011-02-17 10:25:35 +0000785 case Stmt::BinaryConditionalOperatorClass:
Ted Kremenek22579c42009-04-22 18:03:00 +0000786 case Stmt::ConditionalOperatorClass:
787 case Stmt::ObjCForCollectionStmtClass: {
Anna Zaks83128bc2011-09-20 18:23:52 +0000788 SourceLocation L = getValidSourceLocation(S, LAC);
Ted Kremenek22579c42009-04-22 18:03:00 +0000789 return SourceRange(L, L);
790 }
791 }
Anna Zaks15ca5e72011-09-21 00:35:58 +0000792 SourceRange R = S->getSourceRange();
793 if (R.isValid())
794 return R;
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000795 break;
Ted Kremenek22579c42009-04-22 18:03:00 +0000796 }
Ted Kremenek92820d22009-04-06 22:33:35 +0000797 case DeclK:
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000798 if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
Ted Kremenek92820d22009-04-06 22:33:35 +0000799 return MD->getSourceRange();
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000800 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
Argyrios Kyrtzidis0b6a06a2010-07-07 12:24:14 +0000801 if (Stmt *Body = FD->getBody())
802 return Body->getSourceRange();
Douglas Gregore3dcb2d2009-04-18 00:02:19 +0000803 }
Ted Kremenek92820d22009-04-06 22:33:35 +0000804 else {
805 SourceLocation L = D->getLocation();
Ted Kremenek63e29cc2009-04-22 22:26:10 +0000806 return PathDiagnosticRange(SourceRange(L, L), true);
Ted Kremenek92820d22009-04-06 22:33:35 +0000807 }
Ted Kremenek96110d52009-03-26 21:48:17 +0000808 }
Mike Stump11289f42009-09-09 15:08:12 +0000809
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000810 return SourceRange(Loc, Loc);
Ted Kremenek96110d52009-03-26 21:48:17 +0000811}
812
Ted Kremenek92820d22009-04-06 22:33:35 +0000813void PathDiagnosticLocation::flatten() {
814 if (K == StmtK) {
Ted Kremenek92820d22009-04-06 22:33:35 +0000815 K = RangeK;
Craig Topper0dbb7832014-05-27 02:45:47 +0000816 S = nullptr;
817 D = nullptr;
Ted Kremenek92820d22009-04-06 22:33:35 +0000818 }
819 else if (K == DeclK) {
Ted Kremenek92820d22009-04-06 22:33:35 +0000820 K = SingleLocK;
Craig Topper0dbb7832014-05-27 02:45:47 +0000821 S = nullptr;
822 D = nullptr;
Ted Kremenek92820d22009-04-06 22:33:35 +0000823 }
824}
825
Ted Kremenek60a78202012-02-24 06:00:00 +0000826//===----------------------------------------------------------------------===//
827// Manipulation of PathDiagnosticCallPieces.
828//===----------------------------------------------------------------------===//
829
David Blaikie0a0c2752017-01-05 17:26:53 +0000830std::shared_ptr<PathDiagnosticCallPiece>
George Karpenkovc82d4572018-09-28 18:49:41 +0000831PathDiagnosticCallPiece::construct(const CallExitEnd &CE,
Ted Kremenek60a78202012-02-24 06:00:00 +0000832 const SourceManager &SM) {
Anna Zaks7e53bd62012-04-20 21:59:08 +0000833 const Decl *caller = CE.getLocationContext()->getDecl();
Jordan Rosea4c0d212012-07-26 20:04:05 +0000834 PathDiagnosticLocation pos = getLocationForCaller(CE.getCalleeContext(),
835 CE.getLocationContext(),
836 SM);
David Blaikie0a0c2752017-01-05 17:26:53 +0000837 return std::shared_ptr<PathDiagnosticCallPiece>(
838 new PathDiagnosticCallPiece(caller, pos));
Ted Kremenek60a78202012-02-24 06:00:00 +0000839}
840
841PathDiagnosticCallPiece *
Anna Zaksd4e90592012-03-14 18:58:28 +0000842PathDiagnosticCallPiece::construct(PathPieces &path,
843 const Decl *caller) {
David Blaikie0a0c2752017-01-05 17:26:53 +0000844 std::shared_ptr<PathDiagnosticCallPiece> C(
845 new PathDiagnosticCallPiece(path, caller));
Ted Kremenek60a78202012-02-24 06:00:00 +0000846 path.clear();
David Blaikie0a0c2752017-01-05 17:26:53 +0000847 auto *R = C.get();
848 path.push_front(std::move(C));
849 return R;
Ted Kremenek60a78202012-02-24 06:00:00 +0000850}
851
852void PathDiagnosticCallPiece::setCallee(const CallEnter &CE,
853 const SourceManager &SM) {
Jordan Rosea4c0d212012-07-26 20:04:05 +0000854 const StackFrameContext *CalleeCtx = CE.getCalleeContext();
855 Callee = CalleeCtx->getDecl();
856
857 callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM);
858 callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
Artem Dergachevfbe891ee2017-06-05 12:40:03 +0000859
860 // Autosynthesized property accessors are special because we'd never
861 // pop back up to non-autosynthesized code until we leave them.
862 // This is not generally true for autosynthesized callees, which may call
863 // non-autosynthesized callbacks.
864 // Unless set here, the IsCalleeAnAutosynthesizedPropertyAccessor flag
865 // defaults to false.
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000866 if (const auto *MD = dyn_cast<ObjCMethodDecl>(Callee))
Artem Dergachevfbe891ee2017-06-05 12:40:03 +0000867 IsCalleeAnAutosynthesizedPropertyAccessor = (
868 MD->isPropertyAccessor() &&
869 CalleeCtx->getAnalysisDeclContext()->isBodyAutosynthesized());
Ted Kremenek60a78202012-02-24 06:00:00 +0000870}
871
Kristof Umann3ea74422018-05-25 13:18:38 +0000872static void describeTemplateParameters(raw_ostream &Out,
873 const ArrayRef<TemplateArgument> TAList,
874 const LangOptions &LO,
875 StringRef Prefix = StringRef(),
876 StringRef Postfix = StringRef());
877
878static void describeTemplateParameter(raw_ostream &Out,
879 const TemplateArgument &TArg,
880 const LangOptions &LO) {
881
882 if (TArg.getKind() == TemplateArgument::ArgKind::Pack) {
883 describeTemplateParameters(Out, TArg.getPackAsArray(), LO);
884 } else {
885 TArg.print(PrintingPolicy(LO), Out);
886 }
887}
888
889static void describeTemplateParameters(raw_ostream &Out,
890 const ArrayRef<TemplateArgument> TAList,
891 const LangOptions &LO,
892 StringRef Prefix, StringRef Postfix) {
893 if (TAList.empty())
894 return;
895
896 Out << Prefix;
897 for (int I = 0, Last = TAList.size() - 1; I != Last; ++I) {
898 describeTemplateParameter(Out, TAList[I], LO);
899 Out << ", ";
900 }
901 describeTemplateParameter(Out, TAList[TAList.size() - 1], LO);
902 Out << Postfix;
903}
904
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000905static void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
906 StringRef Prefix = StringRef()) {
Jordan Rose1dc39402013-01-18 18:27:21 +0000907 if (!D->getIdentifier())
908 return;
Kristof Umann3ea74422018-05-25 13:18:38 +0000909 Out << Prefix << '\'' << *D;
910 if (const auto T = dyn_cast<ClassTemplateSpecializationDecl>(D))
911 describeTemplateParameters(Out, T->getTemplateArgs().asArray(),
912 D->getASTContext().getLangOpts(), "<", ">");
913
914 Out << '\'';
Jordan Rose1dc39402013-01-18 18:27:21 +0000915}
916
Jordan Rosefe856d52013-01-18 18:27:14 +0000917static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
Jordan Rose1dc39402013-01-18 18:27:21 +0000918 bool ExtendedDescription,
Jordan Rosefe856d52013-01-18 18:27:14 +0000919 StringRef Prefix = StringRef()) {
920 if (!D)
921 return false;
922
923 if (isa<BlockDecl>(D)) {
Jordan Rose1dc39402013-01-18 18:27:21 +0000924 if (ExtendedDescription)
Jordan Rosefe856d52013-01-18 18:27:14 +0000925 Out << Prefix << "anonymous block";
Jordan Rose1dc39402013-01-18 18:27:21 +0000926 return ExtendedDescription;
Jordan Rosefe856d52013-01-18 18:27:14 +0000927 }
928
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000929 if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
Jordan Rose1dc39402013-01-18 18:27:21 +0000930 Out << Prefix;
931 if (ExtendedDescription && !MD->isUserProvided()) {
932 if (MD->isExplicitlyDefaulted())
933 Out << "defaulted ";
934 else
935 Out << "implicit ";
936 }
937
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000938 if (const auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
Jordan Rose1dc39402013-01-18 18:27:21 +0000939 if (CD->isDefaultConstructor())
940 Out << "default ";
941 else if (CD->isCopyConstructor())
942 Out << "copy ";
943 else if (CD->isMoveConstructor())
944 Out << "move ";
945
946 Out << "constructor";
947 describeClass(Out, MD->getParent(), " for ");
Jordan Rose1dc39402013-01-18 18:27:21 +0000948 } else if (isa<CXXDestructorDecl>(MD)) {
949 if (!MD->isUserProvided()) {
950 Out << "destructor";
951 describeClass(Out, MD->getParent(), " for ");
952 } else {
953 // Use ~Foo for explicitly-written destructors.
954 Out << "'" << *MD << "'";
955 }
Jordan Rose1dc39402013-01-18 18:27:21 +0000956 } else if (MD->isCopyAssignmentOperator()) {
957 Out << "copy assignment operator";
958 describeClass(Out, MD->getParent(), " for ");
Jordan Rose1dc39402013-01-18 18:27:21 +0000959 } else if (MD->isMoveAssignmentOperator()) {
960 Out << "move assignment operator";
961 describeClass(Out, MD->getParent(), " for ");
Jordan Rose1dc39402013-01-18 18:27:21 +0000962 } else {
963 if (MD->getParent()->getIdentifier())
964 Out << "'" << *MD->getParent() << "::" << *MD << "'";
965 else
966 Out << "'" << *MD << "'";
967 }
Jordan Rosefe856d52013-01-18 18:27:14 +0000968
969 return true;
970 }
971
Kristof Umann3ea74422018-05-25 13:18:38 +0000972 Out << Prefix << '\'' << cast<NamedDecl>(*D);
973
974 // Adding template parameters.
975 if (const auto FD = dyn_cast<FunctionDecl>(D))
976 if (const TemplateArgumentList *TAList =
977 FD->getTemplateSpecializationArgs())
978 describeTemplateParameters(Out, TAList->asArray(),
979 FD->getASTContext().getLangOpts(), "<", ">");
980
981 Out << '\'';
Jordan Rosefe856d52013-01-18 18:27:14 +0000982 return true;
983}
984
David Blaikie0a0c2752017-01-05 17:26:53 +0000985std::shared_ptr<PathDiagnosticEventPiece>
Ted Kremenek60a78202012-02-24 06:00:00 +0000986PathDiagnosticCallPiece::getCallEnterEvent() const {
Artem Dergachevfbe891ee2017-06-05 12:40:03 +0000987 // We do not produce call enters and call exits for autosynthesized property
988 // accessors. We do generally produce them for other functions coming from
989 // the body farm because they may call callbacks that bring us back into
990 // visible code.
991 if (!Callee || IsCalleeAnAutosynthesizedPropertyAccessor)
Craig Topper0dbb7832014-05-27 02:45:47 +0000992 return nullptr;
Jordan Rosefe856d52013-01-18 18:27:14 +0000993
Ted Kremenek60a78202012-02-24 06:00:00 +0000994 SmallString<256> buf;
995 llvm::raw_svector_ostream Out(buf);
Jordan Rosefe856d52013-01-18 18:27:14 +0000996
997 Out << "Calling ";
Jordan Rose1dc39402013-01-18 18:27:21 +0000998 describeCodeDecl(Out, Callee, /*ExtendedDescription=*/true);
Jordan Rosefe856d52013-01-18 18:27:14 +0000999
Jordan Rose2d98b972012-11-15 02:07:23 +00001000 assert(callEnter.asLocation().isValid());
David Blaikie0a0c2752017-01-05 17:26:53 +00001001 return std::make_shared<PathDiagnosticEventPiece>(callEnter, Out.str());
Ted Kremenek60a78202012-02-24 06:00:00 +00001002}
1003
David Blaikie0a0c2752017-01-05 17:26:53 +00001004std::shared_ptr<PathDiagnosticEventPiece>
Ted Kremenek04e860d2012-03-06 01:25:01 +00001005PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const {
Jordan Rose2d98b972012-11-15 02:07:23 +00001006 if (!callEnterWithin.asLocation().isValid())
Craig Topper0dbb7832014-05-27 02:45:47 +00001007 return nullptr;
Jordan Rose56138262013-05-24 21:43:11 +00001008 if (Callee->isImplicit() || !Callee->hasBody())
Craig Topper0dbb7832014-05-27 02:45:47 +00001009 return nullptr;
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001010 if (const auto *MD = dyn_cast<CXXMethodDecl>(Callee))
Jordan Rosed8876a72013-01-19 19:52:57 +00001011 if (MD->isDefaulted())
Craig Topper0dbb7832014-05-27 02:45:47 +00001012 return nullptr;
Jordan Rosefe856d52013-01-18 18:27:14 +00001013
Ted Kremenek04e860d2012-03-06 01:25:01 +00001014 SmallString<256> buf;
1015 llvm::raw_svector_ostream Out(buf);
Jordan Rosefe856d52013-01-18 18:27:14 +00001016
1017 Out << "Entered call";
Jordan Rose1dc39402013-01-18 18:27:21 +00001018 describeCodeDecl(Out, Caller, /*ExtendedDescription=*/false, " from ");
Jordan Rosefe856d52013-01-18 18:27:14 +00001019
David Blaikie0a0c2752017-01-05 17:26:53 +00001020 return std::make_shared<PathDiagnosticEventPiece>(callEnterWithin, Out.str());
Ted Kremenek04e860d2012-03-06 01:25:01 +00001021}
1022
David Blaikie0a0c2752017-01-05 17:26:53 +00001023std::shared_ptr<PathDiagnosticEventPiece>
Ted Kremenek60a78202012-02-24 06:00:00 +00001024PathDiagnosticCallPiece::getCallExitEvent() const {
Artem Dergachevfbe891ee2017-06-05 12:40:03 +00001025 // We do not produce call enters and call exits for autosynthesized property
1026 // accessors. We do generally produce them for other functions coming from
1027 // the body farm because they may call callbacks that bring us back into
1028 // visible code.
1029 if (NoExit || IsCalleeAnAutosynthesizedPropertyAccessor)
Craig Topper0dbb7832014-05-27 02:45:47 +00001030 return nullptr;
Jordan Rosefe856d52013-01-18 18:27:14 +00001031
Ted Kremenek60a78202012-02-24 06:00:00 +00001032 SmallString<256> buf;
1033 llvm::raw_svector_ostream Out(buf);
Jordan Rosefe856d52013-01-18 18:27:14 +00001034
1035 if (!CallStackMessage.empty()) {
Anna Zaksa7f457a2012-03-16 23:44:28 +00001036 Out << CallStackMessage;
Jordan Rosefe856d52013-01-18 18:27:14 +00001037 } else {
Jordan Rose1dc39402013-01-18 18:27:21 +00001038 bool DidDescribe = describeCodeDecl(Out, Callee,
1039 /*ExtendedDescription=*/false,
Jordan Rosefe856d52013-01-18 18:27:14 +00001040 "Returning from ");
1041 if (!DidDescribe)
1042 Out << "Returning to caller";
1043 }
1044
Jordan Rose2d98b972012-11-15 02:07:23 +00001045 assert(callReturn.asLocation().isValid());
David Blaikie0a0c2752017-01-05 17:26:53 +00001046 return std::make_shared<PathDiagnosticEventPiece>(callReturn, Out.str());
Ted Kremenek60a78202012-02-24 06:00:00 +00001047}
1048
1049static void compute_path_size(const PathPieces &pieces, unsigned &size) {
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001050 for (const auto &I : pieces) {
1051 const PathDiagnosticPiece *piece = I.get();
1052 if (const auto *cp = dyn_cast<PathDiagnosticCallPiece>(piece))
Ted Kremenek60a78202012-02-24 06:00:00 +00001053 compute_path_size(cp->path, size);
Ted Kremenek60a78202012-02-24 06:00:00 +00001054 else
1055 ++size;
1056 }
1057}
1058
1059unsigned PathDiagnostic::full_size() {
1060 unsigned size = 0;
1061 compute_path_size(path, size);
1062 return size;
1063}
1064
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001065//===----------------------------------------------------------------------===//
1066// FoldingSet profiling methods.
1067//===----------------------------------------------------------------------===//
Ted Kremenek92820d22009-04-06 22:33:35 +00001068
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001069void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
Anna Zaksb2dfc2b2011-09-20 21:25:00 +00001070 ID.AddInteger(Range.getBegin().getRawEncoding());
1071 ID.AddInteger(Range.getEnd().getRawEncoding());
1072 ID.AddInteger(Loc.getRawEncoding());
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001073}
1074
1075void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1076 ID.AddInteger((unsigned) getKind());
1077 ID.AddString(str);
1078 // FIXME: Add profiling support for code hints.
1079 ID.AddInteger((unsigned) getDisplayHint());
Ted Kremenek1e602732012-08-16 17:45:29 +00001080 ArrayRef<SourceRange> Ranges = getRanges();
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001081 for (const auto &I : Ranges) {
1082 ID.AddInteger(I.getBegin().getRawEncoding());
1083 ID.AddInteger(I.getEnd().getRawEncoding());
Ted Kremenek3a0678e2015-09-08 03:50:52 +00001084 }
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001085}
1086
Ted Kremenek60a78202012-02-24 06:00:00 +00001087void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1088 PathDiagnosticPiece::Profile(ID);
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001089 for (const auto &I : path)
1090 ID.Add(*I);
Ted Kremenek60a78202012-02-24 06:00:00 +00001091}
1092
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001093void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1094 PathDiagnosticPiece::Profile(ID);
1095 ID.Add(Pos);
1096}
1097
1098void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1099 PathDiagnosticPiece::Profile(ID);
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001100 for (const auto &I : *this)
1101 ID.Add(I);
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001102}
1103
1104void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1105 PathDiagnosticSpotPiece::Profile(ID);
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001106 for (const auto &I : subPieces)
1107 ID.Add(*I);
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001108}
1109
Artem Dergachev8b70c4e2016-10-07 15:23:02 +00001110void PathDiagnosticNotePiece::Profile(llvm::FoldingSetNodeID &ID) const {
1111 PathDiagnosticSpotPiece::Profile(ID);
1112}
1113
Csaba Dabis1d7ca672019-05-29 19:21:59 +00001114void PathDiagnosticPopUpPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1115 PathDiagnosticSpotPiece::Profile(ID);
1116}
1117
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001118void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
Jordan Rosecc0b1bf2012-08-31 00:36:26 +00001119 ID.Add(getLocation());
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001120 ID.AddString(BugType);
Jordan Rosecc0b1bf2012-08-31 00:36:26 +00001121 ID.AddString(VerboseDesc);
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001122 ID.AddString(Category);
Ted Kremenek8e4c4262012-01-25 23:47:14 +00001123}
1124
1125void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const {
1126 Profile(ID);
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001127 for (const auto &I : path)
1128 ID.Add(*I);
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001129 for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
1130 ID.AddString(*I);
1131}
Anna Zakscba4f292012-03-16 23:24:20 +00001132
George Karpenkov1cf8cdc2018-06-12 20:51:01 +00001133LLVM_DUMP_METHOD void PathPieces::dump() const {
1134 unsigned index = 0;
1135 for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
1136 llvm::errs() << "[" << index++ << "] ";
1137 (*I)->dump();
1138 llvm::errs() << "\n";
1139 }
1140}
1141
1142LLVM_DUMP_METHOD void PathDiagnosticCallPiece::dump() const {
1143 llvm::errs() << "CALL\n--------------\n";
1144
1145 if (const Stmt *SLoc = getLocation().getStmtOrNull())
1146 SLoc->dump();
1147 else if (const auto *ND = dyn_cast_or_null<NamedDecl>(getCallee()))
1148 llvm::errs() << *ND << "\n";
1149 else
1150 getLocation().dump();
1151}
1152
1153LLVM_DUMP_METHOD void PathDiagnosticEventPiece::dump() const {
1154 llvm::errs() << "EVENT\n--------------\n";
1155 llvm::errs() << getString() << "\n";
1156 llvm::errs() << " ---- at ----\n";
1157 getLocation().dump();
1158}
1159
1160LLVM_DUMP_METHOD void PathDiagnosticControlFlowPiece::dump() const {
1161 llvm::errs() << "CONTROL\n--------------\n";
1162 getStartLocation().dump();
1163 llvm::errs() << " ---- to ----\n";
1164 getEndLocation().dump();
1165}
1166
1167LLVM_DUMP_METHOD void PathDiagnosticMacroPiece::dump() const {
1168 llvm::errs() << "MACRO\n--------------\n";
1169 // FIXME: Print which macro is being invoked.
1170}
1171
1172LLVM_DUMP_METHOD void PathDiagnosticNotePiece::dump() const {
1173 llvm::errs() << "NOTE\n--------------\n";
1174 llvm::errs() << getString() << "\n";
1175 llvm::errs() << " ---- at ----\n";
1176 getLocation().dump();
1177}
1178
Csaba Dabis1d7ca672019-05-29 19:21:59 +00001179LLVM_DUMP_METHOD void PathDiagnosticPopUpPiece::dump() const {
1180 llvm::errs() << "POP-UP\n--------------\n";
1181 llvm::errs() << getString() << "\n";
1182 llvm::errs() << " ---- at ----\n";
1183 getLocation().dump();
1184}
1185
George Karpenkov1cf8cdc2018-06-12 20:51:01 +00001186LLVM_DUMP_METHOD void PathDiagnosticLocation::dump() const {
1187 if (!isValid()) {
1188 llvm::errs() << "<INVALID>\n";
1189 return;
1190 }
1191
1192 switch (K) {
1193 case RangeK:
1194 // FIXME: actually print the range.
1195 llvm::errs() << "<range>\n";
1196 break;
1197 case SingleLocK:
1198 asLocation().dump();
1199 llvm::errs() << "\n";
1200 break;
1201 case StmtK:
1202 if (S)
1203 S->dump();
1204 else
1205 llvm::errs() << "<NULL STMT>\n";
1206 break;
1207 case DeclK:
1208 if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
1209 llvm::errs() << *ND << "\n";
1210 else if (isa<BlockDecl>(D))
1211 // FIXME: Make this nicer.
1212 llvm::errs() << "<block>\n";
1213 else if (D)
1214 llvm::errs() << "<unknown decl>\n";
1215 else
1216 llvm::errs() << "<NULL DECL>\n";
1217 break;
1218 }
1219}