Skip to content

Commit 54058b5

Browse files
committedDec 17, 2018
[ASTImporter] Add importer specific lookup
Summary: There are certain cases when normal C/C++ lookup (localUncachedLookup) does not find AST nodes. E.g.: Example 1: template <class T> struct X { friend void foo(); // this is never found in the DC of the TU. }; Example 2: // The fwd decl to Foo is not found in the lookupPtr of the DC of the // translation unit decl. struct A { struct Foo *p; }; In these cases we create a new node instead of returning with the old one. To fix it we create a new lookup table which holds every node and we are not interested in any C++ specific visibility considerations. Simply, we must know if there is an existing Decl in a given DC. Reviewers: a_sidorin, a.sidorin Subscribers: mgorny, rnkovacs, dkrupp, Szelethus, cfe-commits Differential Revision: https://reviews.llvm.org/D53708 llvm-svn: 349351
1 parent 193429e commit 54058b5

File tree

9 files changed

+888
-124
lines changed

9 files changed

+888
-124
lines changed
 

Diff for: ‎clang/include/clang/AST/ASTImporter.h

+22-3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
namespace clang {
3434

3535
class ASTContext;
36+
class ASTImporterLookupTable;
3637
class CXXBaseSpecifier;
3738
class CXXCtorInitializer;
3839
class Decl;
@@ -80,12 +81,21 @@ class Attr;
8081
/// Imports selected nodes from one AST context into another context,
8182
/// merging AST nodes where appropriate.
8283
class ASTImporter {
84+
friend class ASTNodeImporter;
8385
public:
8486
using NonEquivalentDeclSet = llvm::DenseSet<std::pair<Decl *, Decl *>>;
8587
using ImportedCXXBaseSpecifierMap =
8688
llvm::DenseMap<const CXXBaseSpecifier *, CXXBaseSpecifier *>;
8789

8890
private:
91+
92+
/// Pointer to the import specific lookup table, which may be shared
93+
/// amongst several ASTImporter objects.
94+
/// This is an externally managed resource (and should exist during the
95+
/// lifetime of the ASTImporter object)
96+
/// If not set then the original C/C++ lookup is used.
97+
ASTImporterLookupTable *LookupTable = nullptr;
98+
8999
/// The contexts we're importing to and from.
90100
ASTContext &ToContext, &FromContext;
91101

@@ -123,9 +133,13 @@ class Attr;
123133
/// (which we have already complained about).
124134
NonEquivalentDeclSet NonEquivalentDecls;
125135

136+
using FoundDeclsTy = SmallVector<NamedDecl *, 2>;
137+
FoundDeclsTy findDeclsInToCtx(DeclContext *DC, DeclarationName Name);
138+
139+
void AddToLookupTable(Decl *ToD);
140+
126141
public:
127-
/// Create a new AST importer.
128-
///
142+
129143
/// \param ToContext The context we'll be importing into.
130144
///
131145
/// \param ToFileManager The file manager we'll be importing into.
@@ -137,9 +151,14 @@ class Attr;
137151
/// \param MinimalImport If true, the importer will attempt to import
138152
/// as little as it can, e.g., by importing declarations as forward
139153
/// declarations that can be completed at a later point.
154+
///
155+
/// \param LookupTable The importer specific lookup table which may be
156+
/// shared amongst several ASTImporter objects.
157+
/// If not set then the original C/C++ lookup is used.
140158
ASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
141159
ASTContext &FromContext, FileManager &FromFileManager,
142-
bool MinimalImport);
160+
bool MinimalImport,
161+
ASTImporterLookupTable *LookupTable = nullptr);
143162

144163
virtual ~ASTImporter();
145164

Diff for: ‎clang/include/clang/AST/ASTImporterLookupTable.h

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
//===- ASTImporterLookupTable.h - ASTImporter specific lookup--*- C++ -*---===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This file defines the ASTImporterLookupTable class which implements a
11+
// lookup procedure for the import mechanism.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef LLVM_CLANG_AST_ASTIMPORTERLOOKUPTABLE_H
16+
#define LLVM_CLANG_AST_ASTIMPORTERLOOKUPTABLE_H
17+
18+
#include "clang/AST/DeclBase.h" // lookup_result
19+
#include "clang/AST/DeclarationName.h"
20+
#include "llvm/ADT/DenseMap.h"
21+
#include "llvm/ADT/SetVector.h"
22+
23+
namespace clang {
24+
25+
class ASTContext;
26+
class NamedDecl;
27+
class DeclContext;
28+
29+
// There are certain cases when normal C/C++ lookup (localUncachedLookup)
30+
// does not find AST nodes. E.g.:
31+
// Example 1:
32+
// template <class T>
33+
// struct X {
34+
// friend void foo(); // this is never found in the DC of the TU.
35+
// };
36+
// Example 2:
37+
// // The fwd decl to Foo is not found in the lookupPtr of the DC of the
38+
// // translation unit decl.
39+
// // Here we could find the node by doing a traverse throught the list of
40+
// // the Decls in the DC, but that would not scale.
41+
// struct A { struct Foo *p; };
42+
// This is a severe problem because the importer decides if it has to create a
43+
// new Decl or not based on the lookup results.
44+
// To overcome these cases we need an importer specific lookup table which
45+
// holds every node and we are not interested in any C/C++ specific visibility
46+
// considerations. Simply, we must know if there is an existing Decl in a
47+
// given DC. Once we found it then we can handle any visibility related tasks.
48+
class ASTImporterLookupTable {
49+
50+
// We store a list of declarations for each name.
51+
// And we collect these lists for each DeclContext.
52+
// We could have a flat map with (DeclContext, Name) tuple as key, but a two
53+
// level map seems easier to handle.
54+
using DeclList = llvm::SmallSetVector<NamedDecl *, 2>;
55+
using NameMap = llvm::SmallDenseMap<DeclarationName, DeclList, 4>;
56+
using DCMap = llvm::DenseMap<DeclContext *, NameMap>;
57+
58+
void add(DeclContext *DC, NamedDecl *ND);
59+
void remove(DeclContext *DC, NamedDecl *ND);
60+
61+
DCMap LookupTable;
62+
63+
public:
64+
ASTImporterLookupTable(TranslationUnitDecl &TU);
65+
void add(NamedDecl *ND);
66+
void remove(NamedDecl *ND);
67+
using LookupResult = DeclList;
68+
LookupResult lookup(DeclContext *DC, DeclarationName Name) const;
69+
void dump(DeclContext *DC) const;
70+
void dump() const;
71+
};
72+
73+
} // namespace clang
74+
75+
#endif // LLVM_CLANG_AST_ASTIMPORTERLOOKUPTABLE_H

Diff for: ‎clang/include/clang/CrossTU/CrossTranslationUnit.h

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#ifndef LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H
1616
#define LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H
1717

18+
#include "clang/AST/ASTImporterLookupTable.h"
1819
#include "clang/Basic/LLVM.h"
1920
#include "llvm/ADT/DenseMap.h"
2021
#include "llvm/ADT/SmallPtrSet.h"
@@ -152,6 +153,7 @@ class CrossTranslationUnitContext {
152153
void emitCrossTUDiagnostics(const IndexError &IE);
153154

154155
private:
156+
void lazyInitLookupTable(TranslationUnitDecl *ToTU);
155157
ASTImporter &getOrCreateASTImporter(ASTContext &From);
156158
const FunctionDecl *findFunctionInDeclContext(const DeclContext *DC,
157159
StringRef LookupFnName);
@@ -163,6 +165,7 @@ class CrossTranslationUnitContext {
163165
ASTUnitImporterMap;
164166
CompilerInstance &CI;
165167
ASTContext &Context;
168+
std::unique_ptr<ASTImporterLookupTable> LookupTable;
166169
};
167170

168171
} // namespace cross_tu

0 commit comments

Comments
 (0)