Example #1
0
void RuleOfTwoSoft::VisitStmt(Stmt *s)
{
    CXXOperatorCallExpr *op = dyn_cast<CXXOperatorCallExpr>(s);
    if (op) {
        FunctionDecl *func = op->getDirectCallee();
        if (func && func->getNameAsString() == "operator=") {
            CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(func);
            if (method && method->getParent()) {
                CXXRecordDecl *record = method->getParent();
                const bool hasCopyCtor = record->hasNonTrivialCopyConstructor();
                const bool hasCopyAssignOp = record->hasNonTrivialCopyAssignment();
                if (hasCopyCtor && !hasCopyAssignOp && !isBlacklisted(record)) {
                    string msg = "Using assign operator but class " + record->getQualifiedNameAsString() + " has copy-ctor but no assign operator";
                    emitWarning(s->getLocStart(), msg);
                }
            }
        }
    } else if (CXXConstructExpr *ctorExpr = dyn_cast<CXXConstructExpr>(s)) {
        CXXConstructorDecl *ctorDecl = ctorExpr->getConstructor();
        CXXRecordDecl *record = ctorDecl->getParent();
        if (ctorDecl->isCopyConstructor() && record) {
            const bool hasCopyCtor = record->hasNonTrivialCopyConstructor();
            const bool hasCopyAssignOp = record->hasNonTrivialCopyAssignment();
            if (!hasCopyCtor && hasCopyAssignOp && !isBlacklisted(record)) {
                string msg = "Using copy-ctor but class " + record->getQualifiedNameAsString() + " has a trivial copy-ctor but non trivial assign operator";
                emitWarning(s->getLocStart(), msg);
            }
        }
    }
}
Example #2
0
   /**
    * Once the recursive visitor has completed, this routine analyzes the
    * MostDerivedTypeMap to find errors in the structure of the OMR classes
    */
   void VerifyTypeStructure() {
      trace("Starting Structure Verification");

      for (std::map<CXXRecordDecl*, bool>::iterator I = Types.begin(), E=Types.end(); I != E; ++I) {
         CXXRecordDecl * Type        = I->first;
         bool extensible             = I->second;
         trace(Type << " " << extensible << " " << getAssociatedConcreteType(Type));
         if (extensible && !getAssociatedConcreteType(Type)) {
            trace("xxxx Issue diagnostic because there's no associated concrete type");
            continue;
         }
         if (extensible) {  //Extnsible type .
            trace("xxxx Verifying " << Type->getQualifiedNameAsString() << " has no non-extensible base classes." );
            for (CXXRecordDecl::base_class_iterator BI = Type->bases_begin(), BE = Type->bases_end(); BI != BE; ++BI) {
               CXXRecordDecl * base_class = BI->getType()->getAsCXXRecordDecl();
               if (base_class
                   && !isExtensible(base_class) // Ensure extensible parent.
                   && !isOMRRootType(Type)) {   // OMR Root type can have non-extensible parents.
                  //Base is not extensible, but an extensible type reaches it, with no concrete class in the middle.
                  //Issue diagnostic.
                  std::string diagnostic("OMR_EXTENSIBLE Type ");
                  diagnostic += Type->getQualifiedNameAsString();
                  diagnostic += " derives from ";
                  diagnostic += base_class->getQualifiedNameAsString();
                  diagnostic += " that is not marked as OMR_EXTENSIBLE.\n";

                  DiagnosticsEngine &diagEngine = Context->getDiagnostics();
                  unsigned diagID = diagEngine.getCustomDiagID(DiagnosticsEngine::Error, "%0");
                  diagEngine.Report(base_class->getLocation(), diagID) << diagnostic;
               }
            }
         } else {
            trace("xxxx Verifying " << Type->getQualifiedNameAsString() << " has no non-extensible base classes." );
            for (CXXRecordDecl::base_class_iterator BI = Type->bases_begin(), BE = Type->bases_end(); BI != BE; ++BI) {
               CXXRecordDecl * base_class = BI->getType()->getAsCXXRecordDecl();
               if (base_class && isExtensible(base_class) && !isOMRConcreteType(base_class)) {
                  //Base is not extensible, but an extensible type reaches it, with no concrete class in the middle.
                  //Issue diagnostic.
                  std::string diagnostic("Type ");
                  diagnostic += Type->getQualifiedNameAsString();
                  diagnostic += " derives from ";
                  diagnostic += base_class->getQualifiedNameAsString();
                  diagnostic += " that is  marked as OMR_EXTENSIBLE.\n";

                  DiagnosticsEngine &diagEngine = Context->getDiagnostics();
                  unsigned diagID = diagEngine.getCustomDiagID(DiagnosticsEngine::Error, "%0");
                  diagEngine.Report(Type->getLocation(), diagID) << diagnostic;
               }
            }
         }
      } //each most derived type
   }
Example #3
0
void FunctionArgsByRef::VisitDecl(Decl *decl)
{
    FunctionDecl *functionDecl = dyn_cast<FunctionDecl>(decl);
    if (functionDecl == nullptr || !functionDecl->hasBody() || shouldIgnoreFunction(functionDecl->getNameAsString())
            || !functionDecl->isThisDeclarationADefinition()) return;

    Stmt *body = functionDecl->getBody();

    for (auto it = functionDecl->param_begin(), end = functionDecl->param_end(); it != end; ++it) {
        const ParmVarDecl *param = *it;
        QualType paramQt = param->getType();
        const Type *paramType = paramQt.getTypePtrOrNull();
        if (paramType == nullptr || paramType->isDependentType())
            continue;

        const int size_of_T = m_ci.getASTContext().getTypeSize(paramQt) / 8;
        const bool isSmall = size_of_T <= 16; // TODO: What about arm ?
        CXXRecordDecl *recordDecl = paramType->getAsCXXRecordDecl();
        const bool isUserNonTrivial = recordDecl && (recordDecl->hasUserDeclaredCopyConstructor() || recordDecl->hasUserDeclaredDestructor());
        const bool isReference = paramType->isLValueReferenceType();
        const bool isConst = paramQt.isConstQualified();
        if (recordDecl && shouldIgnoreClass(recordDecl->getQualifiedNameAsString()))
            continue;

        std::string error;
        if (isConst && !isReference) {
            if (!isSmall) {
                error += warningMsgForSmallType(size_of_T, paramQt.getAsString());
            } else if (isUserNonTrivial) {
                error += "Missing reference on non-trivial type " + recordDecl->getQualifiedNameAsString();
            }
        } else if (isConst && isReference && !isUserNonTrivial && isSmall) {
            //error += "Don't use by-ref on small trivial type";
        } else if (!isConst && !isReference && (!isSmall || isUserNonTrivial)) {
            if (Utils::containsNonConstMemberCall(body, param) || Utils::containsCallByRef(body, param))
                continue;
            if (!isSmall) {
                error += warningMsgForSmallType(size_of_T, paramQt.getAsString());
            } else if (isUserNonTrivial) {
                error += "Missing reference on non-trivial type " + recordDecl->getQualifiedNameAsString();
            }
        }

        if (!error.empty()) {
            emitWarning(param->getLocStart(), error.c_str());
        }
    }
}
Example #4
0
   /**
    * Return the concrete type in the same extensible class string as me, or
    * NULL if it can't be found.
    *
    * This query only really makes sense for an extensible class.
    */
   CXXRecordDecl* getAssociatedConcreteType(CXXRecordDecl* decl) {

      // a concrete type is always part of its own extensible class string.
      if (isOMRConcreteType(decl))
         return decl;

      // Only extensible decls have a meaningful concrete class string.
      if (isExtensible(decl)) {
         int loopCount = 0;
         CXXRecordDecl* concrete = mostDerivedType(decl);
         trace("==isExtensible: " << decl->getQualifiedNameAsString() << " concrete: " << (concrete ? concrete->getQualifiedNameAsString() : "no concrete found"));
         while (concrete) {
            if (loopCount++ > 50) {
               std::string diagnostic("Found more than 50 layers of classes, likely bug.");
               DiagnosticsEngine &diagEngine = Context->getDiagnostics();
               unsigned diagID = diagEngine.getCustomDiagID(DiagnosticsEngine::Error, "%0");
               diagEngine.Report(decl->getLocation(), diagID) << diagnostic;
               exit(EXIT_FAILURE);
            }
            if (inSameClassString(decl, concrete)) {
               trace("=== in same string");
               return concrete;  //Found the concrete class in the same string.
            }

            concrete = mostDerivedType(concrete);
            if (concrete) trace("==== new concrete  " << concrete->getQualifiedNameAsString() << " for " << decl->getQualifiedNameAsString());
         }

         trace("Didn't find a concrete class for " << decl->getQualifiedNameAsString() << " ... issue diagnostic?")
      }
      return NULL;
   }
Example #5
0
void MissingTypeinfo::registerQTypeInfo(ClassTemplateSpecializationDecl *decl)
{
    if (decl->getName() == "QTypeInfo") {
        auto &args = decl->getTemplateArgs();
        if (args.size() != 1)
            return;

        QualType qt = args[0].getAsType();
        const Type *t = qt.getTypePtrOrNull();
        CXXRecordDecl *recordDecl =  t ? t->getAsCXXRecordDecl() : nullptr;
        // llvm::errs() << qt.getAsString() << " foo\n";
        if (recordDecl != nullptr) {
            m_typeInfos.insert(recordDecl->getQualifiedNameAsString());
        }
    }
}
Example #6
0
    // handle method declaration
    Method* HandleFunctionDecl(CXXMethodDecl *MD) {
        assert(MD && "method handle missing in HandleFunctionDecl");

        if (methods.find(MD->getQualifiedNameAsString()) != methods.end()) return 0;

        Method *m = new Method();

        m->qualifiedname = MD->getQualifiedNameAsString();

        QualType type = MD->getResultType();
        m->rtype = type.getAsString();

        // get function paramters
        for (FunctionDecl::param_iterator I = MD->param_begin(),
                E = MD->param_end(); I != E; ++I) {
            //llvm::errs() << "Function: " + FD->getNameAsString() <<" params number: " << FD->param_size () << "\"\n";
            if(ParmVarDecl *PD = dyn_cast<ParmVarDecl>(*I)) {
                QualType type = PD->getType();
                m->params.push_back(type.getAsString());
            }
            else assert(0); // case of interest!
        }

        //find all function calls and variables declaration in function body
        if (MD->hasBody()) {
            Stmt* body = MD->getBody();
            TraverseFunctionBody(body, m);
        }

        CXXRecordDecl *RD;
        RD = MD->getParent();
        m->parentclass = RD->getQualifiedNameAsString();

        //check __attribute__ ((annotate("ssf_starting_procedure")))
        if (MD->getAttr<AnnotateAttr>()) {
            //llvm::errs() << MD->getName() << " has annotate attribute\n";
            m->hasAttri = true;
        }

        m->filename = inFile;

        return m;
    }