Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 77557ae

Browse files
committed
[ASTImporter] Support importing FunctionTemplateDecl and CXXDependentScopeMemberExpr
* Also introduces ImportTemplateArgumentListInfo facility (A. Sidorin) This re-commits r320942 after fixing the behaviour on '-fdelayed-template-parsing' option and adding additional checks. Patch by Peter Szecsi! Differential Revision: https://reviews.llvm.org/D38692 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@321492 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 7e0bf61 commit 77557ae

File tree

2 files changed

+156
-0
lines changed

2 files changed

+156
-0
lines changed

lib/AST/ASTImporter.cpp

+126
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,17 @@ namespace clang {
134134
bool ImportTemplateArguments(const TemplateArgument *FromArgs,
135135
unsigned NumFromArgs,
136136
SmallVectorImpl<TemplateArgument> &ToArgs);
137+
template <typename InContainerTy>
138+
bool ImportTemplateArgumentListInfo(const InContainerTy &Container,
139+
TemplateArgumentListInfo &ToTAInfo);
137140
bool IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord,
138141
bool Complain = true);
139142
bool IsStructuralMatch(VarDecl *FromVar, VarDecl *ToVar,
140143
bool Complain = true);
141144
bool IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToRecord);
142145
bool IsStructuralMatch(EnumConstantDecl *FromEC, EnumConstantDecl *ToEC);
146+
bool IsStructuralMatch(FunctionTemplateDecl *From,
147+
FunctionTemplateDecl *To);
143148
bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To);
144149
bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To);
145150
Decl *VisitDecl(Decl *D);
@@ -195,6 +200,7 @@ namespace clang {
195200
ClassTemplateSpecializationDecl *D);
196201
Decl *VisitVarTemplateDecl(VarTemplateDecl *D);
197202
Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D);
203+
Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
198204

199205
// Importing statements
200206
DeclGroupRef ImportDeclGroup(DeclGroupRef DG);
@@ -280,6 +286,7 @@ namespace clang {
280286
Expr *VisitCXXDeleteExpr(CXXDeleteExpr *E);
281287
Expr *VisitCXXConstructExpr(CXXConstructExpr *E);
282288
Expr *VisitCXXMemberCallExpr(CXXMemberCallExpr *E);
289+
Expr *VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E);
283290
Expr *VisitExprWithCleanups(ExprWithCleanups *EWC);
284291
Expr *VisitCXXThisExpr(CXXThisExpr *E);
285292
Expr *VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
@@ -1247,6 +1254,18 @@ bool ASTNodeImporter::ImportTemplateArguments(const TemplateArgument *FromArgs,
12471254
return false;
12481255
}
12491256

1257+
template <typename InContainerTy>
1258+
bool ASTNodeImporter::ImportTemplateArgumentListInfo(
1259+
const InContainerTy &Container, TemplateArgumentListInfo &ToTAInfo) {
1260+
for (const auto &FromLoc : Container) {
1261+
if (auto ToLoc = ImportTemplateArgumentLoc(FromLoc))
1262+
ToTAInfo.addArgument(*ToLoc);
1263+
else
1264+
return true;
1265+
}
1266+
return false;
1267+
}
1268+
12501269
bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord,
12511270
RecordDecl *ToRecord, bool Complain) {
12521271
// Eliminate a potential failure point where we attempt to re-import
@@ -1280,6 +1299,14 @@ bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) {
12801299
return Ctx.IsStructurallyEquivalent(FromEnum, ToEnum);
12811300
}
12821301

1302+
bool ASTNodeImporter::IsStructuralMatch(FunctionTemplateDecl *From,
1303+
FunctionTemplateDecl *To) {
1304+
StructuralEquivalenceContext Ctx(
1305+
Importer.getFromContext(), Importer.getToContext(),
1306+
Importer.getNonEquivalentDecls(), false, false);
1307+
return Ctx.IsStructurallyEquivalent(From, To);
1308+
}
1309+
12831310
bool ASTNodeImporter::IsStructuralMatch(EnumConstantDecl *FromEC,
12841311
EnumConstantDecl *ToEC)
12851312
{
@@ -4197,6 +4224,64 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl(
41974224
return D2;
41984225
}
41994226

4227+
Decl *ASTNodeImporter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
4228+
DeclContext *DC, *LexicalDC;
4229+
DeclarationName Name;
4230+
SourceLocation Loc;
4231+
NamedDecl *ToD;
4232+
4233+
if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
4234+
return nullptr;
4235+
4236+
if (ToD)
4237+
return ToD;
4238+
4239+
// Try to find a function in our own ("to") context with the same name, same
4240+
// type, and in the same context as the function we're importing.
4241+
if (!LexicalDC->isFunctionOrMethod()) {
4242+
unsigned IDNS = Decl::IDNS_Ordinary;
4243+
SmallVector<NamedDecl *, 2> FoundDecls;
4244+
DC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
4245+
for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) {
4246+
if (!FoundDecls[I]->isInIdentifierNamespace(IDNS))
4247+
continue;
4248+
4249+
if (FunctionTemplateDecl *FoundFunction =
4250+
dyn_cast<FunctionTemplateDecl>(FoundDecls[I])) {
4251+
if (FoundFunction->hasExternalFormalLinkage() &&
4252+
D->hasExternalFormalLinkage()) {
4253+
if (IsStructuralMatch(D, FoundFunction)) {
4254+
Importer.Imported(D, FoundFunction);
4255+
// FIXME: Actually try to merge the body and other attributes.
4256+
return FoundFunction;
4257+
}
4258+
}
4259+
}
4260+
}
4261+
}
4262+
4263+
TemplateParameterList *Params =
4264+
ImportTemplateParameterList(D->getTemplateParameters());
4265+
if (!Params)
4266+
return nullptr;
4267+
4268+
FunctionDecl *TemplatedFD =
4269+
cast_or_null<FunctionDecl>(Importer.Import(D->getTemplatedDecl()));
4270+
if (!TemplatedFD)
4271+
return nullptr;
4272+
4273+
FunctionTemplateDecl *ToFunc = FunctionTemplateDecl::Create(
4274+
Importer.getToContext(), DC, Loc, Name, Params, TemplatedFD);
4275+
4276+
TemplatedFD->setDescribedFunctionTemplate(ToFunc);
4277+
ToFunc->setAccess(D->getAccess());
4278+
ToFunc->setLexicalDeclContext(LexicalDC);
4279+
Importer.Imported(D, ToFunc);
4280+
4281+
LexicalDC->addDeclInternal(ToFunc);
4282+
return ToFunc;
4283+
}
4284+
42004285
//----------------------------------------------------------------------------
42014286
// Import Statements
42024287
//----------------------------------------------------------------------------
@@ -5758,6 +5843,47 @@ Expr *ASTNodeImporter::VisitCXXPseudoDestructorExpr(
57585843
Importer.Import(E->getTildeLoc()), Storage);
57595844
}
57605845

5846+
Expr *ASTNodeImporter::VisitCXXDependentScopeMemberExpr(
5847+
CXXDependentScopeMemberExpr *E) {
5848+
Expr *Base = nullptr;
5849+
if (!E->isImplicitAccess()) {
5850+
Base = Importer.Import(E->getBase());
5851+
if (!Base)
5852+
return nullptr;
5853+
}
5854+
5855+
QualType BaseType = Importer.Import(E->getBaseType());
5856+
if (BaseType.isNull())
5857+
return nullptr;
5858+
5859+
TemplateArgumentListInfo ToTAInfo(Importer.Import(E->getLAngleLoc()),
5860+
Importer.Import(E->getRAngleLoc()));
5861+
TemplateArgumentListInfo *ResInfo = nullptr;
5862+
if (E->hasExplicitTemplateArgs()) {
5863+
if (ImportTemplateArgumentListInfo(E->template_arguments(), ToTAInfo))
5864+
return nullptr;
5865+
ResInfo = &ToTAInfo;
5866+
}
5867+
5868+
DeclarationName Name = Importer.Import(E->getMember());
5869+
if (!E->getMember().isEmpty() && Name.isEmpty())
5870+
return nullptr;
5871+
5872+
DeclarationNameInfo MemberNameInfo(Name, Importer.Import(E->getMemberLoc()));
5873+
// Import additional name location/type info.
5874+
ImportDeclarationNameLoc(E->getMemberNameInfo(), MemberNameInfo);
5875+
auto ToFQ = Importer.Import(E->getFirstQualifierFoundInScope());
5876+
if (!ToFQ && E->getFirstQualifierFoundInScope())
5877+
return nullptr;
5878+
5879+
return CXXDependentScopeMemberExpr::Create(
5880+
Importer.getToContext(), Base, BaseType, E->isArrow(),
5881+
Importer.Import(E->getOperatorLoc()),
5882+
Importer.Import(E->getQualifierLoc()),
5883+
Importer.Import(E->getTemplateKeywordLoc()),
5884+
cast_or_null<NamedDecl>(ToFQ), MemberNameInfo, ResInfo);
5885+
}
5886+
57615887
Expr *ASTNodeImporter::VisitCallExpr(CallExpr *E) {
57625888
QualType T = Importer.Import(E->getType());
57635889
if (T.isNull())

unittests/AST/ASTImporterTest.cpp

+30
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,36 @@ TEST(ImportType, ImportAtomicType) {
495495
has(atomicType())))))))));
496496
}
497497

498+
TEST(ImportDecl, ImportFunctionTemplateDecl) {
499+
MatchVerifier<Decl> Verifier;
500+
testImport("template <typename T> void declToImport() { };", Lang_CXX, "",
501+
Lang_CXX, Verifier, functionTemplateDecl());
502+
}
503+
504+
const internal::VariadicDynCastAllOfMatcher<Expr, CXXDependentScopeMemberExpr>
505+
cxxDependentScopeMemberExpr;
506+
507+
TEST(ImportExpr, ImportCXXDependentScopeMemberExpr) {
508+
MatchVerifier<Decl> Verifier;
509+
testImport("template <typename T> struct C { T t; };"
510+
"template <typename T> void declToImport() {"
511+
" C<T> d;"
512+
" d.t;"
513+
"}"
514+
"void instantiate() { declToImport<int>(); }",
515+
Lang_CXX, "", Lang_CXX, Verifier,
516+
functionTemplateDecl(has(functionDecl(
517+
has(compoundStmt(has(cxxDependentScopeMemberExpr())))))));
518+
testImport("template <typename T> struct C { T t; };"
519+
"template <typename T> void declToImport() {"
520+
" C<T> d;"
521+
" (&d)->t;"
522+
"}"
523+
"void instantiate() { declToImport<int>(); }",
524+
Lang_CXX, "", Lang_CXX, Verifier,
525+
functionTemplateDecl(has(functionDecl(
526+
has(compoundStmt(has(cxxDependentScopeMemberExpr())))))));
527+
}
498528

499529
TEST(ImportType, ImportTypeAliasTemplate) {
500530
MatchVerifier<Decl> Verifier;

0 commit comments

Comments
 (0)