blob: 545f18ed056bec039f94b51bd20eaedf014a38ad [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"
Douglas Gregorfdfab6b2008-12-23 21:31:30 +000017#include "llvm/ADT/STLExtras.h"
Ted Kremenek4b7c9832008-09-05 17:16:31 +000018using namespace clang;
19
20//===----------------------------------------------------------------------===//
21// Decl Allocation/Deallocation Method Implementations
22//===----------------------------------------------------------------------===//
Douglas Gregor72c3f312008-12-05 18:15:24 +000023
24TemplateTypeParmDecl *
25TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC,
Nate Begemanfea86852008-12-16 19:57:09 +000026 SourceLocation L, IdentifierInfo *Id,
27 bool Typename) {
Douglas Gregor72c3f312008-12-05 18:15:24 +000028 void *Mem = C.getAllocator().Allocate<TemplateTypeParmDecl>();
29 return new (Mem) TemplateTypeParmDecl(DC, L, Id, Typename);
30}
31
32NonTypeTemplateParmDecl *
33NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
Nate Begemanfea86852008-12-16 19:57:09 +000034 SourceLocation L, IdentifierInfo *Id,
35 QualType T, SourceLocation TypeSpecStartLoc) {
Douglas Gregor72c3f312008-12-05 18:15:24 +000036 void *Mem = C.getAllocator().Allocate<NonTypeTemplateParmDecl>();
37 return new (Mem) NonTypeTemplateParmDecl(DC, L, Id, T, TypeSpecStartLoc);
38}
39
Douglas Gregorc4b4e7b2008-12-24 02:52:09 +000040TemplateParameterList::TemplateParameterList(Decl **Params, unsigned NumParams)
41 : NumParams(NumParams) {
42 for (unsigned Idx = 0; Idx < NumParams; ++Idx)
43 begin()[Idx] = Params[Idx];
44}
45
46TemplateParameterList *
47TemplateParameterList::Create(ASTContext &C, Decl **Params,
48 unsigned NumParams) {
49 unsigned Size = sizeof(TemplateParameterList) + sizeof(Decl *) * NumParams;
50 unsigned Align = llvm::AlignOf<TemplateParameterList>::Alignment;
51 void *Mem = C.getAllocator().Allocate(Size, Align);
52 return new (Mem) TemplateParameterList(Params, NumParams);
53}
54
Douglas Gregor2e1cd422008-11-17 14:58:09 +000055CXXRecordDecl::CXXRecordDecl(TagKind TK, DeclContext *DC,
Douglas Gregor7d7e6722008-11-12 23:21:09 +000056 SourceLocation L, IdentifierInfo *Id)
Douglas Gregor44b43212008-12-11 16:49:14 +000057 : RecordDecl(CXXRecord, TK, DC, L, Id),
Douglas Gregor7d7e6722008-11-12 23:21:09 +000058 UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
Sebastian Redl64b45f72009-01-05 20:52:13 +000059 UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false),
60 Aggregate(true), PlainOldData(true), Polymorphic(false), Bases(0),
61 NumBases(0), Conversions(DC, DeclarationName()) { }
Douglas Gregor7d7e6722008-11-12 23:21:09 +000062
Ted Kremenek4b7c9832008-09-05 17:16:31 +000063CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
64 SourceLocation L, IdentifierInfo *Id,
65 CXXRecordDecl* PrevDecl) {
Ted Kremenek4b7c9832008-09-05 17:16:31 +000066 void *Mem = C.getAllocator().Allocate<CXXRecordDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +000067 CXXRecordDecl* R = new (Mem) CXXRecordDecl(TK, DC, L, Id);
Ted Kremenek4b7c9832008-09-05 17:16:31 +000068 C.getTypeDeclType(R, PrevDecl);
69 return R;
70}
71
Douglas Gregorf8268ae2008-10-22 17:49:05 +000072CXXRecordDecl::~CXXRecordDecl() {
Douglas Gregorf8268ae2008-10-22 17:49:05 +000073 delete [] Bases;
74}
75
Douglas Gregor57c856b2008-10-23 18:13:27 +000076void
77CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
78 unsigned NumBases) {
Douglas Gregor64bffa92008-11-05 16:20:31 +000079 // C++ [dcl.init.aggr]p1:
80 // An aggregate is an array or a class (clause 9) with [...]
81 // no base classes [...].
82 Aggregate = false;
83
Douglas Gregor57c856b2008-10-23 18:13:27 +000084 if (this->Bases)
85 delete [] this->Bases;
86
87 this->Bases = new CXXBaseSpecifier[NumBases];
88 this->NumBases = NumBases;
89 for (unsigned i = 0; i < NumBases; ++i)
90 this->Bases[i] = *Bases[i];
91}
92
Douglas Gregor396b7cd2008-11-03 17:51:48 +000093bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
Sebastian Redl64b45f72009-01-05 20:52:13 +000094 QualType ClassType
95 = Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this));
Douglas Gregor9e7d9de2008-12-15 21:24:18 +000096 DeclarationName ConstructorName
97 = Context.DeclarationNames.getCXXConstructorName(
98 Context.getCanonicalType(ClassType));
99 unsigned TypeQuals;
Douglas Gregorfdfab6b2008-12-23 21:31:30 +0000100 DeclContext::lookup_const_iterator Con, ConEnd;
101 for (llvm::tie(Con, ConEnd) = this->lookup(Context, ConstructorName);
102 Con != ConEnd; ++Con) {
Douglas Gregor396b7cd2008-11-03 17:51:48 +0000103 if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) &&
Eli Friedmane8e32052008-12-16 20:06:41 +0000104 (TypeQuals & QualType::Const) != 0)
Douglas Gregor396b7cd2008-11-03 17:51:48 +0000105 return true;
106 }
Douglas Gregorfdfab6b2008-12-23 21:31:30 +0000107
Douglas Gregor396b7cd2008-11-03 17:51:48 +0000108 return false;
109}
110
Sebastian Redl64b45f72009-01-05 20:52:13 +0000111bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context) const {
112 QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
113 const_cast<CXXRecordDecl*>(this)));
114 DeclarationName OpName =Context.DeclarationNames.getCXXOperatorName(OO_Equal);
115
116 DeclContext::lookup_const_iterator Op, OpEnd;
117 for (llvm::tie(Op, OpEnd) = this->lookup(Context, OpName);
118 Op != OpEnd; ++Op) {
119 // C++ [class.copy]p9:
120 // A user-declared copy assignment operator is a non-static non-template
121 // member function of class X with exactly one parameter of type X, X&,
122 // const X&, volatile X& or const volatile X&.
123 const CXXMethodDecl* Method = cast<CXXMethodDecl>(*Op);
124 if (Method->isStatic())
125 continue;
126 // TODO: Skip templates? Or is this implicitly done due to parameter types?
127 const FunctionTypeProto *FnType =
128 Method->getType()->getAsFunctionTypeProto();
129 assert(FnType && "Overloaded operator has no prototype.");
130 // Don't assert on this; an invalid decl might have been left in the AST.
131 if (FnType->getNumArgs() != 1 || FnType->isVariadic())
132 continue;
133 bool AcceptsConst = true;
134 QualType ArgType = FnType->getArgType(0);
135 if (const ReferenceType *Ref = ArgType->getAsReferenceType()) {
136 ArgType = Ref->getPointeeType();
137 // Is it a non-const reference?
138 if (!ArgType.isConstQualified())
139 AcceptsConst = false;
140 }
141 if (Context.getCanonicalType(ArgType).getUnqualifiedType() != ClassType)
142 continue;
143
144 // We have a single argument of type cv X or cv X&, i.e. we've found the
145 // copy assignment operator. Return whether it accepts const arguments.
146 return AcceptsConst;
147 }
148 assert(isInvalidDecl() &&
149 "No copy assignment operator declared in valid code.");
150 return false;
151}
152
153void
Douglas Gregor9e7d9de2008-12-15 21:24:18 +0000154CXXRecordDecl::addedConstructor(ASTContext &Context,
155 CXXConstructorDecl *ConDecl) {
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000156 if (!ConDecl->isImplicitlyDeclared()) {
157 // Note that we have a user-declared constructor.
158 UserDeclaredConstructor = true;
159
Douglas Gregor64bffa92008-11-05 16:20:31 +0000160 // C++ [dcl.init.aggr]p1:
161 // An aggregate is an array or a class (clause 9) with no
162 // user-declared constructors (12.1) [...].
163 Aggregate = false;
164
Sebastian Redl64b45f72009-01-05 20:52:13 +0000165 // C++ [class]p4:
166 // A POD-struct is an aggregate class [...]
167 PlainOldData = false;
168
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000169 // Note when we have a user-declared copy constructor, which will
170 // suppress the implicit declaration of a copy constructor.
171 if (ConDecl->isCopyConstructor(Context))
172 UserDeclaredCopyConstructor = true;
173 }
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000174}
175
Sebastian Redl64b45f72009-01-05 20:52:13 +0000176void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context,
177 CXXMethodDecl *OpDecl) {
178 // We're interested specifically in copy assignment operators.
179 // Unlike addedConstructor, this method is not called for implicit
180 // declarations.
181 const FunctionTypeProto *FnType = OpDecl->getType()->getAsFunctionTypeProto();
182 assert(FnType && "Overloaded operator has no proto function type.");
183 assert(FnType->getNumArgs() == 1 && !FnType->isVariadic());
184 QualType ArgType = FnType->getArgType(0);
185 if (const ReferenceType *Ref = ArgType->getAsReferenceType())
186 ArgType = Ref->getPointeeType();
187
188 ArgType = ArgType.getUnqualifiedType();
189 QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
190 const_cast<CXXRecordDecl*>(this)));
191
192 if (ClassType != Context.getCanonicalType(ArgType))
193 return;
194
195 // This is a copy assignment operator.
196 // Suppress the implicit declaration of a copy constructor.
197 UserDeclaredCopyAssignment = true;
198
199 // C++ [class]p4:
200 // A POD-struct is an aggregate class that [...] has no user-defined copy
201 // assignment operator [...].
202 PlainOldData = false;
203}
204
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000205void CXXRecordDecl::addConversionFunction(ASTContext &Context,
206 CXXConversionDecl *ConvDecl) {
207 Conversions.addOverload(ConvDecl);
208}
209
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000210CXXMethodDecl *
211CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
Douglas Gregor10bd3682008-11-17 22:58:34 +0000212 SourceLocation L, DeclarationName N,
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000213 QualType T, bool isStatic, bool isInline,
214 ScopedDecl *PrevDecl) {
215 void *Mem = C.getAllocator().Allocate<CXXMethodDecl>();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000216 return new (Mem) CXXMethodDecl(CXXMethod, RD, L, N, T, isStatic, isInline,
217 PrevDecl);
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000218}
219
220QualType CXXMethodDecl::getThisType(ASTContext &C) const {
Argyrios Kyrtzidisb0d178d2008-10-24 22:28:18 +0000221 // C++ 9.3.2p1: The type of this in a member function of a class X is X*.
222 // If the member function is declared const, the type of this is const X*,
223 // if the member function is declared volatile, the type of this is
224 // volatile X*, and if the member function is declared const volatile,
225 // the type of this is const volatile X*.
226
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000227 assert(isInstance() && "No 'this' for static methods!");
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000228 QualType ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
Argyrios Kyrtzidis971c4fa2008-10-24 21:46:40 +0000229 ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers());
230 return C.getPointerType(ClassTy).withConst();
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000231}
232
Douglas Gregor7ad83902008-11-05 04:29:56 +0000233CXXBaseOrMemberInitializer::
234CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs)
235 : Args(0), NumArgs(0) {
236 BaseOrMember = reinterpret_cast<uintptr_t>(BaseType.getTypePtr());
237 assert((BaseOrMember & 0x01) == 0 && "Invalid base class type pointer");
238 BaseOrMember |= 0x01;
239
240 if (NumArgs > 0) {
241 this->NumArgs = NumArgs;
242 this->Args = new Expr*[NumArgs];
243 for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
244 this->Args[Idx] = Args[Idx];
245 }
246}
247
248CXXBaseOrMemberInitializer::
Douglas Gregor44b43212008-12-11 16:49:14 +0000249CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs)
Douglas Gregor7ad83902008-11-05 04:29:56 +0000250 : Args(0), NumArgs(0) {
251 BaseOrMember = reinterpret_cast<uintptr_t>(Member);
252 assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer");
253
254 if (NumArgs > 0) {
255 this->NumArgs = NumArgs;
256 this->Args = new Expr*[NumArgs];
257 for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
258 this->Args[Idx] = Args[Idx];
259 }
260}
261
262CXXBaseOrMemberInitializer::~CXXBaseOrMemberInitializer() {
263 delete [] Args;
264}
265
Douglas Gregorb48fe382008-10-31 09:07:45 +0000266CXXConstructorDecl *
267CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000268 SourceLocation L, DeclarationName N,
Douglas Gregorb48fe382008-10-31 09:07:45 +0000269 QualType T, bool isExplicit,
270 bool isInline, bool isImplicitlyDeclared) {
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000271 assert(N.getNameKind() == DeclarationName::CXXConstructorName &&
272 "Name must refer to a constructor");
Douglas Gregorb48fe382008-10-31 09:07:45 +0000273 void *Mem = C.getAllocator().Allocate<CXXConstructorDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000274 return new (Mem) CXXConstructorDecl(RD, L, N, T, isExplicit, isInline,
Douglas Gregorb48fe382008-10-31 09:07:45 +0000275 isImplicitlyDeclared);
276}
277
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000278bool CXXConstructorDecl::isDefaultConstructor() const {
279 // C++ [class.ctor]p5:
Douglas Gregor64bffa92008-11-05 16:20:31 +0000280 // A default constructor for a class X is a constructor of class
281 // X that can be called without an argument.
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000282 return (getNumParams() == 0) ||
Douglas Gregorf03d7c72008-11-05 15:29:30 +0000283 (getNumParams() > 0 && getParamDecl(0)->getDefaultArg() != 0);
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000284}
285
286bool
287CXXConstructorDecl::isCopyConstructor(ASTContext &Context,
288 unsigned &TypeQuals) const {
289 // C++ [class.copy]p2:
Douglas Gregor64bffa92008-11-05 16:20:31 +0000290 // A non-template constructor for class X is a copy constructor
291 // if its first parameter is of type X&, const X&, volatile X& or
292 // const volatile X&, and either there are no other parameters
293 // or else all other parameters have default arguments (8.3.6).
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000294 if ((getNumParams() < 1) ||
295 (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() == 0))
296 return false;
297
298 const ParmVarDecl *Param = getParamDecl(0);
299
300 // Do we have a reference type?
301 const ReferenceType *ParamRefType = Param->getType()->getAsReferenceType();
302 if (!ParamRefType)
303 return false;
304
305 // Is it a reference to our class type?
306 QualType PointeeType
307 = Context.getCanonicalType(ParamRefType->getPointeeType());
308 QualType ClassTy
309 = Context.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
310 if (PointeeType.getUnqualifiedType() != ClassTy)
311 return false;
312
313 // We have a copy constructor.
314 TypeQuals = PointeeType.getCVRQualifiers();
315 return true;
316}
317
Douglas Gregor60d62c22008-10-31 16:23:19 +0000318bool CXXConstructorDecl::isConvertingConstructor() const {
319 // C++ [class.conv.ctor]p1:
320 // A constructor declared without the function-specifier explicit
321 // that can be called with a single parameter specifies a
322 // conversion from the type of its first parameter to the type of
323 // its class. Such a constructor is called a converting
324 // constructor.
325 if (isExplicit())
326 return false;
327
328 return (getNumParams() == 0 &&
329 getType()->getAsFunctionTypeProto()->isVariadic()) ||
330 (getNumParams() == 1) ||
331 (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() != 0);
332}
Douglas Gregorb48fe382008-10-31 09:07:45 +0000333
Douglas Gregor42a552f2008-11-05 20:51:48 +0000334CXXDestructorDecl *
335CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000336 SourceLocation L, DeclarationName N,
Douglas Gregor42a552f2008-11-05 20:51:48 +0000337 QualType T, bool isInline,
338 bool isImplicitlyDeclared) {
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000339 assert(N.getNameKind() == DeclarationName::CXXDestructorName &&
340 "Name must refer to a destructor");
Douglas Gregor42a552f2008-11-05 20:51:48 +0000341 void *Mem = C.getAllocator().Allocate<CXXDestructorDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000342 return new (Mem) CXXDestructorDecl(RD, L, N, T, isInline,
Douglas Gregor42a552f2008-11-05 20:51:48 +0000343 isImplicitlyDeclared);
344}
345
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000346CXXConversionDecl *
347CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000348 SourceLocation L, DeclarationName N,
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000349 QualType T, bool isInline, bool isExplicit) {
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000350 assert(N.getNameKind() == DeclarationName::CXXConversionFunctionName &&
351 "Name must refer to a conversion function");
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000352 void *Mem = C.getAllocator().Allocate<CXXConversionDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000353 return new (Mem) CXXConversionDecl(RD, L, N, T, isInline, isExplicit);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000354}
355
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000356CXXClassVarDecl *CXXClassVarDecl::Create(ASTContext &C, CXXRecordDecl *RD,
357 SourceLocation L, IdentifierInfo *Id,
358 QualType T, ScopedDecl *PrevDecl) {
359 void *Mem = C.getAllocator().Allocate<CXXClassVarDecl>();
360 return new (Mem) CXXClassVarDecl(RD, L, Id, T, PrevDecl);
361}
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000362
363OverloadedFunctionDecl *
364OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC,
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000365 DeclarationName N) {
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000366 void *Mem = C.getAllocator().Allocate<OverloadedFunctionDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000367 return new (Mem) OverloadedFunctionDecl(DC, N);
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000368}
Chris Lattner21ef7ae2008-11-04 16:51:42 +0000369
370LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
Douglas Gregor074149e2009-01-05 19:45:36 +0000371 DeclContext *DC,
Chris Lattner21ef7ae2008-11-04 16:51:42 +0000372 SourceLocation L,
Douglas Gregor074149e2009-01-05 19:45:36 +0000373 LanguageIDs Lang, bool Braces) {
Chris Lattner21ef7ae2008-11-04 16:51:42 +0000374 void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>();
Douglas Gregor074149e2009-01-05 19:45:36 +0000375 return new (Mem) LinkageSpecDecl(DC, L, Lang, Braces);
Douglas Gregorf44515a2008-12-16 22:23:02 +0000376}