|
12 | 12 |
|
13 | 13 | #include "ClangClassTemplateNamePrinter.h"
|
14 | 14 | #include "ImporterImpl.h"
|
| 15 | +#include "clang/AST/TemplateArgumentVisitor.h" |
15 | 16 | #include "clang/AST/TypeVisitor.h"
|
16 | 17 |
|
17 | 18 | using namespace swift;
|
@@ -150,41 +151,106 @@ struct TemplateInstantiationNamePrinter
|
150 | 151 | }
|
151 | 152 | };
|
152 | 153 |
|
| 154 | +struct TemplateArgumentPrinter |
| 155 | + : clang::ConstTemplateArgumentVisitor<TemplateArgumentPrinter, void, |
| 156 | + llvm::raw_svector_ostream &> { |
| 157 | + TemplateInstantiationNamePrinter typePrinter; |
| 158 | + |
| 159 | + TemplateArgumentPrinter(ASTContext &swiftCtx, NameImporter *nameImporter, |
| 160 | + ImportNameVersion version) |
| 161 | + : typePrinter(swiftCtx, nameImporter, version) {} |
| 162 | + |
| 163 | + void VisitTemplateArgument(const clang::TemplateArgument &arg, |
| 164 | + llvm::raw_svector_ostream &buffer) { |
| 165 | + // Print "_" as a fallback if we couldn't emit a more meaningful type name. |
| 166 | + buffer << "_"; |
| 167 | + } |
| 168 | + |
| 169 | + void VisitTypeTemplateArgument(const clang::TemplateArgument &arg, |
| 170 | + llvm::raw_svector_ostream &buffer) { |
| 171 | + auto ty = arg.getAsType(); |
| 172 | + buffer << typePrinter.Visit(ty.getTypePtr()); |
| 173 | + if (ty.isConstQualified()) { |
| 174 | + buffer << "_const"; |
| 175 | + } |
| 176 | + } |
| 177 | + |
| 178 | + void VisitIntegralTemplateArgument(const clang::TemplateArgument &arg, |
| 179 | + llvm::raw_svector_ostream &buffer) { |
| 180 | + buffer << "_"; |
| 181 | + if (arg.getIntegralType()->isBuiltinType()) { |
| 182 | + buffer << typePrinter.Visit(arg.getIntegralType().getTypePtr()) << "_"; |
| 183 | + } |
| 184 | + arg.getAsIntegral().print(buffer, true); |
| 185 | + } |
| 186 | + |
| 187 | + void VisitPackTemplateArgument(const clang::TemplateArgument &arg, |
| 188 | + llvm::raw_svector_ostream &buffer) { |
| 189 | + VisitTemplateArgumentArray(arg.getPackAsArray(), buffer); |
| 190 | + } |
| 191 | + |
| 192 | + void VisitTemplateArgumentArray(ArrayRef<clang::TemplateArgument> args, |
| 193 | + llvm::raw_svector_ostream &buffer) { |
| 194 | + bool needsComma = false; |
| 195 | + for (auto &arg : args) { |
| 196 | + // Do not try to print empty packs. |
| 197 | + if (arg.getKind() == clang::TemplateArgument::ArgKind::Pack && |
| 198 | + arg.getPackAsArray().empty()) |
| 199 | + continue; |
| 200 | + |
| 201 | + if (needsComma) |
| 202 | + buffer << ", "; |
| 203 | + Visit(arg, buffer); |
| 204 | + needsComma = true; |
| 205 | + } |
| 206 | + } |
| 207 | + |
| 208 | + // Unfortunately, clang::templateargumentvisitor::Base does not correctly |
| 209 | + // perform static dispatch for methods that aren't overloaded, so we have to |
| 210 | + // overload all of them here. |
| 211 | + |
| 212 | + void VisitNullArgument(const clang::TemplateArgument &arg, |
| 213 | + llvm::raw_svector_ostream &buffer) { |
| 214 | + VisitTemplateArgument(arg, buffer); |
| 215 | + } |
| 216 | + void VisitDeclarationArgument(const clang::TemplateArgument &arg, |
| 217 | + llvm::raw_svector_ostream &buffer) { |
| 218 | + VisitTemplateArgument(arg, buffer); |
| 219 | + } |
| 220 | + void VisitNullPtrArgument(const clang::TemplateArgument &arg, |
| 221 | + llvm::raw_svector_ostream &buffer) { |
| 222 | + VisitTemplateArgument(arg, buffer); |
| 223 | + } |
| 224 | + void VisitStructuralValueArgument(const clang::TemplateArgument &arg, |
| 225 | + llvm::raw_svector_ostream &buffer) { |
| 226 | + VisitTemplateArgument(arg, buffer); |
| 227 | + } |
| 228 | + void VisitTemplateTemplateArgument(const clang::TemplateArgument &arg, |
| 229 | + llvm::raw_svector_ostream &buffer) { |
| 230 | + VisitTemplateArgument(arg, buffer); |
| 231 | + } |
| 232 | + void |
| 233 | + VisitTemplateExpansionTemplateArgument(const clang::TemplateArgument &arg, |
| 234 | + llvm::raw_svector_ostream &buffer) { |
| 235 | + VisitTemplateArgument(arg, buffer); |
| 236 | + } |
| 237 | + void VisitExpressionTemplateArgument(const clang::TemplateArgument &arg, |
| 238 | + llvm::raw_svector_ostream &buffer) { |
| 239 | + VisitTemplateArgument(arg, buffer); |
| 240 | + } |
| 241 | +}; |
| 242 | + |
153 | 243 | std::string swift::importer::printClassTemplateSpecializationName(
|
154 | 244 | const clang::ClassTemplateSpecializationDecl *decl, ASTContext &swiftCtx,
|
155 | 245 | NameImporter *nameImporter, ImportNameVersion version) {
|
156 |
| - TemplateInstantiationNamePrinter templateNamePrinter(swiftCtx, nameImporter, |
157 |
| - version); |
| 246 | + TemplateArgumentPrinter templateArgPrinter(swiftCtx, nameImporter, version); |
158 | 247 |
|
159 |
| - // TODO: the following logic should probably be a ConstTemplateArgumentVisitor |
160 | 248 | llvm::SmallString<128> storage;
|
161 | 249 | llvm::raw_svector_ostream buffer(storage);
|
162 | 250 | decl->printName(buffer);
|
163 | 251 | buffer << "<";
|
164 |
| - llvm::interleaveComma( |
165 |
| - decl->getTemplateArgs().asArray(), buffer, |
166 |
| - [&buffer, &templateNamePrinter](const clang::TemplateArgument &arg) { |
167 |
| - // Use import name here so builtin types such as "int" map to their |
168 |
| - // Swift equivalent ("CInt"). |
169 |
| - if (arg.getKind() == clang::TemplateArgument::Type) { |
170 |
| - auto ty = arg.getAsType(); |
171 |
| - buffer << templateNamePrinter.Visit(ty.getTypePtr()); |
172 |
| - if (ty.isConstQualified()) { |
173 |
| - buffer << "_const"; |
174 |
| - } |
175 |
| - return; |
176 |
| - } else if (arg.getKind() == clang::TemplateArgument::Integral) { |
177 |
| - buffer << "_"; |
178 |
| - if (arg.getIntegralType()->isBuiltinType()) { |
179 |
| - buffer << templateNamePrinter.Visit( |
180 |
| - arg.getIntegralType().getTypePtr()) |
181 |
| - << "_"; |
182 |
| - } |
183 |
| - arg.getAsIntegral().print(buffer, true); |
184 |
| - return; |
185 |
| - } |
186 |
| - buffer << "_"; |
187 |
| - }); |
| 252 | + templateArgPrinter.VisitTemplateArgumentArray( |
| 253 | + decl->getTemplateArgs().asArray(), buffer); |
188 | 254 | buffer << ">";
|
189 | 255 | return buffer.str().str();
|
190 | 256 | }
|
0 commit comments