DeclCXX.cpp revision 6ab3524f72a6e64aa04973fa9433b5559abb3525
1//===--- 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/DeclTemplate.h"
16#include "clang/AST/ASTContext.h"
17#include "clang/AST/Expr.h"
18#include "clang/Basic/IdentifierTable.h"
19#include "llvm/ADT/STLExtras.h"
20using namespace clang;
21
22//===----------------------------------------------------------------------===//
23// Decl Allocation/Deallocation Method Implementations
24//===----------------------------------------------------------------------===//
25
26CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC,
27                             SourceLocation L, IdentifierInfo *Id)
28  : RecordDecl(K, TK, DC, L, Id),
29    UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
30    UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false),
31    Aggregate(true), PlainOldData(true), Polymorphic(false), Abstract(false),
32    Bases(0), NumBases(0), Conversions(DC, DeclarationName()),
33    TemplateOrInstantiation() { }
34
35CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
36                                     SourceLocation L, IdentifierInfo *Id,
37                                     CXXRecordDecl* PrevDecl) {
38  CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TK, DC, L, Id);
39  C.getTypeDeclType(R, PrevDecl);
40  return R;
41}
42
43CXXRecordDecl::~CXXRecordDecl() {
44  delete [] Bases;
45}
46
47void
48CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
49                        unsigned NumBases) {
50  // C++ [dcl.init.aggr]p1:
51  //   An aggregate is an array or a class (clause 9) with [...]
52  //   no base classes [...].
53  Aggregate = false;
54
55  if (this->Bases)
56    delete [] this->Bases;
57
58  // FIXME: allocate using the ASTContext
59  this->Bases = new CXXBaseSpecifier[NumBases];
60  this->NumBases = NumBases;
61  for (unsigned i = 0; i < NumBases; ++i)
62    this->Bases[i] = *Bases[i];
63}
64
65bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
66  QualType ClassType
67    = Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this));
68  DeclarationName ConstructorName
69    = Context.DeclarationNames.getCXXConstructorName(
70                                           Context.getCanonicalType(ClassType));
71  unsigned TypeQuals;
72  DeclContext::lookup_const_iterator Con, ConEnd;
73  for (llvm::tie(Con, ConEnd) = this->lookup(Context, ConstructorName);
74       Con != ConEnd; ++Con) {
75    if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) &&
76        (TypeQuals & QualType::Const) != 0)
77      return true;
78  }
79
80  return false;
81}
82
83bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context) const {
84  QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
85    const_cast<CXXRecordDecl*>(this)));
86  DeclarationName OpName =Context.DeclarationNames.getCXXOperatorName(OO_Equal);
87
88  DeclContext::lookup_const_iterator Op, OpEnd;
89  for (llvm::tie(Op, OpEnd) = this->lookup(Context, OpName);
90       Op != OpEnd; ++Op) {
91    // C++ [class.copy]p9:
92    //   A user-declared copy assignment operator is a non-static non-template
93    //   member function of class X with exactly one parameter of type X, X&,
94    //   const X&, volatile X& or const volatile X&.
95    const CXXMethodDecl* Method = cast<CXXMethodDecl>(*Op);
96    if (Method->isStatic())
97      continue;
98    // TODO: Skip templates? Or is this implicitly done due to parameter types?
99    const FunctionProtoType *FnType =
100      Method->getType()->getAsFunctionProtoType();
101    assert(FnType && "Overloaded operator has no prototype.");
102    // Don't assert on this; an invalid decl might have been left in the AST.
103    if (FnType->getNumArgs() != 1 || FnType->isVariadic())
104      continue;
105    bool AcceptsConst = true;
106    QualType ArgType = FnType->getArgType(0);
107    if (const LValueReferenceType *Ref = ArgType->getAsLValueReferenceType()) {
108      ArgType = Ref->getPointeeType();
109      // Is it a non-const lvalue reference?
110      if (!ArgType.isConstQualified())
111        AcceptsConst = false;
112    }
113    if (Context.getCanonicalType(ArgType).getUnqualifiedType() != ClassType)
114      continue;
115
116    // We have a single argument of type cv X or cv X&, i.e. we've found the
117    // copy assignment operator. Return whether it accepts const arguments.
118    return AcceptsConst;
119  }
120  assert(isInvalidDecl() &&
121         "No copy assignment operator declared in valid code.");
122  return false;
123}
124
125void
126CXXRecordDecl::addedConstructor(ASTContext &Context,
127                                CXXConstructorDecl *ConDecl) {
128  if (!ConDecl->isImplicit()) {
129    // Note that we have a user-declared constructor.
130    UserDeclaredConstructor = true;
131
132    // C++ [dcl.init.aggr]p1:
133    //   An aggregate is an array or a class (clause 9) with no
134    //   user-declared constructors (12.1) [...].
135    Aggregate = false;
136
137    // C++ [class]p4:
138    //   A POD-struct is an aggregate class [...]
139    PlainOldData = false;
140
141    // Note when we have a user-declared copy constructor, which will
142    // suppress the implicit declaration of a copy constructor.
143    if (ConDecl->isCopyConstructor(Context))
144      UserDeclaredCopyConstructor = true;
145  }
146}
147
148void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context,
149                                            CXXMethodDecl *OpDecl) {
150  // We're interested specifically in copy assignment operators.
151  // Unlike addedConstructor, this method is not called for implicit
152  // declarations.
153  const FunctionProtoType *FnType = OpDecl->getType()->getAsFunctionProtoType();
154  assert(FnType && "Overloaded operator has no proto function type.");
155  assert(FnType->getNumArgs() == 1 && !FnType->isVariadic());
156  QualType ArgType = FnType->getArgType(0);
157  if (const LValueReferenceType *Ref = ArgType->getAsLValueReferenceType())
158    ArgType = Ref->getPointeeType();
159
160  ArgType = ArgType.getUnqualifiedType();
161  QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
162    const_cast<CXXRecordDecl*>(this)));
163
164  if (ClassType != Context.getCanonicalType(ArgType))
165    return;
166
167  // This is a copy assignment operator.
168  // Suppress the implicit declaration of a copy constructor.
169  UserDeclaredCopyAssignment = true;
170
171  // C++ [class]p4:
172  //   A POD-struct is an aggregate class that [...] has no user-defined copy
173  //   assignment operator [...].
174  PlainOldData = false;
175}
176
177void CXXRecordDecl::addConversionFunction(ASTContext &Context,
178                                          CXXConversionDecl *ConvDecl) {
179  Conversions.addOverload(ConvDecl);
180}
181
182CXXMethodDecl *
183CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
184                      SourceLocation L, DeclarationName N,
185                      QualType T, bool isStatic, bool isInline) {
186  return new (C) CXXMethodDecl(CXXMethod, RD, L, N, T, isStatic, isInline);
187}
188
189QualType CXXMethodDecl::getThisType(ASTContext &C) const {
190  // C++ 9.3.2p1: The type of this in a member function of a class X is X*.
191  // If the member function is declared const, the type of this is const X*,
192  // if the member function is declared volatile, the type of this is
193  // volatile X*, and if the member function is declared const volatile,
194  // the type of this is const volatile X*.
195
196  assert(isInstance() && "No 'this' for static methods!");
197  QualType ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
198  ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers());
199  return C.getPointerType(ClassTy).withConst();
200}
201
202CXXBaseOrMemberInitializer::
203CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs)
204  : Args(0), NumArgs(0) {
205  BaseOrMember = reinterpret_cast<uintptr_t>(BaseType.getTypePtr());
206  assert((BaseOrMember & 0x01) == 0 && "Invalid base class type pointer");
207  BaseOrMember |= 0x01;
208
209  if (NumArgs > 0) {
210    this->NumArgs = NumArgs;
211    this->Args = new Expr*[NumArgs];
212    for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
213      this->Args[Idx] = Args[Idx];
214  }
215}
216
217CXXBaseOrMemberInitializer::
218CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs)
219  : Args(0), NumArgs(0) {
220  BaseOrMember = reinterpret_cast<uintptr_t>(Member);
221  assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer");
222
223  if (NumArgs > 0) {
224    this->NumArgs = NumArgs;
225    this->Args = new Expr*[NumArgs];
226    for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
227      this->Args[Idx] = Args[Idx];
228  }
229}
230
231CXXBaseOrMemberInitializer::~CXXBaseOrMemberInitializer() {
232  delete [] Args;
233}
234
235CXXConstructorDecl *
236CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
237                           SourceLocation L, DeclarationName N,
238                           QualType T, bool isExplicit,
239                           bool isInline, bool isImplicitlyDeclared) {
240  assert(N.getNameKind() == DeclarationName::CXXConstructorName &&
241         "Name must refer to a constructor");
242  return new (C) CXXConstructorDecl(RD, L, N, T, isExplicit, isInline,
243                                      isImplicitlyDeclared);
244}
245
246bool CXXConstructorDecl::isDefaultConstructor() const {
247  // C++ [class.ctor]p5:
248  //   A default constructor for a class X is a constructor of class
249  //   X that can be called without an argument.
250  return (getNumParams() == 0) ||
251         (getNumParams() > 0 && getParamDecl(0)->getDefaultArg() != 0);
252}
253
254bool
255CXXConstructorDecl::isCopyConstructor(ASTContext &Context,
256                                      unsigned &TypeQuals) const {
257  // C++ [class.copy]p2:
258  //   A non-template constructor for class X is a copy constructor
259  //   if its first parameter is of type X&, const X&, volatile X& or
260  //   const volatile X&, and either there are no other parameters
261  //   or else all other parameters have default arguments (8.3.6).
262  if ((getNumParams() < 1) ||
263      (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() == 0))
264    return false;
265
266  const ParmVarDecl *Param = getParamDecl(0);
267
268  // Do we have a reference type? Rvalue references don't count.
269  const LValueReferenceType *ParamRefType =
270    Param->getType()->getAsLValueReferenceType();
271  if (!ParamRefType)
272    return false;
273
274  // Is it a reference to our class type?
275  QualType PointeeType
276    = Context.getCanonicalType(ParamRefType->getPointeeType());
277  QualType ClassTy
278    = Context.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
279  if (PointeeType.getUnqualifiedType() != ClassTy)
280    return false;
281
282  // We have a copy constructor.
283  TypeQuals = PointeeType.getCVRQualifiers();
284  return true;
285}
286
287bool CXXConstructorDecl::isConvertingConstructor() const {
288  // C++ [class.conv.ctor]p1:
289  //   A constructor declared without the function-specifier explicit
290  //   that can be called with a single parameter specifies a
291  //   conversion from the type of its first parameter to the type of
292  //   its class. Such a constructor is called a converting
293  //   constructor.
294  if (isExplicit())
295    return false;
296
297  return (getNumParams() == 0 &&
298          getType()->getAsFunctionProtoType()->isVariadic()) ||
299         (getNumParams() == 1) ||
300         (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() != 0);
301}
302
303CXXDestructorDecl *
304CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
305                          SourceLocation L, DeclarationName N,
306                          QualType T, bool isInline,
307                          bool isImplicitlyDeclared) {
308  assert(N.getNameKind() == DeclarationName::CXXDestructorName &&
309         "Name must refer to a destructor");
310  return new (C) CXXDestructorDecl(RD, L, N, T, isInline,
311                                   isImplicitlyDeclared);
312}
313
314CXXConversionDecl *
315CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
316                          SourceLocation L, DeclarationName N,
317                          QualType T, bool isInline, bool isExplicit) {
318  assert(N.getNameKind() == DeclarationName::CXXConversionFunctionName &&
319         "Name must refer to a conversion function");
320  return new (C) CXXConversionDecl(RD, L, N, T, isInline, isExplicit);
321}
322
323OverloadedFunctionDecl *
324OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC,
325                               DeclarationName N) {
326  return new (C) OverloadedFunctionDecl(DC, N);
327}
328
329LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
330                                         DeclContext *DC,
331                                         SourceLocation L,
332                                         LanguageIDs Lang, bool Braces) {
333  return new (C) LinkageSpecDecl(DC, L, Lang, Braces);
334}
335
336UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC,
337                                               SourceLocation L,
338                                               SourceLocation NamespaceLoc,
339                                               SourceLocation IdentLoc,
340                                               NamespaceDecl *Used,
341                                               DeclContext *CommonAncestor) {
342  return new (C) UsingDirectiveDecl(DC, L, NamespaceLoc, IdentLoc,
343                                    Used, CommonAncestor);
344}
345
346NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
347                                               SourceLocation L,
348                                               SourceLocation AliasLoc,
349                                               IdentifierInfo *Alias,
350                                               SourceLocation IdentLoc,
351                                               NamedDecl *Namespace) {
352  return new (C) NamespaceAliasDecl(DC, L, AliasLoc, Alias, IdentLoc,
353                                    Namespace);
354}
355
356StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC,
357                                           SourceLocation L, Expr *AssertExpr,
358                                           StringLiteral *Message) {
359  return new (C) StaticAssertDecl(DC, L, AssertExpr, Message);
360}
361
362void StaticAssertDecl::Destroy(ASTContext& C) {
363  AssertExpr->Destroy(C);
364  Message->Destroy(C);
365  this->~StaticAssertDecl();
366  C.Deallocate((void *)this);
367}
368
369StaticAssertDecl::~StaticAssertDecl() {
370}
371
372static const char *getAccessName(AccessSpecifier AS) {
373  switch (AS) {
374    default:
375    case AS_none:
376      assert("Invalid access specifier!");
377      return 0;
378    case AS_public:
379      return "public";
380    case AS_private:
381      return "private";
382    case AS_protected:
383      return "protected";
384  }
385}
386
387const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
388                                           AccessSpecifier AS) {
389  return DB << getAccessName(AS);
390}
391
392
393