blob: b2878b667aa74d9c320689ac97e5fcb213504a30 [file] [log] [blame]
Ted Kremenek4b7c9832008-09-05 17:16:31 +00001//===--- 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"
16using namespace clang;
17
18//===----------------------------------------------------------------------===//
19// Decl Allocation/Deallocation Method Implementations
20//===----------------------------------------------------------------------===//
21
22CXXFieldDecl *CXXFieldDecl::Create(ASTContext &C, CXXRecordDecl *RD,
23 SourceLocation L, IdentifierInfo *Id,
24 QualType T, Expr *BW) {
25 void *Mem = C.getAllocator().Allocate<CXXFieldDecl>();
26 return new (Mem) CXXFieldDecl(RD, L, Id, T, BW);
27}
28
29CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
30 SourceLocation L, IdentifierInfo *Id,
31 CXXRecordDecl* PrevDecl) {
Ted Kremenek4b7c9832008-09-05 17:16:31 +000032 void *Mem = C.getAllocator().Allocate<CXXRecordDecl>();
Argyrios Kyrtzidis35bc0822008-10-15 00:42:39 +000033 CXXRecordDecl* R = new (Mem) CXXRecordDecl(TK, DC, L, Id);
Ted Kremenek4b7c9832008-09-05 17:16:31 +000034 C.getTypeDeclType(R, PrevDecl);
35 return R;
36}
37
Douglas Gregorf8268ae2008-10-22 17:49:05 +000038CXXRecordDecl::~CXXRecordDecl() {
Douglas Gregorf8268ae2008-10-22 17:49:05 +000039 delete [] Bases;
40}
41
Douglas Gregorb48fe382008-10-31 09:07:45 +000042void CXXRecordDecl::Destroy(ASTContext &C) {
43 for (OverloadedFunctionDecl::function_iterator func
44 = Constructors.function_begin();
45 func != Constructors.function_end(); ++func)
46 (*func)->Destroy(C);
Douglas Gregor42a552f2008-11-05 20:51:48 +000047
48 if (isDefinition())
49 Destructor->Destroy(C);
50
Douglas Gregor2f1bc522008-11-07 20:08:42 +000051 for (OverloadedFunctionDecl::function_iterator func
52 = Conversions.function_begin();
53 func != Conversions.function_end(); ++func)
54 (*func)->Destroy(C);
55
Douglas Gregorb48fe382008-10-31 09:07:45 +000056 RecordDecl::Destroy(C);
57}
58
Douglas Gregor57c856b2008-10-23 18:13:27 +000059void
60CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
61 unsigned NumBases) {
Douglas Gregor64bffa92008-11-05 16:20:31 +000062 // C++ [dcl.init.aggr]p1:
63 // An aggregate is an array or a class (clause 9) with [...]
64 // no base classes [...].
65 Aggregate = false;
66
Douglas Gregor57c856b2008-10-23 18:13:27 +000067 if (this->Bases)
68 delete [] this->Bases;
69
70 this->Bases = new CXXBaseSpecifier[NumBases];
71 this->NumBases = NumBases;
72 for (unsigned i = 0; i < NumBases; ++i)
73 this->Bases[i] = *Bases[i];
74}
75
Douglas Gregor396b7cd2008-11-03 17:51:48 +000076bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
77 for (OverloadedFunctionDecl::function_const_iterator Con
78 = Constructors.function_begin();
79 Con != Constructors.function_end(); ++Con) {
80 unsigned TypeQuals;
81 if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) &&
82 (TypeQuals & QualType::Const != 0))
83 return true;
84 }
85 return false;
86}
87
Douglas Gregor030ff0c2008-10-31 20:25:05 +000088void
89CXXRecordDecl::addConstructor(ASTContext &Context,
90 CXXConstructorDecl *ConDecl) {
91 if (!ConDecl->isImplicitlyDeclared()) {
92 // Note that we have a user-declared constructor.
93 UserDeclaredConstructor = true;
94
Douglas Gregor64bffa92008-11-05 16:20:31 +000095 // C++ [dcl.init.aggr]p1:
96 // An aggregate is an array or a class (clause 9) with no
97 // user-declared constructors (12.1) [...].
98 Aggregate = false;
99
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000100 // Note when we have a user-declared copy constructor, which will
101 // suppress the implicit declaration of a copy constructor.
102 if (ConDecl->isCopyConstructor(Context))
103 UserDeclaredCopyConstructor = true;
104 }
105
106 Constructors.addOverload(ConDecl);
107}
108
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000109void CXXRecordDecl::addConversionFunction(ASTContext &Context,
110 CXXConversionDecl *ConvDecl) {
111 Conversions.addOverload(ConvDecl);
112}
113
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000114CXXMethodDecl *
115CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
116 SourceLocation L, IdentifierInfo *Id,
117 QualType T, bool isStatic, bool isInline,
118 ScopedDecl *PrevDecl) {
119 void *Mem = C.getAllocator().Allocate<CXXMethodDecl>();
120 return new (Mem) CXXMethodDecl(RD, L, Id, T, isStatic, isInline, PrevDecl);
121}
122
123QualType CXXMethodDecl::getThisType(ASTContext &C) const {
Argyrios Kyrtzidisb0d178d2008-10-24 22:28:18 +0000124 // C++ 9.3.2p1: The type of this in a member function of a class X is X*.
125 // If the member function is declared const, the type of this is const X*,
126 // if the member function is declared volatile, the type of this is
127 // volatile X*, and if the member function is declared const volatile,
128 // the type of this is const volatile X*.
129
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000130 assert(isInstance() && "No 'this' for static methods!");
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000131 QualType ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
Argyrios Kyrtzidis971c4fa2008-10-24 21:46:40 +0000132 ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers());
133 return C.getPointerType(ClassTy).withConst();
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000134}
135
Douglas Gregor7ad83902008-11-05 04:29:56 +0000136CXXBaseOrMemberInitializer::
137CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs)
138 : Args(0), NumArgs(0) {
139 BaseOrMember = reinterpret_cast<uintptr_t>(BaseType.getTypePtr());
140 assert((BaseOrMember & 0x01) == 0 && "Invalid base class type pointer");
141 BaseOrMember |= 0x01;
142
143 if (NumArgs > 0) {
144 this->NumArgs = NumArgs;
145 this->Args = new Expr*[NumArgs];
146 for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
147 this->Args[Idx] = Args[Idx];
148 }
149}
150
151CXXBaseOrMemberInitializer::
152CXXBaseOrMemberInitializer(CXXFieldDecl *Member, Expr **Args, unsigned NumArgs)
153 : Args(0), NumArgs(0) {
154 BaseOrMember = reinterpret_cast<uintptr_t>(Member);
155 assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer");
156
157 if (NumArgs > 0) {
158 this->NumArgs = NumArgs;
159 this->Args = new Expr*[NumArgs];
160 for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
161 this->Args[Idx] = Args[Idx];
162 }
163}
164
165CXXBaseOrMemberInitializer::~CXXBaseOrMemberInitializer() {
166 delete [] Args;
167}
168
Douglas Gregorb48fe382008-10-31 09:07:45 +0000169CXXConstructorDecl *
170CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
171 SourceLocation L, IdentifierInfo *Id,
172 QualType T, bool isExplicit,
173 bool isInline, bool isImplicitlyDeclared) {
174 void *Mem = C.getAllocator().Allocate<CXXConstructorDecl>();
175 return new (Mem) CXXConstructorDecl(RD, L, Id, T, isExplicit, isInline,
176 isImplicitlyDeclared);
177}
178
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000179bool CXXConstructorDecl::isDefaultConstructor() const {
180 // C++ [class.ctor]p5:
Douglas Gregor64bffa92008-11-05 16:20:31 +0000181 // A default constructor for a class X is a constructor of class
182 // X that can be called without an argument.
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000183 return (getNumParams() == 0) ||
Douglas Gregorf03d7c72008-11-05 15:29:30 +0000184 (getNumParams() > 0 && getParamDecl(0)->getDefaultArg() != 0);
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000185}
186
187bool
188CXXConstructorDecl::isCopyConstructor(ASTContext &Context,
189 unsigned &TypeQuals) const {
190 // C++ [class.copy]p2:
Douglas Gregor64bffa92008-11-05 16:20:31 +0000191 // A non-template constructor for class X is a copy constructor
192 // if its first parameter is of type X&, const X&, volatile X& or
193 // const volatile X&, and either there are no other parameters
194 // or else all other parameters have default arguments (8.3.6).
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000195 if ((getNumParams() < 1) ||
196 (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() == 0))
197 return false;
198
199 const ParmVarDecl *Param = getParamDecl(0);
200
201 // Do we have a reference type?
202 const ReferenceType *ParamRefType = Param->getType()->getAsReferenceType();
203 if (!ParamRefType)
204 return false;
205
206 // Is it a reference to our class type?
207 QualType PointeeType
208 = Context.getCanonicalType(ParamRefType->getPointeeType());
209 QualType ClassTy
210 = Context.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
211 if (PointeeType.getUnqualifiedType() != ClassTy)
212 return false;
213
214 // We have a copy constructor.
215 TypeQuals = PointeeType.getCVRQualifiers();
216 return true;
217}
218
Douglas Gregor60d62c22008-10-31 16:23:19 +0000219bool CXXConstructorDecl::isConvertingConstructor() const {
220 // C++ [class.conv.ctor]p1:
221 // A constructor declared without the function-specifier explicit
222 // that can be called with a single parameter specifies a
223 // conversion from the type of its first parameter to the type of
224 // its class. Such a constructor is called a converting
225 // constructor.
226 if (isExplicit())
227 return false;
228
229 return (getNumParams() == 0 &&
230 getType()->getAsFunctionTypeProto()->isVariadic()) ||
231 (getNumParams() == 1) ||
232 (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() != 0);
233}
Douglas Gregorb48fe382008-10-31 09:07:45 +0000234
Douglas Gregor42a552f2008-11-05 20:51:48 +0000235CXXDestructorDecl *
236CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
237 SourceLocation L, IdentifierInfo *Id,
238 QualType T, bool isInline,
239 bool isImplicitlyDeclared) {
240 void *Mem = C.getAllocator().Allocate<CXXDestructorDecl>();
241 return new (Mem) CXXDestructorDecl(RD, L, Id, T, isInline,
242 isImplicitlyDeclared);
243}
244
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000245CXXConversionDecl *
246CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
247 SourceLocation L, IdentifierInfo *Id,
248 QualType T, bool isInline, bool isExplicit) {
249 void *Mem = C.getAllocator().Allocate<CXXConversionDecl>();
250 return new (Mem) CXXConversionDecl(RD, L, Id, T, isInline, isExplicit);
251}
252
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000253CXXClassVarDecl *CXXClassVarDecl::Create(ASTContext &C, CXXRecordDecl *RD,
254 SourceLocation L, IdentifierInfo *Id,
255 QualType T, ScopedDecl *PrevDecl) {
256 void *Mem = C.getAllocator().Allocate<CXXClassVarDecl>();
257 return new (Mem) CXXClassVarDecl(RD, L, Id, T, PrevDecl);
258}
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000259
260OverloadedFunctionDecl *
261OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC,
262 IdentifierInfo *Id) {
263 void *Mem = C.getAllocator().Allocate<OverloadedFunctionDecl>();
264 return new (Mem) OverloadedFunctionDecl(DC, Id);
265}
Chris Lattner21ef7ae2008-11-04 16:51:42 +0000266
267LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
268 SourceLocation L,
269 LanguageIDs Lang, Decl *D) {
270 void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>();
271 return new (Mem) LinkageSpecDecl(L, Lang, D);
272}
273