Repository: dotnet/runtime
File: src/coreclr/vm/prestub.cpp (C++)

Code before:
    {
        Thread* thread = GetThreadNULLOk();
        if (thread == NULL)
            CREATETHREAD_IF_NULL_FAILFAST(thread, W("Failed to setup new thread during reverse P/Invoke"));

        // Verify the current thread isn't in COOP mode.
        if (thread->PreemptiveGCDisabled())
            ReversePInvokeBadTransition();

#ifdef PROFILING_SUPPORTED
        if (CORProfilerTrackTransitions())
        {
            methodDescToReportAsTransition = pInterpreterCode->Method->methodHnd;
#ifndef FEATURE_PORTABLE_ENTRYPOINTS
            void* thunkDataMaybe = nullptr;
            if (pInterpreterCode->Method->publishSecretStubParam)
                thunkDataMaybe = GetMostRecentUMEntryThunkDataNonDestructive();
            if (thunkDataMaybe != NULL)
            {
                methodDescToReportAsTransition = ((UMEntryThunkData*)thunkDataMaybe)->GetMethod();
            }
#endif // FEATURE_PORTABLE_ENTRYPOINTS
            ProfilerUnmanagedToManagedTransitionMD(methodDescToReportAsTransition, COR_PRF_TRANSITION_CALL);
        }
#endif
#ifdef DEBUGGING_SUPPORTED
        if (g_TrapReturningThreads && CORDebuggerTraceCall())
        {
            void* thunkDataMaybe = nullptr;
            if (pInterpreterCode->Method->publishSecretStubParam)
                thunkDataMaybe = GetMostRecentUMEntryThunkDataNonDestructive();

            DebuggerTraceCall((void*)pInterpreterCode->GetByteCodes(), thunkDataMaybe);
        }
#endif // DEBUGGING_SUPPORTED
    }

    void* retVal;
    {
        GCX_MAYBE_COOP(pInterpreterCode->Method->unmanagedCallersOnly);

        // This construct ensures that the InterpreterFrame is always stored at a higher address than the
        // InterpMethodContextFrame. This is important for the stack walking code.
        struct Frames
        {
            InterpMethodContextFrame interpMethodContextFrame = {0};
            InterpreterFrame interpreterFrame;

            Frames(TransitionBlock* pTransitionBlock)
            : interpreterFrame(pTransitionBlock, &interpMethodContextFrame)
            {

Review comment (bug):
There's another variable shadowing issue here. The variable `thunkDataMaybe` is declared at line 1949 in the outer scope, but is re-declared at line 1984 within the DEBUGGING_SUPPORTED block. The outer declaration at line 1949 should be used instead of re-declaring it.
```suggestion
            thunkDataMaybe = nullptr;
```

Code after:
            CREATETHREAD_IF_NULL_FAILFAST(thread, W("Failed to setup new thread during reverse P/Invoke"));

        // Verify the current thread isn't in COOP mode.
        if (thread->PreemptiveGCDisabled())
            ReversePInvokeBadTransition();

#ifdef PROFILING_SUPPORTED
        if (CORProfilerTrackTransitions())
        {
            methodDescToReportAsTransition = pInterpreterCode->Method->methodHnd;
#ifndef FEATURE_PORTABLE_ENTRYPOINTS
            void* thunkDataMaybe = nullptr;
            if (pInterpreterCode->Method->publishSecretStubParam)
                thunkDataMaybe = GetMostRecentUMEntryThunkDataNonDestructive();
            if (thunkDataMaybe != NULL)
            {
                methodDescToReportAsTransition = ((UMEntryThunkData*)thunkDataMaybe)->GetMethod();
            }
#endif // FEATURE_PORTABLE_ENTRYPOINTS
            ProfilerUnmanagedToManagedTransitionMD(methodDescToReportAsTransition, COR_PRF_TRANSITION_CALL);
        }
#endif
#ifdef DEBUGGING_SUPPORTED
        if (g_TrapReturningThreads && CORDebuggerTraceCall())
        {
            void* thunkDataMaybe = nullptr;
#ifndef FEATURE_PORTABLE_ENTRYPOINTS
            if (pInterpreterCode->Method->publishSecretStubParam)
                thunkDataMaybe = GetMostRecentUMEntryThunkDataNonDestructive();
#endif // FEATURE_PORTABLE_ENTRYPOINTS
            DebuggerTraceCall((void*)pInterpreterCode->GetByteCodes(), thunkDataMaybe);
        }
#endif // DEBUGGING_SUPPORTED
    }

    void* retVal;
    {
        GCX_MAYBE_COOP(pInterpreterCode->Method->unmanagedCallersOnly);

        // This construct ensures that the InterpreterFrame is always stored at a higher address than the
        // InterpMethodContextFrame. This is important for the stack walking code.
        struct Frames
        {
            InterpMethodContextFrame interpMethodContextFrame = {0};
            InterpreterFrame interpreterFrame;

            Frames(TransitionBlock* pTransitionBlock)
            : interpreterFrame(pTransitionBlock, &interpMethodContextFrame)
            {
            }
        }