/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/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 | 177k | unsigned size() const { return NumDecls; } |
39 | | |
40 | 419k | Decl*& operator[](unsigned i) { |
41 | 419k | assert (i < NumDecls && "Out-of-bounds access."); |
42 | 419k | return getTrailingObjects<Decl *>()[i]; |
43 | 419k | } |
44 | | |
45 | 58.2k | Decl* const& operator[](unsigned i) const { |
46 | 58.2k | assert (i < NumDecls && "Out-of-bounds access."); |
47 | 58.2k | return getTrailingObjects<Decl *>()[i]; |
48 | 58.2k | } |
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 | 16.5M | Kind getKind() const { |
59 | 16.5M | return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask); |
60 | 16.5M | } |
61 | | |
62 | | public: |
63 | 5.94M | DeclGroupRef() = default; |
64 | 13.4M | explicit DeclGroupRef(Decl* d) : D(d) {} |
65 | | explicit DeclGroupRef(DeclGroup* dg) |
66 | 221k | : D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {} |
67 | | |
68 | 8.27M | static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls) { |
69 | 8.27M | if (NumDecls == 0) |
70 | 416 | return DeclGroupRef(); |
71 | 8.27M | if (NumDecls == 1) |
72 | 8.05M | return DeclGroupRef(Decls[0]); |
73 | 220k | return DeclGroupRef(DeclGroup::Create(C, Decls, NumDecls)); |
74 | 220k | } |
75 | | |
76 | | using iterator = Decl **; |
77 | | using const_iterator = Decl * const *; |
78 | | |
79 | 2.09M | bool isNull() const { return D == nullptr; } |
80 | 16.5M | bool isSingleDecl() const { return getKind() == SingleDeclKind; } |
81 | 0 | bool isDeclGroup() const { return getKind() == DeclGroupKind; } |
82 | | |
83 | 598k | Decl *getSingleDecl() { |
84 | 598k | assert(isSingleDecl() && "Isn't a single decl"); |
85 | 598k | return D; |
86 | 598k | } |
87 | 55.8k | const Decl *getSingleDecl() const { |
88 | 55.8k | return const_cast<DeclGroupRef*>(this)->getSingleDecl(); |
89 | 55.8k | } |
90 | | |
91 | 477k | DeclGroup &getDeclGroup() { |
92 | 477k | assert(isDeclGroup() && "Isn't a declgroup"); |
93 | 477k | return *((DeclGroup*)(reinterpret_cast<uintptr_t>(D) & ~Mask)); |
94 | 477k | } |
95 | 58.2k | const DeclGroup &getDeclGroup() const { |
96 | 58.2k | return const_cast<DeclGroupRef*>(this)->getDeclGroup(); |
97 | 58.2k | } |
98 | | |
99 | 9.09M | iterator begin() { |
100 | 9.09M | if (isSingleDecl()) |
101 | 8.82M | return D ? &D8.82M : nullptr38 ; |
102 | 271k | return &getDeclGroup()[0]; |
103 | 271k | } |
104 | | |
105 | 5.33M | iterator end() { |
106 | 5.33M | if (isSingleDecl()) |
107 | 5.18M | return D ? &D+15.18M : nullptr38 ; |
108 | 147k | DeclGroup &G = getDeclGroup(); |
109 | 147k | return &G[0] + G.size(); |
110 | 147k | } |
111 | | |
112 | 780k | const_iterator begin() const { |
113 | 780k | if (isSingleDecl()) |
114 | 750k | return D ? &D : nullptr0 ; |
115 | 29.1k | return &getDeclGroup()[0]; |
116 | 29.1k | } |
117 | | |
118 | 752k | const_iterator end() const { |
119 | 752k | if (isSingleDecl()) |
120 | 723k | return D ? &D+1 : nullptr0 ; |
121 | 29.1k | const DeclGroup &G = getDeclGroup(); |
122 | 29.1k | return &G[0] + G.size(); |
123 | 29.1k | } |
124 | | |
125 | 13.2M | void *getAsOpaquePtr() const { return D; } |
126 | 5.92M | static DeclGroupRef getFromOpaquePtr(void *Ptr) { |
127 | 5.92M | DeclGroupRef X; |
128 | 5.92M | X.D = static_cast<Decl*>(Ptr); |
129 | 5.92M | return X; |
130 | 5.92M | } |
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 | 13.2M | static inline void *getAsVoidPointer(clang::DeclGroupRef P) { |
143 | 13.2M | return P.getAsOpaquePtr(); |
144 | 13.2M | } |
145 | | |
146 | 5.92M | static inline clang::DeclGroupRef getFromVoidPointer(void *P) { |
147 | 5.92M | return clang::DeclGroupRef::getFromOpaquePtr(P); |
148 | 5.92M | } |
149 | | |
150 | | enum { NumLowBitsAvailable = 0 }; |
151 | | }; |
152 | | |
153 | | } // namespace llvm |
154 | | |
155 | | #endif // LLVM_CLANG_AST_DECLGROUP_H |