blob: 9f20ac816395469be016f2565c24ffe7b387e0e4 [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"
16using namespace clang;
17
18//===----------------------------------------------------------------------===//
19// Decl Allocation/Deallocation Method Implementations
20//===----------------------------------------------------------------------===//
21
22CXXFieldDecl *CXXFieldDecl::Create(ASTContext &C, CXXRecordDecl *RD,
23 SourceLocation L, IdentifierInfo *Id,
24 QualType T, Expr *BW) {
25 void *Mem = C.getAllocator().Allocate<CXXFieldDecl>();
26 return new (Mem) CXXFieldDecl(RD, L, Id, T, BW);
27}
28
29CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
30 SourceLocation L, IdentifierInfo *Id,
31 CXXRecordDecl* PrevDecl) {
Ted Kremenek4b7c9832008-09-05 17:16:31 +000032 void *Mem = C.getAllocator().Allocate<CXXRecordDecl>();
Argyrios Kyrtzidis35bc0822008-10-15 00:42:39 +000033 CXXRecordDecl* R = new (Mem) CXXRecordDecl(TK, DC, L, Id);
Ted Kremenek4b7c9832008-09-05 17:16:31 +000034 C.getTypeDeclType(R, PrevDecl);
35 return R;
36}
37
Douglas Gregorf8268ae2008-10-22 17:49:05 +000038CXXRecordDecl::~CXXRecordDecl() {
Douglas Gregorf8268ae2008-10-22 17:49:05 +000039 delete [] Bases;
40}
41
Douglas Gregorb48fe382008-10-31 09:07:45 +000042void CXXRecordDecl::Destroy(ASTContext &C) {
43 for (OverloadedFunctionDecl::function_iterator func
44 = Constructors.function_begin();
45 func != Constructors.function_end(); ++func)
46 (*func)->Destroy(C);
47 RecordDecl::Destroy(C);
48}
49
Douglas Gregor57c856b2008-10-23 18:13:27 +000050void
51CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
52 unsigned NumBases) {
53 if (this->Bases)
54 delete [] this->Bases;
55
56 this->Bases = new CXXBaseSpecifier[NumBases];
57 this->NumBases = NumBases;
58 for (unsigned i = 0; i < NumBases; ++i)
59 this->Bases[i] = *Bases[i];
60}
61
Douglas Gregor396b7cd2008-11-03 17:51:48 +000062bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
63 for (OverloadedFunctionDecl::function_const_iterator Con
64 = Constructors.function_begin();
65 Con != Constructors.function_end(); ++Con) {
66 unsigned TypeQuals;
67 if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) &&
68 (TypeQuals & QualType::Const != 0))
69 return true;
70 }
71 return false;
72}
73
Douglas Gregor030ff0c2008-10-31 20:25:05 +000074void
75CXXRecordDecl::addConstructor(ASTContext &Context,
76 CXXConstructorDecl *ConDecl) {
77 if (!ConDecl->isImplicitlyDeclared()) {
78 // Note that we have a user-declared constructor.
79 UserDeclaredConstructor = true;
80
81 // Note when we have a user-declared copy constructor, which will
82 // suppress the implicit declaration of a copy constructor.
83 if (ConDecl->isCopyConstructor(Context))
84 UserDeclaredCopyConstructor = true;
85 }
86
87 Constructors.addOverload(ConDecl);
88}
89
Ted Kremenek4b7c9832008-09-05 17:16:31 +000090CXXMethodDecl *
91CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
92 SourceLocation L, IdentifierInfo *Id,
93 QualType T, bool isStatic, bool isInline,
94 ScopedDecl *PrevDecl) {
95 void *Mem = C.getAllocator().Allocate<CXXMethodDecl>();
96 return new (Mem) CXXMethodDecl(RD, L, Id, T, isStatic, isInline, PrevDecl);
97}
98
99QualType CXXMethodDecl::getThisType(ASTContext &C) const {
Argyrios Kyrtzidisb0d178d2008-10-24 22:28:18 +0000100 // C++ 9.3.2p1: The type of this in a member function of a class X is X*.
101 // If the member function is declared const, the type of this is const X*,
102 // if the member function is declared volatile, the type of this is
103 // volatile X*, and if the member function is declared const volatile,
104 // the type of this is const volatile X*.
105
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000106 assert(isInstance() && "No 'this' for static methods!");
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000107 QualType ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
Argyrios Kyrtzidis971c4fa2008-10-24 21:46:40 +0000108 ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers());
109 return C.getPointerType(ClassTy).withConst();
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000110}
111
Douglas Gregor7ad83902008-11-05 04:29:56 +0000112CXXBaseOrMemberInitializer::
113CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs)
114 : Args(0), NumArgs(0) {
115 BaseOrMember = reinterpret_cast<uintptr_t>(BaseType.getTypePtr());
116 assert((BaseOrMember & 0x01) == 0 && "Invalid base class type pointer");
117 BaseOrMember |= 0x01;
118
119 if (NumArgs > 0) {
120 this->NumArgs = NumArgs;
121 this->Args = new Expr*[NumArgs];
122 for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
123 this->Args[Idx] = Args[Idx];
124 }
125}
126
127CXXBaseOrMemberInitializer::
128CXXBaseOrMemberInitializer(CXXFieldDecl *Member, Expr **Args, unsigned NumArgs)
129 : Args(0), NumArgs(0) {
130 BaseOrMember = reinterpret_cast<uintptr_t>(Member);
131 assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer");
132
133 if (NumArgs > 0) {
134 this->NumArgs = NumArgs;
135 this->Args = new Expr*[NumArgs];
136 for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
137 this->Args[Idx] = Args[Idx];
138 }
139}
140
141CXXBaseOrMemberInitializer::~CXXBaseOrMemberInitializer() {
142 delete [] Args;
143}
144
Douglas Gregorb48fe382008-10-31 09:07:45 +0000145CXXConstructorDecl *
146CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
147 SourceLocation L, IdentifierInfo *Id,
148 QualType T, bool isExplicit,
149 bool isInline, bool isImplicitlyDeclared) {
150 void *Mem = C.getAllocator().Allocate<CXXConstructorDecl>();
151 return new (Mem) CXXConstructorDecl(RD, L, Id, T, isExplicit, isInline,
152 isImplicitlyDeclared);
153}
154
Douglas Gregor030ff0c2008-10-31 20:25:05 +0000155bool CXXConstructorDecl::isDefaultConstructor() const {
156 // C++ [class.ctor]p5:
157 //
158 // A default constructor for a class X is a constructor of class
159 // X that can be called without an argument.
160 return (getNumParams() == 0) ||
161 (getNumParams() > 0 & getParamDecl(1)->getDefaultArg() != 0);
162}
163
164bool
165CXXConstructorDecl::isCopyConstructor(ASTContext &Context,
166 unsigned &TypeQuals) const {
167 // C++ [class.copy]p2:
168 // A non-template constructor for class X is a copy constructor
169 // if its first parameter is of type X&, const X&, volatile X& or
170 // const volatile X&, and either there are no other parameters
171 // or else all other parameters have default arguments (8.3.6).
172 if ((getNumParams() < 1) ||
173 (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() == 0))
174 return false;
175
176 const ParmVarDecl *Param = getParamDecl(0);
177
178 // Do we have a reference type?
179 const ReferenceType *ParamRefType = Param->getType()->getAsReferenceType();
180 if (!ParamRefType)
181 return false;
182
183 // Is it a reference to our class type?
184 QualType PointeeType
185 = Context.getCanonicalType(ParamRefType->getPointeeType());
186 QualType ClassTy
187 = Context.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
188 if (PointeeType.getUnqualifiedType() != ClassTy)
189 return false;
190
191 // We have a copy constructor.
192 TypeQuals = PointeeType.getCVRQualifiers();
193 return true;
194}
195
Douglas Gregor60d62c22008-10-31 16:23:19 +0000196bool CXXConstructorDecl::isConvertingConstructor() const {
197 // C++ [class.conv.ctor]p1:
198 // A constructor declared without the function-specifier explicit
199 // that can be called with a single parameter specifies a
200 // conversion from the type of its first parameter to the type of
201 // its class. Such a constructor is called a converting
202 // constructor.
203 if (isExplicit())
204 return false;
205
206 return (getNumParams() == 0 &&
207 getType()->getAsFunctionTypeProto()->isVariadic()) ||
208 (getNumParams() == 1) ||
209 (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() != 0);
210}
Douglas Gregorb48fe382008-10-31 09:07:45 +0000211
Ted Kremenek4b7c9832008-09-05 17:16:31 +0000212CXXClassVarDecl *CXXClassVarDecl::Create(ASTContext &C, CXXRecordDecl *RD,
213 SourceLocation L, IdentifierInfo *Id,
214 QualType T, ScopedDecl *PrevDecl) {
215 void *Mem = C.getAllocator().Allocate<CXXClassVarDecl>();
216 return new (Mem) CXXClassVarDecl(RD, L, Id, T, PrevDecl);
217}
Douglas Gregor8e9bebd2008-10-21 16:13:35 +0000218
219OverloadedFunctionDecl *
220OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC,
221 IdentifierInfo *Id) {
222 void *Mem = C.getAllocator().Allocate<OverloadedFunctionDecl>();
223 return new (Mem) OverloadedFunctionDecl(DC, Id);
224}
Chris Lattner21ef7ae2008-11-04 16:51:42 +0000225
226LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
227 SourceLocation L,
228 LanguageIDs Lang, Decl *D) {
229 void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>();
230 return new (Mem) LinkageSpecDecl(L, Lang, D);
231}
232