void RedundantVoidArgCheck::registerMatchers(MatchFinder *Finder) {
  Finder->addMatcher(functionDecl(parameterCountIs(0), unless(isImplicit()),
                                  unless(isExternC()))
                         .bind(FunctionId),
                     this);
  Finder->addMatcher(typedefNameDecl().bind(TypedefId), this);
  auto ParenFunctionType = parenType(innerType(functionType()));
  auto PointerToFunctionType = pointee(ParenFunctionType);
  auto FunctionOrMemberPointer =
      anyOf(hasType(pointerType(PointerToFunctionType)),
            hasType(memberPointerType(PointerToFunctionType)));
  Finder->addMatcher(fieldDecl(FunctionOrMemberPointer).bind(FieldId), this);
  Finder->addMatcher(varDecl(FunctionOrMemberPointer).bind(VarId), this);
  auto CastDestinationIsFunction =
      hasDestinationType(pointsTo(ParenFunctionType));
  Finder->addMatcher(
      cStyleCastExpr(CastDestinationIsFunction).bind(CStyleCastId), this);
  Finder->addMatcher(
      cxxStaticCastExpr(CastDestinationIsFunction).bind(NamedCastId), this);
  Finder->addMatcher(
      cxxReinterpretCastExpr(CastDestinationIsFunction).bind(NamedCastId),
      this);
  Finder->addMatcher(
      cxxConstCastExpr(CastDestinationIsFunction).bind(NamedCastId), this);
  Finder->addMatcher(lambdaExpr().bind(LambdaId), this);
}
void CloexecSocketCheck::registerMatchers(MatchFinder *Finder) {
  registerMatchersImpl(Finder,
                       functionDecl(isExternC(), returns(isInteger()),
                                    hasName("socket"),
                                    hasParameter(0, hasType(isInteger())),
                                    hasParameter(1, hasType(isInteger())),
                                    hasParameter(2, hasType(isInteger()))));
}
Beispiel #3
0
bool DeclReferencer::Reference(const clang::NamedDecl *D)
{
    if (D->isInvalidDecl())
        return true;

    for (const clang::Decl *DI = D; !isa<clang::TranslationUnitDecl>(DI); DI = cast<clang::Decl>(DI->getDeclContext()))
        if (auto RD = dyn_cast<clang::CXXRecordDecl>(DI))
            if (RD->isLocalClass())
                return true; // are local records emitted when emitting a function? if no this is a FIXME

    if (auto VD = dyn_cast<clang::VarDecl>(D))
        if (!VD->isFileVarDecl())
            return true;

    if (auto FD = dyn_cast<clang::FunctionDecl>(D))
    {
        if (!isMapped(D))
            return true;
        if (FD->getBuiltinID() ||
                (FD->isOverloadedOperator() && FD->isImplicit()))
            return true;
        if (FD->isExternC())
            return true; // FIXME: Clang 3.6 doesn't always map decls to the right source file,
                // so the path generated by typeQualifiedFor although correct will result in a failed lookup.
                // This may get fixed by 3.7.
    }

    if (Referenced.count(D->getCanonicalDecl()))
        return true;
    Referenced.insert(D->getCanonicalDecl());

    // Although we try to add all the needed imports during importAll(), sometimes we miss a module so ensure it gets loaded
    auto im = mapper.AddImplicitImportForDecl(loc, D, true);
    im->isstatic = true;
    auto dst = Package::resolve(im->packages, NULL, &im->pkg);
    if (!dst->lookup(im->id))
    {
        im->semantic(sc);
        im->semantic2(sc);
    }

    ReferenceTemplateArguments(D);

    auto Func = dyn_cast<clang::FunctionDecl>(D);
    if (Func && Func->getPrimaryTemplate())
        D = cast<clang::NamedDecl>(getCanonicalDecl(getSpecializedDeclOrExplicit(Func)));

    // HACK FIXME
    if (Func && Func->isOutOfLine() &&
            Func->getFriendObjectKind() != clang::Decl::FOK_None)
    {
        auto Pattern = Func;
        if (auto MemberFunc = Func->getInstantiatedFromMemberFunction())
            Pattern = MemberFunc;

        if (Pattern->isDependentContext())
            return true;
    }

    auto e = expmap.fromExpressionDeclRef(loc, const_cast<clang::NamedDecl*>(D),
                                            nullptr, TQ_OverOpSkipSpecArg);
    e = e->semantic(sc);

    if (Func && Func->getPrimaryTemplate())
    {
        assert(e->op == TOKvar || e->op == TOKtemplate || e->op == TOKimport);
        Dsymbol *s;
        if (e->op == TOKvar)
            s = static_cast<SymbolExp*>(e)->var;
        else if (e->op == TOKtemplate)
            s = static_cast<TemplateExp*>(e)->td;
        else
            s = static_cast<ScopeExp*>(e)->sds;

        // if it's a non-template function there's nothing to do, it will be semantic'd along with its declcontext
        // if it's a template spec we must instantiate the right overload
        struct DEquals
        {
            const clang::Decl* D;
            Dsymbol *s = nullptr; // return value

            static int fp(void *param, Dsymbol *s)
            {
                if (!isCPP(s))
                    return 0;
                auto fd = s->isFuncDeclaration();
                auto td = static_cast<cpp::TemplateDeclaration*>(
                                            s->isTemplateDeclaration());
                DEquals *p = (DEquals *)param;

                decltype(D) s_D = fd ? getFD(fd) : td->TempOrSpec;

                if (p->D == getCanonicalDecl(s_D))
                {
                    p->s = s;
                    return 1;
                }

                return 0;
            }
        };
        DEquals p;
        p.D = D;
        overloadApply(s, &p, &DEquals::fp);
        assert(p.s && p.s->isTemplateDeclaration());

        auto td = static_cast<cpp::TemplateDeclaration*>(p.s->isTemplateDeclaration());
        if (td->semanticRun == PASSinit)
        {
            assert(td->scope);
            td->semantic(td->scope); // this must be done here because havetempdecl being set to true it won't be done by findTempDecl()
            assert(td->semanticRun > PASSinit);
        }

        auto tiargs = mapper.fromTemplateArguments(loc, Func->getTemplateSpecializationArgs());
        assert(tiargs);
        SpecValue spec(mapper);
        getIdentifier(Func, &spec, true);
        if (spec)
            tiargs->shift(spec.toTemplateArg(loc));
        auto tempinst = new cpp::TemplateInstance(loc, td, tiargs);
        tempinst->Inst = const_cast<clang::FunctionDecl*>(Func);
        tempinst->semantictiargsdone = false; // NOTE: the "havetempdecl" ctor of Templateinstance set semantictiargsdone to true...
                                                            // Time was lost finding this out for the second or third time.
        td->makeForeignInstance(tempinst);
        tempinst->semantic(sc);
    }

    // Memory usage can skyrocket when using a large library
    if (im->packages) delete im->packages;
    delete im;
    delete e;

    return true;
}