Bug #:
Submitted by: Reviewed by: - Finished Sema::ParseReturnStmt(). Still need to tweak ranges. - Tweaked location for function arguments (they now point at the expression directly, no parens or commas). - Added InvalidOperands helper...was sick of looking at the same 3 lines in ~9 Check functions. - Added a few diags and moved a group of statement diags to the proper comment/category. llvm-svn: 39517
This commit is contained in:
parent
e64a1b5275
commit
6f49f5df03
|
@ -275,6 +275,7 @@ private:
|
|||
/// or a null QualType (indicating an error diagnostic was issued).
|
||||
|
||||
/// type checking binary operators (subroutines of ParseBinOp).
|
||||
inline void InvalidOperands(SourceLocation l, Expr *lex, Expr *rex);
|
||||
inline QualType CheckMultiplyDivideOperands( // C99 6.5.5
|
||||
Expr *lex, Expr *rex, SourceLocation OpLoc);
|
||||
inline QualType CheckRemainderOperands( // C99 6.5.5
|
||||
|
|
|
@ -410,7 +410,7 @@ ParseCallExpr(ExprTy *Fn, SourceLocation LParenLoc,
|
|||
AssignmentConversionResult result;
|
||||
UsualAssignmentConversions(lhsType, rhsType, result);
|
||||
|
||||
SourceLocation l = (i == 0) ? LParenLoc : CommaLocs[i-1];
|
||||
SourceLocation l = argExpr->getLocStart();
|
||||
|
||||
// decode the result (notice that AST's are still created for extensions).
|
||||
// FIXME: decide to include/exclude the argument # (decided to remove
|
||||
|
@ -707,6 +707,12 @@ QualType Sema::UsualAssignmentConversions(QualType lhsType, QualType rhsType,
|
|||
return QualType();
|
||||
}
|
||||
|
||||
inline void Sema::InvalidOperands(SourceLocation loc, Expr *lex, Expr *rex) {
|
||||
Diag(loc, diag::err_typecheck_invalid_operands,
|
||||
lex->getType().getAsString(), rex->getType().getAsString(),
|
||||
lex->getSourceRange(), rex->getSourceRange());
|
||||
}
|
||||
|
||||
inline QualType Sema::CheckMultiplyDivideOperands(
|
||||
Expr *lex, Expr *rex, SourceLocation loc)
|
||||
{
|
||||
|
@ -714,9 +720,7 @@ inline QualType Sema::CheckMultiplyDivideOperands(
|
|||
|
||||
if (resType->isArithmeticType())
|
||||
return resType;
|
||||
Diag(loc, diag::err_typecheck_invalid_operands,
|
||||
lex->getType().getAsString(), rex->getType().getAsString(),
|
||||
lex->getSourceRange(), rex->getSourceRange());
|
||||
InvalidOperands(loc, lex, rex);
|
||||
return QualType();
|
||||
}
|
||||
|
||||
|
@ -727,9 +731,7 @@ inline QualType Sema::CheckRemainderOperands(
|
|||
|
||||
if (resType->isIntegerType())
|
||||
return resType;
|
||||
Diag(loc, diag::err_typecheck_invalid_operands,
|
||||
lex->getType().getAsString(), rex->getType().getAsString(),
|
||||
lex->getSourceRange(), rex->getSourceRange());
|
||||
InvalidOperands(loc, lex, rex);
|
||||
return QualType();
|
||||
}
|
||||
|
||||
|
@ -746,9 +748,7 @@ inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
|
|||
if ((lhsType->isPointerType() && rhsType->isIntegerType()) ||
|
||||
(lhsType->isIntegerType() && rhsType->isPointerType()))
|
||||
return resType;
|
||||
Diag(loc, diag::err_typecheck_invalid_operands,
|
||||
lhsType.getAsString(), rhsType.getAsString(),
|
||||
lex->getSourceRange(), rex->getSourceRange());
|
||||
InvalidOperands(loc, lex, rex);
|
||||
return QualType();
|
||||
}
|
||||
|
||||
|
@ -764,9 +764,7 @@ inline QualType Sema::CheckSubtractionOperands( // C99 6.5.6
|
|||
if ((lhsType->isPointerType() && rhsType->isIntegerType()) ||
|
||||
(lhsType->isPointerType() && rhsType->isPointerType()))
|
||||
return resType;
|
||||
Diag(loc, diag::err_typecheck_invalid_operands,
|
||||
lhsType.getAsString(), rhsType.getAsString(),
|
||||
lex->getSourceRange(), rex->getSourceRange());
|
||||
InvalidOperands(loc, lex, rex);
|
||||
return QualType();
|
||||
}
|
||||
|
||||
|
@ -777,9 +775,7 @@ inline QualType Sema::CheckShiftOperands( // C99 6.5.7
|
|||
|
||||
if (resType->isIntegerType())
|
||||
return resType;
|
||||
Diag(loc, diag::err_typecheck_invalid_operands,
|
||||
lex->getType().getAsString(), rex->getType().getAsString(),
|
||||
lex->getSourceRange(), rex->getSourceRange());
|
||||
InvalidOperands(loc, lex, rex);
|
||||
return QualType();
|
||||
}
|
||||
|
||||
|
@ -798,9 +794,7 @@ inline QualType Sema::CheckRelationalOperands( // C99 6.5.8
|
|||
Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer);
|
||||
return Context.IntTy;
|
||||
}
|
||||
Diag(loc, diag::err_typecheck_invalid_operands,
|
||||
lType.getAsString(), rType.getAsString(),
|
||||
lex->getSourceRange(), rex->getSourceRange());
|
||||
InvalidOperands(loc, lex, rex);
|
||||
return QualType();
|
||||
}
|
||||
|
||||
|
@ -818,9 +812,7 @@ inline QualType Sema::CheckEqualityOperands( // C99 6.5.9
|
|||
Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer);
|
||||
return Context.IntTy;
|
||||
}
|
||||
Diag(loc, diag::err_typecheck_invalid_operands,
|
||||
lType.getAsString(), rType.getAsString(),
|
||||
lex->getSourceRange(), rex->getSourceRange());
|
||||
InvalidOperands(loc, lex, rex);
|
||||
return QualType();
|
||||
}
|
||||
|
||||
|
@ -831,9 +823,7 @@ inline QualType Sema::CheckBitwiseOperands(
|
|||
|
||||
if (resType->isIntegerType())
|
||||
return resType;
|
||||
Diag(loc, diag::err_typecheck_invalid_operands,
|
||||
lex->getType().getAsString(), rex->getType().getAsString(),
|
||||
lex->getSourceRange(), rex->getSourceRange());
|
||||
InvalidOperands(loc, lex, rex);
|
||||
return QualType();
|
||||
}
|
||||
|
||||
|
@ -845,9 +835,7 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
|
|||
|
||||
if (lhsType->isScalarType() || rhsType->isScalarType())
|
||||
return Context.IntTy;
|
||||
Diag(loc, diag::err_typecheck_invalid_operands,
|
||||
lex->getType().getAsString(), rex->getType().getAsString(),
|
||||
lex->getSourceRange(), rex->getSourceRange());
|
||||
InvalidOperands(loc, lex, rex);
|
||||
return QualType();
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include "clang/AST/Expr.h"
|
||||
#include "clang/Parse/Scope.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Basic/LangOptions.h"
|
||||
#include "clang/Lex/IdentifierTable.h"
|
||||
using namespace llvm;
|
||||
using namespace clang;
|
||||
|
||||
|
@ -199,25 +201,33 @@ Sema::ParseBreakStmt(SourceLocation BreakLoc, Scope *CurScope) {
|
|||
|
||||
Action::StmtResult
|
||||
Sema::ParseReturnStmt(SourceLocation ReturnLoc, ExprTy *RetValExp) {
|
||||
// C99 6.8.6.4p3(136): The return statement is not an assignment. The
|
||||
// overlap restriction of subclause 6.5.16.1 does not apply to the case of
|
||||
// function return.
|
||||
QualType lhsType = CurFunctionDecl->getResultType();
|
||||
|
||||
if (!RetValExp)
|
||||
return new ReturnStmt((Expr*)RetValExp);
|
||||
|
||||
// C99 6.8.6.4p1
|
||||
if (lhsType->isVoidType()) {
|
||||
// a void function may not return a value
|
||||
// non-void function "voidFunc" should return a value
|
||||
if (RetValExp) // C99 6.8.6.4p1 (ext_ since GCC warns)
|
||||
Diag(ReturnLoc, diag::ext_return_has_expr,
|
||||
CurFunctionDecl->getIdentifier()->getName(),
|
||||
((Expr *)RetValExp)->getSourceRange());
|
||||
return new ReturnStmt((Expr*)RetValExp);
|
||||
} else {
|
||||
if (!RetValExp) {
|
||||
const char *funcName = CurFunctionDecl->getIdentifier()->getName();
|
||||
if (getLangOptions().C99) // C99 6.8.6.4p1 (ext_ since GCC warns)
|
||||
Diag(ReturnLoc, diag::ext_return_missing_expr, funcName);
|
||||
else // C90 6.6.6.4p4
|
||||
Diag(ReturnLoc, diag::warn_return_missing_expr, funcName);
|
||||
return new ReturnStmt((Expr*)0);
|
||||
}
|
||||
}
|
||||
|
||||
// we have a non-void function with an expression, continue checking
|
||||
QualType rhsType = ((Expr *)RetValExp)->getType();
|
||||
|
||||
if (lhsType == rhsType) // common case, fast path...
|
||||
return new ReturnStmt((Expr*)RetValExp);
|
||||
|
||||
|
||||
// C99 6.8.6.4p3(136): The return statement is not an assignment. The
|
||||
// overlap restriction of subclause 6.5.16.1 does not apply to the case of
|
||||
// function return.
|
||||
AssignmentConversionResult result;
|
||||
QualType resType = UsualAssignmentConversions(lhsType, rhsType, result);
|
||||
bool hadError = false;
|
||||
|
|
|
@ -594,6 +594,18 @@ DIAG(ext_typecheck_passing_pointer_from_int, EXTENSION,
|
|||
"passing argument %0 makes pointer from integer without a cast")
|
||||
DIAG(ext_typecheck_passing_discards_qualifiers, EXTENSION,
|
||||
"passing argument %0 discards qualifiers from pointer target type")
|
||||
DIAG(err_typecheck_cond_expect_scalar, ERROR,
|
||||
"used type '%0' where arithmetic or pointer type is required")
|
||||
DIAG(err_typecheck_cond_incompatible_operands, ERROR,
|
||||
"incompatible operand types ('%0' and '%1')")
|
||||
DIAG(ext_typecheck_cond_incompatible_pointers, EXTENSION,
|
||||
"pointer type mismatch ('%0' and '%1')")
|
||||
|
||||
// Statements.
|
||||
DIAG(err_continue_not_in_loop, ERROR,
|
||||
"'continue' statement not in loop statement")
|
||||
DIAG(err_break_not_in_loop_or_switch, ERROR,
|
||||
"'break' statement not in loop or switch statement")
|
||||
DIAG(err_typecheck_return_incompatible, ERROR,
|
||||
"incompatible types in return ('%0' and '%1')")
|
||||
DIAG(ext_typecheck_return_int_from_pointer, EXTENSION,
|
||||
|
@ -604,19 +616,14 @@ DIAG(ext_typecheck_return_incompatible_pointer, EXTENSION,
|
|||
"return from incompatible pointer type")
|
||||
DIAG(ext_typecheck_return_discards_qualifiers, EXTENSION,
|
||||
"return discards qualifiers from pointer target type")
|
||||
DIAG(err_typecheck_cond_expect_scalar, ERROR,
|
||||
"used type '%0' where arithmetic or pointer type is required")
|
||||
DIAG(err_typecheck_cond_incompatible_operands, ERROR,
|
||||
"incompatible operand types ('%0' and '%1')")
|
||||
DIAG(ext_typecheck_cond_incompatible_pointers, EXTENSION,
|
||||
"pointer type mismatch ('%0' and '%1')")
|
||||
DIAG(err_typecheck_statement_requires_scalar, ERROR,
|
||||
"statement requires expression of scalar type ('%0' invalid)")
|
||||
|
||||
// Statements.
|
||||
DIAG(err_continue_not_in_loop, ERROR,
|
||||
"'continue' statement not in loop statement")
|
||||
DIAG(err_break_not_in_loop_or_switch, ERROR,
|
||||
"'break' statement not in loop or switch statement")
|
||||
|
||||
DIAG(warn_return_missing_expr, WARNING,
|
||||
"non-void function '%0' should return a value")
|
||||
DIAG(ext_return_missing_expr, EXTENSION,
|
||||
"non-void function '%0' should return a value")
|
||||
DIAG(ext_return_has_expr, EXTENSION,
|
||||
"void function '%0' should not return a value")
|
||||
|
||||
#undef DIAG
|
||||
|
|
Loading…
Reference in New Issue