Skip to content

Commit 253c28f

Browse files
authored
[clang-repl] Extend the C support. (#89804)
The IdResolver chain is the main way for C to implement lookup rules. Every new partial translation unit caused clang to exit the top-most scope which in turn cleaned up the IdResolver chain. That was not an issue for C++ because its lookup is implemented on the level of declaration contexts. This patch keeps the IdResolver chain across partial translation units maintaining proper C-style lookup infrastructure.
1 parent 98f105a commit 253c28f

File tree

3 files changed

+39
-5
lines changed

3 files changed

+39
-5
lines changed

clang/lib/Interpreter/IncrementalParser.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -387,8 +387,7 @@ std::unique_ptr<llvm::Module> IncrementalParser::GenModule() {
387387

388388
void IncrementalParser::CleanUpPTU(PartialTranslationUnit &PTU) {
389389
TranslationUnitDecl *MostRecentTU = PTU.TUPart;
390-
TranslationUnitDecl *FirstTU = MostRecentTU->getFirstDecl();
391-
if (StoredDeclsMap *Map = FirstTU->getPrimaryContext()->getLookupPtr()) {
390+
if (StoredDeclsMap *Map = MostRecentTU->getPrimaryContext()->getLookupPtr()) {
392391
for (auto &&[Key, List] : *Map) {
393392
DeclContextLookupResult R = List.getLookupResult();
394393
std::vector<NamedDecl *> NamedDeclsToRemove;
@@ -407,6 +406,16 @@ void IncrementalParser::CleanUpPTU(PartialTranslationUnit &PTU) {
407406
}
408407
}
409408
}
409+
410+
// FIXME: We should de-allocate MostRecentTU
411+
for (Decl *D : MostRecentTU->decls()) {
412+
auto *ND = dyn_cast<NamedDecl>(D);
413+
if (!ND)
414+
continue;
415+
// Check if we need to clean up the IdResolver chain.
416+
if (ND->getDeclName().getFETokenInfo())
417+
getCI()->getSema().IdResolver.RemoveDecl(ND);
418+
}
410419
}
411420

412421
llvm::StringRef IncrementalParser::GetMangledName(GlobalDecl GD) const {

clang/lib/Sema/SemaDecl.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2282,9 +2282,13 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
22822282
if (LabelDecl *LD = dyn_cast<LabelDecl>(D))
22832283
CheckPoppedLabel(LD, *this, addDiag);
22842284

2285-
// Remove this name from our lexical scope, and warn on it if we haven't
2286-
// already.
2287-
IdResolver.RemoveDecl(D);
2285+
// Partial translation units that are created in incremental processing must
2286+
// not clean up the IdResolver because PTUs should take into account the
2287+
// declarations that came from previous PTUs.
2288+
if (!PP.isIncrementalProcessingEnabled())
2289+
IdResolver.RemoveDecl(D);
2290+
2291+
// Warn on it if we are shadowing a declaration.
22882292
auto ShadowI = ShadowingDecls.find(D);
22892293
if (ShadowI != ShadowingDecls.end()) {
22902294
if (const auto *FD = dyn_cast<FieldDecl>(ShadowI->second)) {

clang/test/Interpreter/execute.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// REQUIRES: host-supports-jit
2+
// UNSUPPORTED: system-aix
3+
4+
// RUN: cat %s | clang-repl -Xcc -xc -Xcc -Xclang -Xcc -verify | FileCheck %s
5+
// RUN: cat %s | clang-repl -Xcc -xc -Xcc -O2 -Xcc -Xclang -Xcc -verify| FileCheck %s
6+
int printf(const char *, ...);
7+
int i = 42; err // expected-error{{use of undeclared identifier}}
8+
int i = 42;
9+
struct S { float f; struct S *m;} s = {1.0, 0};
10+
// FIXME: Making foo inline fails to emit the function.
11+
int foo() { return 42; }
12+
void run() { \
13+
printf("i = %d\n", i); \
14+
printf("S[f=%f, m=0x%llx]\n", s.f, (unsigned long long)s.m); \
15+
int r3 = foo(); \
16+
}
17+
run();
18+
// CHECK: i = 42
19+
// CHECK-NEXT: S[f=1.000000, m=0x0]
20+
21+
%quit

0 commit comments

Comments
 (0)