r325116 - [ASTImporter] Fix lexical DC for templated decls; support VarTemplatePartialSpecDecl
Aleksei Sidorin via cfe-commits
cfe-commits at lists.llvm.org
Wed Feb 14 03:18:00 PST 2018
Author: a.sidorin
Date: Wed Feb 14 03:18:00 2018
New Revision: 325116
URL: http://llvm.org/viewvc/llvm-project?rev=325116&view=rev
Log:
[ASTImporter] Fix lexical DC for templated decls; support VarTemplatePartialSpecDecl
Also minor refactoring in related functions was done.
Differential Revision: https://reviews.llvm.org/D43012
Added:
cfe/trunk/test/ASTMerge/var-cpp/
cfe/trunk/test/ASTMerge/var-cpp/Inputs/
cfe/trunk/test/ASTMerge/var-cpp/Inputs/var1.cpp
cfe/trunk/test/ASTMerge/var-cpp/test.cpp
Modified:
cfe/trunk/lib/AST/ASTImporter.cpp
cfe/trunk/unittests/AST/ASTImporterTest.cpp
Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=325116&r1=325115&r2=325116&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Wed Feb 14 03:18:00 2018
@@ -23,7 +23,6 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/MemoryBuffer.h"
-#include <deque>
namespace clang {
class ASTNodeImporter : public TypeVisitor<ASTNodeImporter, QualType>,
@@ -1335,6 +1334,21 @@ bool ASTNodeImporter::ImportTemplateArgu
return false;
}
+template <>
+bool ASTNodeImporter::ImportTemplateArgumentListInfo<TemplateArgumentListInfo>(
+ const TemplateArgumentListInfo &From, TemplateArgumentListInfo &Result) {
+ return ImportTemplateArgumentListInfo(
+ From.getLAngleLoc(), From.getRAngleLoc(), From.arguments(), Result);
+}
+
+template <>
+bool ASTNodeImporter::ImportTemplateArgumentListInfo<
+ ASTTemplateArgumentListInfo>(const ASTTemplateArgumentListInfo &From,
+ TemplateArgumentListInfo &Result) {
+ return ImportTemplateArgumentListInfo(From.LAngleLoc, From.RAngleLoc,
+ From.arguments(), Result);
+}
+
bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord,
RecordDecl *ToRecord, bool Complain) {
// Eliminate a potential failure point where we attempt to re-import
@@ -1655,10 +1669,8 @@ Decl *ASTNodeImporter::VisitTypedefNameD
SourceLocation StartL = Importer.Import(D->getLocStart());
TypedefNameDecl *ToTypedef;
if (IsAlias)
- ToTypedef = TypeAliasDecl::Create(Importer.getToContext(), DC,
- StartL, Loc,
- Name.getAsIdentifierInfo(),
- TInfo);
+ ToTypedef = TypeAliasDecl::Create(Importer.getToContext(), DC, StartL, Loc,
+ Name.getAsIdentifierInfo(), TInfo);
else
ToTypedef = TypedefDecl::Create(Importer.getToContext(), DC,
StartL, Loc,
@@ -1668,7 +1680,11 @@ Decl *ASTNodeImporter::VisitTypedefNameD
ToTypedef->setAccess(D->getAccess());
ToTypedef->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToTypedef);
- LexicalDC->addDeclInternal(ToTypedef);
+
+ // Templated declarations should not appear in DeclContext.
+ TypeAliasDecl *FromAlias = IsAlias ? cast<TypeAliasDecl>(D) : nullptr;
+ if (!FromAlias || !FromAlias->getDescribedAliasTemplate())
+ LexicalDC->addDeclInternal(ToTypedef);
return ToTypedef;
}
@@ -1686,11 +1702,11 @@ Decl *ASTNodeImporter::VisitTypeAliasTem
DeclContext *DC, *LexicalDC;
DeclarationName Name;
SourceLocation Loc;
- NamedDecl *ToD;
- if (ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc))
+ NamedDecl *FoundD;
+ if (ImportDeclParts(D, DC, LexicalDC, Name, FoundD, Loc))
return nullptr;
- if (ToD)
- return ToD;
+ if (FoundD)
+ return FoundD;
// If this typedef is not in block scope, determine whether we've
// seen a typedef with the same name (that we can merge with) or any
@@ -1723,7 +1739,7 @@ Decl *ASTNodeImporter::VisitTypeAliasTem
if (!Params)
return nullptr;
- NamedDecl *TemplDecl = cast_or_null<NamedDecl>(
+ auto *TemplDecl = cast_or_null<TypeAliasDecl>(
Importer.Import(D->getTemplatedDecl()));
if (!TemplDecl)
return nullptr;
@@ -1731,11 +1747,13 @@ Decl *ASTNodeImporter::VisitTypeAliasTem
TypeAliasTemplateDecl *ToAlias = TypeAliasTemplateDecl::Create(
Importer.getToContext(), DC, Loc, Name, Params, TemplDecl);
+ TemplDecl->setDescribedAliasTemplate(ToAlias);
+
ToAlias->setAccess(D->getAccess());
ToAlias->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToAlias);
LexicalDC->addDeclInternal(ToAlias);
- return ToD;
+ return ToAlias;
}
Decl *ASTNodeImporter::VisitLabelDecl(LabelDecl *D) {
@@ -2155,12 +2173,9 @@ bool ASTNodeImporter::ImportTemplateInfo
TemplateArgumentListInfo ToTAInfo;
const auto *FromTAArgsAsWritten = FTSInfo->TemplateArgumentsAsWritten;
- if (FromTAArgsAsWritten) {
- if (ImportTemplateArgumentListInfo(
- FromTAArgsAsWritten->LAngleLoc, FromTAArgsAsWritten->RAngleLoc,
- FromTAArgsAsWritten->arguments(), ToTAInfo))
+ if (FromTAArgsAsWritten)
+ if (ImportTemplateArgumentListInfo(*FromTAArgsAsWritten, ToTAInfo))
return true;
- }
SourceLocation POI = Importer.Import(FTSInfo->getPointOfInstantiation());
@@ -2839,7 +2854,10 @@ Decl *ASTNodeImporter::VisitVarDecl(VarD
ToVar->setAccess(D->getAccess());
ToVar->setLexicalDeclContext(LexicalDC);
Importer.Imported(D, ToVar);
- LexicalDC->addDeclInternal(ToVar);
+
+ // Templated declarations should never appear in the enclosing DeclContext.
+ if (!D->getDescribedVarTemplate())
+ LexicalDC->addDeclInternal(ToVar);
if (!D->isFileVarDecl() &&
D->isUsed())
@@ -4142,8 +4160,8 @@ Decl *ASTNodeImporter::VisitClassTemplat
// Import TemplateArgumentListInfo
TemplateArgumentListInfo ToTAInfo;
- auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten();
- if (ImportTemplateArgumentListInfo(ASTTemplateArgs.arguments(), ToTAInfo))
+ const auto &ASTTemplateArgs = *PartialSpec->getTemplateArgsAsWritten();
+ if (ImportTemplateArgumentListInfo(ASTTemplateArgs, ToTAInfo))
return nullptr;
QualType CanonInjType = Importer.Import(
@@ -4275,21 +4293,8 @@ Decl *ASTNodeImporter::VisitVarTemplateD
return nullptr;
// Create the declaration that is being templated.
- SourceLocation StartLoc = Importer.Import(DTemplated->getLocStart());
- SourceLocation IdLoc = Importer.Import(DTemplated->getLocation());
- TypeSourceInfo *TInfo = Importer.Import(DTemplated->getTypeSourceInfo());
- VarDecl *D2Templated = VarDecl::Create(Importer.getToContext(), DC, StartLoc,
- IdLoc, Name.getAsIdentifierInfo(), T,
- TInfo, DTemplated->getStorageClass());
- D2Templated->setAccess(DTemplated->getAccess());
- D2Templated->setQualifierInfo(Importer.Import(DTemplated->getQualifierLoc()));
- D2Templated->setLexicalDeclContext(LexicalDC);
-
- // Importer.Imported(DTemplated, D2Templated);
- // LexicalDC->addDeclInternal(D2Templated);
-
- // Merge the initializer.
- if (ImportDefinition(DTemplated, D2Templated))
+ auto *ToTemplated = dyn_cast_or_null<VarDecl>(Importer.Import(DTemplated));
+ if (!ToTemplated)
return nullptr;
// Create the variable template declaration itself.
@@ -4298,24 +4303,24 @@ Decl *ASTNodeImporter::VisitVarTemplateD
if (!TemplateParams)
return nullptr;
- VarTemplateDecl *D2 = VarTemplateDecl::Create(
- Importer.getToContext(), DC, Loc, Name, TemplateParams, D2Templated);
- D2Templated->setDescribedVarTemplate(D2);
-
- D2->setAccess(D->getAccess());
- D2->setLexicalDeclContext(LexicalDC);
- LexicalDC->addDeclInternal(D2);
+ VarTemplateDecl *ToVarTD = VarTemplateDecl::Create(
+ Importer.getToContext(), DC, Loc, Name, TemplateParams, ToTemplated);
+ ToTemplated->setDescribedVarTemplate(ToVarTD);
+
+ ToVarTD->setAccess(D->getAccess());
+ ToVarTD->setLexicalDeclContext(LexicalDC);
+ LexicalDC->addDeclInternal(ToVarTD);
// Note the relationship between the variable templates.
- Importer.Imported(D, D2);
- Importer.Imported(DTemplated, D2Templated);
+ Importer.Imported(D, ToVarTD);
+ Importer.Imported(DTemplated, ToTemplated);
if (DTemplated->isThisDeclarationADefinition() &&
- !D2Templated->isThisDeclarationADefinition()) {
+ !ToTemplated->isThisDeclarationADefinition()) {
// FIXME: Import definition!
}
- return D2;
+ return ToVarTD;
}
Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl(
@@ -4384,14 +4389,57 @@ Decl *ASTNodeImporter::VisitVarTemplateS
QualType T = Importer.Import(D->getType());
if (T.isNull())
return nullptr;
+
TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo());
+ if (D->getTypeSourceInfo() && !TInfo)
+ return nullptr;
+
+ TemplateArgumentListInfo ToTAInfo;
+ if (ImportTemplateArgumentListInfo(D->getTemplateArgsInfo(), ToTAInfo))
+ return nullptr;
+ using PartVarSpecDecl = VarTemplatePartialSpecializationDecl;
// Create a new specialization.
- D2 = VarTemplateSpecializationDecl::Create(
- Importer.getToContext(), DC, StartLoc, IdLoc, VarTemplate, T, TInfo,
- D->getStorageClass(), TemplateArgs);
+ if (auto *FromPartial = dyn_cast<PartVarSpecDecl>(D)) {
+ // Import TemplateArgumentListInfo
+ TemplateArgumentListInfo ArgInfos;
+ const auto *FromTAArgsAsWritten = FromPartial->getTemplateArgsAsWritten();
+ // NOTE: FromTAArgsAsWritten and template parameter list are non-null.
+ if (ImportTemplateArgumentListInfo(*FromTAArgsAsWritten, ArgInfos))
+ return nullptr;
+
+ TemplateParameterList *ToTPList = ImportTemplateParameterList(
+ FromPartial->getTemplateParameters());
+ if (!ToTPList)
+ return nullptr;
+
+ auto *ToPartial = PartVarSpecDecl::Create(
+ Importer.getToContext(), DC, StartLoc, IdLoc, ToTPList, VarTemplate,
+ T, TInfo, D->getStorageClass(), TemplateArgs, ArgInfos);
+
+ auto *FromInst = FromPartial->getInstantiatedFromMember();
+ auto *ToInst = cast_or_null<PartVarSpecDecl>(Importer.Import(FromInst));
+ if (FromInst && !ToInst)
+ return nullptr;
+
+ ToPartial->setInstantiatedFromMember(ToInst);
+ if (FromPartial->isMemberSpecialization())
+ ToPartial->setMemberSpecialization();
+
+ D2 = ToPartial;
+
+ } else { // Full specialization
+ D2 = VarTemplateSpecializationDecl::Create(
+ Importer.getToContext(), DC, StartLoc, IdLoc, VarTemplate, T, TInfo,
+ D->getStorageClass(), TemplateArgs);
+ }
+
+ SourceLocation POI = D->getPointOfInstantiation();
+ if (POI.isValid())
+ D2->setPointOfInstantiation(Importer.Import(POI));
+
D2->setSpecializationKind(D->getSpecializationKind());
- D2->setTemplateArgsInfo(D->getTemplateArgsInfo());
+ D2->setTemplateArgsInfo(ToTAInfo);
// Add this specialization to the class template.
VarTemplate->AddSpecialization(D2, InsertPos);
@@ -4399,13 +4447,24 @@ Decl *ASTNodeImporter::VisitVarTemplateS
// Import the qualifier, if any.
D2->setQualifierInfo(Importer.Import(D->getQualifierLoc()));
+ if (D->isConstexpr())
+ D2->setConstexpr(true);
+
// Add the specialization to this context.
D2->setLexicalDeclContext(LexicalDC);
LexicalDC->addDeclInternal(D2);
+
+ D2->setAccess(D->getAccess());
}
+
Importer.Imported(D, D2);
- if (D->isThisDeclarationADefinition() && ImportDefinition(D, D2))
+ // NOTE: isThisDeclarationADefinition() can return DeclarationOnly even if
+ // declaration has initializer. Should this be fixed in the AST?.. Anyway,
+ // we have to check the declaration for initializer - otherwise, it won't be
+ // imported.
+ if ((D->isThisDeclarationADefinition() || D->hasInit()) &&
+ ImportDefinition(D, D2))
return nullptr;
return D2;
Added: cfe/trunk/test/ASTMerge/var-cpp/Inputs/var1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ASTMerge/var-cpp/Inputs/var1.cpp?rev=325116&view=auto
==============================================================================
--- cfe/trunk/test/ASTMerge/var-cpp/Inputs/var1.cpp (added)
+++ cfe/trunk/test/ASTMerge/var-cpp/Inputs/var1.cpp Wed Feb 14 03:18:00 2018
@@ -0,0 +1,17 @@
+
+template <typename T>
+constexpr T my_pi = T(3.1415926535897932385L); // variable template
+
+template <> constexpr char my_pi<char> = '3'; // variable template specialization
+
+template <typename T>
+struct Wrapper {
+ template <typename U> static constexpr U my_const = U(1);
+ // Variable template partial specialization with member variable.
+ template <typename U> static constexpr U *my_const<const U *> = (U *)(0);
+};
+
+constexpr char a[] = "hello";
+
+template <> template <>
+constexpr const char *Wrapper<float>::my_const<const char *> = a;
Added: cfe/trunk/test/ASTMerge/var-cpp/test.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ASTMerge/var-cpp/test.cpp?rev=325116&view=auto
==============================================================================
--- cfe/trunk/test/ASTMerge/var-cpp/test.cpp (added)
+++ cfe/trunk/test/ASTMerge/var-cpp/test.cpp Wed Feb 14 03:18:00 2018
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -emit-pch -std=c++17 -o %t.1.ast %S/Inputs/var1.cpp
+// RUN: %clang_cc1 -std=c++17 -ast-merge %t.1.ast -fsyntax-only %s 2>&1
+
+static_assert(my_pi<double> == (double)3.1415926535897932385L);
+static_assert(my_pi<char> == '3');
+
+static_assert(Wrapper<int>::my_const<float> == 1.f);
+static_assert(Wrapper<char>::my_const<const float *> == nullptr);
+static_assert(Wrapper<float>::my_const<const char *> == a);
Modified: cfe/trunk/unittests/AST/ASTImporterTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterTest.cpp?rev=325116&r1=325115&r2=325116&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/ASTImporterTest.cpp (original)
+++ cfe/trunk/unittests/AST/ASTImporterTest.cpp Wed Feb 14 03:18:00 2018
@@ -542,20 +542,32 @@ TEST(ImportExpr, ImportCXXDependentScope
TEST(ImportType, ImportTypeAliasTemplate) {
MatchVerifier<Decl> Verifier;
- testImport("template <int K>"
- "struct dummy { static const int i = K; };"
- "template <int K> using dummy2 = dummy<K>;"
- "int declToImport() { return dummy2<3>::i; }",
- Lang_CXX11, "", Lang_CXX11, Verifier,
- functionDecl(
- hasBody(
- compoundStmt(
- has(
- returnStmt(
- has(
- implicitCastExpr(
- has(
- declRefExpr())))))))));
+ testImport(
+ "template <int K>"
+ "struct dummy { static const int i = K; };"
+ "template <int K> using dummy2 = dummy<K>;"
+ "int declToImport() { return dummy2<3>::i; }",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ functionDecl(
+ hasBody(compoundStmt(
+ has(returnStmt(has(implicitCastExpr(has(declRefExpr()))))))),
+ unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
+}
+
+const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
+ varTemplateSpecializationDecl;
+
+TEST(ImportDecl, ImportVarTemplate) {
+ MatchVerifier<Decl> Verifier;
+ testImport(
+ "template <typename T>"
+ "T pi = T(3.1415926535897932385L);"
+ "void declToImport() { pi<int>; }",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ functionDecl(
+ hasBody(has(declRefExpr(to(varTemplateSpecializationDecl())))),
+ unless(hasAncestor(translationUnitDecl(has(varDecl(
+ hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
}
TEST(ImportType, ImportPackExpansion) {
More information about the cfe-commits
mailing list