Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/lib/AST/ItaniumCXXABI.cpp
Line
Count
Source (jump to first uncovered line)
1
//===------- ItaniumCXXABI.cpp - AST support for the Itanium C++ ABI ------===//
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 provides C++ AST support targeting the Itanium C++ ABI, which is
10
// documented at:
11
//  http://www.codesourcery.com/public/cxx-abi/abi.html
12
//  http://www.codesourcery.com/public/cxx-abi/abi-eh.html
13
//
14
// It also supports the closely-related ARM C++ ABI, documented at:
15
// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0041c/IHI0041C_cppabi.pdf
16
//
17
//===----------------------------------------------------------------------===//
18
19
#include "CXXABI.h"
20
#include "clang/AST/ASTContext.h"
21
#include "clang/AST/DeclCXX.h"
22
#include "clang/AST/MangleNumberingContext.h"
23
#include "clang/AST/RecordLayout.h"
24
#include "clang/AST/Type.h"
25
#include "clang/Basic/TargetInfo.h"
26
#include "llvm/ADT/iterator.h"
27
28
using namespace clang;
29
30
namespace {
31
32
/// According to Itanium C++ ABI 5.1.2:
33
/// the name of an anonymous union is considered to be
34
/// the name of the first named data member found by a pre-order,
35
/// depth-first, declaration-order walk of the data members of
36
/// the anonymous union.
37
/// If there is no such data member (i.e., if all of the data members
38
/// in the union are unnamed), then there is no way for a program to
39
/// refer to the anonymous union, and there is therefore no need to mangle its name.
40
///
41
/// Returns the name of anonymous union VarDecl or nullptr if it is not found.
42
6
static const IdentifierInfo *findAnonymousUnionVarDeclName(const VarDecl& VD) {
43
6
  const RecordType *RT = VD.getType()->getAs<RecordType>();
44
6
  assert(RT && "type of VarDecl is expected to be RecordType.");
45
6
  assert(RT->getDecl()->isUnion() && "RecordType is expected to be a union.");
46
6
  if (const FieldDecl *FD = RT->getDecl()->findFirstNamedDataMember()) {
47
5
    return FD->getIdentifier();
48
5
  }
49
1
50
1
  return nullptr;
51
1
}
52
53
/// The name of a decomposition declaration.
54
struct DecompositionDeclName {
55
  using BindingArray = ArrayRef<const BindingDecl*>;
56
57
  /// Representative example of a set of bindings with these names.
58
  BindingArray Bindings;
59
60
  /// Iterators over the sequence of identifiers in the name.
61
  struct Iterator
62
      : llvm::iterator_adaptor_base<Iterator, BindingArray::const_iterator,
63
                                    std::random_access_iterator_tag,
64
                                    const IdentifierInfo *> {
65
2
    Iterator(BindingArray::const_iterator It) : iterator_adaptor_base(It) {}
66
1
    const IdentifierInfo *operator*() const {
67
1
      return (*this->I)->getIdentifier();
68
1
    }
69
  };
70
1
  Iterator begin() const { return Iterator(Bindings.begin()); }
71
1
  Iterator end() const { return Iterator(Bindings.end()); }
72
};
73
}
74
75
namespace llvm {
76
template<>
77
struct DenseMapInfo<DecompositionDeclName> {
78
  using ArrayInfo = llvm::DenseMapInfo<ArrayRef<const BindingDecl*>>;
79
  using IdentInfo = llvm::DenseMapInfo<const IdentifierInfo*>;
80
4
  static DecompositionDeclName getEmptyKey() {
81
4
    return {ArrayInfo::getEmptyKey()};
82
4
  }
83
2
  static DecompositionDeclName getTombstoneKey() {
84
2
    return {ArrayInfo::getTombstoneKey()};
85
2
  }
86
1
  static unsigned getHashValue(DecompositionDeclName Key) {
87
1
    assert(!isEqual(Key, getEmptyKey()) && !isEqual(Key, getTombstoneKey()));
88
1
    return llvm::hash_combine_range(Key.begin(), Key.end());
89
1
  }
90
68
  static bool isEqual(DecompositionDeclName LHS, DecompositionDeclName RHS) {
91
68
    if (ArrayInfo::isEqual(LHS.Bindings, ArrayInfo::getEmptyKey()))
92
65
      return ArrayInfo::isEqual(RHS.Bindings, ArrayInfo::getEmptyKey());
93
3
    if (ArrayInfo::isEqual(LHS.Bindings, ArrayInfo::getTombstoneKey()))
94
0
      return ArrayInfo::isEqual(RHS.Bindings, ArrayInfo::getTombstoneKey());
95
3
    return LHS.Bindings.size() == RHS.Bindings.size() &&
96
3
           
std::equal(LHS.begin(), LHS.end(), RHS.begin())0
;
97
3
  }
98
};
99
}
100
101
namespace {
102
103
/// Keeps track of the mangled names of lambda expressions and block
104
/// literals within a particular context.
105
class ItaniumNumberingContext : public MangleNumberingContext {
106
  llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
107
  llvm::DenseMap<const IdentifierInfo *, unsigned> VarManglingNumbers;
108
  llvm::DenseMap<const IdentifierInfo *, unsigned> TagManglingNumbers;
109
  llvm::DenseMap<DecompositionDeclName, unsigned>
110
      DecompsitionDeclManglingNumbers;
111
112
public:
113
4.24k
  unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override {
114
4.24k
    const FunctionProtoType *Proto =
115
4.24k
        CallOperator->getType()->getAs<FunctionProtoType>();
116
4.24k
    ASTContext &Context = CallOperator->getASTContext();
117
4.24k
118
4.24k
    FunctionProtoType::ExtProtoInfo EPI;
119
4.24k
    EPI.Variadic = Proto->isVariadic();
120
4.24k
    QualType Key =
121
4.24k
        Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), EPI);
122
4.24k
    Key = Context.getCanonicalType(Key);
123
4.24k
    return ++ManglingNumbers[Key->castAs<FunctionProtoType>()];
124
4.24k
  }
125
126
186
  unsigned getManglingNumber(const BlockDecl *BD) override {
127
186
    const Type *Ty = nullptr;
128
186
    return ++ManglingNumbers[Ty];
129
186
  }
130
131
3.06k
  unsigned getStaticLocalNumber(const VarDecl *VD) override {
132
3.06k
    return 0;
133
3.06k
  }
134
135
  /// Variable decls are numbered by identifier.
136
3.06k
  unsigned getManglingNumber(const VarDecl *VD, unsigned) override {
137
3.06k
    if (auto *DD = dyn_cast<DecompositionDecl>(VD)) {
138
1
      DecompositionDeclName Name{DD->bindings()};
139
1
      return ++DecompsitionDeclManglingNumbers[Name];
140
1
    }
141
3.06k
142
3.06k
    const IdentifierInfo *Identifier = VD->getIdentifier();
143
3.06k
    if (!Identifier) {
144
6
      // VarDecl without an identifier represents an anonymous union
145
6
      // declaration.
146
6
      Identifier = findAnonymousUnionVarDeclName(*VD);
147
6
    }
148
3.06k
    return ++VarManglingNumbers[Identifier];
149
3.06k
  }
150
151
35.3k
  unsigned getManglingNumber(const TagDecl *TD, unsigned) override {
152
35.3k
    return ++TagManglingNumbers[TD->getIdentifier()];
153
35.3k
  }
154
};
155
156
class ItaniumCXXABI : public CXXABI {
157
protected:
158
  ASTContext &Context;
159
public:
160
25.5k
  ItaniumCXXABI(ASTContext &Ctx) : Context(Ctx) { }
161
162
  MemberPointerInfo
163
813
  getMemberPointerInfo(const MemberPointerType *MPT) const override {
164
813
    const TargetInfo &Target = Context.getTargetInfo();
165
813
    TargetInfo::IntType PtrDiff = Target.getPtrDiffType(0);
166
813
    MemberPointerInfo MPI;
167
813
    MPI.Width = Target.getTypeWidth(PtrDiff);
168
813
    MPI.Align = Target.getTypeAlign(PtrDiff);
169
813
    MPI.HasPadding = false;
170
813
    if (MPT->isMemberFunctionPointer())
171
690
      MPI.Width *= 2;
172
813
    return MPI;
173
813
  }
174
175
3.55M
  CallingConv getDefaultMethodCallConv(bool isVariadic) const override {
176
3.55M
    const llvm::Triple &T = Context.getTargetInfo().getTriple();
177
3.55M
    if (!isVariadic && 
T.isWindowsGNUEnvironment()3.53M
&&
178
3.55M
        
T.getArch() == llvm::Triple::x866.79k
)
179
4.01k
      return CC_X86ThisCall;
180
3.55M
    return CC_C;
181
3.55M
  }
182
183
  // We cheat and just check that the class has a vtable pointer, and that it's
184
  // only big enough to have a vtable pointer and nothing more (or less).
185
2.36k
  bool isNearlyEmpty(const CXXRecordDecl *RD) const override {
186
2.36k
187
2.36k
    // Check that the class has a vtable pointer.
188
2.36k
    if (!RD->isDynamicClass())
189
404
      return false;
190
1.96k
191
1.96k
    const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
192
1.96k
    CharUnits PointerSize =
193
1.96k
      Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
194
1.96k
    return Layout.getNonVirtualSize() == PointerSize;
195
1.96k
  }
196
197
  const CXXConstructorDecl *
198
0
  getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override {
199
0
    return nullptr;
200
0
  }
201
202
  void addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
203
0
                                            CXXConstructorDecl *CD) override {}
204
205
  void addTypedefNameForUnnamedTagDecl(TagDecl *TD,
206
123
                                       TypedefNameDecl *DD) override {}
207
208
1.13M
  TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD) override {
209
1.13M
    return nullptr;
210
1.13M
  }
211
212
  void addDeclaratorForUnnamedTagDecl(TagDecl *TD,
213
9.49k
                                      DeclaratorDecl *DD) override {}
214
215
1.13M
  DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) override {
216
1.13M
    return nullptr;
217
1.13M
  }
218
219
  std::unique_ptr<MangleNumberingContext>
220
28.6k
  createMangleNumberingContext() const override {
221
28.6k
    return llvm::make_unique<ItaniumNumberingContext>();
222
28.6k
  }
223
};
224
}
225
226
25.5k
CXXABI *clang::CreateItaniumCXXABI(ASTContext &Ctx) {
227
25.5k
  return new ItaniumCXXABI(Ctx);
228
25.5k
}