Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion core/metacling/src/ClingRAII.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,24 @@ namespace ROOT {
decltype(clang::Sema::MaybeODRUseExprs) fMaybeODRUseExprs;
decltype(clang::Sema::FunctionScopes) fFunctionScopes;
decltype(clang::Sema::UndefinedButUsed) fUndefinedButUsed;
// The start indices into FunctionScopes and InventedParameterInfos must
// follow the swap: when we are called during a template instantiation,
// Sema::ContextRAII has set them to the depth of the outer stack, which
// is past the end of our fresh FunctionScopes.
decltype(clang::Sema::FunctionScopesStart) fFunctionScopesStart = 0;
decltype(clang::Sema::InventedParameterInfosStart) fInventedParameterInfosStart; // Set by the constructor to the size of Sema::InventedParameterInfos
clang::Sema& fSema;
void Swapem() {
std::swap(fCleanup, fSema.Cleanup);
std::swap(fExprCleanupObjects, fSema.ExprCleanupObjects);
std::swap(fMaybeODRUseExprs, fSema.MaybeODRUseExprs);
std::swap(fFunctionScopes, fSema.FunctionScopes);
std::swap(fFunctionScopesStart, fSema.FunctionScopesStart);
std::swap(fInventedParameterInfosStart, fSema.InventedParameterInfosStart);
std::swap(fUndefinedButUsed, fSema.UndefinedButUsed);
}
SemaExprCleanupsRAII(clang::Sema& S): fSema(S) {
SemaExprCleanupsRAII(clang::Sema& S):
fInventedParameterInfosStart(S.InventedParameterInfos.size()), fSema(S) {
fFunctionScopes.push_back(new clang::sema::FunctionScopeInfo(S.Diags));
Swapem();
};
Expand Down
11 changes: 11 additions & 0 deletions roottest/root/meta/autoloading/nestedAutoParse/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
ROOTTEST_GENERATE_REFLEX_DICTIONARY(nestedAutoParse
nestedAutoParse.h
SELECTION selection.xml
LIBNAME libnestedAutoParse_dictrflx
NO_ROOTMAP
FIXTURES_SETUP root-meta-autoloading-nestedAutoParse-fixture)

ROOTTEST_ADD_TEST(nestedAutoParse
MACRO execNestedAutoParse.C
COPY_TO_BUILDDIR useNestedAutoParse.C
FIXTURES_REQUIRED root-meta-autoloading-nestedAutoParse-fixture)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Autoparsing a payload from within a template instantiation used to crash in
// Sema::EnterTemplatedContext, because the nested parse saw the function scopes
// of the outer instantiation (Sema::FunctionScopesStart was not reset).
int execNestedAutoParse()
{
// Registers only the forward declaration of Payload; its definition is
// parsed on demand.
if (gSystem->Load("libnestedAutoParse_dictrflx") < 0)
return 1;
// Use ProcessLine rather than TInterpreter::Declare: Declare suspends
// autoparsing.
if (gROOT->ProcessLine(".L useNestedAutoParse.C") != 0)
return 2;
return gROOT->ProcessLine("useNestedAutoParse();") == 42 ? 0 : 3;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef ROOTTEST_NESTEDAUTOPARSE_H
#define ROOTTEST_NESTEDAUTOPARSE_H

namespace NestedAutoParse {
namespace Inner {

// Declaring a class template while parsing the payload calls
// Sema::EnterTemplatedContext, which walks Sema's function scopes.
template <int N>
struct Tmpl {
static constexpr int value = N;
};

struct Payload {
int fValue = 42;
int get() const { return fValue + Tmpl<0>::value; }
};

} // namespace Inner
} // namespace NestedAutoParse

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<lcgdict>
<class name="NestedAutoParse::Inner::Payload" />
</lcgdict>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include <vector>

int useNestedAutoParse()
{
// Payload is only forward declared here. Instantiating the members of
// std::vector<Payload> needs the complete type, so its payload is
// autoparsed from within a template instantiation.
std::vector<NestedAutoParse::Inner::Payload> v(1);
return v[0].get();
}
Loading