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:
Steve Naroff 2007-05-29 14:23:36 +00:00
parent e64a1b5275
commit 6f49f5df03
4 changed files with 57 additions and 51 deletions

View File

@ -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

View File

@ -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();
}

View File

@ -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;

View File

@ -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