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 
19 ProgramPointTag::~ProgramPointTag() {}
20 
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 
46 static void printLocation(raw_ostream &Out, SourceLocation SLoc,
47                           const SourceManager &SM,
48                           StringRef CR,
49                           StringRef Postfix) {
50   if (SLoc.isFileID()) {
51     Out << CR << "line=" << SM.getExpansionLineNumber(SLoc)
52         << " col=" << SM.getExpansionColumnNumber(SLoc) << Postfix;
53   }
54 }
55 
56 void ProgramPoint::print(StringRef CR, llvm::raw_ostream &Out) const {
57   const ASTContext &Context =
58       getLocationContext()->getAnalysisDeclContext()->getASTContext();
59   const SourceManager &SM = Context.getSourceManager();
60   switch (getKind()) {
61   case ProgramPoint::BlockEntranceKind:
62     Out << "Block Entrance: B"
63         << castAs<BlockEntrance>().getBlock()->getBlockID();
64     break;
65 
66   case ProgramPoint::FunctionExitKind: {
67     auto FEP = getAs<FunctionExitPoint>();
68     Out << "Function Exit: B" << FEP->getBlock()->getBlockID();
69     if (const ReturnStmt *RS = FEP->getStmt()) {
70       Out << CR << " Return: S" << RS->getID(Context) << CR;
71       RS->printPretty(Out, /*helper=*/nullptr, Context.getPrintingPolicy(),
72                       /*Indentation=*/2, /*NewlineSymbol=*/CR);
73     }
74     break;
75   }
76   case ProgramPoint::BlockExitKind:
77     assert(false);
78     break;
79 
80   case ProgramPoint::CallEnterKind:
81     Out << "CallEnter";
82     break;
83 
84   case ProgramPoint::CallExitBeginKind:
85     Out << "CallExitBegin";
86     break;
87 
88   case ProgramPoint::CallExitEndKind:
89     Out << "CallExitEnd";
90     break;
91 
92   case ProgramPoint::PostStmtPurgeDeadSymbolsKind:
93     Out << "PostStmtPurgeDeadSymbols";
94     break;
95 
96   case ProgramPoint::PreStmtPurgeDeadSymbolsKind:
97     Out << "PreStmtPurgeDeadSymbols";
98     break;
99 
100   case ProgramPoint::EpsilonKind:
101     Out << "Epsilon Point";
102     break;
103 
104   case ProgramPoint::LoopExitKind: {
105     LoopExit LE = castAs<LoopExit>();
106     Out << "LoopExit: " << LE.getLoopStmt()->getStmtClassName();
107     break;
108   }
109 
110   case ProgramPoint::PreImplicitCallKind: {
111     ImplicitCallPoint PC = castAs<ImplicitCallPoint>();
112     Out << "PreCall: ";
113     PC.getDecl()->print(Out, Context.getLangOpts());
114     printLocation(Out, PC.getLocation(), SM, CR, /*Postfix=*/CR);
115     break;
116   }
117 
118   case ProgramPoint::PostImplicitCallKind: {
119     ImplicitCallPoint PC = castAs<ImplicitCallPoint>();
120     Out << "PostCall: ";
121     PC.getDecl()->print(Out, Context.getLangOpts());
122     printLocation(Out, PC.getLocation(), SM, CR, /*Postfix=*/CR);
123     break;
124   }
125 
126   case ProgramPoint::PostInitializerKind: {
127     Out << "PostInitializer: ";
128     const CXXCtorInitializer *Init = castAs<PostInitializer>().getInitializer();
129     if (const FieldDecl *FD = Init->getAnyMember())
130       Out << *FD;
131     else {
132       QualType Ty = Init->getTypeSourceInfo()->getType();
133       Ty = Ty.getLocalUnqualifiedType();
134       Ty.print(Out, Context.getLangOpts());
135     }
136     break;
137   }
138 
139   case ProgramPoint::BlockEdgeKind: {
140     const BlockEdge &E = castAs<BlockEdge>();
141     Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
142         << E.getDst()->getBlockID() << ')';
143 
144     if (const Stmt *T = E.getSrc()->getTerminator()) {
145       SourceLocation SLoc = T->getBeginLoc();
146 
147       Out << "\\|Terminator: ";
148       E.getSrc()->printTerminator(Out, Context.getLangOpts());
149       printLocation(Out, SLoc, SM, CR, /*Postfix=*/"");
150 
151       if (isa<SwitchStmt>(T)) {
152         const Stmt *Label = E.getDst()->getLabel();
153 
154         if (Label) {
155           if (const auto *C = dyn_cast<CaseStmt>(Label)) {
156             Out << CR << "case ";
157             if (C->getLHS())
158               C->getLHS()->printPretty(
159                   Out, nullptr, Context.getPrintingPolicy(),
160                   /*Indentation=*/0, /*NewlineSymbol=*/CR);
161 
162             if (const Stmt *RHS = C->getRHS()) {
163               Out << " .. ";
164               RHS->printPretty(Out, nullptr, Context.getPrintingPolicy(),
165                                /*Indetation=*/0, /*NewlineSymbol=*/CR);
166             }
167 
168             Out << ":";
169           } else {
170             assert(isa<DefaultStmt>(Label));
171             Out << CR << "default:";
172           }
173         } else
174           Out << CR << "(implicit) default:";
175       } else if (isa<IndirectGotoStmt>(T)) {
176         // FIXME
177       } else {
178         Out << CR << "Condition: ";
179         if (*E.getSrc()->succ_begin() == E.getDst())
180           Out << "true";
181         else
182           Out << "false";
183       }
184 
185       Out << CR;
186     }
187 
188     break;
189   }
190 
191   default: {
192     const Stmt *S = castAs<StmtPoint>().getStmt();
193     assert(S != nullptr && "Expecting non-null Stmt");
194 
195     Out << S->getStmtClassName() << " S" << S->getID(Context) << " <"
196         << (const void *)S << "> ";
197     S->printPretty(Out, /*helper=*/nullptr, Context.getPrintingPolicy(),
198                    /*Indentation=*/2, /*NewlineSymbol=*/CR);
199     printLocation(Out, S->getBeginLoc(), SM, CR, /*Postfix=*/"");
200 
201     if (getAs<PreStmt>())
202       Out << CR << "PreStmt" << CR;
203     else if (getAs<PostLoad>())
204       Out << CR << "PostLoad" << CR;
205     else if (getAs<PostStore>())
206       Out << CR << "PostStore" << CR;
207     else if (getAs<PostLValue>())
208       Out << CR << "PostLValue" << CR;
209     else if (getAs<PostAllocatorCall>())
210       Out << CR << "PostAllocatorCall" << CR;
211 
212     break;
213   }
214   }
215 }
216 
217 SimpleProgramPointTag::SimpleProgramPointTag(StringRef MsgProvider,
218                                              StringRef Msg)
219   : Desc((MsgProvider + " : " + Msg).str()) {}
220 
221 StringRef SimpleProgramPointTag::getTagDescription() const {
222   return Desc;
223 }
224