[cfe-commits] r61246 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaOverload.h test/SemaObjCXX/overload.mm
Douglas Gregor
dgregor at apple.com
Fri Dec 19 09:40:10 PST 2008
Author: dgregor
Date: Fri Dec 19 11:40:08 2008
New Revision: 61246
URL: http://llvm.org/viewvc/llvm-project?rev=61246&view=rev
Log:
Allow downcasts of pointers to Objective-C interfaces, with a
warning. This matches GCC's behavior and addresses
<rdar://problem/6458293>.
Modified:
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/SemaOverload.h
cfe/trunk/test/SemaObjCXX/overload.mm
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=61246&r1=61245&r2=61246&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Dec 19 11:40:08 2008
@@ -382,7 +382,7 @@
bool IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType);
bool IsFloatingPointPromotion(QualType FromType, QualType ToType);
bool IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
- QualType& ConvertedType);
+ QualType& ConvertedType, bool &IncompatibleObjC);
bool CheckPointerConversion(Expr *From, QualType ToType);
bool IsQualificationConversion(QualType FromType, QualType ToType);
bool IsUserDefinedConversion(Expr *From, QualType ToType,
@@ -1260,9 +1260,11 @@
bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType);
- bool PerformImplicitConversion(Expr *&From, QualType ToType);
+ bool PerformImplicitConversion(Expr *&From, QualType ToType,
+ const char *Flavor);
bool PerformImplicitConversion(Expr *&From, QualType ToType,
- const StandardConversionSequence& SCS);
+ const StandardConversionSequence& SCS,
+ const char *Flavor);
/// the following "Check" methods will return a valid/converted QualType
/// or a null QualType (indicating an error diagnostic was issued).
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=61246&r1=61245&r2=61246&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Dec 19 11:40:08 2008
@@ -744,7 +744,10 @@
// Get the type before calling CheckSingleAssignmentConstraints(), since
// it can promote the expression.
QualType InitType = Init->getType();
-
+
+ if (getLangOptions().CPlusPlus)
+ return PerformCopyInitialization(Init, DeclType, "initializing");
+
AssignConvertType ConvTy = CheckSingleAssignmentConstraints(DeclType, Init);
return DiagnoseAssignmentResult(ConvTy, Init->getLocStart(), DeclType,
InitType, Init, "initializing");
@@ -843,7 +846,7 @@
// destination type.
// FIXME: We're pretending to do copy elision here; return to
// this when we have ASTs for such things.
- if (!PerformImplicitConversion(Init, DeclType))
+ if (!PerformImplicitConversion(Init, DeclType, "initializing"))
return false;
return Diag(InitLoc, diag::err_typecheck_convert_incompatible)
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=61246&r1=61245&r2=61246&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Dec 19 11:40:08 2008
@@ -1838,7 +1838,7 @@
*ICS = TryImplicitConversion(Init, T1, SuppressUserConversions);
return ICS->ConversionKind == ImplicitConversionSequence::BadConversion;
} else {
- return PerformImplicitConversion(Init, T1);
+ return PerformImplicitConversion(Init, T1, "initializing");
}
}
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=61246&r1=61245&r2=61246&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Dec 19 11:40:08 2008
@@ -2138,7 +2138,8 @@
// C++ 5.17p3: If the left operand is not of class type, the
// expression is implicitly converted (C++ 4) to the
// cv-unqualified type of the left operand.
- if (PerformImplicitConversion(rExpr, lhsType.getUnqualifiedType()))
+ if (PerformImplicitConversion(rExpr, lhsType.getUnqualifiedType(),
+ "assigning"))
return Incompatible;
else
return Compatible;
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=61246&r1=61245&r2=61246&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Dec 19 11:40:08 2008
@@ -708,14 +708,16 @@
/// PerformImplicitConversion - Perform an implicit conversion of the
/// expression From to the type ToType. Returns true if there was an
/// error, false otherwise. The expression From is replaced with the
-/// converted expression.
+/// converted expression. Flavor is the kind of conversion we're
+/// performing, used in the error message.
bool
-Sema::PerformImplicitConversion(Expr *&From, QualType ToType)
+Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
+ const char *Flavor)
{
ImplicitConversionSequence ICS = TryImplicitConversion(From, ToType);
switch (ICS.ConversionKind) {
case ImplicitConversionSequence::StandardConversion:
- if (PerformImplicitConversion(From, ToType, ICS.Standard))
+ if (PerformImplicitConversion(From, ToType, ICS.Standard, Flavor))
return true;
break;
@@ -742,10 +744,12 @@
/// expression From to the type ToType by following the standard
/// conversion sequence SCS. Returns true if there was an error, false
/// otherwise. The expression From is replaced with the converted
-/// expression.
+/// expression. Flavor is the context in which we're performing this
+/// conversion, for use in error messages.
bool
Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
- const StandardConversionSequence& SCS)
+ const StandardConversionSequence& SCS,
+ const char *Flavor)
{
// Overall FIXME: we are recomputing too many types here and doing
// far too much extra work. What this means is that we need to keep
@@ -808,6 +812,14 @@
break;
case ICK_Pointer_Conversion:
+ if (SCS.IncompatibleObjC) {
+ // Diagnose incompatible Objective-C conversions
+ Diag(From->getSourceRange().getBegin(),
+ diag::ext_typecheck_convert_incompatible_pointer)
+ << From->getType() << ToType << Flavor
+ << From->getSourceRange();
+ }
+
if (CheckPointerConversion(From, ToType))
return true;
ImpCastExprToType(From, ToType);
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=61246&r1=61245&r2=61246&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Fri Dec 19 11:40:08 2008
@@ -419,6 +419,7 @@
// Standard conversions (C++ [conv])
SCS.setAsIdentityConversion();
SCS.Deprecated = false;
+ SCS.IncompatibleObjC = false;
SCS.FromTypePtr = FromType.getAsOpaquePtr();
SCS.CopyConstructor = 0;
@@ -494,6 +495,7 @@
// point promotion, integral conversion, floating point conversion,
// floating-integral conversion, pointer conversion,
// pointer-to-member conversion, or boolean conversion (C++ 4p1).
+ bool IncompatibleObjC = false;
if (Context.getCanonicalType(FromType).getUnqualifiedType() ==
Context.getCanonicalType(ToType).getUnqualifiedType()) {
// The unqualified versions of the types are the same: there's no
@@ -533,8 +535,10 @@
FromType = ToType.getUnqualifiedType();
}
// Pointer conversions (C++ 4.10).
- else if (IsPointerConversion(From, FromType, ToType, FromType)) {
+ else if (IsPointerConversion(From, FromType, ToType, FromType,
+ IncompatibleObjC)) {
SCS.Second = ICK_Pointer_Conversion;
+ SCS.IncompatibleObjC = IncompatibleObjC;
}
// FIXME: Pointer to member conversions (4.11).
// Boolean conversions (C++ 4.12).
@@ -751,10 +755,15 @@
/// appropriate overloading rules for Objective-C, we may want to
/// split the Objective-C checks into a different routine; however,
/// GCC seems to consider all of these conversions to be pointer
-/// conversions, so for now they live here.
+/// conversions, so for now they live here. IncompatibleObjC will be
+/// set if the conversion is an allowed Objective-C conversion that
+/// should result in a warning.
bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
- QualType& ConvertedType)
+ QualType& ConvertedType,
+ bool &IncompatibleObjC)
{
+ IncompatibleObjC = false;
+
// Blocks: Block pointers can be converted to void*.
if (FromType->isBlockPointerType() && ToType->isPointerType() &&
ToType->getAsPointerType()->getPointeeType()->isVoidType()) {
@@ -836,6 +845,18 @@
return true;
}
+ if (FromIface && ToIface &&
+ Context.canAssignObjCInterfaces(FromIface, ToIface)) {
+ // Okay: this is some kind of implicit downcast of Objective-C
+ // interfaces, which is permitted. However, we're going to
+ // complain about it.
+ IncompatibleObjC = true;
+ ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr,
+ ToPointeeType,
+ ToType, Context);
+ return true;
+ }
+
// Objective C++: We're able to convert between "id" and a pointer
// to any interface (in both directions).
if ((FromIface && Context.isObjCIdType(ToPointeeType))
@@ -1533,7 +1554,7 @@
if (ToType->isReferenceType())
return CheckReferenceInit(From, ToType);
- if (!PerformImplicitConversion(From, ToType))
+ if (!PerformImplicitConversion(From, ToType, Flavor))
return false;
return Diag(From->getSourceRange().getBegin(),
Modified: cfe/trunk/lib/Sema/SemaOverload.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.h?rev=61246&r1=61245&r2=61246&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.h (original)
+++ cfe/trunk/lib/Sema/SemaOverload.h Fri Dec 19 11:40:08 2008
@@ -98,6 +98,10 @@
/// (C++ 4.2p2).
bool Deprecated : 1;
+ /// IncompatibleObjC - Whether this is an Objective-C conversion
+ /// that we should warn about (if we actually use it).
+ bool IncompatibleObjC : 1;
+
/// ReferenceBinding - True when this is a reference binding
/// (C++ [over.ics.ref]).
bool ReferenceBinding : 1;
Modified: cfe/trunk/test/SemaObjCXX/overload.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/overload.mm?rev=61246&r1=61245&r2=61246&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/overload.mm (original)
+++ cfe/trunk/test/SemaObjCXX/overload.mm Fri Dec 19 11:40:08 2008
@@ -45,6 +45,11 @@
// int& i3 = h(b); FIXME: we match GCC here, but shouldn't this work?
}
+void downcast_test(A* a) {
+ B* b = a; // expected-warning{{incompatible pointer types initializing 'B *', expected 'A *'}}
+ b = a; // expected-warning{{incompatible pointer types assigning 'B *', expected 'A *'}}
+}
+
int& cv(A*);
float& cv(const A*);
int& cv2(void*);
More information about the cfe-commits
mailing list