Merge pull request #7376 from jakobandersen/c_cpp_error_messages

C, C++, improve error messages
This commit is contained in:
Jakob Lykke Andersen 2020-03-24 21:27:00 +01:00 committed by GitHub
commit 6deb592a2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 18 deletions

View File

@ -1986,6 +1986,10 @@ class DefinitionParser(BaseParser):
_prefix_keys = ('struct', 'enum', 'union')
@property
def language(self) -> str:
return 'C'
def _parse_string(self) -> str:
if self.current_char != '"':
return None
@ -2697,7 +2701,7 @@ class DefinitionParser(BaseParser):
restrict=restrict, volatile=volatile, const=const,
attrs=attrs)
if typed and self.current_char == '(': # note: peeking, not skipping
# maybe this is the beginning of params,try that first,
# maybe this is the beginning of params, try that first,
# otherwise assume it's noptr->declarator > ( ptr-declarator )
pos = self.pos
try:
@ -2706,7 +2710,10 @@ class DefinitionParser(BaseParser):
typed)
return res
except DefinitionError as exParamQual:
prevErrors.append((exParamQual, "If declId and parameters"))
msg = "If declarator-id with parameters"
if paramMode == 'function':
msg += " (e.g., 'void f(int arg)')"
prevErrors.append((exParamQual, msg))
self.pos = pos
try:
assert self.current_char == '('
@ -2723,7 +2730,10 @@ class DefinitionParser(BaseParser):
return ASTDeclaratorParen(inner=inner, next=next)
except DefinitionError as exNoPtrParen:
self.pos = pos
prevErrors.append((exNoPtrParen, "If parenthesis in noptr-declarator"))
msg = "If parenthesis in noptr-declarator"
if paramMode == 'function':
msg += " (e.g., 'void (*f(int arg))(double)')"
prevErrors.append((exNoPtrParen, msg))
header = "Error in declarator"
raise self._make_multi_error(prevErrors, header)
pos = self.pos

View File

@ -4576,6 +4576,10 @@ class DefinitionParser(BaseParser):
super().__init__(definition, location=location)
self.config = config
@property
def language(self) -> str:
return 'C++'
def _parse_string(self) -> str:
if self.current_char != '"':
return None
@ -5470,7 +5474,7 @@ class DefinitionParser(BaseParser):
self.skip_ws()
if not self.skip_string('('):
if paramMode == 'function':
self.fail('Expecting "(" in parameters_and_qualifiers.')
self.fail('Expecting "(" in parameters-and-qualifiers.')
else:
return None
args = []
@ -5483,7 +5487,7 @@ class DefinitionParser(BaseParser):
self.skip_ws()
if not self.skip_string(')'):
self.fail('Expected ")" after "..." in '
'parameters_and_qualifiers.')
'parameters-and-qualifiers.')
break
# note: it seems that function arguments can always be named,
# even in function pointers and similar.
@ -5498,7 +5502,7 @@ class DefinitionParser(BaseParser):
break
else:
self.fail(
'Expecting "," or ")" in parameters_and_qualifiers, '
'Expecting "," or ")" in parameters-and-qualifiers, '
'got "%s".' % self.current_char)
# TODO: why did we have this bail-out?
@ -5529,7 +5533,7 @@ class DefinitionParser(BaseParser):
exceptionSpec = 'noexcept'
self.skip_ws()
if self.skip_string('('):
self.fail('Parameterised "noexcept" not implemented.')
self.fail('Parameterised "noexcept" not yet implemented.')
self.skip_ws()
override = self.skip_word_and_ws('override')
@ -5795,14 +5799,15 @@ class DefinitionParser(BaseParser):
typed)
return res
except DefinitionError as exParamQual:
prevErrors.append((exParamQual, "If declId, parameters, and qualifiers"))
prevErrors.append((exParamQual,
"If declarator-id with parameters-and-qualifiers"))
self.pos = pos
try:
assert self.current_char == '('
self.skip_string('(')
# TODO: hmm, if there is a name, it must be in inner, right?
# TODO: hmm, if there must be parameters, they must b
# inside, right?
# TODO: hmm, if there must be parameters, they must be
# inside, right?
inner = self._parse_declarator(named, paramMode, typed)
if not self.skip_string(')'):
self.fail("Expected ')' in \"( ptr-declarator )\"")
@ -5821,7 +5826,7 @@ class DefinitionParser(BaseParser):
except DefinitionError as e:
self.pos = pos
prevErrors.append((e, "If declarator-id"))
header = "Error in declarator or parameters and qualifiers"
header = "Error in declarator or parameters-and-qualifiers"
raise self._make_multi_error(prevErrors, header)
def _parse_initializer(self, outer: str = None, allowFallback: bool = True
@ -5994,10 +5999,10 @@ class DefinitionParser(BaseParser):
if eExpr is None:
raise eType
errs = []
errs.append((eExpr, "If default is an expression"))
errs.append((eType, "If default is a type"))
errs.append((eExpr, "If default template argument is an expression"))
errs.append((eType, "If default template argument is a type"))
msg = "Error in non-type template parameter"
msg += " or constrianted template paramter."
msg += " or constrained template parameter."
raise self._make_multi_error(errs, msg)
def _parse_type_using(self) -> ASTTypeUsing:

View File

@ -154,19 +154,23 @@ class BaseParser:
result = [header, '\n']
for e in errors:
if len(e[1]) > 0:
ident = ' '
indent = ' '
result.append(e[1])
result.append(':\n')
for line in str(e[0]).split('\n'):
if len(line) == 0:
continue
result.append(ident)
result.append(indent)
result.append(line)
result.append('\n')
else:
result.append(str(e[0]))
return DefinitionError(''.join(result))
@property
def language(self) -> str:
raise NotImplementedError
def status(self, msg: str) -> None:
# for debugging
indicator = '-' * self.pos + '^'
@ -176,8 +180,8 @@ class BaseParser:
errors = []
indicator = '-' * self.pos + '^'
exMain = DefinitionError(
'Invalid definition: %s [error at %d]\n %s\n %s' %
(msg, self.pos, self.definition, indicator))
'Invalid %s declaration: %s [error at %d]\n %s\n %s' %
(self.language, msg, self.pos, self.definition, indicator))
errors.append((exMain, "Main error"))
for err in self.otherErrors:
errors.append((err, "Potential other error"))