forked from OSchip/llvm-project
Improve "assignment to cast" diagnostic.
- Strip off extra parens when looking for casts. - Change the location info to point at the cast (instead of the assignment). For example, on int *b; #define a ((void*) b) void f0() { a = 10; } we now emit: /tmp/t.c:4:3: error: assignment to cast is illegal, lvalue casts are not supported a = 10; ^ ~ /tmp/t.c:2:12: note: instantiated from: #define a ((void*) b) ~^~~~~~~~~~ instead of: /tmp/t.c:4:5: error: expression is not assignable a = 10; ~ ^ llvm-svn: 69114
This commit is contained in:
parent
1be3b53d3c
commit
c2223ab255
|
@ -152,6 +152,10 @@ public:
|
|||
/// and if it is a structure or union, does not have any member (including,
|
||||
/// recursively, any member or element of all contained aggregates or unions)
|
||||
/// with a const-qualified type.
|
||||
///
|
||||
/// \param Loc [in] [out] - A source location which *may* be filled
|
||||
/// in with the location of the expression making this a
|
||||
/// non-modifiable lvalue, if specified.
|
||||
enum isModifiableLvalueResult {
|
||||
MLV_Valid,
|
||||
MLV_NotObjectType,
|
||||
|
@ -167,7 +171,8 @@ public:
|
|||
MLV_NoSetterProperty,
|
||||
MLV_MemberFunction
|
||||
};
|
||||
isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx) const;
|
||||
isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx,
|
||||
SourceLocation *Loc = 0) const;
|
||||
|
||||
bool isBitField();
|
||||
|
||||
|
|
|
@ -756,7 +756,8 @@ Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const {
|
|||
/// if it is a structure or union, does not have any member (including,
|
||||
/// recursively, any member or element of all contained aggregates or unions)
|
||||
/// with a const-qualified type.
|
||||
Expr::isModifiableLvalueResult Expr::isModifiableLvalue(ASTContext &Ctx) const {
|
||||
Expr::isModifiableLvalueResult
|
||||
Expr::isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc) const {
|
||||
isLvalueResult lvalResult = isLvalue(Ctx);
|
||||
|
||||
switch (lvalResult) {
|
||||
|
@ -775,9 +776,13 @@ Expr::isModifiableLvalueResult Expr::isModifiableLvalue(ASTContext &Ctx) const {
|
|||
// lvalue, then this is probably a use of the old-school "cast as lvalue"
|
||||
// GCC extension. We don't support it, but we want to produce good
|
||||
// diagnostics when it happens so that the user knows why.
|
||||
if (const CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(IgnoreParens()))
|
||||
if (CE->getSubExpr()->isLvalue(Ctx) == LV_Valid)
|
||||
if (const CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(IgnoreParens())) {
|
||||
if (CE->getSubExpr()->isLvalue(Ctx) == LV_Valid) {
|
||||
if (Loc)
|
||||
*Loc = CE->getLParenLoc();
|
||||
return MLV_LValueCast;
|
||||
}
|
||||
}
|
||||
return MLV_InvalidExpression;
|
||||
case LV_MemberFunction: return MLV_MemberFunction;
|
||||
}
|
||||
|
|
|
@ -3725,7 +3725,9 @@ static bool IsReadonlyProperty(Expr *E, Sema &S)
|
|||
/// CheckForModifiableLvalue - Verify that E is a modifiable lvalue. If not,
|
||||
/// emit an error and return true. If so, return false.
|
||||
static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
|
||||
Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(S.Context);
|
||||
SourceLocation OrigLoc = Loc;
|
||||
Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(S.Context,
|
||||
&Loc);
|
||||
if (IsLV == Expr::MLV_Valid && IsReadonlyProperty(E, S))
|
||||
IsLV = Expr::MLV_ReadonlyProperty;
|
||||
if (IsLV == Expr::MLV_Valid)
|
||||
|
@ -3769,10 +3771,13 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
|
|||
break;
|
||||
}
|
||||
|
||||
SourceRange Assign;
|
||||
if (Loc != OrigLoc)
|
||||
Assign = SourceRange(OrigLoc, OrigLoc);
|
||||
if (NeedType)
|
||||
S.Diag(Loc, Diag) << E->getType() << E->getSourceRange();
|
||||
S.Diag(Loc, Diag) << E->getType() << E->getSourceRange() << Assign;
|
||||
else
|
||||
S.Diag(Loc, Diag) << E->getSourceRange();
|
||||
S.Diag(Loc, Diag) << E->getSourceRange() << Assign;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,8 @@ void test4() {
|
|||
// rdar://6319320
|
||||
void test5(int *X, float *P) {
|
||||
(float*)X = P; // expected-error {{assignment to cast is illegal, lvalue casts are not supported}}
|
||||
((float*)X) = P; // expected-error {{assignment to cast is illegal, lvalue casts are not supported}}
|
||||
#define FOO ((float*) X)
|
||||
FOO = P; // expected-error {{assignment to cast is illegal, lvalue casts are not supported}}
|
||||
}
|
||||
|
||||
void test6() {
|
||||
|
|
Loading…
Reference in New Issue