Example #1
0
      bool Find(const TypedValueRegion *R) {
        QualType T = R->getValueType();
        if (const RecordType *RT = T->getAsStructureType()) {
          const RecordDecl *RD = RT->getDecl()->getDefinition();
          assert(RD && "Referred record has no definition");
          for (RecordDecl::field_iterator I =
               RD->field_begin(), E = RD->field_end(); I!=E; ++I) {
            const FieldRegion *FR = MrMgr.getFieldRegion(*I, R);
            FieldChain.push_back(*I);
            T = (*I)->getType();
            if (T->getAsStructureType()) {
              if (Find(FR))
                return true;
            }
            else {
              const SVal &V = StoreMgr.getBinding(store, loc::MemRegionVal(FR));
              if (V.isUndef())
                return true;
            }
            FieldChain.pop_back();
          }
        }

        return false;
      }
Example #2
0
static bool isCallbackArg(SVal V, QualType T) {
  // If the parameter is 0, it's harmless.
  if (V.isZeroConstant())
    return false;

  // If a parameter is a block or a callback, assume it can modify pointer.
  if (T->isBlockPointerType() ||
      T->isFunctionPointerType() ||
      T->isObjCSelType())
    return true;

  // Check if a callback is passed inside a struct (for both, struct passed by
  // reference and by value). Dig just one level into the struct for now.

  if (isa<PointerType>(T) || isa<ReferenceType>(T))
    T = T->getPointeeType();

  if (const RecordType *RT = T->getAsStructureType()) {
    const RecordDecl *RD = RT->getDecl();
    for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
         I != E; ++I) {
      QualType FieldT = I->getType();
      if (FieldT->isBlockPointerType() || FieldT->isFunctionPointerType())
        return true;
    }
  }

  return false;
}
Example #3
0
void
CodeGenFunction::ExpandTypeToArgs(QualType Ty, RValue RV,
                                  llvm::SmallVector<llvm::Value*, 16> &Args) {
  const RecordType *RT = Ty->getAsStructureType();
  assert(RT && "Can only expand structure types.");

  RecordDecl *RD = RT->getDecl();
  assert(RV.isAggregate() && "Unexpected rvalue during struct expansion");
  llvm::Value *Addr = RV.getAggregateAddr();
  for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
         i != e; ++i) {
    FieldDecl *FD = *i;
    QualType FT = FD->getType();

    // FIXME: What are the right qualifiers here?
    LValue LV = EmitLValueForField(Addr, FD, false, 0);
    if (CodeGenFunction::hasAggregateLLVMType(FT)) {
      ExpandTypeToArgs(FT, RValue::getAggregate(LV.getAddress()), Args);
    } else {
      RValue RV = EmitLoadOfLValue(LV, FT);
      assert(RV.isScalar() &&
             "Unexpected non-scalar rvalue during struct expansion.");
      Args.push_back(RV.getScalarVal());
    }
  }
}
Example #4
0
llvm::Function::arg_iterator
CodeGenFunction::ExpandTypeFromArgs(QualType Ty, LValue LV,
                                    llvm::Function::arg_iterator AI) {
  const RecordType *RT = Ty->getAsStructureType();
  assert(RT && "Can only expand structure types.");

  RecordDecl *RD = RT->getDecl();
  assert(LV.isSimple() &&
         "Unexpected non-simple lvalue during struct expansion.");
  llvm::Value *Addr = LV.getAddress();
  for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
         i != e; ++i) {
    FieldDecl *FD = *i;
    QualType FT = FD->getType();

    // FIXME: What are the right qualifiers here?
    LValue LV = EmitLValueForField(Addr, FD, false, 0);
    if (CodeGenFunction::hasAggregateLLVMType(FT)) {
      AI = ExpandTypeFromArgs(FT, LV, AI);
    } else {
      EmitStoreThroughLValue(RValue::get(AI), LV, FT);
      ++AI;
    }
  }

  return AI;
}
Example #5
0
void CodeGenTypes::GetExpandedTypes(QualType Ty,
                                    std::vector<const llvm::Type*> &ArgTys) {
  const RecordType *RT = Ty->getAsStructureType();
  assert(RT && "Can only expand structure types.");
  const RecordDecl *RD = RT->getDecl();
  assert(!RD->hasFlexibleArrayMember() &&
         "Cannot expand structure with flexible array.");

  for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
         i != e; ++i) {
    const FieldDecl *FD = *i;
    assert(!FD->isBitField() &&
           "Cannot expand structure with bit-field members.");

    QualType FT = FD->getType();
    if (CodeGenFunction::hasAggregateLLVMType(FT)) {
      GetExpandedTypes(FT, ArgTys);
    } else {
      ArgTys.push_back(ConvertType(FT));
    }
  }
}
Example #6
0
static bool isCallback(QualType T) {
  // If a parameter is a block or a callback, assume it can modify pointer.
  if (T->isBlockPointerType() ||
      T->isFunctionPointerType() ||
      T->isObjCSelType())
    return true;

  // Check if a callback is passed inside a struct (for both, struct passed by
  // reference and by value). Dig just one level into the struct for now.

  if (T->isAnyPointerType() || T->isReferenceType())
    T = T->getPointeeType();

  if (const RecordType *RT = T->getAsStructureType()) {
    const RecordDecl *RD = RT->getDecl();
    for (const auto *I : RD->fields()) {
      QualType FieldT = I->getType();
      if (FieldT->isBlockPointerType() || FieldT->isFunctionPointerType())
        return true;
    }
  }
  return false;
}
Example #7
0
clang::analyze_format_string::ArgType::MatchKind
ArgType::matchesType(ASTContext &C, QualType argTy) const {
  if (Ptr) {
    // It has to be a pointer.
    const PointerType *PT = argTy->getAs<PointerType>();
    if (!PT)
      return NoMatch;

    // We cannot write through a const qualified pointer.
    if (PT->getPointeeType().isConstQualified())
      return NoMatch;

    argTy = PT->getPointeeType();
  }

  switch (K) {
    case InvalidTy:
      llvm_unreachable("ArgType must be valid");

    case UnknownTy:
      return Match;

    case AnyCharTy: {
      if (const EnumType *ETy = argTy->getAs<EnumType>())
        argTy = ETy->getDecl()->getIntegerType();

      if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
        switch (BT->getKind()) {
          default:
            break;
          case BuiltinType::Char_S:
          case BuiltinType::SChar:
          case BuiltinType::UChar:
          case BuiltinType::Char_U:
            return Match;
        }
      return NoMatch;
    }

    case SpecificTy: {
      if (const EnumType *ETy = argTy->getAs<EnumType>())
        argTy = ETy->getDecl()->getIntegerType();
      argTy = C.getCanonicalType(argTy).getUnqualifiedType();

      if (T == argTy)
        return Match;
      // Check for "compatible types".
      if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
        switch (BT->getKind()) {
          default:
            break;
          case BuiltinType::Char_S:
          case BuiltinType::SChar:
          case BuiltinType::Char_U:
          case BuiltinType::UChar:
            return T == C.UnsignedCharTy || T == C.SignedCharTy ? Match
                                                                : NoMatch;
          case BuiltinType::Short:
            return T == C.UnsignedShortTy ? Match : NoMatch;
          case BuiltinType::UShort:
            return T == C.ShortTy ? Match : NoMatch;
          case BuiltinType::Int:
            return T == C.UnsignedIntTy ? Match : NoMatch;
          case BuiltinType::UInt:
            return T == C.IntTy ? Match : NoMatch;
          case BuiltinType::Long:
            return T == C.UnsignedLongTy ? Match : NoMatch;
          case BuiltinType::ULong:
            return T == C.LongTy ? Match : NoMatch;
          case BuiltinType::LongLong:
            return T == C.UnsignedLongLongTy ? Match : NoMatch;
          case BuiltinType::ULongLong:
            return T == C.LongLongTy ? Match : NoMatch;
        }
      return NoMatch;
    }

    case CStrTy: {
      const PointerType *PT = argTy->getAs<PointerType>();
      if (!PT)
        return NoMatch;
      QualType pointeeTy = PT->getPointeeType();
      if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())
        switch (BT->getKind()) {
          case BuiltinType::Void:
          case BuiltinType::Char_U:
          case BuiltinType::UChar:
          case BuiltinType::Char_S:
          case BuiltinType::SChar:
            return Match;
          default:
            break;
        }

      return NoMatch;
    }

    case WCStrTy: {
      const PointerType *PT = argTy->getAs<PointerType>();
      if (!PT)
        return NoMatch;
      QualType pointeeTy =
        C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();
      return pointeeTy == C.getWideCharType() ? Match : NoMatch;
    }

    case WIntTy: {

      QualType PromoArg = 
        argTy->isPromotableIntegerType()
          ? C.getPromotedIntegerType(argTy) : argTy;

      QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType();
      PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType();

      // If the promoted argument is the corresponding signed type of the
      // wint_t type, then it should match.
      if (PromoArg->hasSignedIntegerRepresentation() &&
          C.getCorrespondingUnsignedType(PromoArg) == WInt)
        return Match;

      return WInt == PromoArg ? Match : NoMatch;
    }

    case CPointerTy:
      if (argTy->isVoidPointerType()) {
        return Match;
      } if (argTy->isPointerType() || argTy->isObjCObjectPointerType() ||
            argTy->isBlockPointerType() || argTy->isNullPtrType()) {
        return NoMatchPedantic;
      } else {
        return NoMatch;
      }

    case ObjCPointerTy: {
      if (argTy->getAs<ObjCObjectPointerType>() ||
          argTy->getAs<BlockPointerType>())
        return Match;

      // Handle implicit toll-free bridging.
      if (const PointerType *PT = argTy->getAs<PointerType>()) {
        // Things such as CFTypeRef are really just opaque pointers
        // to C structs representing CF types that can often be bridged
        // to Objective-C objects.  Since the compiler doesn't know which
        // structs can be toll-free bridged, we just accept them all.
        QualType pointee = PT->getPointeeType();
        if (pointee->getAsStructureType() || pointee->isVoidType())
          return Match;
      }
      return NoMatch;
    }
  }

  llvm_unreachable("Invalid ArgType Kind!");
}