Skip to content

Commit bc35ad3

Browse files
committed
Refactor ASTNodes who have both a Symbol and name into common base class ASTnamed_symbol.
1 parent 020214b commit bc35ad3

7 files changed

Lines changed: 234 additions & 85 deletions

File tree

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,9 @@ TESTSUITE ( aastep allowconnect-err and-or-not-synonyms arithmetic
271271
oslc-comma oslc-D
272272
oslc-err-arrayindex oslc-err-closuremul oslc-err-field
273273
oslc-err-format oslc-err-funcoverload
274-
oslc-err-intoverflow oslc-err-noreturn oslc-err-notfunc
274+
oslc-err-intoverflow
275275
oslc-err-initlist-args oslc-err-initlist-return
276+
oslc-err-names oslc-err-noreturn oslc-err-notfunc
276277
oslc-err-outputparamvararray oslc-err-paramdefault
277278
oslc-err-struct-array-init oslc-err-struct-ctr
278279
oslc-err-struct-dup oslc-err-struct-print

src/liboslcomp/ast.cpp

Lines changed: 120 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,109 @@ ASTNode::list_to_types_string (const ASTNode *node)
291291

292292

293293

294+
ASTnamed_symbol::ASTnamed_symbol (NodeType node_type, OSLCompilerImpl *comp,
295+
ustring name)
296+
: ASTNode (node_type, comp, Nothing), m_name(name), m_sym(nullptr)
297+
{
298+
}
299+
300+
301+
302+
ASTnamed_symbol::ASTnamed_symbol (NodeType node_type, OSLCompilerImpl *comp,
303+
ustring name, ASTNode *a)
304+
: ASTNode (node_type, comp, Nothing, a), m_name(name), m_sym(nullptr)
305+
{
306+
}
307+
308+
309+
310+
ASTnamed_symbol::ASTnamed_symbol (NodeType node_type, OSLCompilerImpl *comp,
311+
ustring name, ASTNode *a, ASTNode *b)
312+
: ASTNode (node_type, comp, Nothing, a, b), m_name(name), m_sym(nullptr)
313+
{
314+
}
315+
316+
317+
318+
ASTnamed_symbol::ASTnamed_symbol (NodeType node_type, OSLCompilerImpl *comp,
319+
ustring name, ASTNode *a, ASTNode *b,
320+
ASTNode *c)
321+
: ASTNode (node_type, comp, Nothing, a, b, c), m_name(name), m_sym(nullptr)
322+
{
323+
}
324+
325+
326+
327+
void
328+
ASTnamed_symbol::check_reserved (ustring name, OSLCompilerImpl *comp)
329+
{
330+
if (Strutil::starts_with(name, "___")) {
331+
comp->error (comp->filename(), comp->lineno(),
332+
"'%s' : sorry, can't start with three underscores",
333+
name);
334+
}
335+
}
336+
337+
338+
339+
std::string
340+
ASTnamed_symbol::previous_decl (ASTNode* node)
341+
{
342+
if (! node)
343+
return "";
344+
345+
return Strutil::format ("\n\t\tprevious declaration was at %s:%d",
346+
OIIO::Filesystem::filename(node->sourcefile().string()),
347+
node->sourceline());
348+
}
349+
350+
351+
352+
Symbol*
353+
ASTnamed_symbol::validate (ustring name, OSLCompilerImpl *comp,
354+
Validation vflags, int allowed)
355+
{
356+
check_reserved (name, comp);
357+
358+
Symbol *f;
359+
bool shadow = vflags & warn_shadow;
360+
if (! (vflags & check_clashes)) {
361+
f = comp->symtab().find (name);
362+
if (! f) {
363+
comp->error (comp->filename(), comp->lineno(),
364+
"'%s' was not declared in this scope", name);
365+
// FIXME -- would be fun to troll through the symtab and try to
366+
// find the things that almost matched and offer suggestions.
367+
}
368+
else if (shadow && f->symtype() == SymTypeFunction) {
369+
comp->error (comp->filename(), comp->lineno(),
370+
"function '%s' can't be used as a variable", name);
371+
}
372+
} else {
373+
f = comp->symtab().clash (name);
374+
// If no symbol, or symbol matches allowed type: no clash.
375+
if (! f || f->symtype() == allowed)
376+
return f;
377+
378+
std::string e = Strutil::format ("'%s' already declared in this scope",
379+
name);
380+
e += previous_decl (f->node());
381+
382+
if (shadow) {
383+
// special case: only a warning for param to mask global function
384+
shadow = f->scope() == 0 && f->symtype() == SymTypeFunction;
385+
}
386+
387+
if (shadow)
388+
comp->warning(comp->filename(), comp->lineno(), "%s", e);
389+
else
390+
comp->error(comp->filename(), comp->lineno(), "%s", e);
391+
}
392+
return f;
393+
}
394+
395+
396+
294397
ASTshader_declaration::ASTshader_declaration (OSLCompilerImpl *comp,
295398
int stype, ustring name, ASTNode *form,
296399
ASTNode *stmts, ASTNode *meta)
@@ -346,20 +449,17 @@ ASTfunction_declaration::ASTfunction_declaration (OSLCompilerImpl *comp,
346449
TypeSpec type, ustring name,
347450
ASTNode *form, ASTNode *stmts, ASTNode *meta,
348451
int sourceline_start)
349-
: ASTNode (function_declaration_node, comp, 0, meta, form, stmts),
350-
m_name(name), m_sym(NULL), m_is_builtin(false)
452+
: ASTnamed_symbol (function_declaration_node, comp, name, meta, form, stmts),
453+
m_is_builtin(false)
351454
{
352455
// Some trickery -- the compiler's idea of the "current" source line
353456
// is the END of the function body, so if a hint was passed about the
354457
// start of the declaration, substitute that.
355458
if (sourceline_start >= 0)
356459
m_sourceline = sourceline_start;
357460

358-
if (Strutil::starts_with (name, "___"))
359-
error ("\"%s\" : sorry, can't start with three underscores", name);
360-
361461
// Get a pointer to the first of the existing symbols of that name.
362-
Symbol *existing_syms = comp->symtab().clash (name);
462+
Symbol *existing_syms = validate (check_clashes, SymTypeFunction);
363463
if (existing_syms && existing_syms->symtype() != SymTypeFunction) {
364464
error ("\"%s\" already declared in this scope as a %s",
365465
name, existing_syms->typespec());
@@ -493,8 +593,7 @@ ASTvariable_declaration::ASTvariable_declaration (OSLCompilerImpl *comp,
493593
ustring name, ASTNode *init,
494594
bool isparam, bool ismeta,
495595
bool isoutput, bool initlist)
496-
: ASTNode (variable_declaration_node, comp, 0, init, NULL /* meta */),
497-
m_name(name), m_sym(NULL),
596+
: ASTnamed_symbol (variable_declaration_node, comp, name, init, NULL /* meta */),
498597
m_isparam(isparam), m_isoutput(isoutput), m_ismetadata(ismeta),
499598
m_initlist(initlist)
500599
{
@@ -505,25 +604,11 @@ ASTvariable_declaration::ASTvariable_declaration (OSLCompilerImpl *comp,
505604
}
506605

507606
m_typespec = type;
508-
Symbol *f = comp->symtab().clash (name);
509-
if (f && ! m_ismetadata) {
510-
std::string e = Strutil::format ("\"%s\" already declared in this scope", name.c_str());
511-
if (f->node()) {
512-
std::string filename = OIIO::Filesystem::filename(f->node()->sourcefile().string());
513-
e += Strutil::format ("\n\t\tprevious declaration was at %s:%d",
514-
filename, f->node()->sourceline());
515-
}
516-
if (f->scope() == 0 && f->symtype() == SymTypeFunction && isparam) {
517-
// special case: only a warning for param to mask global function
518-
warning ("%s", e.c_str());
519-
} else {
520-
error ("%s", e.c_str());
521-
}
522-
}
523-
if (name[0] == '_' && name[1] == '_' && name[2] == '_') {
524-
error ("\"%s\" : sorry, can't start with three underscores",
525-
name.c_str());
526-
}
607+
if (! m_ismetadata)
608+
validate (warn_function_clash);
609+
else
610+
check_reserved ();
611+
527612
SymType symtype = isparam ? (isoutput ? SymTypeOutputParam : SymTypeParam)
528613
: SymTypeLocal;
529614
// Sneaky debugging aid: a local that starts with "__debug_tmp__"
@@ -584,20 +669,11 @@ ASTvariable_declaration::print (std::ostream &out, int indentlevel) const
584669

585670

586671
ASTvariable_ref::ASTvariable_ref (OSLCompilerImpl *comp, ustring name)
587-
: ASTNode (variable_ref_node, comp), m_name(name), m_sym(NULL)
672+
: ASTnamed_symbol (variable_ref_node, comp, name)
588673
{
589-
m_sym = comp->symtab().find (name);
590-
if (! m_sym) {
591-
error ("'%s' was not declared in this scope", name.c_str());
592-
// FIXME -- would be fun to troll through the symtab and try to
593-
// find the things that almost matched and offer suggestions.
594-
return;
595-
}
596-
if (m_sym->symtype() == SymTypeFunction) {
597-
error ("function '%s' can't be used as a variable", name.c_str());
598-
return;
599-
}
600-
m_typespec = m_sym->typespec();
674+
m_sym = validate (warn_function_exists);
675+
if (m_sym)
676+
m_typespec = m_sym->typespec();
601677
}
602678

603679

@@ -1111,25 +1187,18 @@ ASTtype_constructor::childname (size_t i) const
11111187

11121188
ASTfunction_call::ASTfunction_call (OSLCompilerImpl *comp, ustring name,
11131189
ASTNode *args, FunctionSymbol *funcsym)
1114-
: ASTNode (function_call_node, comp, 0, args), m_name(name),
1115-
m_sym(funcsym ? funcsym : comp->symtab().find (name)), // Look it up.
1190+
: ASTnamed_symbol (function_call_node, comp, name, args),
11161191
m_poly(funcsym), // Default - resolved symbol or null
11171192
m_argread(~1), // Default - all args are read except the first
11181193
m_argwrite(1), // Default - first arg only is written by the op
11191194
m_argtakesderivs(0) // Default - doesn't take derivs
11201195
{
1121-
if (! m_sym) {
1122-
error ("function '%s' was not declared in this scope", name);
1123-
// FIXME -- would be fun to troll through the symtab and try to
1124-
// find the things that almost matched and offer suggestions.
1196+
m_sym = funcsym ? funcsym : validate (err_must_exist); // Look it up.
1197+
if (! m_sym || is_struct_ctr())
11251198
return;
1126-
}
1127-
if (is_struct_ctr()) {
1128-
return; // It's a struct constructor
1129-
}
11301199
if (m_sym->symtype() != SymTypeFunction) {
11311200
error ("'%s' is not a function", name.c_str());
1132-
m_sym = NULL;
1201+
m_sym = nullptr;
11331202
return;
11341203
}
11351204
}

src/liboslcomp/ast.h

Lines changed: 59 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,60 @@ class ASTNode : public OIIO::RefCnt {
392392
};
393393

394394

395+
// Base class for any ASTNode that holds a name and Symbol that allows for
396+
// common error handling of using reserved or clashing names.
397+
class ASTnamed_symbol : public ASTNode
398+
{
399+
public:
400+
ASTnamed_symbol (NodeType node_type, OSLCompilerImpl *comp, ustring name);
401+
402+
ASTnamed_symbol (NodeType node_type, OSLCompilerImpl *comp, ustring name,
403+
ASTNode *a);
404+
405+
ASTnamed_symbol (NodeType node_type, OSLCompilerImpl *comp, ustring name,
406+
ASTNode *a, ASTNode *b);
407+
408+
ASTnamed_symbol (NodeType node_type, OSLCompilerImpl *comp, ustring name,
409+
ASTNode *a, ASTNode *b, ASTNode *c);
410+
411+
Symbol *sym () const { return m_sym; }
412+
ustring name () const { return m_name; }
413+
std::string mangled () const { ASSERT (m_sym); return m_sym->mangled(); }
414+
415+
enum Validation {
416+
err_must_exist = 0, ///< Error when the named Symbol does not exist.
417+
check_clashes = 1, ///< If named Symbol exists error as a clash.
418+
warn_shadow = 2, ///< Warn if name shadows a known function.
419+
420+
/// Convenient aliases of validation schemes.
421+
warn_function_exists = err_must_exist | warn_shadow,
422+
warn_function_clash = check_clashes | warn_shadow,
423+
};
424+
425+
/// Validate that m_name is a legal name.
426+
static void check_reserved (ustring name, OSLCompilerImpl *comp);
427+
428+
/// Validate that m_name is a legal name, and doesn't conflict with rules
429+
/// given in vflags allowing duplicate symbol if its SymType matches allowed.
430+
static Symbol* validate (ustring name, OSLCompilerImpl *comp,
431+
Validation vflags, int allowed = -1);
432+
433+
protected:
434+
void check_reserved () {
435+
ASTnamed_symbol::check_reserved (m_name, m_compiler);
436+
}
437+
438+
Symbol* validate (Validation vflags, int allowed = -1) {
439+
return validate (m_name, m_compiler, vflags, allowed);
440+
}
441+
442+
static std::string previous_decl (ASTNode* node);
443+
444+
ustring m_name; ///< Name of the symbol (unmangled)
445+
Symbol *m_sym; ///< Ptr to the symbol this declares
446+
};
447+
448+
395449

396450
class ASTshader_declaration : public ASTNode
397451
{
@@ -416,7 +470,7 @@ class ASTshader_declaration : public ASTNode
416470

417471

418472

419-
class ASTfunction_declaration : public ASTNode
473+
class ASTfunction_declaration : public ASTnamed_symbol
420474
{
421475
public:
422476
ASTfunction_declaration (OSLCompilerImpl *comp, TypeSpec type, ustring name,
@@ -439,14 +493,12 @@ class ASTfunction_declaration : public ASTNode
439493
void add_meta (ref meta);
440494

441495
private:
442-
ustring m_name;
443-
Symbol *m_sym;
444496
bool m_is_builtin;
445497
};
446498

447499

448500

449-
class ASTvariable_declaration : public ASTNode
501+
class ASTvariable_declaration : public ASTnamed_symbol
450502
{
451503
public:
452504
ASTvariable_declaration (OSLCompilerImpl *comp, const TypeSpec &type,
@@ -468,9 +520,6 @@ class ASTvariable_declaration : public ASTNode
468520
m_children[1] = meta; // beware changing the order!
469521
}
470522

471-
Symbol *sym () const { return m_sym; }
472-
ustring name () const { return m_name; }
473-
474523
bool is_output () const { return m_isoutput; }
475524

476525
/// For shader params, generate the string that gives the
@@ -487,8 +536,6 @@ class ASTvariable_declaration : public ASTNode
487536
}
488537

489538
private:
490-
ustring m_name; ///< Name of the symbol (unmangled)
491-
Symbol *m_sym; ///< Ptr to the symbol this declares
492539
bool m_isparam; ///< Is this a parameter?
493540
bool m_isoutput; ///< Is this an output parameter?
494541
bool m_ismetadata; ///< Is this declaration a piece of metadata?
@@ -501,7 +548,7 @@ class ASTvariable_declaration : public ASTNode
501548

502549

503550

504-
class ASTvariable_ref : public ASTNode
551+
class ASTvariable_ref : public ASTnamed_symbol
505552
{
506553
public:
507554
ASTvariable_ref (OSLCompilerImpl *comp, ustring name);
@@ -510,12 +557,6 @@ class ASTvariable_ref : public ASTNode
510557
void print (std::ostream &out, int indentlevel=0) const;
511558
TypeSpec typecheck (TypeSpec expected);
512559
Symbol *codegen (Symbol *dest = NULL);
513-
ustring name () const { return m_name; }
514-
std::string mangled () const { return m_sym->mangled(); }
515-
Symbol *sym () const { return m_sym; }
516-
private:
517-
ustring m_name;
518-
Symbol *m_sym;
519560
};
520561

521562

@@ -882,7 +923,8 @@ class ASTtypecast_expression : public ASTNode
882923

883924

884925

885-
class ASTfunction_call : public ASTNode
926+
927+
class ASTfunction_call : public ASTnamed_symbol
886928
{
887929
public:
888930
ASTfunction_call (OSLCompilerImpl *comp, ustring name, ASTNode *args,
@@ -985,8 +1027,6 @@ class ASTfunction_call : public ASTNode
9851027
ustring formal, ustring actual,
9861028
Symbol *arrayindex = NULL);
9871029

988-
ustring m_name; ///< Name of the function being called
989-
Symbol *m_sym; ///< Symbol of the function
9901030
FunctionSymbol *m_poly; ///< The specific polymorphic variant
9911031
unsigned int m_argread; ///< Bit field - which args are read
9921032
unsigned int m_argwrite; ///< Bit field - which args are written

0 commit comments

Comments
 (0)