diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4785,8 +4785,17 @@ // Build an unanalyzed expression if either operand is type-dependent. if (getLangOpts().CPlusPlus && (base->isTypeDependent() || idx->isTypeDependent())) { - return new (Context) ArraySubscriptExpr(base, idx, Context.DependentTy, - VK_LValue, OK_Ordinary, rbLoc); + QualType Type = Context.DependentTy; + // Refine type if LHS is an array or pointer. + // This is safe because overloading is not possible in this case, and + // arrays/pointers can't be the index of of a builtin subscript. + // Don't bother for RHS, that case is very rare. + if (const PointerType *PT = base->getType()->getAs()) + Type = PT->getPointeeType(); + else if (const ArrayType *AT = base->getType()->getAsArrayTypeUnsafe()) + Type = AT->getElementType(); + return new (Context) + ArraySubscriptExpr(base, idx, Type, VK_LValue, OK_Ordinary, rbLoc); } // MSDN, property (C++) @@ -5541,6 +5550,13 @@ BaseExpr = LHSExp; IndexExpr = RHSExp; ResultType = Context.DependentTy; + // One of LHS and RHS must be pointer, the other must be array. + // We don't know in general, but determine a more specific type if we can. + // Don't bother for the uncommon case where the index is on the left. + if (const PointerType *PT = LHSTy->getAs()) + ResultType = PT->getPointeeType(); + else if (const ArrayType *AT = LHSTy->getAsArrayTypeUnsafe()) + ResultType = AT->getElementType(); } else if (const PointerType *PTy = LHSTy->getAs()) { BaseExpr = LHSExp; IndexExpr = RHSExp; diff --git a/clang/test/AST/ast-dump-array.cpp b/clang/test/AST/ast-dump-array.cpp --- a/clang/test/AST/ast-dump-array.cpp +++ b/clang/test/AST/ast-dump-array.cpp @@ -25,3 +25,32 @@ // CHECK: `-DependentSizedArrayType 0x{{[^ ]*}} 'T [Size]' dependent }; +template +void testDependentSubscript() { + U* a; + U b[5]; + Idx i{}; + + // Can types of subscript expressions can be determined? + // LHS is a type-dependent array + a[1]; + // CHECK: ArraySubscriptExpr {{.*}} 'U' lvalue + b[1]; + // CHECK: ArraySubscriptExpr {{.*}} 'U' lvalue + + // LHS is a type-dependent array, RHS is type-dependent. + a[i]; + // CHECK: ArraySubscriptExpr {{.*}} 'U' lvalue + b[i]; + // CHECK: ArraySubscriptExpr {{.*}} 'U' lvalue + + struct V; + V *a2; + V b2[5]; + + // LHS is a known array, RHS is type-dependent. + a2[i]; + // CHECK: ArraySubscriptExpr {{.*}} 'V' lvalue + b2[i]; + // CHECK: ArraySubscriptExpr {{.*}} 'V' lvalue +};