1f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek//===--- ParentMap.cpp - Mappings from Stmts to their Parents ---*- C++ -*-===//
2f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek//
3f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek//                     The LLVM Compiler Infrastructure
4f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek//
5f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek// This file is distributed under the University of Illinois Open Source
6f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek// License. See LICENSE.TXT for details.
7f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek//
8f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek//===----------------------------------------------------------------------===//
9f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek//
10f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek//  This file defines the ParentMap class.
11f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek//
12f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek//===----------------------------------------------------------------------===//
13f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek
14f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek#include "clang/AST/ParentMap.h"
15acc5f3e42334525bf28c86471551f83dfce222d5Daniel Dunbar#include "clang/AST/Decl.h"
16f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek#include "clang/AST/Expr.h"
17f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek#include "llvm/ADT/DenseMap.h"
18f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek
19f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenekusing namespace clang;
20f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek
21f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenektypedef llvm::DenseMap<Stmt*, Stmt*> MapTy;
22f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek
23f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenekstatic void BuildParentMap(MapTy& M, Stmt* S) {
247502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall  for (Stmt::child_range I = S->children(); I; ++I)
25f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek    if (*I) {
262b1b025fa6e848ec36c0554924d7d63342aa80e4Jordan Rose      // Prefer the first time we see this statement in the traversal.
272b1b025fa6e848ec36c0554924d7d63342aa80e4Jordan Rose      // This is important for PseudoObjectExprs.
282b1b025fa6e848ec36c0554924d7d63342aa80e4Jordan Rose      Stmt *&Parent = M[*I];
292b1b025fa6e848ec36c0554924d7d63342aa80e4Jordan Rose      if (!Parent) {
302b1b025fa6e848ec36c0554924d7d63342aa80e4Jordan Rose        Parent = S;
312b1b025fa6e848ec36c0554924d7d63342aa80e4Jordan Rose        BuildParentMap(M, *I);
322b1b025fa6e848ec36c0554924d7d63342aa80e4Jordan Rose      }
33f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek    }
34e215ba1c2a3f29fe2cbc4cfb0e532cd204970c49Ted Kremenek
35e215ba1c2a3f29fe2cbc4cfb0e532cd204970c49Ted Kremenek  // Also include the source expr tree of an OpaqueValueExpr in the map.
362b1b025fa6e848ec36c0554924d7d63342aa80e4Jordan Rose  if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(S)) {
372b1b025fa6e848ec36c0554924d7d63342aa80e4Jordan Rose    M[OVE->getSourceExpr()] = S;
38e215ba1c2a3f29fe2cbc4cfb0e532cd204970c49Ted Kremenek    BuildParentMap(M, OVE->getSourceExpr());
392b1b025fa6e848ec36c0554924d7d63342aa80e4Jordan Rose  }
40f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek}
41f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek
42f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed KremenekParentMap::ParentMap(Stmt* S) : Impl(0) {
43f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek  if (S) {
44f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek    MapTy *M = new MapTy();
45f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek    BuildParentMap(*M, S);
461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    Impl = M;
47f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek  }
48f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek}
49f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek
50f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed KremenekParentMap::~ParentMap() {
51f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek  delete (MapTy*) Impl;
52f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek}
53f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek
54d6543f8bbac18cdb678a67da2a676c30c2941ecaTed Kremenekvoid ParentMap::addStmt(Stmt* S) {
55d6543f8bbac18cdb678a67da2a676c30c2941ecaTed Kremenek  if (S) {
56d6543f8bbac18cdb678a67da2a676c30c2941ecaTed Kremenek    BuildParentMap(*(MapTy*) Impl, S);
57d6543f8bbac18cdb678a67da2a676c30c2941ecaTed Kremenek  }
58d6543f8bbac18cdb678a67da2a676c30c2941ecaTed Kremenek}
59d6543f8bbac18cdb678a67da2a676c30c2941ecaTed Kremenek
60f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed KremenekStmt* ParentMap::getParent(Stmt* S) const {
61f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek  MapTy* M = (MapTy*) Impl;
62f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek  MapTy::iterator I = M->find(S);
63f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek  return I == M->end() ? 0 : I->second;
64f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek}
65b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek
66b1b9f680f5fc65230de877baccae50820a969a94Ted KremenekStmt *ParentMap::getParentIgnoreParens(Stmt *S) const {
67b1b9f680f5fc65230de877baccae50820a969a94Ted Kremenek  do { S = getParent(S); } while (S && isa<ParenExpr>(S));
68b1b9f680f5fc65230de877baccae50820a969a94Ted Kremenek  return S;
69b1b9f680f5fc65230de877baccae50820a969a94Ted Kremenek}
70b1b9f680f5fc65230de877baccae50820a969a94Ted Kremenek
71f4e532b5a1683a9f6c842f361c7415bf3474315fTed KremenekStmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const {
72f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek  do {
73f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek    S = getParent(S);
74f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek  }
75f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek  while (S && (isa<ParenExpr>(S) || isa<CastExpr>(S)));
76f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek
77f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek  return S;
78f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek}
79f4e532b5a1683a9f6c842f361c7415bf3474315fTed Kremenek
8018fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios KyrtzidisStmt *ParentMap::getParentIgnoreParenImpCasts(Stmt *S) const {
8118fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  do {
8218fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis    S = getParent(S);
8318fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  } while (S && isa<Expr>(S) && cast<Expr>(S)->IgnoreParenImpCasts() != S);
8418fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
8518fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis  return S;
8618fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis}
8718fd0c6915b45c4daafe18e3cd324c13306f913fArgyrios Kyrtzidis
88f85e193739c953358c865005855253af4f68a497John McCallStmt *ParentMap::getOuterParenParent(Stmt *S) const {
89f85e193739c953358c865005855253af4f68a497John McCall  Stmt *Paren = 0;
90f85e193739c953358c865005855253af4f68a497John McCall  while (isa<ParenExpr>(S)) {
91f85e193739c953358c865005855253af4f68a497John McCall    Paren = S;
92f85e193739c953358c865005855253af4f68a497John McCall    S = getParent(S);
93f85e193739c953358c865005855253af4f68a497John McCall  };
94f85e193739c953358c865005855253af4f68a497John McCall  return Paren;
95f85e193739c953358c865005855253af4f68a497John McCall}
96f85e193739c953358c865005855253af4f68a497John McCall
97b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenekbool ParentMap::isConsumedExpr(Expr* E) const {
98b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek  Stmt *P = getParent(E);
99b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek  Stmt *DirectChild = E;
1001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
101b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek  // Ignore parents that are parentheses or casts.
102ade9ecaba935489840fa74aaf5b4c640d6589e33Ted Kremenek  while (P && (isa<ParenExpr>(P) || isa<CastExpr>(P))) {
103b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    DirectChild = P;
104b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    P = getParent(P);
105b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek  }
1061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
107b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek  if (!P)
108b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    return false;
1091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
110b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek  switch (P->getStmtClass()) {
111b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    default:
112b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek      return isa<Expr>(P);
113b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    case Stmt::DeclStmtClass:
114b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek      return true;
115b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    case Stmt::BinaryOperatorClass: {
116b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek      BinaryOperator *BE = cast<BinaryOperator>(P);
11724ae89a5a25f8971c7436bb3b7663e66ed99b987Ted Kremenek      // If it is a comma, only the right side is consumed.
118e42ac98bc2d50506216b6ef258594bdaa59c47c1Ted Kremenek      // If it isn't a comma, both sides are consumed.
1192de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall      return BE->getOpcode()!=BO_Comma ||DirectChild==BE->getRHS();
120b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    }
121b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    case Stmt::ForStmtClass:
122b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek      return DirectChild == cast<ForStmt>(P)->getCond();
123b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    case Stmt::WhileStmtClass:
1241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      return DirectChild == cast<WhileStmt>(P)->getCond();
125b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    case Stmt::DoStmtClass:
126b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek      return DirectChild == cast<DoStmt>(P)->getCond();
127b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    case Stmt::IfStmtClass:
128b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek      return DirectChild == cast<IfStmt>(P)->getCond();
129b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    case Stmt::IndirectGotoStmtClass:
130b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek      return DirectChild == cast<IndirectGotoStmt>(P)->getTarget();
131b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    case Stmt::SwitchStmtClass:
132b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek      return DirectChild == cast<SwitchStmt>(P)->getCond();
133b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    case Stmt::ReturnStmtClass:
134b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek      return true;
135b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek  }
136b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek}
137b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek
138