Index: cfe/trunk/lib/Sema/SemaChecking.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaChecking.cpp +++ cfe/trunk/lib/Sema/SemaChecking.cpp @@ -12383,12 +12383,6 @@ return; const Type *BaseType = ArrayTy->getElementType().getTypePtr(); - // It is possible that the type of the base expression after IgnoreParenCasts - // is incomplete, even though the type of the base expression before - // IgnoreParenCasts is complete (see PR39746 for an example). In this case we - // have no information about whether the array access is out-of-bounds. - if (BaseType->isIncompleteType()) - return; Expr::EvalResult Result; if (!IndexExpr->EvaluateAsInt(Result, Context, Expr::SE_AllowSideEffects)) @@ -12405,6 +12399,15 @@ ND = ME->getMemberDecl(); if (index.isUnsigned() || !index.isNegative()) { + // It is possible that the type of the base expression after + // IgnoreParenCasts is incomplete, even though the type of the base + // expression before IgnoreParenCasts is complete (see PR39746 for an + // example). In this case we have no information about whether the array + // access exceeds the array bounds. However we can still diagnose an array + // access which precedes the array bounds. + if (BaseType->isIncompleteType()) + return; + llvm::APInt size = ArrayTy->getSize(); if (!size.isStrictlyPositive()) return; Index: cfe/trunk/test/SemaCXX/array-bounds.cpp =================================================================== --- cfe/trunk/test/SemaCXX/array-bounds.cpp +++ cfe/trunk/test/SemaCXX/array-bounds.cpp @@ -287,9 +287,12 @@ namespace PR39746 { struct S; - extern S xxx[2]; + extern S xxx[2]; // expected-note {{array 'xxx' declared here}} class C {}; C &f() { return reinterpret_cast(xxx)[1]; } // no-warning + // We have no info on whether this is out-of-bounds. C &g() { return reinterpret_cast(xxx)[2]; } // no-warning + // We can still diagnose this. + C &h() { return reinterpret_cast(xxx)[-1]; } // expected-warning {{array index -1 is before the beginning of the array}} }