@@ -15870,6 +15870,54 @@ static bool checkBuiltinVectorMathMixedEnums(Sema &S, Expr *LHS, Expr *RHS,
1587015870 return false;
1587115871}
1587215872
15873+ /// Check if all arguments have the same type. If the types don't match, emit an
15874+ /// error message and return true. Otherwise return false.
15875+ ///
15876+ /// For scalars we directly compare their unqualified types. But even if we
15877+ /// compare unqualified vector types, a difference in qualifiers in the element
15878+ /// types can make the vector types be considered not equal. For example,
15879+ /// vector of 4 'const float' values vs vector of 4 'float' values.
15880+ /// So we compare unqualified types of their elements and number of elements.
15881+ static bool checkBuiltinVectorMathArgTypes(Sema &SemaRef,
15882+ ArrayRef<Expr *> Args) {
15883+ assert(!Args.empty() && "Should have at least one argument.");
15884+
15885+ Expr *Arg0 = Args.front();
15886+ QualType Ty0 = Arg0->getType();
15887+
15888+ auto EmitError = [&](Expr *ArgI) {
15889+ SemaRef.Diag(Arg0->getBeginLoc(),
15890+ diag::err_typecheck_call_different_arg_types)
15891+ << Arg0->getType() << ArgI->getType();
15892+ };
15893+
15894+ // Compare scalar types.
15895+ if (!Ty0->isVectorType()) {
15896+ for (Expr *ArgI : Args.drop_front())
15897+ if (!SemaRef.Context.hasSameUnqualifiedType(Ty0, ArgI->getType())) {
15898+ EmitError(ArgI);
15899+ return true;
15900+ }
15901+
15902+ return false;
15903+ }
15904+
15905+ // Compare vector types.
15906+ const auto *Vec0 = Ty0->castAs<VectorType>();
15907+ for (Expr *ArgI : Args.drop_front()) {
15908+ const auto *VecI = ArgI->getType()->getAs<VectorType>();
15909+ if (!VecI ||
15910+ !SemaRef.Context.hasSameUnqualifiedType(Vec0->getElementType(),
15911+ VecI->getElementType()) ||
15912+ Vec0->getNumElements() != VecI->getNumElements()) {
15913+ EmitError(ArgI);
15914+ return true;
15915+ }
15916+ }
15917+
15918+ return false;
15919+ }
15920+
1587315921std::optional<QualType>
1587415922Sema::BuiltinVectorMath(CallExpr *TheCall,
1587515923 EltwiseBuiltinArgTyRestriction ArgTyRestr) {
@@ -15891,15 +15939,12 @@ Sema::BuiltinVectorMath(CallExpr *TheCall,
1589115939
1589215940 SourceLocation LocA = Args[0]->getBeginLoc();
1589315941 QualType TyA = Args[0]->getType();
15894- QualType TyB = Args[1]->getType();
1589515942
1589615943 if (checkMathBuiltinElementType(*this, LocA, TyA, ArgTyRestr, 1))
1589715944 return std::nullopt;
1589815945
15899- if (!Context.hasSameUnqualifiedType(TyA, TyB)) {
15900- Diag(LocA, diag::err_typecheck_call_different_arg_types) << TyA << TyB;
15946+ if (checkBuiltinVectorMathArgTypes(*this, Args))
1590115947 return std::nullopt;
15902- }
1590315948
1590415949 TheCall->setArg(0, Args[0]);
1590515950 TheCall->setArg(1, Args[1]);
@@ -15934,17 +15979,11 @@ bool Sema::BuiltinElementwiseTernaryMath(
1593415979 return true;
1593515980 }
1593615981
15937- TheCall->setArg(0, Args[0]);
15938- for (int I = 1; I < 3; ++I) {
15939- if (Args[0]->getType().getCanonicalType() !=
15940- Args[I]->getType().getCanonicalType()) {
15941- return Diag(Args[0]->getBeginLoc(),
15942- diag::err_typecheck_call_different_arg_types)
15943- << Args[0]->getType() << Args[I]->getType();
15944- }
15982+ if (checkBuiltinVectorMathArgTypes(*this, Args))
15983+ return true;
1594515984
15985+ for (int I = 0; I < 3; ++I)
1594615986 TheCall->setArg(I, Args[I]);
15947- }
1594815987
1594915988 TheCall->setType(Args[0]->getType());
1595015989 return false;
0 commit comments