mirror of
https://github.com/intel/llvm.git
synced 2026-01-27 06:06:34 +08:00
Bug #:
Submitted by:
Reviewed by:
Refine Sema::ParseCallExpr() diags (range support, add types).
Before:
func-assign.c:27:11: warning: passing argument 1 from incompatible pointer type
pintFunc(&FOO);
^
func-assign.c:28:12: error: incompatible type for argument 1
floatFunc(&FOO);
^
func-assign.c:29:12: error: too many arguments to function
floatFunc(1,2,3);
^
After:
func-assign.c:27:11: warning: passing incompatible pointer 'struct foo *' to function expecting 'int *'
pintFunc(&FOO);
~~~~~~~~^~~~~
func-assign.c:28:12: error: passing incompatible type 'struct foo *' to function expecting 'float'
floatFunc(&FOO);
~~~~~~~~~^~~~~
func-assign.c:29:12: error: too many arguments to function
floatFunc(1,2,3);
~~~~~~~~~^ ~
llvm-svn: 39513
This commit is contained in:
@@ -363,7 +363,11 @@ Action::ExprResult Sema::
|
||||
ParseCallExpr(ExprTy *Fn, SourceLocation LParenLoc,
|
||||
ExprTy **Args, unsigned NumArgsInCall,
|
||||
SourceLocation *CommaLocs, SourceLocation RParenLoc) {
|
||||
QualType qType = ((Expr *)Fn)->getType();
|
||||
Expr *funcExpr = (Expr *)Fn;
|
||||
|
||||
assert(funcExpr && "no function call expression");
|
||||
|
||||
QualType qType = funcExpr->getType();
|
||||
|
||||
assert(!qType.isNull() && "no type for function call expression");
|
||||
|
||||
@@ -382,16 +386,24 @@ ParseCallExpr(ExprTy *Fn, SourceLocation LParenLoc,
|
||||
unsigned NumArgsToCheck = NumArgsInCall;
|
||||
|
||||
if (NumArgsInCall < NumArgsInProto)
|
||||
Diag(LParenLoc, diag::err_typecheck_call_too_few_args);
|
||||
Diag(LParenLoc, diag::err_typecheck_call_too_few_args,
|
||||
funcExpr->getSourceRange());
|
||||
else if (NumArgsInCall > NumArgsInProto) {
|
||||
if (!proto->isVariadic())
|
||||
Diag(LParenLoc, diag::err_typecheck_call_too_many_args);
|
||||
if (!proto->isVariadic()) {
|
||||
Diag(LParenLoc, diag::err_typecheck_call_too_many_args,
|
||||
funcExpr->getSourceRange(),
|
||||
((Expr **)Args)[NumArgsInProto]->getSourceRange());
|
||||
}
|
||||
NumArgsToCheck = NumArgsInProto;
|
||||
}
|
||||
// Continue to check argument types (even if we have too few/many args).
|
||||
for (unsigned i = 0; i < NumArgsToCheck; i++) {
|
||||
Expr *argExpr = ((Expr **)Args)[i];
|
||||
|
||||
assert(argExpr && "ParseCallExpr(): missing argument expression");
|
||||
|
||||
QualType lhsType = proto->getArgType(i);
|
||||
QualType rhsType = ((Expr **)Args)[i]->getType();
|
||||
QualType rhsType = argExpr->getType();
|
||||
|
||||
if (lhsType == rhsType) // common case, fast path...
|
||||
continue;
|
||||
@@ -401,28 +413,34 @@ ParseCallExpr(ExprTy *Fn, SourceLocation LParenLoc,
|
||||
SourceLocation l = (i == 0) ? LParenLoc : CommaLocs[i-1];
|
||||
|
||||
// decode the result (notice that AST's are still created for extensions).
|
||||
// FIXME: consider fancier error diagnostics (since this is quite common).
|
||||
// #1: emit the actual prototype arg...requires adding source loc info.
|
||||
// #2: pass Diag the offending argument type...requires hacking Diag.
|
||||
// FIXME: decide to include/exclude the argument # (decided to remove
|
||||
// it for the incompatible diags below). The range should be sufficient.
|
||||
switch (result) {
|
||||
case Compatible:
|
||||
break;
|
||||
case PointerFromInt:
|
||||
// check for null pointer constant (C99 6.3.2.3p3)
|
||||
if (!((Expr **)Args)[i]->isNullPointerConstant())
|
||||
Diag(l, diag::ext_typecheck_passing_pointer_from_int, utostr(i+1));
|
||||
if (!argExpr->isNullPointerConstant())
|
||||
Diag(l, diag::ext_typecheck_passing_pointer_from_int, utostr(i+1),
|
||||
funcExpr->getSourceRange(), argExpr->getSourceRange());
|
||||
break;
|
||||
case IntFromPointer:
|
||||
Diag(l, diag::ext_typecheck_passing_int_from_pointer, utostr(i+1));
|
||||
Diag(l, diag::ext_typecheck_passing_int_from_pointer, utostr(i+1),
|
||||
funcExpr->getSourceRange(), argExpr->getSourceRange());
|
||||
break;
|
||||
case IncompatiblePointer:
|
||||
Diag(l, diag::ext_typecheck_passing_incompatible_pointer, utostr(i+1));
|
||||
Diag(l, diag::ext_typecheck_passing_incompatible_pointer,
|
||||
rhsType.getAsString(), lhsType.getAsString(),
|
||||
funcExpr->getSourceRange(), argExpr->getSourceRange());
|
||||
break;
|
||||
case CompatiblePointerDiscardsQualifiers:
|
||||
Diag(l, diag::ext_typecheck_passing_discards_qualifiers, utostr(i+1));
|
||||
Diag(l, diag::ext_typecheck_passing_discards_qualifiers, utostr(i+1),
|
||||
funcExpr->getSourceRange(), argExpr->getSourceRange());
|
||||
break;
|
||||
case Incompatible:
|
||||
return Diag(l, diag::err_typecheck_passing_incompatible, utostr(i+1));
|
||||
return Diag(l, diag::err_typecheck_passing_incompatible,
|
||||
rhsType.getAsString(), lhsType.getAsString(),
|
||||
funcExpr->getSourceRange(), argExpr->getSourceRange());
|
||||
}
|
||||
}
|
||||
// Even if the types checked, bail if we had the wrong number of arguments.
|
||||
|
||||
@@ -103,6 +103,23 @@
|
||||
DED7D9E50A5257F6003AD0FB /* ScratchBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED7D9E40A5257F6003AD0FB /* ScratchBuffer.cpp */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXBuildStyle section */
|
||||
84FADE170C0B37FF00330902 /* Development */ = {
|
||||
isa = PBXBuildStyle;
|
||||
buildSettings = {
|
||||
COPY_PHASE_STRIP = NO;
|
||||
};
|
||||
name = Development;
|
||||
};
|
||||
84FADE180C0B37FF00330902 /* Deployment */ = {
|
||||
isa = PBXBuildStyle;
|
||||
buildSettings = {
|
||||
COPY_PHASE_STRIP = YES;
|
||||
};
|
||||
name = Deployment;
|
||||
};
|
||||
/* End PBXBuildStyle section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
8DD76F690486A84900D96B5E /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
@@ -538,6 +555,12 @@
|
||||
08FB7793FE84155DC02AAC07 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
|
||||
buildSettings = {
|
||||
};
|
||||
buildStyles = (
|
||||
84FADE170C0B37FF00330902 /* Development */,
|
||||
84FADE180C0B37FF00330902 /* Deployment */,
|
||||
);
|
||||
hasScannedForEncodings = 1;
|
||||
mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
|
||||
projectDirPath = "";
|
||||
|
||||
@@ -585,13 +585,13 @@ DIAG(err_typecheck_call_too_few_args, ERROR,
|
||||
DIAG(err_typecheck_call_too_many_args, ERROR,
|
||||
"too many arguments to function")
|
||||
DIAG(err_typecheck_passing_incompatible, ERROR,
|
||||
"incompatible type for argument %0")
|
||||
"passing incompatible type '%0' to function expecting '%1'")
|
||||
DIAG(ext_typecheck_passing_incompatible_pointer, EXTENSION,
|
||||
"passing incompatible pointer '%0' to function expecting '%1'")
|
||||
DIAG(ext_typecheck_passing_int_from_pointer, EXTENSION,
|
||||
"passing argument %0 makes integer from pointer without a cast")
|
||||
DIAG(ext_typecheck_passing_pointer_from_int, EXTENSION,
|
||||
"passing argument %0 makes pointer from integer without a cast")
|
||||
DIAG(ext_typecheck_passing_incompatible_pointer, EXTENSION,
|
||||
"passing argument %0 from incompatible pointer type")
|
||||
DIAG(ext_typecheck_passing_discards_qualifiers, EXTENSION,
|
||||
"passing argument %0 discards qualifiers from pointer target type")
|
||||
DIAG(err_typecheck_return_incompatible, ERROR,
|
||||
|
||||
Reference in New Issue
Block a user