diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp | 60 |
1 files changed, 53 insertions, 7 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp index 0e66329..722ac19 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaPseudoObject.cpp @@ -34,6 +34,7 @@ #include "clang/Sema/Initialization.h" #include "clang/AST/ExprObjC.h" #include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/SmallString.h" using namespace clang; using namespace sema; @@ -232,7 +233,7 @@ namespace { Expr *op); bool tryBuildGetOfReference(Expr *op, ExprResult &result); - bool findSetter(); + bool findSetter(bool warn=true); bool findGetter(); Expr *rebuildAndCaptureObject(Expr *syntacticBase); @@ -505,7 +506,7 @@ bool ObjCPropertyOpBuilder::findGetter() { /// reference. /// /// \return true if a setter was found, in which case Setter -bool ObjCPropertyOpBuilder::findSetter() { +bool ObjCPropertyOpBuilder::findSetter(bool warn) { // For implicit properties, just trust the lookup we already did. if (RefExpr->isImplicitProperty()) { if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) { @@ -531,6 +532,23 @@ bool ObjCPropertyOpBuilder::findSetter() { // Do a normal method lookup first. if (ObjCMethodDecl *setter = LookupMethodInReceiverType(S, SetterSelector, RefExpr)) { + if (setter->isSynthesized() && warn) + if (const ObjCInterfaceDecl *IFace = + dyn_cast<ObjCInterfaceDecl>(setter->getDeclContext())) { + const StringRef thisPropertyName(prop->getName()); + char front = thisPropertyName.front(); + front = islower(front) ? toupper(front) : tolower(front); + SmallString<100> PropertyName = thisPropertyName; + PropertyName[0] = front; + IdentifierInfo *AltMember = &S.PP.getIdentifierTable().get(PropertyName); + if (ObjCPropertyDecl *prop1 = IFace->FindPropertyDeclaration(AltMember)) + if (prop != prop1 && (prop1->getSetterMethodDecl() == setter)) { + S.Diag(RefExpr->getExprLoc(), diag::error_property_setter_ambiguous_use) + << prop->getName() << prop1->getName() << setter->getSelector(); + S.Diag(prop->getLocation(), diag::note_property_declare); + S.Diag(prop1->getLocation(), diag::note_property_declare); + } + } Setter = setter; return true; } @@ -603,7 +621,7 @@ ExprResult ObjCPropertyOpBuilder::buildGet() { /// value being set as the value of the property operation. ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, bool captureSetValueAsResult) { - bool hasSetter = findSetter(); + bool hasSetter = findSetter(false); assert(hasSetter); (void) hasSetter; if (SyntacticRefExpr) @@ -889,8 +907,7 @@ Sema::ObjCSubscriptKind // We must have a complete class type. if (RequireCompleteType(FromE->getExprLoc(), T, - PDiag(diag::err_objc_index_incomplete_class_type) - << FromE->getSourceRange())) + diag::err_objc_index_incomplete_class_type, FromE)) return OS_Error; // Look for a conversion to an integral, enumeration type, or @@ -938,6 +955,27 @@ Sema::ObjCSubscriptKind return OS_Error; } +/// CheckKeyForObjCARCConversion - This routine suggests bridge casting of CF +/// objects used as dictionary subscript key objects. +static void CheckKeyForObjCARCConversion(Sema &S, QualType ContainerT, + Expr *Key) { + if (ContainerT.isNull()) + return; + // dictionary subscripting. + // - (id)objectForKeyedSubscript:(id)key; + IdentifierInfo *KeyIdents[] = { + &S.Context.Idents.get("objectForKeyedSubscript") + }; + Selector GetterSelector = S.Context.Selectors.getSelector(1, KeyIdents); + ObjCMethodDecl *Getter = S.LookupMethodInObjectType(GetterSelector, ContainerT, + true /*instance*/); + if (!Getter) + return; + QualType T = Getter->param_begin()[0]->getType(); + S.CheckObjCARCConversion(Key->getSourceRange(), + T, Key, Sema::CCK_ImplicitConversion); +} + bool ObjCSubscriptOpBuilder::findAtIndexGetter() { if (AtIndexGetter) return true; @@ -955,8 +993,12 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() { } Sema::ObjCSubscriptKind Res = S.CheckSubscriptingKind(RefExpr->getKeyExpr()); - if (Res == Sema::OS_Error) + if (Res == Sema::OS_Error) { + if (S.getLangOpts().ObjCAutoRefCount) + CheckKeyForObjCARCConversion(S, ResultType, + RefExpr->getKeyExpr()); return false; + } bool arrayRef = (Res == Sema::OS_Array); if (ResultType.isNull()) { @@ -1063,8 +1105,12 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() { Sema::ObjCSubscriptKind Res = S.CheckSubscriptingKind(RefExpr->getKeyExpr()); - if (Res == Sema::OS_Error) + if (Res == Sema::OS_Error) { + if (S.getLangOpts().ObjCAutoRefCount) + CheckKeyForObjCARCConversion(S, ResultType, + RefExpr->getKeyExpr()); return false; + } bool arrayRef = (Res == Sema::OS_Array); if (ResultType.isNull()) { |