DeclCXX.cpp revision c0ac4923f08b25ae973a8ee7942cf3eb89da57b7
1//===--- DeclCXX.cpp - C++ Declaration AST Node Implementation ------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the C++ related Decl classes.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/DeclCXX.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/Basic/IdentifierTable.h"
17#include "llvm/ADT/STLExtras.h"
18using namespace clang;
19
20//===----------------------------------------------------------------------===//
21// Decl Allocation/Deallocation Method Implementations
22//===----------------------------------------------------------------------===//
23
24TemplateTypeParmDecl *
25TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC,
26                             SourceLocation L, IdentifierInfo *Id,
27                             bool Typename) {
28  return new (C) TemplateTypeParmDecl(DC, L, Id, Typename);
29}
30
31NonTypeTemplateParmDecl *
32NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
33                                SourceLocation L, IdentifierInfo *Id,
34                                QualType T, SourceLocation TypeSpecStartLoc) {
35  return new (C) NonTypeTemplateParmDecl(DC, L, Id, T, TypeSpecStartLoc);
36}
37
38TemplateParameterList::TemplateParameterList(Decl **Params, unsigned NumParams)
39  : NumParams(NumParams) {
40  for (unsigned Idx = 0; Idx < NumParams; ++Idx)
41    begin()[Idx] = Params[Idx];
42}
43
44TemplateParameterList *
45TemplateParameterList::Create(ASTContext &C, Decl **Params,
46                              unsigned NumParams) {
47  // FIXME: how do I pass in Size to ASTContext::new?
48  unsigned Size = sizeof(TemplateParameterList) + sizeof(Decl *) * NumParams;
49  unsigned Align = llvm::AlignOf<TemplateParameterList>::Alignment;
50  void *Mem = C.Allocate(Size, Align);
51  return new (Mem) TemplateParameterList(Params, NumParams);
52}
53
54CXXRecordDecl::CXXRecordDecl(TagKind TK, DeclContext *DC,
55                             SourceLocation L, IdentifierInfo *Id)
56  : RecordDecl(CXXRecord, TK, DC, L, Id),
57    UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
58    UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false),
59    Aggregate(true), PlainOldData(true), Polymorphic(false), Bases(0),
60    NumBases(0), Conversions(DC, DeclarationName()) { }
61
62CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
63                                     SourceLocation L, IdentifierInfo *Id,
64                                     CXXRecordDecl* PrevDecl) {
65  CXXRecordDecl* R = new (C) CXXRecordDecl(TK, DC, L, Id);
66  C.getTypeDeclType(R, PrevDecl);
67  return R;
68}
69
70CXXRecordDecl::~CXXRecordDecl() {
71  delete [] Bases;
72}
73
74void
75CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
76                        unsigned NumBases) {
77  // C++ [dcl.init.aggr]p1:
78  //   An aggregate is an array or a class (clause 9) with [...]
79  //   no base classes [...].
80  Aggregate = false;
81
82  if (this->Bases)
83    delete [] this->Bases;
84
85  this->Bases = new CXXBaseSpecifier[NumBases];
86  this->NumBases = NumBases;
87  for (unsigned i = 0; i < NumBases; ++i)
88    this->Bases[i] = *Bases[i];
89}
90
91bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
92  QualType ClassType
93    = Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this));
94  DeclarationName ConstructorName
95    = Context.DeclarationNames.getCXXConstructorName(
96                                           Context.getCanonicalType(ClassType));
97  unsigned TypeQuals;
98  DeclContext::lookup_const_iterator Con, ConEnd;
99  for (llvm::tie(Con, ConEnd) = this->lookup(ConstructorName);
100       Con != ConEnd; ++Con) {
101    if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) &&
102        (TypeQuals & QualType::Const) != 0)
103      return true;
104  }
105
106  return false;
107}
108
109bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context) const {
110  QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
111    const_cast<CXXRecordDecl*>(this)));
112  DeclarationName OpName =Context.DeclarationNames.getCXXOperatorName(OO_Equal);
113
114  DeclContext::lookup_const_iterator Op, OpEnd;
115  for (llvm::tie(Op, OpEnd) = this->lookup(OpName);
116       Op != OpEnd; ++Op) {
117    // C++ [class.copy]p9:
118    //   A user-declared copy assignment operator is a non-static non-template
119    //   member function of class X with exactly one parameter of type X, X&,
120    //   const X&, volatile X& or const volatile X&.
121    const CXXMethodDecl* Method = cast<CXXMethodDecl>(*Op);
122    if (Method->isStatic())
123      continue;
124    // TODO: Skip templates? Or is this implicitly done due to parameter types?
125    const FunctionTypeProto *FnType =
126      Method->getType()->getAsFunctionTypeProto();
127    assert(FnType && "Overloaded operator has no prototype.");
128    // Don't assert on this; an invalid decl might have been left in the AST.
129    if (FnType->getNumArgs() != 1 || FnType->isVariadic())
130      continue;
131    bool AcceptsConst = true;
132    QualType ArgType = FnType->getArgType(0);
133    if (const ReferenceType *Ref = ArgType->getAsReferenceType()) {
134      ArgType = Ref->getPointeeType();
135      // Is it a non-const reference?
136      if (!ArgType.isConstQualified())
137        AcceptsConst = false;
138    }
139    if (Context.getCanonicalType(ArgType).getUnqualifiedType() != ClassType)
140      continue;
141
142    // We have a single argument of type cv X or cv X&, i.e. we've found the
143    // copy assignment operator. Return whether it accepts const arguments.
144    return AcceptsConst;
145  }
146  assert(isInvalidDecl() &&
147         "No copy assignment operator declared in valid code.");
148  return false;
149}
150
151void
152CXXRecordDecl::addedConstructor(ASTContext &Context,
153                                CXXConstructorDecl *ConDecl) {
154  if (!ConDecl->isImplicit()) {
155    // Note that we have a user-declared constructor.
156    UserDeclaredConstructor = true;
157
158    // C++ [dcl.init.aggr]p1:
159    //   An aggregate is an array or a class (clause 9) with no
160    //   user-declared constructors (12.1) [...].
161    Aggregate = false;
162
163    // C++ [class]p4:
164    //   A POD-struct is an aggregate class [...]
165    PlainOldData = false;
166
167    // Note when we have a user-declared copy constructor, which will
168    // suppress the implicit declaration of a copy constructor.
169    if (ConDecl->isCopyConstructor(Context))
170      UserDeclaredCopyConstructor = true;
171  }
172}
173
174void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context,
175                                            CXXMethodDecl *OpDecl) {
176  // We're interested specifically in copy assignment operators.
177  // Unlike addedConstructor, this method is not called for implicit
178  // declarations.
179  const FunctionTypeProto *FnType = OpDecl->getType()->getAsFunctionTypeProto();
180  assert(FnType && "Overloaded operator has no proto function type.");
181  assert(FnType->getNumArgs() == 1 && !FnType->isVariadic());
182  QualType ArgType = FnType->getArgType(0);
183  if (const ReferenceType *Ref = ArgType->getAsReferenceType())
184    ArgType = Ref->getPointeeType();
185
186  ArgType = ArgType.getUnqualifiedType();
187  QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
188    const_cast<CXXRecordDecl*>(this)));
189
190  if (ClassType != Context.getCanonicalType(ArgType))
191    return;
192
193  // This is a copy assignment operator.
194  // Suppress the implicit declaration of a copy constructor.
195  UserDeclaredCopyAssignment = true;
196
197  // C++ [class]p4:
198  //   A POD-struct is an aggregate class that [...] has no user-defined copy
199  //   assignment operator [...].
200  PlainOldData = false;
201}
202
203void CXXRecordDecl::addConversionFunction(ASTContext &Context,
204                                          CXXConversionDecl *ConvDecl) {
205  Conversions.addOverload(ConvDecl);
206}
207
208CXXMethodDecl *
209CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
210                      SourceLocation L, DeclarationName N,
211                      QualType T, bool isStatic, bool isInline) {
212  return new (C) CXXMethodDecl(CXXMethod, RD, L, N, T, isStatic, isInline);
213}
214
215QualType CXXMethodDecl::getThisType(ASTContext &C) const {
216  // C++ 9.3.2p1: The type of this in a member function of a class X is X*.
217  // If the member function is declared const, the type of this is const X*,
218  // if the member function is declared volatile, the type of this is
219  // volatile X*, and if the member function is declared const volatile,
220  // the type of this is const volatile X*.
221
222  assert(isInstance() && "No 'this' for static methods!");
223  QualType ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
224  ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers());
225  return C.getPointerType(ClassTy).withConst();
226}
227
228CXXBaseOrMemberInitializer::
229CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs)
230  : Args(0), NumArgs(0) {
231  BaseOrMember = reinterpret_cast<uintptr_t>(BaseType.getTypePtr());
232  assert((BaseOrMember & 0x01) == 0 && "Invalid base class type pointer");
233  BaseOrMember |= 0x01;
234
235  if (NumArgs > 0) {
236    this->NumArgs = NumArgs;
237    this->Args = new Expr*[NumArgs];
238    for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
239      this->Args[Idx] = Args[Idx];
240  }
241}
242
243CXXBaseOrMemberInitializer::
244CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs)
245  : Args(0), NumArgs(0) {
246  BaseOrMember = reinterpret_cast<uintptr_t>(Member);
247  assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer");
248
249  if (NumArgs > 0) {
250    this->NumArgs = NumArgs;
251    this->Args = new Expr*[NumArgs];
252    for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
253      this->Args[Idx] = Args[Idx];
254  }
255}
256
257CXXBaseOrMemberInitializer::~CXXBaseOrMemberInitializer() {
258  delete [] Args;
259}
260
261CXXConstructorDecl *
262CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
263                           SourceLocation L, DeclarationName N,
264                           QualType T, bool isExplicit,
265                           bool isInline, bool isImplicitlyDeclared) {
266  assert(N.getNameKind() == DeclarationName::CXXConstructorName &&
267         "Name must refer to a constructor");
268  return new (C) CXXConstructorDecl(RD, L, N, T, isExplicit, isInline,
269                                      isImplicitlyDeclared);
270}
271
272bool CXXConstructorDecl::isDefaultConstructor() const {
273  // C++ [class.ctor]p5:
274  //   A default constructor for a class X is a constructor of class
275  //   X that can be called without an argument.
276  return (getNumParams() == 0) ||
277         (getNumParams() > 0 && getParamDecl(0)->getDefaultArg() != 0);
278}
279
280bool
281CXXConstructorDecl::isCopyConstructor(ASTContext &Context,
282                                      unsigned &TypeQuals) const {
283  // C++ [class.copy]p2:
284  //   A non-template constructor for class X is a copy constructor
285  //   if its first parameter is of type X&, const X&, volatile X& or
286  //   const volatile X&, and either there are no other parameters
287  //   or else all other parameters have default arguments (8.3.6).
288  if ((getNumParams() < 1) ||
289      (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() == 0))
290    return false;
291
292  const ParmVarDecl *Param = getParamDecl(0);
293
294  // Do we have a reference type?
295  const ReferenceType *ParamRefType = Param->getType()->getAsReferenceType();
296  if (!ParamRefType)
297    return false;
298
299  // Is it a reference to our class type?
300  QualType PointeeType
301    = Context.getCanonicalType(ParamRefType->getPointeeType());
302  QualType ClassTy
303    = Context.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
304  if (PointeeType.getUnqualifiedType() != ClassTy)
305    return false;
306
307  // We have a copy constructor.
308  TypeQuals = PointeeType.getCVRQualifiers();
309  return true;
310}
311
312bool CXXConstructorDecl::isConvertingConstructor() const {
313  // C++ [class.conv.ctor]p1:
314  //   A constructor declared without the function-specifier explicit
315  //   that can be called with a single parameter specifies a
316  //   conversion from the type of its first parameter to the type of
317  //   its class. Such a constructor is called a converting
318  //   constructor.
319  if (isExplicit())
320    return false;
321
322  return (getNumParams() == 0 &&
323          getType()->getAsFunctionTypeProto()->isVariadic()) ||
324         (getNumParams() == 1) ||
325         (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() != 0);
326}
327
328CXXDestructorDecl *
329CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
330                          SourceLocation L, DeclarationName N,
331                          QualType T, bool isInline,
332                          bool isImplicitlyDeclared) {
333  assert(N.getNameKind() == DeclarationName::CXXDestructorName &&
334         "Name must refer to a destructor");
335  return new (C) CXXDestructorDecl(RD, L, N, T, isInline,
336                                   isImplicitlyDeclared);
337}
338
339CXXConversionDecl *
340CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
341                          SourceLocation L, DeclarationName N,
342                          QualType T, bool isInline, bool isExplicit) {
343  assert(N.getNameKind() == DeclarationName::CXXConversionFunctionName &&
344         "Name must refer to a conversion function");
345  return new (C) CXXConversionDecl(RD, L, N, T, isInline, isExplicit);
346}
347
348CXXClassVarDecl *CXXClassVarDecl::Create(ASTContext &C, CXXRecordDecl *RD,
349                                   SourceLocation L, IdentifierInfo *Id,
350                                   QualType T) {
351  return new (C) CXXClassVarDecl(RD, L, Id, T);
352}
353
354OverloadedFunctionDecl *
355OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC,
356                               DeclarationName N) {
357  return new (C) OverloadedFunctionDecl(DC, N);
358}
359
360LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
361                                         DeclContext *DC,
362                                         SourceLocation L,
363                                         LanguageIDs Lang, bool Braces) {
364  return new (C) LinkageSpecDecl(DC, L, Lang, Braces);
365}
366