92 lines · cpp
1//===- Origins.cpp - Origin Implementation -----------------------*- 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-exception6//7//===----------------------------------------------------------------------===//8 9#include "clang/Analysis/Analyses/LifetimeSafety/Origins.h"10 11namespace clang::lifetimes::internal {12 13void OriginManager::dump(OriginID OID, llvm::raw_ostream &OS) const {14 OS << OID << " (";15 Origin O = getOrigin(OID);16 if (const ValueDecl *VD = O.getDecl())17 OS << "Decl: " << VD->getNameAsString();18 else if (const Expr *E = O.getExpr())19 OS << "Expr: " << E->getStmtClassName();20 else21 OS << "Unknown";22 OS << ")";23}24 25Origin &OriginManager::addOrigin(OriginID ID, const clang::ValueDecl &D) {26 AllOrigins.emplace_back(ID, &D);27 return AllOrigins.back();28}29 30Origin &OriginManager::addOrigin(OriginID ID, const clang::Expr &E) {31 AllOrigins.emplace_back(ID, &E);32 return AllOrigins.back();33}34 35// TODO: Mark this method as const once we remove the call to getOrCreate.36OriginID OriginManager::get(const Expr &E) {37 if (auto *ParenIgnored = E.IgnoreParens(); ParenIgnored != &E)38 return get(*ParenIgnored);39 auto It = ExprToOriginID.find(&E);40 if (It != ExprToOriginID.end())41 return It->second;42 // If the expression itself has no specific origin, and it's a reference43 // to a declaration, its origin is that of the declaration it refers to.44 // For pointer types, where we don't pre-emptively create an origin for the45 // DeclRefExpr itself.46 if (const auto *DRE = dyn_cast<DeclRefExpr>(&E))47 return get(*DRE->getDecl());48 // TODO: This should be an assert(It != ExprToOriginID.end()). The current49 // implementation falls back to getOrCreate to avoid crashing on50 // yet-unhandled pointer expressions, creating an empty origin for them.51 return getOrCreate(E);52}53 54OriginID OriginManager::get(const ValueDecl &D) {55 auto It = DeclToOriginID.find(&D);56 // TODO: This should be an assert(It != DeclToOriginID.end()). The current57 // implementation falls back to getOrCreate to avoid crashing on58 // yet-unhandled pointer expressions, creating an empty origin for them.59 if (It == DeclToOriginID.end())60 return getOrCreate(D);61 62 return It->second;63}64 65OriginID OriginManager::getOrCreate(const Expr &E) {66 auto It = ExprToOriginID.find(&E);67 if (It != ExprToOriginID.end())68 return It->second;69 70 OriginID NewID = getNextOriginID();71 addOrigin(NewID, E);72 ExprToOriginID[&E] = NewID;73 return NewID;74}75 76const Origin &OriginManager::getOrigin(OriginID ID) const {77 assert(ID.Value < AllOrigins.size());78 return AllOrigins[ID.Value];79}80 81OriginID OriginManager::getOrCreate(const ValueDecl &D) {82 auto It = DeclToOriginID.find(&D);83 if (It != DeclToOriginID.end())84 return It->second;85 OriginID NewID = getNextOriginID();86 addOrigin(NewID, D);87 DeclToOriginID[&D] = NewID;88 return NewID;89}90 91} // namespace clang::lifetimes::internal92