[cfe-commits] r69534 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaExprCXX.cpp test/SemaCXX/conditional-expr.cpp
Sebastian Redl
sebastian.redl at getdesigned.at
Sun Apr 19 12:26:31 PDT 2009
Author: cornedbee
Date: Sun Apr 19 14:26:31 2009
New Revision: 69534
URL: http://llvm.org/viewvc/llvm-project?rev=69534&view=rev
Log:
Another piece of the conditional operator puzzle. We'll want to use FindCompositePointerType in some other places, too.
Modified:
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/test/SemaCXX/conditional-expr.cpp
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=69534&r1=69533&r2=69534&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sun Apr 19 14:26:31 2009
@@ -2389,7 +2389,7 @@
QualType rhsType);
// Helper function for CheckAssignmentConstraints involving two
- // blcok pointer types.
+ // block pointer types.
AssignConvertType CheckBlockPointerTypesForAssignment(QualType lhsType,
QualType rhsType);
@@ -2440,6 +2440,7 @@
Expr *&cond, Expr *&lhs, Expr *&rhs, SourceLocation questionLoc);
QualType CXXCheckConditionalOperands( // C++ 5.16
Expr *&cond, Expr *&lhs, Expr *&rhs, SourceLocation questionLoc);
+ QualType FindCompositePointerType(Expr *&E1, Expr *&E2); // C++ 5.9
/// type checking for vector binary operators.
inline QualType CheckVectorOperands(SourceLocation l, Expr *&lex, Expr *&rex);
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=69534&r1=69533&r2=69534&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sun Apr 19 14:26:31 2009
@@ -1307,21 +1307,101 @@
// type and the other is a null pointer constant; pointer conversions
// and qualification conversions are performed to bring them to their
// composite pointer type. The result is of the composite pointer type.
- // Fourth bullet is same for pointers-to-member.
- if ((LTy->isPointerType() || LTy->isMemberPointerType()) &&
- RHS->isNullPointerConstant(Context)) {
- ImpCastExprToType(RHS, LTy); // promote the null to a pointer.
- return LTy;
- }
- if ((RTy->isPointerType() || RTy->isMemberPointerType()) &&
- LHS->isNullPointerConstant(Context)) {
- ImpCastExprToType(LHS, RTy); // promote the null to a pointer.
- return RTy;
- }
+ QualType Composite = FindCompositePointerType(LHS, RHS);
+ if (!Composite.isNull())
+ return Composite;
- // FIXME: Handle the case where both are pointers.
+ // Fourth bullet is same for pointers-to-member.
+ // FIXME: Handle this case where both are member pointers.
Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
<< LHS->getType() << RHS->getType()
<< LHS->getSourceRange() << RHS->getSourceRange();
return QualType();
}
+
+/// \brief Find a merged pointer type and convert the two expressions to it.
+///
+/// This finds the composite pointer type for @p E1 and @p E2 according to
+/// C++0x 5.9p2. It converts both expressions to this type and returns it.
+/// It does not emit diagnostics.
+QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) {
+ assert(getLangOptions().CPlusPlus && "This function assumes C++");
+ QualType T1 = E1->getType(), T2 = E2->getType();
+ if(!T1->isPointerType() && !T2->isPointerType())
+ return QualType();
+
+ // C++0x 5.9p2
+ // Pointer conversions and qualification conversions are performed on
+ // pointer operands to bring them to their composite pointer type. If
+ // one operand is a null pointer constant, the composite pointer type is
+ // the type of the other operand.
+ if (E1->isNullPointerConstant(Context)) {
+ ImpCastExprToType(E1, T2);
+ return T2;
+ }
+ if (E2->isNullPointerConstant(Context)) {
+ ImpCastExprToType(E2, T1);
+ return T1;
+ }
+ // Now both have to be pointers.
+ if(!T1->isPointerType() || !T2->isPointerType())
+ return QualType();
+
+ // Otherwise, of one of the operands has type "pointer to cv1 void," then
+ // the other has type "pointer to cv2 T" and the composite pointer type is
+ // "pointer to cv12 void," where cv12 is the union of cv1 and cv2.
+ // Otherwise, the composite pointer type is a pointer type similar to the
+ // type of one of the operands, with a cv-qualification signature that is
+ // the union of the cv-qualification signatures of the operand types.
+ // In practice, the first part here is redundant; it's subsumed by the second.
+ // What we do here is, we build the two possible composite types, and try the
+ // conversions in both directions. If only one works, or if the two composite
+ // types are the same, we have succeeded.
+ llvm::SmallVector<unsigned, 4> QualifierUnion;
+ QualType Composite1 = T1, Composite2 = T2;
+ const PointerType *Ptr1, *Ptr2;
+ while ((Ptr1 = Composite1->getAsPointerType()) &&
+ (Ptr2 = Composite2->getAsPointerType())) {
+ Composite1 = Ptr1->getPointeeType();
+ Composite2 = Ptr2->getPointeeType();
+ QualifierUnion.push_back(
+ Composite1.getCVRQualifiers() | Composite2.getCVRQualifiers());
+ }
+ // Rewrap the composites as pointers with the union CVRs.
+ for (llvm::SmallVector<unsigned, 4>::iterator I = QualifierUnion.begin(),
+ E = QualifierUnion.end(); I != E; ++I) {
+ Composite1 = Context.getPointerType(Composite1.getQualifiedType(*I));
+ Composite2 = Context.getPointerType(Composite2.getQualifiedType(*I));
+ }
+
+ ImplicitConversionSequence E1ToC1 = TryImplicitConversion(E1, Composite1);
+ ImplicitConversionSequence E2ToC1 = TryImplicitConversion(E2, Composite1);
+ ImplicitConversionSequence E1ToC2, E2ToC2;
+ E1ToC2.ConversionKind = ImplicitConversionSequence::BadConversion;
+ E2ToC2.ConversionKind = ImplicitConversionSequence::BadConversion;
+ if (Context.getCanonicalType(Composite1) !=
+ Context.getCanonicalType(Composite2)) {
+ E1ToC2 = TryImplicitConversion(E1, Composite2);
+ E2ToC2 = TryImplicitConversion(E2, Composite2);
+ }
+
+ bool ToC1Viable = E1ToC1.ConversionKind !=
+ ImplicitConversionSequence::BadConversion
+ && E2ToC1.ConversionKind !=
+ ImplicitConversionSequence::BadConversion;
+ bool ToC2Viable = E1ToC2.ConversionKind !=
+ ImplicitConversionSequence::BadConversion
+ && E2ToC2.ConversionKind !=
+ ImplicitConversionSequence::BadConversion;
+ if (ToC1Viable && !ToC2Viable) {
+ if (!PerformImplicitConversion(E1, Composite1, E1ToC1, "converting") &&
+ !PerformImplicitConversion(E2, Composite1, E2ToC1, "converting"))
+ return Composite1;
+ }
+ if (ToC2Viable && !ToC1Viable) {
+ if (!PerformImplicitConversion(E1, Composite2, E1ToC2, "converting") &&
+ !PerformImplicitConversion(E2, Composite2, E2ToC2, "converting"))
+ return Composite2;
+ }
+ return QualType();
+}
Modified: cfe/trunk/test/SemaCXX/conditional-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conditional-expr.cpp?rev=69534&r1=69533&r2=69534&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/conditional-expr.cpp (original)
+++ cfe/trunk/test/SemaCXX/conditional-expr.cpp Sun Apr 19 14:26:31 2009
@@ -146,13 +146,13 @@
i1 = i1 ? EVal : i1;
d1 = i1 ? 'c' : 4.0;
d1 = i1 ? 4.0 : 'c';
- pfm = i1 ? &Derived::fn2 : 0;
- pfm = i1 ? 0 : &Derived::fn2;
- // FIXME: pointer conversions don't work yet.
- //Base *pb = i1 ? (Base*)0 : (Derived*)0;
- //Base *pb = i1 ? (Derived*)0 : (Base*)0;
+ Base *pb = i1 ? (Base*)0 : (Derived*)0;
+ pb = i1 ? (Derived*)0 : (Base*)0;
+ // FIXME: member pointer conversions don't work yet.
//pfm = i1 ? &Base::fn1 : &Derived::fn2;
//pfm = i1 ? &Derived::fn2 : &Base::fn1;
+ //pfm = i1 ? &Derived::fn2 : 0;
+ //pfm = i1 ? 0 : &Derived::fn2;
// Conversion of primitives does not result in an lvalue.
&(i1 ? i1 : d1); // expected-error {{address expression must be an lvalue or a function designator}}
More information about the cfe-commits
mailing list