blob: b0df75b404d1db81974086bf21b44364a15011ca [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 Gregorb48fe382008-10-31 09:07:45 +000051 RecordDecl::Destroy(C);
52}
53
Douglas Gregor57c856b2008-10-23 18:13:27 +000054void
55CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
56 unsigned NumBases) {
Douglas Gregor64bffa92008-11-05 16:20:31 +000057 // C++ [dcl.init.aggr]p1:
58 // An aggregate is an array or a class (clause 9) with [...]
59 // no base classes [...].
60 Aggregate = false;
61
Douglas Gregor57c856b2008-10-23 18:13:27 +000062 if (this->Bases)
63 delete [] this->Bases;
64
65 this->Bases = new CXXBaseSpecifier[NumBases];
66 this->NumBases = NumBases;
67 for (unsigned i = 0; i < NumBases; ++i)
68 this->Bases[i] = *Bases[i];
69}
70
Douglas Gregor396b7cd2008-11-03 17:51:48 +000071bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
72 for (OverloadedFunctionDecl::function_const_iterator Con
73 = Constructors.function_begin();
74 Con != Constructors.function_end(); ++Con) {
75 unsigned TypeQuals;
76 if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) &&
77 (TypeQuals & QualType::Const != 0))
78 return true;
79 }
80 return false;
81}
82
Douglas Gregor030ff0c2008-10-31 20:25:05 +000083void
84CXXRecordDecl::addConstructor(ASTContext &Context,
85 CXXConstructorDecl *ConDecl) {
86 if (!ConDecl->isImplicitlyDeclared()) {
87 // Note that we have a user-declared constructor.
88 UserDeclaredConstructor = true;
89
Douglas Gregor64bffa92008-11-05 16:20:31 +000090 // C++ [dcl.init.aggr]p1:
91 // An aggregate is an array or a class (clause 9) with no
92 // user-declared constructors (12.1) [...].
93 Aggregate = false;
94
Douglas Gregor030ff0c2008-10-31 20:25:05 +000095 // Note when we have a user-declared copy constructor, which will
96 // suppress the implicit declaration of a copy constructor.
97 if (ConDecl->isCopyConstructor(Context))
98 UserDeclaredCopyConstructor = true;
99 }
100
101 Constructors.addOverload(ConDecl);
102}
103
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000104CXXMethodDecl *
105CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
106 SourceLocation L, IdentifierInfo *Id,
107 QualType T, bool isStatic, bool isInline,
108 ScopedDecl *PrevDecl) {
109 void *Mem = C.getAllocator().Allocate<CXXMethodDecl>();
110 return new (Mem) CXXMethodDecl(RD, L, Id, T, isStatic, isInline, PrevDecl);
111}
112
113QualType CXXMethodDecl::getThisType(ASTContext &C) const {
Argyrios Kyrtzidisb0d178d2008-10-24 22:28:18 +0000114 // C++ 9.3.2p1: The type of this in a member function of a class X is X*.
115 // If the member function is declared const, the type of this is const X*,
116 // if the member function is declared volatile, the type of this is
117 // volatile X*, and if the member function is declared const volatile,
118 // the type of this is const volatile X*.
119
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000120 assert(isInstance() && "No 'this' for static methods!");
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000121 QualType ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
Argyrios Kyrtzidis971c4fa2008-10-24 21:46:40 +0000122 ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers());
123 return C.getPointerType(ClassTy).withConst();
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000124}
125
Douglas Gregor7ad83902008-11-05 04:29:56 +0000126CXXBaseOrMemberInitializer::
127CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs)
128 : Args(0), NumArgs(0) {
129 BaseOrMember = reinterpret_cast<uintptr_t>(BaseType.getTypePtr());
130 assert((BaseOrMember & 0x01) == 0 && "Invalid base class type pointer");
131 BaseOrMember |= 0x01;
132
133 if (NumArgs > 0) {
134 this->NumArgs = NumArgs;
135 this->Args = new Expr*[NumArgs];
136 for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
137 this->Args[Idx] = Args[Idx];
138 }
139}
140
141CXXBaseOrMemberInitializer::
142CXXBaseOrMemberInitializer(CXXFieldDecl *Member, Expr **Args, unsigned NumArgs)
143 : Args(0), NumArgs(0) {
144 BaseOrMember = reinterpret_cast<uintptr_t>(Member);
145 assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer");
146
147 if (NumArgs > 0) {
148 this->NumArgs = NumArgs;
149 this->Args = new Expr*[NumArgs];
150 for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
151 this->Args[Idx] = Args[Idx];
152 }
153}
154
155CXXBaseOrMemberInitializer::~CXXBaseOrMemberInitializer() {
156 delete [] Args;
157}
158
Douglas Gregorb48fe382008-10-31 09:07:45 +0000159CXXConstructorDecl *
160CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
161 SourceLocation L, IdentifierInfo *Id,
162 QualType T, bool isExplicit,
163 bool isInline, bool isImplicitlyDeclared) {
164 void *Mem = C.getAllocator().Allocate<CXXConstructorDecl>();
165 return new (Mem) CXXConstructorDecl(RD, L, Id, T, isExplicit, isInline,
166 isImplicitlyDeclared);
167}
168
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000169bool CXXConstructorDecl::isDefaultConstructor() const {
170 // C++ [class.ctor]p5:
Douglas Gregor64bffa92008-11-05 16:20:31 +0000171 // A default constructor for a class X is a constructor of class
172 // X that can be called without an argument.
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000173 return (getNumParams() == 0) ||
Douglas Gregorf03d7c72008-11-05 15:29:30 +0000174 (getNumParams() > 0 && getParamDecl(0)->getDefaultArg() != 0);
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000175}
176
177bool
178CXXConstructorDecl::isCopyConstructor(ASTContext &Context,
179 unsigned &TypeQuals) const {
180 // C++ [class.copy]p2:
Douglas Gregor64bffa92008-11-05 16:20:31 +0000181 // A non-template constructor for class X is a copy constructor
182 // if its first parameter is of type X&, const X&, volatile X& or
183 // const volatile X&, and either there are no other parameters
184 // or else all other parameters have default arguments (8.3.6).
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000185 if ((getNumParams() < 1) ||
186 (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() == 0))
187 return false;
188
189 const ParmVarDecl *Param = getParamDecl(0);
190
191 // Do we have a reference type?
192 const ReferenceType *ParamRefType = Param->getType()->getAsReferenceType();
193 if (!ParamRefType)
194 return false;
195
196 // Is it a reference to our class type?
197 QualType PointeeType
198 = Context.getCanonicalType(ParamRefType->getPointeeType());
199 QualType ClassTy
200 = Context.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
201 if (PointeeType.getUnqualifiedType() != ClassTy)
202 return false;
203
204 // We have a copy constructor.
205 TypeQuals = PointeeType.getCVRQualifiers();
206 return true;
207}
208
Douglas Gregor60d62c22008-10-31 16:23:19 +0000209bool CXXConstructorDecl::isConvertingConstructor() const {
210 // C++ [class.conv.ctor]p1:
211 // A constructor declared without the function-specifier explicit
212 // that can be called with a single parameter specifies a
213 // conversion from the type of its first parameter to the type of
214 // its class. Such a constructor is called a converting
215 // constructor.
216 if (isExplicit())
217 return false;
218
219 return (getNumParams() == 0 &&
220 getType()->getAsFunctionTypeProto()->isVariadic()) ||
221 (getNumParams() == 1) ||
222 (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() != 0);
223}
Douglas Gregorb48fe382008-10-31 09:07:45 +0000224
Douglas Gregor42a552f2008-11-05 20:51:48 +0000225CXXDestructorDecl *
226CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
227 SourceLocation L, IdentifierInfo *Id,
228 QualType T, bool isInline,
229 bool isImplicitlyDeclared) {
230 void *Mem = C.getAllocator().Allocate<CXXDestructorDecl>();
231 return new (Mem) CXXDestructorDecl(RD, L, Id, T, isInline,
232 isImplicitlyDeclared);
233}
234
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000235CXXClassVarDecl *CXXClassVarDecl::Create(ASTContext &C, CXXRecordDecl *RD,
236 SourceLocation L, IdentifierInfo *Id,
237 QualType T, ScopedDecl *PrevDecl) {
238 void *Mem = C.getAllocator().Allocate<CXXClassVarDecl>();
239 return new (Mem) CXXClassVarDecl(RD, L, Id, T, PrevDecl);
240}
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000241
242OverloadedFunctionDecl *
243OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC,
244 IdentifierInfo *Id) {
245 void *Mem = C.getAllocator().Allocate<OverloadedFunctionDecl>();
246 return new (Mem) OverloadedFunctionDecl(DC, Id);
247}
Chris Lattner21ef7ae2008-11-04 16:51:42 +0000248
249LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
250 SourceLocation L,
251 LanguageIDs Lang, Decl *D) {
252 void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>();
253 return new (Mem) LinkageSpecDecl(L, Lang, D);
254}
255