|
|
|
@ -17,6 +17,7 @@
@@ -17,6 +17,7 @@
|
|
|
|
|
#include <stdlib.h> |
|
|
|
|
|
|
|
|
|
#include <llvm/TargetParser/Host.h> |
|
|
|
|
#include <llvm/Support/ManagedStatic.h> |
|
|
|
|
#include <llvm/Support/Path.h> |
|
|
|
|
#include <llvm/Support/raw_ostream.h> |
|
|
|
|
#include <llvm/Support/TargetSelect.h> |
|
|
|
@ -36,6 +37,7 @@
@@ -36,6 +37,7 @@
|
|
|
|
|
#include <clang/AST/Comment.h> |
|
|
|
|
#include <clang/AST/DeclFriend.h> |
|
|
|
|
#include <clang/AST/ExprCXX.h> |
|
|
|
|
#include "clang/AST/TemplateBase.h" |
|
|
|
|
#include <clang/CodeGen/CodeGenAction.h> |
|
|
|
|
#include <clang/Lex/DirectoryLookup.h> |
|
|
|
|
#include <clang/Lex/HeaderSearch.h> |
|
|
|
@ -1097,15 +1099,15 @@ static TagKind ConvertToTagKind(clang::TagTypeKind AS)
@@ -1097,15 +1099,15 @@ static TagKind ConvertToTagKind(clang::TagTypeKind AS)
|
|
|
|
|
{ |
|
|
|
|
switch (AS) |
|
|
|
|
{ |
|
|
|
|
case clang::TagTypeKind::TTK_Struct: |
|
|
|
|
case clang::TagTypeKind::Struct: |
|
|
|
|
return TagKind::Struct; |
|
|
|
|
case clang::TagTypeKind::TTK_Interface: |
|
|
|
|
case clang::TagTypeKind::Interface: |
|
|
|
|
return TagKind::Interface; |
|
|
|
|
case clang::TagTypeKind::TTK_Union: |
|
|
|
|
case clang::TagTypeKind::Union: |
|
|
|
|
return TagKind::Union; |
|
|
|
|
case clang::TagTypeKind::TTK_Class: |
|
|
|
|
case clang::TagTypeKind::Class: |
|
|
|
|
return TagKind::Class; |
|
|
|
|
case clang::TagTypeKind::TTK_Enum: |
|
|
|
|
case clang::TagTypeKind::Enum: |
|
|
|
|
return TagKind::Enum; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1394,17 +1396,9 @@ Parser::WalkClassTemplateSpecialization(const clang::ClassTemplateSpecialization
@@ -1394,17 +1396,9 @@ Parser::WalkClassTemplateSpecialization(const clang::ClassTemplateSpecialization
|
|
|
|
|
CT->Specializations.push_back(TS); |
|
|
|
|
|
|
|
|
|
auto& TAL = CTS->getTemplateArgs(); |
|
|
|
|
auto TSI = CTS->getTypeAsWritten(); |
|
|
|
|
if (TSI) |
|
|
|
|
{ |
|
|
|
|
auto TL = TSI->getTypeLoc(); |
|
|
|
|
auto TSL = TL.getAs<TemplateSpecializationTypeLoc>(); |
|
|
|
|
TS->Arguments = WalkTemplateArgumentList(&TAL, &TSL); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
TS->Arguments = WalkTemplateArgumentList(&TAL, (TemplateSpecializationTypeLoc*)0); |
|
|
|
|
} |
|
|
|
|
TemplateSpecializationTypeLoc TSL; |
|
|
|
|
|
|
|
|
|
TS->Arguments = WalkTemplateArgumentList(&TAL, nullptr); |
|
|
|
|
|
|
|
|
|
if (CTS->isCompleteDefinition()) |
|
|
|
|
{ |
|
|
|
@ -1448,13 +1442,8 @@ Parser::WalkClassTemplatePartialSpecialization(const clang::ClassTemplatePartial
@@ -1448,13 +1442,8 @@ Parser::WalkClassTemplatePartialSpecialization(const clang::ClassTemplatePartial
|
|
|
|
|
TS->specializationKind = WalkTemplateSpecializationKind(CTS->getSpecializationKind()); |
|
|
|
|
CT->Specializations.push_back(TS); |
|
|
|
|
|
|
|
|
|
auto& TAL = CTS->getTemplateArgs(); |
|
|
|
|
if (auto TSI = CTS->getTypeAsWritten()) |
|
|
|
|
{ |
|
|
|
|
auto TL = TSI->getTypeLoc(); |
|
|
|
|
auto TSL = TL.getAs<TemplateSpecializationTypeLoc>(); |
|
|
|
|
TS->Arguments = WalkTemplateArgumentList(&TAL, &TSL); |
|
|
|
|
} |
|
|
|
|
const TemplateArgumentList& TAL = CTS->getTemplateArgs(); |
|
|
|
|
WalkTemplateArgumentList(&TAL, nullptr); |
|
|
|
|
|
|
|
|
|
if (CTS->isCompleteDefinition()) |
|
|
|
|
{ |
|
|
|
@ -1567,7 +1556,11 @@ TypeTemplateParameter* Parser::WalkTypeTemplateParameter(const clang::TemplateTy
@@ -1567,7 +1556,11 @@ TypeTemplateParameter* Parser::WalkTypeTemplateParameter(const clang::TemplateTy
|
|
|
|
|
|
|
|
|
|
HandleDeclaration(TTPD, TP); |
|
|
|
|
if (TTPD->hasDefaultArgument()) |
|
|
|
|
TP->defaultArgument = GetQualifiedType(TTPD->getDefaultArgument()); |
|
|
|
|
{ |
|
|
|
|
auto TSI = TTPD->getDefaultArgument().getTypeSourceInfo(); |
|
|
|
|
if (TSI) |
|
|
|
|
TP->defaultArgument = GetQualifiedType(TSI->getType()); |
|
|
|
|
} |
|
|
|
|
TP->depth = TTPD->getDepth(); |
|
|
|
|
TP->index = TTPD->getIndex(); |
|
|
|
|
TP->isParameterPack = TTPD->isParameterPack(); |
|
|
|
@ -1591,7 +1584,7 @@ NonTypeTemplateParameter* Parser::WalkNonTypeTemplateParameter(const clang::NonT
@@ -1591,7 +1584,7 @@ NonTypeTemplateParameter* Parser::WalkNonTypeTemplateParameter(const clang::NonT
|
|
|
|
|
|
|
|
|
|
HandleDeclaration(NTTPD, NTP); |
|
|
|
|
if (NTTPD->hasDefaultArgument()) |
|
|
|
|
NTP->defaultArgument = WalkExpressionObsolete(NTTPD->getDefaultArgument()); |
|
|
|
|
NTP->defaultArgument = WalkExpressionObsolete(NTTPD->getDefaultArgument().getSourceExpression()); |
|
|
|
|
NTP->type = GetQualifiedType(NTTPD->getType()); |
|
|
|
|
NTP->depth = NTTPD->getDepth(); |
|
|
|
|
NTP->index = NTTPD->getIndex(); |
|
|
|
@ -1641,6 +1634,39 @@ std::vector<TemplateArgument> Parser::WalkTemplateArgumentList(const clang::Temp
@@ -1641,6 +1634,39 @@ std::vector<TemplateArgument> Parser::WalkTemplateArgumentList(const clang::Temp
|
|
|
|
|
|
|
|
|
|
//-----------------------------------//
|
|
|
|
|
|
|
|
|
|
template <typename TypeLoc> |
|
|
|
|
std::vector<TemplateArgument> Parser::WalkTemplateArgumentList( |
|
|
|
|
llvm::ArrayRef<clang::TemplateArgument> TAL, TypeLoc* TSTL) |
|
|
|
|
{ |
|
|
|
|
using namespace clang; |
|
|
|
|
|
|
|
|
|
const bool LocValid = TSTL && !TSTL->isNull() && TSTL->getTypePtr(); |
|
|
|
|
|
|
|
|
|
std::vector<AST::TemplateArgument> params; |
|
|
|
|
const size_t typeLocNumArgs = LocValid ? TSTL->getNumArgs() : 0; |
|
|
|
|
|
|
|
|
|
for (size_t i = 0, e = TAL.size(); i < e; ++i) |
|
|
|
|
{ |
|
|
|
|
const clang::TemplateArgument& TA = TAL[i]; |
|
|
|
|
|
|
|
|
|
TemplateArgumentLoc TArgLoc; |
|
|
|
|
TemplateArgumentLoc* ArgLoc = nullptr; |
|
|
|
|
|
|
|
|
|
if (i < typeLocNumArgs && e == typeLocNumArgs) |
|
|
|
|
{ |
|
|
|
|
TArgLoc = TSTL->getArgLoc(i); |
|
|
|
|
ArgLoc = &TArgLoc; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
auto Arg = WalkTemplateArgument(TA, ArgLoc); |
|
|
|
|
params.push_back(Arg); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return params; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//-----------------------------------//
|
|
|
|
|
|
|
|
|
|
std::vector<TemplateArgument> |
|
|
|
|
Parser::WalkTemplateArgumentList(const clang::TemplateArgumentList* TAL, |
|
|
|
|
const clang::ASTTemplateArgumentListInfo* TALI) |
|
|
|
@ -1893,7 +1919,7 @@ Parser::WalkVarTemplateSpecialization(const clang::VarTemplateSpecializationDecl
@@ -1893,7 +1919,7 @@ Parser::WalkVarTemplateSpecialization(const clang::VarTemplateSpecializationDecl
|
|
|
|
|
VT->Specializations.push_back(TS); |
|
|
|
|
|
|
|
|
|
auto& TAL = VTS->getTemplateArgs(); |
|
|
|
|
auto TSI = VTS->getTypeAsWritten(); |
|
|
|
|
auto TSI = VTS->getTypeSourceInfo(); |
|
|
|
|
if (TSI) |
|
|
|
|
{ |
|
|
|
|
auto TL = TSI->getTypeLoc(); |
|
|
|
@ -1933,7 +1959,7 @@ Parser::WalkVarTemplatePartialSpecialization(const clang::VarTemplatePartialSpec
@@ -1933,7 +1959,7 @@ Parser::WalkVarTemplatePartialSpecialization(const clang::VarTemplatePartialSpec
|
|
|
|
|
VT->Specializations.push_back(TS); |
|
|
|
|
|
|
|
|
|
auto& TAL = VTS->getTemplateArgs(); |
|
|
|
|
if (auto TSI = VTS->getTypeAsWritten()) |
|
|
|
|
if (auto TSI = VTS->getTypeSourceInfo()) |
|
|
|
|
{ |
|
|
|
|
auto TL = TSI->getTypeLoc(); |
|
|
|
|
auto TSL = TL.getAs<TemplateSpecializationTypeLoc>(); |
|
|
|
@ -2812,11 +2838,9 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL, bool
@@ -2812,11 +2838,9 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL, bool
|
|
|
|
|
if (TS->isSugared()) |
|
|
|
|
TST->desugared = GetQualifiedType(TS->getCanonicalTypeInternal(), TL); |
|
|
|
|
|
|
|
|
|
TemplateArgumentList TArgs(TemplateArgumentList::OnStack, TS->template_arguments()); |
|
|
|
|
|
|
|
|
|
if (!LocValid) |
|
|
|
|
{ |
|
|
|
|
TST->Arguments = WalkTemplateArgumentList(&TArgs, (TemplateSpecializationTypeLoc*)nullptr); |
|
|
|
|
TST->Arguments = WalkTemplateArgumentList(TS->template_arguments(), (TemplateSpecializationTypeLoc*)nullptr); |
|
|
|
|
Ty = TST; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
@ -2840,21 +2864,21 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL, bool
@@ -2840,21 +2864,21 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL, bool
|
|
|
|
|
case TypeLoc::DependentTemplateSpecialization: |
|
|
|
|
{ |
|
|
|
|
DependentTemplateSpecializationTypeLoc TSpecTL = TL->getAs<DependentTemplateSpecializationTypeLoc>(); |
|
|
|
|
TST->Arguments = WalkTemplateArgumentList(&TArgs, &TSpecTL); |
|
|
|
|
TST->Arguments = WalkTemplateArgumentList(TS->template_arguments(), &TSpecTL); |
|
|
|
|
Ty = TST; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case TypeLoc::TemplateSpecialization: |
|
|
|
|
{ |
|
|
|
|
TemplateSpecializationTypeLoc TSpecTL = TL->getAs<TemplateSpecializationTypeLoc>(); |
|
|
|
|
TST->Arguments = WalkTemplateArgumentList(&TArgs, &TSpecTL); |
|
|
|
|
TST->Arguments = WalkTemplateArgumentList(TS->template_arguments(), &TSpecTL); |
|
|
|
|
Ty = TST; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case TypeLoc::TemplateTypeParm: |
|
|
|
|
{ |
|
|
|
|
TemplateTypeParmTypeLoc TTPTL = TL->getAs<TemplateTypeParmTypeLoc>(); |
|
|
|
|
TST->Arguments = WalkTemplateArgumentList(&TArgs, (TemplateSpecializationTypeLoc*)nullptr); |
|
|
|
|
TST->Arguments = WalkTemplateArgumentList(TS->template_arguments(), (TemplateSpecializationTypeLoc*)nullptr); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
default: |
|
|
|
@ -2873,11 +2897,9 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL, bool
@@ -2873,11 +2897,9 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL, bool
|
|
|
|
|
if (TS->isSugared()) |
|
|
|
|
TST->desugared = GetQualifiedType(TS->getCanonicalTypeInternal(), TL); |
|
|
|
|
|
|
|
|
|
TemplateArgumentList TArgs(TemplateArgumentList::OnStack, TS->template_arguments()); |
|
|
|
|
|
|
|
|
|
if (!LocValid) |
|
|
|
|
{ |
|
|
|
|
TST->Arguments = WalkTemplateArgumentList(&TArgs, (DependentTemplateSpecializationTypeLoc*)nullptr); |
|
|
|
|
TST->Arguments = WalkTemplateArgumentList(TS->template_arguments(), (DependentTemplateSpecializationTypeLoc*)nullptr); |
|
|
|
|
Ty = TST; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
@ -2901,18 +2923,18 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL, bool
@@ -2901,18 +2923,18 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL, bool
|
|
|
|
|
case TypeLoc::DependentTemplateSpecialization: |
|
|
|
|
{ |
|
|
|
|
DependentTemplateSpecializationTypeLoc TSpecTL = TL->getAs<DependentTemplateSpecializationTypeLoc>(); |
|
|
|
|
TST->Arguments = WalkTemplateArgumentList(&TArgs, &TSpecTL); |
|
|
|
|
TST->Arguments = WalkTemplateArgumentList(TS->template_arguments(), &TSpecTL); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case TypeLoc::TemplateSpecialization: |
|
|
|
|
{ |
|
|
|
|
TemplateSpecializationTypeLoc TSpecTL = TL->getAs<TemplateSpecializationTypeLoc>(); |
|
|
|
|
TST->Arguments = WalkTemplateArgumentList(&TArgs, &TSpecTL); |
|
|
|
|
TST->Arguments = WalkTemplateArgumentList(TS->template_arguments(), &TSpecTL); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case TypeLoc::TemplateTypeParm: |
|
|
|
|
{ |
|
|
|
|
TST->Arguments = WalkTemplateArgumentList(&TArgs, (DependentTemplateSpecializationTypeLoc*)nullptr); |
|
|
|
|
TST->Arguments = WalkTemplateArgumentList(TS->template_arguments(), (DependentTemplateSpecializationTypeLoc*)nullptr); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
default: |
|
|
|
@ -3510,7 +3532,7 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F)
@@ -3510,7 +3532,7 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F)
|
|
|
|
|
F->isConstExpr = FD->isConstexpr(); |
|
|
|
|
F->isVariadic = FD->isVariadic(); |
|
|
|
|
F->isDependent = FD->isDependentContext(); |
|
|
|
|
F->isPure = FD->isPure(); |
|
|
|
|
F->isPure = FD->isPureVirtual(); |
|
|
|
|
F->isDeleted = FD->isDeleted(); |
|
|
|
|
F->isDefaulted = FD->isDefaulted(); |
|
|
|
|
SetBody(FD, F); |
|
|
|
@ -4476,7 +4498,6 @@ Declaration* Parser::WalkDeclaration(const clang::Decl* D)
@@ -4476,7 +4498,6 @@ Declaration* Parser::WalkDeclaration(const clang::Decl* D)
|
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
case Decl::BuiltinTemplate: |
|
|
|
|
case Decl::ClassScopeFunctionSpecialization: |
|
|
|
|
case Decl::PragmaComment: |
|
|
|
|
case Decl::PragmaDetectMismatch: |
|
|
|
|
case Decl::Empty: |
|
|
|
@ -4614,31 +4635,31 @@ void Parser::SetupLLVMCodegen()
@@ -4614,31 +4635,31 @@ void Parser::SetupLLVMCodegen()
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool Parser::SetupSourceFiles(const std::vector<std::string>& SourceFiles, |
|
|
|
|
std::vector<const clang::FileEntry*>& FileEntries) |
|
|
|
|
std::vector<clang::OptionalFileEntryRef>& FileEntries) |
|
|
|
|
{ |
|
|
|
|
// Check that the file is reachable.
|
|
|
|
|
clang::ConstSearchDirIterator* Dir = 0; |
|
|
|
|
llvm::ArrayRef<std::pair<const clang::FileEntry*, clang::DirectoryEntryRef>> Includers; |
|
|
|
|
clang::ConstSearchDirIterator* Dir = nullptr; |
|
|
|
|
llvm::ArrayRef<std::pair<clang::OptionalFileEntryRef, clang::DirectoryEntryRef>> EmptyIncluders; |
|
|
|
|
|
|
|
|
|
for (const auto& SourceFile : SourceFiles) |
|
|
|
|
{ |
|
|
|
|
auto FileEntry = c->getPreprocessor().getHeaderSearchInfo().LookupFile(SourceFile, |
|
|
|
|
clang::SourceLocation(), /*isAngled*/ true, |
|
|
|
|
nullptr, Dir, Includers, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); |
|
|
|
|
auto FileEntry = c->getPreprocessor().getHeaderSearchInfo().LookupFile( |
|
|
|
|
SourceFile, |
|
|
|
|
clang::SourceLocation(), |
|
|
|
|
/*isAngled*/ true, |
|
|
|
|
nullptr, Dir, |
|
|
|
|
EmptyIncluders, |
|
|
|
|
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); |
|
|
|
|
|
|
|
|
|
if (!FileEntry) |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
FileEntries.push_back(&FileEntry.getPointer()->getFileEntry()); |
|
|
|
|
FileEntries.push_back(FileEntry); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Create a virtual file that includes the header. This gets rid of some
|
|
|
|
|
// Clang warnings about parsing an header file as the main file.
|
|
|
|
|
|
|
|
|
|
std::string source; |
|
|
|
|
for (const auto& SourceFile : SourceFiles) |
|
|
|
|
{ |
|
|
|
|
source += "#include \"" + SourceFile + "\"" + "\n"; |
|
|
|
|
source += "#include \"" + SourceFile + "\"\n"; |
|
|
|
|
} |
|
|
|
|
source += "\0"; |
|
|
|
|
|
|
|
|
@ -4652,7 +4673,7 @@ bool Parser::SetupSourceFiles(const std::vector<std::string>& SourceFiles,
@@ -4652,7 +4673,7 @@ bool Parser::SetupSourceFiles(const std::vector<std::string>& SourceFiles,
|
|
|
|
|
class SemaConsumer : public clang::SemaConsumer |
|
|
|
|
{ |
|
|
|
|
public: |
|
|
|
|
SemaConsumer(Parser& parser, std::vector<const clang::FileEntry*>& entries) |
|
|
|
|
SemaConsumer(Parser& parser, std::vector<clang::OptionalFileEntryRef>& entries) |
|
|
|
|
: Parser(parser) |
|
|
|
|
, FileEntries(entries) |
|
|
|
|
{ |
|
|
|
@ -4662,7 +4683,7 @@ public:
@@ -4662,7 +4683,7 @@ public:
|
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
Parser& Parser; |
|
|
|
|
std::vector<const clang::FileEntry*>& FileEntries; |
|
|
|
|
std::vector<clang::OptionalFileEntryRef>& FileEntries; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
void SemaConsumer::HandleTranslationUnit(clang::ASTContext& Ctx) |
|
|
|
@ -4675,7 +4696,7 @@ void SemaConsumer::HandleTranslationUnit(clang::ASTContext& Ctx)
@@ -4675,7 +4696,7 @@ void SemaConsumer::HandleTranslationUnit(clang::ASTContext& Ctx)
|
|
|
|
|
Parser.HandleDeclaration(TU, Unit); |
|
|
|
|
|
|
|
|
|
if (Unit->originalPtr == nullptr) |
|
|
|
|
Unit->originalPtr = (void*)FileEntry; |
|
|
|
|
Unit->originalPtr = (void*)&FileEntry->getFileEntry(); |
|
|
|
|
|
|
|
|
|
Parser.WalkAST(TU); |
|
|
|
|
} |
|
|
|
@ -4695,7 +4716,7 @@ ParserResult* Parser::Parse(const std::vector<std::string>& SourceFiles)
@@ -4695,7 +4716,7 @@ ParserResult* Parser::Parse(const std::vector<std::string>& SourceFiles)
|
|
|
|
|
Setup(); |
|
|
|
|
SetupLLVMCodegen(); |
|
|
|
|
|
|
|
|
|
std::vector<const clang::FileEntry*> FileEntries; |
|
|
|
|
std::vector<clang::OptionalFileEntryRef> FileEntries; |
|
|
|
|
if (!SetupSourceFiles(SourceFiles, FileEntries)) |
|
|
|
|
{ |
|
|
|
|
res->kind = ParserResultKind::FileNotFound; |
|
|
|
@ -4829,7 +4850,7 @@ ParserResultKind Parser::ParseSharedLib(const std::string& File,
@@ -4829,7 +4850,7 @@ ParserResultKind Parser::ParseSharedLib(const std::string& File,
|
|
|
|
|
for (const auto& ImportedSymbol : COFFObjectFile->import_directories()) |
|
|
|
|
{ |
|
|
|
|
llvm::StringRef Name; |
|
|
|
|
if (!ImportedSymbol.getName(Name) && (Name.endswith(".dll") || Name.endswith(".DLL"))) |
|
|
|
|
if (!ImportedSymbol.getName(Name) && (Name.ends_with(".dll") || Name.ends_with(".DLL"))) |
|
|
|
|
NativeLib->Dependencies.push_back(Name.str()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|