/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/AST/DeclGroup.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- DeclGroup.h - Classes for representing groups of Decls ---*- 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 defines the DeclGroup, DeclGroupRef, and OwningDeclGroup classes. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #ifndef LLVM_CLANG_AST_DECLGROUP_H |
14 | | #define LLVM_CLANG_AST_DECLGROUP_H |
15 | | |
16 | | #include "llvm/Support/TrailingObjects.h" |
17 | | #include <cassert> |
18 | | #include <cstdint> |
19 | | |
20 | | namespace clang { |
21 | | |
22 | | class ASTContext; |
23 | | class Decl; |
24 | | |
25 | | class DeclGroup final : private llvm::TrailingObjects<DeclGroup, Decl *> { |
26 | | // FIXME: Include a TypeSpecifier object. |
27 | | unsigned NumDecls = 0; |
28 | | |
29 | | private: |
30 | | DeclGroup() = default; |
31 | | DeclGroup(unsigned numdecls, Decl** decls); |
32 | | |
33 | | public: |
34 | | friend TrailingObjects; |
35 | | |
36 | | static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls); |
37 | | |
38 | 414k | unsigned size() const { return NumDecls; } |
39 | | |
40 | 1.16M | Decl*& operator[](unsigned i) { |
41 | 1.16M | assert (i < NumDecls && "Out-of-bounds access."); |
42 | 1.16M | return getTrailingObjects<Decl *>()[i]; |
43 | 1.16M | } |
44 | | |
45 | 18.1k | Decl* const& operator[](unsigned i) const { |
46 | 18.1k | assert (i < NumDecls && "Out-of-bounds access."); |
47 | 18.1k | return getTrailingObjects<Decl *>()[i]; |
48 | 18.1k | } |
49 | | }; |
50 | | |
51 | | class DeclGroupRef { |
52 | | // Note this is not a PointerIntPair because we need the address of the |
53 | | // non-group case to be valid as a Decl** for iteration. |
54 | | enum Kind { SingleDeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 }; |
55 | | |
56 | | Decl* D = nullptr; |
57 | | |
58 | 79.0M | Kind getKind() const { |
59 | 79.0M | return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask); |
60 | 79.0M | } |
61 | | |
62 | | public: |
63 | 27.4M | DeclGroupRef() = default; |
64 | 46.7M | explicit DeclGroupRef(Decl* d) : D(d) {} |
65 | | explicit DeclGroupRef(DeclGroup* dg) |
66 | 503k | : D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {} |
67 | | |
68 | 37.5M | static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls) { |
69 | 37.5M | if (NumDecls == 0) |
70 | 681 | return DeclGroupRef(); |
71 | 37.5M | if (NumDecls == 1) |
72 | 37.0M | return DeclGroupRef(Decls[0]); |
73 | 501k | return DeclGroupRef(DeclGroup::Create(C, Decls, NumDecls)); |
74 | 37.5M | } |
75 | | |
76 | | using iterator = Decl **; |
77 | | using const_iterator = Decl * const *; |
78 | | |
79 | 2.21M | bool isNull() const { return D == nullptr; } |
80 | 77.9M | bool isSingleDecl() const { return getKind() == SingleDeclKind; } |
81 | 1.18M | bool isDeclGroup() const { return getKind() == DeclGroupKind; } |
82 | | |
83 | 1.27M | Decl *getSingleDecl() { |
84 | 1.27M | assert(isSingleDecl() && "Isn't a single decl"); |
85 | 1.27M | return D; |
86 | 1.27M | } |
87 | 103k | const Decl *getSingleDecl() const { |
88 | 103k | return const_cast<DeclGroupRef*>(this)->getSingleDecl(); |
89 | 103k | } |
90 | | |
91 | 1.18M | DeclGroup &getDeclGroup() { |
92 | 1.18M | assert(isDeclGroup() && "Isn't a declgroup"); |
93 | 1.18M | return *((DeclGroup*)(reinterpret_cast<uintptr_t>(D) & ~Mask)); |
94 | 1.18M | } |
95 | 18.1k | const DeclGroup &getDeclGroup() const { |
96 | 18.1k | return const_cast<DeclGroupRef*>(this)->getDeclGroup(); |
97 | 18.1k | } |
98 | | |
99 | 48.7M | iterator begin() { |
100 | 48.7M | if (isSingleDecl()) |
101 | 47.9M | return D ? &D47.9M : nullptr38 ; |
102 | 759k | return &getDeclGroup()[0]; |
103 | 48.7M | } |
104 | | |
105 | 25.9M | iterator end() { |
106 | 25.9M | if (isSingleDecl()) |
107 | 25.5M | return D ? &D+125.5M : nullptr38 ; |
108 | 405k | DeclGroup &G = getDeclGroup(); |
109 | 405k | return &G[0] + G.size(); |
110 | 25.9M | } |
111 | | |
112 | 414k | const_iterator begin() const { |
113 | 414k | if (isSingleDecl()) |
114 | 405k | return D ? &D : nullptr0 ; |
115 | 9.08k | return &getDeclGroup()[0]; |
116 | 414k | } |
117 | | |
118 | 325k | const_iterator end() const { |
119 | 325k | if (isSingleDecl()) |
120 | 316k | return D ? &D+1 : nullptr0 ; |
121 | 9.08k | const DeclGroup &G = getDeclGroup(); |
122 | 9.08k | return &G[0] + G.size(); |
123 | 325k | } |
124 | | |
125 | 46.6M | void *getAsOpaquePtr() const { return D; } |
126 | 27.4M | static DeclGroupRef getFromOpaquePtr(void *Ptr) { |
127 | 27.4M | DeclGroupRef X; |
128 | 27.4M | X.D = static_cast<Decl*>(Ptr); |
129 | 27.4M | return X; |
130 | 27.4M | } |
131 | | }; |
132 | | |
133 | | } // namespace clang |
134 | | |
135 | | namespace llvm { |
136 | | |
137 | | // DeclGroupRef is "like a pointer", implement PointerLikeTypeTraits. |
138 | | template <typename T> |
139 | | struct PointerLikeTypeTraits; |
140 | | template <> |
141 | | struct PointerLikeTypeTraits<clang::DeclGroupRef> { |
142 | 46.6M | static inline void *getAsVoidPointer(clang::DeclGroupRef P) { |
143 | 46.6M | return P.getAsOpaquePtr(); |
144 | 46.6M | } |
145 | | |
146 | 27.4M | static inline clang::DeclGroupRef getFromVoidPointer(void *P) { |
147 | 27.4M | return clang::DeclGroupRef::getFromOpaquePtr(P); |
148 | 27.4M | } |
149 | | |
150 | | static constexpr int NumLowBitsAvailable = 0; |
151 | | }; |
152 | | |
153 | | } // namespace llvm |
154 | | |
155 | | #endif // LLVM_CLANG_AST_DECLGROUP_H |