blob: 12d715e0684a804509530040b65dfac33555a60c [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
Douglas Gregor2e1cd422008-11-17 14:58:09 +000039CXXRecordDecl::CXXRecordDecl(TagKind TK, DeclContext *DC,
Douglas Gregor7d7e6722008-11-12 23:21:09 +000040 SourceLocation L, IdentifierInfo *Id)
Douglas Gregor44b43212008-12-11 16:49:14 +000041 : RecordDecl(CXXRecord, TK, DC, L, Id),
Douglas Gregor7d7e6722008-11-12 23:21:09 +000042 UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
Douglas Gregor9e7d9de2008-12-15 21:24:18 +000043 UserDeclaredDestructor(false), Aggregate(true), Polymorphic(false),
44 Bases(0), NumBases(0),
Douglas Gregor2e1cd422008-11-17 14:58:09 +000045 Conversions(DC, DeclarationName()) { }
Douglas Gregor7d7e6722008-11-12 23:21:09 +000046
Ted Kremenek4b7c9832008-09-05 17:16:31 +000047CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
48 SourceLocation L, IdentifierInfo *Id,
49 CXXRecordDecl* PrevDecl) {
Ted Kremenek4b7c9832008-09-05 17:16:31 +000050 void *Mem = C.getAllocator().Allocate<CXXRecordDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +000051 CXXRecordDecl* R = new (Mem) CXXRecordDecl(TK, DC, L, Id);
Ted Kremenek4b7c9832008-09-05 17:16:31 +000052 C.getTypeDeclType(R, PrevDecl);
53 return R;
54}
55
Douglas Gregorf8268ae2008-10-22 17:49:05 +000056CXXRecordDecl::~CXXRecordDecl() {
Douglas Gregorf8268ae2008-10-22 17:49:05 +000057 delete [] Bases;
58}
59
Douglas Gregor57c856b2008-10-23 18:13:27 +000060void
61CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
62 unsigned NumBases) {
Douglas Gregor64bffa92008-11-05 16:20:31 +000063 // C++ [dcl.init.aggr]p1:
64 // An aggregate is an array or a class (clause 9) with [...]
65 // no base classes [...].
66 Aggregate = false;
67
Douglas Gregor57c856b2008-10-23 18:13:27 +000068 if (this->Bases)
69 delete [] this->Bases;
70
71 this->Bases = new CXXBaseSpecifier[NumBases];
72 this->NumBases = NumBases;
73 for (unsigned i = 0; i < NumBases; ++i)
74 this->Bases[i] = *Bases[i];
75}
76
Douglas Gregor396b7cd2008-11-03 17:51:48 +000077bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
Douglas Gregor9e7d9de2008-12-15 21:24:18 +000078 QualType ClassType = Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this));
79 DeclarationName ConstructorName
80 = Context.DeclarationNames.getCXXConstructorName(
81 Context.getCanonicalType(ClassType));
82 unsigned TypeQuals;
83 DeclContext::lookup_const_result Lookup
84 = this->lookup(Context, ConstructorName);
85 if (Lookup.first == Lookup.second)
86 return false;
87 else if (OverloadedFunctionDecl *Constructors
88 = dyn_cast<OverloadedFunctionDecl>(*Lookup.first)) {
89 for (OverloadedFunctionDecl::function_const_iterator Con
90 = Constructors->function_begin();
91 Con != Constructors->function_end(); ++Con) {
Douglas Gregor396b7cd2008-11-03 17:51:48 +000092 if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) &&
93 (TypeQuals & QualType::Const != 0))
94 return true;
Douglas Gregor9e7d9de2008-12-15 21:24:18 +000095 }
96 } else if (CXXConstructorDecl *Constructor
97 = dyn_cast<CXXConstructorDecl>(*Lookup.first)) {
98 return Constructor->isCopyConstructor(Context, TypeQuals) &&
99 (TypeQuals & QualType::Const != 0);
Douglas Gregor396b7cd2008-11-03 17:51:48 +0000100 }
101 return false;
102}
103
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000104void
Douglas Gregor9e7d9de2008-12-15 21:24:18 +0000105CXXRecordDecl::addedConstructor(ASTContext &Context,
106 CXXConstructorDecl *ConDecl) {
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000107 if (!ConDecl->isImplicitlyDeclared()) {
108 // Note that we have a user-declared constructor.
109 UserDeclaredConstructor = true;
110
Douglas Gregor64bffa92008-11-05 16:20:31 +0000111 // C++ [dcl.init.aggr]p1:
112 // An aggregate is an array or a class (clause 9) with no
113 // user-declared constructors (12.1) [...].
114 Aggregate = false;
115
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000116 // Note when we have a user-declared copy constructor, which will
117 // suppress the implicit declaration of a copy constructor.
118 if (ConDecl->isCopyConstructor(Context))
119 UserDeclaredCopyConstructor = true;
120 }
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000121}
122
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000123void CXXRecordDecl::addConversionFunction(ASTContext &Context,
124 CXXConversionDecl *ConvDecl) {
125 Conversions.addOverload(ConvDecl);
126}
127
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000128CXXMethodDecl *
129CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
Douglas Gregor10bd3682008-11-17 22:58:34 +0000130 SourceLocation L, DeclarationName N,
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000131 QualType T, bool isStatic, bool isInline,
132 ScopedDecl *PrevDecl) {
133 void *Mem = C.getAllocator().Allocate<CXXMethodDecl>();
Douglas Gregor10bd3682008-11-17 22:58:34 +0000134 return new (Mem) CXXMethodDecl(CXXMethod, RD, L, N, T, isStatic, isInline,
135 PrevDecl);
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000136}
137
138QualType CXXMethodDecl::getThisType(ASTContext &C) const {
Argyrios Kyrtzidisb0d178d2008-10-24 22:28:18 +0000139 // C++ 9.3.2p1: The type of this in a member function of a class X is X*.
140 // If the member function is declared const, the type of this is const X*,
141 // if the member function is declared volatile, the type of this is
142 // volatile X*, and if the member function is declared const volatile,
143 // the type of this is const volatile X*.
144
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000145 assert(isInstance() && "No 'this' for static methods!");
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000146 QualType ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
Argyrios Kyrtzidis971c4fa2008-10-24 21:46:40 +0000147 ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers());
148 return C.getPointerType(ClassTy).withConst();
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000149}
150
Douglas Gregor7ad83902008-11-05 04:29:56 +0000151CXXBaseOrMemberInitializer::
152CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs)
153 : Args(0), NumArgs(0) {
154 BaseOrMember = reinterpret_cast<uintptr_t>(BaseType.getTypePtr());
155 assert((BaseOrMember & 0x01) == 0 && "Invalid base class type pointer");
156 BaseOrMember |= 0x01;
157
158 if (NumArgs > 0) {
159 this->NumArgs = NumArgs;
160 this->Args = new Expr*[NumArgs];
161 for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
162 this->Args[Idx] = Args[Idx];
163 }
164}
165
166CXXBaseOrMemberInitializer::
Douglas Gregor44b43212008-12-11 16:49:14 +0000167CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs)
Douglas Gregor7ad83902008-11-05 04:29:56 +0000168 : Args(0), NumArgs(0) {
169 BaseOrMember = reinterpret_cast<uintptr_t>(Member);
170 assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer");
171
172 if (NumArgs > 0) {
173 this->NumArgs = NumArgs;
174 this->Args = new Expr*[NumArgs];
175 for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
176 this->Args[Idx] = Args[Idx];
177 }
178}
179
180CXXBaseOrMemberInitializer::~CXXBaseOrMemberInitializer() {
181 delete [] Args;
182}
183
Douglas Gregorb48fe382008-10-31 09:07:45 +0000184CXXConstructorDecl *
185CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000186 SourceLocation L, DeclarationName N,
Douglas Gregorb48fe382008-10-31 09:07:45 +0000187 QualType T, bool isExplicit,
188 bool isInline, bool isImplicitlyDeclared) {
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000189 assert(N.getNameKind() == DeclarationName::CXXConstructorName &&
190 "Name must refer to a constructor");
Douglas Gregorb48fe382008-10-31 09:07:45 +0000191 void *Mem = C.getAllocator().Allocate<CXXConstructorDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000192 return new (Mem) CXXConstructorDecl(RD, L, N, T, isExplicit, isInline,
Douglas Gregorb48fe382008-10-31 09:07:45 +0000193 isImplicitlyDeclared);
194}
195
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000196bool CXXConstructorDecl::isDefaultConstructor() const {
197 // C++ [class.ctor]p5:
Douglas Gregor64bffa92008-11-05 16:20:31 +0000198 // A default constructor for a class X is a constructor of class
199 // X that can be called without an argument.
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000200 return (getNumParams() == 0) ||
Douglas Gregorf03d7c72008-11-05 15:29:30 +0000201 (getNumParams() > 0 && getParamDecl(0)->getDefaultArg() != 0);
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000202}
203
204bool
205CXXConstructorDecl::isCopyConstructor(ASTContext &Context,
206 unsigned &TypeQuals) const {
207 // C++ [class.copy]p2:
Douglas Gregor64bffa92008-11-05 16:20:31 +0000208 // A non-template constructor for class X is a copy constructor
209 // if its first parameter is of type X&, const X&, volatile X& or
210 // const volatile X&, and either there are no other parameters
211 // or else all other parameters have default arguments (8.3.6).
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000212 if ((getNumParams() < 1) ||
213 (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() == 0))
214 return false;
215
216 const ParmVarDecl *Param = getParamDecl(0);
217
218 // Do we have a reference type?
219 const ReferenceType *ParamRefType = Param->getType()->getAsReferenceType();
220 if (!ParamRefType)
221 return false;
222
223 // Is it a reference to our class type?
224 QualType PointeeType
225 = Context.getCanonicalType(ParamRefType->getPointeeType());
226 QualType ClassTy
227 = Context.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
228 if (PointeeType.getUnqualifiedType() != ClassTy)
229 return false;
230
231 // We have a copy constructor.
232 TypeQuals = PointeeType.getCVRQualifiers();
233 return true;
234}
235
Douglas Gregor60d62c22008-10-31 16:23:19 +0000236bool CXXConstructorDecl::isConvertingConstructor() const {
237 // C++ [class.conv.ctor]p1:
238 // A constructor declared without the function-specifier explicit
239 // that can be called with a single parameter specifies a
240 // conversion from the type of its first parameter to the type of
241 // its class. Such a constructor is called a converting
242 // constructor.
243 if (isExplicit())
244 return false;
245
246 return (getNumParams() == 0 &&
247 getType()->getAsFunctionTypeProto()->isVariadic()) ||
248 (getNumParams() == 1) ||
249 (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() != 0);
250}
Douglas Gregorb48fe382008-10-31 09:07:45 +0000251
Douglas Gregor42a552f2008-11-05 20:51:48 +0000252CXXDestructorDecl *
253CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000254 SourceLocation L, DeclarationName N,
Douglas Gregor42a552f2008-11-05 20:51:48 +0000255 QualType T, bool isInline,
256 bool isImplicitlyDeclared) {
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000257 assert(N.getNameKind() == DeclarationName::CXXDestructorName &&
258 "Name must refer to a destructor");
Douglas Gregor42a552f2008-11-05 20:51:48 +0000259 void *Mem = C.getAllocator().Allocate<CXXDestructorDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000260 return new (Mem) CXXDestructorDecl(RD, L, N, T, isInline,
Douglas Gregor42a552f2008-11-05 20:51:48 +0000261 isImplicitlyDeclared);
262}
263
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000264CXXConversionDecl *
265CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000266 SourceLocation L, DeclarationName N,
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000267 QualType T, bool isInline, bool isExplicit) {
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000268 assert(N.getNameKind() == DeclarationName::CXXConversionFunctionName &&
269 "Name must refer to a conversion function");
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000270 void *Mem = C.getAllocator().Allocate<CXXConversionDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000271 return new (Mem) CXXConversionDecl(RD, L, N, T, isInline, isExplicit);
Douglas Gregor2f1bc522008-11-07 20:08:42 +0000272}
273
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000274CXXClassVarDecl *CXXClassVarDecl::Create(ASTContext &C, CXXRecordDecl *RD,
275 SourceLocation L, IdentifierInfo *Id,
276 QualType T, ScopedDecl *PrevDecl) {
277 void *Mem = C.getAllocator().Allocate<CXXClassVarDecl>();
278 return new (Mem) CXXClassVarDecl(RD, L, Id, T, PrevDecl);
279}
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000280
281OverloadedFunctionDecl *
282OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC,
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000283 DeclarationName N) {
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000284 void *Mem = C.getAllocator().Allocate<OverloadedFunctionDecl>();
Douglas Gregor2e1cd422008-11-17 14:58:09 +0000285 return new (Mem) OverloadedFunctionDecl(DC, N);
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000286}
Chris Lattner21ef7ae2008-11-04 16:51:42 +0000287
288LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
289 SourceLocation L,
290 LanguageIDs Lang, Decl *D) {
291 void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>();
292 return new (Mem) LinkageSpecDecl(L, Lang, D);
293}
294