llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Vassil Vassilev (vgvassilev) <details> <summary>Changes</summary> Depends on #<!-- -->89804. --- Full diff: https://github.com/llvm/llvm-project/pull/89811.diff 6 Files Affected: - (modified) clang/lib/Interpreter/IncrementalParser.cpp (+11-2) - (modified) clang/lib/Interpreter/Interpreter.cpp (+92-76) - (modified) clang/lib/Parse/ParseStmt.cpp (+1-4) - (modified) clang/lib/Sema/SemaDecl.cpp (+2-1) - (added) clang/test/Interpreter/execute.c (+21) - (added) clang/test/Interpreter/pretty-print.c (+8) ``````````diff diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp index ef90fe9e6f5451..f1cb5fc870eb94 100644 --- a/clang/lib/Interpreter/IncrementalParser.cpp +++ b/clang/lib/Interpreter/IncrementalParser.cpp @@ -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; @@ -407,6 +406,16 @@ void IncrementalParser::CleanUpPTU(PartialTranslationUnit &PTU) { } } } + + // FIXME: We should de-allocate MostRecentTU + for (Decl *D : MostRecentTU->decls()) { + if (!isa<NamedDecl>(D)) + continue; + // Check if we need to clean up the IdResolver chain. + NamedDecl *ND = cast<NamedDecl>(D); + if (ND->getDeclName().getFETokenInfo()) + getCI()->getSema().IdResolver.RemoveDecl(ND); + } } llvm::StringRef IncrementalParser::GetMangledName(GlobalDecl GD) const { diff --git a/clang/lib/Interpreter/Interpreter.cpp b/clang/lib/Interpreter/Interpreter.cpp index b20e6efcebfd10..96abf4bc53ef4b 100644 --- a/clang/lib/Interpreter/Interpreter.cpp +++ b/clang/lib/Interpreter/Interpreter.cpp @@ -42,6 +42,9 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Host.h" + +#include <stdarg.h> + using namespace clang; // FIXME: Figure out how to unify with namespace init_convenience from @@ -250,14 +253,9 @@ Interpreter::~Interpreter() { // can't find the precise resource directory in unittests so we have to hard // code them. const char *const Runtimes = R"( + #define __CLANG_REPL__ 1 #ifdef __cplusplus void *__clang_Interpreter_SetValueWithAlloc(void*, void*, void*); - void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*); - void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, void*); - void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, float); - void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, double); - void __clang_Interpreter_SetValueNoAlloc(void*, void*, void*, long double); - void __clang_Interpreter_SetValueNoAlloc(void*,void*,void*,unsigned long long); struct __clang_Interpreter_NewTag{} __ci_newtag; void* operator new(__SIZE_TYPE__, void* __p, __clang_Interpreter_NewTag) noexcept; template <class T, class = T (*)() /*disable for arrays*/> @@ -269,7 +267,10 @@ const char *const Runtimes = R"( void __clang_Interpreter_SetValueCopyArr(const T (*Src)[N], void* Placement, unsigned long Size) { __clang_Interpreter_SetValueCopyArr(Src[0], Placement, Size); } + extern "C" #endif // __cplusplus + + void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, ...); )"; llvm::Expected<std::unique_ptr<Interpreter>> @@ -564,15 +565,17 @@ std::unique_ptr<RuntimeInterfaceBuilder> Interpreter::FindRuntimeInterface() { if (!LookupInterface(ValuePrintingInfo[NoAlloc], MagicRuntimeInterface[NoAlloc])) return nullptr; - if (!LookupInterface(ValuePrintingInfo[WithAlloc], - MagicRuntimeInterface[WithAlloc])) - return nullptr; - if (!LookupInterface(ValuePrintingInfo[CopyArray], - MagicRuntimeInterface[CopyArray])) - return nullptr; - if (!LookupInterface(ValuePrintingInfo[NewTag], - MagicRuntimeInterface[NewTag])) - return nullptr; + if (Ctx.getLangOpts().CPlusPlus) { + if (!LookupInterface(ValuePrintingInfo[WithAlloc], + MagicRuntimeInterface[WithAlloc])) + return nullptr; + if (!LookupInterface(ValuePrintingInfo[CopyArray], + MagicRuntimeInterface[CopyArray])) + return nullptr; + if (!LookupInterface(ValuePrintingInfo[NewTag], + MagicRuntimeInterface[NewTag])) + return nullptr; + } return createInProcessRuntimeInterfaceBuilder(*this, Ctx, S); } @@ -831,69 +834,82 @@ __clang_Interpreter_SetValueWithAlloc(void *This, void *OutVal, return VRef.getPtr(); } -// Pointers, lvalue struct that can take as a reference. -REPL_EXTERNAL_VISIBILITY void -__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, - void *Val) { - Value &VRef = *(Value *)OutVal; - VRef = Value(static_cast<Interpreter *>(This), OpaqueType); - VRef.setPtr(Val); -} - -REPL_EXTERNAL_VISIBILITY void -__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, - void *OpaqueType) { +REPL_EXTERNAL_VISIBILITY +extern "C" void __clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, + void *OpaqueType, ...) { Value &VRef = *(Value *)OutVal; - VRef = Value(static_cast<Interpreter *>(This), OpaqueType); -} - -static void SetValueDataBasedOnQualType(Value &V, unsigned long long Data) { - QualType QT = V.getType(); - if (const auto *ET = QT->getAs<EnumType>()) - QT = ET->getDecl()->getIntegerType(); - - switch (QT->castAs<BuiltinType>()->getKind()) { - default: - llvm_unreachable("unknown type kind!"); -#define X(type, name) \ - case BuiltinType::name: \ - V.set##name(Data); \ - break; - REPL_BUILTIN_TYPES -#undef X + Interpreter *I = static_cast<Interpreter *>(This); + VRef = Value(I, OpaqueType); + if (VRef.isVoid()) + return; + + va_list args; + va_start(args, /*last named param*/ OpaqueType); + + QualType QT = VRef.getType(); + if (VRef.getKind() == Value::K_PtrOrObj) { + VRef.setPtr(va_arg(args, void *)); + } else { + if (const auto *ET = QT->getAs<EnumType>()) + QT = ET->getDecl()->getIntegerType(); + switch (QT->castAs<BuiltinType>()->getKind()) { + default: + llvm_unreachable("unknown type kind!"); + break; + // Types shorter than int are resolved as int, else va_arg has UB. + case BuiltinType::Bool: + VRef.setBool(va_arg(args, int)); + break; + case BuiltinType::Char_S: + VRef.setChar_S(va_arg(args, int)); + break; + case BuiltinType::SChar: + VRef.setSChar(va_arg(args, int)); + break; + case BuiltinType::Char_U: + VRef.setChar_U(va_arg(args, unsigned)); + break; + case BuiltinType::UChar: + VRef.setUChar(va_arg(args, unsigned)); + break; + case BuiltinType::Short: + VRef.setShort(va_arg(args, int)); + break; + case BuiltinType::UShort: + VRef.setUShort(va_arg(args, unsigned)); + break; + case BuiltinType::Int: + VRef.setInt(va_arg(args, int)); + break; + case BuiltinType::UInt: + VRef.setUInt(va_arg(args, unsigned)); + break; + case BuiltinType::Long: + VRef.setLong(va_arg(args, long)); + break; + case BuiltinType::ULong: + VRef.setULong(va_arg(args, unsigned long)); + break; + case BuiltinType::LongLong: + VRef.setLongLong(va_arg(args, long long)); + break; + case BuiltinType::ULongLong: + VRef.setULongLong(va_arg(args, unsigned long long)); + break; + // Types shorter than double are resolved as double, else va_arg has UB. + case BuiltinType::Float: + VRef.setFloat(va_arg(args, double)); + break; + case BuiltinType::Double: + VRef.setDouble(va_arg(args, double)); + break; + case BuiltinType::LongDouble: + VRef.setLongDouble(va_arg(args, long double)); + break; + // See REPL_BUILTIN_TYPES. + } } -} - -REPL_EXTERNAL_VISIBILITY void -__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, - unsigned long long Val) { - Value &VRef = *(Value *)OutVal; - VRef = Value(static_cast<Interpreter *>(This), OpaqueType); - SetValueDataBasedOnQualType(VRef, Val); -} - -REPL_EXTERNAL_VISIBILITY void -__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, - float Val) { - Value &VRef = *(Value *)OutVal; - VRef = Value(static_cast<Interpreter *>(This), OpaqueType); - VRef.setFloat(Val); -} - -REPL_EXTERNAL_VISIBILITY void -__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, - double Val) { - Value &VRef = *(Value *)OutVal; - VRef = Value(static_cast<Interpreter *>(This), OpaqueType); - VRef.setDouble(Val); -} - -REPL_EXTERNAL_VISIBILITY void -__clang_Interpreter_SetValueNoAlloc(void *This, void *OutVal, void *OpaqueType, - long double Val) { - Value &VRef = *(Value *)OutVal; - VRef = Value(static_cast<Interpreter *>(This), OpaqueType); - VRef.setLongDouble(Val); + va_end(args); } // A trampoline to work around the fact that operator placement new cannot diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 629421c01d17d2..63bc83c1cfd506 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -560,11 +560,8 @@ StmtResult Parser::ParseExprStatement(ParsedStmtContext StmtCtx) { } Token *CurTok = nullptr; - // If the semicolon is missing at the end of REPL input, consider if - // we want to do value printing. Note this is only enabled in C++ mode - // since part of the implementation requires C++ language features. // Note we shouldn't eat the token since the callback needs it. - if (Tok.is(tok::annot_repl_input_end) && Actions.getLangOpts().CPlusPlus) + if (Tok.is(tok::annot_repl_input_end)) CurTok = &Tok; else // Otherwise, eat the semicolon. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 452e00fa32b102..2a0f73b42d3088 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2282,7 +2282,8 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { // Remove this name from our lexical scope, and warn on it if we haven't // already. - IdResolver.RemoveDecl(D); + if (!PP.isIncrementalProcessingEnabled()) + IdResolver.RemoveDecl(D); auto ShadowI = ShadowingDecls.find(D); if (ShadowI != ShadowingDecls.end()) { if (const auto *FD = dyn_cast<FieldDecl>(ShadowI->second)) { diff --git a/clang/test/Interpreter/execute.c b/clang/test/Interpreter/execute.c new file mode 100644 index 00000000000000..44a3a32c930112 --- /dev/null +++ b/clang/test/Interpreter/execute.c @@ -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 diff --git a/clang/test/Interpreter/pretty-print.c b/clang/test/Interpreter/pretty-print.c new file mode 100644 index 00000000000000..f6158ad4ecc99c --- /dev/null +++ b/clang/test/Interpreter/pretty-print.c @@ -0,0 +1,8 @@ +// REQUIRES: host-supports-jit +// UNSUPPORTED: system-aix +// RUN: cat %s | clang-repl -Xcc -xc | FileCheck %s +// RUN: cat %s | clang-repl -Xcc -std=c++11 | FileCheck %s + +const char* c_str = "Hello, world!"; c_str + +// CHECK: Not implement yet. `````````` </details> https://github.com/llvm/llvm-project/pull/89811 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits