forked from OSchip/llvm-project
Improve the error message for attempting to build a for range loop using a
function parameter that has array type. Such a parameter will be treated as a pointer type instead, resulting in a missing begin function error is a suggestion to dereference the pointer. This provides a different, more informative diagnostic as well as point to the parameter declaration. llvm-svn: 192512
This commit is contained in:
parent
98f134835f
commit
0825469126
|
@ -1623,6 +1623,9 @@ def note_in_for_range: Note<
|
|||
def err_for_range_invalid: Error<
|
||||
"invalid range expression of type %0; no viable '%select{begin|end}1' "
|
||||
"function available">;
|
||||
def err_range_on_array_parameter : Error<
|
||||
"cannot build range expression with array function parameter %0 since "
|
||||
"parameter with array type %1 is treated as pointer type %2">;
|
||||
def err_for_range_dereference : Error<
|
||||
"invalid range expression of type %0; did you mean to dereference it "
|
||||
"with '*'?">;
|
||||
|
|
|
@ -2131,10 +2131,25 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
|
|||
BeginVar, EndVar, ColonLoc, &CandidateSet,
|
||||
&BeginExpr, &EndExpr, &BEFFailure);
|
||||
|
||||
// If building the range failed, try dereferencing the range expression
|
||||
// unless a diagnostic was issued or the end function is problematic.
|
||||
if (Kind == BFRK_Build && RangeStatus == FRS_NoViableFunction &&
|
||||
BEFFailure == BEF_begin) {
|
||||
// If the range is being built from an array parameter, emit a
|
||||
// a diagnostic that it is being treated as a pointer.
|
||||
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Range)) {
|
||||
if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
|
||||
QualType ArrayTy = PVD->getOriginalType();
|
||||
QualType PointerTy = PVD->getType();
|
||||
if (PointerTy->isPointerType() && ArrayTy->isArrayType()) {
|
||||
Diag(Range->getLocStart(), diag::err_range_on_array_parameter)
|
||||
<< RangeLoc << PVD << ArrayTy << PointerTy;
|
||||
Diag(PVD->getLocation(), diag::note_declared_at);
|
||||
return StmtError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If building the range failed, try dereferencing the range expression
|
||||
// unless a diagnostic was issued or the end function is problematic.
|
||||
StmtResult SR = RebuildForRangeWithDereference(*this, S, ForLoc,
|
||||
LoopVarDecl, ColonLoc,
|
||||
Range, RangeLoc,
|
||||
|
|
|
@ -191,3 +191,21 @@ namespace test5 {
|
|||
x->foo();
|
||||
}
|
||||
}
|
||||
|
||||
namespace test6 {
|
||||
void foo(int arr[]) { // expected-note {{declared here}}
|
||||
for (auto i : arr) { }
|
||||
// expected-error@-1 {{cannot build range expression with array function parameter 'arr' since parameter with array type 'int []' is treated as pointer type 'int *'}}
|
||||
}
|
||||
|
||||
struct vector {
|
||||
int *begin() { return 0; }
|
||||
int *end() { return 0; }
|
||||
};
|
||||
|
||||
void foo(vector arr[]) { // expected-note {{declared here}}
|
||||
// Don't suggest to dereference arr.
|
||||
for (auto i : arr) { }
|
||||
// expected-error@-1 {{cannot build range expression with array function parameter 'arr' since parameter with array type 'test6::vector []' is treated as pointer type 'test6::vector *'}}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue