Some cleanup for the implementation of built-in operator

candidates. Thanks to Chris for the review!

llvm-svn: 59260
This commit is contained in:
Douglas Gregor 2008-11-13 20:12:29 +00:00
parent f8cfd1647e
commit 58e008d2a6
5 changed files with 72 additions and 28 deletions

View File

@ -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;

View File

@ -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(); }

View File

@ -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:

View File

@ -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)

View File

@ -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.