Ejemplo n.º 1
0
int DeclarationName::compare(DeclarationName LHS, DeclarationName RHS) {
    if (LHS.getNameKind() != RHS.getNameKind())
        return (LHS.getNameKind() < RHS.getNameKind() ? -1 : 1);

    switch (LHS.getNameKind()) {
    case DeclarationName::Identifier: {
        IdentifierInfo *LII = LHS.getAsIdentifierInfo();
        IdentifierInfo *RII = RHS.getAsIdentifierInfo();
        if (!LII) return RII ? -1 : 0;
        if (!RII) return 1;

        return LII->getName().compare(RII->getName());
    }

    case DeclarationName::ObjCZeroArgSelector:
    case DeclarationName::ObjCOneArgSelector:
    case DeclarationName::ObjCMultiArgSelector: {
        Selector LHSSelector = LHS.getObjCSelector();
        Selector RHSSelector = RHS.getObjCSelector();
        unsigned LN = LHSSelector.getNumArgs(), RN = RHSSelector.getNumArgs();
        for (unsigned I = 0, N = std::min(LN, RN); I != N; ++I) {
            switch (LHSSelector.getNameForSlot(I).compare(
                        RHSSelector.getNameForSlot(I))) {
            case -1:
                return true;
            case 1:
                return false;
            default:
                break;
            }
        }

        return compareInt(LN, RN);
    }

    case DeclarationName::CXXConstructorName:
    case DeclarationName::CXXDestructorName:
    case DeclarationName::CXXConversionFunctionName:
        if (QualTypeOrdering()(LHS.getCXXNameType(), RHS.getCXXNameType()))
            return -1;
        if (QualTypeOrdering()(RHS.getCXXNameType(), LHS.getCXXNameType()))
            return 1;
        return 0;

    case DeclarationName::CXXOperatorName:
        return compareInt(LHS.getCXXOverloadedOperator(),
                          RHS.getCXXOverloadedOperator());

    case DeclarationName::CXXLiteralOperatorName:
        return LHS.getCXXLiteralIdentifier()->getName().compare(
                   RHS.getCXXLiteralIdentifier()->getName());

    case DeclarationName::CXXUsingDirective:
        return 0;
    }

    return 0;
}
void NilArgChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
                                        CheckerContext &C) const {
  const ObjCInterfaceDecl *ID = msg.getReceiverInterface();
  if (!ID)
    return;

  FoundationClass Class = findKnownClass(ID);

  static const unsigned InvalidArgIndex = UINT_MAX;
  unsigned Arg = InvalidArgIndex;
  bool CanBeSubscript = false;
  
  if (Class == FC_NSString) {
    Selector S = msg.getSelector();
    
    if (S.isUnarySelector())
      return;
    
    // FIXME: This is going to be really slow doing these checks with
    //  lexical comparisons.
    
    std::string NameStr = S.getAsString();
    StringRef Name(NameStr);
    assert(!Name.empty());
    
    // FIXME: Checking for initWithFormat: will not work in most cases
    //  yet because [NSString alloc] returns id, not NSString*.  We will
    //  need support for tracking expected-type information in the analyzer
    //  to find these errors.
    if (Name == "caseInsensitiveCompare:" ||
        Name == "compare:" ||
        Name == "compare:options:" ||
        Name == "compare:options:range:" ||
        Name == "compare:options:range:locale:" ||
        Name == "componentsSeparatedByCharactersInSet:" ||
        Name == "initWithFormat:") {
      Arg = 0;
    }
  } else if (Class == FC_NSArray) {
    Selector S = msg.getSelector();

    if (S.isUnarySelector())
      return;

    if (S.getNameForSlot(0).equals("addObject")) {
      Arg = 0;
    } else if (S.getNameForSlot(0).equals("insertObject") &&
               S.getNameForSlot(1).equals("atIndex")) {
      Arg = 0;
    } else if (S.getNameForSlot(0).equals("replaceObjectAtIndex") &&
               S.getNameForSlot(1).equals("withObject")) {
      Arg = 1;
    } else if (S.getNameForSlot(0).equals("setObject") &&
               S.getNameForSlot(1).equals("atIndexedSubscript")) {
      Arg = 0;
      CanBeSubscript = true;
    } else if (S.getNameForSlot(0).equals("arrayByAddingObject")) {
      Arg = 0;
    }
  } else if (Class == FC_NSDictionary) {
    Selector S = msg.getSelector();

    if (S.isUnarySelector())
      return;

    if (S.getNameForSlot(0).equals("dictionaryWithObject") &&
        S.getNameForSlot(1).equals("forKey")) {
      Arg = 0;
      WarnIfNilArg(C, msg, /* Arg */1, Class);
    } else if (S.getNameForSlot(0).equals("setObject") &&
               S.getNameForSlot(1).equals("forKey")) {
      Arg = 0;
      WarnIfNilArg(C, msg, /* Arg */1, Class);
    } else if (S.getNameForSlot(0).equals("setObject") &&
               S.getNameForSlot(1).equals("forKeyedSubscript")) {
      CanBeSubscript = true;
      Arg = 0;
      WarnIfNilArg(C, msg, /* Arg */1, Class, CanBeSubscript);
    } else if (S.getNameForSlot(0).equals("removeObjectForKey")) {
      Arg = 0;
    }
  }


  // If argument is '0', report a warning.
  if ((Arg != InvalidArgIndex))
    WarnIfNilArg(C, msg, Arg, Class, CanBeSubscript);

}