diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 628f233d6813..6b82eadaea2c 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1571,6 +1571,12 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, } else MemberDecl = Result; + // If the decl being referenced had an error, return an error for this + // sub-expr without emitting another error, in order to avoid cascading + // error cases. + if (MemberDecl->isInvalidDecl()) + return ExprError(); + if (FieldDecl *FD = dyn_cast(MemberDecl)) { // We may have found a field within an anonymous union or struct // (C++ [class.union]). @@ -1623,6 +1629,12 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, // (*Obj).ivar. if (const ObjCInterfaceType *IFTy = BaseType->getAsObjCInterfaceType()) { if (ObjCIvarDecl *IV = IFTy->getDecl()->lookupInstanceVariable(&Member)) { + // If the decl being referenced had an error, return an error for this + // sub-expr without emitting another error, in order to avoid cascading + // error cases. + if (IV->isInvalidDecl()) + return ExprError(); + ObjCIvarRefExpr *MRef= new (Context) ObjCIvarRefExpr(IV, IV->getType(), MemberLoc, BaseExpr, OpKind == tok::arrow); diff --git a/clang/test/Sema/exprs.c b/clang/test/Sema/exprs.c index db2daf1f7ca8..4ddb976eb2e0 100644 --- a/clang/test/Sema/exprs.c +++ b/clang/test/Sema/exprs.c @@ -57,3 +57,10 @@ int test9(struct f *P) { return R; } +// PR3562 +void test10(int n,...) { + struct S { + double a[n]; // expected-error {{fields must have a constant size}} + } s; + double x = s.a[0]; // should not get another error here. +}