DeclCXX.cpp revision f44515a49b549171dc3ee9faa6281b72609da563
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"
17using namespace clang;
18
19//===----------------------------------------------------------------------===//
20// Decl Allocation/Deallocation Method Implementations
21//===----------------------------------------------------------------------===//
22
23TemplateTypeParmDecl *
24TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC,
25                             SourceLocation L, IdentifierInfo *Id,
26                             bool Typename) {
27  void *Mem = C.getAllocator().Allocate<TemplateTypeParmDecl>();
28  return new (Mem) 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  void *Mem = C.getAllocator().Allocate<NonTypeTemplateParmDecl>();
36  return new (Mem) NonTypeTemplateParmDecl(DC, L, Id, T, TypeSpecStartLoc);
37}
38
39CXXRecordDecl::CXXRecordDecl(TagKind TK, DeclContext *DC,
40                             SourceLocation L, IdentifierInfo *Id)
41  : RecordDecl(CXXRecord, TK, DC, L, Id),
42    UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
43    UserDeclaredDestructor(false), Aggregate(true), Polymorphic(false),
44    Bases(0), NumBases(0),
45    Conversions(DC, DeclarationName()) { }
46
47CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
48                                     SourceLocation L, IdentifierInfo *Id,
49                                     CXXRecordDecl* PrevDecl) {
50  void *Mem = C.getAllocator().Allocate<CXXRecordDecl>();
51  CXXRecordDecl* R = new (Mem) CXXRecordDecl(TK, DC, L, Id);
52  C.getTypeDeclType(R, PrevDecl);
53  return R;
54}
55
56CXXRecordDecl::~CXXRecordDecl() {
57  delete [] Bases;
58}
59
60void
61CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
62                        unsigned NumBases) {
63  // C++ [dcl.init.aggr]p1:
64  //   An aggregate is an array or a class (clause 9) with [...]
65  //   no base classes [...].
66  Aggregate = false;
67
68  if (this->Bases)
69    delete [] this->Bases;
70
71  this->Bases = new CXXBaseSpecifier[NumBases];
72  this->NumBases = NumBases;
73  for (unsigned i = 0; i < NumBases; ++i)
74    this->Bases[i] = *Bases[i];
75}
76
77bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
78  QualType ClassType = Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this));
79  DeclarationName ConstructorName
80    = Context.DeclarationNames.getCXXConstructorName(
81                                           Context.getCanonicalType(ClassType));
82  unsigned TypeQuals;
83  DeclContext::lookup_const_result Lookup
84    = this->lookup(Context, ConstructorName);
85  if (Lookup.first == Lookup.second)
86    return false;
87  else if (OverloadedFunctionDecl *Constructors
88             = dyn_cast<OverloadedFunctionDecl>(*Lookup.first)) {
89    for (OverloadedFunctionDecl::function_const_iterator Con
90           = Constructors->function_begin();
91         Con != Constructors->function_end(); ++Con) {
92    if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) &&
93        (TypeQuals & QualType::Const) != 0)
94      return true;
95    }
96  } else if (CXXConstructorDecl *Constructor
97               = dyn_cast<CXXConstructorDecl>(*Lookup.first)) {
98    return Constructor->isCopyConstructor(Context, TypeQuals) &&
99           (TypeQuals & QualType::Const) != 0;
100  }
101  return false;
102}
103
104void
105CXXRecordDecl::addedConstructor(ASTContext &Context,
106                                CXXConstructorDecl *ConDecl) {
107  if (!ConDecl->isImplicitlyDeclared()) {
108    // Note that we have a user-declared constructor.
109    UserDeclaredConstructor = true;
110
111    // C++ [dcl.init.aggr]p1:
112    //   An aggregate is an array or a class (clause 9) with no
113    //   user-declared constructors (12.1) [...].
114    Aggregate = false;
115
116    // Note when we have a user-declared copy constructor, which will
117    // suppress the implicit declaration of a copy constructor.
118    if (ConDecl->isCopyConstructor(Context))
119      UserDeclaredCopyConstructor = true;
120  }
121}
122
123void CXXRecordDecl::addConversionFunction(ASTContext &Context,
124                                          CXXConversionDecl *ConvDecl) {
125  Conversions.addOverload(ConvDecl);
126}
127
128CXXMethodDecl *
129CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
130                      SourceLocation L, DeclarationName N,
131                      QualType T, bool isStatic, bool isInline,
132                      ScopedDecl *PrevDecl) {
133  void *Mem = C.getAllocator().Allocate<CXXMethodDecl>();
134  return new (Mem) CXXMethodDecl(CXXMethod, RD, L, N, T, isStatic, isInline,
135                                 PrevDecl);
136}
137
138QualType CXXMethodDecl::getThisType(ASTContext &C) const {
139  // C++ 9.3.2p1: The type of this in a member function of a class X is X*.
140  // If the member function is declared const, the type of this is const X*,
141  // if the member function is declared volatile, the type of this is
142  // volatile X*, and if the member function is declared const volatile,
143  // the type of this is const volatile X*.
144
145  assert(isInstance() && "No 'this' for static methods!");
146  QualType ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
147  ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers());
148  return C.getPointerType(ClassTy).withConst();
149}
150
151CXXBaseOrMemberInitializer::
152CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs)
153  : Args(0), NumArgs(0) {
154  BaseOrMember = reinterpret_cast<uintptr_t>(BaseType.getTypePtr());
155  assert((BaseOrMember & 0x01) == 0 && "Invalid base class type pointer");
156  BaseOrMember |= 0x01;
157
158  if (NumArgs > 0) {
159    this->NumArgs = NumArgs;
160    this->Args = new Expr*[NumArgs];
161    for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
162      this->Args[Idx] = Args[Idx];
163  }
164}
165
166CXXBaseOrMemberInitializer::
167CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs)
168  : Args(0), NumArgs(0) {
169  BaseOrMember = reinterpret_cast<uintptr_t>(Member);
170  assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer");
171
172  if (NumArgs > 0) {
173    this->NumArgs = NumArgs;
174    this->Args = new Expr*[NumArgs];
175    for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
176      this->Args[Idx] = Args[Idx];
177  }
178}
179
180CXXBaseOrMemberInitializer::~CXXBaseOrMemberInitializer() {
181  delete [] Args;
182}
183
184CXXConstructorDecl *
185CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
186                           SourceLocation L, DeclarationName N,
187                           QualType T, bool isExplicit,
188                           bool isInline, bool isImplicitlyDeclared) {
189  assert(N.getNameKind() == DeclarationName::CXXConstructorName &&
190         "Name must refer to a constructor");
191  void *Mem = C.getAllocator().Allocate<CXXConstructorDecl>();
192  return new (Mem) CXXConstructorDecl(RD, L, N, T, isExplicit, isInline,
193                                      isImplicitlyDeclared);
194}
195
196bool CXXConstructorDecl::isDefaultConstructor() const {
197  // C++ [class.ctor]p5:
198  //   A default constructor for a class X is a constructor of class
199  //   X that can be called without an argument.
200  return (getNumParams() == 0) ||
201         (getNumParams() > 0 && getParamDecl(0)->getDefaultArg() != 0);
202}
203
204bool
205CXXConstructorDecl::isCopyConstructor(ASTContext &Context,
206                                      unsigned &TypeQuals) const {
207  // C++ [class.copy]p2:
208  //   A non-template constructor for class X is a copy constructor
209  //   if its first parameter is of type X&, const X&, volatile X& or
210  //   const volatile X&, and either there are no other parameters
211  //   or else all other parameters have default arguments (8.3.6).
212  if ((getNumParams() < 1) ||
213      (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() == 0))
214    return false;
215
216  const ParmVarDecl *Param = getParamDecl(0);
217
218  // Do we have a reference type?
219  const ReferenceType *ParamRefType = Param->getType()->getAsReferenceType();
220  if (!ParamRefType)
221    return false;
222
223  // Is it a reference to our class type?
224  QualType PointeeType
225    = Context.getCanonicalType(ParamRefType->getPointeeType());
226  QualType ClassTy
227    = Context.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
228  if (PointeeType.getUnqualifiedType() != ClassTy)
229    return false;
230
231  // We have a copy constructor.
232  TypeQuals = PointeeType.getCVRQualifiers();
233  return true;
234}
235
236bool CXXConstructorDecl::isConvertingConstructor() const {
237  // C++ [class.conv.ctor]p1:
238  //   A constructor declared without the function-specifier explicit
239  //   that can be called with a single parameter specifies a
240  //   conversion from the type of its first parameter to the type of
241  //   its class. Such a constructor is called a converting
242  //   constructor.
243  if (isExplicit())
244    return false;
245
246  return (getNumParams() == 0 &&
247          getType()->getAsFunctionTypeProto()->isVariadic()) ||
248         (getNumParams() == 1) ||
249         (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() != 0);
250}
251
252CXXDestructorDecl *
253CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
254                          SourceLocation L, DeclarationName N,
255                          QualType T, bool isInline,
256                          bool isImplicitlyDeclared) {
257  assert(N.getNameKind() == DeclarationName::CXXDestructorName &&
258         "Name must refer to a destructor");
259  void *Mem = C.getAllocator().Allocate<CXXDestructorDecl>();
260  return new (Mem) CXXDestructorDecl(RD, L, N, T, isInline,
261                                     isImplicitlyDeclared);
262}
263
264CXXConversionDecl *
265CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
266                          SourceLocation L, DeclarationName N,
267                          QualType T, bool isInline, bool isExplicit) {
268  assert(N.getNameKind() == DeclarationName::CXXConversionFunctionName &&
269         "Name must refer to a conversion function");
270  void *Mem = C.getAllocator().Allocate<CXXConversionDecl>();
271  return new (Mem) CXXConversionDecl(RD, L, N, T, isInline, isExplicit);
272}
273
274CXXClassVarDecl *CXXClassVarDecl::Create(ASTContext &C, CXXRecordDecl *RD,
275                                   SourceLocation L, IdentifierInfo *Id,
276                                   QualType T, ScopedDecl *PrevDecl) {
277  void *Mem = C.getAllocator().Allocate<CXXClassVarDecl>();
278  return new (Mem) CXXClassVarDecl(RD, L, Id, T, PrevDecl);
279}
280
281OverloadedFunctionDecl *
282OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC,
283                               DeclarationName N) {
284  void *Mem = C.getAllocator().Allocate<OverloadedFunctionDecl>();
285  return new (Mem) OverloadedFunctionDecl(DC, N);
286}
287
288LinkageSpecDecl::LinkageSpecDecl(SourceLocation L, LanguageIDs lang,
289                                 Decl **InDecls, unsigned InNumDecls)
290  : Decl(LinkageSpec, L), Language(lang), HadBraces(true),
291    Decls(0), NumDecls(InNumDecls) {
292  Decl **NewDecls = new Decl*[NumDecls];
293  for (unsigned I = 0; I < NumDecls; ++I)
294    NewDecls[I] = InDecls[I];
295  Decls = NewDecls;
296}
297
298LinkageSpecDecl::~LinkageSpecDecl() {
299  if (HadBraces)
300    delete [] (Decl**)Decls;
301}
302
303LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
304                                         SourceLocation L,
305                                         LanguageIDs Lang, Decl *D) {
306  void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>();
307  return new (Mem) LinkageSpecDecl(L, Lang, D);
308}
309
310LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
311                                         SourceLocation L,
312                                         LanguageIDs Lang,
313                                         Decl **Decls, unsigned NumDecls) {
314  void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>();
315  return new (Mem) LinkageSpecDecl(L, Lang, Decls, NumDecls);
316}
317
318LinkageSpecDecl::decl_const_iterator LinkageSpecDecl::decls_begin() const {
319  if (hasBraces()) return (Decl**)Decls;
320  else return (Decl**)&Decls;
321}
322
323LinkageSpecDecl::decl_iterator LinkageSpecDecl::decls_end() const {
324  if (hasBraces()) return (Decl**)Decls + NumDecls;
325  else return (Decl**)&Decls + 1;
326}
327