Skip to content

Commit 416fbca

Browse files
Code review
Add comments for new member. Make RAII approach for cycles monitoring.
1 parent 3e23230 commit 416fbca

File tree

2 files changed

+58
-7
lines changed

2 files changed

+58
-7
lines changed

clang/include/clang/AST/ASTImporter.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,8 @@ class TypeSourceInfo;
190190
llvm::SmallDenseMap<Decl *, int, 32> Aux;
191191
};
192192

193+
class FunctionReturnTypeDeclCycleDetector;
194+
193195
private:
194196
std::shared_ptr<ASTImporterSharedState> SharedState = nullptr;
195197

@@ -254,7 +256,16 @@ class TypeSourceInfo;
254256
/// Declaration (from, to) pairs that are known not to be equivalent
255257
/// (which we have already complained about).
256258
NonEquivalentDeclSet NonEquivalentDecls;
257-
llvm::DenseSet<const Decl *> DeclTypeCycles;
259+
// When template function return type is auto and return type is declared as
260+
// typename from template params, there could be cycles in function
261+
// importing when function decaration is still the need for return type
262+
// declaration import. We have code path for nested types inside function
263+
// (see hasReturnTypeDeclaredInside): assuming return type as VoidTy and
264+
// calculate it later under UsedDifferentProtoType boolean. This class is
265+
// reuse of this approach and make logic lazy - detect cycle - calculate
266+
// return type later on.
267+
std::unique_ptr<FunctionReturnTypeDeclCycleDetector>
268+
FunctionReturnTypeCycleDetector;
258269

259270
using FoundDeclsTy = SmallVector<NamedDecl *, 2>;
260271
FoundDeclsTy findDeclsInToCtx(DeclContext *DC, DeclarationName Name);

clang/lib/AST/ASTImporter.cpp

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,6 +1287,44 @@ bool ASTNodeImporter::hasSameVisibilityContextAndLinkage(TypedefNameDecl *Found,
12871287

12881288
using namespace clang;
12891289

1290+
class ASTImporter::FunctionReturnTypeDeclCycleDetector {
1291+
public:
1292+
class ScopedReturnTypeImport {
1293+
public:
1294+
// Do not track cycles on D == nullptr.
1295+
ScopedReturnTypeImport(FunctionReturnTypeDeclCycleDetector &owner,
1296+
const Decl *D)
1297+
: CycleDetector(owner), D(D) {
1298+
if (D)
1299+
CycleDetector.FunctionReturnTypeDeclCycles.insert(D);
1300+
}
1301+
~ScopedReturnTypeImport() {
1302+
if (D)
1303+
CycleDetector.FunctionReturnTypeDeclCycles.erase(D);
1304+
}
1305+
ScopedReturnTypeImport(const ScopedReturnTypeImport &) = delete;
1306+
ScopedReturnTypeImport &operator=(const ScopedReturnTypeImport &) = delete;
1307+
1308+
private:
1309+
FunctionReturnTypeDeclCycleDetector &CycleDetector;
1310+
const Decl *D;
1311+
};
1312+
1313+
ScopedReturnTypeImport DetectImportCycles(const Decl *D) {
1314+
if (!IsCycle(D))
1315+
return ScopedReturnTypeImport(*this, D);
1316+
return ScopedReturnTypeImport(*this, nullptr);
1317+
}
1318+
1319+
bool IsCycle(const Decl *D) const {
1320+
return FunctionReturnTypeDeclCycles.find(D) !=
1321+
FunctionReturnTypeDeclCycles.end();
1322+
}
1323+
1324+
private:
1325+
llvm::DenseSet<const Decl *> FunctionReturnTypeDeclCycles;
1326+
};
1327+
12901328
ExpectedType ASTNodeImporter::VisitType(const Type *T) {
12911329
Importer.FromDiag(SourceLocation(), diag::err_unsupported_ast_node)
12921330
<< T->getTypeClassName();
@@ -4035,8 +4073,10 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
40354073
// E.g.: auto foo() { struct X{}; return X(); }
40364074
// To avoid an infinite recursion when importing, create the FunctionDecl
40374075
// with a simplified return type.
4076+
// Reuse this approach for auto return types declared as typenames from
4077+
// template pamams, tracked in FunctionReturnTypeCycleDetector.
40384078
if (hasReturnTypeDeclaredInside(D) ||
4039-
Importer.DeclTypeCycles.find(D) != Importer.DeclTypeCycles.end()) {
4079+
Importer.FunctionReturnTypeCycleDetector->IsCycle(D)) {
40404080
FromReturnTy = Importer.getFromContext().VoidTy;
40414081
UsedDifferentProtoType = true;
40424082
}
@@ -4059,11 +4099,9 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {
40594099
}
40604100

40614101
Error Err = Error::success();
4062-
if (!UsedDifferentProtoType)
4063-
Importer.DeclTypeCycles.insert(D);
4102+
auto ScopedReturnTypeDeclCycleDetector =
4103+
Importer.FunctionReturnTypeCycleDetector->DetectImportCycles(D);
40644104
auto T = importChecked(Err, FromTy);
4065-
if (!UsedDifferentProtoType)
4066-
Importer.DeclTypeCycles.erase(D);
40674105
auto TInfo = importChecked(Err, FromTSI);
40684106
auto ToInnerLocStart = importChecked(Err, D->getInnerLocStart());
40694107
auto ToEndLoc = importChecked(Err, D->getEndLoc());
@@ -9299,7 +9337,9 @@ ASTImporter::ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
92999337
std::shared_ptr<ASTImporterSharedState> SharedState)
93009338
: SharedState(SharedState), ToContext(ToContext), FromContext(FromContext),
93019339
ToFileManager(ToFileManager), FromFileManager(FromFileManager),
9302-
Minimal(MinimalImport), ODRHandling(ODRHandlingType::Conservative) {
9340+
Minimal(MinimalImport), ODRHandling(ODRHandlingType::Conservative),
9341+
FunctionReturnTypeCycleDetector(
9342+
std::make_unique<FunctionReturnTypeDeclCycleDetector>()) {
93039343

93049344
// Create a default state without the lookup table: LLDB case.
93059345
if (!SharedState) {

0 commit comments

Comments
 (0)