1//===--- VarBypassDetector.h - Bypass jumps detector --------------*- 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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains VarBypassDetector class, which is used to detect
10// local variable declarations which can be bypassed by jumps.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_LIB_CODEGEN_VARBYPASSDETECTOR_H
15#define LLVM_CLANG_LIB_CODEGEN_VARBYPASSDETECTOR_H
16
17#include "CodeGenModule.h"
18#include "clang/AST/Decl.h"
19#include "llvm/ADT/DenseMap.h"
20#include "llvm/ADT/DenseSet.h"
21#include "llvm/ADT/SetVector.h"
22#include "llvm/ADT/SmallVector.h"
23
24namespace clang {
25
26class Decl;
27class Stmt;
28class VarDecl;
29
30namespace CodeGen {
31
32/// The class detects jumps which bypass local variables declaration:
33/// goto L;
34/// int a;
35/// L:
36///
37/// This is simplified version of JumpScopeChecker. Primary differences:
38/// * Detects only jumps into the scope local variables.
39/// * Does not detect jumps out of the scope of local variables.
40/// * Not limited to variables with initializers, JumpScopeChecker is limited.
41class VarBypassDetector {
42 // Scope information. Contains a parent scope and related variable
43 // declaration.
44 llvm::SmallVector<std::pair<unsigned, const VarDecl *>, 48> Scopes;
45 // List of jumps with scopes.
46 llvm::SmallVector<std::pair<const Stmt *, unsigned>, 16> FromScopes;
47 // Lookup map to find scope for destinations.
48 llvm::DenseMap<const Stmt *, unsigned> ToScopes;
49 // Set of variables which were bypassed by some jump.
50 llvm::DenseSet<const VarDecl *> Bypasses;
51 // Map from a bypassing jump (goto/switch) to the variable declarations it
52 // bypasses. Used to reinitialize those variables at the jump.
53 llvm::DenseMap<const Stmt *, llvm::SmallSetVector<const VarDecl *, 4>>
54 BypassedVarsAtSource;
55 // If true assume that all variables are being bypassed.
56 bool AlwaysBypassed = false;
57
58public:
59 void Init(CodeGenModule &CGM, const Stmt *Body);
60
61 /// Returns true if the variable declaration was by bypassed by any goto or
62 /// switch statement.
63 bool IsBypassed(const VarDecl *D) const {
64 return AlwaysBypassed || Bypasses.contains(V: D);
65 }
66
67 /// Returns true if jump sources cannot be determined (e.g. computed gotos),
68 /// so all variables must be treated as bypassed.
69 bool isAlwaysBypassed() const { return AlwaysBypassed; }
70
71 /// Returns the variables bypassed by jumps from the given source statement,
72 /// or nullptr if it bypasses none.
73 const llvm::SmallSetVector<const VarDecl *, 4> *
74 getBypassedVarsForSource(const Stmt *Source) const {
75 auto It = BypassedVarsAtSource.find(Val: Source);
76 if (It == BypassedVarsAtSource.end())
77 return nullptr;
78 return &It->second;
79 }
80
81private:
82 bool BuildScopeInformation(CodeGenModule &CGM, const Decl *D,
83 unsigned &ParentScope);
84 bool BuildScopeInformation(CodeGenModule &CGM, const Stmt *S,
85 unsigned &origParentScope);
86 void Detect();
87 void Detect(unsigned From, unsigned To, const Stmt *Source);
88};
89}
90}
91
92#endif
93