Пример #1
0
void Sema::checkCUDATargetOverload(FunctionDecl *NewFD,
                                   const LookupResult &Previous) {
  assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
  CUDAFunctionTarget NewTarget = IdentifyCUDATarget(NewFD);
  for (NamedDecl *OldND : Previous) {
    FunctionDecl *OldFD = OldND->getAsFunction();
    if (!OldFD)
      continue;

    CUDAFunctionTarget OldTarget = IdentifyCUDATarget(OldFD);
    // Don't allow HD and global functions to overload other functions with the
    // same signature.  We allow overloading based on CUDA attributes so that
    // functions can have different implementations on the host and device, but
    // HD/global functions "exist" in some sense on both the host and device, so
    // should have the same implementation on both sides.
    if (NewTarget != OldTarget &&
        ((NewTarget == CFT_HostDevice) || (OldTarget == CFT_HostDevice) ||
         (NewTarget == CFT_Global) || (OldTarget == CFT_Global)) &&
        !IsOverload(NewFD, OldFD, /* UseMemberUsingDeclRules = */ false,
                    /* ConsiderCudaAttrs = */ false)) {
      Diag(NewFD->getLocation(), diag::err_cuda_ovl_target)
          << NewTarget << NewFD->getDeclName() << OldTarget << OldFD;
      Diag(OldFD->getLocation(), diag::note_previous_declaration);
      NewFD->setInvalidDecl();
      break;
    }
  }
}
Пример #2
0
bool TeslaVisitor::VisitCallExpr(CallExpr *E) {
    FunctionDecl *F = E->getDirectCallee();
    if (!F) return true;

    StringRef FnName = F->getName();
    if (!FnName.startswith(TESLA_BASE)) return true;

    // TESLA function calls might be inline assertions.
    if (FnName == INLINE_ASSERTION) {
        OwningPtr<Parser> P(Parser::AssertionParser(E, *Context));
        if (!P)
            return false;

        OwningPtr<AutomatonDescription> Description;
        OwningPtr<Usage> Use;
        if (!P->Parse(Description, Use))
            return false;

        Automata.push_back(Description.take());
        Roots.push_back(Use.take());
        return true;
    }

    return true;
}
Пример #3
0
static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
  // check the attribute arguments.
  if (Attr.getNumArgs() != 0) {
    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
    return;
  }

  // Attribute can be applied only to functions or variables.
  if (isa<VarDecl>(D)) {
    D->addAttr(::new (S.Context) DLLExportAttr(Attr.getLoc(), S.Context));
    return;
  }

  FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
  if (!FD) {
    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
      << Attr.getName() << 2 /*variable and function*/;
    return;
  }

  // Currently, the dllexport attribute is ignored for inlined functions, unless
  // the -fkeep-inline-functions flag has been used. Warning is emitted;
  if (FD->isInlineSpecified()) {
    // FIXME: ... unless the -fkeep-inline-functions flag has been used.
    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
    return;
  }

  D->addAttr(::new (S.Context) DLLExportAttr(Attr.getLoc(), S.Context));
}
Пример #4
0
 FunctionDecl * GetLivenessFunction() {
     IdentifierInfo & II = Context->Idents.get(livenessfunction);
     DeclarationName N = Context->DeclarationNames.getIdentifier(&II);
     #if LLVM_VERSION >= 33
     QualType T = Context->getFunctionType(Context->VoidTy, outputtypes, FunctionProtoType::ExtProtoInfo());
     #else
     QualType T = Context->getFunctionType(Context->VoidTy, &outputtypes[0],outputtypes.size(), FunctionProtoType::ExtProtoInfo());
     #endif
     FunctionDecl * F = FunctionDecl::Create(*Context, Context->getTranslationUnitDecl(), SourceLocation(), SourceLocation(), N,T, 0, SC_Extern);
     
     std::vector<ParmVarDecl *> params;
     for(size_t i = 0; i < outputtypes.size(); i++) {
         params.push_back(ParmVarDecl::Create(*Context, F, SourceLocation(), SourceLocation(), 0, outputtypes[i], /*TInfo=*/0, SC_None,
         #if LLVM_VERSION <= 32
         SC_None,
         #endif
         0));
     }
     F->setParams(params);
     #if LLVM_VERSION >= 33
     CompoundStmt * stmts = new (*Context) CompoundStmt(*Context, outputstmts, SourceLocation(), SourceLocation());
     #else
     CompoundStmt * stmts = new (*Context) CompoundStmt(*Context, &outputstmts[0], outputstmts.size(), SourceLocation(), SourceLocation());
     #endif
     F->setBody(stmts);
     return F;
 }
Пример #5
0
    void TraverseFunctionBody(Stmt *S, Method *m) {
        // perform depth first traversal of all children
        for (Stmt::child_iterator CI = S->child_begin(),
                E = S->child_end(); CI != E; ++CI) {
            if (*CI) TraverseFunctionBody(*CI, m);
        }

        // if it's a function call, register it
        if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
            FunctionDecl *fd = CE->getDirectCallee();
            if (fd != 0) {
                QualType type = fd->getResultType();
                std::string rtype = type.getAsString();
                std::string qname = fd->getQualifiedNameAsString();
                std::string param = "";
                param += "(";

                for (FunctionDecl::param_iterator I = fd->param_begin(),
                        E = fd->param_end(); I != E; ++I) {
                    if(ParmVarDecl *PD = dyn_cast<ParmVarDecl>(*I)) {
                        QualType type = PD->getType();
                        param += type.getAsString() + ",";
                    }
                    else assert(0); // case of interest!
                }

                if (param != "(") param.erase(param.end() - 1); // remove the last comma
                param += ")";
                std::string callee = rtype + " " + qname + param;
                m->callexprs.insert(callee);
            }
        }
    }
Пример #6
0
static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
  // check the attribute arguments.
  if (Attr.getNumArgs() != 0) {
    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
    return;
  }

  // Attribute can be applied only to functions or variables.
  FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
  if (!FD && !isa<VarDecl>(D)) {
    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
      << Attr.getName() << 2 /*variable and function*/;
    return;
  }

  // Currently, the dllexport attribute is ignored for inlined functions, unless
  // the -fkeep-inline-functions flag has been used. Warning is emitted;
  if (FD && FD->isInlineSpecified()) {
    // FIXME: ... unless the -fkeep-inline-functions flag has been used.
    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
    return;
  }

  unsigned Index = Attr.getAttributeSpellingListIndex();
  DLLExportAttr *NewAttr = S.mergeDLLExportAttr(D, Attr.getRange(), Index);
  if (NewAttr)
    D->addAttr(NewAttr);
}
Пример #7
0
void ReplaceCallExpr::getNewParmRefStr(const DeclRefExpr *DE,
                                       std::string &ParmRefStr)
{
  const ValueDecl *OrigDecl = DE->getDecl();
  const ParmVarDecl *PD = dyn_cast<ParmVarDecl>(OrigDecl);
  TransAssert(PD && "Bad ParmVarDecl!");

  FunctionDecl *FD = TheCallExpr->getDirectCallee();

  unsigned int Pos = 0;
  for(FunctionDecl::param_const_iterator I = FD->param_begin(),
      E = FD->param_end(); I != E; ++I) {
    TransAssert((Pos < TheCallExpr->getNumArgs()) &&
                "Unmatched Parm and Arg!");
    if (PD != (*I)) {
      Pos++;
      continue;
    }

    const Expr *Arg = TheCallExpr->getArg(Pos)->IgnoreParenImpCasts();
    RewriteHelper->getExprString(Arg, ParmRefStr);
    ParmRefStr = "(" + ParmRefStr + ")";

    const Type *ParmT = PD->getType().getTypePtr();
    const Type *CanParmT = Context->getCanonicalType(ParmT);
    const Type *ArgT = Arg->getType().getTypePtr();
    const Type *CanArgT = Context->getCanonicalType(ArgT);
    if (CanParmT != CanArgT) {
      std::string TypeCastStr = PD->getType().getAsString();
      ParmRefStr = "(" + TypeCastStr + ")" + ParmRefStr;
    }
    return;
  }
  TransAssert(0 && "Unreachable Code!");
}
Пример #8
0
static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
  // Attribute can be applied only to functions or variables.
  FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
  if (!FD && !isa<VarDecl>(D)) {
    // Apparently Visual C++ thinks it is okay to not emit a warning
    // in this case, so only emit a warning when -fms-extensions is not
    // specified.
    if (!S.getLangOpts().MicrosoftExt)
      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
        << Attr.getName() << 2 /*variable and function*/;
    return;
  }

  // Currently, the dllimport attribute is ignored for inlined functions.
  // Warning is emitted.
  if (FD && FD->isInlineSpecified()) {
    S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
    return;
  }

  unsigned Index = Attr.getAttributeSpellingListIndex();
  DLLImportAttr *NewAttr = S.mergeDLLImportAttr(D, Attr.getRange(), Index);
  if (NewAttr)
    D->addAttr(NewAttr);
}
Пример #9
0
bool Utils::isInitializedExternally(clang::VarDecl *varDecl)
{
    if (!varDecl)
        return false;

    DeclContext *context = varDecl->getDeclContext();
    FunctionDecl *fDecl = context ? dyn_cast<FunctionDecl>(context) : nullptr;
    Stmt *body = fDecl ? fDecl->getBody() : nullptr;
    if (!body)
        return false;

    vector<DeclStmt*> declStmts;
    HierarchyUtils::getChilds<DeclStmt>(body, declStmts);
    for (DeclStmt *declStmt : declStmts) {
        if (referencesVarDecl(declStmt, varDecl)) {
            vector<DeclRefExpr*> declRefs;

            HierarchyUtils::getChilds<DeclRefExpr>(declStmt, declRefs);
            if (!declRefs.empty()) {
                return true;
            }

            vector<CallExpr*> callExprs;
            HierarchyUtils::getChilds<CallExpr>(declStmt, callExprs);
            if (!callExprs.empty()) {
                return true;
            }
        }
    }

    return false;
}
Пример #10
0
void ReplaceCallExpr::getParmPosVector(ParameterPosVector &PosVector,
                                       ReturnStmt *RS, CallExpr *CE)
{
  DenseMap<ReturnStmt *, ParmRefsVector *>::iterator RI =
    ReturnStmtToParmRefs.find(RS);
  if (RI == ReturnStmtToParmRefs.end())
    return;

  ParmRefsVector *PVector = (*RI).second;

  FunctionDecl *FD = CE->getDirectCallee();
  for (ParmRefsVector::const_iterator PI = PVector->begin(),
       PE = PVector->end(); PI != PE; ++PI) {

    const ValueDecl *OrigDecl = (*PI)->getDecl();
    const ParmVarDecl *PD = dyn_cast<ParmVarDecl>(OrigDecl);
    unsigned int Pos = 0;
    for(FunctionDecl::param_const_iterator I = FD->param_begin(),
        E = FD->param_end(); I != E; ++I) {
      if (PD == (*I))
        break;
      Pos++;
    }
    PosVector.push_back(Pos);
  }
}
Пример #11
0
static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M,
                                              const ParmVarDecl *Callback,
                                              CXXRecordDecl *CallbackDecl,
                                              ArrayRef<Expr *> CallArgs) {
  assert(CallbackDecl != nullptr);
  assert(CallbackDecl->isLambda());
  FunctionDecl *callOperatorDecl = CallbackDecl->getLambdaCallOperator();
  assert(callOperatorDecl != nullptr);

  DeclRefExpr *callOperatorDeclRef =
      DeclRefExpr::Create(/* Ctx =*/ C,
                          /* QualifierLoc =*/ NestedNameSpecifierLoc(),
                          /* TemplateKWLoc =*/ SourceLocation(),
                          const_cast<FunctionDecl *>(callOperatorDecl),
                          /* RefersToEnclosingVariableOrCapture=*/ false,
                          /* NameLoc =*/ SourceLocation(),
                          /* T =*/ callOperatorDecl->getType(),
                          /* VK =*/ VK_LValue);

  return new (C)
      CXXOperatorCallExpr(/*AstContext=*/C, OO_Call, callOperatorDeclRef,
                          /*args=*/CallArgs,
                          /*QualType=*/C.VoidTy,
                          /*ExprValueType=*/VK_RValue,
                          /*SourceLocation=*/SourceLocation(), FPOptions());
}
Пример #12
0
  virtual void HandleTranslationUnit(TranslationUnit& tu) {
    // called when everything is done

    UsageMap uses;
    for (int i = 0; i < globals.size(); ++i) {
      uses[globals[i]] = vector<DeclRefExpr*>();
    }

    FindUsages fu(uses);
    for (int i = 0; i < functions.size(); ++i) {
      fu.process(functions[i]);
    }

    for (int i = 0; i < globals.size(); ++i) {
      VarDecl* VD = globals[i];
      FullSourceLoc loc(VD->getLocation(), *sm);
      bool isStatic = VD->getStorageClass() == VarDecl::Static;

      cout << "<span class=\"global\">" << loc.getSourceName() << ": "
           << (isStatic?"static ":"") << VD->getName()
           << "  (" << uses[VD].size() << " local uses)"
           << "\n</span>";

      cout << "<span class=\"uses\">";
      for (int j = 0; j < uses[VD].size(); ++j) {
        DeclRefExpr* dre = uses[VD][j];
        FunctionDecl* fd = enclosing[dre];
        FullSourceLoc loc(dre->getLocStart(), *sm);
        cout << "  " << fd->getName() << ":"
             << loc.getLogicalLineNumber() << "\n";
      }
      cout << "</span>";
    }
  }
Пример #13
0
bool FlattenCFGTransformer::HandleAnyFunctionDecl(Decl *D){
	DPRINT("enter FuncDecl");
	FunctionDecl *fd = NULL;
	if(FunctionTemplateDecl *td = dyn_cast<FunctionTemplateDecl>(D)) { // function template
		fd = td->getTemplatedDecl();
	} else if(FunctionDecl *td = dyn_cast<FunctionDecl>(D)) { // function, c++ method
		fd = td;
	} else {
		DPRINT("unknown FunctionDecl type: %s %x", D->getDeclKindName(),(unsigned int)D);
		return false;
	}
	assert(fd && "get FunctionDecl failed");

	//TODO
	Stmt *oldBody = fd->getBody();
	this->renamer->HandleDecl(fd);
	this->preTranser->HandleDecl(fd);
	this->dclMover->HandelDecl(fd);
	this->flat->HandleDecl(fd);

	// refresh RewriteBuffer
	Rewriter &rw = resMgr.getRewriter();
	rw.ReplaceStmt(oldBody, fd->getBody());

	return true;
}
Пример #14
0
	clang::Decl* InsiemeSema::ActOnFinishFunctionBody(clang::Decl* Decl, clang::Stmt* Body) {
		VLOG(2) << "{InsiemeSema}: ActOnFinishFunctionBody()";
		clang::Decl* ret = Sema::ActOnFinishFunctionBody(Decl, std::move(Body));
		// We are sure all the pragmas inside the function body have been matched

		FunctionDecl* FD = dyn_cast<FunctionDecl>(ret);
		
		if(!FD) { return ret; }

		PragmaList matched;
		std::list<PragmaPtr>::reverse_iterator I = pimpl->pending_pragma.rbegin(), E = pimpl->pending_pragma.rend();

		while(I != E && isAfterRange(FD->getSourceRange(), (*I)->getStartLocation(), SourceMgr)) {
			++I;
		}

		while(I != E) {
			unsigned int pragmaEnd = utils::Line((*I)->getEndLocation(), SourceMgr);
			unsigned int declBegin = utils::Line(ret->getSourceRange().getBegin(), SourceMgr);

			if(pragmaEnd <= declBegin) {
				(*I)->setDecl(FD);
				matched.push_back(*I);
			}
			++I;
		}
		EraseMatchedPragmas(pimpl->pending_pragma, matched);
		isInsideFunctionDef = false;

		return ret;
	}
Пример #15
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);
            }
        }
    }
}
Пример #16
0
  void ReturnSynthesizer::Transform() {
    if (!getTransaction()->getCompilationOpts().ResultEvaluation)
      return;

    FunctionDecl* FD = getTransaction()->getWrapperFD();

    int foundAtPos = -1;
    Expr* lastExpr = utils::Analyze::GetOrCreateLastExpr(FD, &foundAtPos, 
                                                         /*omitDS*/false,
                                                         m_Sema);
    if (lastExpr) {
      QualType RetTy = lastExpr->getType();
      if (!RetTy->isVoidType() && RetTy.isTriviallyCopyableType(*m_Context)) {
        // Change the void function's return type
        // We can't PushDeclContext, because we don't have scope.
        Sema::ContextRAII pushedDC(*m_Sema, FD);
        FunctionProtoType::ExtProtoInfo EPI;
        QualType FnTy
          = m_Context->getFunctionType(RetTy, llvm::ArrayRef<QualType>(), EPI);
        FD->setType(FnTy);
        CompoundStmt* CS = cast<CompoundStmt>(FD->getBody());
        assert(CS && "Missing body?");
        // Change it to a return stmt (Avoid dealloc/alloc of all el.)
        *(CS->body_begin() + foundAtPos)
          = m_Sema->ActOnReturnStmt(lastExpr->getExprLoc(), 
                                    lastExpr).take();
      }
    } else if (foundAtPos >= 0) {
      // check for non-void return statement
      CompoundStmt* CS = cast<CompoundStmt>(FD->getBody());
      Stmt* CSS = *(CS->body_begin() + foundAtPos);
      if (ReturnStmt* RS = dyn_cast<ReturnStmt>(CSS)) {
        if (Expr* RetV = RS->getRetValue()) {
          QualType RetTy = RetV->getType();
          // Any return statement will have been "healed" by Sema
          // to correspond to the original void return type of the
          // wrapper, using a ImplicitCastExpr 'void' <ToVoid>.
          // Remove that.
          if (RetTy->isVoidType()) {
            ImplicitCastExpr* VoidCast = dyn_cast<ImplicitCastExpr>(RetV);
            if (VoidCast) {
              RS->setRetValue(VoidCast->getSubExpr());
              RetTy = VoidCast->getSubExpr()->getType();
            }
          }

          if (!RetTy->isVoidType()
              && RetTy.isTriviallyCopyableType(*m_Context)) {
            Sema::ContextRAII pushedDC(*m_Sema, FD);
            FunctionProtoType::ExtProtoInfo EPI;
            QualType FnTy
              = m_Context->getFunctionType(RetTy, llvm::ArrayRef<QualType>(),
                                           EPI);
            FD->setType(FnTy);
          } // not returning void
        } // have return value
      } // is a return statement
    } // have a statement
  }
Пример #17
0
Decl* StructTypeDecl::findFunction(const char* name_) const {
    // struct-functions
    for (unsigned i=0; i<numStructFunctions(); i++) {
        FunctionDecl* F = structFunctions[i];
        if (F->matchesStructFuncName(name_)) return F;
    }
    return 0;
}
Пример #18
0
 bool isInNonTemplateFunction(Decl *varDecl)
 {
     FunctionDecl *decl = dyn_cast_or_null<FunctionDecl>(varDecl->getLexicalDeclContext());
     if (decl)
     {
         return decl->getTemplatedKind() == FunctionDecl::TK_NonTemplate;
     }
     return true;
 }
Пример #19
0
void QGetEnv::VisitStmt(clang::Stmt *stmt)
{
    // Lets check only in function calls. Otherwise there are too many false positives, it's common
    // to implicit cast to bool when checking pointers for validity, like if (ptr)

    CXXMemberCallExpr *memberCall = dyn_cast<CXXMemberCallExpr>(stmt);
    if (!memberCall)
        return;

    CXXMethodDecl *method = memberCall->getMethodDecl();
    if (!method)
        return;

    CXXRecordDecl *record = method->getParent();
    if (!record || record->getNameAsString() != "QByteArray") {
        return;
    }

    std::vector<CallExpr *> calls = Utils::callListForChain(memberCall);
    if (calls.size() != 2)
        return;

    CallExpr *qgetEnvCall = calls.back();

    FunctionDecl *func = qgetEnvCall->getDirectCallee();

    if (!func || func->getNameAsString() != "qgetenv")
        return;

    string methodname = method->getNameAsString();
    string errorMsg;
    std::string replacement;
    if (methodname == "isEmpty") {
        errorMsg = "qgetenv().isEmpty() allocates.";
        replacement = "qEnvironmentVariableIsEmpty";
    } else if (methodname == "isNull") {
        errorMsg = "qgetenv().isNull() allocates.";
        replacement = "qEnvironmentVariableIsSet";
    } else if (methodname == "toInt") {
        errorMsg = "qgetenv().toInt() is slow.";
        replacement = "qEnvironmentVariableIntValue";
    }

    if (!errorMsg.empty()) {
        std::vector<FixItHint> fixits;
        if (isFixitEnabled(FixitAll)) {
            const bool success = FixItUtils::transformTwoCallsIntoOne(m_ci, qgetEnvCall, memberCall, replacement, fixits);
            if (!success) {
                queueManualFixitWarning(memberCall->getLocStart(), FixitAll);
            }
        }

        errorMsg += " Use " + replacement + "() instead";
        emitWarning(memberCall->getLocStart(), errorMsg.c_str(), fixits);
    }
}
  void NullDerefProtectionTransformer::Transform() {
    FunctionDecl* FD = getTransaction()->getWrapperFD();
    if (!FD)
      return;

    CompoundStmt* CS = dyn_cast<CompoundStmt>(FD->getBody());
    assert(CS && "Function body not a CompundStmt?");
    IfStmtInjector injector((*m_Sema));
    CompoundStmt* newCS = injector.Inject(CS);
    FD->setBody(newCS);
  }
Пример #21
0
unsigned RefFinder::find() {
    // TODO search more places (types, inits, etc)

    // search Function bodies
    for (unsigned i=0; i<ast.numFunctions(); i++) {
        FunctionDecl* F = ast.getFunction(i);
        searchCompoundStmt(F->getBody());
    }

    return locs.size();
}
Пример #22
0
  // Here is the test Eval function specialization. Here the CallExpr to the
  // function is created.
  CallExpr*
  EvaluateTSynthesizer::BuildEvalCallExpr(const QualType InstTy,
                                            Expr* SubTree,
                                            ASTOwningVector<Expr*>& CallArgs) {
    // Set up new context for the new FunctionDecl
    DeclContext* PrevContext = m_Sema->CurContext;

    m_Sema->CurContext = m_EvalDecl->getDeclContext();

    // Create template arguments
    Sema::InstantiatingTemplate Inst(*m_Sema, m_NoSLoc, m_EvalDecl);
    TemplateArgument Arg(InstTy);
    TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, &Arg, 1U);

    // Substitute the declaration of the templated function, with the
    // specified template argument
    Decl* D = m_Sema->SubstDecl(m_EvalDecl,
                                m_EvalDecl->getDeclContext(),
                                MultiLevelTemplateArgumentList(TemplateArgs));

    FunctionDecl* Fn = dyn_cast<FunctionDecl>(D);
    // Creates new body of the substituted declaration
    m_Sema->InstantiateFunctionDefinition(Fn->getLocation(), Fn, true, true);

    m_Sema->CurContext = PrevContext;

    const FunctionProtoType* FPT = Fn->getType()->getAs<FunctionProtoType>();
    FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
    QualType FnTy = m_Context->getFunctionType(Fn->getResultType(),
                                               FPT->arg_type_begin(),
                                               FPT->getNumArgs(),
                                               EPI);
    DeclRefExpr* DRE = m_Sema->BuildDeclRefExpr(Fn,
                                                FnTy,
                                                VK_RValue,
                                                m_NoSLoc
                                                ).takeAs<DeclRefExpr>();

    // TODO: Figure out a way to avoid passing in wrong source locations
    // of the symbol being replaced. This is important when we calculate the
    // size of the memory buffers and may lead to creation of wrong wrappers.
    Scope* S = m_Sema->getScopeForContext(m_Sema->CurContext);
    CallExpr* EvalCall = m_Sema->ActOnCallExpr(S,
                                               DRE,
                                               SubTree->getLocStart(),
                                               move_arg(CallArgs),
                                               SubTree->getLocEnd()
                                               ).takeAs<CallExpr>();
    assert (EvalCall && "Cannot create call to Eval");

    return EvalCall;

  }
Пример #23
0
C2::FunctionDecl* C2Sema::ActOnFuncDecl(const char* name, SourceLocation loc, bool is_public, Expr* rtype) {
#ifdef SEMA_DEBUG
    std::cerr << COL_SEMA"SEMA: func decl " << name << " at ";
    loc.dump(SourceMgr);
    std::cerr << ANSI_NORMAL"\n";
#endif
    FunctionDecl* D = createFuncDecl(name, loc, is_public, rtype);
    if (D->getName() == "main") D->setExported();
    ast.addFunction(D);
    addSymbol(D);
    return D;
}
Пример #24
0
// We can't handle function template explicit instantiation because
// I am not sure how to analyze its source location.
// For example, in the code below:
// template<typename T> bool foo(const int&) {return true;}
// template bool foo<char>(const int&);
//               ^ point of instantiation
// What I could get is the point of the instantiation, but I
// don't know the source range for the entire instantiation declaration.
void RemoveUnusedFunction::removeFunctionExplicitInstantiations(
       const FunctionDecl *FD)
{
  const FunctionTemplateDecl *FTD = getTopDescribedTemplate(FD);
  if (!FTD)
    return;

  const FunctionDecl *CanonicalFD = FD->getCanonicalDecl();
  MemberSpecializationSet *S = MemberToInstantiations[CanonicalFD];
  MemberSpecializationSet *ExplicitSpecs = 
          FuncToExplicitSpecs[CanonicalFD];

  for (FunctionTemplateDecl::spec_iterator I = FTD->spec_begin(),
       E = FTD->spec_end(); I != E; ++I) {
    FunctionDecl *Spec = (*I);
    TemplateSpecializationKind K = Spec->getTemplateSpecializationKind();
    if (K == TSK_ExplicitSpecialization) {
      // check if the explicit spec points to any dependent specs,
      // skip it if yes
      if (!ExplicitSpecs) {
        removeOneFunctionDecl(Spec);
      }
      else if (ExplicitSpecs->count(Spec)) {
        removeOneFunctionDecl(Spec);
        ExplicitSpecs->erase(Spec);
      }
      continue;
    }
    if (K != TSK_ExplicitInstantiationDeclaration &&
        K != TSK_ExplicitInstantiationDefinition)
      continue;
    TransAssert(!Spec->isReferenced() && "Referenced Instantiation!");
    removeOneExplicitInstantiation(Spec);
    if (S && S->count(Spec)) {
      S->erase(Spec);
    }
  }

  removeRemainingExplicitSpecs(ExplicitSpecs);

  if (!S)
    return;
  for (MemberSpecializationSet::iterator I = S->begin(), E = S->end();
       I != E; ++I) {
    const FunctionDecl *Spec = (*I);
    TemplateSpecializationKind K = Spec->getTemplateSpecializationKind();
    TransAssert(((K == TSK_ExplicitInstantiationDeclaration) ||
                  (K == TSK_ExplicitInstantiationDefinition)) &&
                "Bad Instantiation!"); (void)K;
    removeOneExplicitInstantiation(Spec);
  }
}
Пример #25
0
void QStringAllocations::VisitFromLatin1OrUtf8(Stmt *stmt)
{
    CallExpr *callExpr = dyn_cast<CallExpr>(stmt);
    if (!callExpr)
        return;

    FunctionDecl *functionDecl = callExpr->getDirectCallee();
    if (!StringUtils::functionIsOneOf(functionDecl, {"fromLatin1", "fromUtf8"}))
        return;

    CXXMethodDecl *methodDecl = dyn_cast<CXXMethodDecl>(functionDecl);
    if (!StringUtils::isOfClass(methodDecl, "QString"))
        return;

    if (!Utils::callHasDefaultArguments(callExpr) || !hasCharPtrArgument(functionDecl, 2)) // QString::fromLatin1("foo", 1) is ok
        return;

    if (!containsStringLiteralNoCallExpr(callExpr))
        return;

    if (!isOptionSet("no-msvc-compat")) {
        StringLiteral *lt = stringLiteralForCall(callExpr);
        if (lt && lt->getNumConcatenated() > 1) {
            return; // Nothing to do here, MSVC doesn't like it
        }
    }

    vector<ConditionalOperator*> ternaries;
    HierarchyUtils::getChilds(callExpr, ternaries, 2);
    if (!ternaries.empty()) {
        auto ternary = ternaries[0];
        if (Utils::ternaryOperatorIsOfStringLiteral(ternary)) {
            emitWarning(stmt->getLocStart(), string("QString::fromLatin1() being passed a literal"));
        }

        return;
    }

    std::vector<FixItHint> fixits;

    if (isFixitEnabled(FromLatin1_FromUtf8Allocations)) {
        const FromFunction fromFunction = functionDecl->getNameAsString() == "fromLatin1" ? FromLatin1 : FromUtf8;
        fixits = fixItReplaceFromLatin1OrFromUtf8(callExpr, fromFunction);
    }

    if (functionDecl->getNameAsString() == "fromLatin1") {
        emitWarning(stmt->getLocStart(), string("QString::fromLatin1() being passed a literal"), fixits);
    } else {
        emitWarning(stmt->getLocStart(), string("QString::fromUtf8() being passed a literal"), fixits);
    }
}
Пример #26
0
 virtual void run(const MatchFinder::MatchResult &results)
 {
     FunctionDecl *functionDecl = (FunctionDecl *)
         results.Nodes.getNodeAs<FunctionDecl>("functionDecl");
     if (functionDecl)
     {
         NPathComplexityMetric nPathMetric;
         EXPECT_EQ(_nPath, nPathMetric.nPath(functionDecl->getBody()));
     }
     else
     {
         FAIL();
     }
 }
Пример #27
0
 virtual void run(const MatchFinder::MatchResult &results)
 {
     FunctionDecl *functionDecl = (FunctionDecl *)
         results.Nodes.getNodeAs<FunctionDecl>("functionDecl");
     if (functionDecl)
     {
         StmtDepthMetric stmtDepthMetric;
         EXPECT_EQ(_depth, stmtDepthMetric.depth(functionDecl->getBody()));
     }
     else
     {
         FAIL();
     }
 }
Пример #28
0
 virtual void run(const MatchFinder::MatchResult &results)
 {
     FunctionDecl *functionDecl = (FunctionDecl *)
         results.Nodes.getNodeAs<FunctionDecl>("functionDecl");
     if (functionDecl)
     {
         NcssMetric ncssMetric;
         EXPECT_EQ(_ncss, ncssMetric.ncss(functionDecl->getBody()));
     }
     else
     {
         FAIL();
     }
 }
Пример #29
0
Decl *Sema::ActOnEntityDecl(ASTContext &C, const QualType &T,
                            SourceLocation IDLoc, const IdentifierInfo *IDInfo) {
  auto Quals = T.getQualifiers();

  if(Quals.hasAttributeSpec(Qualifiers::AS_external))
    return ActOnExternalEntityDecl(C, T, IDLoc, IDInfo);
  else if(Quals.hasAttributeSpec(Qualifiers::AS_intrinsic))
    return ActOnIntrinsicEntityDecl(C, T, IDLoc, IDInfo);

  if (auto Prev = LookupIdentifier(IDInfo)) {
    FunctionDecl *FD = dyn_cast<FunctionDecl>(Prev);
    if(auto VD = dyn_cast<VarDecl>(Prev)) {
      if(VD->isArgument() && VD->getType().isNull()) {
        VD->setType(T);
        return VD;
      } else if(VD->isFunctionResult())
         FD = CurrentContextAsFunction();
    }

    if(FD && (FD->isNormalFunction() || FD->isExternal())) {
      if(FD->getType().isNull() || FD->getType()->isVoidType()) {
        SetFunctionType(FD, T, IDLoc, SourceRange()); //Fixme: proper loc and range
        return FD;
      } else {
        Diags.Report(IDLoc, diag::err_func_return_type_already_specified) << IDInfo;
        return nullptr;
      }
    }
    Diags.Report(IDLoc, diag::err_redefinition) << IDInfo;
    Diags.Report(Prev->getLocation(), diag::note_previous_definition);
    return nullptr;
  }

  VarDecl *VD = VarDecl::Create(C, CurContext, IDLoc, IDInfo, T);
  CurContext->addDecl(VD);

  if(!T.isNull()) {
    auto SubT = T;
    if(T->isArrayType()) {
      CheckArrayTypeDeclarationCompability(T->asArrayType(), VD);
      SubT = T->asArrayType()->getElementType();
      VD->MarkUsedAsVariable(IDLoc);
    }
    else if(SubT->isCharacterType())
      CheckCharacterLengthDeclarationCompability(SubT, VD);
  }

  return VD;
}
Пример #30
0
C2::FunctionDecl* C2Sema::createFuncDecl(const char* name, SourceLocation loc,
            bool is_public, Expr* rtype) {
    assert(rtype);
    TypeExpr* typeExpr = cast<TypeExpr>(rtype);
    if (typeExpr->hasLocalQualifier()) {
        // TODO let Parser check this (need extra arg for ParseSingleTypeSpecifier())
        // TODO need local's location
        Diag(loc, diag::err_invalid_local_returntype);
    }
    FunctionDecl* D = new FunctionDecl(name, loc, is_public, typeExpr->getType());
    delete typeExpr;
    QualType qt =  typeContext.getFunctionType(D);
    D->setType(qt);
    return D;
}