From: Douglas Gregor Date: Thu, 13 Nov 2008 20:12:29 +0000 (+0000) Subject: Some cleanup for the implementation of built-in operator X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bf3af056289893f58d37b05a2c80970708781d61;p=clang Some cleanup for the implementation of built-in operator candidates. Thanks to Chris for the review! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59260 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 6fe205cd08..6e376cedba 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -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; diff --git a/include/clang/AST/TypeOrdering.h b/include/clang/AST/TypeOrdering.h index b3d826cf38..4f60273d68 100644 --- a/include/clang/AST/TypeOrdering.h +++ b/include/clang/AST/TypeOrdering.h @@ -17,7 +17,6 @@ #define LLVM_CLANG_TYPE_ORDERING_H #include "clang/AST/Type.h" -#include "llvm/ADT/DenseMap.h" #include namespace clang { @@ -33,6 +32,8 @@ struct QualTypeOrdering : std::binary_function { } namespace llvm { + template struct DenseMapInfo; + template<> struct DenseMapInfo { static inline clang::QualType getEmptyKey() { return clang::QualType(); } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index c320cfc670..249bebc91f 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -397,19 +397,18 @@ Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const { case BinaryOperatorClass: case CompoundAssignOperatorClass: { const BinaryOperator *BinOp = cast(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: diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 21bf990fba..c9f311a204 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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) diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 9229fa35d2..58ab5aa759 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -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 @@ -1588,7 +1588,7 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys, /// enumeration types. class BuiltinCandidateTypeSet { /// TypeSet - A set of types. - typedef llvm::DenseSet TypeSet; + typedef llvm::SmallPtrSet 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(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.