| Ted Kremenek | 4b7c983 | 2008-09-05 17:16:31 +0000 | [diff] [blame] | 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" | 
| Douglas Gregor | d475b8d | 2009-03-25 21:17:03 +0000 | [diff] [blame] | 15 | #include "clang/AST/DeclTemplate.h" | 
| Ted Kremenek | 4b7c983 | 2008-09-05 17:16:31 +0000 | [diff] [blame] | 16 | #include "clang/AST/ASTContext.h" | 
| Anders Carlsson | fb31176 | 2009-03-14 00:25:26 +0000 | [diff] [blame] | 17 | #include "clang/AST/Expr.h" | 
| Douglas Gregor | 802ab45 | 2009-12-02 22:36:29 +0000 | [diff] [blame] | 18 | #include "clang/AST/TypeLoc.h" | 
| Douglas Gregor | 7d7e672 | 2008-11-12 23:21:09 +0000 | [diff] [blame] | 19 | #include "clang/Basic/IdentifierTable.h" | 
| Douglas Gregor | fdfab6b | 2008-12-23 21:31:30 +0000 | [diff] [blame] | 20 | #include "llvm/ADT/STLExtras.h" | 
| Fariborz Jahanian | faebcbb | 2009-09-12 19:52:10 +0000 | [diff] [blame] | 21 | #include "llvm/ADT/SmallPtrSet.h" | 
| Ted Kremenek | 4b7c983 | 2008-09-05 17:16:31 +0000 | [diff] [blame] | 22 | using namespace clang; | 
|  | 23 |  | 
|  | 24 | //===----------------------------------------------------------------------===// | 
|  | 25 | // Decl Allocation/Deallocation Method Implementations | 
|  | 26 | //===----------------------------------------------------------------------===// | 
| Douglas Gregor | 72c3f31 | 2008-12-05 18:15:24 +0000 | [diff] [blame] | 27 |  | 
| John McCall | 86ff308 | 2010-02-04 22:26:26 +0000 | [diff] [blame] | 28 | CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) | 
|  | 29 | : UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false), | 
| Sebastian Redl | 64b45f7 | 2009-01-05 20:52:13 +0000 | [diff] [blame] | 30 | UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false), | 
| Eli Friedman | 97c134e | 2009-08-15 22:23:00 +0000 | [diff] [blame] | 31 | Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false), | 
|  | 32 | Abstract(false), HasTrivialConstructor(true), | 
|  | 33 | HasTrivialCopyConstructor(true), HasTrivialCopyAssignment(true), | 
| Fariborz Jahanian | 6250921 | 2009-09-12 18:26:03 +0000 | [diff] [blame] | 34 | HasTrivialDestructor(true), ComputedVisibleConversions(false), | 
| Douglas Gregor | 1827403 | 2010-07-03 00:47:00 +0000 | [diff] [blame] | 35 | DeclaredDefaultConstructor(false), DeclaredCopyConstructor(false), | 
| Douglas Gregor | a376d10 | 2010-07-02 21:50:04 +0000 | [diff] [blame] | 36 | DeclaredCopyAssignment(false), DeclaredDestructor(false), | 
| Fariborz Jahanian | 6250921 | 2009-09-12 18:26:03 +0000 | [diff] [blame] | 37 | Bases(0), NumBases(0), VBases(0), NumVBases(0), | 
| John McCall | d60e22e | 2010-03-12 01:19:31 +0000 | [diff] [blame] | 38 | Definition(D), FirstFriend(0) { | 
| John McCall | 86ff308 | 2010-02-04 22:26:26 +0000 | [diff] [blame] | 39 | } | 
|  | 40 |  | 
|  | 41 | CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, | 
|  | 42 | SourceLocation L, IdentifierInfo *Id, | 
|  | 43 | CXXRecordDecl *PrevDecl, | 
|  | 44 | SourceLocation TKL) | 
|  | 45 | : RecordDecl(K, TK, DC, L, Id, PrevDecl, TKL), | 
|  | 46 | DefinitionData(PrevDecl ? PrevDecl->DefinitionData : 0), | 
| Douglas Gregor | d475b8d | 2009-03-25 21:17:03 +0000 | [diff] [blame] | 47 | TemplateOrInstantiation() { } | 
| Douglas Gregor | 7d7e672 | 2008-11-12 23:21:09 +0000 | [diff] [blame] | 48 |  | 
| Ted Kremenek | 4b7c983 | 2008-09-05 17:16:31 +0000 | [diff] [blame] | 49 | CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC, | 
|  | 50 | SourceLocation L, IdentifierInfo *Id, | 
| Douglas Gregor | 741dd9a | 2009-07-21 14:46:17 +0000 | [diff] [blame] | 51 | SourceLocation TKL, | 
| Douglas Gregor | aafc0cc | 2009-05-15 19:11:46 +0000 | [diff] [blame] | 52 | CXXRecordDecl* PrevDecl, | 
|  | 53 | bool DelayTypeCreation) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 54 | CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TK, DC, L, Id, | 
| Douglas Gregor | 8e9e9ef | 2009-07-29 23:36:44 +0000 | [diff] [blame] | 55 | PrevDecl, TKL); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 56 |  | 
| Douglas Gregor | 8e9e9ef | 2009-07-29 23:36:44 +0000 | [diff] [blame] | 57 | // FIXME: DelayTypeCreation seems like such a hack | 
| Douglas Gregor | aafc0cc | 2009-05-15 19:11:46 +0000 | [diff] [blame] | 58 | if (!DelayTypeCreation) | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 59 | C.getTypeDeclType(R, PrevDecl); | 
| Ted Kremenek | 4b7c983 | 2008-09-05 17:16:31 +0000 | [diff] [blame] | 60 | return R; | 
|  | 61 | } | 
|  | 62 |  | 
| Argyrios Kyrtzidis | b8b03e6 | 2010-07-02 11:54:55 +0000 | [diff] [blame] | 63 | CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, EmptyShell Empty) { | 
|  | 64 | return new (C) CXXRecordDecl(CXXRecord, TTK_Struct, 0, SourceLocation(), 0, 0, | 
|  | 65 | SourceLocation()); | 
|  | 66 | } | 
|  | 67 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 68 | void | 
| Douglas Gregor | 2d5b703 | 2010-02-11 01:30:34 +0000 | [diff] [blame] | 69 | CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, | 
| Douglas Gregor | 57c856b | 2008-10-23 18:13:27 +0000 | [diff] [blame] | 70 | unsigned NumBases) { | 
| Douglas Gregor | 2d5b703 | 2010-02-11 01:30:34 +0000 | [diff] [blame] | 71 | ASTContext &C = getASTContext(); | 
|  | 72 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 73 | // C++ [dcl.init.aggr]p1: | 
| Douglas Gregor | 64bffa9 | 2008-11-05 16:20:31 +0000 | [diff] [blame] | 74 | //   An aggregate is an array or a class (clause 9) with [...] | 
|  | 75 | //   no base classes [...]. | 
| John McCall | 86ff308 | 2010-02-04 22:26:26 +0000 | [diff] [blame] | 76 | data().Aggregate = false; | 
| Douglas Gregor | 64bffa9 | 2008-11-05 16:20:31 +0000 | [diff] [blame] | 77 |  | 
| John McCall | 86ff308 | 2010-02-04 22:26:26 +0000 | [diff] [blame] | 78 | if (data().Bases) | 
|  | 79 | C.Deallocate(data().Bases); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 80 |  | 
| Anders Carlsson | 6f6de73 | 2010-03-29 05:13:12 +0000 | [diff] [blame] | 81 | // The set of seen virtual base types. | 
| Anders Carlsson | 1c36393 | 2010-03-29 19:49:09 +0000 | [diff] [blame] | 82 | llvm::SmallPtrSet<CanQualType, 8> SeenVBaseTypes; | 
| Anders Carlsson | 6f6de73 | 2010-03-29 05:13:12 +0000 | [diff] [blame] | 83 |  | 
|  | 84 | // The virtual bases of this class. | 
|  | 85 | llvm::SmallVector<const CXXBaseSpecifier *, 8> VBases; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 86 |  | 
| John McCall | 86ff308 | 2010-02-04 22:26:26 +0000 | [diff] [blame] | 87 | data().Bases = new(C) CXXBaseSpecifier [NumBases]; | 
|  | 88 | data().NumBases = NumBases; | 
| Fariborz Jahanian | 40c072f | 2009-07-10 20:13:23 +0000 | [diff] [blame] | 89 | for (unsigned i = 0; i < NumBases; ++i) { | 
| John McCall | 86ff308 | 2010-02-04 22:26:26 +0000 | [diff] [blame] | 90 | data().Bases[i] = *Bases[i]; | 
| Fariborz Jahanian | 40c072f | 2009-07-10 20:13:23 +0000 | [diff] [blame] | 91 | // Keep track of inherited vbases for this base class. | 
|  | 92 | const CXXBaseSpecifier *Base = Bases[i]; | 
|  | 93 | QualType BaseType = Base->getType(); | 
| Douglas Gregor | 5fe8c04 | 2010-02-27 00:25:28 +0000 | [diff] [blame] | 94 | // Skip dependent types; we can't do any checking on them now. | 
| Fariborz Jahanian | 40c072f | 2009-07-10 20:13:23 +0000 | [diff] [blame] | 95 | if (BaseType->isDependentType()) | 
|  | 96 | continue; | 
|  | 97 | CXXRecordDecl *BaseClassDecl | 
| Ted Kremenek | 6217b80 | 2009-07-29 21:53:49 +0000 | [diff] [blame] | 98 | = cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl()); | 
| Anders Carlsson | 6f6de73 | 2010-03-29 05:13:12 +0000 | [diff] [blame] | 99 |  | 
|  | 100 | // Now go through all virtual bases of this base and add them. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 101 | for (CXXRecordDecl::base_class_iterator VBase = | 
| Fariborz Jahanian | 40c072f | 2009-07-10 20:13:23 +0000 | [diff] [blame] | 102 | BaseClassDecl->vbases_begin(), | 
|  | 103 | E = BaseClassDecl->vbases_end(); VBase != E; ++VBase) { | 
| Anders Carlsson | 6f6de73 | 2010-03-29 05:13:12 +0000 | [diff] [blame] | 104 | // Add this base if it's not already in the list. | 
| Anders Carlsson | 1c36393 | 2010-03-29 19:49:09 +0000 | [diff] [blame] | 105 | if (SeenVBaseTypes.insert(C.getCanonicalType(VBase->getType()))) | 
| Anders Carlsson | 6f6de73 | 2010-03-29 05:13:12 +0000 | [diff] [blame] | 106 | VBases.push_back(VBase); | 
| Fariborz Jahanian | 40c072f | 2009-07-10 20:13:23 +0000 | [diff] [blame] | 107 | } | 
| Anders Carlsson | 6f6de73 | 2010-03-29 05:13:12 +0000 | [diff] [blame] | 108 |  | 
|  | 109 | if (Base->isVirtual()) { | 
|  | 110 | // Add this base if it's not already in the list. | 
| Anders Carlsson | 1c36393 | 2010-03-29 19:49:09 +0000 | [diff] [blame] | 111 | if (SeenVBaseTypes.insert(C.getCanonicalType(BaseType))) | 
| Anders Carlsson | 6f6de73 | 2010-03-29 05:13:12 +0000 | [diff] [blame] | 112 | VBases.push_back(Base); | 
|  | 113 | } | 
|  | 114 |  | 
| Fariborz Jahanian | 40c072f | 2009-07-10 20:13:23 +0000 | [diff] [blame] | 115 | } | 
| Anders Carlsson | 6f6de73 | 2010-03-29 05:13:12 +0000 | [diff] [blame] | 116 |  | 
|  | 117 | if (VBases.empty()) | 
|  | 118 | return; | 
|  | 119 |  | 
|  | 120 | // Create base specifier for any direct or indirect virtual bases. | 
|  | 121 | data().VBases = new (C) CXXBaseSpecifier[VBases.size()]; | 
|  | 122 | data().NumVBases = VBases.size(); | 
|  | 123 | for (int I = 0, E = VBases.size(); I != E; ++I) { | 
| Nick Lewycky | 5606220 | 2010-07-26 16:56:01 +0000 | [diff] [blame] | 124 | TypeSourceInfo *VBaseTypeInfo = VBases[I]->getTypeSourceInfo(); | 
|  | 125 |  | 
| Anders Carlsson | 6f6de73 | 2010-03-29 05:13:12 +0000 | [diff] [blame] | 126 | // Skip dependent types; we can't do any checking on them now. | 
| Nick Lewycky | 5606220 | 2010-07-26 16:56:01 +0000 | [diff] [blame] | 127 | if (VBaseTypeInfo->getType()->isDependentType()) | 
| Anders Carlsson | 6f6de73 | 2010-03-29 05:13:12 +0000 | [diff] [blame] | 128 | continue; | 
|  | 129 |  | 
| Nick Lewycky | 5606220 | 2010-07-26 16:56:01 +0000 | [diff] [blame] | 130 | CXXRecordDecl *VBaseClassDecl = cast<CXXRecordDecl>( | 
|  | 131 | VBaseTypeInfo->getType()->getAs<RecordType>()->getDecl()); | 
| Anders Carlsson | 6f6de73 | 2010-03-29 05:13:12 +0000 | [diff] [blame] | 132 |  | 
|  | 133 | data().VBases[I] = | 
|  | 134 | CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true, | 
| Abramo Bagnara | 465d41b | 2010-05-11 21:36:43 +0000 | [diff] [blame] | 135 | VBaseClassDecl->getTagKind() == TTK_Class, | 
| Nick Lewycky | 5606220 | 2010-07-26 16:56:01 +0000 | [diff] [blame] | 136 | VBases[I]->getAccessSpecifier(), VBaseTypeInfo); | 
| Fariborz Jahanian | 40c072f | 2009-07-10 20:13:23 +0000 | [diff] [blame] | 137 | } | 
| Douglas Gregor | 57c856b | 2008-10-23 18:13:27 +0000 | [diff] [blame] | 138 | } | 
|  | 139 |  | 
| Douglas Gregor | 9edad9b | 2010-01-14 17:47:39 +0000 | [diff] [blame] | 140 | /// Callback function for CXXRecordDecl::forallBases that acknowledges | 
|  | 141 | /// that it saw a base class. | 
|  | 142 | static bool SawBase(const CXXRecordDecl *, void *) { | 
|  | 143 | return true; | 
|  | 144 | } | 
|  | 145 |  | 
|  | 146 | bool CXXRecordDecl::hasAnyDependentBases() const { | 
|  | 147 | if (!isDependentContext()) | 
|  | 148 | return false; | 
|  | 149 |  | 
|  | 150 | return !forallBases(SawBase, 0); | 
|  | 151 | } | 
|  | 152 |  | 
| Douglas Gregor | 396b7cd | 2008-11-03 17:51:48 +0000 | [diff] [blame] | 153 | bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const { | 
| John McCall | 0953e76 | 2009-09-24 19:53:00 +0000 | [diff] [blame] | 154 | return getCopyConstructor(Context, Qualifiers::Const) != 0; | 
| Fariborz Jahanian | 485f087 | 2009-06-22 23:34:40 +0000 | [diff] [blame] | 155 | } | 
|  | 156 |  | 
| Douglas Gregor | 0d405db | 2010-07-01 20:59:04 +0000 | [diff] [blame] | 157 | /// \brief Perform a simplistic form of overload resolution that only considers | 
|  | 158 | /// cv-qualifiers on a single parameter, and return the best overload candidate | 
|  | 159 | /// (if there is one). | 
|  | 160 | static CXXMethodDecl * | 
|  | 161 | GetBestOverloadCandidateSimple( | 
|  | 162 | const llvm::SmallVectorImpl<std::pair<CXXMethodDecl *, Qualifiers> > &Cands) { | 
|  | 163 | if (Cands.empty()) | 
|  | 164 | return 0; | 
|  | 165 | if (Cands.size() == 1) | 
|  | 166 | return Cands[0].first; | 
|  | 167 |  | 
|  | 168 | unsigned Best = 0, N = Cands.size(); | 
|  | 169 | for (unsigned I = 1; I != N; ++I) | 
|  | 170 | if (Cands[Best].second.isSupersetOf(Cands[I].second)) | 
|  | 171 | Best = I; | 
|  | 172 |  | 
|  | 173 | for (unsigned I = 1; I != N; ++I) | 
|  | 174 | if (Cands[Best].second.isSupersetOf(Cands[I].second)) | 
|  | 175 | return 0; | 
|  | 176 |  | 
|  | 177 | return Cands[Best].first; | 
|  | 178 | } | 
|  | 179 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 180 | CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext &Context, | 
| Fariborz Jahanian | 485f087 | 2009-06-22 23:34:40 +0000 | [diff] [blame] | 181 | unsigned TypeQuals) const{ | 
| Sebastian Redl | 64b45f7 | 2009-01-05 20:52:13 +0000 | [diff] [blame] | 182 | QualType ClassType | 
|  | 183 | = Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this)); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 184 | DeclarationName ConstructorName | 
| Douglas Gregor | 9e7d9de | 2008-12-15 21:24:18 +0000 | [diff] [blame] | 185 | = Context.DeclarationNames.getCXXConstructorName( | 
| Fariborz Jahanian | 485f087 | 2009-06-22 23:34:40 +0000 | [diff] [blame] | 186 | Context.getCanonicalType(ClassType)); | 
|  | 187 | unsigned FoundTQs; | 
| Douglas Gregor | 0d405db | 2010-07-01 20:59:04 +0000 | [diff] [blame] | 188 | llvm::SmallVector<std::pair<CXXMethodDecl *, Qualifiers>, 4> Found; | 
| Douglas Gregor | fdfab6b | 2008-12-23 21:31:30 +0000 | [diff] [blame] | 189 | DeclContext::lookup_const_iterator Con, ConEnd; | 
| Argyrios Kyrtzidis | 17945a0 | 2009-06-30 02:36:12 +0000 | [diff] [blame] | 190 | for (llvm::tie(Con, ConEnd) = this->lookup(ConstructorName); | 
| Douglas Gregor | fdfab6b | 2008-12-23 21:31:30 +0000 | [diff] [blame] | 191 | Con != ConEnd; ++Con) { | 
| Douglas Gregor | d93bacf | 2009-09-04 14:46:39 +0000 | [diff] [blame] | 192 | // C++ [class.copy]p2: | 
|  | 193 | //   A non-template constructor for class X is a copy constructor if [...] | 
|  | 194 | if (isa<FunctionTemplateDecl>(*Con)) | 
|  | 195 | continue; | 
|  | 196 |  | 
| Douglas Gregor | 0d405db | 2010-07-01 20:59:04 +0000 | [diff] [blame] | 197 | CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con); | 
|  | 198 | if (Constructor->isCopyConstructor(FoundTQs)) { | 
| John McCall | 0953e76 | 2009-09-24 19:53:00 +0000 | [diff] [blame] | 199 | if (((TypeQuals & Qualifiers::Const) == (FoundTQs & Qualifiers::Const)) || | 
|  | 200 | (!(TypeQuals & Qualifiers::Const) && (FoundTQs & Qualifiers::Const))) | 
| Douglas Gregor | 0d405db | 2010-07-01 20:59:04 +0000 | [diff] [blame] | 201 | Found.push_back(std::make_pair( | 
|  | 202 | const_cast<CXXConstructorDecl *>(Constructor), | 
|  | 203 | Qualifiers::fromCVRMask(FoundTQs))); | 
| Fariborz Jahanian | 485f087 | 2009-06-22 23:34:40 +0000 | [diff] [blame] | 204 | } | 
| Douglas Gregor | 396b7cd | 2008-11-03 17:51:48 +0000 | [diff] [blame] | 205 | } | 
| Douglas Gregor | 0d405db | 2010-07-01 20:59:04 +0000 | [diff] [blame] | 206 |  | 
|  | 207 | return cast_or_null<CXXConstructorDecl>( | 
|  | 208 | GetBestOverloadCandidateSimple(Found)); | 
| Douglas Gregor | 396b7cd | 2008-11-03 17:51:48 +0000 | [diff] [blame] | 209 | } | 
|  | 210 |  | 
| Douglas Gregor | b87786f | 2010-07-01 17:48:08 +0000 | [diff] [blame] | 211 | CXXMethodDecl *CXXRecordDecl::getCopyAssignmentOperator(bool ArgIsConst) const { | 
|  | 212 | ASTContext &Context = getASTContext(); | 
|  | 213 | QualType Class = Context.getTypeDeclType(const_cast<CXXRecordDecl *>(this)); | 
|  | 214 | DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); | 
|  | 215 |  | 
|  | 216 | llvm::SmallVector<std::pair<CXXMethodDecl *, Qualifiers>, 4> Found; | 
|  | 217 | DeclContext::lookup_const_iterator Op, OpEnd; | 
|  | 218 | for (llvm::tie(Op, OpEnd) = this->lookup(Name); Op != OpEnd; ++Op) { | 
|  | 219 | // C++ [class.copy]p9: | 
|  | 220 | //   A user-declared copy assignment operator is a non-static non-template | 
|  | 221 | //   member function of class X with exactly one parameter of type X, X&, | 
|  | 222 | //   const X&, volatile X& or const volatile X&. | 
|  | 223 | const CXXMethodDecl* Method = dyn_cast<CXXMethodDecl>(*Op); | 
|  | 224 | if (!Method || Method->isStatic() || Method->getPrimaryTemplate()) | 
|  | 225 | continue; | 
|  | 226 |  | 
|  | 227 | const FunctionProtoType *FnType | 
|  | 228 | = Method->getType()->getAs<FunctionProtoType>(); | 
|  | 229 | assert(FnType && "Overloaded operator has no prototype."); | 
|  | 230 | // Don't assert on this; an invalid decl might have been left in the AST. | 
|  | 231 | if (FnType->getNumArgs() != 1 || FnType->isVariadic()) | 
|  | 232 | continue; | 
|  | 233 |  | 
|  | 234 | QualType ArgType = FnType->getArgType(0); | 
|  | 235 | Qualifiers Quals; | 
|  | 236 | if (const LValueReferenceType *Ref = ArgType->getAs<LValueReferenceType>()) { | 
|  | 237 | ArgType = Ref->getPointeeType(); | 
|  | 238 | // If we have a const argument and we have a reference to a non-const, | 
|  | 239 | // this function does not match. | 
|  | 240 | if (ArgIsConst && !ArgType.isConstQualified()) | 
|  | 241 | continue; | 
|  | 242 |  | 
|  | 243 | Quals = ArgType.getQualifiers(); | 
|  | 244 | } else { | 
|  | 245 | // By-value copy-assignment operators are treated like const X& | 
|  | 246 | // copy-assignment operators. | 
|  | 247 | Quals = Qualifiers::fromCVRMask(Qualifiers::Const); | 
|  | 248 | } | 
|  | 249 |  | 
|  | 250 | if (!Context.hasSameUnqualifiedType(ArgType, Class)) | 
|  | 251 | continue; | 
|  | 252 |  | 
|  | 253 | // Save this copy-assignment operator. It might be "the one". | 
|  | 254 | Found.push_back(std::make_pair(const_cast<CXXMethodDecl *>(Method), Quals)); | 
|  | 255 | } | 
|  | 256 |  | 
|  | 257 | // Use a simplistic form of overload resolution to find the candidate. | 
|  | 258 | return GetBestOverloadCandidateSimple(Found); | 
|  | 259 | } | 
|  | 260 |  | 
| Sebastian Redl | 64b45f7 | 2009-01-05 20:52:13 +0000 | [diff] [blame] | 261 | void | 
| Douglas Gregor | 5c0646b | 2010-09-27 21:17:54 +0000 | [diff] [blame^] | 262 | CXXRecordDecl::addedConstructor(CXXConstructorDecl *Constructor) { | 
|  | 263 | // Ignore friends. | 
|  | 264 | if (Constructor->getFriendObjectKind()) | 
|  | 265 | return; | 
|  | 266 |  | 
|  | 267 | if (Constructor->isImplicit()) { | 
|  | 268 | // If this is the implicit default constructor, note that we have now | 
|  | 269 | // declared it. | 
|  | 270 | if (Constructor->isDefaultConstructor()) | 
|  | 271 | data().DeclaredDefaultConstructor = true; | 
|  | 272 | // If this is the implicit copy constructor, note that we have now | 
|  | 273 | // declared it. | 
|  | 274 | else if (Constructor->isCopyConstructor()) | 
|  | 275 | data().DeclaredCopyConstructor = true; | 
|  | 276 |  | 
|  | 277 | // Nothing else to do for implicitly-declared constructors. | 
|  | 278 | return; | 
|  | 279 | } | 
|  | 280 |  | 
| Fariborz Jahanian | 8bc3fa4 | 2009-06-17 22:44:31 +0000 | [diff] [blame] | 281 | // Note that we have a user-declared constructor. | 
| John McCall | 86ff308 | 2010-02-04 22:26:26 +0000 | [diff] [blame] | 282 | data().UserDeclaredConstructor = true; | 
| Douglas Gregor | 030ff0c | 2008-10-31 20:25:05 +0000 | [diff] [blame] | 283 |  | 
| Douglas Gregor | 1827403 | 2010-07-03 00:47:00 +0000 | [diff] [blame] | 284 | // Note that we have no need of an implicitly-declared default constructor. | 
|  | 285 | data().DeclaredDefaultConstructor = true; | 
|  | 286 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 287 | // C++ [dcl.init.aggr]p1: | 
| Fariborz Jahanian | 8bc3fa4 | 2009-06-17 22:44:31 +0000 | [diff] [blame] | 288 | //   An aggregate is an array or a class (clause 9) with no | 
|  | 289 | //   user-declared constructors (12.1) [...]. | 
| John McCall | 86ff308 | 2010-02-04 22:26:26 +0000 | [diff] [blame] | 290 | data().Aggregate = false; | 
| Douglas Gregor | 64bffa9 | 2008-11-05 16:20:31 +0000 | [diff] [blame] | 291 |  | 
| Fariborz Jahanian | 8bc3fa4 | 2009-06-17 22:44:31 +0000 | [diff] [blame] | 292 | // C++ [class]p4: | 
|  | 293 | //   A POD-struct is an aggregate class [...] | 
| John McCall | 86ff308 | 2010-02-04 22:26:26 +0000 | [diff] [blame] | 294 | data().PlainOldData = false; | 
| Sebastian Redl | 64b45f7 | 2009-01-05 20:52:13 +0000 | [diff] [blame] | 295 |  | 
| Fariborz Jahanian | 8bc3fa4 | 2009-06-17 22:44:31 +0000 | [diff] [blame] | 296 | // C++ [class.ctor]p5: | 
|  | 297 | //   A constructor is trivial if it is an implicitly-declared default | 
|  | 298 | //   constructor. | 
| Douglas Gregor | 1f2023a | 2009-07-22 18:25:24 +0000 | [diff] [blame] | 299 | // FIXME: C++0x: don't do this for "= default" default constructors. | 
| John McCall | 86ff308 | 2010-02-04 22:26:26 +0000 | [diff] [blame] | 300 | data().HasTrivialConstructor = false; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 301 |  | 
| Fariborz Jahanian | 8bc3fa4 | 2009-06-17 22:44:31 +0000 | [diff] [blame] | 302 | // Note when we have a user-declared copy constructor, which will | 
|  | 303 | // suppress the implicit declaration of a copy constructor. | 
| Douglas Gregor | 5c0646b | 2010-09-27 21:17:54 +0000 | [diff] [blame^] | 304 | if (!Constructor->getDescribedFunctionTemplate() && | 
|  | 305 | Constructor->isCopyConstructor()) { | 
| John McCall | 86ff308 | 2010-02-04 22:26:26 +0000 | [diff] [blame] | 306 | data().UserDeclaredCopyConstructor = true; | 
| Douglas Gregor | 2258431 | 2010-07-02 23:41:54 +0000 | [diff] [blame] | 307 | data().DeclaredCopyConstructor = true; | 
|  | 308 |  | 
| Douglas Gregor | 1f2023a | 2009-07-22 18:25:24 +0000 | [diff] [blame] | 309 | // C++ [class.copy]p6: | 
|  | 310 | //   A copy constructor is trivial if it is implicitly declared. | 
|  | 311 | // FIXME: C++0x: don't do this for "= default" copy constructors. | 
| John McCall | 86ff308 | 2010-02-04 22:26:26 +0000 | [diff] [blame] | 312 | data().HasTrivialCopyConstructor = false; | 
| Douglas Gregor | 1f2023a | 2009-07-22 18:25:24 +0000 | [diff] [blame] | 313 | } | 
| Douglas Gregor | 030ff0c | 2008-10-31 20:25:05 +0000 | [diff] [blame] | 314 | } | 
|  | 315 |  | 
| Sebastian Redl | 64b45f7 | 2009-01-05 20:52:13 +0000 | [diff] [blame] | 316 | void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context, | 
|  | 317 | CXXMethodDecl *OpDecl) { | 
|  | 318 | // We're interested specifically in copy assignment operators. | 
| John McCall | 183700f | 2009-09-21 23:43:11 +0000 | [diff] [blame] | 319 | const FunctionProtoType *FnType = OpDecl->getType()->getAs<FunctionProtoType>(); | 
| Sebastian Redl | 64b45f7 | 2009-01-05 20:52:13 +0000 | [diff] [blame] | 320 | assert(FnType && "Overloaded operator has no proto function type."); | 
|  | 321 | assert(FnType->getNumArgs() == 1 && !FnType->isVariadic()); | 
| Douglas Gregor | 77da3f4 | 2009-10-13 23:45:19 +0000 | [diff] [blame] | 322 |  | 
|  | 323 | // Copy assignment operators must be non-templates. | 
|  | 324 | if (OpDecl->getPrimaryTemplate() || OpDecl->getDescribedFunctionTemplate()) | 
|  | 325 | return; | 
|  | 326 |  | 
| Sebastian Redl | 64b45f7 | 2009-01-05 20:52:13 +0000 | [diff] [blame] | 327 | QualType ArgType = FnType->getArgType(0); | 
| Ted Kremenek | 6217b80 | 2009-07-29 21:53:49 +0000 | [diff] [blame] | 328 | if (const LValueReferenceType *Ref = ArgType->getAs<LValueReferenceType>()) | 
| Sebastian Redl | 64b45f7 | 2009-01-05 20:52:13 +0000 | [diff] [blame] | 329 | ArgType = Ref->getPointeeType(); | 
|  | 330 |  | 
|  | 331 | ArgType = ArgType.getUnqualifiedType(); | 
|  | 332 | QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType( | 
|  | 333 | const_cast<CXXRecordDecl*>(this))); | 
|  | 334 |  | 
| Douglas Gregor | a4923eb | 2009-11-16 21:35:15 +0000 | [diff] [blame] | 335 | if (!Context.hasSameUnqualifiedType(ClassType, ArgType)) | 
| Sebastian Redl | 64b45f7 | 2009-01-05 20:52:13 +0000 | [diff] [blame] | 336 | return; | 
|  | 337 |  | 
|  | 338 | // This is a copy assignment operator. | 
| Eli Friedman | 88fad63 | 2009-11-07 00:02:45 +0000 | [diff] [blame] | 339 | // Note on the decl that it is a copy assignment operator. | 
|  | 340 | OpDecl->setCopyAssignment(true); | 
|  | 341 |  | 
| Sebastian Redl | 64b45f7 | 2009-01-05 20:52:13 +0000 | [diff] [blame] | 342 | // Suppress the implicit declaration of a copy constructor. | 
| John McCall | 86ff308 | 2010-02-04 22:26:26 +0000 | [diff] [blame] | 343 | data().UserDeclaredCopyAssignment = true; | 
| Douglas Gregor | a376d10 | 2010-07-02 21:50:04 +0000 | [diff] [blame] | 344 | data().DeclaredCopyAssignment = true; | 
|  | 345 |  | 
| Douglas Gregor | 1f2023a | 2009-07-22 18:25:24 +0000 | [diff] [blame] | 346 | // C++ [class.copy]p11: | 
|  | 347 | //   A copy assignment operator is trivial if it is implicitly declared. | 
|  | 348 | // FIXME: C++0x: don't do this for "= default" copy operators. | 
| John McCall | 86ff308 | 2010-02-04 22:26:26 +0000 | [diff] [blame] | 349 | data().HasTrivialCopyAssignment = false; | 
| Douglas Gregor | 1f2023a | 2009-07-22 18:25:24 +0000 | [diff] [blame] | 350 |  | 
| Sebastian Redl | 64b45f7 | 2009-01-05 20:52:13 +0000 | [diff] [blame] | 351 | // C++ [class]p4: | 
|  | 352 | //   A POD-struct is an aggregate class that [...] has no user-defined copy | 
|  | 353 | //   assignment operator [...]. | 
| John McCall | 86ff308 | 2010-02-04 22:26:26 +0000 | [diff] [blame] | 354 | data().PlainOldData = false; | 
| Sebastian Redl | 64b45f7 | 2009-01-05 20:52:13 +0000 | [diff] [blame] | 355 | } | 
|  | 356 |  | 
| John McCall | b05b5f3 | 2010-03-15 09:07:48 +0000 | [diff] [blame] | 357 | static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) { | 
|  | 358 | QualType T; | 
| John McCall | 32daa42 | 2010-03-31 01:36:47 +0000 | [diff] [blame] | 359 | if (isa<UsingShadowDecl>(Conv)) | 
|  | 360 | Conv = cast<UsingShadowDecl>(Conv)->getTargetDecl(); | 
| John McCall | b05b5f3 | 2010-03-15 09:07:48 +0000 | [diff] [blame] | 361 | if (FunctionTemplateDecl *ConvTemp = dyn_cast<FunctionTemplateDecl>(Conv)) | 
|  | 362 | T = ConvTemp->getTemplatedDecl()->getResultType(); | 
|  | 363 | else | 
|  | 364 | T = cast<CXXConversionDecl>(Conv)->getConversionType(); | 
|  | 365 | return Context.getCanonicalType(T); | 
| Fariborz Jahanian | 0351a1e | 2009-10-07 20:43:36 +0000 | [diff] [blame] | 366 | } | 
|  | 367 |  | 
| John McCall | b05b5f3 | 2010-03-15 09:07:48 +0000 | [diff] [blame] | 368 | /// Collect the visible conversions of a base class. | 
|  | 369 | /// | 
|  | 370 | /// \param Base a base class of the class we're considering | 
|  | 371 | /// \param InVirtual whether this base class is a virtual base (or a base | 
|  | 372 | ///   of a virtual base) | 
|  | 373 | /// \param Access the access along the inheritance path to this base | 
|  | 374 | /// \param ParentHiddenTypes the conversions provided by the inheritors | 
|  | 375 | ///   of this base | 
|  | 376 | /// \param Output the set to which to add conversions from non-virtual bases | 
|  | 377 | /// \param VOutput the set to which to add conversions from virtual bases | 
|  | 378 | /// \param HiddenVBaseCs the set of conversions which were hidden in a | 
|  | 379 | ///   virtual base along some inheritance path | 
|  | 380 | static void CollectVisibleConversions(ASTContext &Context, | 
|  | 381 | CXXRecordDecl *Record, | 
|  | 382 | bool InVirtual, | 
|  | 383 | AccessSpecifier Access, | 
|  | 384 | const llvm::SmallPtrSet<CanQualType, 8> &ParentHiddenTypes, | 
|  | 385 | UnresolvedSetImpl &Output, | 
|  | 386 | UnresolvedSetImpl &VOutput, | 
|  | 387 | llvm::SmallPtrSet<NamedDecl*, 8> &HiddenVBaseCs) { | 
|  | 388 | // The set of types which have conversions in this class or its | 
|  | 389 | // subclasses.  As an optimization, we don't copy the derived set | 
|  | 390 | // unless it might change. | 
|  | 391 | const llvm::SmallPtrSet<CanQualType, 8> *HiddenTypes = &ParentHiddenTypes; | 
|  | 392 | llvm::SmallPtrSet<CanQualType, 8> HiddenTypesBuffer; | 
|  | 393 |  | 
|  | 394 | // Collect the direct conversions and figure out which conversions | 
|  | 395 | // will be hidden in the subclasses. | 
|  | 396 | UnresolvedSetImpl &Cs = *Record->getConversionFunctions(); | 
|  | 397 | if (!Cs.empty()) { | 
|  | 398 | HiddenTypesBuffer = ParentHiddenTypes; | 
|  | 399 | HiddenTypes = &HiddenTypesBuffer; | 
|  | 400 |  | 
|  | 401 | for (UnresolvedSetIterator I = Cs.begin(), E = Cs.end(); I != E; ++I) { | 
|  | 402 | bool Hidden = | 
|  | 403 | !HiddenTypesBuffer.insert(GetConversionType(Context, I.getDecl())); | 
|  | 404 |  | 
|  | 405 | // If this conversion is hidden and we're in a virtual base, | 
|  | 406 | // remember that it's hidden along some inheritance path. | 
|  | 407 | if (Hidden && InVirtual) | 
|  | 408 | HiddenVBaseCs.insert(cast<NamedDecl>(I.getDecl()->getCanonicalDecl())); | 
|  | 409 |  | 
|  | 410 | // If this conversion isn't hidden, add it to the appropriate output. | 
|  | 411 | else if (!Hidden) { | 
|  | 412 | AccessSpecifier IAccess | 
|  | 413 | = CXXRecordDecl::MergeAccess(Access, I.getAccess()); | 
|  | 414 |  | 
|  | 415 | if (InVirtual) | 
|  | 416 | VOutput.addDecl(I.getDecl(), IAccess); | 
| Fariborz Jahanian | 6250921 | 2009-09-12 18:26:03 +0000 | [diff] [blame] | 417 | else | 
| John McCall | b05b5f3 | 2010-03-15 09:07:48 +0000 | [diff] [blame] | 418 | Output.addDecl(I.getDecl(), IAccess); | 
| Fariborz Jahanian | 5346278 | 2009-09-11 21:44:33 +0000 | [diff] [blame] | 419 | } | 
|  | 420 | } | 
|  | 421 | } | 
| Sebastian Redl | 9994a34 | 2009-10-25 17:03:50 +0000 | [diff] [blame] | 422 |  | 
| John McCall | b05b5f3 | 2010-03-15 09:07:48 +0000 | [diff] [blame] | 423 | // Collect information recursively from any base classes. | 
|  | 424 | for (CXXRecordDecl::base_class_iterator | 
|  | 425 | I = Record->bases_begin(), E = Record->bases_end(); I != E; ++I) { | 
|  | 426 | const RecordType *RT = I->getType()->getAs<RecordType>(); | 
|  | 427 | if (!RT) continue; | 
| Sebastian Redl | 9994a34 | 2009-10-25 17:03:50 +0000 | [diff] [blame] | 428 |  | 
| John McCall | b05b5f3 | 2010-03-15 09:07:48 +0000 | [diff] [blame] | 429 | AccessSpecifier BaseAccess | 
|  | 430 | = CXXRecordDecl::MergeAccess(Access, I->getAccessSpecifier()); | 
|  | 431 | bool BaseInVirtual = InVirtual || I->isVirtual(); | 
| Sebastian Redl | 9994a34 | 2009-10-25 17:03:50 +0000 | [diff] [blame] | 432 |  | 
| John McCall | b05b5f3 | 2010-03-15 09:07:48 +0000 | [diff] [blame] | 433 | CXXRecordDecl *Base = cast<CXXRecordDecl>(RT->getDecl()); | 
|  | 434 | CollectVisibleConversions(Context, Base, BaseInVirtual, BaseAccess, | 
|  | 435 | *HiddenTypes, Output, VOutput, HiddenVBaseCs); | 
| Fariborz Jahanian | 5346278 | 2009-09-11 21:44:33 +0000 | [diff] [blame] | 436 | } | 
| John McCall | b05b5f3 | 2010-03-15 09:07:48 +0000 | [diff] [blame] | 437 | } | 
| Sebastian Redl | 9994a34 | 2009-10-25 17:03:50 +0000 | [diff] [blame] | 438 |  | 
| John McCall | b05b5f3 | 2010-03-15 09:07:48 +0000 | [diff] [blame] | 439 | /// Collect the visible conversions of a class. | 
|  | 440 | /// | 
|  | 441 | /// This would be extremely straightforward if it weren't for virtual | 
|  | 442 | /// bases.  It might be worth special-casing that, really. | 
|  | 443 | static void CollectVisibleConversions(ASTContext &Context, | 
|  | 444 | CXXRecordDecl *Record, | 
|  | 445 | UnresolvedSetImpl &Output) { | 
|  | 446 | // The collection of all conversions in virtual bases that we've | 
|  | 447 | // found.  These will be added to the output as long as they don't | 
|  | 448 | // appear in the hidden-conversions set. | 
|  | 449 | UnresolvedSet<8> VBaseCs; | 
|  | 450 |  | 
|  | 451 | // The set of conversions in virtual bases that we've determined to | 
|  | 452 | // be hidden. | 
|  | 453 | llvm::SmallPtrSet<NamedDecl*, 8> HiddenVBaseCs; | 
|  | 454 |  | 
|  | 455 | // The set of types hidden by classes derived from this one. | 
|  | 456 | llvm::SmallPtrSet<CanQualType, 8> HiddenTypes; | 
|  | 457 |  | 
|  | 458 | // Go ahead and collect the direct conversions and add them to the | 
|  | 459 | // hidden-types set. | 
|  | 460 | UnresolvedSetImpl &Cs = *Record->getConversionFunctions(); | 
|  | 461 | Output.append(Cs.begin(), Cs.end()); | 
|  | 462 | for (UnresolvedSetIterator I = Cs.begin(), E = Cs.end(); I != E; ++I) | 
|  | 463 | HiddenTypes.insert(GetConversionType(Context, I.getDecl())); | 
|  | 464 |  | 
|  | 465 | // Recursively collect conversions from base classes. | 
|  | 466 | for (CXXRecordDecl::base_class_iterator | 
|  | 467 | I = Record->bases_begin(), E = Record->bases_end(); I != E; ++I) { | 
|  | 468 | const RecordType *RT = I->getType()->getAs<RecordType>(); | 
|  | 469 | if (!RT) continue; | 
|  | 470 |  | 
|  | 471 | CollectVisibleConversions(Context, cast<CXXRecordDecl>(RT->getDecl()), | 
|  | 472 | I->isVirtual(), I->getAccessSpecifier(), | 
|  | 473 | HiddenTypes, Output, VBaseCs, HiddenVBaseCs); | 
|  | 474 | } | 
|  | 475 |  | 
|  | 476 | // Add any unhidden conversions provided by virtual bases. | 
|  | 477 | for (UnresolvedSetIterator I = VBaseCs.begin(), E = VBaseCs.end(); | 
|  | 478 | I != E; ++I) { | 
|  | 479 | if (!HiddenVBaseCs.count(cast<NamedDecl>(I.getDecl()->getCanonicalDecl()))) | 
|  | 480 | Output.addDecl(I.getDecl(), I.getAccess()); | 
| Fariborz Jahanian | 5346278 | 2009-09-11 21:44:33 +0000 | [diff] [blame] | 481 | } | 
| Fariborz Jahanian | 6250921 | 2009-09-12 18:26:03 +0000 | [diff] [blame] | 482 | } | 
|  | 483 |  | 
|  | 484 | /// getVisibleConversionFunctions - get all conversion functions visible | 
|  | 485 | /// in current class; including conversion function templates. | 
| John McCall | eec51cf | 2010-01-20 00:46:10 +0000 | [diff] [blame] | 486 | const UnresolvedSetImpl *CXXRecordDecl::getVisibleConversionFunctions() { | 
| Fariborz Jahanian | 6250921 | 2009-09-12 18:26:03 +0000 | [diff] [blame] | 487 | // If root class, all conversions are visible. | 
|  | 488 | if (bases_begin() == bases_end()) | 
| John McCall | 86ff308 | 2010-02-04 22:26:26 +0000 | [diff] [blame] | 489 | return &data().Conversions; | 
| Fariborz Jahanian | 6250921 | 2009-09-12 18:26:03 +0000 | [diff] [blame] | 490 | // If visible conversion list is already evaluated, return it. | 
| John McCall | 86ff308 | 2010-02-04 22:26:26 +0000 | [diff] [blame] | 491 | if (data().ComputedVisibleConversions) | 
|  | 492 | return &data().VisibleConversions; | 
| John McCall | b05b5f3 | 2010-03-15 09:07:48 +0000 | [diff] [blame] | 493 | CollectVisibleConversions(getASTContext(), this, data().VisibleConversions); | 
| John McCall | 86ff308 | 2010-02-04 22:26:26 +0000 | [diff] [blame] | 494 | data().ComputedVisibleConversions = true; | 
|  | 495 | return &data().VisibleConversions; | 
| Fariborz Jahanian | 5346278 | 2009-09-11 21:44:33 +0000 | [diff] [blame] | 496 | } | 
|  | 497 |  | 
| John McCall | 32daa42 | 2010-03-31 01:36:47 +0000 | [diff] [blame] | 498 | #ifndef NDEBUG | 
|  | 499 | void CXXRecordDecl::CheckConversionFunction(NamedDecl *ConvDecl) { | 
| John McCall | b05b5f3 | 2010-03-15 09:07:48 +0000 | [diff] [blame] | 500 | assert(ConvDecl->getDeclContext() == this && | 
|  | 501 | "conversion function does not belong to this record"); | 
|  | 502 |  | 
| John McCall | 32daa42 | 2010-03-31 01:36:47 +0000 | [diff] [blame] | 503 | ConvDecl = ConvDecl->getUnderlyingDecl(); | 
|  | 504 | if (FunctionTemplateDecl *Temp = dyn_cast<FunctionTemplateDecl>(ConvDecl)) { | 
|  | 505 | assert(isa<CXXConversionDecl>(Temp->getTemplatedDecl())); | 
|  | 506 | } else { | 
|  | 507 | assert(isa<CXXConversionDecl>(ConvDecl)); | 
|  | 508 | } | 
| Douglas Gregor | 2f1bc52 | 2008-11-07 20:08:42 +0000 | [diff] [blame] | 509 | } | 
| John McCall | 32daa42 | 2010-03-31 01:36:47 +0000 | [diff] [blame] | 510 | #endif | 
| Douglas Gregor | 2f1bc52 | 2008-11-07 20:08:42 +0000 | [diff] [blame] | 511 |  | 
| John McCall | 32daa42 | 2010-03-31 01:36:47 +0000 | [diff] [blame] | 512 | void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) { | 
|  | 513 | // This operation is O(N) but extremely rare.  Sema only uses it to | 
|  | 514 | // remove UsingShadowDecls in a class that were followed by a direct | 
|  | 515 | // declaration, e.g.: | 
|  | 516 | //   class A : B { | 
|  | 517 | //     using B::operator int; | 
|  | 518 | //     operator int(); | 
|  | 519 | //   }; | 
|  | 520 | // This is uncommon by itself and even more uncommon in conjunction | 
|  | 521 | // with sufficiently large numbers of directly-declared conversions | 
|  | 522 | // that asymptotic behavior matters. | 
|  | 523 |  | 
|  | 524 | UnresolvedSetImpl &Convs = *getConversionFunctions(); | 
|  | 525 | for (unsigned I = 0, E = Convs.size(); I != E; ++I) { | 
|  | 526 | if (Convs[I].getDecl() == ConvDecl) { | 
|  | 527 | Convs.erase(I); | 
|  | 528 | assert(std::find(Convs.begin(), Convs.end(), ConvDecl) == Convs.end() | 
|  | 529 | && "conversion was found multiple times in unresolved set"); | 
|  | 530 | return; | 
|  | 531 | } | 
|  | 532 | } | 
|  | 533 |  | 
|  | 534 | llvm_unreachable("conversion not found in set!"); | 
| Douglas Gregor | 65ec1fd | 2009-08-21 23:19:43 +0000 | [diff] [blame] | 535 | } | 
| Fariborz Jahanian | f8dcb86 | 2009-06-19 19:55:27 +0000 | [diff] [blame] | 536 |  | 
| Fariborz Jahanian | e7184df | 2009-12-03 18:44:40 +0000 | [diff] [blame] | 537 | void CXXRecordDecl::setMethodAsVirtual(FunctionDecl *Method) { | 
|  | 538 | Method->setVirtualAsWritten(true); | 
|  | 539 | setAggregate(false); | 
|  | 540 | setPOD(false); | 
|  | 541 | setEmpty(false); | 
|  | 542 | setPolymorphic(true); | 
|  | 543 | setHasTrivialConstructor(false); | 
|  | 544 | setHasTrivialCopyConstructor(false); | 
|  | 545 | setHasTrivialCopyAssignment(false); | 
|  | 546 | } | 
|  | 547 |  | 
| Douglas Gregor | f6b1185 | 2009-10-08 15:14:33 +0000 | [diff] [blame] | 548 | CXXRecordDecl *CXXRecordDecl::getInstantiatedFromMemberClass() const { | 
| Douglas Gregor | b3ae4fc | 2009-10-12 20:18:28 +0000 | [diff] [blame] | 549 | if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) | 
| Douglas Gregor | f6b1185 | 2009-10-08 15:14:33 +0000 | [diff] [blame] | 550 | return cast<CXXRecordDecl>(MSInfo->getInstantiatedFrom()); | 
|  | 551 |  | 
|  | 552 | return 0; | 
|  | 553 | } | 
|  | 554 |  | 
| Douglas Gregor | b3ae4fc | 2009-10-12 20:18:28 +0000 | [diff] [blame] | 555 | MemberSpecializationInfo *CXXRecordDecl::getMemberSpecializationInfo() const { | 
|  | 556 | return TemplateOrInstantiation.dyn_cast<MemberSpecializationInfo *>(); | 
|  | 557 | } | 
|  | 558 |  | 
| Douglas Gregor | f6b1185 | 2009-10-08 15:14:33 +0000 | [diff] [blame] | 559 | void | 
|  | 560 | CXXRecordDecl::setInstantiationOfMemberClass(CXXRecordDecl *RD, | 
|  | 561 | TemplateSpecializationKind TSK) { | 
|  | 562 | assert(TemplateOrInstantiation.isNull() && | 
|  | 563 | "Previous template or instantiation?"); | 
|  | 564 | assert(!isa<ClassTemplateSpecializationDecl>(this)); | 
|  | 565 | TemplateOrInstantiation | 
|  | 566 | = new (getASTContext()) MemberSpecializationInfo(RD, TSK); | 
|  | 567 | } | 
|  | 568 |  | 
| Anders Carlsson | b13e357 | 2009-12-07 06:33:48 +0000 | [diff] [blame] | 569 | TemplateSpecializationKind CXXRecordDecl::getTemplateSpecializationKind() const{ | 
|  | 570 | if (const ClassTemplateSpecializationDecl *Spec | 
| Douglas Gregor | f6b1185 | 2009-10-08 15:14:33 +0000 | [diff] [blame] | 571 | = dyn_cast<ClassTemplateSpecializationDecl>(this)) | 
|  | 572 | return Spec->getSpecializationKind(); | 
|  | 573 |  | 
| Douglas Gregor | b3ae4fc | 2009-10-12 20:18:28 +0000 | [diff] [blame] | 574 | if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) | 
| Douglas Gregor | f6b1185 | 2009-10-08 15:14:33 +0000 | [diff] [blame] | 575 | return MSInfo->getTemplateSpecializationKind(); | 
|  | 576 |  | 
|  | 577 | return TSK_Undeclared; | 
|  | 578 | } | 
|  | 579 |  | 
|  | 580 | void | 
|  | 581 | CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) { | 
|  | 582 | if (ClassTemplateSpecializationDecl *Spec | 
|  | 583 | = dyn_cast<ClassTemplateSpecializationDecl>(this)) { | 
|  | 584 | Spec->setSpecializationKind(TSK); | 
|  | 585 | return; | 
|  | 586 | } | 
|  | 587 |  | 
| Douglas Gregor | b3ae4fc | 2009-10-12 20:18:28 +0000 | [diff] [blame] | 588 | if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) { | 
| Douglas Gregor | f6b1185 | 2009-10-08 15:14:33 +0000 | [diff] [blame] | 589 | MSInfo->setTemplateSpecializationKind(TSK); | 
|  | 590 | return; | 
|  | 591 | } | 
|  | 592 |  | 
|  | 593 | assert(false && "Not a class template or member class specialization"); | 
|  | 594 | } | 
|  | 595 |  | 
| Douglas Gregor | 1d110e0 | 2010-07-01 14:13:13 +0000 | [diff] [blame] | 596 | CXXDestructorDecl *CXXRecordDecl::getDestructor() const { | 
|  | 597 | ASTContext &Context = getASTContext(); | 
| Anders Carlsson | 7267c16 | 2009-05-29 21:03:38 +0000 | [diff] [blame] | 598 | QualType ClassType = Context.getTypeDeclType(this); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 599 |  | 
|  | 600 | DeclarationName Name | 
| Douglas Gregor | 50d62d1 | 2009-08-05 05:36:45 +0000 | [diff] [blame] | 601 | = Context.DeclarationNames.getCXXDestructorName( | 
|  | 602 | Context.getCanonicalType(ClassType)); | 
| Anders Carlsson | 7267c16 | 2009-05-29 21:03:38 +0000 | [diff] [blame] | 603 |  | 
| John McCall | c0bf462 | 2010-02-23 00:48:20 +0000 | [diff] [blame] | 604 | DeclContext::lookup_const_iterator I, E; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 605 | llvm::tie(I, E) = lookup(Name); | 
| Sebastian Redl | d4b25cb | 2010-09-02 23:19:42 +0000 | [diff] [blame] | 606 | if (I == E) | 
|  | 607 | return 0; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 608 |  | 
| Anders Carlsson | 5ec02ae | 2009-12-02 17:15:43 +0000 | [diff] [blame] | 609 | CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(*I); | 
| Anders Carlsson | 7267c16 | 2009-05-29 21:03:38 +0000 | [diff] [blame] | 610 | assert(++I == E && "Found more than one destructor!"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 611 |  | 
| Anders Carlsson | 7267c16 | 2009-05-29 21:03:38 +0000 | [diff] [blame] | 612 | return Dtor; | 
|  | 613 | } | 
|  | 614 |  | 
| Ted Kremenek | 4b7c983 | 2008-09-05 17:16:31 +0000 | [diff] [blame] | 615 | CXXMethodDecl * | 
|  | 616 | CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD, | 
| Abramo Bagnara | 2577743 | 2010-08-11 22:01:17 +0000 | [diff] [blame] | 617 | const DeclarationNameInfo &NameInfo, | 
| John McCall | a93c934 | 2009-12-07 02:54:59 +0000 | [diff] [blame] | 618 | QualType T, TypeSourceInfo *TInfo, | 
| Douglas Gregor | 16573fa | 2010-04-19 22:54:31 +0000 | [diff] [blame] | 619 | bool isStatic, StorageClass SCAsWritten, bool isInline) { | 
| Abramo Bagnara | 2577743 | 2010-08-11 22:01:17 +0000 | [diff] [blame] | 620 | return new (C) CXXMethodDecl(CXXMethod, RD, NameInfo, T, TInfo, | 
| Douglas Gregor | 16573fa | 2010-04-19 22:54:31 +0000 | [diff] [blame] | 621 | isStatic, SCAsWritten, isInline); | 
| Ted Kremenek | 4b7c983 | 2008-09-05 17:16:31 +0000 | [diff] [blame] | 622 | } | 
|  | 623 |  | 
| Douglas Gregor | 9091656 | 2009-09-29 18:16:17 +0000 | [diff] [blame] | 624 | bool CXXMethodDecl::isUsualDeallocationFunction() const { | 
|  | 625 | if (getOverloadedOperator() != OO_Delete && | 
|  | 626 | getOverloadedOperator() != OO_Array_Delete) | 
|  | 627 | return false; | 
| Douglas Gregor | 6d90870 | 2010-02-26 05:06:18 +0000 | [diff] [blame] | 628 |  | 
|  | 629 | // C++ [basic.stc.dynamic.deallocation]p2: | 
|  | 630 | //   A template instance is never a usual deallocation function, | 
|  | 631 | //   regardless of its signature. | 
|  | 632 | if (getPrimaryTemplate()) | 
|  | 633 | return false; | 
|  | 634 |  | 
| Douglas Gregor | 9091656 | 2009-09-29 18:16:17 +0000 | [diff] [blame] | 635 | // C++ [basic.stc.dynamic.deallocation]p2: | 
|  | 636 | //   If a class T has a member deallocation function named operator delete | 
|  | 637 | //   with exactly one parameter, then that function is a usual (non-placement) | 
|  | 638 | //   deallocation function. [...] | 
|  | 639 | if (getNumParams() == 1) | 
|  | 640 | return true; | 
|  | 641 |  | 
|  | 642 | // C++ [basic.stc.dynamic.deallocation]p2: | 
|  | 643 | //   [...] If class T does not declare such an operator delete but does | 
|  | 644 | //   declare a member deallocation function named operator delete with | 
|  | 645 | //   exactly two parameters, the second of which has type std::size_t (18.1), | 
|  | 646 | //   then this function is a usual deallocation function. | 
|  | 647 | ASTContext &Context = getASTContext(); | 
|  | 648 | if (getNumParams() != 2 || | 
| Chandler Carruth | e228ba9 | 2010-02-08 18:54:05 +0000 | [diff] [blame] | 649 | !Context.hasSameUnqualifiedType(getParamDecl(1)->getType(), | 
|  | 650 | Context.getSizeType())) | 
| Douglas Gregor | 9091656 | 2009-09-29 18:16:17 +0000 | [diff] [blame] | 651 | return false; | 
|  | 652 |  | 
|  | 653 | // This function is a usual deallocation function if there are no | 
|  | 654 | // single-parameter deallocation functions of the same kind. | 
|  | 655 | for (DeclContext::lookup_const_result R = getDeclContext()->lookup(getDeclName()); | 
|  | 656 | R.first != R.second; ++R.first) { | 
|  | 657 | if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*R.first)) | 
|  | 658 | if (FD->getNumParams() == 1) | 
|  | 659 | return false; | 
|  | 660 | } | 
|  | 661 |  | 
|  | 662 | return true; | 
|  | 663 | } | 
|  | 664 |  | 
| Douglas Gregor | 06a9f36 | 2010-05-01 20:49:11 +0000 | [diff] [blame] | 665 | bool CXXMethodDecl::isCopyAssignmentOperator() const { | 
|  | 666 | // C++0x [class.copy]p19: | 
|  | 667 | //  A user-declared copy assignment operator X::operator= is a non-static | 
|  | 668 | //  non-template member function of class X with exactly one parameter of | 
|  | 669 | //  type X, X&, const X&, volatile X& or const volatile X&. | 
|  | 670 | if (/*operator=*/getOverloadedOperator() != OO_Equal || | 
|  | 671 | /*non-static*/ isStatic() || | 
|  | 672 | /*non-template*/getPrimaryTemplate() || getDescribedFunctionTemplate() || | 
|  | 673 | /*exactly one parameter*/getNumParams() != 1) | 
|  | 674 | return false; | 
|  | 675 |  | 
|  | 676 | QualType ParamType = getParamDecl(0)->getType(); | 
|  | 677 | if (const LValueReferenceType *Ref = ParamType->getAs<LValueReferenceType>()) | 
|  | 678 | ParamType = Ref->getPointeeType(); | 
|  | 679 |  | 
|  | 680 | ASTContext &Context = getASTContext(); | 
|  | 681 | QualType ClassType | 
|  | 682 | = Context.getCanonicalType(Context.getTypeDeclType(getParent())); | 
|  | 683 | return Context.hasSameUnqualifiedType(ClassType, ParamType); | 
|  | 684 | } | 
|  | 685 |  | 
| Anders Carlsson | 05eb244 | 2009-05-16 23:58:37 +0000 | [diff] [blame] | 686 | void CXXMethodDecl::addOverriddenMethod(const CXXMethodDecl *MD) { | 
| Anders Carlsson | 3aaf486 | 2009-12-04 05:51:56 +0000 | [diff] [blame] | 687 | assert(MD->isCanonicalDecl() && "Method is not canonical!"); | 
| Anders Carlsson | c076c45 | 2010-01-30 17:42:34 +0000 | [diff] [blame] | 688 | assert(!MD->getParent()->isDependentContext() && | 
|  | 689 | "Can't add an overridden method to a class template!"); | 
|  | 690 |  | 
| Douglas Gregor | 7d10b7e | 2010-03-02 23:58:15 +0000 | [diff] [blame] | 691 | getASTContext().addOverriddenMethod(this, MD); | 
| Anders Carlsson | 05eb244 | 2009-05-16 23:58:37 +0000 | [diff] [blame] | 692 | } | 
|  | 693 |  | 
|  | 694 | CXXMethodDecl::method_iterator CXXMethodDecl::begin_overridden_methods() const { | 
| Douglas Gregor | 7d10b7e | 2010-03-02 23:58:15 +0000 | [diff] [blame] | 695 | return getASTContext().overridden_methods_begin(this); | 
| Anders Carlsson | 05eb244 | 2009-05-16 23:58:37 +0000 | [diff] [blame] | 696 | } | 
|  | 697 |  | 
|  | 698 | CXXMethodDecl::method_iterator CXXMethodDecl::end_overridden_methods() const { | 
| Douglas Gregor | 7d10b7e | 2010-03-02 23:58:15 +0000 | [diff] [blame] | 699 | return getASTContext().overridden_methods_end(this); | 
| Anders Carlsson | 05eb244 | 2009-05-16 23:58:37 +0000 | [diff] [blame] | 700 | } | 
|  | 701 |  | 
| Argyrios Kyrtzidis | c91e9f4 | 2010-07-04 21:44:35 +0000 | [diff] [blame] | 702 | unsigned CXXMethodDecl::size_overridden_methods() const { | 
|  | 703 | return getASTContext().overridden_methods_size(this); | 
|  | 704 | } | 
|  | 705 |  | 
| Ted Kremenek | 4b7c983 | 2008-09-05 17:16:31 +0000 | [diff] [blame] | 706 | QualType CXXMethodDecl::getThisType(ASTContext &C) const { | 
| Argyrios Kyrtzidis | b0d178d | 2008-10-24 22:28:18 +0000 | [diff] [blame] | 707 | // C++ 9.3.2p1: The type of this in a member function of a class X is X*. | 
|  | 708 | // If the member function is declared const, the type of this is const X*, | 
|  | 709 | // if the member function is declared volatile, the type of this is | 
|  | 710 | // volatile X*, and if the member function is declared const volatile, | 
|  | 711 | // the type of this is const volatile X*. | 
|  | 712 |  | 
| Ted Kremenek | 4b7c983 | 2008-09-05 17:16:31 +0000 | [diff] [blame] | 713 | assert(isInstance() && "No 'this' for static methods!"); | 
| Anders Carlsson | 31a0875 | 2009-06-13 02:59:33 +0000 | [diff] [blame] | 714 |  | 
| John McCall | 3cb0ebd | 2010-03-10 03:28:59 +0000 | [diff] [blame] | 715 | QualType ClassTy = C.getTypeDeclType(getParent()); | 
| John McCall | 0953e76 | 2009-09-24 19:53:00 +0000 | [diff] [blame] | 716 | ClassTy = C.getQualifiedType(ClassTy, | 
|  | 717 | Qualifiers::fromCVRMask(getTypeQualifiers())); | 
| Anders Carlsson | 4e57992 | 2009-07-10 21:35:09 +0000 | [diff] [blame] | 718 | return C.getPointerType(ClassTy); | 
| Ted Kremenek | 4b7c983 | 2008-09-05 17:16:31 +0000 | [diff] [blame] | 719 | } | 
|  | 720 |  | 
| Eli Friedman | d7d7f67 | 2009-12-06 20:50:05 +0000 | [diff] [blame] | 721 | bool CXXMethodDecl::hasInlineBody() const { | 
| Douglas Gregor | bd6d619 | 2010-01-05 19:06:31 +0000 | [diff] [blame] | 722 | // If this function is a template instantiation, look at the template from | 
|  | 723 | // which it was instantiated. | 
|  | 724 | const FunctionDecl *CheckFn = getTemplateInstantiationPattern(); | 
|  | 725 | if (!CheckFn) | 
|  | 726 | CheckFn = this; | 
|  | 727 |  | 
| Eli Friedman | d7d7f67 | 2009-12-06 20:50:05 +0000 | [diff] [blame] | 728 | const FunctionDecl *fn; | 
| Argyrios Kyrtzidis | 06a54a3 | 2010-07-07 11:31:19 +0000 | [diff] [blame] | 729 | return CheckFn->hasBody(fn) && !fn->isOutOfLine(); | 
| Eli Friedman | d7d7f67 | 2009-12-06 20:50:05 +0000 | [diff] [blame] | 730 | } | 
|  | 731 |  | 
| Douglas Gregor | 7ad8390 | 2008-11-05 04:29:56 +0000 | [diff] [blame] | 732 | CXXBaseOrMemberInitializer:: | 
| Douglas Gregor | 802ab45 | 2009-12-02 22:36:29 +0000 | [diff] [blame] | 733 | CXXBaseOrMemberInitializer(ASTContext &Context, | 
| Anders Carlsson | 80638c5 | 2010-04-12 00:51:03 +0000 | [diff] [blame] | 734 | TypeSourceInfo *TInfo, bool IsVirtual, | 
| Douglas Gregor | 9db7dbb | 2010-01-31 09:12:51 +0000 | [diff] [blame] | 735 | SourceLocation L, Expr *Init, SourceLocation R) | 
| Abramo Bagnara | a0af3b4 | 2010-05-26 18:09:23 +0000 | [diff] [blame] | 736 | : BaseOrMember(TInfo), Init(Init), AnonUnionMember(0), | 
|  | 737 | LParenLoc(L), RParenLoc(R), IsVirtual(IsVirtual), IsWritten(false), | 
|  | 738 | SourceOrderOrNumArrayIndices(0) | 
| Douglas Gregor | 802ab45 | 2009-12-02 22:36:29 +0000 | [diff] [blame] | 739 | { | 
| Douglas Gregor | 7ad8390 | 2008-11-05 04:29:56 +0000 | [diff] [blame] | 740 | } | 
|  | 741 |  | 
|  | 742 | CXXBaseOrMemberInitializer:: | 
| Douglas Gregor | 802ab45 | 2009-12-02 22:36:29 +0000 | [diff] [blame] | 743 | CXXBaseOrMemberInitializer(ASTContext &Context, | 
|  | 744 | FieldDecl *Member, SourceLocation MemberLoc, | 
| Douglas Gregor | 9db7dbb | 2010-01-31 09:12:51 +0000 | [diff] [blame] | 745 | SourceLocation L, Expr *Init, SourceLocation R) | 
| Abramo Bagnara | a0af3b4 | 2010-05-26 18:09:23 +0000 | [diff] [blame] | 746 | : BaseOrMember(Member), MemberLocation(MemberLoc), Init(Init), | 
|  | 747 | AnonUnionMember(0), LParenLoc(L), RParenLoc(R), IsVirtual(false), | 
|  | 748 | IsWritten(false), SourceOrderOrNumArrayIndices(0) | 
| Douglas Gregor | 802ab45 | 2009-12-02 22:36:29 +0000 | [diff] [blame] | 749 | { | 
| Douglas Gregor | 7ad8390 | 2008-11-05 04:29:56 +0000 | [diff] [blame] | 750 | } | 
|  | 751 |  | 
| Douglas Gregor | fb8cc25 | 2010-05-05 05:51:00 +0000 | [diff] [blame] | 752 | CXXBaseOrMemberInitializer:: | 
|  | 753 | CXXBaseOrMemberInitializer(ASTContext &Context, | 
|  | 754 | FieldDecl *Member, SourceLocation MemberLoc, | 
|  | 755 | SourceLocation L, Expr *Init, SourceLocation R, | 
|  | 756 | VarDecl **Indices, | 
|  | 757 | unsigned NumIndices) | 
|  | 758 | : BaseOrMember(Member), MemberLocation(MemberLoc), Init(Init), | 
| Abramo Bagnara | a0af3b4 | 2010-05-26 18:09:23 +0000 | [diff] [blame] | 759 | AnonUnionMember(0), LParenLoc(L), RParenLoc(R), IsVirtual(false), | 
|  | 760 | IsWritten(false), SourceOrderOrNumArrayIndices(NumIndices) | 
| Douglas Gregor | fb8cc25 | 2010-05-05 05:51:00 +0000 | [diff] [blame] | 761 | { | 
|  | 762 | VarDecl **MyIndices = reinterpret_cast<VarDecl **> (this + 1); | 
|  | 763 | memcpy(MyIndices, Indices, NumIndices * sizeof(VarDecl *)); | 
|  | 764 | } | 
|  | 765 |  | 
|  | 766 | CXXBaseOrMemberInitializer * | 
|  | 767 | CXXBaseOrMemberInitializer::Create(ASTContext &Context, | 
|  | 768 | FieldDecl *Member, | 
|  | 769 | SourceLocation MemberLoc, | 
|  | 770 | SourceLocation L, | 
|  | 771 | Expr *Init, | 
|  | 772 | SourceLocation R, | 
|  | 773 | VarDecl **Indices, | 
|  | 774 | unsigned NumIndices) { | 
|  | 775 | void *Mem = Context.Allocate(sizeof(CXXBaseOrMemberInitializer) + | 
|  | 776 | sizeof(VarDecl *) * NumIndices, | 
|  | 777 | llvm::alignof<CXXBaseOrMemberInitializer>()); | 
|  | 778 | return new (Mem) CXXBaseOrMemberInitializer(Context, Member, MemberLoc, | 
|  | 779 | L, Init, R, Indices, NumIndices); | 
|  | 780 | } | 
|  | 781 |  | 
| Douglas Gregor | 802ab45 | 2009-12-02 22:36:29 +0000 | [diff] [blame] | 782 | TypeLoc CXXBaseOrMemberInitializer::getBaseClassLoc() const { | 
|  | 783 | if (isBaseInitializer()) | 
| John McCall | a93c934 | 2009-12-07 02:54:59 +0000 | [diff] [blame] | 784 | return BaseOrMember.get<TypeSourceInfo*>()->getTypeLoc(); | 
| Douglas Gregor | 802ab45 | 2009-12-02 22:36:29 +0000 | [diff] [blame] | 785 | else | 
|  | 786 | return TypeLoc(); | 
|  | 787 | } | 
|  | 788 |  | 
|  | 789 | Type *CXXBaseOrMemberInitializer::getBaseClass() { | 
|  | 790 | if (isBaseInitializer()) | 
| John McCall | a93c934 | 2009-12-07 02:54:59 +0000 | [diff] [blame] | 791 | return BaseOrMember.get<TypeSourceInfo*>()->getType().getTypePtr(); | 
| Douglas Gregor | 802ab45 | 2009-12-02 22:36:29 +0000 | [diff] [blame] | 792 | else | 
|  | 793 | return 0; | 
|  | 794 | } | 
|  | 795 |  | 
|  | 796 | const Type *CXXBaseOrMemberInitializer::getBaseClass() const { | 
|  | 797 | if (isBaseInitializer()) | 
| John McCall | a93c934 | 2009-12-07 02:54:59 +0000 | [diff] [blame] | 798 | return BaseOrMember.get<TypeSourceInfo*>()->getType().getTypePtr(); | 
| Douglas Gregor | 802ab45 | 2009-12-02 22:36:29 +0000 | [diff] [blame] | 799 | else | 
|  | 800 | return 0; | 
|  | 801 | } | 
|  | 802 |  | 
|  | 803 | SourceLocation CXXBaseOrMemberInitializer::getSourceLocation() const { | 
|  | 804 | if (isMemberInitializer()) | 
|  | 805 | return getMemberLocation(); | 
|  | 806 |  | 
| Abramo Bagnara | bd054db | 2010-05-20 10:00:11 +0000 | [diff] [blame] | 807 | return getBaseClassLoc().getLocalSourceRange().getBegin(); | 
| Douglas Gregor | 802ab45 | 2009-12-02 22:36:29 +0000 | [diff] [blame] | 808 | } | 
|  | 809 |  | 
|  | 810 | SourceRange CXXBaseOrMemberInitializer::getSourceRange() const { | 
|  | 811 | return SourceRange(getSourceLocation(), getRParenLoc()); | 
| Douglas Gregor | 7ad8390 | 2008-11-05 04:29:56 +0000 | [diff] [blame] | 812 | } | 
|  | 813 |  | 
| Douglas Gregor | b48fe38 | 2008-10-31 09:07:45 +0000 | [diff] [blame] | 814 | CXXConstructorDecl * | 
| Chris Lattner | 6ad9ac0 | 2010-05-07 21:43:38 +0000 | [diff] [blame] | 815 | CXXConstructorDecl::Create(ASTContext &C, EmptyShell Empty) { | 
| Abramo Bagnara | 2577743 | 2010-08-11 22:01:17 +0000 | [diff] [blame] | 816 | return new (C) CXXConstructorDecl(0, DeclarationNameInfo(), | 
| Chris Lattner | 6ad9ac0 | 2010-05-07 21:43:38 +0000 | [diff] [blame] | 817 | QualType(), 0, false, false, false); | 
|  | 818 | } | 
|  | 819 |  | 
|  | 820 | CXXConstructorDecl * | 
| Douglas Gregor | b48fe38 | 2008-10-31 09:07:45 +0000 | [diff] [blame] | 821 | CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, | 
| Abramo Bagnara | 2577743 | 2010-08-11 22:01:17 +0000 | [diff] [blame] | 822 | const DeclarationNameInfo &NameInfo, | 
| John McCall | a93c934 | 2009-12-07 02:54:59 +0000 | [diff] [blame] | 823 | QualType T, TypeSourceInfo *TInfo, | 
| Argyrios Kyrtzidis | a1d5662 | 2009-08-19 01:27:57 +0000 | [diff] [blame] | 824 | bool isExplicit, | 
| Douglas Gregor | 16573fa | 2010-04-19 22:54:31 +0000 | [diff] [blame] | 825 | bool isInline, | 
|  | 826 | bool isImplicitlyDeclared) { | 
| Abramo Bagnara | 2577743 | 2010-08-11 22:01:17 +0000 | [diff] [blame] | 827 | assert(NameInfo.getName().getNameKind() | 
|  | 828 | == DeclarationName::CXXConstructorName && | 
| Douglas Gregor | 2e1cd42 | 2008-11-17 14:58:09 +0000 | [diff] [blame] | 829 | "Name must refer to a constructor"); | 
| Abramo Bagnara | 2577743 | 2010-08-11 22:01:17 +0000 | [diff] [blame] | 830 | return new (C) CXXConstructorDecl(RD, NameInfo, T, TInfo, isExplicit, | 
| Douglas Gregor | 16573fa | 2010-04-19 22:54:31 +0000 | [diff] [blame] | 831 | isInline, isImplicitlyDeclared); | 
| Douglas Gregor | b48fe38 | 2008-10-31 09:07:45 +0000 | [diff] [blame] | 832 | } | 
|  | 833 |  | 
| Douglas Gregor | 030ff0c | 2008-10-31 20:25:05 +0000 | [diff] [blame] | 834 | bool CXXConstructorDecl::isDefaultConstructor() const { | 
|  | 835 | // C++ [class.ctor]p5: | 
| Douglas Gregor | 64bffa9 | 2008-11-05 16:20:31 +0000 | [diff] [blame] | 836 | //   A default constructor for a class X is a constructor of class | 
|  | 837 | //   X that can be called without an argument. | 
| Douglas Gregor | 030ff0c | 2008-10-31 20:25:05 +0000 | [diff] [blame] | 838 | return (getNumParams() == 0) || | 
| Anders Carlsson | da3f4e2 | 2009-08-25 05:12:04 +0000 | [diff] [blame] | 839 | (getNumParams() > 0 && getParamDecl(0)->hasDefaultArg()); | 
| Douglas Gregor | 030ff0c | 2008-10-31 20:25:05 +0000 | [diff] [blame] | 840 | } | 
|  | 841 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 842 | bool | 
| Douglas Gregor | 9e9199d | 2009-12-22 00:34:07 +0000 | [diff] [blame] | 843 | CXXConstructorDecl::isCopyConstructor(unsigned &TypeQuals) const { | 
| Douglas Gregor | 030ff0c | 2008-10-31 20:25:05 +0000 | [diff] [blame] | 844 | // C++ [class.copy]p2: | 
| Douglas Gregor | 64bffa9 | 2008-11-05 16:20:31 +0000 | [diff] [blame] | 845 | //   A non-template constructor for class X is a copy constructor | 
|  | 846 | //   if its first parameter is of type X&, const X&, volatile X& or | 
|  | 847 | //   const volatile X&, and either there are no other parameters | 
|  | 848 | //   or else all other parameters have default arguments (8.3.6). | 
| Douglas Gregor | 030ff0c | 2008-10-31 20:25:05 +0000 | [diff] [blame] | 849 | if ((getNumParams() < 1) || | 
| Douglas Gregor | 77da3f4 | 2009-10-13 23:45:19 +0000 | [diff] [blame] | 850 | (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) || | 
| Douglas Gregor | fd47648 | 2009-11-13 23:59:09 +0000 | [diff] [blame] | 851 | (getPrimaryTemplate() != 0) || | 
| Douglas Gregor | 77da3f4 | 2009-10-13 23:45:19 +0000 | [diff] [blame] | 852 | (getDescribedFunctionTemplate() != 0)) | 
| Douglas Gregor | 030ff0c | 2008-10-31 20:25:05 +0000 | [diff] [blame] | 853 | return false; | 
|  | 854 |  | 
|  | 855 | const ParmVarDecl *Param = getParamDecl(0); | 
|  | 856 |  | 
| Sebastian Redl | 7c80bd6 | 2009-03-16 23:22:08 +0000 | [diff] [blame] | 857 | // Do we have a reference type? Rvalue references don't count. | 
| Douglas Gregor | fd47648 | 2009-11-13 23:59:09 +0000 | [diff] [blame] | 858 | const LValueReferenceType *ParamRefType = | 
|  | 859 | Param->getType()->getAs<LValueReferenceType>(); | 
|  | 860 | if (!ParamRefType) | 
|  | 861 | return false; | 
| Douglas Gregor | 030ff0c | 2008-10-31 20:25:05 +0000 | [diff] [blame] | 862 |  | 
| Douglas Gregor | fd47648 | 2009-11-13 23:59:09 +0000 | [diff] [blame] | 863 | // Is it a reference to our class type? | 
| Douglas Gregor | 9e9199d | 2009-12-22 00:34:07 +0000 | [diff] [blame] | 864 | ASTContext &Context = getASTContext(); | 
|  | 865 |  | 
| Douglas Gregor | fd47648 | 2009-11-13 23:59:09 +0000 | [diff] [blame] | 866 | CanQualType PointeeType | 
|  | 867 | = Context.getCanonicalType(ParamRefType->getPointeeType()); | 
| Douglas Gregor | 14e0b3d | 2009-09-15 20:50:23 +0000 | [diff] [blame] | 868 | CanQualType ClassTy | 
|  | 869 | = Context.getCanonicalType(Context.getTagDeclType(getParent())); | 
| Douglas Gregor | 030ff0c | 2008-10-31 20:25:05 +0000 | [diff] [blame] | 870 | if (PointeeType.getUnqualifiedType() != ClassTy) | 
|  | 871 | return false; | 
|  | 872 |  | 
| John McCall | 0953e76 | 2009-09-24 19:53:00 +0000 | [diff] [blame] | 873 | // FIXME: other qualifiers? | 
|  | 874 |  | 
| Douglas Gregor | 030ff0c | 2008-10-31 20:25:05 +0000 | [diff] [blame] | 875 | // We have a copy constructor. | 
|  | 876 | TypeQuals = PointeeType.getCVRQualifiers(); | 
|  | 877 | return true; | 
|  | 878 | } | 
|  | 879 |  | 
| Anders Carlsson | faccd72 | 2009-08-28 16:57:08 +0000 | [diff] [blame] | 880 | bool CXXConstructorDecl::isConvertingConstructor(bool AllowExplicit) const { | 
| Douglas Gregor | 60d62c2 | 2008-10-31 16:23:19 +0000 | [diff] [blame] | 881 | // C++ [class.conv.ctor]p1: | 
|  | 882 | //   A constructor declared without the function-specifier explicit | 
|  | 883 | //   that can be called with a single parameter specifies a | 
|  | 884 | //   conversion from the type of its first parameter to the type of | 
|  | 885 | //   its class. Such a constructor is called a converting | 
|  | 886 | //   constructor. | 
| Anders Carlsson | faccd72 | 2009-08-28 16:57:08 +0000 | [diff] [blame] | 887 | if (isExplicit() && !AllowExplicit) | 
| Douglas Gregor | 60d62c2 | 2008-10-31 16:23:19 +0000 | [diff] [blame] | 888 | return false; | 
|  | 889 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 890 | return (getNumParams() == 0 && | 
| John McCall | 183700f | 2009-09-21 23:43:11 +0000 | [diff] [blame] | 891 | getType()->getAs<FunctionProtoType>()->isVariadic()) || | 
| Douglas Gregor | 60d62c2 | 2008-10-31 16:23:19 +0000 | [diff] [blame] | 892 | (getNumParams() == 1) || | 
| Anders Carlsson | ae0b4e7 | 2009-06-06 04:14:07 +0000 | [diff] [blame] | 893 | (getNumParams() > 1 && getParamDecl(1)->hasDefaultArg()); | 
| Douglas Gregor | 60d62c2 | 2008-10-31 16:23:19 +0000 | [diff] [blame] | 894 | } | 
| Douglas Gregor | b48fe38 | 2008-10-31 09:07:45 +0000 | [diff] [blame] | 895 |  | 
| Douglas Gregor | 66724ea | 2009-11-14 01:20:54 +0000 | [diff] [blame] | 896 | bool CXXConstructorDecl::isCopyConstructorLikeSpecialization() const { | 
|  | 897 | if ((getNumParams() < 1) || | 
|  | 898 | (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) || | 
|  | 899 | (getPrimaryTemplate() == 0) || | 
|  | 900 | (getDescribedFunctionTemplate() != 0)) | 
|  | 901 | return false; | 
|  | 902 |  | 
|  | 903 | const ParmVarDecl *Param = getParamDecl(0); | 
|  | 904 |  | 
|  | 905 | ASTContext &Context = getASTContext(); | 
|  | 906 | CanQualType ParamType = Context.getCanonicalType(Param->getType()); | 
|  | 907 |  | 
|  | 908 | // Strip off the lvalue reference, if any. | 
|  | 909 | if (CanQual<LValueReferenceType> ParamRefType | 
|  | 910 | = ParamType->getAs<LValueReferenceType>()) | 
|  | 911 | ParamType = ParamRefType->getPointeeType(); | 
|  | 912 |  | 
|  | 913 |  | 
|  | 914 | // Is it the same as our our class type? | 
|  | 915 | CanQualType ClassTy | 
|  | 916 | = Context.getCanonicalType(Context.getTagDeclType(getParent())); | 
|  | 917 | if (ParamType.getUnqualifiedType() != ClassTy) | 
|  | 918 | return false; | 
|  | 919 |  | 
|  | 920 | return true; | 
|  | 921 | } | 
|  | 922 |  | 
| Douglas Gregor | 42a552f | 2008-11-05 20:51:48 +0000 | [diff] [blame] | 923 | CXXDestructorDecl * | 
| Chris Lattner | 6ad9ac0 | 2010-05-07 21:43:38 +0000 | [diff] [blame] | 924 | CXXDestructorDecl::Create(ASTContext &C, EmptyShell Empty) { | 
| Abramo Bagnara | 2577743 | 2010-08-11 22:01:17 +0000 | [diff] [blame] | 925 | return new (C) CXXDestructorDecl(0, DeclarationNameInfo(), | 
| Chris Lattner | 6ad9ac0 | 2010-05-07 21:43:38 +0000 | [diff] [blame] | 926 | QualType(), false, false); | 
|  | 927 | } | 
|  | 928 |  | 
|  | 929 | CXXDestructorDecl * | 
| Douglas Gregor | 42a552f | 2008-11-05 20:51:48 +0000 | [diff] [blame] | 930 | CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, | 
| Abramo Bagnara | 2577743 | 2010-08-11 22:01:17 +0000 | [diff] [blame] | 931 | const DeclarationNameInfo &NameInfo, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 932 | QualType T, bool isInline, | 
| Douglas Gregor | 42a552f | 2008-11-05 20:51:48 +0000 | [diff] [blame] | 933 | bool isImplicitlyDeclared) { | 
| Abramo Bagnara | 2577743 | 2010-08-11 22:01:17 +0000 | [diff] [blame] | 934 | assert(NameInfo.getName().getNameKind() | 
|  | 935 | == DeclarationName::CXXDestructorName && | 
| Douglas Gregor | 2e1cd42 | 2008-11-17 14:58:09 +0000 | [diff] [blame] | 936 | "Name must refer to a destructor"); | 
| Abramo Bagnara | 2577743 | 2010-08-11 22:01:17 +0000 | [diff] [blame] | 937 | return new (C) CXXDestructorDecl(RD, NameInfo, T, isInline, | 
|  | 938 | isImplicitlyDeclared); | 
| Douglas Gregor | 42a552f | 2008-11-05 20:51:48 +0000 | [diff] [blame] | 939 | } | 
|  | 940 |  | 
| Douglas Gregor | 2f1bc52 | 2008-11-07 20:08:42 +0000 | [diff] [blame] | 941 | CXXConversionDecl * | 
| Chris Lattner | 6ad9ac0 | 2010-05-07 21:43:38 +0000 | [diff] [blame] | 942 | CXXConversionDecl::Create(ASTContext &C, EmptyShell Empty) { | 
| Abramo Bagnara | 2577743 | 2010-08-11 22:01:17 +0000 | [diff] [blame] | 943 | return new (C) CXXConversionDecl(0, DeclarationNameInfo(), | 
| Chris Lattner | 6ad9ac0 | 2010-05-07 21:43:38 +0000 | [diff] [blame] | 944 | QualType(), 0, false, false); | 
|  | 945 | } | 
|  | 946 |  | 
|  | 947 | CXXConversionDecl * | 
| Douglas Gregor | 2f1bc52 | 2008-11-07 20:08:42 +0000 | [diff] [blame] | 948 | CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD, | 
| Abramo Bagnara | 2577743 | 2010-08-11 22:01:17 +0000 | [diff] [blame] | 949 | const DeclarationNameInfo &NameInfo, | 
| John McCall | a93c934 | 2009-12-07 02:54:59 +0000 | [diff] [blame] | 950 | QualType T, TypeSourceInfo *TInfo, | 
| Argyrios Kyrtzidis | a1d5662 | 2009-08-19 01:27:57 +0000 | [diff] [blame] | 951 | bool isInline, bool isExplicit) { | 
| Abramo Bagnara | 2577743 | 2010-08-11 22:01:17 +0000 | [diff] [blame] | 952 | assert(NameInfo.getName().getNameKind() | 
|  | 953 | == DeclarationName::CXXConversionFunctionName && | 
| Douglas Gregor | 2e1cd42 | 2008-11-17 14:58:09 +0000 | [diff] [blame] | 954 | "Name must refer to a conversion function"); | 
| Abramo Bagnara | 2577743 | 2010-08-11 22:01:17 +0000 | [diff] [blame] | 955 | return new (C) CXXConversionDecl(RD, NameInfo, T, TInfo, | 
|  | 956 | isInline, isExplicit); | 
| Douglas Gregor | 2f1bc52 | 2008-11-07 20:08:42 +0000 | [diff] [blame] | 957 | } | 
|  | 958 |  | 
| Chris Lattner | 21ef7ae | 2008-11-04 16:51:42 +0000 | [diff] [blame] | 959 | LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 960 | DeclContext *DC, | 
| Chris Lattner | 21ef7ae | 2008-11-04 16:51:42 +0000 | [diff] [blame] | 961 | SourceLocation L, | 
| Douglas Gregor | 074149e | 2009-01-05 19:45:36 +0000 | [diff] [blame] | 962 | LanguageIDs Lang, bool Braces) { | 
| Steve Naroff | 3e97049 | 2009-01-27 21:25:57 +0000 | [diff] [blame] | 963 | return new (C) LinkageSpecDecl(DC, L, Lang, Braces); | 
| Douglas Gregor | f44515a | 2008-12-16 22:23:02 +0000 | [diff] [blame] | 964 | } | 
| Douglas Gregor | 2a3009a | 2009-02-03 19:21:40 +0000 | [diff] [blame] | 965 |  | 
|  | 966 | UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC, | 
|  | 967 | SourceLocation L, | 
|  | 968 | SourceLocation NamespaceLoc, | 
| Douglas Gregor | 8419fa3 | 2009-05-30 06:31:56 +0000 | [diff] [blame] | 969 | SourceRange QualifierRange, | 
|  | 970 | NestedNameSpecifier *Qualifier, | 
| Douglas Gregor | 2a3009a | 2009-02-03 19:21:40 +0000 | [diff] [blame] | 971 | SourceLocation IdentLoc, | 
| Sebastian Redl | eb0d8c9 | 2009-11-23 15:34:23 +0000 | [diff] [blame] | 972 | NamedDecl *Used, | 
| Douglas Gregor | 2a3009a | 2009-02-03 19:21:40 +0000 | [diff] [blame] | 973 | DeclContext *CommonAncestor) { | 
| Sebastian Redl | eb0d8c9 | 2009-11-23 15:34:23 +0000 | [diff] [blame] | 974 | if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Used)) | 
|  | 975 | Used = NS->getOriginalNamespace(); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 976 | return new (C) UsingDirectiveDecl(DC, L, NamespaceLoc, QualifierRange, | 
| Douglas Gregor | 8419fa3 | 2009-05-30 06:31:56 +0000 | [diff] [blame] | 977 | Qualifier, IdentLoc, Used, CommonAncestor); | 
| Douglas Gregor | 2a3009a | 2009-02-03 19:21:40 +0000 | [diff] [blame] | 978 | } | 
|  | 979 |  | 
| Sebastian Redl | eb0d8c9 | 2009-11-23 15:34:23 +0000 | [diff] [blame] | 980 | NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() { | 
|  | 981 | if (NamespaceAliasDecl *NA = | 
|  | 982 | dyn_cast_or_null<NamespaceAliasDecl>(NominatedNamespace)) | 
|  | 983 | return NA->getNamespace(); | 
|  | 984 | return cast_or_null<NamespaceDecl>(NominatedNamespace); | 
|  | 985 | } | 
|  | 986 |  | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 987 | NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC, | 
| Douglas Gregor | 0a35bce | 2010-09-01 03:07:18 +0000 | [diff] [blame] | 988 | SourceLocation UsingLoc, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 989 | SourceLocation AliasLoc, | 
|  | 990 | IdentifierInfo *Alias, | 
| Douglas Gregor | 6c9c940 | 2009-05-30 06:48:27 +0000 | [diff] [blame] | 991 | SourceRange QualifierRange, | 
|  | 992 | NestedNameSpecifier *Qualifier, | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 993 | SourceLocation IdentLoc, | 
| Anders Carlsson | 68771c7 | 2009-03-28 22:58:02 +0000 | [diff] [blame] | 994 | NamedDecl *Namespace) { | 
| Sebastian Redl | eb0d8c9 | 2009-11-23 15:34:23 +0000 | [diff] [blame] | 995 | if (NamespaceDecl *NS = dyn_cast_or_null<NamespaceDecl>(Namespace)) | 
|  | 996 | Namespace = NS->getOriginalNamespace(); | 
| Douglas Gregor | 0a35bce | 2010-09-01 03:07:18 +0000 | [diff] [blame] | 997 | return new (C) NamespaceAliasDecl(DC, UsingLoc, AliasLoc, Alias, QualifierRange, | 
| Douglas Gregor | 6c9c940 | 2009-05-30 06:48:27 +0000 | [diff] [blame] | 998 | Qualifier, IdentLoc, Namespace); | 
| Anders Carlsson | 68771c7 | 2009-03-28 22:58:02 +0000 | [diff] [blame] | 999 | } | 
|  | 1000 |  | 
| Douglas Gregor | 9cfbe48 | 2009-06-20 00:51:54 +0000 | [diff] [blame] | 1001 | UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, | 
| Abramo Bagnara | ef3dce8 | 2010-08-12 11:46:03 +0000 | [diff] [blame] | 1002 | SourceRange NNR, SourceLocation UL, | 
|  | 1003 | NestedNameSpecifier* TargetNNS, | 
|  | 1004 | const DeclarationNameInfo &NameInfo, | 
|  | 1005 | bool IsTypeNameArg) { | 
|  | 1006 | return new (C) UsingDecl(DC, NNR, UL, TargetNNS, NameInfo, IsTypeNameArg); | 
| Douglas Gregor | 9cfbe48 | 2009-06-20 00:51:54 +0000 | [diff] [blame] | 1007 | } | 
|  | 1008 |  | 
| John McCall | 7ba107a | 2009-11-18 02:36:19 +0000 | [diff] [blame] | 1009 | UnresolvedUsingValueDecl * | 
|  | 1010 | UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC, | 
|  | 1011 | SourceLocation UsingLoc, | 
|  | 1012 | SourceRange TargetNNR, | 
|  | 1013 | NestedNameSpecifier *TargetNNS, | 
| Abramo Bagnara | ef3dce8 | 2010-08-12 11:46:03 +0000 | [diff] [blame] | 1014 | const DeclarationNameInfo &NameInfo) { | 
| John McCall | 7ba107a | 2009-11-18 02:36:19 +0000 | [diff] [blame] | 1015 | return new (C) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc, | 
| Abramo Bagnara | ef3dce8 | 2010-08-12 11:46:03 +0000 | [diff] [blame] | 1016 | TargetNNR, TargetNNS, NameInfo); | 
| John McCall | 7ba107a | 2009-11-18 02:36:19 +0000 | [diff] [blame] | 1017 | } | 
|  | 1018 |  | 
|  | 1019 | UnresolvedUsingTypenameDecl * | 
|  | 1020 | UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC, | 
|  | 1021 | SourceLocation UsingLoc, | 
|  | 1022 | SourceLocation TypenameLoc, | 
|  | 1023 | SourceRange TargetNNR, | 
|  | 1024 | NestedNameSpecifier *TargetNNS, | 
|  | 1025 | SourceLocation TargetNameLoc, | 
|  | 1026 | DeclarationName TargetName) { | 
|  | 1027 | return new (C) UnresolvedUsingTypenameDecl(DC, UsingLoc, TypenameLoc, | 
|  | 1028 | TargetNNR, TargetNNS, | 
|  | 1029 | TargetNameLoc, | 
|  | 1030 | TargetName.getAsIdentifierInfo()); | 
| Anders Carlsson | 665b49c | 2009-08-28 05:30:28 +0000 | [diff] [blame] | 1031 | } | 
|  | 1032 |  | 
| Anders Carlsson | fb31176 | 2009-03-14 00:25:26 +0000 | [diff] [blame] | 1033 | StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC, | 
|  | 1034 | SourceLocation L, Expr *AssertExpr, | 
|  | 1035 | StringLiteral *Message) { | 
|  | 1036 | return new (C) StaticAssertDecl(DC, L, AssertExpr, Message); | 
|  | 1037 | } | 
|  | 1038 |  | 
| Anders Carlsson | 05bf2c7 | 2009-03-26 23:46:50 +0000 | [diff] [blame] | 1039 | static const char *getAccessName(AccessSpecifier AS) { | 
|  | 1040 | switch (AS) { | 
|  | 1041 | default: | 
|  | 1042 | case AS_none: | 
|  | 1043 | assert("Invalid access specifier!"); | 
|  | 1044 | return 0; | 
|  | 1045 | case AS_public: | 
|  | 1046 | return "public"; | 
|  | 1047 | case AS_private: | 
|  | 1048 | return "private"; | 
|  | 1049 | case AS_protected: | 
|  | 1050 | return "protected"; | 
|  | 1051 | } | 
|  | 1052 | } | 
|  | 1053 |  | 
|  | 1054 | const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, | 
|  | 1055 | AccessSpecifier AS) { | 
|  | 1056 | return DB << getAccessName(AS); | 
|  | 1057 | } |