| //===--- DeclCXX.cpp - C++ Declaration AST Node Implementation ------------===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | // | 
 | // This file implements the C++ related Decl classes. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "clang/AST/DeclCXX.h" | 
 | #include "clang/AST/ASTContext.h" | 
 | #include "clang/AST/Expr.h" | 
 | #include "clang/Basic/IdentifierTable.h" | 
 | #include "llvm/ADT/STLExtras.h" | 
 | using namespace clang; | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | // Decl Allocation/Deallocation Method Implementations | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, | 
 |                              SourceLocation L, IdentifierInfo *Id)  | 
 |   : RecordDecl(K, TK, DC, L, Id), | 
 |     UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false), | 
 |     UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false), | 
 |     Aggregate(true), PlainOldData(true), Polymorphic(false), Bases(0), | 
 |     NumBases(0), Conversions(DC, DeclarationName()) { } | 
 |  | 
 | CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC, | 
 |                                      SourceLocation L, IdentifierInfo *Id, | 
 |                                      CXXRecordDecl* PrevDecl) { | 
 |   CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TK, DC, L, Id); | 
 |   C.getTypeDeclType(R, PrevDecl);   | 
 |   return R; | 
 | } | 
 |  | 
 | CXXRecordDecl::~CXXRecordDecl() { | 
 |   delete [] Bases; | 
 | } | 
 |  | 
 | void  | 
 | CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,  | 
 |                         unsigned NumBases) { | 
 |   // C++ [dcl.init.aggr]p1:  | 
 |   //   An aggregate is an array or a class (clause 9) with [...] | 
 |   //   no base classes [...]. | 
 |   Aggregate = false; | 
 |  | 
 |   if (this->Bases) | 
 |     delete [] this->Bases; | 
 |  | 
 |   // FIXME: allocate using the ASTContext | 
 |   this->Bases = new CXXBaseSpecifier[NumBases]; | 
 |   this->NumBases = NumBases; | 
 |   for (unsigned i = 0; i < NumBases; ++i) | 
 |     this->Bases[i] = *Bases[i]; | 
 | } | 
 |  | 
 | bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const { | 
 |   QualType ClassType | 
 |     = Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this)); | 
 |   DeclarationName ConstructorName  | 
 |     = Context.DeclarationNames.getCXXConstructorName( | 
 |                                            Context.getCanonicalType(ClassType)); | 
 |   unsigned TypeQuals; | 
 |   DeclContext::lookup_const_iterator Con, ConEnd; | 
 |   for (llvm::tie(Con, ConEnd) = this->lookup(ConstructorName); | 
 |        Con != ConEnd; ++Con) { | 
 |     if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) && | 
 |         (TypeQuals & QualType::Const) != 0) | 
 |       return true; | 
 |   } | 
 |  | 
 |   return false; | 
 | } | 
 |  | 
 | bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context) const { | 
 |   QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType( | 
 |     const_cast<CXXRecordDecl*>(this))); | 
 |   DeclarationName OpName =Context.DeclarationNames.getCXXOperatorName(OO_Equal); | 
 |  | 
 |   DeclContext::lookup_const_iterator Op, OpEnd; | 
 |   for (llvm::tie(Op, OpEnd) = this->lookup(OpName); | 
 |        Op != OpEnd; ++Op) { | 
 |     // C++ [class.copy]p9: | 
 |     //   A user-declared copy assignment operator is a non-static non-template | 
 |     //   member function of class X with exactly one parameter of type X, X&, | 
 |     //   const X&, volatile X& or const volatile X&. | 
 |     const CXXMethodDecl* Method = cast<CXXMethodDecl>(*Op); | 
 |     if (Method->isStatic()) | 
 |       continue; | 
 |     // TODO: Skip templates? Or is this implicitly done due to parameter types? | 
 |     const FunctionProtoType *FnType = | 
 |       Method->getType()->getAsFunctionProtoType(); | 
 |     assert(FnType && "Overloaded operator has no prototype."); | 
 |     // Don't assert on this; an invalid decl might have been left in the AST. | 
 |     if (FnType->getNumArgs() != 1 || FnType->isVariadic()) | 
 |       continue; | 
 |     bool AcceptsConst = true; | 
 |     QualType ArgType = FnType->getArgType(0); | 
 |     if (const LValueReferenceType *Ref = ArgType->getAsLValueReferenceType()) { | 
 |       ArgType = Ref->getPointeeType(); | 
 |       // Is it a non-const lvalue reference? | 
 |       if (!ArgType.isConstQualified()) | 
 |         AcceptsConst = false; | 
 |     } | 
 |     if (Context.getCanonicalType(ArgType).getUnqualifiedType() != ClassType) | 
 |       continue; | 
 |  | 
 |     // We have a single argument of type cv X or cv X&, i.e. we've found the | 
 |     // copy assignment operator. Return whether it accepts const arguments. | 
 |     return AcceptsConst; | 
 |   } | 
 |   assert(isInvalidDecl() && | 
 |          "No copy assignment operator declared in valid code."); | 
 |   return false; | 
 | } | 
 |  | 
 | void | 
 | CXXRecordDecl::addedConstructor(ASTContext &Context,  | 
 |                                 CXXConstructorDecl *ConDecl) { | 
 |   if (!ConDecl->isImplicit()) { | 
 |     // Note that we have a user-declared constructor. | 
 |     UserDeclaredConstructor = true; | 
 |  | 
 |     // C++ [dcl.init.aggr]p1:  | 
 |     //   An aggregate is an array or a class (clause 9) with no | 
 |     //   user-declared constructors (12.1) [...]. | 
 |     Aggregate = false; | 
 |  | 
 |     // C++ [class]p4: | 
 |     //   A POD-struct is an aggregate class [...] | 
 |     PlainOldData = false; | 
 |  | 
 |     // Note when we have a user-declared copy constructor, which will | 
 |     // suppress the implicit declaration of a copy constructor. | 
 |     if (ConDecl->isCopyConstructor(Context)) | 
 |       UserDeclaredCopyConstructor = true; | 
 |   } | 
 | } | 
 |  | 
 | void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context, | 
 |                                             CXXMethodDecl *OpDecl) { | 
 |   // We're interested specifically in copy assignment operators. | 
 |   // Unlike addedConstructor, this method is not called for implicit | 
 |   // declarations. | 
 |   const FunctionProtoType *FnType = OpDecl->getType()->getAsFunctionProtoType(); | 
 |   assert(FnType && "Overloaded operator has no proto function type."); | 
 |   assert(FnType->getNumArgs() == 1 && !FnType->isVariadic()); | 
 |   QualType ArgType = FnType->getArgType(0); | 
 |   if (const LValueReferenceType *Ref = ArgType->getAsLValueReferenceType()) | 
 |     ArgType = Ref->getPointeeType(); | 
 |  | 
 |   ArgType = ArgType.getUnqualifiedType(); | 
 |   QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType( | 
 |     const_cast<CXXRecordDecl*>(this))); | 
 |  | 
 |   if (ClassType != Context.getCanonicalType(ArgType)) | 
 |     return; | 
 |  | 
 |   // This is a copy assignment operator. | 
 |   // Suppress the implicit declaration of a copy constructor. | 
 |   UserDeclaredCopyAssignment = true; | 
 |  | 
 |   // C++ [class]p4: | 
 |   //   A POD-struct is an aggregate class that [...] has no user-defined copy | 
 |   //   assignment operator [...]. | 
 |   PlainOldData = false; | 
 | } | 
 |  | 
 | void CXXRecordDecl::addConversionFunction(ASTContext &Context,  | 
 |                                           CXXConversionDecl *ConvDecl) { | 
 |   Conversions.addOverload(ConvDecl); | 
 | } | 
 |  | 
 | CXXMethodDecl * | 
 | CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, | 
 |                       SourceLocation L, DeclarationName N, | 
 |                       QualType T, bool isStatic, bool isInline) { | 
 |   return new (C) CXXMethodDecl(CXXMethod, RD, L, N, T, isStatic, isInline); | 
 | } | 
 |  | 
 | QualType CXXMethodDecl::getThisType(ASTContext &C) const { | 
 |   // C++ 9.3.2p1: The type of this in a member function of a class X is X*. | 
 |   // If the member function is declared const, the type of this is const X*, | 
 |   // if the member function is declared volatile, the type of this is | 
 |   // volatile X*, and if the member function is declared const volatile, | 
 |   // the type of this is const volatile X*. | 
 |  | 
 |   assert(isInstance() && "No 'this' for static methods!"); | 
 |   QualType ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(getParent())); | 
 |   ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers()); | 
 |   return C.getPointerType(ClassTy).withConst(); | 
 | } | 
 |  | 
 | CXXBaseOrMemberInitializer:: | 
 | CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs)  | 
 |   : Args(0), NumArgs(0) { | 
 |   BaseOrMember = reinterpret_cast<uintptr_t>(BaseType.getTypePtr()); | 
 |   assert((BaseOrMember & 0x01) == 0 && "Invalid base class type pointer"); | 
 |   BaseOrMember |= 0x01; | 
 |    | 
 |   if (NumArgs > 0) { | 
 |     this->NumArgs = NumArgs; | 
 |     this->Args = new Expr*[NumArgs]; | 
 |     for (unsigned Idx = 0; Idx < NumArgs; ++Idx) | 
 |       this->Args[Idx] = Args[Idx]; | 
 |   } | 
 | } | 
 |  | 
 | CXXBaseOrMemberInitializer:: | 
 | CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs) | 
 |   : Args(0), NumArgs(0) { | 
 |   BaseOrMember = reinterpret_cast<uintptr_t>(Member); | 
 |   assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer");   | 
 |  | 
 |   if (NumArgs > 0) { | 
 |     this->NumArgs = NumArgs; | 
 |     this->Args = new Expr*[NumArgs]; | 
 |     for (unsigned Idx = 0; Idx < NumArgs; ++Idx) | 
 |       this->Args[Idx] = Args[Idx]; | 
 |   } | 
 | } | 
 |  | 
 | CXXBaseOrMemberInitializer::~CXXBaseOrMemberInitializer() { | 
 |   delete [] Args; | 
 | } | 
 |  | 
 | CXXConstructorDecl * | 
 | CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, | 
 |                            SourceLocation L, DeclarationName N, | 
 |                            QualType T, bool isExplicit, | 
 |                            bool isInline, bool isImplicitlyDeclared) { | 
 |   assert(N.getNameKind() == DeclarationName::CXXConstructorName && | 
 |          "Name must refer to a constructor"); | 
 |   return new (C) CXXConstructorDecl(RD, L, N, T, isExplicit, isInline, | 
 |                                       isImplicitlyDeclared); | 
 | } | 
 |  | 
 | bool CXXConstructorDecl::isDefaultConstructor() const { | 
 |   // C++ [class.ctor]p5: | 
 |   //   A default constructor for a class X is a constructor of class | 
 |   //   X that can be called without an argument. | 
 |   return (getNumParams() == 0) || | 
 |          (getNumParams() > 0 && getParamDecl(0)->getDefaultArg() != 0); | 
 | } | 
 |  | 
 | bool  | 
 | CXXConstructorDecl::isCopyConstructor(ASTContext &Context,  | 
 |                                       unsigned &TypeQuals) const { | 
 |   // C++ [class.copy]p2: | 
 |   //   A non-template constructor for class X is a copy constructor | 
 |   //   if its first parameter is of type X&, const X&, volatile X& or | 
 |   //   const volatile X&, and either there are no other parameters | 
 |   //   or else all other parameters have default arguments (8.3.6). | 
 |   if ((getNumParams() < 1) || | 
 |       (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() == 0)) | 
 |     return false; | 
 |  | 
 |   const ParmVarDecl *Param = getParamDecl(0); | 
 |  | 
 |   // Do we have a reference type? Rvalue references don't count. | 
 |   const LValueReferenceType *ParamRefType = | 
 |     Param->getType()->getAsLValueReferenceType(); | 
 |   if (!ParamRefType) | 
 |     return false; | 
 |  | 
 |   // Is it a reference to our class type? | 
 |   QualType PointeeType  | 
 |     = Context.getCanonicalType(ParamRefType->getPointeeType()); | 
 |   QualType ClassTy  | 
 |     = Context.getTagDeclType(const_cast<CXXRecordDecl*>(getParent())); | 
 |   if (PointeeType.getUnqualifiedType() != ClassTy) | 
 |     return false; | 
 |  | 
 |   // We have a copy constructor. | 
 |   TypeQuals = PointeeType.getCVRQualifiers(); | 
 |   return true; | 
 | } | 
 |  | 
 | bool CXXConstructorDecl::isConvertingConstructor() const { | 
 |   // C++ [class.conv.ctor]p1: | 
 |   //   A constructor declared without the function-specifier explicit | 
 |   //   that can be called with a single parameter specifies a | 
 |   //   conversion from the type of its first parameter to the type of | 
 |   //   its class. Such a constructor is called a converting | 
 |   //   constructor. | 
 |   if (isExplicit()) | 
 |     return false; | 
 |  | 
 |   return (getNumParams() == 0 &&  | 
 |           getType()->getAsFunctionProtoType()->isVariadic()) || | 
 |          (getNumParams() == 1) || | 
 |          (getNumParams() > 1 && getParamDecl(1)->getDefaultArg() != 0); | 
 | } | 
 |  | 
 | CXXDestructorDecl * | 
 | CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, | 
 |                           SourceLocation L, DeclarationName N, | 
 |                           QualType T, bool isInline,  | 
 |                           bool isImplicitlyDeclared) { | 
 |   assert(N.getNameKind() == DeclarationName::CXXDestructorName && | 
 |          "Name must refer to a destructor"); | 
 |   return new (C) CXXDestructorDecl(RD, L, N, T, isInline,  | 
 |                                    isImplicitlyDeclared); | 
 | } | 
 |  | 
 | CXXConversionDecl * | 
 | CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD, | 
 |                           SourceLocation L, DeclarationName N, | 
 |                           QualType T, bool isInline, bool isExplicit) { | 
 |   assert(N.getNameKind() == DeclarationName::CXXConversionFunctionName && | 
 |          "Name must refer to a conversion function"); | 
 |   return new (C) CXXConversionDecl(RD, L, N, T, isInline, isExplicit); | 
 | } | 
 |  | 
 | OverloadedFunctionDecl * | 
 | OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC, | 
 |                                DeclarationName N) { | 
 |   return new (C) OverloadedFunctionDecl(DC, N); | 
 | } | 
 |  | 
 | LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, | 
 |                                          DeclContext *DC,  | 
 |                                          SourceLocation L, | 
 |                                          LanguageIDs Lang, bool Braces) { | 
 |   return new (C) LinkageSpecDecl(DC, L, Lang, Braces); | 
 | } | 
 |  | 
 | UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC, | 
 |                                                SourceLocation L, | 
 |                                                SourceLocation NamespaceLoc, | 
 |                                                SourceLocation IdentLoc, | 
 |                                                NamespaceDecl *Used, | 
 |                                                DeclContext *CommonAncestor) { | 
 |   return new (C) UsingDirectiveDecl(DC, L, NamespaceLoc, IdentLoc, | 
 |                                     Used, CommonAncestor); | 
 | } | 
 |  | 
 | StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC, | 
 |                                            SourceLocation L, Expr *AssertExpr, | 
 |                                            StringLiteral *Message) { | 
 |   return new (C) StaticAssertDecl(DC, L, AssertExpr, Message); | 
 | } | 
 |  | 
 | void StaticAssertDecl::Destroy(ASTContext& C) { | 
 |   AssertExpr->Destroy(C); | 
 |   Message->Destroy(C); | 
 |   this->~StaticAssertDecl(); | 
 |   C.Deallocate((void *)this); | 
 | } | 
 |  | 
 | StaticAssertDecl::~StaticAssertDecl() { | 
 | } | 
 |  |