[cfe-commits] r97177 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/Sema.h lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp test/SemaCXX/composite-pointer-type.cpp
Douglas Gregor
dgregor at apple.com
Thu Feb 25 14:29:57 PST 2010
Author: dgregor
Date: Thu Feb 25 16:29:57 2010
New Revision: 97177
URL: http://llvm.org/viewvc/llvm-project?rev=97177&view=rev
Log:
When computing the composite pointer type for relational comparisons,
equality comparisons, and conditional operators, produce a composite
pointer type with the appropriate additional "const" qualifiers if the
pointer types would otherwise be incompatible. This is a small
extension (also present in GCC and EDG in a slightly different form)
that permits code like:
void** i; void const** j;
i == j;
with the following extwarn:
t.cpp:5:5: warning: comparison of distinct pointer types ('void **' and
'void const **') uses non-standard composite pointer type
'void const *const *' [-pedantic]
i == j;
~ ^ ~
Fixes PR6346, and I'll be filing a core issue about this with the C++
committee.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/test/SemaCXX/composite-pointer-type.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=97177&r1=97176&r2=97177&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Feb 25 16:29:57 2010
@@ -1828,6 +1828,9 @@
"incompatible operand types (%0 and %1)">;
def err_typecheck_comparison_of_distinct_pointers : Error<
"comparison of distinct pointer types (%0 and %1)">;
+def ext_typecheck_comparison_of_distinct_pointers_nonstandard : ExtWarn<
+ "comparison of distinct pointer types (%0 and %1) uses non-standard "
+ "composite pointer type %2">;
def err_typecheck_vector_comparison : Error<
"comparison of vector types (%0 and %1) not supported yet">;
def err_typecheck_assign_const : Error<"read-only variable is not assignable">;
@@ -2252,6 +2255,9 @@
"operand of type %0 where arithmetic or pointer type is required">;
def err_typecheck_cond_incompatible_operands : Error<
"incompatible operand types (%0 and %1)">;
+def ext_typecheck_cond_incompatible_operands_nonstandard : ExtWarn<
+ "incompatible operand types (%0 and %1) use non-standard composite pointer "
+ "type %2">;
def err_cast_selector_expr : Error<
"cannot type cast @selector expression">;
def warn_typecheck_cond_incompatible_pointers : ExtWarn<
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=97177&r1=97176&r2=97177&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Feb 25 16:29:57 2010
@@ -3947,7 +3947,8 @@
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
+ QualType FindCompositePointerType(Expr *&E1, Expr *&E2,
+ bool *NonStandardCompositeType = 0);
QualType FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS,
SourceLocation questionLoc);
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=97177&r1=97176&r2=97177&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Feb 25 16:29:57 2010
@@ -5324,11 +5324,18 @@
//
// C++ [expr.eq]p1 uses the same notion for (in)equality
// comparisons of pointers.
- QualType T = FindCompositePointerType(lex, rex);
+ bool NonStandardCompositeType = false;
+ QualType T = FindCompositePointerType(lex, rex,
+ isSFINAEContext()? 0 : &NonStandardCompositeType);
if (T.isNull()) {
Diag(Loc, diag::err_typecheck_comparison_of_distinct_pointers)
<< lType << rType << lex->getSourceRange() << rex->getSourceRange();
return QualType();
+ } else if (NonStandardCompositeType) {
+ Diag(Loc,
+ diag::ext_typecheck_comparison_of_distinct_pointers_nonstandard)
+ << lType << rType << T
+ << lex->getSourceRange() << rex->getSourceRange();
}
ImpCastExprToType(lex, T, CastExpr::CK_BitCast);
@@ -5390,11 +5397,18 @@
// of one of the operands, with a cv-qualification signature (4.4)
// that is the union of the cv-qualification signatures of the operand
// types.
- QualType T = FindCompositePointerType(lex, rex);
+ bool NonStandardCompositeType = false;
+ QualType T = FindCompositePointerType(lex, rex,
+ isSFINAEContext()? 0 : &NonStandardCompositeType);
if (T.isNull()) {
Diag(Loc, diag::err_typecheck_comparison_of_distinct_pointers)
- << lType << rType << lex->getSourceRange() << rex->getSourceRange();
+ << lType << rType << lex->getSourceRange() << rex->getSourceRange();
return QualType();
+ } else if (NonStandardCompositeType) {
+ Diag(Loc,
+ diag::ext_typecheck_comparison_of_distinct_pointers_nonstandard)
+ << lType << rType << T
+ << lex->getSourceRange() << rex->getSourceRange();
}
ImpCastExprToType(lex, T, CastExpr::CK_BitCast);
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=97177&r1=97176&r2=97177&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Feb 25 16:29:57 2010
@@ -2080,9 +2080,18 @@
// performed to bring them to a common type, whose cv-qualification
// shall match the cv-qualification of either the second or the third
// operand. The result is of the common type.
- QualType Composite = FindCompositePointerType(LHS, RHS);
- if (!Composite.isNull())
+ bool NonStandardCompositeType = false;
+ QualType Composite = FindCompositePointerType(LHS, RHS,
+ isSFINAEContext()? 0 : &NonStandardCompositeType);
+ if (!Composite.isNull()) {
+ if (NonStandardCompositeType)
+ Diag(QuestionLoc,
+ diag::ext_typecheck_cond_incompatible_operands_nonstandard)
+ << LTy << RTy << Composite
+ << LHS->getSourceRange() << RHS->getSourceRange();
+
return Composite;
+ }
// Similarly, attempt to find composite type of twp objective-c pointers.
Composite = FindCompositeObjCPointerType(LHS, RHS, QuestionLoc);
@@ -2101,7 +2110,16 @@
/// 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) {
+///
+/// If \p NonStandardCompositeType is non-NULL, then we are permitted to find
+/// a non-standard (but still sane) composite type to which both expressions
+/// can be converted. When such a type is chosen, \c *NonStandardCompositeType
+/// will be set true.
+QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2,
+ bool *NonStandardCompositeType) {
+ if (NonStandardCompositeType)
+ *NonStandardCompositeType = false;
+
assert(getLangOptions().CPlusPlus && "This function assumes C++");
QualType T1 = E1->getType(), T2 = E2->getType();
@@ -2152,12 +2170,20 @@
ContainingClassVector MemberOfClass;
QualType Composite1 = Context.getCanonicalType(T1),
Composite2 = Context.getCanonicalType(T2);
+ unsigned NeedConstBefore = 0;
do {
const PointerType *Ptr1, *Ptr2;
if ((Ptr1 = Composite1->getAs<PointerType>()) &&
(Ptr2 = Composite2->getAs<PointerType>())) {
Composite1 = Ptr1->getPointeeType();
Composite2 = Ptr2->getPointeeType();
+
+ // If we're allowed to create a non-standard composite type, keep track
+ // of where we need to fill in additional 'const' qualifiers.
+ if (NonStandardCompositeType &&
+ Composite1.getCVRQualifiers() != Composite2.getCVRQualifiers())
+ NeedConstBefore = QualifierUnion.size();
+
QualifierUnion.push_back(
Composite1.getCVRQualifiers() | Composite2.getCVRQualifiers());
MemberOfClass.push_back(std::make_pair((const Type *)0, (const Type *)0));
@@ -2169,6 +2195,13 @@
(MemPtr2 = Composite2->getAs<MemberPointerType>())) {
Composite1 = MemPtr1->getPointeeType();
Composite2 = MemPtr2->getPointeeType();
+
+ // If we're allowed to create a non-standard composite type, keep track
+ // of where we need to fill in additional 'const' qualifiers.
+ if (NonStandardCompositeType &&
+ Composite1.getCVRQualifiers() != Composite2.getCVRQualifiers())
+ NeedConstBefore = QualifierUnion.size();
+
QualifierUnion.push_back(
Composite1.getCVRQualifiers() | Composite2.getCVRQualifiers());
MemberOfClass.push_back(std::make_pair(MemPtr1->getClass(),
@@ -2182,6 +2215,18 @@
break;
} while (true);
+ if (NeedConstBefore && NonStandardCompositeType) {
+ // Extension: Add 'const' to qualifiers that come before the first qualifier
+ // mismatch, so that our (non-standard!) composite type meets the
+ // requirements of C++ [conv.qual]p4 bullet 3.
+ for (unsigned I = 0; I != NeedConstBefore; ++I) {
+ if ((QualifierUnion[I] & Qualifiers::Const) == 0) {
+ QualifierUnion[I] = QualifierUnion[I] | Qualifiers::Const;
+ *NonStandardCompositeType = true;
+ }
+ }
+ }
+
// Rewrap the composites as pointers or member pointers with the union CVRs.
ContainingClassVector::reverse_iterator MOC
= MemberOfClass.rbegin();
Modified: cfe/trunk/test/SemaCXX/composite-pointer-type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/composite-pointer-type.cpp?rev=97177&r1=97176&r2=97177&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/composite-pointer-type.cpp (original)
+++ cfe/trunk/test/SemaCXX/composite-pointer-type.cpp Thu Feb 25 16:29:57 2010
@@ -50,3 +50,11 @@
bool f(Matrix4 m1, const Matrix4 m2) {
return m1 != m2;
}
+
+// PR6346
+bool f1(bool b, void **p, const void **q) {
+ if (p == q) // expected-warning{{comparison of distinct pointer types ('void **' and 'void const **') uses non-standard composite pointer type 'void const *const *'}}
+ return false;
+
+ return b? p : q; // expected-warning{{incompatible operand types ('void **' and 'void const **') use non-standard composite pointer type 'void const *const *'}}
+}
More information about the cfe-commits
mailing list