Some cleanup for the implementation of built-in operator
candidates. Thanks to Chris for the review! llvm-svn: 59260
This commit is contained in:
parent
f8cfd1647e
commit
58e008d2a6
|
@ -833,6 +833,17 @@ public:
|
|||
/// source code. For example: converting T[]->T*, void f()->void
|
||||
/// (*f)(), float->double, short->int, etc.
|
||||
///
|
||||
/// In C, implicit casts always produce rvalues. However, in C++, an
|
||||
/// implicit cast whose result is being bound to a reference will be
|
||||
/// an lvalue. For example:
|
||||
///
|
||||
/// @code
|
||||
/// class Base { };
|
||||
/// class Derived : public Base { };
|
||||
/// void f(Derived d) {
|
||||
/// Base& b = d; // initializer is an ImplicitCastExpr to an lvalue of type Base
|
||||
/// }
|
||||
/// @endcode
|
||||
class ImplicitCastExpr : public CastExpr {
|
||||
/// LvalueCast - Whether this cast produces an lvalue.
|
||||
bool LvalueCast;
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#define LLVM_CLANG_TYPE_ORDERING_H
|
||||
|
||||
#include "clang/AST/Type.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include <functional>
|
||||
|
||||
namespace clang {
|
||||
|
@ -33,6 +32,8 @@ struct QualTypeOrdering : std::binary_function<QualType, QualType, bool> {
|
|||
}
|
||||
|
||||
namespace llvm {
|
||||
template<class> struct DenseMapInfo;
|
||||
|
||||
template<> struct DenseMapInfo<clang::QualType> {
|
||||
static inline clang::QualType getEmptyKey() { return clang::QualType(); }
|
||||
|
||||
|
|
|
@ -397,19 +397,18 @@ Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const {
|
|||
case BinaryOperatorClass:
|
||||
case CompoundAssignOperatorClass: {
|
||||
const BinaryOperator *BinOp = cast<BinaryOperator>(this);
|
||||
if (BinOp->isAssignmentOp()) {
|
||||
if (Ctx.getLangOptions().CPlusPlus)
|
||||
// C++ [expr.ass]p1:
|
||||
// The result of an assignment operation [...] is an lvalue.
|
||||
return LV_Valid;
|
||||
else
|
||||
// C99 6.5.16:
|
||||
// An assignment expression [...] is not an lvalue.
|
||||
return LV_InvalidExpression;
|
||||
} else
|
||||
if (!BinOp->isAssignmentOp())
|
||||
return LV_InvalidExpression;
|
||||
|
||||
break;
|
||||
if (Ctx.getLangOptions().CPlusPlus)
|
||||
// C++ [expr.ass]p1:
|
||||
// The result of an assignment operation [...] is an lvalue.
|
||||
return LV_Valid;
|
||||
|
||||
|
||||
// C99 6.5.16:
|
||||
// An assignment expression [...] is not an lvalue.
|
||||
return LV_InvalidExpression;
|
||||
}
|
||||
case CallExprClass: {
|
||||
// C++ [expr.call]p10:
|
||||
|
|
|
@ -130,15 +130,10 @@ QualType Sema::UsualArithmeticConversionsType(QualType lhs, QualType rhs) {
|
|||
// lhs == rhs check. Also, for conversion purposes, we ignore any
|
||||
// qualifiers. For example, "const float" and "float" are
|
||||
// equivalent.
|
||||
if (lhs->isPromotableIntegerType())
|
||||
lhs = Context.IntTy;
|
||||
else
|
||||
lhs = Context.getCanonicalType(lhs).getUnqualifiedType();
|
||||
|
||||
if (rhs->isPromotableIntegerType())
|
||||
rhs = Context.IntTy;
|
||||
else
|
||||
rhs = Context.getCanonicalType(rhs).getUnqualifiedType();
|
||||
if (lhs->isPromotableIntegerType()) lhs = Context.IntTy;
|
||||
else lhs = lhs.getUnqualifiedType();
|
||||
if (rhs->isPromotableIntegerType()) rhs = Context.IntTy;
|
||||
else rhs = rhs.getUnqualifiedType();
|
||||
|
||||
// If both types are identical, no conversion is needed.
|
||||
if (lhs == rhs)
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/TypeOrdering.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -1588,7 +1588,7 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
|
|||
/// enumeration types.
|
||||
class BuiltinCandidateTypeSet {
|
||||
/// TypeSet - A set of types.
|
||||
typedef llvm::DenseSet<QualType> TypeSet;
|
||||
typedef llvm::SmallPtrSet<void*, 8> TypeSet;
|
||||
|
||||
/// PointerTypes - The set of pointer types that will be used in the
|
||||
/// built-in candidates.
|
||||
|
@ -1605,7 +1605,45 @@ class BuiltinCandidateTypeSet {
|
|||
|
||||
public:
|
||||
/// iterator - Iterates through the types that are part of the set.
|
||||
typedef TypeSet::iterator iterator;
|
||||
class iterator {
|
||||
TypeSet::iterator Base;
|
||||
|
||||
public:
|
||||
typedef QualType value_type;
|
||||
typedef QualType reference;
|
||||
typedef QualType pointer;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::input_iterator_tag iterator_category;
|
||||
|
||||
iterator(TypeSet::iterator B) : Base(B) { }
|
||||
|
||||
iterator& operator++() {
|
||||
++Base;
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator operator++(int) {
|
||||
iterator tmp(*this);
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
reference operator*() const {
|
||||
return QualType::getFromOpaquePtr(*Base);
|
||||
}
|
||||
|
||||
pointer operator->() const {
|
||||
return **this;
|
||||
}
|
||||
|
||||
friend bool operator==(iterator LHS, iterator RHS) {
|
||||
return LHS.Base == RHS.Base;
|
||||
}
|
||||
|
||||
friend bool operator!=(iterator LHS, iterator RHS) {
|
||||
return LHS.Base != RHS.Base;
|
||||
}
|
||||
};
|
||||
|
||||
BuiltinCandidateTypeSet(ASTContext &Context) : Context(Context) { }
|
||||
|
||||
|
@ -1633,7 +1671,7 @@ public:
|
|||
/// false otherwise.
|
||||
bool BuiltinCandidateTypeSet::AddWithMoreQualifiedTypeVariants(QualType Ty) {
|
||||
// Insert this type.
|
||||
if (!PointerTypes.insert(Ty).second)
|
||||
if (!PointerTypes.insert(Ty.getAsOpaquePtr()))
|
||||
return false;
|
||||
|
||||
if (const PointerType *PointerTy = Ty->getAsPointerType()) {
|
||||
|
@ -1703,7 +1741,7 @@ void BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
|
|||
}
|
||||
}
|
||||
} else if (Ty->isEnumeralType()) {
|
||||
EnumerationTypes.insert(Ty);
|
||||
EnumerationTypes.insert(Ty.getAsOpaquePtr());
|
||||
} else if (AllowUserConversions) {
|
||||
if (const RecordType *TyRec = Ty->getAsRecordType()) {
|
||||
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl());
|
||||
|
@ -1953,7 +1991,7 @@ Sema::AddBuiltinBinaryOperatorCandidates(OverloadedOperatorKind Op,
|
|||
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
|
||||
|
||||
// volatile T& operator=(volatile T&, T)
|
||||
ParamTypes[0] = Context.getReferenceType(Enum->withVolatile());
|
||||
ParamTypes[0] = Context.getReferenceType((*Enum).withVolatile());
|
||||
ParamTypes[1] = *Enum;
|
||||
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
|
||||
}
|
||||
|
@ -1987,7 +2025,7 @@ Sema::AddBuiltinBinaryOperatorCandidates(OverloadedOperatorKind Op,
|
|||
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
|
||||
|
||||
// volatile version
|
||||
ParamTypes[0] = Context.getReferenceType(Ptr->withVolatile());
|
||||
ParamTypes[0] = Context.getReferenceType((*Ptr).withVolatile());
|
||||
AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet);
|
||||
}
|
||||
// Fall through.
|
||||
|
|
Loading…
Reference in New Issue