diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 29 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 62 |
2 files changed, 66 insertions, 25 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 960c99af1f2..0e62e26e8b5 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2145,9 +2145,12 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, Diag(Loc, diag::warn_selfcomparison); } + // The result of comparisons is 'bool' in C++, 'int' in C. + QualType ResultTy = getLangOptions().CPlusPlus? Context.BoolTy : Context.IntTy; + if (isRelational) { if (lType->isRealType() && rType->isRealType()) - return Context.IntTy; + return ResultTy; } else { // Check for comparisons of floating point operands using != and ==. if (lType->isFloatingType()) { @@ -2156,7 +2159,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, } if (lType->isArithmeticType() && rType->isArithmeticType()) - return Context.IntTy; + return ResultTy; } bool LHSIsNull = lex->isNullPointerConstant(Context); @@ -2181,7 +2184,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, << lex->getSourceRange() << rex->getSourceRange(); } ImpCastExprToType(rex, lType); // promote the pointer to pointer - return Context.IntTy; + return ResultTy; } // Handle block pointer types. if (lType->isBlockPointerType() && rType->isBlockPointerType()) { @@ -2195,7 +2198,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, << lex->getSourceRange() << rex->getSourceRange(); } ImpCastExprToType(rex, lType); // promote the pointer to pointer - return Context.IntTy; + return ResultTy; } // Allow block pointers to be compared with null pointer constants. if ((lType->isBlockPointerType() && rType->isPointerType()) || @@ -2206,7 +2209,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, << lex->getSourceRange() << rex->getSourceRange(); } ImpCastExprToType(rex, lType); // promote the pointer to pointer - return Context.IntTy; + return ResultTy; } if ((lType->isObjCQualifiedIdType() || rType->isObjCQualifiedIdType())) { @@ -2224,21 +2227,21 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, << lType.getAsString() << rType.getAsString() << lex->getSourceRange() << rex->getSourceRange(); ImpCastExprToType(rex, lType); - return Context.IntTy; + return ResultTy; } ImpCastExprToType(rex, lType); - return Context.IntTy; + return ResultTy; } if (ObjCQualifiedIdTypesAreCompatible(lType, rType, true)) { ImpCastExprToType(rex, lType); - return Context.IntTy; + return ResultTy; } else { if ((lType->isObjCQualifiedIdType() && rType->isObjCQualifiedIdType())) { Diag(Loc, diag::warn_incompatible_qualified_id_operands) << lType.getAsString() << rType.getAsString() << lex->getSourceRange() << rex->getSourceRange(); ImpCastExprToType(rex, lType); - return Context.IntTy; + return ResultTy; } } } @@ -2249,7 +2252,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, << lType.getAsString() << rType.getAsString() << lex->getSourceRange() << rex->getSourceRange(); ImpCastExprToType(rex, lType); // promote the integer to pointer - return Context.IntTy; + return ResultTy; } if (lType->isIntegerType() && (rType->isPointerType() || rType->isObjCQualifiedIdType())) { @@ -2258,7 +2261,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, << lType.getAsString() << rType.getAsString() << lex->getSourceRange() << rex->getSourceRange(); ImpCastExprToType(lex, rType); // promote the integer to pointer - return Context.IntTy; + return ResultTy; } // Handle block pointers. if (lType->isBlockPointerType() && rType->isIntegerType()) { @@ -2267,7 +2270,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, << lType.getAsString() << rType.getAsString() << lex->getSourceRange() << rex->getSourceRange(); ImpCastExprToType(rex, lType); // promote the integer to pointer - return Context.IntTy; + return ResultTy; } if (lType->isIntegerType() && rType->isBlockPointerType()) { if (!LHSIsNull) @@ -2275,7 +2278,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, << lType.getAsString() << rType.getAsString() << lex->getSourceRange() << rex->getSourceRange(); ImpCastExprToType(lex, rType); // promote the integer to pointer - return Context.IntTy; + return ResultTy; } return InvalidOperands(Loc, lex, rex); } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 749b916e0d6..98a32ef2679 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -637,7 +637,7 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) Context.IntTy, Context.UnsignedIntTy, Context.LongTy, Context.UnsignedLongTy }; - for (int Idx = 0; Idx < 0; ++Idx) { + for (int Idx = 0; Idx < 4; ++Idx) { uint64_t ToSize = Context.getTypeSize(PromoteTypes[Idx]); if (FromSize < ToSize || (FromSize == ToSize && @@ -1712,6 +1712,42 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, } } +/// IsAcceptableNonMemberOperatorCandidate - Determine whether Fn is +/// an acceptable non-member overloaded operator for a call whose +/// arguments have types T1 (and, if non-empty, T2). This routine +/// implements the check in C++ [over.match.oper]p3b2 concerning +/// enumeration types. +static bool +IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn, + QualType T1, QualType T2, + ASTContext &Context) { + if (T1->isRecordType() || (!T2.isNull() && T2->isRecordType())) + return true; + + const FunctionTypeProto *Proto = Fn->getType()->getAsFunctionTypeProto(); + if (Proto->getNumArgs() < 1) + return false; + + if (T1->isEnumeralType()) { + QualType ArgType = Proto->getArgType(0).getNonReferenceType(); + if (Context.getCanonicalType(T1).getUnqualifiedType() + == Context.getCanonicalType(ArgType).getUnqualifiedType()) + return true; + } + + if (Proto->getNumArgs() < 2) + return false; + + if (!T2.isNull() && T2->isEnumeralType()) { + QualType ArgType = Proto->getArgType(1).getNonReferenceType(); + if (Context.getCanonicalType(T2).getUnqualifiedType() + == Context.getCanonicalType(ArgType).getUnqualifiedType()) + return true; + } + + return false; +} + /// AddOperatorCandidates - Add the overloaded operator candidates for /// the operator Op that was used in an operator expression such as "x /// Op y". S is the scope in which the expression occurred (used for @@ -1790,18 +1826,19 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S, break; } - // FIXME: check that strange "However" condition above. It's going - // to need a special test. - if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(NonMemberOps)) - AddOverloadCandidate(FD, Args, NumArgs, CandidateSet, - /*SuppressUserConversions=*/false); - else if (OverloadedFunctionDecl *Ovl - = dyn_cast_or_null<OverloadedFunctionDecl>(NonMemberOps)) { + if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(NonMemberOps)) { + if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context)) + AddOverloadCandidate(FD, Args, NumArgs, CandidateSet, + /*SuppressUserConversions=*/false); + } else if (OverloadedFunctionDecl *Ovl + = dyn_cast_or_null<OverloadedFunctionDecl>(NonMemberOps)) { for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(), FEnd = Ovl->function_end(); - F != FEnd; ++F) - AddOverloadCandidate(*F, Args, NumArgs, CandidateSet, - /*SuppressUserConversions=*/false); + F != FEnd; ++F) { + if (IsAcceptableNonMemberOperatorCandidate(*F, T1, T2, Context)) + AddOverloadCandidate(*F, Args, NumArgs, CandidateSet, + /*SuppressUserConversions=*/false); + } } } @@ -2476,7 +2513,8 @@ Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1, // the type of the entity being initialized) is a better // conversion sequence than the standard conversion sequence // from the return type of F2 to the destination type. - if (isa<CXXConversionDecl>(Cand1.Function) && + if (Cand1.Function && Cand2.Function && + isa<CXXConversionDecl>(Cand1.Function) && isa<CXXConversionDecl>(Cand2.Function)) { switch (CompareStandardConversionSequences(Cand1.FinalConversion, Cand2.FinalConversion)) { |