blob: 6be9eaf1a34287a303ade0b381bb99e2ea06e686 [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"
Douglas Gregor7d7e6722008-11-12 23:21:09 +000016#include "clang/Basic/IdentifierTable.h"
Ted Kremenek4b7c9832008-09-05 17:16:31 +000017using namespace clang;
18
19//===----------------------------------------------------------------------===//
20// Decl Allocation/Deallocation Method Implementations
21//===----------------------------------------------------------------------===//
22
23CXXFieldDecl *CXXFieldDecl::Create(ASTContext &C, CXXRecordDecl *RD,
24 SourceLocation L, IdentifierInfo *Id,
Sebastian Redla11f42f2008-11-17 23:24:37 +000025 QualType T, bool Mut, Expr *BW) {
Ted Kremenek4b7c9832008-09-05 17:16:31 +000026 void *Mem = C.getAllocator().Allocate<CXXFieldDecl>();
Sebastian Redla11f42f2008-11-17 23:24:37 +000027 return new (Mem) CXXFieldDecl(RD, L, Id, T, Mut, BW);
Ted Kremenek4b7c9832008-09-05 17:16:31 +000028}
29
Douglas Gregor2e1cd422008-11-17 14:58:09 +000030CXXRecordDecl::CXXRecordDecl(TagKind TK, DeclContext *DC,
Douglas Gregor7d7e6722008-11-12 23:21:09 +000031 SourceLocation L, IdentifierInfo *Id)
32 : RecordDecl(CXXRecord, TK, DC, L, Id), DeclContext(CXXRecord),
33 UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
34 Aggregate(true), Polymorphic(false), Bases(0), NumBases(0),
Douglas Gregor2e1cd422008-11-17 14:58:09 +000035 Constructors(DC, DeclarationName()),
Douglas Gregor7d7e6722008-11-12 23:21:09 +000036 Destructor(0),
Douglas Gregor2e1cd422008-11-17 14:58:09 +000037 Conversions(DC, DeclarationName()) { }
Douglas Gregor7d7e6722008-11-12 23:21:09 +000038
Ted Kremenek4b7c9832008-09-05 17:16:31 +000039CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
40 SourceLocation L, IdentifierInfo *Id,
41 CXXRecordDecl* PrevDecl) {
Ted Kremenek4b7c9832008-09-05 17:16:31 +000042 void *Mem = C.getAllocator().Allocate<CXXRecordDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +000043 CXXRecordDecl* R = new (Mem) CXXRecordDecl(TK, DC, L, Id);
Ted Kremenek4b7c9832008-09-05 17:16:31 +000044 C.getTypeDeclType(R, PrevDecl);
45 return R;
46}
47
Douglas Gregorf8268ae2008-10-22 17:49:05 +000048CXXRecordDecl::~CXXRecordDecl() {
Douglas Gregorf8268ae2008-10-22 17:49:05 +000049 delete [] Bases;
50}
51
Douglas Gregorb48fe382008-10-31 09:07:45 +000052void CXXRecordDecl::Destroy(ASTContext &C) {
53 for (OverloadedFunctionDecl::function_iterator func
54 = Constructors.function_begin();
55 func != Constructors.function_end(); ++func)
56 (*func)->Destroy(C);
Douglas Gregor42a552f2008-11-05 20:51:48 +000057
58 if (isDefinition())
59 Destructor->Destroy(C);
60
Douglas Gregor2f1bc522008-11-07 20:08:42 +000061 for (OverloadedFunctionDecl::function_iterator func
62 = Conversions.function_begin();
63 func != Conversions.function_end(); ++func)
64 (*func)->Destroy(C);
65
Douglas Gregorb48fe382008-10-31 09:07:45 +000066 RecordDecl::Destroy(C);
67}
68
Douglas Gregor57c856b2008-10-23 18:13:27 +000069void
70CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
71 unsigned NumBases) {
Douglas Gregor64bffa92008-11-05 16:20:31 +000072 // C++ [dcl.init.aggr]p1:
73 // An aggregate is an array or a class (clause 9) with [...]
74 // no base classes [...].
75 Aggregate = false;
76
Douglas Gregor57c856b2008-10-23 18:13:27 +000077 if (this->Bases)
78 delete [] this->Bases;
79
80 this->Bases = new CXXBaseSpecifier[NumBases];
81 this->NumBases = NumBases;
82 for (unsigned i = 0; i < NumBases; ++i)
83 this->Bases[i] = *Bases[i];
84}
85
Douglas Gregor396b7cd2008-11-03 17:51:48 +000086bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
87 for (OverloadedFunctionDecl::function_const_iterator Con
88 = Constructors.function_begin();
89 Con != Constructors.function_end(); ++Con) {
90 unsigned TypeQuals;
91 if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) &&
92 (TypeQuals & QualType::Const != 0))
93 return true;
94 }
95 return false;
96}
97
Douglas Gregor030ff0c2008-10-31 20:25:05 +000098void
99CXXRecordDecl::addConstructor(ASTContext &Context,
100 CXXConstructorDecl *ConDecl) {
101 if (!ConDecl->isImplicitlyDeclared()) {
102 // Note that we have a user-declared constructor.
103 UserDeclaredConstructor = true;
104
Douglas Gregor64bffa92008-11-05 16:20:31 +0000105 // C++ [dcl.init.aggr]p1:
106 // An aggregate is an array or a class (clause 9) with no
107 // user-declared constructors (12.1) [...].
108 Aggregate = false;
109
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000110 // Note when we have a user-declared copy constructor, which will
111 // suppress the implicit declaration of a copy constructor.
112 if (ConDecl->isCopyConstructor(Context))
113 UserDeclaredCopyConstructor = true;
114 }
115
116 Constructors.addOverload(ConDecl);
117}
118
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000119void CXXRecordDecl::addConversionFunction(ASTContext &Context,
120 CXXConversionDecl *ConvDecl) {
121 Conversions.addOverload(ConvDecl);
122}
123
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000124CXXMethodDecl *
125CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
Douglas Gregor10bd3682008-11-17 22:58:34 +0000126 SourceLocation L, DeclarationName N,
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000127 QualType T, bool isStatic, bool isInline,
128 ScopedDecl *PrevDecl) {
129 void *Mem = C.getAllocator().Allocate<CXXMethodDecl>();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000130 return new (Mem) CXXMethodDecl(CXXMethod, RD, L, N, T, isStatic, isInline,
131 PrevDecl);
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000132}
133
134QualType CXXMethodDecl::getThisType(ASTContext &C) const {
Argyrios Kyrtzidisb0d178d2008-10-24 22:28:18 +0000135 // C++ 9.3.2p1: The type of this in a member function of a class X is X*.
136 // If the member function is declared const, the type of this is const X*,
137 // if the member function is declared volatile, the type of this is
138 // volatile X*, and if the member function is declared const volatile,
139 // the type of this is const volatile X*.
140
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000141 assert(isInstance() && "No 'this' for static methods!");
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000142 QualType ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
Argyrios Kyrtzidis971c4fa2008-10-24 21:46:40 +0000143 ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers());
144 return C.getPointerType(ClassTy).withConst();
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000145}
146
Douglas Gregor7ad83902008-11-05 04:29:56 +0000147CXXBaseOrMemberInitializer::
148CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs)
149 : Args(0), NumArgs(0) {
150 BaseOrMember = reinterpret_cast<uintptr_t>(BaseType.getTypePtr());
151 assert((BaseOrMember & 0x01) == 0 && "Invalid base class type pointer");
152 BaseOrMember |= 0x01;
153
154 if (NumArgs > 0) {
155 this->NumArgs = NumArgs;
156 this->Args = new Expr*[NumArgs];
157 for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
158 this->Args[Idx] = Args[Idx];
159 }
160}
161
162CXXBaseOrMemberInitializer::
163CXXBaseOrMemberInitializer(CXXFieldDecl *Member, Expr **Args, unsigned NumArgs)
164 : Args(0), NumArgs(0) {
165 BaseOrMember = reinterpret_cast<uintptr_t>(Member);
166 assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer");
167
168 if (NumArgs > 0) {
169 this->NumArgs = NumArgs;
170 this->Args = new Expr*[NumArgs];
171 for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
172 this->Args[Idx] = Args[Idx];
173 }
174}
175
176CXXBaseOrMemberInitializer::~CXXBaseOrMemberInitializer() {
177 delete [] Args;
178}
179
Douglas Gregorb48fe382008-10-31 09:07:45 +0000180CXXConstructorDecl *
181CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000182 SourceLocation L, DeclarationName N,
Douglas Gregorb48fe382008-10-31 09:07:45 +0000183 QualType T, bool isExplicit,
184 bool isInline, bool isImplicitlyDeclared) {
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000185 assert(N.getNameKind() == DeclarationName::CXXConstructorName &&
186 "Name must refer to a constructor");
Douglas Gregorb48fe382008-10-31 09:07:45 +0000187 void *Mem = C.getAllocator().Allocate<CXXConstructorDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000188 return new (Mem) CXXConstructorDecl(RD, L, N, T, isExplicit, isInline,
Douglas Gregorb48fe382008-10-31 09:07:45 +0000189 isImplicitlyDeclared);
190}
191
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000192bool CXXConstructorDecl::isDefaultConstructor() const {
193 // C++ [class.ctor]p5:
Douglas Gregor64bffa92008-11-05 16:20:31 +0000194 // A default constructor for a class X is a constructor of class
195 // X that can be called without an argument.
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000196 return (getNumParams() == 0) ||
Douglas Gregorf03d7c72008-11-05 15:29:30 +0000197 (getNumParams() > 0 && getParamDecl(0)->getDefaultArg() != 0);
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000198}
199
200bool
201CXXConstructorDecl::isCopyConstructor(ASTContext &Context,
202 unsigned &TypeQuals) const {
203 // C++ [class.copy]p2:
Douglas Gregor64bffa92008-11-05 16:20:31 +0000204 // A non-template constructor for class X is a copy constructor
205 // if its first parameter is of type X&, const X&, volatile X& or
206 // const volatile X&, and either there are no other parameters
207 // or else all other parameters have default arguments (8.3.6).
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000208 if ((getNumParams() < 1) ||
209 (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() == 0))
210 return false;
211
212 const ParmVarDecl *Param = getParamDecl(0);
213
214 // Do we have a reference type?
215 const ReferenceType *ParamRefType = Param->getType()->getAsReferenceType();
216 if (!ParamRefType)
217 return false;
218
219 // Is it a reference to our class type?
220 QualType PointeeType
221 = Context.getCanonicalType(ParamRefType->getPointeeType());
222 QualType ClassTy
223 = Context.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
224 if (PointeeType.getUnqualifiedType() != ClassTy)
225 return false;
226
227 // We have a copy constructor.
228 TypeQuals = PointeeType.getCVRQualifiers();
229 return true;
230}
231
Douglas Gregor60d62c22008-10-31 16:23:19 +0000232bool CXXConstructorDecl::isConvertingConstructor() const {
233 // C++ [class.conv.ctor]p1:
234 // A constructor declared without the function-specifier explicit
235 // that can be called with a single parameter specifies a
236 // conversion from the type of its first parameter to the type of
237 // its class. Such a constructor is called a converting
238 // constructor.
239 if (isExplicit())
240 return false;
241
242 return (getNumParams() == 0 &&
243 getType()->getAsFunctionTypeProto()->isVariadic()) ||
244 (getNumParams() == 1) ||
245 (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() != 0);
246}
Douglas Gregorb48fe382008-10-31 09:07:45 +0000247
Douglas Gregor42a552f2008-11-05 20:51:48 +0000248CXXDestructorDecl *
249CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000250 SourceLocation L, DeclarationName N,
Douglas Gregor42a552f2008-11-05 20:51:48 +0000251 QualType T, bool isInline,
252 bool isImplicitlyDeclared) {
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000253 assert(N.getNameKind() == DeclarationName::CXXDestructorName &&
254 "Name must refer to a destructor");
Douglas Gregor42a552f2008-11-05 20:51:48 +0000255 void *Mem = C.getAllocator().Allocate<CXXDestructorDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000256 return new (Mem) CXXDestructorDecl(RD, L, N, T, isInline,
Douglas Gregor42a552f2008-11-05 20:51:48 +0000257 isImplicitlyDeclared);
258}
259
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000260CXXConversionDecl *
261CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000262 SourceLocation L, DeclarationName N,
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000263 QualType T, bool isInline, bool isExplicit) {
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000264 assert(N.getNameKind() == DeclarationName::CXXConversionFunctionName &&
265 "Name must refer to a conversion function");
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000266 void *Mem = C.getAllocator().Allocate<CXXConversionDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000267 return new (Mem) CXXConversionDecl(RD, L, N, T, isInline, isExplicit);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000268}
269
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000270CXXClassVarDecl *CXXClassVarDecl::Create(ASTContext &C, CXXRecordDecl *RD,
271 SourceLocation L, IdentifierInfo *Id,
272 QualType T, ScopedDecl *PrevDecl) {
273 void *Mem = C.getAllocator().Allocate<CXXClassVarDecl>();
274 return new (Mem) CXXClassVarDecl(RD, L, Id, T, PrevDecl);
275}
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000276
277OverloadedFunctionDecl *
278OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC,
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000279 DeclarationName N) {
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000280 void *Mem = C.getAllocator().Allocate<OverloadedFunctionDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000281 return new (Mem) OverloadedFunctionDecl(DC, N);
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000282}
Chris Lattner21ef7ae2008-11-04 16:51:42 +0000283
284LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
285 SourceLocation L,
286 LanguageIDs Lang, Decl *D) {
287 void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>();
288 return new (Mem) LinkageSpecDecl(L, Lang, D);
289}
290