Clang Project

clang_source_code/lib/Analysis/ProgramPoint.cpp
1//==- ProgramPoint.cpp - Program Points for Path-Sensitive Analysis -*- C++ -*-/
2//
3// 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
6//
7//===----------------------------------------------------------------------===//
8//
9//  This file defines the interface ProgramPoint, which identifies a
10//  distinct location in a function.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Analysis/ProgramPoint.h"
15
16using namespace clang;
17
18ProgramPointTag::~ProgramPointTag() {}
19
20ProgramPoint ProgramPoint::getProgramPoint(const Stmt *SProgramPoint::Kind K,
21                                           const LocationContext *LC,
22                                           const ProgramPointTag *tag){
23  switch (K) {
24    default:
25      llvm_unreachable("Unhandled ProgramPoint kind");
26    case ProgramPoint::PreStmtKind:
27      return PreStmt(S, LC, tag);
28    case ProgramPoint::PostStmtKind:
29      return PostStmt(S, LC, tag);
30    case ProgramPoint::PreLoadKind:
31      return PreLoad(S, LC, tag);
32    case ProgramPoint::PostLoadKind:
33      return PostLoad(S, LC, tag);
34    case ProgramPoint::PreStoreKind:
35      return PreStore(S, LC, tag);
36    case ProgramPoint::PostLValueKind:
37      return PostLValue(S, LC, tag);
38    case ProgramPoint::PostStmtPurgeDeadSymbolsKind:
39      return PostStmtPurgeDeadSymbols(S, LC, tag);
40    case ProgramPoint::PreStmtPurgeDeadSymbolsKind:
41      return PreStmtPurgeDeadSymbols(S, LC, tag);
42  }
43}
44
45LLVM_DUMP_METHOD void ProgramPoint::dump() const {
46  return print(/*CR=*/"\n", llvm::errs());
47}
48
49static void printLocation(raw_ostream &OutSourceLocation SLoc,
50                          const SourceManager &SM,
51                          StringRef CR,
52                          StringRef Postfix) {
53  if (SLoc.isFileID()) {
54    Out << CR << "line=" << SM.getExpansionLineNumber(SLoc)
55        << " col=" << SM.getExpansionColumnNumber(SLoc) << Postfix;
56  }
57}
58
59void ProgramPoint::print(StringRef CRllvm::raw_ostream &Outconst {
60  const ASTContext &Context =
61      getLocationContext()->getAnalysisDeclContext()->getASTContext();
62  const SourceManager &SM = Context.getSourceManager();
63  switch (getKind()) {
64  case ProgramPoint::BlockEntranceKind:
65    Out << "Block Entrance: B"
66        << castAs<BlockEntrance>().getBlock()->getBlockID();
67    break;
68
69  case ProgramPoint::FunctionExitKind: {
70    auto FEP = getAs<FunctionExitPoint>();
71    Out << "Function Exit: B" << FEP->getBlock()->getBlockID();
72    if (const ReturnStmt *RS = FEP->getStmt()) {
73      Out << CR << " Return: S" << RS->getID(Context) << CR;
74      RS->printPretty(Out, /*helper=*/nullptr, Context.getPrintingPolicy(),
75                      /*Indentation=*/2/*NewlineSymbol=*/CR);
76    }
77    break;
78  }
79  case ProgramPoint::BlockExitKind:
80    assert(false);
81    break;
82
83  case ProgramPoint::CallEnterKind:
84    Out << "CallEnter";
85    break;
86
87  case ProgramPoint::CallExitBeginKind:
88    Out << "CallExitBegin";
89    break;
90
91  case ProgramPoint::CallExitEndKind:
92    Out << "CallExitEnd";
93    break;
94
95  case ProgramPoint::PostStmtPurgeDeadSymbolsKind:
96    Out << "PostStmtPurgeDeadSymbols";
97    break;
98
99  case ProgramPoint::PreStmtPurgeDeadSymbolsKind:
100    Out << "PreStmtPurgeDeadSymbols";
101    break;
102
103  case ProgramPoint::EpsilonKind:
104    Out << "Epsilon Point";
105    break;
106
107  case ProgramPoint::LoopExitKind: {
108    LoopExit LE = castAs<LoopExit>();
109    Out << "LoopExit: " << LE.getLoopStmt()->getStmtClassName();
110    break;
111  }
112
113  case ProgramPoint::PreImplicitCallKind: {
114    ImplicitCallPoint PC = castAs<ImplicitCallPoint>();
115    Out << "PreCall: ";
116    PC.getDecl()->print(OutContext.getLangOpts());
117    printLocation(Out, PC.getLocation(), SM, CR, /*Postfix=*/CR);
118    break;
119  }
120
121  case ProgramPoint::PostImplicitCallKind: {
122    ImplicitCallPoint PC = castAs<ImplicitCallPoint>();
123    Out << "PostCall: ";
124    PC.getDecl()->print(OutContext.getLangOpts());
125    printLocation(Out, PC.getLocation(), SM, CR, /*Postfix=*/CR);
126    break;
127  }
128
129  case ProgramPoint::PostInitializerKind: {
130    Out << "PostInitializer: ";
131    const CXXCtorInitializer *Init = castAs<PostInitializer>().getInitializer();
132    if (const FieldDecl *FD = Init->getAnyMember())
133      Out << *FD;
134    else {
135      QualType Ty = Init->getTypeSourceInfo()->getType();
136      Ty = Ty.getLocalUnqualifiedType();
137      Ty.print(OutContext.getLangOpts());
138    }
139    break;
140  }
141
142  case ProgramPoint::BlockEdgeKind: {
143    const BlockEdge &E = castAs<BlockEdge>();
144    Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
145        << E.getDst()->getBlockID() << ')';
146
147    if (const Stmt *T = E.getSrc()->getTerminator()) {
148      SourceLocation SLoc = T->getBeginLoc();
149
150      Out << "\\|Terminator: ";
151      E.getSrc()->printTerminator(OutContext.getLangOpts());
152      printLocation(Out, SLoc, SM, CR, /*Postfix=*/"");
153
154      if (isa<SwitchStmt>(T)) {
155        const Stmt *Label = E.getDst()->getLabel();
156
157        if (Label) {
158          if (const auto *C = dyn_cast<CaseStmt>(Label)) {
159            Out << CR << "case ";
160            if (C->getLHS())
161              C->getLHS()->printPretty(
162                  Out, nullptr, Context.getPrintingPolicy(),
163                  /*Indentation=*/0/*NewlineSymbol=*/CR);
164
165            if (const Stmt *RHS = C->getRHS()) {
166              Out << " .. ";
167              RHS->printPretty(Out, nullptr, Context.getPrintingPolicy(),
168                               /*Indetation=*/0/*NewlineSymbol=*/CR);
169            }
170
171            Out << ":";
172          } else {
173            (Label)", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/ProgramPoint.cpp", 173, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isa<DefaultStmt>(Label));
174            Out << CR << "default:";
175          }
176        } else
177          Out << CR << "(implicit) default:";
178      } else if (isa<IndirectGotoStmt>(T)) {
179        // FIXME
180      } else {
181        Out << CR << "Condition: ";
182        if (*E.getSrc()->succ_begin() == E.getDst())
183          Out << "true";
184        else
185          Out << "false";
186      }
187
188      Out << CR;
189    }
190
191    break;
192  }
193
194  default: {
195    const Stmt *S = castAs<StmtPoint>().getStmt();
196     (0) . __assert_fail ("S != nullptr && \"Expecting non-null Stmt\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/ProgramPoint.cpp", 196, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(S != nullptr && "Expecting non-null Stmt");
197
198    Out << S->getStmtClassName() << " S" << S->getID(Context) << " <"
199        << (const void *)S << "> ";
200    S->printPretty(Out, /*helper=*/nullptr, Context.getPrintingPolicy(),
201                   /*Indentation=*/2/*NewlineSymbol=*/CR);
202    printLocation(Out, S->getBeginLoc(), SM, CR, /*Postfix=*/"");
203
204    if (getAs<PreStmt>())
205      Out << CR << "PreStmt" << CR;
206    else if (getAs<PostLoad>())
207      Out << CR << "PostLoad" << CR;
208    else if (getAs<PostStore>())
209      Out << CR << "PostStore" << CR;
210    else if (getAs<PostLValue>())
211      Out << CR << "PostLValue" << CR;
212    else if (getAs<PostAllocatorCall>())
213      Out << CR << "PostAllocatorCall" << CR;
214
215    break;
216  }
217  }
218}
219
220SimpleProgramPointTag::SimpleProgramPointTag(StringRef MsgProvider,
221                                             StringRef Msg)
222  : Desc((MsgProvider + " : " + Msg).str()) {}
223
224StringRef SimpleProgramPointTag::getTagDescription() const {
225  return Desc;
226}
227
clang::ProgramPoint::getProgramPoint
clang::ProgramPoint::dump
clang::ProgramPoint::print
clang::SimpleProgramPointTag::getTagDescription