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