sammccall created this revision. sammccall added reviewers: kadircet, rsmith. Herald added a subscriber: usaxena95. sammccall requested review of this revision. Herald added subscribers: cfe-commits, ilya-biryukov. Herald added a project: clang.
This more precise type is useful for tools, e.g. fixes https://github.com/clangd/clangd/issues/831 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D107275 Files: clang/lib/Sema/SemaExpr.cpp clang/test/AST/ast-dump-array.cpp Index: clang/test/AST/ast-dump-array.cpp =================================================================== --- clang/test/AST/ast-dump-array.cpp +++ clang/test/AST/ast-dump-array.cpp @@ -25,3 +25,32 @@ // CHECK: `-DependentSizedArrayType 0x{{[^ ]*}} 'T [Size]' dependent <col:25, col:30> }; +template <typename U, typename Idx> +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 +}; Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ 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<PointerType>()) + 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<PointerType>()) + ResultType = PT->getPointeeType(); + else if (const ArrayType *AT = LHSTy->getAsArrayTypeUnsafe()) + ResultType = AT->getElementType(); } else if (const PointerType *PTy = LHSTy->getAs<PointerType>()) { BaseExpr = LHSExp; IndexExpr = RHSExp;
Index: clang/test/AST/ast-dump-array.cpp =================================================================== --- clang/test/AST/ast-dump-array.cpp +++ clang/test/AST/ast-dump-array.cpp @@ -25,3 +25,32 @@ // CHECK: `-DependentSizedArrayType 0x{{[^ ]*}} 'T [Size]' dependent <col:25, col:30> }; +template <typename U, typename Idx> +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 +}; Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ 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<PointerType>()) + 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<PointerType>()) + ResultType = PT->getPointeeType(); + else if (const ArrayType *AT = LHSTy->getAsArrayTypeUnsafe()) + ResultType = AT->getElementType(); } else if (const PointerType *PTy = LHSTy->getAs<PointerType>()) { BaseExpr = LHSExp; IndexExpr = RHSExp;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits