clang  9.0.0svn
ItaniumCXXABI.cpp
Go to the documentation of this file.
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"
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 static const IdentifierInfo *findAnonymousUnionVarDeclName(const VarDecl& VD) {
43  const RecordType *RT = VD.getType()->getAs<RecordType>();
44  assert(RT && "type of VarDecl is expected to be RecordType.");
45  assert(RT->getDecl()->isUnion() && "RecordType is expected to be a union.");
46  if (const FieldDecl *FD = RT->getDecl()->findFirstNamedDataMember()) {
47  return FD->getIdentifier();
48  }
49 
50  return nullptr;
51 }
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  Iterator(BindingArray::const_iterator It) : iterator_adaptor_base(It) {}
66  const IdentifierInfo *operator*() const {
67  return (*this->I)->getIdentifier();
68  }
69  };
70  Iterator begin() const { return Iterator(Bindings.begin()); }
71  Iterator end() const { return Iterator(Bindings.end()); }
72 };
73 }
74 
75 namespace llvm {
76 template<>
77 struct DenseMapInfo<DecompositionDeclName> {
80  static DecompositionDeclName getEmptyKey() {
81  return {ArrayInfo::getEmptyKey()};
82  }
83  static DecompositionDeclName getTombstoneKey() {
84  return {ArrayInfo::getTombstoneKey()};
85  }
86  static unsigned getHashValue(DecompositionDeclName Key) {
87  assert(!isEqual(Key, getEmptyKey()) && !isEqual(Key, getTombstoneKey()));
88  return llvm::hash_combine_range(Key.begin(), Key.end());
89  }
90  static bool isEqual(DecompositionDeclName LHS, DecompositionDeclName RHS) {
91  if (ArrayInfo::isEqual(LHS.Bindings, ArrayInfo::getEmptyKey()))
92  return ArrayInfo::isEqual(RHS.Bindings, ArrayInfo::getEmptyKey());
93  if (ArrayInfo::isEqual(LHS.Bindings, ArrayInfo::getTombstoneKey()))
94  return ArrayInfo::isEqual(RHS.Bindings, ArrayInfo::getTombstoneKey());
95  return LHS.Bindings.size() == RHS.Bindings.size() &&
96  std::equal(LHS.begin(), LHS.end(), RHS.begin());
97  }
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  unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override {
114  const FunctionProtoType *Proto =
115  CallOperator->getType()->getAs<FunctionProtoType>();
116  ASTContext &Context = CallOperator->getASTContext();
117 
119  EPI.Variadic = Proto->isVariadic();
120  QualType Key =
121  Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), EPI);
122  Key = Context.getCanonicalType(Key);
123  return ++ManglingNumbers[Key->castAs<FunctionProtoType>()];
124  }
125 
126  unsigned getManglingNumber(const BlockDecl *BD) override {
127  const Type *Ty = nullptr;
128  return ++ManglingNumbers[Ty];
129  }
130 
131  unsigned getStaticLocalNumber(const VarDecl *VD) override {
132  return 0;
133  }
134 
135  /// Variable decls are numbered by identifier.
136  unsigned getManglingNumber(const VarDecl *VD, unsigned) override {
137  if (auto *DD = dyn_cast<DecompositionDecl>(VD)) {
138  DecompositionDeclName Name{DD->bindings()};
139  return ++DecompsitionDeclManglingNumbers[Name];
140  }
141 
142  const IdentifierInfo *Identifier = VD->getIdentifier();
143  if (!Identifier) {
144  // VarDecl without an identifier represents an anonymous union
145  // declaration.
146  Identifier = findAnonymousUnionVarDeclName(*VD);
147  }
148  return ++VarManglingNumbers[Identifier];
149  }
150 
151  unsigned getManglingNumber(const TagDecl *TD, unsigned) override {
152  return ++TagManglingNumbers[TD->getIdentifier()];
153  }
154 };
155 
156 class ItaniumCXXABI : public CXXABI {
157 protected:
158  ASTContext &Context;
159 public:
160  ItaniumCXXABI(ASTContext &Ctx) : Context(Ctx) { }
161 
162  MemberPointerInfo
163  getMemberPointerInfo(const MemberPointerType *MPT) const override {
164  const TargetInfo &Target = Context.getTargetInfo();
165  TargetInfo::IntType PtrDiff = Target.getPtrDiffType(0);
166  MemberPointerInfo MPI;
167  MPI.Width = Target.getTypeWidth(PtrDiff);
168  MPI.Align = Target.getTypeAlign(PtrDiff);
169  MPI.HasPadding = false;
170  if (MPT->isMemberFunctionPointer())
171  MPI.Width *= 2;
172  return MPI;
173  }
174 
175  CallingConv getDefaultMethodCallConv(bool isVariadic) const override {
176  const llvm::Triple &T = Context.getTargetInfo().getTriple();
177  if (!isVariadic && T.isWindowsGNUEnvironment() &&
178  T.getArch() == llvm::Triple::x86)
179  return CC_X86ThisCall;
180  return CC_C;
181  }
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  bool isNearlyEmpty(const CXXRecordDecl *RD) const override {
186 
187  // Check that the class has a vtable pointer.
188  if (!RD->isDynamicClass())
189  return false;
190 
191  const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
192  CharUnits PointerSize =
193  Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0));
194  return Layout.getNonVirtualSize() == PointerSize;
195  }
196 
197  const CXXConstructorDecl *
198  getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override {
199  return nullptr;
200  }
201 
202  void addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
203  CXXConstructorDecl *CD) override {}
204 
205  void addTypedefNameForUnnamedTagDecl(TagDecl *TD,
206  TypedefNameDecl *DD) override {}
207 
208  TypedefNameDecl *getTypedefNameForUnnamedTagDecl(const TagDecl *TD) override {
209  return nullptr;
210  }
211 
212  void addDeclaratorForUnnamedTagDecl(TagDecl *TD,
213  DeclaratorDecl *DD) override {}
214 
215  DeclaratorDecl *getDeclaratorForUnnamedTagDecl(const TagDecl *TD) override {
216  return nullptr;
217  }
218 
219  std::unique_ptr<MangleNumberingContext>
220  createMangleNumberingContext() const override {
221  return llvm::make_unique<ItaniumNumberingContext>();
222  }
223 };
224 }
225 
227  return new ItaniumCXXABI(Ctx);
228 }
Defines the clang::ASTContext interface.
unsigned getTypeWidth(IntType T) const
Return the width (in bits) of the specified integer type enum.
Definition: TargetInfo.cpp:213
StringRef Identifier
Definition: Format.cpp:1714
A (possibly-)qualified type.
Definition: Type.h:639
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
Definition: Dominators.h:29
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D...
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:983
C Language Family Type Representation.
bool isVariadic() const
Whether this function prototype is variadic.
Definition: Type.h:4014
The base class of the type hierarchy.
Definition: Type.h:1414
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:690
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2562
Represents a variable declaration or definition.
Definition: Decl.h:812
const T * getAs() const
Member-template getAs<specific type>&#39;.
Definition: Type.h:6805
Extra information about a function prototype.
Definition: Type.h:3779
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:269
uint64_t getPointerWidth(unsigned AddrSpace) const
Return the width of pointers on this target, for the specified address space.
Definition: TargetInfo.h:358
One of these records is kept for each identifier that is lexed.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:154
ArrayRef< QualType > getParamTypes() const
Definition: Type.h:3907
Represents a member of a struct/union/class.
Definition: Decl.h:2584
static DecompositionDeclName getTombstoneKey()
clang::CharUnits operator*(clang::CharUnits::QuantityType Scale, const clang::CharUnits &CU)
Definition: CharUnits.h:207
static bool isEqual(DecompositionDeclName LHS, DecompositionDeclName RHS)
CharUnits - This is an opaque type for sizes expressed in character units.
Definition: CharUnits.h:37
Keeps track of the mangled names of lambda expressions and block literals within a particular context...
CXXABI * CreateItaniumCXXABI(ASTContext &Ctx)
Creates an instance of a C++ ABI class.
static unsigned getHashValue(DecompositionDeclName Key)
Represents a prototype with parameter type info, e.g.
Definition: Type.h:3699
bool isDynamicClass() const
Definition: DeclCXX.h:788
Represents a ValueDecl that came out of a declarator.
Definition: Decl.h:688
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
Definition: RecordLayout.h:38
Exposes information about the current target.
Definition: TargetInfo.h:161
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Definition: Decl.h:3863
const FieldDecl * findFirstNamedDataMember() const
Finds the first data member which has a name.
Definition: Decl.cpp:4335
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:6870
static DecompositionDeclName getEmptyKey()
Implements C++ ABI-specific semantic analysis functions.
Definition: CXXABI.h:29
CallingConv
CallingConv - Specifies the calling convention that a function uses.
Definition: Specifiers.h:243
unsigned getTypeAlign(IntType T) const
Return the alignment (in bits) of the specified integer type enum.
Definition: TargetInfo.cpp:284
RecordDecl * getDecl() const
Definition: Type.h:4427
IntType getPtrDiffType(unsigned AddrSpace) const
Definition: TargetInfo.h:287
QualType getCanonicalType() const
Definition: Type.h:6160
Represents the declaration of a struct/union/class/enum.
Definition: Decl.h:3069
ASTContext & getASTContext() const LLVM_READONLY
Definition: DeclBase.cpp:376
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2108
IntType
===-— Target Data Type Query Methods ----------------------------—===//
Definition: TargetInfo.h:104
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:2921
Dataflow Directional Tag Classes.
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition: Type.h:2768
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:4417
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
Represents a C++ struct/union/class.
Definition: DeclCXX.h:299
bool isMemberFunctionPointer() const
Returns true if the member type (i.e.
Definition: Type.h:2792
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
Definition: RecordLayout.h:202
Defines the clang::TargetInfo interface.
bool isUnion() const
Definition: Decl.h:3257
QualType getType() const
Definition: Decl.h:647