Skip to content

Commit

Permalink
[cling] Treat operator overload as normal function. Do not wrap it.
Browse files Browse the repository at this point in the history
Fixes root-project#9449

so it is possible to define operator overload in cling cmd prompt.

btw, Make SkipPointerRefs() to not assume next token being a

tok::raw_identifier since it can be a global-scoped identifier,

e.g. int* ::class_a::func_b(short c) { return nullptr; }
  • Loading branch information
jiangyilism committed Aug 28, 2022
1 parent 3e1142e commit b34a511
Showing 1 changed file with 74 additions and 12 deletions.
86 changes: 74 additions & 12 deletions interpreter/cling/lib/Utils/SourceNormalization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,19 @@ namespace {
///\brief A Lexer that exposes preprocessor directives.
class MinimalPPLexer: public Lexer {

///\brief Jump to last Identifier in a scope chain A::B::C::D
///\brief Jump to the next token after a scope chain A::B::C::D
///
bool SkipScopes(Token& Tok) {
Token LastTok;
return SkipScopes(Tok, LastTok);
}

bool SkipScopes(Token& Tok, Token& LastTok) {
LastTok = Tok;

if (getLangOpts().CPlusPlus) {
while (Tok.is(tok::coloncolon)) {
if (!LexClean(Tok) || Identifier(Tok).empty())
if (!LexClean(LastTok) || Identifier(LastTok).empty())
return false;
if (!LexClean(Tok))
return false;
Expand All @@ -38,9 +45,7 @@ class MinimalPPLexer: public Lexer {
///\brief Skips all contiguous '*' '&' tokens
///
bool SkipPointerRefs(Token& Tok) {
while (Tok.isNot(tok::raw_identifier)) {
if (!Tok.isOneOf(tok::star, tok::amp))
return false;
while (Tok.isOneOf(tok::star, tok::amp)) {
if (!LexClean(Tok))
return false;
}
Expand Down Expand Up @@ -71,13 +76,54 @@ class MinimalPPLexer: public Lexer {
return false;
}

auto LastTok{Tok};
// skip scopes in function name
// e.g. int ::the_namespace::class_a::mem_func() { return 3; }
if (Tok.is(tok::coloncolon)) {
if (!SkipScopes(Tok, LastTok)) {
return false;
}
} else {
if (!LexClean(Tok)) {
return false;
}

if (Tok.is(tok::coloncolon)) {
if (!SkipScopes(Tok, LastTok)) {
return false;
}
}
}

const auto Ident{Identifier(LastTok)};

// Function or class name should be in Tok now
if (Identifier(Tok).empty())
if (Ident.empty()) {
return false;
}

// Advance to argument list or method name
if (!LexClean(Tok))
return false;
if (Ident.equals("operator")) {
// Tok is the operator, e.g. <=, ==, +...
// however, in case of operator() and [], Tok only contains the
// left side so we need to parse the closing right side
if (Tok.isOneOf(tok::l_paren, tok::l_square)) {
if (!CheckBalance(Tok)) {
return kNONE;
}
}

// user-defined literal, e.g. double operator "" _dd(char t)
if (Tok.is(tok::string_literal)) {
if (!LexClean(Tok)) {
return false;
}
}
// TODO: tok::spaceship operator<=>

// Advance to argument list or method name
if (!LexClean(Tok))
return false;
}

if (!SkipScopes(Tok))
return false;
Expand Down Expand Up @@ -225,7 +271,7 @@ class MinimalPPLexer: public Lexer {
return kNONE;

// Advance to argument list, or next scope
if (!LexClean(Tok))
if (!SkipIdentifier(Tok))
return kNONE;

// Function name should be last on scope chain
Expand Down Expand Up @@ -302,11 +348,27 @@ class MinimalPPLexer: public Lexer {
// 'int func() {' or 'CLASS::method() {'
if (Tok.is(tok::l_brace))
return kFunction;

if (getLangOpts().CPlusPlus) {
// constructor initialization 'CLASS::CLASS() :'
if (Ctor && Tok.is(tok::colon))
if (Ctor && Tok.is(tok::colon)) {
return !AdvanceTo(Tok, tok::l_brace) ? kFunction : kNONE;
}

if (Ctor || Dtor) {
// e.g. CLASS::CLASS() = default;
// ~CLASS::CLASS() = delete;
if (Tok.is(tok::equal)) {
if (!LexClean(Tok) && Tok.isNot(tok::raw_identifier)) {
return kNONE;
}

if (!LexClean(Tok) && Tok.isNot(tok::semi)) {
return kNONE;
}
DefinitionParsed = true;
return kFunction;
}
}

if (Ctor || Dtor) {
// e.g. CLASS::CLASS() = default;
Expand Down

0 comments on commit b34a511

Please sign in to comment.