Skip to content

Commit 020214b

Browse files
authored
Warning fixes and general cleanup to recently added typecheck code (#863)
The most important change here is to modify the practice making multi-line warnings/errors by issuing a warning/error for the first line followed by message() calls for the subsequent line. Instead, we generate those line-by-line messages as strings, and at the very end issue a single warning or error call. Also, directly call m_compiler->warning or error, don't bypass the compiler by calling the app's error handler. The reason both of those are important is that I have a separate change I am ready to submit that is about giving a `#pragma nowarn` that can be used to suppress warnings on the following line. This is totally borked by warnings that span multiple calls and where most of their output is in the form of message() and thus aren't easily recognized as part of the warning. This includes some general stylistic cleanup also in a few spots, some preferences I have but but did not feel was worth nit picking line by line in the original PRs.
1 parent f19ab7c commit 020214b

File tree

2 files changed

+69
-70
lines changed

2 files changed

+69
-70
lines changed

src/liboslcomp/oslcomp_pvt.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ class OSLCompilerImpl {
105105
{
106106
ASSERT (format.size());
107107
std::string msg = OIIO::Strutil::format (format, args...);
108+
if (msg.size() && msg.back() == '\n') // trim extra newline
109+
msg.pop_back();
108110
if (filename.size())
109111
m_errhandler->error ("%s:%d: error: %s", filename, line, msg);
110112
else
@@ -119,6 +121,8 @@ class OSLCompilerImpl {
119121
{
120122
ASSERT (format.size());
121123
std::string msg = OIIO::Strutil::format (format, args...);
124+
if (msg.size() && msg.back() == '\n') // trim extra newline
125+
msg.pop_back();
122126
if (m_err_on_warning) {
123127
error (filename, line, "%s", msg);
124128
return;
@@ -136,6 +140,8 @@ class OSLCompilerImpl {
136140
{
137141
ASSERT (format.size());
138142
std::string msg = OIIO::Strutil::format (format, args...);
143+
if (msg.size() && msg.back() == '\n') // trim extra newline
144+
msg.pop_back();
139145
if (filename.size())
140146
m_errhandler->info ("%s:%d: info: %s", filename, line, msg);
141147
else
@@ -149,6 +155,8 @@ class OSLCompilerImpl {
149155
{
150156
ASSERT (format.size());
151157
std::string msg = OIIO::Strutil::format (format, args...);
158+
if (msg.size() && msg.back() == '\n') // trim extra newline
159+
msg.pop_back();
152160
if (filename.size())
153161
m_errhandler->message ("%s:%d: %s", filename, line, msg);
154162
else

src/liboslcomp/typecheck.cpp

Lines changed: 61 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1605,15 +1605,11 @@ class CandidateFunctions {
16051605
return argscore;
16061606
}
16071607

1608-
void candidateHeader(const char* msg) const {
1609-
m_compiler->errhandler().message(" %s:\n", msg);
1610-
}
1611-
16121608
public:
1613-
CandidateFunctions(OSLCompilerImpl* compiler, TypeSpec rval, ASTNode::ref args,
1614-
FunctionSymbol* func) :
1615-
m_compiler(compiler), m_rval(rval), m_args(args), m_nargs(0),
1616-
m_called(func), m_had_initlist(false) {
1609+
CandidateFunctions(OSLCompilerImpl* compiler, TypeSpec rval,
1610+
ASTNode::ref args, FunctionSymbol* func)
1611+
: m_compiler(compiler), m_rval(rval), m_args(args), m_nargs(0),
1612+
m_called(func), m_had_initlist(false) {
16171613

16181614
//std::cerr << "Matching " << func->name() << " formals='" << (rval.simpletype().basetype != TypeDesc::UNKNOWN ? compiler->code_from_type (rval) : " ");
16191615
for (ASTNode::ref arg = m_args; arg; arg = arg->next()) {
@@ -1630,46 +1626,37 @@ class CandidateFunctions {
16301626
}
16311627
}
16321628

1633-
void reportAmbiguity(ASTNode* caller, const ustring& funcname,
1634-
bool candidateMsg = true,
1635-
const char* msg = "No matching function call to",
1636-
bool asWarning = true, bool showArgs = true) const {
1629+
std::string reportAmbiguity (ustring funcname, bool candidateMsg,
1630+
string_view msg) const {
16371631
std::string argstr = funcname.string();
1638-
if (showArgs) {
1639-
argstr += " (";
1640-
const char *comma = "";
1641-
for (ASTNode::ref arg = m_args; arg; arg = arg->next()) {
1642-
argstr += comma;
1643-
if (arg->typespec().simpletype().is_unknown() &&
1644-
arg->nodetype() == ASTNode::compound_initializer_node) {
1645-
argstr += "initializer-list";
1646-
} else
1647-
argstr += arg->typespec().string();
1648-
comma = ", ";
1632+
argstr += " (";
1633+
const char *comma = "";
1634+
for (ASTNode::ref arg = m_args; arg; arg = arg->next()) {
1635+
argstr += comma;
1636+
if (arg->typespec().simpletype().is_unknown() &&
1637+
arg->nodetype() == ASTNode::compound_initializer_node) {
1638+
argstr += "initializer-list";
1639+
} else {
1640+
argstr += arg->typespec().string();
16491641
}
1650-
argstr += ")";
1642+
comma = ", ";
16511643
}
1652-
asWarning ? caller->warning ("%s '%s'", msg, argstr)
1653-
: caller->error ("%s '%s'", msg, argstr);
1654-
if (candidateMsg)
1655-
candidateHeader("Candidates are");
1644+
argstr += ")";
1645+
return Strutil::format ("%s '%s'%s\n", msg, argstr,
1646+
candidateMsg ? "\n Candidates are:" : "");
16561647
}
16571648

1658-
void reportFunction(FunctionSymbol* sym) const {
1649+
std::string reportFunction (FunctionSymbol* sym) const {
16591650
int advance;
16601651
const char *formals = sym->argcodes().c_str();
16611652
TypeSpec returntype = m_compiler->type_from_code (formals, &advance);
16621653
formals += advance;
1663-
1664-
auto& errh = m_compiler->errhandler();
1665-
errh.message(" ");
1666-
1654+
std::string msg = " ";
16671655
if (ASTNode* decl = sym->node())
1668-
errh.message("%s:%d\t", decl->sourcefile(), decl->sourceline());
1669-
1670-
errh.message("%s %s (%s)\n", m_compiler->type_c_str(returntype),
1671-
sym->name(),
1672-
m_compiler->typelist_from_code(formals).c_str());
1656+
msg += Strutil::format("%s:%d\t", decl->sourcefile(), decl->sourceline());
1657+
msg += Strutil::format("%s %s (%s)\n", m_compiler->type_c_str(returntype),
1658+
sym->name(), m_compiler->typelist_from_code(formals));
1659+
return msg;
16731660
}
16741661

16751662
std::pair<FunctionSymbol*, TypeSpec>
@@ -1680,21 +1667,20 @@ class CandidateFunctions {
16801667
auto best = [](Candidate* c) -> std::pair<FunctionSymbol*, TypeSpec> {
16811668
for (auto&& t : c->bindings)
16821669
t.second.bind();
1683-
return {c->sym, c->rtype };
1670+
return { c->sym, c->rtype };
16841671
};
16851672

1673+
std::string errmsg;
16861674
switch (m_candidates.size()) {
16871675
case 0:
16881676
// Nothing at all, Error
16891677
// If m_called is 0, then user tried to call an undefined func.
16901678
// Might be nice to fuzzy match funcname against m_compiler->symtab()
1691-
reportAmbiguity(caller, funcname,
1692-
m_called != nullptr /*Candidate Msg?*/,
1693-
"No matching function call to",
1694-
false /*As warning*/);
1679+
errmsg = reportAmbiguity (funcname, m_called != nullptr /*Candidate Msg?*/,
1680+
"No matching function call to");
16951681
for (FunctionSymbol* f = m_called; f; f = f->nextpoly())
1696-
reportFunction(f);
1697-
1682+
errmsg += reportFunction (f);
1683+
caller->error ("%s", errmsg);
16981684
return { nullptr, TypeSpec() };
16991685

17001686
case 1: // Success
@@ -1717,7 +1703,6 @@ class CandidateFunctions {
17171703
ASSERT (c.first && c.first->sym);
17181704

17191705
if (ambiguity != -1) {
1720-
17211706
unsigned userstructs = 0;
17221707

17231708
auto rank = [&userstructs] (const TypeSpec& s) -> int {
@@ -1751,7 +1736,7 @@ class CandidateFunctions {
17511736
}
17521737
if (s.is_void())
17531738
return 10;
1754-
1739+
17551740
ASSERT (0 && "Unranked type");
17561741
return std::numeric_limits<int>::max();
17571742
};
@@ -1812,20 +1797,20 @@ class CandidateFunctions {
18121797
}
18131798
}
18141799

1815-
reportAmbiguity(caller, funcname, !warn /* "Candidates are" msg*/,
1816-
"Ambiguous call to", warn /* As warning */);
1800+
std::string errmsg = reportAmbiguity (funcname, !warn /* "Candidates are" msg*/,
1801+
"Ambiguous call to");
18171802
if (warn) {
1818-
candidateHeader("Chosen function is");
1819-
reportFunction(c.first->sym);
1820-
1821-
candidateHeader("Other candidates are");
1822-
for (auto& candidate : m_candidates) {
1803+
errmsg += Strutil::format (" Chosen function is:\n%s",
1804+
reportFunction (c.first->sym));
1805+
errmsg += " Other candidates are:\n";
1806+
for (auto& candidate : m_candidates)
18231807
if (candidate.sym != c.first->sym)
1824-
reportFunction(candidate.sym);
1825-
}
1808+
errmsg += reportFunction (candidate.sym);
1809+
caller->warning ("%s", errmsg);
18261810
} else {
18271811
for (auto& candidate : m_candidates)
1828-
reportFunction(candidate.sym);
1812+
errmsg += reportFunction (candidate.sym);
1813+
caller->error ("%s", errmsg);
18291814
}
18301815
}
18311816

@@ -1964,23 +1949,29 @@ ASTfunction_call::typecheck (TypeSpec expected)
19641949
// Check resolution against prior versions of OSL.
19651950
// Skip the check if any arguments used initializer list syntax.
19661951
static const char* OSL_LEGACY = ::getenv("OSL_LEGACY_FUNCTION_RESOLUTION");
1967-
if (candidates.hadinitlist() && OSL_LEGACY && strcmp(OSL_LEGACY, "0")) {
1952+
if (!candidates.hadinitlist() && OSL_LEGACY && strcmp(OSL_LEGACY, "0")) {
19681953
auto* legacy = LegacyOverload(m_compiler, this, poly,
19691954
&ASTfunction_call::check_arglist)(expected);
19701955
if (m_sym != legacy) {
1971-
Strutil::iequals(OSL_LEGACY, "err")
1972-
? error("overload chosen differs from OSL 1.9")
1973-
: warning("overload chosen differs from OSL 1.9");
1974-
1975-
m_compiler->errhandler().message (" Current overload is ");
1976-
!m_sym ? m_compiler->errhandler().message("<none>")
1977-
: candidates.reportFunction(static_cast<FunctionSymbol*>(m_sym));
1978-
m_compiler->errhandler().message (" Prior overload was ");
1979-
!legacy ? m_compiler->errhandler().message("<none>")
1980-
: candidates.reportFunction(legacy);
1981-
1956+
bool as_warning = true;
1957+
if (Strutil::iequals(OSL_LEGACY, "err"))
1958+
as_warning = false; // full error
1959+
std::string errmsg = " Current overload is\n";
1960+
if (m_sym)
1961+
errmsg += candidates.reportFunction (static_cast<FunctionSymbol*>(m_sym));
1962+
else
1963+
errmsg += "<none>";
1964+
errmsg += "\n Prior overload was ";
1965+
if (legacy)
1966+
errmsg += candidates.reportFunction (legacy);
1967+
else
1968+
errmsg += "<none>";
19821969
if (Strutil::iequals(OSL_LEGACY, "use"))
19831970
m_sym = legacy;
1971+
if (as_warning)
1972+
warning ("overload chosen differs from OSL 1.9\n%s", errmsg);
1973+
else
1974+
warning ("overload chosen differs from OSL 1.9\n%s", errmsg);
19841975
}
19851976
}
19861977

@@ -1989,7 +1980,7 @@ ASTfunction_call::typecheck (TypeSpec expected)
19891980
if (func()->number_of_returns() == 0 &&
19901981
! func()->typespec().is_void()) {
19911982
error ("non-void function \"%s\" had no 'return' statement.",
1992-
func()->name().c_str());
1983+
func()->name());
19931984
}
19941985
} else {
19951986
// built-in

0 commit comments

Comments
 (0)