blob: a26803caecb2c22b53bc17cdd0fa88e387dd87c3 [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//===----------------------------------------------------------------------===//
Douglas Gregor72c3f312008-12-05 18:15:24 +000022
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
Ted Kremenek4b7c9832008-09-05 17:16:31 +000039CXXFieldDecl *CXXFieldDecl::Create(ASTContext &C, CXXRecordDecl *RD,
40 SourceLocation L, IdentifierInfo *Id,
Sebastian Redla11f42f2008-11-17 23:24:37 +000041 QualType T, bool Mut, Expr *BW) {
Ted Kremenek4b7c9832008-09-05 17:16:31 +000042 void *Mem = C.getAllocator().Allocate<CXXFieldDecl>();
Sebastian Redla11f42f2008-11-17 23:24:37 +000043 return new (Mem) CXXFieldDecl(RD, L, Id, T, Mut, BW);
Ted Kremenek4b7c9832008-09-05 17:16:31 +000044}
45
Douglas Gregor2e1cd422008-11-17 14:58:09 +000046CXXRecordDecl::CXXRecordDecl(TagKind TK, DeclContext *DC,
Douglas Gregor7d7e6722008-11-12 23:21:09 +000047 SourceLocation L, IdentifierInfo *Id)
48 : RecordDecl(CXXRecord, TK, DC, L, Id), DeclContext(CXXRecord),
49 UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
50 Aggregate(true), Polymorphic(false), Bases(0), NumBases(0),
Douglas Gregor2e1cd422008-11-17 14:58:09 +000051 Constructors(DC, DeclarationName()),
Douglas Gregor7d7e6722008-11-12 23:21:09 +000052 Destructor(0),
Douglas Gregor2e1cd422008-11-17 14:58:09 +000053 Conversions(DC, DeclarationName()) { }
Douglas Gregor7d7e6722008-11-12 23:21:09 +000054
Ted Kremenek4b7c9832008-09-05 17:16:31 +000055CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
56 SourceLocation L, IdentifierInfo *Id,
57 CXXRecordDecl* PrevDecl) {
Ted Kremenek4b7c9832008-09-05 17:16:31 +000058 void *Mem = C.getAllocator().Allocate<CXXRecordDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +000059 CXXRecordDecl* R = new (Mem) CXXRecordDecl(TK, DC, L, Id);
Ted Kremenek4b7c9832008-09-05 17:16:31 +000060 C.getTypeDeclType(R, PrevDecl);
61 return R;
62}
63
Douglas Gregorf8268ae2008-10-22 17:49:05 +000064CXXRecordDecl::~CXXRecordDecl() {
Douglas Gregorf8268ae2008-10-22 17:49:05 +000065 delete [] Bases;
66}
67
Douglas Gregorb48fe382008-10-31 09:07:45 +000068void CXXRecordDecl::Destroy(ASTContext &C) {
69 for (OverloadedFunctionDecl::function_iterator func
70 = Constructors.function_begin();
71 func != Constructors.function_end(); ++func)
72 (*func)->Destroy(C);
Douglas Gregor42a552f2008-11-05 20:51:48 +000073
74 if (isDefinition())
75 Destructor->Destroy(C);
76
Douglas Gregor2f1bc522008-11-07 20:08:42 +000077 for (OverloadedFunctionDecl::function_iterator func
78 = Conversions.function_begin();
79 func != Conversions.function_end(); ++func)
80 (*func)->Destroy(C);
81
Douglas Gregorb48fe382008-10-31 09:07:45 +000082 RecordDecl::Destroy(C);
83}
84
Douglas Gregor57c856b2008-10-23 18:13:27 +000085void
86CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
87 unsigned NumBases) {
Douglas Gregor64bffa92008-11-05 16:20:31 +000088 // C++ [dcl.init.aggr]p1:
89 // An aggregate is an array or a class (clause 9) with [...]
90 // no base classes [...].
91 Aggregate = false;
92
Douglas Gregor57c856b2008-10-23 18:13:27 +000093 if (this->Bases)
94 delete [] this->Bases;
95
96 this->Bases = new CXXBaseSpecifier[NumBases];
97 this->NumBases = NumBases;
98 for (unsigned i = 0; i < NumBases; ++i)
99 this->Bases[i] = *Bases[i];
100}
101
Douglas Gregor396b7cd2008-11-03 17:51:48 +0000102bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
103 for (OverloadedFunctionDecl::function_const_iterator Con
104 = Constructors.function_begin();
105 Con != Constructors.function_end(); ++Con) {
106 unsigned TypeQuals;
107 if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) &&
108 (TypeQuals & QualType::Const != 0))
109 return true;
110 }
111 return false;
112}
113
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000114void
115CXXRecordDecl::addConstructor(ASTContext &Context,
116 CXXConstructorDecl *ConDecl) {
117 if (!ConDecl->isImplicitlyDeclared()) {
118 // Note that we have a user-declared constructor.
119 UserDeclaredConstructor = true;
120
Douglas Gregor64bffa92008-11-05 16:20:31 +0000121 // C++ [dcl.init.aggr]p1:
122 // An aggregate is an array or a class (clause 9) with no
123 // user-declared constructors (12.1) [...].
124 Aggregate = false;
125
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000126 // Note when we have a user-declared copy constructor, which will
127 // suppress the implicit declaration of a copy constructor.
128 if (ConDecl->isCopyConstructor(Context))
129 UserDeclaredCopyConstructor = true;
130 }
131
132 Constructors.addOverload(ConDecl);
133}
134
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000135void CXXRecordDecl::addConversionFunction(ASTContext &Context,
136 CXXConversionDecl *ConvDecl) {
137 Conversions.addOverload(ConvDecl);
138}
139
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000140CXXMethodDecl *
141CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
Douglas Gregor10bd3682008-11-17 22:58:34 +0000142 SourceLocation L, DeclarationName N,
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000143 QualType T, bool isStatic, bool isInline,
144 ScopedDecl *PrevDecl) {
145 void *Mem = C.getAllocator().Allocate<CXXMethodDecl>();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000146 return new (Mem) CXXMethodDecl(CXXMethod, RD, L, N, T, isStatic, isInline,
147 PrevDecl);
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000148}
149
150QualType CXXMethodDecl::getThisType(ASTContext &C) const {
Argyrios Kyrtzidisb0d178d2008-10-24 22:28:18 +0000151 // C++ 9.3.2p1: The type of this in a member function of a class X is X*.
152 // If the member function is declared const, the type of this is const X*,
153 // if the member function is declared volatile, the type of this is
154 // volatile X*, and if the member function is declared const volatile,
155 // the type of this is const volatile X*.
156
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000157 assert(isInstance() && "No 'this' for static methods!");
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000158 QualType ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
Argyrios Kyrtzidis971c4fa2008-10-24 21:46:40 +0000159 ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers());
160 return C.getPointerType(ClassTy).withConst();
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000161}
162
Douglas Gregor7ad83902008-11-05 04:29:56 +0000163CXXBaseOrMemberInitializer::
164CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs)
165 : Args(0), NumArgs(0) {
166 BaseOrMember = reinterpret_cast<uintptr_t>(BaseType.getTypePtr());
167 assert((BaseOrMember & 0x01) == 0 && "Invalid base class type pointer");
168 BaseOrMember |= 0x01;
169
170 if (NumArgs > 0) {
171 this->NumArgs = NumArgs;
172 this->Args = new Expr*[NumArgs];
173 for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
174 this->Args[Idx] = Args[Idx];
175 }
176}
177
178CXXBaseOrMemberInitializer::
179CXXBaseOrMemberInitializer(CXXFieldDecl *Member, Expr **Args, unsigned NumArgs)
180 : Args(0), NumArgs(0) {
181 BaseOrMember = reinterpret_cast<uintptr_t>(Member);
182 assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer");
183
184 if (NumArgs > 0) {
185 this->NumArgs = NumArgs;
186 this->Args = new Expr*[NumArgs];
187 for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
188 this->Args[Idx] = Args[Idx];
189 }
190}
191
192CXXBaseOrMemberInitializer::~CXXBaseOrMemberInitializer() {
193 delete [] Args;
194}
195
Douglas Gregorb48fe382008-10-31 09:07:45 +0000196CXXConstructorDecl *
197CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000198 SourceLocation L, DeclarationName N,
Douglas Gregorb48fe382008-10-31 09:07:45 +0000199 QualType T, bool isExplicit,
200 bool isInline, bool isImplicitlyDeclared) {
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000201 assert(N.getNameKind() == DeclarationName::CXXConstructorName &&
202 "Name must refer to a constructor");
Douglas Gregorb48fe382008-10-31 09:07:45 +0000203 void *Mem = C.getAllocator().Allocate<CXXConstructorDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000204 return new (Mem) CXXConstructorDecl(RD, L, N, T, isExplicit, isInline,
Douglas Gregorb48fe382008-10-31 09:07:45 +0000205 isImplicitlyDeclared);
206}
207
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000208bool CXXConstructorDecl::isDefaultConstructor() const {
209 // C++ [class.ctor]p5:
Douglas Gregor64bffa92008-11-05 16:20:31 +0000210 // A default constructor for a class X is a constructor of class
211 // X that can be called without an argument.
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000212 return (getNumParams() == 0) ||
Douglas Gregorf03d7c72008-11-05 15:29:30 +0000213 (getNumParams() > 0 && getParamDecl(0)->getDefaultArg() != 0);
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000214}
215
216bool
217CXXConstructorDecl::isCopyConstructor(ASTContext &Context,
218 unsigned &TypeQuals) const {
219 // C++ [class.copy]p2:
Douglas Gregor64bffa92008-11-05 16:20:31 +0000220 // A non-template constructor for class X is a copy constructor
221 // if its first parameter is of type X&, const X&, volatile X& or
222 // const volatile X&, and either there are no other parameters
223 // or else all other parameters have default arguments (8.3.6).
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000224 if ((getNumParams() < 1) ||
225 (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() == 0))
226 return false;
227
228 const ParmVarDecl *Param = getParamDecl(0);
229
230 // Do we have a reference type?
231 const ReferenceType *ParamRefType = Param->getType()->getAsReferenceType();
232 if (!ParamRefType)
233 return false;
234
235 // Is it a reference to our class type?
236 QualType PointeeType
237 = Context.getCanonicalType(ParamRefType->getPointeeType());
238 QualType ClassTy
239 = Context.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
240 if (PointeeType.getUnqualifiedType() != ClassTy)
241 return false;
242
243 // We have a copy constructor.
244 TypeQuals = PointeeType.getCVRQualifiers();
245 return true;
246}
247
Douglas Gregor60d62c22008-10-31 16:23:19 +0000248bool CXXConstructorDecl::isConvertingConstructor() const {
249 // C++ [class.conv.ctor]p1:
250 // A constructor declared without the function-specifier explicit
251 // that can be called with a single parameter specifies a
252 // conversion from the type of its first parameter to the type of
253 // its class. Such a constructor is called a converting
254 // constructor.
255 if (isExplicit())
256 return false;
257
258 return (getNumParams() == 0 &&
259 getType()->getAsFunctionTypeProto()->isVariadic()) ||
260 (getNumParams() == 1) ||
261 (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() != 0);
262}
Douglas Gregorb48fe382008-10-31 09:07:45 +0000263
Douglas Gregor42a552f2008-11-05 20:51:48 +0000264CXXDestructorDecl *
265CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000266 SourceLocation L, DeclarationName N,
Douglas Gregor42a552f2008-11-05 20:51:48 +0000267 QualType T, bool isInline,
268 bool isImplicitlyDeclared) {
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000269 assert(N.getNameKind() == DeclarationName::CXXDestructorName &&
270 "Name must refer to a destructor");
Douglas Gregor42a552f2008-11-05 20:51:48 +0000271 void *Mem = C.getAllocator().Allocate<CXXDestructorDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000272 return new (Mem) CXXDestructorDecl(RD, L, N, T, isInline,
Douglas Gregor42a552f2008-11-05 20:51:48 +0000273 isImplicitlyDeclared);
274}
275
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000276CXXConversionDecl *
277CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000278 SourceLocation L, DeclarationName N,
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000279 QualType T, bool isInline, bool isExplicit) {
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000280 assert(N.getNameKind() == DeclarationName::CXXConversionFunctionName &&
281 "Name must refer to a conversion function");
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000282 void *Mem = C.getAllocator().Allocate<CXXConversionDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000283 return new (Mem) CXXConversionDecl(RD, L, N, T, isInline, isExplicit);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000284}
285
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000286CXXClassVarDecl *CXXClassVarDecl::Create(ASTContext &C, CXXRecordDecl *RD,
287 SourceLocation L, IdentifierInfo *Id,
288 QualType T, ScopedDecl *PrevDecl) {
289 void *Mem = C.getAllocator().Allocate<CXXClassVarDecl>();
290 return new (Mem) CXXClassVarDecl(RD, L, Id, T, PrevDecl);
291}
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000292
293OverloadedFunctionDecl *
294OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC,
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000295 DeclarationName N) {
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000296 void *Mem = C.getAllocator().Allocate<OverloadedFunctionDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000297 return new (Mem) OverloadedFunctionDecl(DC, N);
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000298}
Chris Lattner21ef7ae2008-11-04 16:51:42 +0000299
300LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
301 SourceLocation L,
302 LanguageIDs Lang, Decl *D) {
303 void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>();
304 return new (Mem) LinkageSpecDecl(L, Lang, D);
305}
306