Skip to content

Commit

Permalink
[clang-repl] Extend the C support.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
vgvassilev committed May 20, 2024
1 parent 42070a5 commit 72d655c
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 5 deletions.
13 changes: 11 additions & 2 deletions clang/lib/Interpreter/IncrementalParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,7 @@ std::unique_ptr<llvm::Module> IncrementalParser::GenModule() {

void IncrementalParser::CleanUpPTU(PartialTranslationUnit &PTU) {
TranslationUnitDecl *MostRecentTU = PTU.TUPart;
TranslationUnitDecl *FirstTU = MostRecentTU->getFirstDecl();
if (StoredDeclsMap *Map = FirstTU->getPrimaryContext()->getLookupPtr()) {
if (StoredDeclsMap *Map = MostRecentTU->getPrimaryContext()->getLookupPtr()) {
for (auto &&[Key, List] : *Map) {
DeclContextLookupResult R = List.getLookupResult();
std::vector<NamedDecl *> NamedDeclsToRemove;
Expand All @@ -407,6 +406,16 @@ void IncrementalParser::CleanUpPTU(PartialTranslationUnit &PTU) {
}
}
}

// FIXME: We should de-allocate MostRecentTU
for (Decl *D : MostRecentTU->decls()) {
auto *ND = dyn_cast<NamedDecl>(D);
if (!ND)
continue;
// Check if we need to clean up the IdResolver chain.
if (ND->getDeclName().getFETokenInfo())
getCI()->getSema().IdResolver.RemoveDecl(ND);
}
}

llvm::StringRef IncrementalParser::GetMangledName(GlobalDecl GD) const {
Expand Down
10 changes: 7 additions & 3 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2280,9 +2280,13 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
if (LabelDecl *LD = dyn_cast<LabelDecl>(D))
CheckPoppedLabel(LD, *this, addDiag);

// Remove this name from our lexical scope, and warn on it if we haven't
// already.
IdResolver.RemoveDecl(D);
// Partial translation units that are created in incremental processing must
// not clean up the IdResolver because PTUs should take into account the
// declarations that came from previous PTUs.
if (!PP.isIncrementalProcessingEnabled())
IdResolver.RemoveDecl(D);

// Warn on it if we are shadowing a declaration.
auto ShadowI = ShadowingDecls.find(D);
if (ShadowI != ShadowingDecls.end()) {
if (const auto *FD = dyn_cast<FieldDecl>(ShadowI->second)) {
Expand Down
21 changes: 21 additions & 0 deletions clang/test/Interpreter/execute.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// REQUIRES: host-supports-jit
// UNSUPPORTED: system-aix

// RUN: cat %s | clang-repl -Xcc -xc -Xcc -Xclang -Xcc -verify | FileCheck %s
// RUN: cat %s | clang-repl -Xcc -xc -Xcc -O2 -Xcc -Xclang -Xcc -verify| FileCheck %s
int printf(const char *, ...);
int i = 42; err // expected-error{{use of undeclared identifier}}
int i = 42;
struct S { float f; struct S *m;} s = {1.0, 0};
// FIXME: Making foo inline fails to emit the function.
int foo() { return 42; }
void run() { \
printf("i = %d\n", i); \
printf("S[f=%f, m=0x%llx]\n", s.f, (unsigned long long)s.m); \
int r3 = foo(); \
}
run();
// CHECK: i = 42
// CHECK-NEXT: S[f=1.000000, m=0x0]

%quit

0 comments on commit 72d655c

Please sign in to comment.