blob: d213385d918be43469ced865017c18770055eae0 [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 Gregor2e1cd422008-11-17 14:58:09 +000040CXXRecordDecl::CXXRecordDecl(TagKind TK, DeclContext *DC,
Douglas Gregor7d7e6722008-11-12 23:21:09 +000041 SourceLocation L, IdentifierInfo *Id)
Douglas Gregor44b43212008-12-11 16:49:14 +000042 : RecordDecl(CXXRecord, TK, DC, L, Id),
Douglas Gregor7d7e6722008-11-12 23:21:09 +000043 UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
Douglas Gregor9e7d9de2008-12-15 21:24:18 +000044 UserDeclaredDestructor(false), Aggregate(true), Polymorphic(false),
45 Bases(0), NumBases(0),
Douglas Gregor2e1cd422008-11-17 14:58:09 +000046 Conversions(DC, DeclarationName()) { }
Douglas Gregor7d7e6722008-11-12 23:21:09 +000047
Ted Kremenek4b7c9832008-09-05 17:16:31 +000048CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
49 SourceLocation L, IdentifierInfo *Id,
50 CXXRecordDecl* PrevDecl) {
Ted Kremenek4b7c9832008-09-05 17:16:31 +000051 void *Mem = C.getAllocator().Allocate<CXXRecordDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +000052 CXXRecordDecl* R = new (Mem) CXXRecordDecl(TK, DC, L, Id);
Ted Kremenek4b7c9832008-09-05 17:16:31 +000053 C.getTypeDeclType(R, PrevDecl);
54 return R;
55}
56
Douglas Gregorf8268ae2008-10-22 17:49:05 +000057CXXRecordDecl::~CXXRecordDecl() {
Douglas Gregorf8268ae2008-10-22 17:49:05 +000058 delete [] Bases;
59}
60
Douglas Gregor57c856b2008-10-23 18:13:27 +000061void
62CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
63 unsigned NumBases) {
Douglas Gregor64bffa92008-11-05 16:20:31 +000064 // C++ [dcl.init.aggr]p1:
65 // An aggregate is an array or a class (clause 9) with [...]
66 // no base classes [...].
67 Aggregate = false;
68
Douglas Gregor57c856b2008-10-23 18:13:27 +000069 if (this->Bases)
70 delete [] this->Bases;
71
72 this->Bases = new CXXBaseSpecifier[NumBases];
73 this->NumBases = NumBases;
74 for (unsigned i = 0; i < NumBases; ++i)
75 this->Bases[i] = *Bases[i];
76}
77
Douglas Gregor396b7cd2008-11-03 17:51:48 +000078bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
Douglas Gregor9e7d9de2008-12-15 21:24:18 +000079 QualType ClassType = Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this));
80 DeclarationName ConstructorName
81 = Context.DeclarationNames.getCXXConstructorName(
82 Context.getCanonicalType(ClassType));
83 unsigned TypeQuals;
Douglas Gregorfdfab6b2008-12-23 21:31:30 +000084 DeclContext::lookup_const_iterator Con, ConEnd;
85 for (llvm::tie(Con, ConEnd) = this->lookup(Context, ConstructorName);
86 Con != ConEnd; ++Con) {
Douglas Gregor396b7cd2008-11-03 17:51:48 +000087 if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) &&
Eli Friedmane8e32052008-12-16 20:06:41 +000088 (TypeQuals & QualType::Const) != 0)
Douglas Gregor396b7cd2008-11-03 17:51:48 +000089 return true;
90 }
Douglas Gregorfdfab6b2008-12-23 21:31:30 +000091
Douglas Gregor396b7cd2008-11-03 17:51:48 +000092 return false;
93}
94
Douglas Gregor030ff0c2008-10-31 20:25:05 +000095void
Douglas Gregor9e7d9de2008-12-15 21:24:18 +000096CXXRecordDecl::addedConstructor(ASTContext &Context,
97 CXXConstructorDecl *ConDecl) {
Douglas Gregor030ff0c2008-10-31 20:25:05 +000098 if (!ConDecl->isImplicitlyDeclared()) {
99 // Note that we have a user-declared constructor.
100 UserDeclaredConstructor = true;
101
Douglas Gregor64bffa92008-11-05 16:20:31 +0000102 // C++ [dcl.init.aggr]p1:
103 // An aggregate is an array or a class (clause 9) with no
104 // user-declared constructors (12.1) [...].
105 Aggregate = false;
106
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000107 // Note when we have a user-declared copy constructor, which will
108 // suppress the implicit declaration of a copy constructor.
109 if (ConDecl->isCopyConstructor(Context))
110 UserDeclaredCopyConstructor = true;
111 }
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000112}
113
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000114void CXXRecordDecl::addConversionFunction(ASTContext &Context,
115 CXXConversionDecl *ConvDecl) {
116 Conversions.addOverload(ConvDecl);
117}
118
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000119CXXMethodDecl *
120CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
Douglas Gregor10bd3682008-11-17 22:58:34 +0000121 SourceLocation L, DeclarationName N,
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000122 QualType T, bool isStatic, bool isInline,
123 ScopedDecl *PrevDecl) {
124 void *Mem = C.getAllocator().Allocate<CXXMethodDecl>();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000125 return new (Mem) CXXMethodDecl(CXXMethod, RD, L, N, T, isStatic, isInline,
126 PrevDecl);
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000127}
128
129QualType CXXMethodDecl::getThisType(ASTContext &C) const {
Argyrios Kyrtzidisb0d178d2008-10-24 22:28:18 +0000130 // C++ 9.3.2p1: The type of this in a member function of a class X is X*.
131 // If the member function is declared const, the type of this is const X*,
132 // if the member function is declared volatile, the type of this is
133 // volatile X*, and if the member function is declared const volatile,
134 // the type of this is const volatile X*.
135
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000136 assert(isInstance() && "No 'this' for static methods!");
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000137 QualType ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
Argyrios Kyrtzidis971c4fa2008-10-24 21:46:40 +0000138 ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers());
139 return C.getPointerType(ClassTy).withConst();
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000140}
141
Douglas Gregor7ad83902008-11-05 04:29:56 +0000142CXXBaseOrMemberInitializer::
143CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs)
144 : Args(0), NumArgs(0) {
145 BaseOrMember = reinterpret_cast<uintptr_t>(BaseType.getTypePtr());
146 assert((BaseOrMember & 0x01) == 0 && "Invalid base class type pointer");
147 BaseOrMember |= 0x01;
148
149 if (NumArgs > 0) {
150 this->NumArgs = NumArgs;
151 this->Args = new Expr*[NumArgs];
152 for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
153 this->Args[Idx] = Args[Idx];
154 }
155}
156
157CXXBaseOrMemberInitializer::
Douglas Gregor44b43212008-12-11 16:49:14 +0000158CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs)
Douglas Gregor7ad83902008-11-05 04:29:56 +0000159 : Args(0), NumArgs(0) {
160 BaseOrMember = reinterpret_cast<uintptr_t>(Member);
161 assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer");
162
163 if (NumArgs > 0) {
164 this->NumArgs = NumArgs;
165 this->Args = new Expr*[NumArgs];
166 for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
167 this->Args[Idx] = Args[Idx];
168 }
169}
170
171CXXBaseOrMemberInitializer::~CXXBaseOrMemberInitializer() {
172 delete [] Args;
173}
174
Douglas Gregorb48fe382008-10-31 09:07:45 +0000175CXXConstructorDecl *
176CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000177 SourceLocation L, DeclarationName N,
Douglas Gregorb48fe382008-10-31 09:07:45 +0000178 QualType T, bool isExplicit,
179 bool isInline, bool isImplicitlyDeclared) {
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000180 assert(N.getNameKind() == DeclarationName::CXXConstructorName &&
181 "Name must refer to a constructor");
Douglas Gregorb48fe382008-10-31 09:07:45 +0000182 void *Mem = C.getAllocator().Allocate<CXXConstructorDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000183 return new (Mem) CXXConstructorDecl(RD, L, N, T, isExplicit, isInline,
Douglas Gregorb48fe382008-10-31 09:07:45 +0000184 isImplicitlyDeclared);
185}
186
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000187bool CXXConstructorDecl::isDefaultConstructor() const {
188 // C++ [class.ctor]p5:
Douglas Gregor64bffa92008-11-05 16:20:31 +0000189 // A default constructor for a class X is a constructor of class
190 // X that can be called without an argument.
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000191 return (getNumParams() == 0) ||
Douglas Gregorf03d7c72008-11-05 15:29:30 +0000192 (getNumParams() > 0 && getParamDecl(0)->getDefaultArg() != 0);
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000193}
194
195bool
196CXXConstructorDecl::isCopyConstructor(ASTContext &Context,
197 unsigned &TypeQuals) const {
198 // C++ [class.copy]p2:
Douglas Gregor64bffa92008-11-05 16:20:31 +0000199 // A non-template constructor for class X is a copy constructor
200 // if its first parameter is of type X&, const X&, volatile X& or
201 // const volatile X&, and either there are no other parameters
202 // or else all other parameters have default arguments (8.3.6).
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000203 if ((getNumParams() < 1) ||
204 (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() == 0))
205 return false;
206
207 const ParmVarDecl *Param = getParamDecl(0);
208
209 // Do we have a reference type?
210 const ReferenceType *ParamRefType = Param->getType()->getAsReferenceType();
211 if (!ParamRefType)
212 return false;
213
214 // Is it a reference to our class type?
215 QualType PointeeType
216 = Context.getCanonicalType(ParamRefType->getPointeeType());
217 QualType ClassTy
218 = Context.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
219 if (PointeeType.getUnqualifiedType() != ClassTy)
220 return false;
221
222 // We have a copy constructor.
223 TypeQuals = PointeeType.getCVRQualifiers();
224 return true;
225}
226
Douglas Gregor60d62c22008-10-31 16:23:19 +0000227bool CXXConstructorDecl::isConvertingConstructor() const {
228 // C++ [class.conv.ctor]p1:
229 // A constructor declared without the function-specifier explicit
230 // that can be called with a single parameter specifies a
231 // conversion from the type of its first parameter to the type of
232 // its class. Such a constructor is called a converting
233 // constructor.
234 if (isExplicit())
235 return false;
236
237 return (getNumParams() == 0 &&
238 getType()->getAsFunctionTypeProto()->isVariadic()) ||
239 (getNumParams() == 1) ||
240 (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() != 0);
241}
Douglas Gregorb48fe382008-10-31 09:07:45 +0000242
Douglas Gregor42a552f2008-11-05 20:51:48 +0000243CXXDestructorDecl *
244CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000245 SourceLocation L, DeclarationName N,
Douglas Gregor42a552f2008-11-05 20:51:48 +0000246 QualType T, bool isInline,
247 bool isImplicitlyDeclared) {
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000248 assert(N.getNameKind() == DeclarationName::CXXDestructorName &&
249 "Name must refer to a destructor");
Douglas Gregor42a552f2008-11-05 20:51:48 +0000250 void *Mem = C.getAllocator().Allocate<CXXDestructorDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000251 return new (Mem) CXXDestructorDecl(RD, L, N, T, isInline,
Douglas Gregor42a552f2008-11-05 20:51:48 +0000252 isImplicitlyDeclared);
253}
254
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000255CXXConversionDecl *
256CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000257 SourceLocation L, DeclarationName N,
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000258 QualType T, bool isInline, bool isExplicit) {
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000259 assert(N.getNameKind() == DeclarationName::CXXConversionFunctionName &&
260 "Name must refer to a conversion function");
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000261 void *Mem = C.getAllocator().Allocate<CXXConversionDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000262 return new (Mem) CXXConversionDecl(RD, L, N, T, isInline, isExplicit);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000263}
264
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000265CXXClassVarDecl *CXXClassVarDecl::Create(ASTContext &C, CXXRecordDecl *RD,
266 SourceLocation L, IdentifierInfo *Id,
267 QualType T, ScopedDecl *PrevDecl) {
268 void *Mem = C.getAllocator().Allocate<CXXClassVarDecl>();
269 return new (Mem) CXXClassVarDecl(RD, L, Id, T, PrevDecl);
270}
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000271
272OverloadedFunctionDecl *
273OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC,
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000274 DeclarationName N) {
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000275 void *Mem = C.getAllocator().Allocate<OverloadedFunctionDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000276 return new (Mem) OverloadedFunctionDecl(DC, N);
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000277}
Chris Lattner21ef7ae2008-11-04 16:51:42 +0000278
Douglas Gregorf44515a2008-12-16 22:23:02 +0000279LinkageSpecDecl::LinkageSpecDecl(SourceLocation L, LanguageIDs lang,
280 Decl **InDecls, unsigned InNumDecls)
281 : Decl(LinkageSpec, L), Language(lang), HadBraces(true),
282 Decls(0), NumDecls(InNumDecls) {
283 Decl **NewDecls = new Decl*[NumDecls];
284 for (unsigned I = 0; I < NumDecls; ++I)
285 NewDecls[I] = InDecls[I];
286 Decls = NewDecls;
287}
288
289LinkageSpecDecl::~LinkageSpecDecl() {
290 if (HadBraces)
291 delete [] (Decl**)Decls;
292}
293
Chris Lattner21ef7ae2008-11-04 16:51:42 +0000294LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
295 SourceLocation L,
296 LanguageIDs Lang, Decl *D) {
297 void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>();
298 return new (Mem) LinkageSpecDecl(L, Lang, D);
299}
300
Douglas Gregorf44515a2008-12-16 22:23:02 +0000301LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
302 SourceLocation L,
303 LanguageIDs Lang,
304 Decl **Decls, unsigned NumDecls) {
305 void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>();
306 return new (Mem) LinkageSpecDecl(L, Lang, Decls, NumDecls);
307}
308
309LinkageSpecDecl::decl_const_iterator LinkageSpecDecl::decls_begin() const {
310 if (hasBraces()) return (Decl**)Decls;
311 else return (Decl**)&Decls;
312}
313
314LinkageSpecDecl::decl_iterator LinkageSpecDecl::decls_end() const {
315 if (hasBraces()) return (Decl**)Decls + NumDecls;
316 else return (Decl**)&Decls + 1;
317}