blob: 764cb8ed0e4f87100d0d0954a6ec736e02b93963 [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>()) {
698 CFGElement BlockFront = BE->getBlock()->front();
699 if (auto StmtElt = BlockFront.getAs<CFGStmt>()) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000700 return PathDiagnosticLocation(StmtElt->getStmt()->getBeginLoc(), SMng);
Devin Coughlin9a2c14a2017-11-29 18:25:37 +0000701 } else if (auto NewAllocElt = BlockFront.getAs<CFGNewAllocator>()) {
702 return PathDiagnosticLocation(
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000703 NewAllocElt->getAllocatorExpr()->getBeginLoc(), SMng);
Devin Coughlin9a2c14a2017-11-29 18:25:37 +0000704 }
705 llvm_unreachable("Unexpected CFG element at front of block");
Csaba Dabis57835bc2019-07-04 00:50:50 +0000706 } else if (Optional<FunctionExitPoint> FE = P.getAs<FunctionExitPoint>()) {
707 return PathDiagnosticLocation(FE->getStmt(), SMng,
708 FE->getLocationContext());
David Blaikie87396b92013-02-21 22:23:56 +0000709 } else {
Jordan Roseec44ac62012-10-29 17:31:59 +0000710 llvm_unreachable("Unexpected ProgramPoint");
711 }
Anna Zaks921f0492011-09-15 18:56:07 +0000712
Anna Zaksde8c5ed2011-09-20 01:38:47 +0000713 return PathDiagnosticLocation(S, SMng, P.getLocationContext());
Anna Zaks921f0492011-09-15 18:56:07 +0000714}
715
Anna Zaksde8c5ed2011-09-20 01:38:47 +0000716PathDiagnosticLocation PathDiagnosticLocation::createSingleLocation(
717 const PathDiagnosticLocation &PDL) {
718 FullSourceLoc L = PDL.asLocation();
719 return PathDiagnosticLocation(L, L.getManager(), SingleLocK);
720}
721
Anna Zaks745486a2011-09-20 01:51:40 +0000722FullSourceLoc
Anna Zaks15ca5e72011-09-21 00:35:58 +0000723 PathDiagnosticLocation::genLocation(SourceLocation L,
Ted Kremenek81ce1c82011-10-24 01:32:45 +0000724 LocationOrAnalysisDeclContext LAC) const {
Ted Kremenek0bb09092009-04-01 06:13:56 +0000725 assert(isValid());
Ted Kremenekc2511652009-03-26 21:42:51 +0000726 // Note that we want a 'switch' here so that the compiler can warn us in
727 // case we add more cases.
Ted Kremenekbade06e2009-03-26 21:39:39 +0000728 switch (K) {
Ted Kremenek92820d22009-04-06 22:33:35 +0000729 case SingleLocK:
730 case RangeK:
Ted Kremenek7c36d902009-03-26 21:42:00 +0000731 break;
Ted Kremenek92820d22009-04-06 22:33:35 +0000732 case StmtK:
Ted Kremenekc07e34c2012-01-10 15:26:13 +0000733 // Defensive checking.
734 if (!S)
735 break;
Anna Zaks83128bc2011-09-20 18:23:52 +0000736 return FullSourceLoc(getValidSourceLocation(S, LAC),
Anna Zaks615e3a62011-09-14 17:48:01 +0000737 const_cast<SourceManager&>(*SM));
Ted Kremenek92820d22009-04-06 22:33:35 +0000738 case DeclK:
Ted Kremenekc07e34c2012-01-10 15:26:13 +0000739 // Defensive checking.
740 if (!D)
741 break;
Ted Kremenek92820d22009-04-06 22:33:35 +0000742 return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
Ted Kremenekbade06e2009-03-26 21:39:39 +0000743 }
Mike Stump11289f42009-09-09 15:08:12 +0000744
Anna Zaksd70da082011-09-20 23:27:32 +0000745 return FullSourceLoc(L, const_cast<SourceManager&>(*SM));
Ted Kremenekbade06e2009-03-26 21:39:39 +0000746}
Ted Kremenek96110d52009-03-26 21:48:17 +0000747
Anna Zaks745486a2011-09-20 01:51:40 +0000748PathDiagnosticRange
Ted Kremenek81ce1c82011-10-24 01:32:45 +0000749 PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const {
Ted Kremenek0bb09092009-04-01 06:13:56 +0000750 assert(isValid());
Ted Kremenek96110d52009-03-26 21:48:17 +0000751 // Note that we want a 'switch' here so that the compiler can warn us in
752 // case we add more cases.
753 switch (K) {
Ted Kremenek92820d22009-04-06 22:33:35 +0000754 case SingleLocK:
Anna Zaks15ca5e72011-09-21 00:35:58 +0000755 return PathDiagnosticRange(SourceRange(Loc,Loc), true);
Ted Kremenek92820d22009-04-06 22:33:35 +0000756 case RangeK:
Ted Kremenek96110d52009-03-26 21:48:17 +0000757 break;
Ted Kremenek22579c42009-04-22 18:03:00 +0000758 case StmtK: {
759 const Stmt *S = asStmt();
760 switch (S->getStmtClass()) {
761 default:
762 break;
Ted Kremenek18665fe2009-05-15 02:05:25 +0000763 case Stmt::DeclStmtClass: {
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000764 const auto *DS = cast<DeclStmt>(S);
Ted Kremenek18665fe2009-05-15 02:05:25 +0000765 if (DS->isSingleDecl()) {
766 // Should always be the case, but we'll be defensive.
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000767 return SourceRange(DS->getBeginLoc(),
Mike Stump11289f42009-09-09 15:08:12 +0000768 DS->getSingleDecl()->getLocation());
Ted Kremenek18665fe2009-05-15 02:05:25 +0000769 }
770 break;
771 }
Ted Kremenek22579c42009-04-22 18:03:00 +0000772 // FIXME: Provide better range information for different
773 // terminators.
774 case Stmt::IfStmtClass:
775 case Stmt::WhileStmtClass:
776 case Stmt::DoStmtClass:
777 case Stmt::ForStmtClass:
778 case Stmt::ChooseExprClass:
779 case Stmt::IndirectGotoStmtClass:
780 case Stmt::SwitchStmtClass:
John McCallc07a0c72011-02-17 10:25:35 +0000781 case Stmt::BinaryConditionalOperatorClass:
Ted Kremenek22579c42009-04-22 18:03:00 +0000782 case Stmt::ConditionalOperatorClass:
783 case Stmt::ObjCForCollectionStmtClass: {
Anna Zaks83128bc2011-09-20 18:23:52 +0000784 SourceLocation L = getValidSourceLocation(S, LAC);
Ted Kremenek22579c42009-04-22 18:03:00 +0000785 return SourceRange(L, L);
786 }
787 }
Anna Zaks15ca5e72011-09-21 00:35:58 +0000788 SourceRange R = S->getSourceRange();
789 if (R.isValid())
790 return R;
Ted Kremenek3a0678e2015-09-08 03:50:52 +0000791 break;
Ted Kremenek22579c42009-04-22 18:03:00 +0000792 }
Ted Kremenek92820d22009-04-06 22:33:35 +0000793 case DeclK:
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000794 if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
Ted Kremenek92820d22009-04-06 22:33:35 +0000795 return MD->getSourceRange();
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000796 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
Argyrios Kyrtzidis0b6a06a2010-07-07 12:24:14 +0000797 if (Stmt *Body = FD->getBody())
798 return Body->getSourceRange();
Douglas Gregore3dcb2d2009-04-18 00:02:19 +0000799 }
Ted Kremenek92820d22009-04-06 22:33:35 +0000800 else {
801 SourceLocation L = D->getLocation();
Ted Kremenek63e29cc2009-04-22 22:26:10 +0000802 return PathDiagnosticRange(SourceRange(L, L), true);
Ted Kremenek92820d22009-04-06 22:33:35 +0000803 }
Ted Kremenek96110d52009-03-26 21:48:17 +0000804 }
Mike Stump11289f42009-09-09 15:08:12 +0000805
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000806 return SourceRange(Loc, Loc);
Ted Kremenek96110d52009-03-26 21:48:17 +0000807}
808
Ted Kremenek92820d22009-04-06 22:33:35 +0000809void PathDiagnosticLocation::flatten() {
810 if (K == StmtK) {
Ted Kremenek92820d22009-04-06 22:33:35 +0000811 K = RangeK;
Craig Topper0dbb7832014-05-27 02:45:47 +0000812 S = nullptr;
813 D = nullptr;
Ted Kremenek92820d22009-04-06 22:33:35 +0000814 }
815 else if (K == DeclK) {
Ted Kremenek92820d22009-04-06 22:33:35 +0000816 K = SingleLocK;
Craig Topper0dbb7832014-05-27 02:45:47 +0000817 S = nullptr;
818 D = nullptr;
Ted Kremenek92820d22009-04-06 22:33:35 +0000819 }
820}
821
Ted Kremenek60a78202012-02-24 06:00:00 +0000822//===----------------------------------------------------------------------===//
823// Manipulation of PathDiagnosticCallPieces.
824//===----------------------------------------------------------------------===//
825
David Blaikie0a0c2752017-01-05 17:26:53 +0000826std::shared_ptr<PathDiagnosticCallPiece>
George Karpenkovc82d4572018-09-28 18:49:41 +0000827PathDiagnosticCallPiece::construct(const CallExitEnd &CE,
Ted Kremenek60a78202012-02-24 06:00:00 +0000828 const SourceManager &SM) {
Anna Zaks7e53bd62012-04-20 21:59:08 +0000829 const Decl *caller = CE.getLocationContext()->getDecl();
Jordan Rosea4c0d212012-07-26 20:04:05 +0000830 PathDiagnosticLocation pos = getLocationForCaller(CE.getCalleeContext(),
831 CE.getLocationContext(),
832 SM);
David Blaikie0a0c2752017-01-05 17:26:53 +0000833 return std::shared_ptr<PathDiagnosticCallPiece>(
834 new PathDiagnosticCallPiece(caller, pos));
Ted Kremenek60a78202012-02-24 06:00:00 +0000835}
836
837PathDiagnosticCallPiece *
Anna Zaksd4e90592012-03-14 18:58:28 +0000838PathDiagnosticCallPiece::construct(PathPieces &path,
839 const Decl *caller) {
David Blaikie0a0c2752017-01-05 17:26:53 +0000840 std::shared_ptr<PathDiagnosticCallPiece> C(
841 new PathDiagnosticCallPiece(path, caller));
Ted Kremenek60a78202012-02-24 06:00:00 +0000842 path.clear();
David Blaikie0a0c2752017-01-05 17:26:53 +0000843 auto *R = C.get();
844 path.push_front(std::move(C));
845 return R;
Ted Kremenek60a78202012-02-24 06:00:00 +0000846}
847
848void PathDiagnosticCallPiece::setCallee(const CallEnter &CE,
849 const SourceManager &SM) {
Jordan Rosea4c0d212012-07-26 20:04:05 +0000850 const StackFrameContext *CalleeCtx = CE.getCalleeContext();
851 Callee = CalleeCtx->getDecl();
852
853 callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM);
854 callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
Artem Dergachevfbe891ee2017-06-05 12:40:03 +0000855
856 // Autosynthesized property accessors are special because we'd never
857 // pop back up to non-autosynthesized code until we leave them.
858 // This is not generally true for autosynthesized callees, which may call
859 // non-autosynthesized callbacks.
860 // Unless set here, the IsCalleeAnAutosynthesizedPropertyAccessor flag
861 // defaults to false.
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000862 if (const auto *MD = dyn_cast<ObjCMethodDecl>(Callee))
Artem Dergachevfbe891ee2017-06-05 12:40:03 +0000863 IsCalleeAnAutosynthesizedPropertyAccessor = (
864 MD->isPropertyAccessor() &&
865 CalleeCtx->getAnalysisDeclContext()->isBodyAutosynthesized());
Ted Kremenek60a78202012-02-24 06:00:00 +0000866}
867
Kristof Umann3ea74422018-05-25 13:18:38 +0000868static void describeTemplateParameters(raw_ostream &Out,
869 const ArrayRef<TemplateArgument> TAList,
870 const LangOptions &LO,
871 StringRef Prefix = StringRef(),
872 StringRef Postfix = StringRef());
873
874static void describeTemplateParameter(raw_ostream &Out,
875 const TemplateArgument &TArg,
876 const LangOptions &LO) {
877
878 if (TArg.getKind() == TemplateArgument::ArgKind::Pack) {
879 describeTemplateParameters(Out, TArg.getPackAsArray(), LO);
880 } else {
881 TArg.print(PrintingPolicy(LO), Out);
882 }
883}
884
885static void describeTemplateParameters(raw_ostream &Out,
886 const ArrayRef<TemplateArgument> TAList,
887 const LangOptions &LO,
888 StringRef Prefix, StringRef Postfix) {
889 if (TAList.empty())
890 return;
891
892 Out << Prefix;
893 for (int I = 0, Last = TAList.size() - 1; I != Last; ++I) {
894 describeTemplateParameter(Out, TAList[I], LO);
895 Out << ", ";
896 }
897 describeTemplateParameter(Out, TAList[TAList.size() - 1], LO);
898 Out << Postfix;
899}
900
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000901static void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
902 StringRef Prefix = StringRef()) {
Jordan Rose1dc39402013-01-18 18:27:21 +0000903 if (!D->getIdentifier())
904 return;
Kristof Umann3ea74422018-05-25 13:18:38 +0000905 Out << Prefix << '\'' << *D;
906 if (const auto T = dyn_cast<ClassTemplateSpecializationDecl>(D))
907 describeTemplateParameters(Out, T->getTemplateArgs().asArray(),
908 D->getASTContext().getLangOpts(), "<", ">");
909
910 Out << '\'';
Jordan Rose1dc39402013-01-18 18:27:21 +0000911}
912
Jordan Rosefe856d52013-01-18 18:27:14 +0000913static bool describeCodeDecl(raw_ostream &Out, const Decl *D,
Jordan Rose1dc39402013-01-18 18:27:21 +0000914 bool ExtendedDescription,
Jordan Rosefe856d52013-01-18 18:27:14 +0000915 StringRef Prefix = StringRef()) {
916 if (!D)
917 return false;
918
919 if (isa<BlockDecl>(D)) {
Jordan Rose1dc39402013-01-18 18:27:21 +0000920 if (ExtendedDescription)
Jordan Rosefe856d52013-01-18 18:27:14 +0000921 Out << Prefix << "anonymous block";
Jordan Rose1dc39402013-01-18 18:27:21 +0000922 return ExtendedDescription;
Jordan Rosefe856d52013-01-18 18:27:14 +0000923 }
924
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000925 if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
Jordan Rose1dc39402013-01-18 18:27:21 +0000926 Out << Prefix;
927 if (ExtendedDescription && !MD->isUserProvided()) {
928 if (MD->isExplicitlyDefaulted())
929 Out << "defaulted ";
930 else
931 Out << "implicit ";
932 }
933
Eugene Zelenko9f103a12018-03-08 22:45:13 +0000934 if (const auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
Jordan Rose1dc39402013-01-18 18:27:21 +0000935 if (CD->isDefaultConstructor())
936 Out << "default ";
937 else if (CD->isCopyConstructor())
938 Out << "copy ";
939 else if (CD->isMoveConstructor())
940 Out << "move ";
941
942 Out << "constructor";
943 describeClass(Out, MD->getParent(), " for ");
Jordan Rose1dc39402013-01-18 18:27:21 +0000944 } else if (isa<CXXDestructorDecl>(MD)) {
945 if (!MD->isUserProvided()) {
946 Out << "destructor";
947 describeClass(Out, MD->getParent(), " for ");
948 } else {
949 // Use ~Foo for explicitly-written destructors.
950 Out << "'" << *MD << "'";
951 }
Jordan Rose1dc39402013-01-18 18:27:21 +0000952 } else if (MD->isCopyAssignmentOperator()) {
953 Out << "copy assignment operator";
954 describeClass(Out, MD->getParent(), " for ");
Jordan Rose1dc39402013-01-18 18:27:21 +0000955 } else if (MD->isMoveAssignmentOperator()) {
956 Out << "move assignment operator";
957 describeClass(Out, MD->getParent(), " for ");
Jordan Rose1dc39402013-01-18 18:27:21 +0000958 } else {
959 if (MD->getParent()->getIdentifier())
960 Out << "'" << *MD->getParent() << "::" << *MD << "'";
961 else
962 Out << "'" << *MD << "'";
963 }
Jordan Rosefe856d52013-01-18 18:27:14 +0000964
965 return true;
966 }
967
Kristof Umann3ea74422018-05-25 13:18:38 +0000968 Out << Prefix << '\'' << cast<NamedDecl>(*D);
969
970 // Adding template parameters.
971 if (const auto FD = dyn_cast<FunctionDecl>(D))
972 if (const TemplateArgumentList *TAList =
973 FD->getTemplateSpecializationArgs())
974 describeTemplateParameters(Out, TAList->asArray(),
975 FD->getASTContext().getLangOpts(), "<", ">");
976
977 Out << '\'';
Jordan Rosefe856d52013-01-18 18:27:14 +0000978 return true;
979}
980
David Blaikie0a0c2752017-01-05 17:26:53 +0000981std::shared_ptr<PathDiagnosticEventPiece>
Ted Kremenek60a78202012-02-24 06:00:00 +0000982PathDiagnosticCallPiece::getCallEnterEvent() const {
Artem Dergachevfbe891ee2017-06-05 12:40:03 +0000983 // We do not produce call enters and call exits for autosynthesized property
984 // accessors. We do generally produce them for other functions coming from
985 // the body farm because they may call callbacks that bring us back into
986 // visible code.
987 if (!Callee || IsCalleeAnAutosynthesizedPropertyAccessor)
Craig Topper0dbb7832014-05-27 02:45:47 +0000988 return nullptr;
Jordan Rosefe856d52013-01-18 18:27:14 +0000989
Ted Kremenek60a78202012-02-24 06:00:00 +0000990 SmallString<256> buf;
991 llvm::raw_svector_ostream Out(buf);
Jordan Rosefe856d52013-01-18 18:27:14 +0000992
993 Out << "Calling ";
Jordan Rose1dc39402013-01-18 18:27:21 +0000994 describeCodeDecl(Out, Callee, /*ExtendedDescription=*/true);
Jordan Rosefe856d52013-01-18 18:27:14 +0000995
Jordan Rose2d98b972012-11-15 02:07:23 +0000996 assert(callEnter.asLocation().isValid());
David Blaikie0a0c2752017-01-05 17:26:53 +0000997 return std::make_shared<PathDiagnosticEventPiece>(callEnter, Out.str());
Ted Kremenek60a78202012-02-24 06:00:00 +0000998}
999
David Blaikie0a0c2752017-01-05 17:26:53 +00001000std::shared_ptr<PathDiagnosticEventPiece>
Ted Kremenek04e860d2012-03-06 01:25:01 +00001001PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const {
Jordan Rose2d98b972012-11-15 02:07:23 +00001002 if (!callEnterWithin.asLocation().isValid())
Craig Topper0dbb7832014-05-27 02:45:47 +00001003 return nullptr;
Jordan Rose56138262013-05-24 21:43:11 +00001004 if (Callee->isImplicit() || !Callee->hasBody())
Craig Topper0dbb7832014-05-27 02:45:47 +00001005 return nullptr;
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001006 if (const auto *MD = dyn_cast<CXXMethodDecl>(Callee))
Jordan Rosed8876a72013-01-19 19:52:57 +00001007 if (MD->isDefaulted())
Craig Topper0dbb7832014-05-27 02:45:47 +00001008 return nullptr;
Jordan Rosefe856d52013-01-18 18:27:14 +00001009
Ted Kremenek04e860d2012-03-06 01:25:01 +00001010 SmallString<256> buf;
1011 llvm::raw_svector_ostream Out(buf);
Jordan Rosefe856d52013-01-18 18:27:14 +00001012
1013 Out << "Entered call";
Jordan Rose1dc39402013-01-18 18:27:21 +00001014 describeCodeDecl(Out, Caller, /*ExtendedDescription=*/false, " from ");
Jordan Rosefe856d52013-01-18 18:27:14 +00001015
David Blaikie0a0c2752017-01-05 17:26:53 +00001016 return std::make_shared<PathDiagnosticEventPiece>(callEnterWithin, Out.str());
Ted Kremenek04e860d2012-03-06 01:25:01 +00001017}
1018
David Blaikie0a0c2752017-01-05 17:26:53 +00001019std::shared_ptr<PathDiagnosticEventPiece>
Ted Kremenek60a78202012-02-24 06:00:00 +00001020PathDiagnosticCallPiece::getCallExitEvent() const {
Artem Dergachevfbe891ee2017-06-05 12:40:03 +00001021 // We do not produce call enters and call exits for autosynthesized property
1022 // accessors. We do generally produce them for other functions coming from
1023 // the body farm because they may call callbacks that bring us back into
1024 // visible code.
1025 if (NoExit || IsCalleeAnAutosynthesizedPropertyAccessor)
Craig Topper0dbb7832014-05-27 02:45:47 +00001026 return nullptr;
Jordan Rosefe856d52013-01-18 18:27:14 +00001027
Ted Kremenek60a78202012-02-24 06:00:00 +00001028 SmallString<256> buf;
1029 llvm::raw_svector_ostream Out(buf);
Jordan Rosefe856d52013-01-18 18:27:14 +00001030
1031 if (!CallStackMessage.empty()) {
Anna Zaksa7f457a2012-03-16 23:44:28 +00001032 Out << CallStackMessage;
Jordan Rosefe856d52013-01-18 18:27:14 +00001033 } else {
Jordan Rose1dc39402013-01-18 18:27:21 +00001034 bool DidDescribe = describeCodeDecl(Out, Callee,
1035 /*ExtendedDescription=*/false,
Jordan Rosefe856d52013-01-18 18:27:14 +00001036 "Returning from ");
1037 if (!DidDescribe)
1038 Out << "Returning to caller";
1039 }
1040
Jordan Rose2d98b972012-11-15 02:07:23 +00001041 assert(callReturn.asLocation().isValid());
David Blaikie0a0c2752017-01-05 17:26:53 +00001042 return std::make_shared<PathDiagnosticEventPiece>(callReturn, Out.str());
Ted Kremenek60a78202012-02-24 06:00:00 +00001043}
1044
1045static void compute_path_size(const PathPieces &pieces, unsigned &size) {
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001046 for (const auto &I : pieces) {
1047 const PathDiagnosticPiece *piece = I.get();
1048 if (const auto *cp = dyn_cast<PathDiagnosticCallPiece>(piece))
Ted Kremenek60a78202012-02-24 06:00:00 +00001049 compute_path_size(cp->path, size);
Ted Kremenek60a78202012-02-24 06:00:00 +00001050 else
1051 ++size;
1052 }
1053}
1054
1055unsigned PathDiagnostic::full_size() {
1056 unsigned size = 0;
1057 compute_path_size(path, size);
1058 return size;
1059}
1060
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001061//===----------------------------------------------------------------------===//
1062// FoldingSet profiling methods.
1063//===----------------------------------------------------------------------===//
Ted Kremenek92820d22009-04-06 22:33:35 +00001064
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001065void PathDiagnosticLocation::Profile(llvm::FoldingSetNodeID &ID) const {
Anna Zaksb2dfc2b2011-09-20 21:25:00 +00001066 ID.AddInteger(Range.getBegin().getRawEncoding());
1067 ID.AddInteger(Range.getEnd().getRawEncoding());
1068 ID.AddInteger(Loc.getRawEncoding());
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001069}
1070
1071void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1072 ID.AddInteger((unsigned) getKind());
1073 ID.AddString(str);
1074 // FIXME: Add profiling support for code hints.
1075 ID.AddInteger((unsigned) getDisplayHint());
Ted Kremenek1e602732012-08-16 17:45:29 +00001076 ArrayRef<SourceRange> Ranges = getRanges();
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001077 for (const auto &I : Ranges) {
1078 ID.AddInteger(I.getBegin().getRawEncoding());
1079 ID.AddInteger(I.getEnd().getRawEncoding());
Ted Kremenek3a0678e2015-09-08 03:50:52 +00001080 }
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001081}
1082
Ted Kremenek60a78202012-02-24 06:00:00 +00001083void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1084 PathDiagnosticPiece::Profile(ID);
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001085 for (const auto &I : path)
1086 ID.Add(*I);
Ted Kremenek60a78202012-02-24 06:00:00 +00001087}
1088
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001089void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1090 PathDiagnosticPiece::Profile(ID);
1091 ID.Add(Pos);
1092}
1093
1094void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1095 PathDiagnosticPiece::Profile(ID);
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001096 for (const auto &I : *this)
1097 ID.Add(I);
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001098}
1099
1100void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1101 PathDiagnosticSpotPiece::Profile(ID);
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001102 for (const auto &I : subPieces)
1103 ID.Add(*I);
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001104}
1105
Artem Dergachev8b70c4e2016-10-07 15:23:02 +00001106void PathDiagnosticNotePiece::Profile(llvm::FoldingSetNodeID &ID) const {
1107 PathDiagnosticSpotPiece::Profile(ID);
1108}
1109
Csaba Dabis1d7ca672019-05-29 19:21:59 +00001110void PathDiagnosticPopUpPiece::Profile(llvm::FoldingSetNodeID &ID) const {
1111 PathDiagnosticSpotPiece::Profile(ID);
1112}
1113
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001114void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const {
Jordan Rosecc0b1bf2012-08-31 00:36:26 +00001115 ID.Add(getLocation());
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001116 ID.AddString(BugType);
Jordan Rosecc0b1bf2012-08-31 00:36:26 +00001117 ID.AddString(VerboseDesc);
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001118 ID.AddString(Category);
Ted Kremenek8e4c4262012-01-25 23:47:14 +00001119}
1120
1121void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const {
1122 Profile(ID);
Eugene Zelenko9f103a12018-03-08 22:45:13 +00001123 for (const auto &I : path)
1124 ID.Add(*I);
Ted Kremenek3d8f8622009-09-18 22:33:39 +00001125 for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I)
1126 ID.AddString(*I);
1127}
Anna Zakscba4f292012-03-16 23:24:20 +00001128
George Karpenkov1cf8cdc2018-06-12 20:51:01 +00001129LLVM_DUMP_METHOD void PathPieces::dump() const {
1130 unsigned index = 0;
1131 for (PathPieces::const_iterator I = begin(), E = end(); I != E; ++I) {
1132 llvm::errs() << "[" << index++ << "] ";
1133 (*I)->dump();
1134 llvm::errs() << "\n";
1135 }
1136}
1137
1138LLVM_DUMP_METHOD void PathDiagnosticCallPiece::dump() const {
1139 llvm::errs() << "CALL\n--------------\n";
1140
1141 if (const Stmt *SLoc = getLocation().getStmtOrNull())
1142 SLoc->dump();
1143 else if (const auto *ND = dyn_cast_or_null<NamedDecl>(getCallee()))
1144 llvm::errs() << *ND << "\n";
1145 else
1146 getLocation().dump();
1147}
1148
1149LLVM_DUMP_METHOD void PathDiagnosticEventPiece::dump() const {
1150 llvm::errs() << "EVENT\n--------------\n";
1151 llvm::errs() << getString() << "\n";
1152 llvm::errs() << " ---- at ----\n";
1153 getLocation().dump();
1154}
1155
1156LLVM_DUMP_METHOD void PathDiagnosticControlFlowPiece::dump() const {
1157 llvm::errs() << "CONTROL\n--------------\n";
1158 getStartLocation().dump();
1159 llvm::errs() << " ---- to ----\n";
1160 getEndLocation().dump();
1161}
1162
1163LLVM_DUMP_METHOD void PathDiagnosticMacroPiece::dump() const {
1164 llvm::errs() << "MACRO\n--------------\n";
1165 // FIXME: Print which macro is being invoked.
1166}
1167
1168LLVM_DUMP_METHOD void PathDiagnosticNotePiece::dump() const {
1169 llvm::errs() << "NOTE\n--------------\n";
1170 llvm::errs() << getString() << "\n";
1171 llvm::errs() << " ---- at ----\n";
1172 getLocation().dump();
1173}
1174
Csaba Dabis1d7ca672019-05-29 19:21:59 +00001175LLVM_DUMP_METHOD void PathDiagnosticPopUpPiece::dump() const {
1176 llvm::errs() << "POP-UP\n--------------\n";
1177 llvm::errs() << getString() << "\n";
1178 llvm::errs() << " ---- at ----\n";
1179 getLocation().dump();
1180}
1181
George Karpenkov1cf8cdc2018-06-12 20:51:01 +00001182LLVM_DUMP_METHOD void PathDiagnosticLocation::dump() const {
1183 if (!isValid()) {
1184 llvm::errs() << "<INVALID>\n";
1185 return;
1186 }
1187
1188 switch (K) {
1189 case RangeK:
1190 // FIXME: actually print the range.
1191 llvm::errs() << "<range>\n";
1192 break;
1193 case SingleLocK:
1194 asLocation().dump();
1195 llvm::errs() << "\n";
1196 break;
1197 case StmtK:
1198 if (S)
1199 S->dump();
1200 else
1201 llvm::errs() << "<NULL STMT>\n";
1202 break;
1203 case DeclK:
1204 if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
1205 llvm::errs() << *ND << "\n";
1206 else if (isa<BlockDecl>(D))
1207 // FIXME: Make this nicer.
1208 llvm::errs() << "<block>\n";
1209 else if (D)
1210 llvm::errs() << "<unknown decl>\n";
1211 else
1212 llvm::errs() << "<NULL DECL>\n";
1213 break;
1214 }
1215}