ParentMap.cpp revision 2de56d1d0c3a504ad1529de2677628bdfbb95cd4
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) {
24f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek  for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I)
25f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek    if (*I) {
26f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek      M[*I] = S;
27f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek      BuildParentMap(M, *I);
28f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek    }
29f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek}
30f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek
31f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed KremenekParentMap::ParentMap(Stmt* S) : Impl(0) {
32f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek  if (S) {
33f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek    MapTy *M = new MapTy();
34f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek    BuildParentMap(*M, S);
351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    Impl = M;
36f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek  }
37f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek}
38f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek
39f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed KremenekParentMap::~ParentMap() {
40f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek  delete (MapTy*) Impl;
41f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek}
42f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek
43f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed KremenekStmt* ParentMap::getParent(Stmt* S) const {
44f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek  MapTy* M = (MapTy*) Impl;
45f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek  MapTy::iterator I = M->find(S);
46f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek  return I == M->end() ? 0 : I->second;
47f8e32cf062f39fff1a00aff748cb6b5dc0abc2feTed Kremenek}
48b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek
49b1b9f680f5fc65230de877baccae50820a969a94Ted KremenekStmt *ParentMap::getParentIgnoreParens(Stmt *S) const {
50b1b9f680f5fc65230de877baccae50820a969a94Ted Kremenek  do { S = getParent(S); } while (S && isa<ParenExpr>(S));
51b1b9f680f5fc65230de877baccae50820a969a94Ted Kremenek  return S;
52b1b9f680f5fc65230de877baccae50820a969a94Ted Kremenek}
53b1b9f680f5fc65230de877baccae50820a969a94Ted Kremenek
54b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenekbool ParentMap::isConsumedExpr(Expr* E) const {
55b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek  Stmt *P = getParent(E);
56b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek  Stmt *DirectChild = E;
571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
58b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek  // Ignore parents that are parentheses or casts.
59ade9ecaba935489840fa74aaf5b4c640d6589e33Ted Kremenek  while (P && (isa<ParenExpr>(P) || isa<CastExpr>(P))) {
60b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    DirectChild = P;
61b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    P = getParent(P);
62b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek  }
631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
64b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek  if (!P)
65b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    return false;
661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
67b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek  switch (P->getStmtClass()) {
68b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    default:
69b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek      return isa<Expr>(P);
70b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    case Stmt::DeclStmtClass:
71b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek      return true;
72b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    case Stmt::BinaryOperatorClass: {
73b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek      BinaryOperator *BE = cast<BinaryOperator>(P);
7424ae89a5a25f8971c7436bb3b7663e66ed99b987Ted Kremenek      // If it is a comma, only the right side is consumed.
75e42ac98bc2d50506216b6ef258594bdaa59c47c1Ted Kremenek      // If it isn't a comma, both sides are consumed.
762de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall      return BE->getOpcode()!=BO_Comma ||DirectChild==BE->getRHS();
77b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    }
78b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    case Stmt::ForStmtClass:
79b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek      return DirectChild == cast<ForStmt>(P)->getCond();
80b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    case Stmt::WhileStmtClass:
811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      return DirectChild == cast<WhileStmt>(P)->getCond();
82b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    case Stmt::DoStmtClass:
83b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek      return DirectChild == cast<DoStmt>(P)->getCond();
84b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    case Stmt::IfStmtClass:
85b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek      return DirectChild == cast<IfStmt>(P)->getCond();
86b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    case Stmt::IndirectGotoStmtClass:
87b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek      return DirectChild == cast<IndirectGotoStmt>(P)->getTarget();
88b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    case Stmt::SwitchStmtClass:
89b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek      return DirectChild == cast<SwitchStmt>(P)->getCond();
90b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek    case Stmt::ReturnStmtClass:
91b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek      return true;
92b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek  }
93b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek}
94b930d7adb7cb7642c9c49b39df04ebd5cbfa713aTed Kremenek
95