| Douglas Gregor | e4e5b05 | 2009-03-19 00:18:19 +0000 | [diff] [blame] | 1 | //===--- NestedNameSpecifier.cpp - C++ nested name specifiers -----*- C++ -*-=// | 
 | 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 defines the NestedNameSpecifier class, which represents | 
 | 11 | //  a C++ nested-name-specifier. | 
 | 12 | // | 
 | 13 | //===----------------------------------------------------------------------===// | 
 | 14 | #include "clang/AST/NestedNameSpecifier.h" | 
 | 15 | #include "clang/AST/ASTContext.h" | 
 | 16 | #include "clang/AST/Decl.h" | 
| Douglas Gregor | 14aba76 | 2011-02-24 02:36:08 +0000 | [diff] [blame] | 17 | #include "clang/AST/DeclCXX.h" | 
| Douglas Gregor | d249e1d1f | 2009-05-29 20:38:28 +0000 | [diff] [blame] | 18 | #include "clang/AST/PrettyPrinter.h" | 
| Douglas Gregor | e4e5b05 | 2009-03-19 00:18:19 +0000 | [diff] [blame] | 19 | #include "clang/AST/Type.h" | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 20 | #include "clang/AST/TypeLoc.h" | 
| Richard Smith | 4746704 | 2012-08-15 01:41:43 +0000 | [diff] [blame^] | 21 | #include "llvm/Support/AlignOf.h" | 
| Douglas Gregor | bad3518 | 2009-03-19 03:51:16 +0000 | [diff] [blame] | 22 | #include "llvm/Support/raw_ostream.h" | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 23 | #include <cassert> | 
| Douglas Gregor | bad3518 | 2009-03-19 03:51:16 +0000 | [diff] [blame] | 24 |  | 
| Douglas Gregor | e4e5b05 | 2009-03-19 00:18:19 +0000 | [diff] [blame] | 25 | using namespace clang; | 
 | 26 |  | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 27 | NestedNameSpecifier * | 
| Jay Foad | 4ba2a17 | 2011-01-12 09:06:06 +0000 | [diff] [blame] | 28 | NestedNameSpecifier::FindOrInsert(const ASTContext &Context, | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 29 |                                   const NestedNameSpecifier &Mockup) { | 
 | 30 |   llvm::FoldingSetNodeID ID; | 
 | 31 |   Mockup.Profile(ID); | 
| Douglas Gregor | e4e5b05 | 2009-03-19 00:18:19 +0000 | [diff] [blame] | 32 |  | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 33 |   void *InsertPos = 0; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 34 |   NestedNameSpecifier *NNS | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 35 |     = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos); | 
 | 36 |   if (!NNS) { | 
| Richard Smith | 4746704 | 2012-08-15 01:41:43 +0000 | [diff] [blame^] | 37 |     NNS = new (Context, llvm::alignOf<NestedNameSpecifier>()) | 
 | 38 |         NestedNameSpecifier(Mockup); | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 39 |     Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos); | 
 | 40 |   } | 
| Douglas Gregor | e4e5b05 | 2009-03-19 00:18:19 +0000 | [diff] [blame] | 41 |  | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 42 |   return NNS; | 
| Douglas Gregor | e4e5b05 | 2009-03-19 00:18:19 +0000 | [diff] [blame] | 43 | } | 
| Douglas Gregor | bad3518 | 2009-03-19 03:51:16 +0000 | [diff] [blame] | 44 |  | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 45 | NestedNameSpecifier * | 
| Jay Foad | 4ba2a17 | 2011-01-12 09:06:06 +0000 | [diff] [blame] | 46 | NestedNameSpecifier::Create(const ASTContext &Context, | 
 | 47 |                             NestedNameSpecifier *Prefix, IdentifierInfo *II) { | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 48 |   assert(II && "Identifier cannot be NULL"); | 
| Douglas Gregor | 3b6afbb | 2009-09-09 00:23:06 +0000 | [diff] [blame] | 49 |   assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent"); | 
| Douglas Gregor | bad3518 | 2009-03-19 03:51:16 +0000 | [diff] [blame] | 50 |  | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 51 |   NestedNameSpecifier Mockup; | 
| Douglas Gregor | 1734317 | 2009-04-01 00:28:59 +0000 | [diff] [blame] | 52 |   Mockup.Prefix.setPointer(Prefix); | 
| Douglas Gregor | 14aba76 | 2011-02-24 02:36:08 +0000 | [diff] [blame] | 53 |   Mockup.Prefix.setInt(StoredIdentifier); | 
| Douglas Gregor | 1734317 | 2009-04-01 00:28:59 +0000 | [diff] [blame] | 54 |   Mockup.Specifier = II; | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 55 |   return FindOrInsert(Context, Mockup); | 
 | 56 | } | 
| Douglas Gregor | bad3518 | 2009-03-19 03:51:16 +0000 | [diff] [blame] | 57 |  | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 58 | NestedNameSpecifier * | 
| Jay Foad | 4ba2a17 | 2011-01-12 09:06:06 +0000 | [diff] [blame] | 59 | NestedNameSpecifier::Create(const ASTContext &Context, | 
 | 60 |                             NestedNameSpecifier *Prefix, NamespaceDecl *NS) { | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 61 |   assert(NS && "Namespace cannot be NULL"); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 62 |   assert((!Prefix || | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 63 |           (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) && | 
 | 64 |          "Broken nested name specifier"); | 
 | 65 |   NestedNameSpecifier Mockup; | 
| Douglas Gregor | 1734317 | 2009-04-01 00:28:59 +0000 | [diff] [blame] | 66 |   Mockup.Prefix.setPointer(Prefix); | 
| Douglas Gregor | 14aba76 | 2011-02-24 02:36:08 +0000 | [diff] [blame] | 67 |   Mockup.Prefix.setInt(StoredNamespaceOrAlias); | 
| Douglas Gregor | 1734317 | 2009-04-01 00:28:59 +0000 | [diff] [blame] | 68 |   Mockup.Specifier = NS; | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 69 |   return FindOrInsert(Context, Mockup); | 
 | 70 | } | 
 | 71 |  | 
 | 72 | NestedNameSpecifier * | 
| Jay Foad | 4ba2a17 | 2011-01-12 09:06:06 +0000 | [diff] [blame] | 73 | NestedNameSpecifier::Create(const ASTContext &Context, | 
| Douglas Gregor | 14aba76 | 2011-02-24 02:36:08 +0000 | [diff] [blame] | 74 |                             NestedNameSpecifier *Prefix,  | 
 | 75 |                             NamespaceAliasDecl *Alias) { | 
 | 76 |   assert(Alias && "Namespace alias cannot be NULL"); | 
 | 77 |   assert((!Prefix || | 
 | 78 |           (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) && | 
 | 79 |          "Broken nested name specifier"); | 
 | 80 |   NestedNameSpecifier Mockup; | 
 | 81 |   Mockup.Prefix.setPointer(Prefix); | 
 | 82 |   Mockup.Prefix.setInt(StoredNamespaceOrAlias); | 
 | 83 |   Mockup.Specifier = Alias; | 
 | 84 |   return FindOrInsert(Context, Mockup); | 
 | 85 | } | 
 | 86 |  | 
 | 87 | NestedNameSpecifier * | 
 | 88 | NestedNameSpecifier::Create(const ASTContext &Context, | 
| Jay Foad | 4ba2a17 | 2011-01-12 09:06:06 +0000 | [diff] [blame] | 89 |                             NestedNameSpecifier *Prefix, | 
| John McCall | f4c7371 | 2011-01-19 06:33:43 +0000 | [diff] [blame] | 90 |                             bool Template, const Type *T) { | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 91 |   assert(T && "Type cannot be NULL"); | 
 | 92 |   NestedNameSpecifier Mockup; | 
| Douglas Gregor | 1734317 | 2009-04-01 00:28:59 +0000 | [diff] [blame] | 93 |   Mockup.Prefix.setPointer(Prefix); | 
| Douglas Gregor | 14aba76 | 2011-02-24 02:36:08 +0000 | [diff] [blame] | 94 |   Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec); | 
| John McCall | f4c7371 | 2011-01-19 06:33:43 +0000 | [diff] [blame] | 95 |   Mockup.Specifier = const_cast<Type*>(T); | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 96 |   return FindOrInsert(Context, Mockup); | 
 | 97 | } | 
| Douglas Gregor | 2700dcd | 2009-09-02 23:58:38 +0000 | [diff] [blame] | 98 |  | 
 | 99 | NestedNameSpecifier * | 
| Jay Foad | 4ba2a17 | 2011-01-12 09:06:06 +0000 | [diff] [blame] | 100 | NestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) { | 
| Douglas Gregor | 2700dcd | 2009-09-02 23:58:38 +0000 | [diff] [blame] | 101 |   assert(II && "Identifier cannot be NULL"); | 
 | 102 |   NestedNameSpecifier Mockup; | 
 | 103 |   Mockup.Prefix.setPointer(0); | 
| Douglas Gregor | 14aba76 | 2011-02-24 02:36:08 +0000 | [diff] [blame] | 104 |   Mockup.Prefix.setInt(StoredIdentifier); | 
| Douglas Gregor | 2700dcd | 2009-09-02 23:58:38 +0000 | [diff] [blame] | 105 |   Mockup.Specifier = II; | 
 | 106 |   return FindOrInsert(Context, Mockup); | 
 | 107 | } | 
 | 108 |  | 
| Jay Foad | 4ba2a17 | 2011-01-12 09:06:06 +0000 | [diff] [blame] | 109 | NestedNameSpecifier * | 
 | 110 | NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) { | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 111 |   if (!Context.GlobalNestedNameSpecifier) | 
| Richard Smith | 4746704 | 2012-08-15 01:41:43 +0000 | [diff] [blame^] | 112 |     Context.GlobalNestedNameSpecifier = | 
 | 113 |         new (Context, llvm::alignOf<NestedNameSpecifier>()) | 
 | 114 |             NestedNameSpecifier(); | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 115 |   return Context.GlobalNestedNameSpecifier; | 
 | 116 | } | 
 | 117 |  | 
| Douglas Gregor | 14aba76 | 2011-02-24 02:36:08 +0000 | [diff] [blame] | 118 | NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { | 
 | 119 |   if (Specifier == 0) | 
 | 120 |     return Global; | 
 | 121 |  | 
 | 122 |   switch (Prefix.getInt()) { | 
 | 123 |   case StoredIdentifier: | 
 | 124 |     return Identifier; | 
 | 125 |  | 
 | 126 |   case StoredNamespaceOrAlias: | 
 | 127 |     return isa<NamespaceDecl>(static_cast<NamedDecl *>(Specifier))? Namespace | 
 | 128 |                                                             : NamespaceAlias; | 
 | 129 |  | 
 | 130 |   case StoredTypeSpec: | 
 | 131 |     return TypeSpec; | 
 | 132 |  | 
 | 133 |   case StoredTypeSpecWithTemplate: | 
 | 134 |     return TypeSpecWithTemplate; | 
 | 135 |   } | 
 | 136 |  | 
| David Blaikie | 3026348 | 2012-01-20 21:50:17 +0000 | [diff] [blame] | 137 |   llvm_unreachable("Invalid NNS Kind!"); | 
| Douglas Gregor | 14aba76 | 2011-02-24 02:36:08 +0000 | [diff] [blame] | 138 | } | 
 | 139 |  | 
 | 140 | /// \brief Retrieve the namespace stored in this nested name | 
 | 141 | /// specifier. | 
 | 142 | NamespaceDecl *NestedNameSpecifier::getAsNamespace() const { | 
 | 143 |   if (Prefix.getInt() == StoredNamespaceOrAlias) | 
 | 144 |     return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier)); | 
 | 145 |  | 
 | 146 |   return 0; | 
 | 147 | } | 
 | 148 |  | 
 | 149 | /// \brief Retrieve the namespace alias stored in this nested name | 
 | 150 | /// specifier. | 
 | 151 | NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const { | 
 | 152 |   if (Prefix.getInt() == StoredNamespaceOrAlias) | 
 | 153 |     return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier)); | 
 | 154 |  | 
 | 155 |   return 0; | 
 | 156 | } | 
 | 157 |  | 
 | 158 |  | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 159 | /// \brief Whether this nested name specifier refers to a dependent | 
 | 160 | /// type or not. | 
 | 161 | bool NestedNameSpecifier::isDependent() const { | 
 | 162 |   switch (getKind()) { | 
 | 163 |   case Identifier: | 
 | 164 |     // Identifier specifiers always represent dependent types | 
 | 165 |     return true; | 
 | 166 |  | 
 | 167 |   case Namespace: | 
| Douglas Gregor | 14aba76 | 2011-02-24 02:36:08 +0000 | [diff] [blame] | 168 |   case NamespaceAlias: | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 169 |   case Global: | 
 | 170 |     return false; | 
 | 171 |  | 
 | 172 |   case TypeSpec: | 
 | 173 |   case TypeSpecWithTemplate: | 
 | 174 |     return getAsType()->isDependentType(); | 
| Douglas Gregor | bad3518 | 2009-03-19 03:51:16 +0000 | [diff] [blame] | 175 |   } | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 176 |  | 
| David Blaikie | 3026348 | 2012-01-20 21:50:17 +0000 | [diff] [blame] | 177 |   llvm_unreachable("Invalid NNS Kind!"); | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 178 | } | 
 | 179 |  | 
| Douglas Gregor | 561f812 | 2011-07-01 01:22:09 +0000 | [diff] [blame] | 180 | /// \brief Whether this nested name specifier refers to a dependent | 
 | 181 | /// type or not. | 
 | 182 | bool NestedNameSpecifier::isInstantiationDependent() const { | 
 | 183 |   switch (getKind()) { | 
 | 184 |   case Identifier: | 
 | 185 |     // Identifier specifiers always represent dependent types | 
 | 186 |     return true; | 
 | 187 |      | 
 | 188 |   case Namespace: | 
 | 189 |   case NamespaceAlias: | 
 | 190 |   case Global: | 
 | 191 |     return false; | 
 | 192 |      | 
 | 193 |   case TypeSpec: | 
 | 194 |   case TypeSpecWithTemplate: | 
 | 195 |     return getAsType()->isInstantiationDependentType(); | 
 | 196 |   } | 
| David Blaikie | 3026348 | 2012-01-20 21:50:17 +0000 | [diff] [blame] | 197 |  | 
 | 198 |   llvm_unreachable("Invalid NNS Kind!"); | 
| Douglas Gregor | 561f812 | 2011-07-01 01:22:09 +0000 | [diff] [blame] | 199 | } | 
 | 200 |  | 
| Douglas Gregor | d093722 | 2010-12-13 22:49:22 +0000 | [diff] [blame] | 201 | bool NestedNameSpecifier::containsUnexpandedParameterPack() const { | 
 | 202 |   switch (getKind()) { | 
 | 203 |   case Identifier: | 
 | 204 |     return getPrefix() && getPrefix()->containsUnexpandedParameterPack(); | 
 | 205 |  | 
 | 206 |   case Namespace: | 
| Douglas Gregor | 14aba76 | 2011-02-24 02:36:08 +0000 | [diff] [blame] | 207 |   case NamespaceAlias: | 
| Douglas Gregor | d093722 | 2010-12-13 22:49:22 +0000 | [diff] [blame] | 208 |   case Global: | 
 | 209 |     return false; | 
 | 210 |  | 
 | 211 |   case TypeSpec: | 
 | 212 |   case TypeSpecWithTemplate: | 
 | 213 |     return getAsType()->containsUnexpandedParameterPack(); | 
 | 214 |   } | 
 | 215 |  | 
| David Blaikie | 3026348 | 2012-01-20 21:50:17 +0000 | [diff] [blame] | 216 |   llvm_unreachable("Invalid NNS Kind!"); | 
| Douglas Gregor | d093722 | 2010-12-13 22:49:22 +0000 | [diff] [blame] | 217 | } | 
 | 218 |  | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 219 | /// \brief Print this nested name specifier to the given output | 
 | 220 | /// stream. | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 221 | void | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 222 | NestedNameSpecifier::print(raw_ostream &OS, | 
| Douglas Gregor | d249e1d1f | 2009-05-29 20:38:28 +0000 | [diff] [blame] | 223 |                            const PrintingPolicy &Policy) const { | 
| Douglas Gregor | 1734317 | 2009-04-01 00:28:59 +0000 | [diff] [blame] | 224 |   if (getPrefix()) | 
| Douglas Gregor | d249e1d1f | 2009-05-29 20:38:28 +0000 | [diff] [blame] | 225 |     getPrefix()->print(OS, Policy); | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 226 |  | 
 | 227 |   switch (getKind()) { | 
 | 228 |   case Identifier: | 
 | 229 |     OS << getAsIdentifier()->getName(); | 
 | 230 |     break; | 
 | 231 |  | 
 | 232 |   case Namespace: | 
| Douglas Gregor | 25270b6 | 2011-11-03 00:16:13 +0000 | [diff] [blame] | 233 |     if (getAsNamespace()->isAnonymousNamespace()) | 
 | 234 |       return; | 
 | 235 |        | 
| Douglas Gregor | 14aba76 | 2011-02-24 02:36:08 +0000 | [diff] [blame] | 236 |     OS << getAsNamespace()->getName(); | 
 | 237 |     break; | 
 | 238 |  | 
 | 239 |   case NamespaceAlias: | 
 | 240 |     OS << getAsNamespaceAlias()->getName(); | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 241 |     break; | 
 | 242 |  | 
 | 243 |   case Global: | 
 | 244 |     break; | 
 | 245 |  | 
 | 246 |   case TypeSpecWithTemplate: | 
 | 247 |     OS << "template "; | 
 | 248 |     // Fall through to print the type. | 
 | 249 |  | 
 | 250 |   case TypeSpec: { | 
 | 251 |     std::string TypeStr; | 
| John McCall | f4c7371 | 2011-01-19 06:33:43 +0000 | [diff] [blame] | 252 |     const Type *T = getAsType(); | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 253 |  | 
| Douglas Gregor | d249e1d1f | 2009-05-29 20:38:28 +0000 | [diff] [blame] | 254 |     PrintingPolicy InnerPolicy(Policy); | 
| John McCall | 2191b20 | 2009-09-05 06:31:47 +0000 | [diff] [blame] | 255 |     InnerPolicy.SuppressScope = true; | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 256 |  | 
| Douglas Gregor | dacd434 | 2009-08-26 00:04:55 +0000 | [diff] [blame] | 257 |     // Nested-name-specifiers are intended to contain minimally-qualified | 
| Abramo Bagnara | 465d41b | 2010-05-11 21:36:43 +0000 | [diff] [blame] | 258 |     // types. An actual ElaboratedType will not occur, since we'll store | 
| Douglas Gregor | dacd434 | 2009-08-26 00:04:55 +0000 | [diff] [blame] | 259 |     // just the type that is referred to in the nested-name-specifier (e.g., | 
 | 260 |     // a TypedefType, TagType, etc.). However, when we are dealing with | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 261 |     // dependent template-id types (e.g., Outer<T>::template Inner<U>), | 
| Douglas Gregor | dacd434 | 2009-08-26 00:04:55 +0000 | [diff] [blame] | 262 |     // the type requires its own nested-name-specifier for uniqueness, so we | 
 | 263 |     // suppress that nested-name-specifier during printing. | 
| Abramo Bagnara | 465d41b | 2010-05-11 21:36:43 +0000 | [diff] [blame] | 264 |     assert(!isa<ElaboratedType>(T) && | 
 | 265 |            "Elaborated type in nested-name-specifier"); | 
| Douglas Gregor | dacd434 | 2009-08-26 00:04:55 +0000 | [diff] [blame] | 266 |     if (const TemplateSpecializationType *SpecType | 
 | 267 |           = dyn_cast<TemplateSpecializationType>(T)) { | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 268 |       // Print the template name without its corresponding | 
| Douglas Gregor | dacd434 | 2009-08-26 00:04:55 +0000 | [diff] [blame] | 269 |       // nested-name-specifier. | 
 | 270 |       SpecType->getTemplateName().print(OS, InnerPolicy, true); | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 271 |  | 
| Douglas Gregor | dacd434 | 2009-08-26 00:04:55 +0000 | [diff] [blame] | 272 |       // Print the template argument list. | 
 | 273 |       TypeStr = TemplateSpecializationType::PrintTemplateArgumentList( | 
| Mike Stump | 1eb4433 | 2009-09-09 15:08:12 +0000 | [diff] [blame] | 274 |                                                           SpecType->getArgs(), | 
 | 275 |                                                        SpecType->getNumArgs(), | 
| Douglas Gregor | dacd434 | 2009-08-26 00:04:55 +0000 | [diff] [blame] | 276 |                                                                  InnerPolicy); | 
 | 277 |     } else { | 
 | 278 |       // Print the type normally | 
| Douglas Gregor | fee8a3c | 2009-11-10 00:39:07 +0000 | [diff] [blame] | 279 |       TypeStr = QualType(T, 0).getAsString(InnerPolicy); | 
| Douglas Gregor | dacd434 | 2009-08-26 00:04:55 +0000 | [diff] [blame] | 280 |     } | 
| Douglas Gregor | ab452ba | 2009-03-26 23:50:42 +0000 | [diff] [blame] | 281 |     OS << TypeStr; | 
 | 282 |     break; | 
 | 283 |   } | 
 | 284 |   } | 
 | 285 |  | 
 | 286 |   OS << "::"; | 
 | 287 | } | 
 | 288 |  | 
| Chris Lattner | e4f2142 | 2009-06-30 01:26:17 +0000 | [diff] [blame] | 289 | void NestedNameSpecifier::dump(const LangOptions &LO) { | 
 | 290 |   print(llvm::errs(), PrintingPolicy(LO)); | 
| Douglas Gregor | d57959a | 2009-03-27 23:10:48 +0000 | [diff] [blame] | 291 | } | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 292 |  | 
 | 293 | unsigned  | 
 | 294 | NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) { | 
 | 295 |   assert(Qualifier && "Expected a non-NULL qualifier"); | 
 | 296 |  | 
 | 297 |   // Location of the trailing '::'. | 
 | 298 |   unsigned Length = sizeof(unsigned); | 
 | 299 |  | 
 | 300 |   switch (Qualifier->getKind()) { | 
 | 301 |   case NestedNameSpecifier::Global: | 
 | 302 |     // Nothing more to add. | 
 | 303 |     break; | 
 | 304 |  | 
 | 305 |   case NestedNameSpecifier::Identifier: | 
 | 306 |   case NestedNameSpecifier::Namespace: | 
 | 307 |   case NestedNameSpecifier::NamespaceAlias: | 
 | 308 |     // The location of the identifier or namespace name. | 
 | 309 |     Length += sizeof(unsigned); | 
 | 310 |     break; | 
 | 311 |  | 
 | 312 |   case NestedNameSpecifier::TypeSpecWithTemplate: | 
 | 313 |   case NestedNameSpecifier::TypeSpec: | 
 | 314 |     // The "void*" that points at the TypeLoc data. | 
 | 315 |     // Note: the 'template' keyword is part of the TypeLoc. | 
 | 316 |     Length += sizeof(void *); | 
 | 317 |     break; | 
 | 318 |   } | 
 | 319 |  | 
 | 320 |   return Length; | 
 | 321 | } | 
 | 322 |  | 
 | 323 | unsigned  | 
 | 324 | NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) { | 
 | 325 |   unsigned Length = 0; | 
 | 326 |   for (; Qualifier; Qualifier = Qualifier->getPrefix()) | 
 | 327 |     Length += getLocalDataLength(Qualifier); | 
 | 328 |   return Length; | 
 | 329 | } | 
 | 330 |  | 
 | 331 | namespace { | 
 | 332 |   /// \brief Load a (possibly unaligned) source location from a given address | 
 | 333 |   /// and offset. | 
 | 334 |   SourceLocation LoadSourceLocation(void *Data, unsigned Offset) { | 
 | 335 |     unsigned Raw; | 
 | 336 |     memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned)); | 
 | 337 |     return SourceLocation::getFromRawEncoding(Raw); | 
 | 338 |   } | 
 | 339 |    | 
 | 340 |   /// \brief Load a (possibly unaligned) pointer from a given address and | 
 | 341 |   /// offset. | 
 | 342 |   void *LoadPointer(void *Data, unsigned Offset) { | 
 | 343 |     void *Result; | 
 | 344 |     memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*)); | 
 | 345 |     return Result; | 
 | 346 |   } | 
 | 347 | } | 
 | 348 |  | 
| Douglas Gregor | dc35571 | 2011-02-25 00:36:19 +0000 | [diff] [blame] | 349 | SourceRange NestedNameSpecifierLoc::getSourceRange() const { | 
| Douglas Gregor | db99241 | 2011-02-25 16:33:46 +0000 | [diff] [blame] | 350 |   if (!Qualifier) | 
 | 351 |     return SourceRange(); | 
 | 352 |    | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 353 |   NestedNameSpecifierLoc First = *this; | 
| Douglas Gregor | db99241 | 2011-02-25 16:33:46 +0000 | [diff] [blame] | 354 |   while (NestedNameSpecifierLoc Prefix = First.getPrefix()) | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 355 |     First = Prefix; | 
 | 356 |    | 
 | 357 |   return SourceRange(First.getLocalSourceRange().getBegin(),  | 
 | 358 |                      getLocalSourceRange().getEnd()); | 
 | 359 | } | 
 | 360 |  | 
| Douglas Gregor | dc35571 | 2011-02-25 00:36:19 +0000 | [diff] [blame] | 361 | SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const { | 
| Douglas Gregor | db99241 | 2011-02-25 16:33:46 +0000 | [diff] [blame] | 362 |   if (!Qualifier) | 
 | 363 |     return SourceRange(); | 
 | 364 |    | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 365 |   unsigned Offset = getDataLength(Qualifier->getPrefix()); | 
 | 366 |   switch (Qualifier->getKind()) { | 
 | 367 |   case NestedNameSpecifier::Global: | 
 | 368 |     return LoadSourceLocation(Data, Offset); | 
 | 369 |  | 
 | 370 |   case NestedNameSpecifier::Identifier: | 
 | 371 |   case NestedNameSpecifier::Namespace: | 
 | 372 |   case NestedNameSpecifier::NamespaceAlias: | 
 | 373 |     return SourceRange(LoadSourceLocation(Data, Offset), | 
 | 374 |                        LoadSourceLocation(Data, Offset + sizeof(unsigned))); | 
 | 375 |  | 
 | 376 |   case NestedNameSpecifier::TypeSpecWithTemplate: | 
 | 377 |   case NestedNameSpecifier::TypeSpec: { | 
 | 378 |     // The "void*" that points at the TypeLoc data. | 
 | 379 |     // Note: the 'template' keyword is part of the TypeLoc. | 
 | 380 |     void *TypeData = LoadPointer(Data, Offset); | 
 | 381 |     TypeLoc TL(Qualifier->getAsType(), TypeData); | 
 | 382 |     return SourceRange(TL.getBeginLoc(), | 
 | 383 |                        LoadSourceLocation(Data, Offset + sizeof(void*))); | 
 | 384 |   } | 
 | 385 |   } | 
| David Blaikie | 3026348 | 2012-01-20 21:50:17 +0000 | [diff] [blame] | 386 |  | 
 | 387 |   llvm_unreachable("Invalid NNS Kind!"); | 
| Douglas Gregor | c34348a | 2011-02-24 17:54:50 +0000 | [diff] [blame] | 388 | } | 
| Douglas Gregor | dc35571 | 2011-02-25 00:36:19 +0000 | [diff] [blame] | 389 |  | 
 | 390 | TypeLoc NestedNameSpecifierLoc::getTypeLoc() const { | 
 | 391 |   assert((Qualifier->getKind() == NestedNameSpecifier::TypeSpec || | 
 | 392 |           Qualifier->getKind() == NestedNameSpecifier::TypeSpecWithTemplate) && | 
 | 393 |          "Nested-name-specifier location is not a type"); | 
 | 394 |  | 
 | 395 |   // The "void*" that points at the TypeLoc data. | 
 | 396 |   unsigned Offset = getDataLength(Qualifier->getPrefix()); | 
 | 397 |   void *TypeData = LoadPointer(Data, Offset); | 
 | 398 |   return TypeLoc(Qualifier->getAsType(), TypeData); | 
 | 399 | } | 
| Douglas Gregor | 5f791bb | 2011-02-28 23:58:31 +0000 | [diff] [blame] | 400 |  | 
 | 401 | namespace { | 
 | 402 |   void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, | 
 | 403 |               unsigned &BufferCapacity) { | 
 | 404 |     if (BufferSize + (End - Start) > BufferCapacity) { | 
 | 405 |       // Reallocate the buffer. | 
 | 406 |       unsigned NewCapacity  | 
 | 407 |       = std::max((unsigned)(BufferCapacity? BufferCapacity * 2  | 
 | 408 |                             : sizeof(void*) * 2), | 
 | 409 |                  (unsigned)(BufferSize + (End - Start))); | 
 | 410 |       char *NewBuffer = static_cast<char *>(malloc(NewCapacity)); | 
 | 411 |       memcpy(NewBuffer, Buffer, BufferSize); | 
 | 412 |        | 
 | 413 |       if (BufferCapacity) | 
 | 414 |         free(Buffer); | 
 | 415 |       Buffer = NewBuffer; | 
 | 416 |       BufferCapacity = NewCapacity; | 
 | 417 |     } | 
 | 418 |      | 
 | 419 |     memcpy(Buffer + BufferSize, Start, End - Start); | 
 | 420 |     BufferSize += End-Start; | 
 | 421 |   } | 
 | 422 |    | 
 | 423 |   /// \brief Save a source location to the given buffer. | 
 | 424 |   void SaveSourceLocation(SourceLocation Loc, char *&Buffer, | 
 | 425 |                           unsigned &BufferSize, unsigned &BufferCapacity) { | 
 | 426 |     unsigned Raw = Loc.getRawEncoding(); | 
 | 427 |     Append(reinterpret_cast<char *>(&Raw), | 
 | 428 |            reinterpret_cast<char *>(&Raw) + sizeof(unsigned), | 
 | 429 |            Buffer, BufferSize, BufferCapacity); | 
 | 430 |   } | 
 | 431 |    | 
 | 432 |   /// \brief Save a pointer to the given buffer. | 
 | 433 |   void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize, | 
 | 434 |                    unsigned &BufferCapacity) { | 
 | 435 |     Append(reinterpret_cast<char *>(&Ptr), | 
 | 436 |            reinterpret_cast<char *>(&Ptr) + sizeof(void *), | 
 | 437 |            Buffer, BufferSize, BufferCapacity); | 
 | 438 |   } | 
 | 439 | } | 
 | 440 |  | 
| Douglas Gregor | 5f791bb | 2011-02-28 23:58:31 +0000 | [diff] [blame] | 441 | NestedNameSpecifierLocBuilder:: | 
 | 442 | NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other)  | 
 | 443 |   : Representation(Other.Representation), Buffer(0), | 
 | 444 |     BufferSize(0), BufferCapacity(0) | 
 | 445 | { | 
 | 446 |   if (!Other.Buffer) | 
 | 447 |     return; | 
 | 448 |    | 
 | 449 |   if (Other.BufferCapacity == 0) { | 
 | 450 |     // Shallow copy is okay. | 
 | 451 |     Buffer = Other.Buffer; | 
 | 452 |     BufferSize = Other.BufferSize; | 
 | 453 |     return; | 
 | 454 |   } | 
 | 455 |    | 
 | 456 |   // Deep copy | 
 | 457 |   BufferSize = Other.BufferSize; | 
 | 458 |   BufferCapacity = Other.BufferSize; | 
 | 459 |   Buffer = static_cast<char *>(malloc(BufferCapacity)); | 
 | 460 |   memcpy(Buffer, Other.Buffer, BufferSize); | 
 | 461 | } | 
 | 462 |  | 
 | 463 | NestedNameSpecifierLocBuilder & | 
 | 464 | NestedNameSpecifierLocBuilder:: | 
 | 465 | operator=(const NestedNameSpecifierLocBuilder &Other) { | 
 | 466 |   Representation = Other.Representation; | 
 | 467 |    | 
 | 468 |   if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) { | 
 | 469 |     // Re-use our storage. | 
 | 470 |     BufferSize = Other.BufferSize; | 
 | 471 |     memcpy(Buffer, Other.Buffer, BufferSize); | 
 | 472 |     return *this; | 
 | 473 |   } | 
 | 474 |    | 
 | 475 |   // Free our storage, if we have any. | 
 | 476 |   if (BufferCapacity) { | 
 | 477 |     free(Buffer); | 
 | 478 |     BufferCapacity = 0; | 
 | 479 |   } | 
 | 480 |    | 
 | 481 |   if (!Other.Buffer) { | 
 | 482 |     // Empty. | 
 | 483 |     Buffer = 0; | 
 | 484 |     BufferSize = 0; | 
 | 485 |     return *this; | 
 | 486 |   } | 
 | 487 |    | 
 | 488 |   if (Other.BufferCapacity == 0) { | 
 | 489 |     // Shallow copy is okay. | 
 | 490 |     Buffer = Other.Buffer; | 
 | 491 |     BufferSize = Other.BufferSize; | 
 | 492 |     return *this; | 
 | 493 |   } | 
 | 494 |    | 
 | 495 |   // Deep copy. | 
 | 496 |   BufferSize = Other.BufferSize; | 
 | 497 |   BufferCapacity = BufferSize; | 
 | 498 |   Buffer = static_cast<char *>(malloc(BufferSize)); | 
 | 499 |   memcpy(Buffer, Other.Buffer, BufferSize); | 
 | 500 |   return *this; | 
 | 501 | } | 
 | 502 |  | 
| Douglas Gregor | 5f791bb | 2011-02-28 23:58:31 +0000 | [diff] [blame] | 503 | void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,  | 
 | 504 |                                            SourceLocation TemplateKWLoc,  | 
 | 505 |                                            TypeLoc TL,  | 
 | 506 |                                            SourceLocation ColonColonLoc) { | 
 | 507 |   Representation = NestedNameSpecifier::Create(Context, Representation,  | 
 | 508 |                                                TemplateKWLoc.isValid(),  | 
 | 509 |                                                TL.getTypePtr()); | 
 | 510 |    | 
 | 511 |   // Push source-location info into the buffer. | 
 | 512 |   SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity); | 
 | 513 |   SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); | 
 | 514 | } | 
 | 515 |  | 
 | 516 | void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,  | 
 | 517 |                                            IdentifierInfo *Identifier, | 
 | 518 |                                            SourceLocation IdentifierLoc,  | 
 | 519 |                                            SourceLocation ColonColonLoc) { | 
 | 520 |   Representation = NestedNameSpecifier::Create(Context, Representation,  | 
 | 521 |                                                Identifier); | 
 | 522 |    | 
 | 523 |   // Push source-location info into the buffer. | 
 | 524 |   SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity); | 
 | 525 |   SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); | 
 | 526 | } | 
 | 527 |  | 
 | 528 | void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,  | 
 | 529 |                                            NamespaceDecl *Namespace, | 
 | 530 |                                            SourceLocation NamespaceLoc,  | 
 | 531 |                                            SourceLocation ColonColonLoc) { | 
 | 532 |   Representation = NestedNameSpecifier::Create(Context, Representation,  | 
 | 533 |                                                Namespace); | 
 | 534 |    | 
 | 535 |   // Push source-location info into the buffer. | 
 | 536 |   SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity); | 
 | 537 |   SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); | 
 | 538 | } | 
 | 539 |  | 
 | 540 | void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, | 
 | 541 |                                            NamespaceAliasDecl *Alias, | 
 | 542 |                                            SourceLocation AliasLoc,  | 
 | 543 |                                            SourceLocation ColonColonLoc) { | 
 | 544 |   Representation = NestedNameSpecifier::Create(Context, Representation, Alias); | 
 | 545 |    | 
 | 546 |   // Push source-location info into the buffer. | 
 | 547 |   SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity); | 
 | 548 |   SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); | 
 | 549 | } | 
 | 550 |  | 
 | 551 | void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context,  | 
 | 552 |                                                SourceLocation ColonColonLoc) { | 
 | 553 |   assert(!Representation && "Already have a nested-name-specifier!?"); | 
 | 554 |   Representation = NestedNameSpecifier::GlobalSpecifier(Context); | 
 | 555 |    | 
 | 556 |   // Push source-location info into the buffer. | 
 | 557 |   SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); | 
 | 558 | } | 
 | 559 |  | 
 | 560 | void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,  | 
 | 561 |                                                 NestedNameSpecifier *Qualifier,  | 
 | 562 |                                                 SourceRange R) { | 
 | 563 |   Representation = Qualifier; | 
 | 564 |    | 
 | 565 |   // Construct bogus (but well-formed) source information for the  | 
 | 566 |   // nested-name-specifier. | 
 | 567 |   BufferSize = 0; | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 568 |   SmallVector<NestedNameSpecifier *, 4> Stack; | 
| Douglas Gregor | 5f791bb | 2011-02-28 23:58:31 +0000 | [diff] [blame] | 569 |   for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix()) | 
 | 570 |     Stack.push_back(NNS); | 
 | 571 |   while (!Stack.empty()) { | 
 | 572 |     NestedNameSpecifier *NNS = Stack.back(); | 
 | 573 |     Stack.pop_back(); | 
 | 574 |     switch (NNS->getKind()) { | 
 | 575 |       case NestedNameSpecifier::Identifier: | 
 | 576 |       case NestedNameSpecifier::Namespace: | 
 | 577 |       case NestedNameSpecifier::NamespaceAlias: | 
 | 578 |         SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity); | 
 | 579 |         break; | 
 | 580 |          | 
 | 581 |       case NestedNameSpecifier::TypeSpec: | 
 | 582 |       case NestedNameSpecifier::TypeSpecWithTemplate: { | 
 | 583 |         TypeSourceInfo *TSInfo | 
 | 584 |         = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0), | 
 | 585 |                                            R.getBegin()); | 
 | 586 |         SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,  | 
 | 587 |                     BufferCapacity); | 
 | 588 |         break; | 
 | 589 |       } | 
 | 590 |          | 
 | 591 |       case NestedNameSpecifier::Global: | 
 | 592 |         break; | 
 | 593 |     } | 
 | 594 |      | 
 | 595 |     // Save the location of the '::'. | 
 | 596 |     SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(),  | 
 | 597 |                        Buffer, BufferSize, BufferCapacity); | 
 | 598 |   } | 
 | 599 | } | 
 | 600 |  | 
 | 601 | void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) { | 
 | 602 |   if (BufferCapacity) | 
 | 603 |     free(Buffer); | 
 | 604 |  | 
 | 605 |   if (!Other) { | 
 | 606 |     Representation = 0; | 
 | 607 |     BufferSize = 0; | 
 | 608 |     return; | 
 | 609 |   } | 
 | 610 |    | 
 | 611 |   // Rather than copying the data (which is wasteful), "adopt" the  | 
 | 612 |   // pointer (which points into the ASTContext) but set the capacity to zero to | 
 | 613 |   // indicate that we don't own it. | 
 | 614 |   Representation = Other.getNestedNameSpecifier(); | 
 | 615 |   Buffer = static_cast<char *>(Other.getOpaqueData()); | 
 | 616 |   BufferSize = Other.getDataLength(); | 
 | 617 |   BufferCapacity = 0; | 
 | 618 | } | 
 | 619 |  | 
 | 620 | NestedNameSpecifierLoc  | 
 | 621 | NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const { | 
 | 622 |   if (!Representation) | 
 | 623 |     return NestedNameSpecifierLoc(); | 
 | 624 |    | 
 | 625 |   // If we adopted our data pointer from elsewhere in the AST context, there's | 
 | 626 |   // no need to copy the memory. | 
 | 627 |   if (BufferCapacity == 0) | 
 | 628 |     return NestedNameSpecifierLoc(Representation, Buffer); | 
 | 629 |    | 
 | 630 |   // FIXME: After copying the source-location information, should we free | 
 | 631 |   // our (temporary) buffer and adopt the ASTContext-allocated memory? | 
 | 632 |   // Doing so would optimize repeated calls to getWithLocInContext(). | 
 | 633 |   void *Mem = Context.Allocate(BufferSize, llvm::alignOf<void *>()); | 
 | 634 |   memcpy(Mem, Buffer, BufferSize); | 
 | 635 |   return NestedNameSpecifierLoc(Representation, Mem); | 
 | 636 | } |