Index: lib/Sema/SemaChecking.cpp =================================================================== --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -12377,7 +12377,10 @@ return; const Type *BaseType = BaseExpr->getType()->getPointeeOrArrayElementType(); - if (BaseType != EffectiveType) { + // It is possible that the base type is incomplete (see PR39746), even + // though the effective type is complete. In this case we have no info + // about the size of the base type and so skip the following adjustment. + if ((BaseType != EffectiveType) && !BaseType->isIncompleteType(nullptr)) { // Make sure we're comparing apples to apples when comparing index to size uint64_t ptrarith_typesize = Context.getTypeSize(EffectiveType); uint64_t array_typesize = Context.getTypeSize(BaseType); Index: test/SemaCXX/array-bounds.cpp =================================================================== --- test/SemaCXX/array-bounds.cpp +++ test/SemaCXX/array-bounds.cpp @@ -284,3 +284,12 @@ int test_struct_multiarray() { return multi2[4].arr[0]; // expected-warning {{array index 4 is past the end of the array (which contains 4 elements)}} } + +namespace PR39746 { + struct S; + extern S xxx[2]; // expected-note {{array 'xxx' declared here}} + class C {}; + + C &f() { return reinterpret_cast(xxx)[1]; } // no-warning + C &g() { return reinterpret_cast(xxx)[2]; } // expected-warning {{array index 2 is past the end of the array (which contains 2 elements)}} +}