llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> Clang will make the instance pointer be of type 'int' if it is invalid, which trips up later logic. Mark functions as invalid if any of their parameters is and compile + check them early in CallPtr. Fixes https://github.com/llvm/llvm-project/issues/175425 --- Full diff: https://github.com/llvm/llvm-project/pull/175511.diff 3 Files Affected: - (modified) clang/lib/AST/ByteCode/ByteCodeEmitter.cpp (+4-2) - (modified) clang/lib/AST/ByteCode/Interp.cpp (+9) - (modified) clang/test/AST/ByteCode/cxx23.cpp (+11-2) ``````````diff diff --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp index f430b2329a6f3..5dc6eca582ad9 100644 --- a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp +++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp @@ -54,12 +54,15 @@ void ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl, } } + bool IsValid = !FuncDecl->isInvalidDecl(); // Register parameters with their offset. unsigned ParamIndex = 0; unsigned Drop = Func->hasRVO() + (Func->hasThisPointer() && !Func->isThisPointerExplicit()); for (auto ParamOffset : llvm::drop_begin(Func->ParamOffsets, Drop)) { const ParmVarDecl *PD = FuncDecl->parameters()[ParamIndex]; + if (PD->isInvalidDecl()) + IsValid = false; OptPrimType T = Ctx.classify(PD->getType()); this->Params.insert({PD, {ParamOffset, T != std::nullopt}}); ++ParamIndex; @@ -86,8 +89,7 @@ void ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl, // Set the function's code. Func->setCode(FuncDecl, NextLocalOffset, std::move(Code), std::move(SrcMap), - std::move(Scopes), FuncDecl->hasBody(), - !FuncDecl->isInvalidDecl()); + std::move(Scopes), FuncDecl->hasBody(), IsValid); Func->setIsFullyCompiled(true); } diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index 7e901aa65af1c..b5a66ff6fbab3 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -1869,6 +1869,15 @@ bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize, return false; } + // We nedd to compile (and check) early for function pointer calls + // because the Call/CallVirt below might access the instance pointer + // but the Function's information about them is wrong. + if (!F->isFullyCompiled()) + compileFunction(S, F); + + if (!CheckCallable(S, OpPC, F)) + return false; + assert(ArgSize >= F->getWrittenArgSize()); uint32_t VarArgSize = ArgSize - F->getWrittenArgSize(); diff --git a/clang/test/AST/ByteCode/cxx23.cpp b/clang/test/AST/ByteCode/cxx23.cpp index 4b87f44d14345..eb35cd904c6db 100644 --- a/clang/test/AST/ByteCode/cxx23.cpp +++ b/clang/test/AST/ByteCode/cxx23.cpp @@ -1,8 +1,8 @@ // UNSUPPORTED: target={{.*}}-zos{{.*}} // RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -Wno-deprecated-volatile -verify=ref,ref20,all,all20 %s // RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -Wno-deprecated-volatile -verify=ref,ref23,all,all23 %s -// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -Wno-deprecated-volatile -verify=expected20,all,all20 %s -fexperimental-new-constant-interpreter -// RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -Wno-deprecated-volatile -verify=expected23,all,all23 %s -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -Wno-deprecated-volatile -verify=expected,expected20,all,all20 %s -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -Wno-deprecated-volatile -verify=expected,expected23,all,all23 %s -fexperimental-new-constant-interpreter #define assert_active(F) if (!__builtin_is_within_lifetime(&F)) (1/0); @@ -259,6 +259,15 @@ namespace ExplicitLambdaInstancePointer { constexpr int (*fp)(C) = b; static_assert(fp(1) == 1, ""); } + + /// Failure case. The instance pointer is of type int. + struct S2 { + constexpr K(auto) { } // all-error {{a type specifier is required for all declarations}} + }; + constexpr auto b = [](this K) { return 1; }; // all20-error {{explicit object parameters are incompatible with C++ standards before C++2b}} \ + // all-error {{unknown type name 'K'}} + constexpr int (*fp)(K) = b; // all-error {{unknown type name 'K'}} + static_assert(fp(1) == 1, ""); // expected-error {{not an integral constant expression}} } namespace TwosComplementShifts { `````````` </details> https://github.com/llvm/llvm-project/pull/175511 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
