Пример #1
0
raw_ostream &operator<<(raw_ostream &OS, DeclarationName N) {
    switch (N.getNameKind()) {
    case DeclarationName::Identifier:
        if (const IdentifierInfo *II = N.getAsIdentifierInfo())
            OS << II->getName();
        return OS;

    case DeclarationName::ObjCZeroArgSelector:
    case DeclarationName::ObjCOneArgSelector:
    case DeclarationName::ObjCMultiArgSelector:
        N.getObjCSelector().print(OS);
        return OS;

    case DeclarationName::CXXConstructorName: {
        QualType ClassType = N.getCXXNameType();
        if (const RecordType *ClassRec = ClassType->getAs<RecordType>())
            return OS << *ClassRec->getDecl();
        return OS << ClassType.getAsString();
    }

    case DeclarationName::CXXDestructorName: {
        OS << '~';
        QualType Type = N.getCXXNameType();
        if (const RecordType *Rec = Type->getAs<RecordType>())
            return OS << *Rec->getDecl();
        return OS << Type.getAsString();
    }

    case DeclarationName::CXXOperatorName: {
        static const char* const OperatorNames[NUM_OVERLOADED_OPERATORS] = {
            0,
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
  Spelling,
#include "clang/Basic/OperatorKinds.def"
        };
        const char *OpName = OperatorNames[N.getCXXOverloadedOperator()];
        assert(OpName && "not an overloaded operator");

        OS << "operator";
        if (OpName[0] >= 'a' && OpName[0] <= 'z')
            OS << ' ';
        return OS << OpName;
    }

    case DeclarationName::CXXLiteralOperatorName:
        return OS << "operator \"\" " << N.getCXXLiteralIdentifier()->getName();

    case DeclarationName::CXXConversionFunctionName: {
        OS << "operator ";
        QualType Type = N.getCXXNameType();
        if (const RecordType *Rec = Type->getAs<RecordType>())
            return OS << *Rec->getDecl();
        return OS << Type.getAsString();
    }
    case DeclarationName::CXXUsingDirective:
        return OS << "<using-directive>";
    }

    llvm_unreachable("Unexpected declaration name kind");
}
Пример #2
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);
            }
        }
    }
Пример #3
0
static void CompareReturnTypes(const ObjCMethodDecl *MethDerived,
                               const ObjCMethodDecl *MethAncestor,
                               BugReporter &BR, ASTContext &Ctx,
                               const ObjCImplementationDecl *ID) {

  QualType ResDerived  = MethDerived->getResultType();
  QualType ResAncestor = MethAncestor->getResultType();

  if (!AreTypesCompatible(ResDerived, ResAncestor, Ctx)) {
    std::string sbuf;
    llvm::raw_string_ostream os(sbuf);

    os << "The Objective-C class '"
       << MethDerived->getClassInterface()
       << "', which is derived from class '"
       << MethAncestor->getClassInterface()
       << "', defines the instance method '"
       << MethDerived->getSelector().getAsString()
       << "' whose return type is '"
       << ResDerived.getAsString()
       << "'.  A method with the same name (same selector) is also defined in "
          "class '"
       << MethAncestor->getClassInterface()
       << "' and has a return type of '"
       << ResAncestor.getAsString()
       << "'.  These two types are incompatible, and may result in undefined "
          "behavior for clients of these classes.";

    BR.EmitBasicReport("Incompatible instance method return type",
                       os.str(), MethDerived->getLocStart());
  }
}
Пример #4
0
void InheritanceHierarchyWriter::WriteNode(QualType Type, bool FromVirtual) {
  QualType CanonType = Context.getCanonicalType(Type);

  if (FromVirtual) {
    if (KnownVirtualBases.find(CanonType) != KnownVirtualBases.end())
      return;

    // We haven't seen this virtual base before, so display it and
    // its bases.
    KnownVirtualBases.insert(CanonType);
  }

  // Declare the node itself.
  Out << "  ";
  WriteNodeReference(Type, FromVirtual);

  // Give the node a label based on the name of the class.
  std::string TypeName = Type.getAsString();
  Out << " [ shape=\"box\", label=\"" << DOT::EscapeString(TypeName);

  // If the name of the class was a typedef or something different
  // from the "real" class name, show the real class name in
  // parentheses so we don't confuse ourselves.
  if (TypeName != CanonType.getAsString()) {
    Out << "\\n(" << CanonType.getAsString() << ")";
  }

  // Finished describing the node.
  Out << " \"];\n";

  // Display the base classes.
  const CXXRecordDecl *Decl
    = static_cast<const CXXRecordDecl *>(Type->getAs<RecordType>()->getDecl());
  for (CXXRecordDecl::base_class_const_iterator Base = Decl->bases_begin();
       Base != Decl->bases_end(); ++Base) {
    QualType CanonBaseType = Context.getCanonicalType(Base->getType());

    // If this is not virtual inheritance, bump the direct base
    // count for the type.
    if (!Base->isVirtual())
      ++DirectBaseCount[CanonBaseType];

    // Write out the node (if we need to).
    WriteNode(Base->getType(), Base->isVirtual());

    // Write out the edge.
    Out << "  ";
    WriteNodeReference(Type, FromVirtual);
    Out << " -> ";
    WriteNodeReference(Base->getType(), Base->isVirtual());

    // Write out edge attributes to show the kind of inheritance.
    if (Base->isVirtual()) {
      Out << " [ style=\"dashed\" ]";
    }
    Out << ";";
  }
}
Пример #5
0
bool FFIBindingsUtils::isNewType(QualType Type) {

  if (isInResolvedDecls(Type.getAsString())) {
    return false;
  }
  if (isInUnresolvedDeclarations(Type.getAsString())) {
    return false;
  }
  return true;
}
Пример #6
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());
        }
    }
}
Пример #7
0
    bool VisitFunctionDecl(FunctionDecl *f) {
        // Only function definitions (with bodies), not declarations.
        if (f->hasBody()) {
            Stmt *FuncBody = f->getBody();

            // Type name as string
            QualType QT = f->getResultType();
            string TypeStr = QT.getAsString();

            // Function name
            DeclarationName DeclName = f->getNameInfo().getName();
            string FuncName = DeclName.getAsString();

            // Add comment before
            stringstream SSBefore;
            SSBefore << "// Begin function " << FuncName << " returning "
                     << TypeStr << "\n";
            SourceLocation ST = f->getSourceRange().getBegin();
            TheRewriter.InsertText(ST, SSBefore.str(), true, true);

            // And after
            stringstream SSAfter;
            SSAfter << "\n// End function " << FuncName << "\n";
            ST = FuncBody->getLocEnd().getLocWithOffset(1);
            TheRewriter.InsertText(ST, SSAfter.str(), true, true);
        }

        return true;
    }
Пример #8
0
    Record* HandleRecordDecl(CXXRecordDecl *D) {
        assert(D && "Class missing in HandleRecordDecl");
        if (!D->hasDefinition())
            return NULL;

        // skip duplication
        if(records.find(D->getQualifiedNameAsString()) != records.end()) return 0;

        Record *r = new Record;
        r->qualifiedname = D->getQualifiedNameAsString();
        //find all base classes
        //we skip all the template classes or there will be Assertion failed
        if (!D->getDescribedClassTemplate ()) {
            for (CXXRecordDecl::base_class_iterator iter = D->bases_begin();
                    iter != D->bases_end(); ++iter) {
                if (iter) {
                    QualType type = iter->getType();
                    std::string tmp = type.getAsString();
                    //remove "class "
                    tmp.erase(0, 6);
                    r->bases.insert(tmp);
                }
            }
        }

        return r;
    }
std::shared_ptr<PathDiagnosticPiece>
InnerPointerChecker::InnerPointerBRVisitor::VisitNode(const ExplodedNode *N,
                                                      BugReporterContext &BRC,
                                                      BugReport &) {
  if (!isSymbolTracked(N->getState(), PtrToBuf) ||
      isSymbolTracked(N->getFirstPred()->getState(), PtrToBuf))
    return nullptr;

  const Stmt *S = PathDiagnosticLocation::getStmt(N);
  if (!S)
    return nullptr;

  const MemRegion *ObjRegion =
      allocation_state::getContainerObjRegion(N->getState(), PtrToBuf);
  const auto *TypedRegion = cast<TypedValueRegion>(ObjRegion);
  QualType ObjTy = TypedRegion->getValueType();

  SmallString<256> Buf;
  llvm::raw_svector_ostream OS(Buf);
  OS << "Pointer to inner buffer of '" << ObjTy.getAsString()
     << "' obtained here";
  PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
                             N->getLocationContext());
  return std::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(), true,
                                                    nullptr);
}
Пример #10
0
/// viewInheritance - Display the inheritance hierarchy of this C++
/// class using GraphViz.
void CXXRecordDecl::viewInheritance(ASTContext& Context) const {
  QualType Self = Context.getTypeDeclType(this);
  std::string ErrMsg;
  sys::Path Filename = sys::Path::GetTemporaryDirectory(&ErrMsg);
  if (Filename.isEmpty()) {
    llvm::errs() << "Error: " << ErrMsg << "\n";
    return;
  }
  Filename.appendComponent(Self.getAsString() + ".dot");
  if (Filename.makeUnique(true,&ErrMsg)) {
    llvm::errs() << "Error: " << ErrMsg << "\n";
    return;
  }

  llvm::errs() << "Writing '" << Filename.c_str() << "'... ";

  llvm::raw_fd_ostream O(Filename.c_str(), ErrMsg);

  if (ErrMsg.empty()) {
    InheritanceHierarchyWriter Writer(Context, O);
    Writer.WriteGraph(Self);
    llvm::errs() << " done. \n";

    O.close();

    // Display the graph
    DisplayGraph(Filename);
  } else {
    llvm::errs() << "error opening file for writing!\n";
  }
}
/// If type represents a pointer to CXXRecordDecl,
/// and is not a typedef, return the decl name.
/// Otherwise, return the serialization of type.
static std::string getPrettyTypeName(QualType QT) {
  QualType PT = QT->getPointeeType();
  if (!PT.isNull() && !QT->getAs<TypedefType>())
    if (const auto *RD = PT->getAsCXXRecordDecl())
      return RD->getName();
  return QT.getAsString();
}
std::string getTypeName(QualType qualType, bool qualifyNames)
{
    auto langOptions = clang::LangOptions{};
    auto printPolicy = PrintingPolicy{ langOptions };
    printPolicy.SuppressSpecifiers = false;
    printPolicy.ConstantArraySizeAsWritten = false;
    return qualType.getAsString(printPolicy);

}
Пример #13
0
std::string getFullyQualifiedName(QualType QT,
                                  const ASTContext &Ctx) {
  PrintingPolicy Policy(Ctx.getPrintingPolicy());
  Policy.SuppressScope = false;
  Policy.AnonymousTagLocations = false;
  Policy.PolishForDeclaration = true;
  Policy.SuppressUnwrittenScope = true;
  QualType FQQT = getFullyQualifiedType(QT, Ctx);
  return FQQT.getAsString(Policy);
}
Пример #14
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;
    }
//// \brief Apply the source transformations necessary to migrate the loop!
void LoopFixer::doConversion(ASTContext *Context,
                             const VarDecl *IndexVar,
                             const VarDecl *MaybeContainer,
                             StringRef ContainerString,
                             const UsageResult &Usages,
                             const DeclStmt *AliasDecl, const ForStmt *TheLoop,
                             bool ContainerNeedsDereference) {
  std::string VarName;

  if (Usages.size() == 1 && AliasDecl) {
    const VarDecl *AliasVar = cast<VarDecl>(AliasDecl->getSingleDecl());
    VarName = AliasVar->getName().str();
    // We keep along the entire DeclStmt to keep the correct range here.
    const SourceRange &ReplaceRange = AliasDecl->getSourceRange();
    if (!CountOnly)
      Replace->insert(
          Replacement(Context->getSourceManager(),
                      CharSourceRange::getTokenRange(ReplaceRange), ""));
    // No further replacements are made to the loop, since the iterator or index
    // was used exactly once - in the initialization of AliasVar.
  } else {
    VariableNamer Namer(GeneratedDecls, &ParentFinder->getStmtToParentStmtMap(),
                        TheLoop, IndexVar, MaybeContainer);
    VarName = Namer.createIndexName();
    // First, replace all usages of the array subscript expression with our new
    // variable.
    for (UsageResult::const_iterator I = Usages.begin(), E = Usages.end();
         I != E; ++I) {
      std::string ReplaceText = I->IsArrow ? VarName + "." : VarName;
      ReplacedVarRanges->insert(std::make_pair(TheLoop, IndexVar));
      if (!CountOnly)
        Replace->insert(
            Replacement(Context->getSourceManager(),
                        CharSourceRange::getTokenRange(I->Range),
                        ReplaceText));
    }
  }

  // Now, we need to construct the new range expresion.
  SourceRange ParenRange(TheLoop->getLParenLoc(), TheLoop->getRParenLoc());

  QualType AutoRefType =
      Context->getLValueReferenceType(Context->getAutoDeductType());

  std::string MaybeDereference = ContainerNeedsDereference ? "*" : "";
  std::string TypeString = AutoRefType.getAsString();
  std::string Range = ("(" + TypeString + " " + VarName + " : "
                           + MaybeDereference + ContainerString + ")").str();
  if (!CountOnly)
    Replace->insert(Replacement(Context->getSourceManager(),
                                CharSourceRange::getTokenRange(ParenRange),
                                Range));
  GeneratedDecls->insert(make_pair(TheLoop, VarName));
}
Пример #16
0
/// \brief Convert the given type to a string suitable for printing as part of 
/// a diagnostic.
///
/// There are three main criteria when determining whether we should have an
/// a.k.a. clause when pretty-printing a type:
///
/// 1) Some types provide very minimal sugar that doesn't impede the
///    user's understanding --- for example, elaborated type
///    specifiers.  If this is all the sugar we see, we don't want an
///    a.k.a. clause.
/// 2) Some types are technically sugared but are much more familiar
///    when seen in their sugared form --- for example, va_list,
///    vector types, and the magic Objective C types.  We don't
///    want to desugar these, even if we do produce an a.k.a. clause.
/// 3) Some types may have already been desugared previously in this diagnostic.
///    if this is the case, doing another "aka" would just be clutter.
///
/// \param Context the context in which the type was allocated
/// \param Ty the type to print
static std::string
ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
                              const Diagnostic::ArgumentValue *PrevArgs,
                              unsigned NumPrevArgs) {
  // FIXME: Playing with std::string is really slow.
  std::string S = Ty.getAsString(Context.PrintingPolicy);

  // Check to see if we already desugared this type in this
  // diagnostic.  If so, don't do it again.
  bool Repeated = false;
  for (unsigned i = 0; i != NumPrevArgs; ++i) {
    // TODO: Handle ak_declcontext case.
    if (PrevArgs[i].first == Diagnostic::ak_qualtype) {
      void *Ptr = (void*)PrevArgs[i].second;
      QualType PrevTy(QualType::getFromOpaquePtr(Ptr));
      if (PrevTy == Ty) {
        Repeated = true;
        break;
      }
    }
  }

  // Consider producing an a.k.a. clause if removing all the direct
  // sugar gives us something "significantly different".
  if (!Repeated) {
    bool ShouldAKA = false;
    QualType DesugaredTy = Desugar(Context, Ty, ShouldAKA);
    if (ShouldAKA) {
      std::string D = DesugaredTy.getAsString(Context.PrintingPolicy);
      if (D != S) {
        S = "'" + S + "' (aka '";
        S += D;
        S += "')";
        return S;
      }
    }
  }

  S = "'" + S + "'";
  return S;
}
Пример #17
0
/// \brief Convert the given type to a string suitable for printing as part of 
/// a diagnostic. 
///
/// \param Context the context in which the type was allocated
/// \param Ty the type to print
static std::string
ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
                              const Diagnostic::ArgumentValue *PrevArgs,
                              unsigned NumPrevArgs) {
  // FIXME: Playing with std::string is really slow.
  std::string S = Ty.getAsString(Context.PrintingPolicy);
  
  // Consider producing an a.k.a. clause if removing all the direct
  // sugar gives us something "significantly different".
  
  QualType DesugaredTy;
  if (ShouldAKA(Context, Ty, PrevArgs, NumPrevArgs, DesugaredTy)) {
    S = "'"+S+"' (aka '";
    S += DesugaredTy.getAsString(Context.PrintingPolicy);
    S += "')";
    return S;
  }
  
  S = "'" + S + "'";
  return S;
}
Пример #18
0
clang::ast_matchers::MatchFinder MatchContainer::getMatcher()
{
	MatchFinder finder;

	// Some debug bind slot
	onStmtMatch.emplace("dump", [](Stmt const * d) {d->dump(); });
	onTypeMatch.emplace("dump", [](Type const * d) {d->dump(); });
	onDeclMatch.emplace("dump", [](Decl const * d) {d->dump(); });
	onDeclMatch.emplace("print_name", [](Decl const * d)
	{
		if(auto* nd = dyn_cast<NamedDecl>(d))
			llvm::errs() << nd->getNameAsString() << "\n";
	});

	//free operators
	DeclarationMatcher out_stream_op =
	  functionDecl(
	    unless(hasDeclContext(recordDecl())),
	    matchesName("operator[\\+-\\*\\^\\[\\(\\!\\&\\|\\~\\=\\/\\%\\<\\>]")
	  ).bind("free_operator");
	finder.addMatcher(out_stream_op, this);
	declPrinters.emplace("free_operator", [](DPrinter&, Decl*) {});
	onDeclMatch.emplace("free_operator", [this](Decl const * d)
	{
		if(auto* funcDecl = dyn_cast<FunctionDecl>(d))
		{
			auto getParamTypeName = [](ParmVarDecl const * typeParam)
			{
				QualType canType = typeParam->getType().getCanonicalType()
				                   .getUnqualifiedType().getNonReferenceType();
				canType.removeLocalConst();
				return canType.getAsString();
			};

			if(funcDecl->getNumParams() > 0)
			{
				std::string const left_name = getParamTypeName(funcDecl->getParamDecl(0));
				freeOperator.emplace(left_name, funcDecl);
				if(funcDecl->getNumParams() > 1)
				{
					std::string const right_name = getParamTypeName(funcDecl->getParamDecl(1));
					if(right_name != left_name)
						freeOperatorRight.emplace(right_name, funcDecl);
				}
			}
		}
	});

	for(auto printerRegisterers : CustomPrinters::getInstance().getRegisterers())
		printerRegisterers(*this, finder);

	return finder;
}
Пример #19
0
static bool rewriteToObjCProperty(const ObjCMethodDecl *Getter,
                                  const ObjCMethodDecl *Setter,
                                  const NSAPI &NS, edit::Commit &commit) {
  ASTContext &Context = NS.getASTContext();
  std::string PropertyString = "@property";
  const ParmVarDecl *argDecl = *Setter->param_begin();
  QualType ArgType = Context.getCanonicalType(argDecl->getType());
  Qualifiers::ObjCLifetime propertyLifetime = ArgType.getObjCLifetime();
  
  if (ArgType->isObjCRetainableType() &&
      propertyLifetime == Qualifiers::OCL_Strong) {
    if (const ObjCObjectPointerType *ObjPtrTy =
        ArgType->getAs<ObjCObjectPointerType>()) {
      ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
      if (IDecl &&
          IDecl->lookupNestedProtocol(&Context.Idents.get("NSCopying")))
        PropertyString += "(copy)";
    }
  }
  else if (propertyLifetime == Qualifiers::OCL_Weak)
    // TODO. More precise determination of 'weak' attribute requires
    // looking into setter's implementation for backing weak ivar.
    PropertyString += "(weak)";
  else
    PropertyString += "(unsafe_unretained)";
  
  // strip off any ARC lifetime qualifier.
  QualType CanResultTy = Context.getCanonicalType(Getter->getResultType());
  if (CanResultTy.getQualifiers().hasObjCLifetime()) {
    Qualifiers Qs = CanResultTy.getQualifiers();
    Qs.removeObjCLifetime();
    CanResultTy = Context.getQualifiedType(CanResultTy.getUnqualifiedType(), Qs);
  }
  PropertyString += " ";
  PropertyString += CanResultTy.getAsString(Context.getPrintingPolicy());
  PropertyString += " ";
  PropertyString += Getter->getNameAsString();
  commit.replace(CharSourceRange::getCharRange(Getter->getLocStart(),
                                               Getter->getDeclaratorEndLoc()),
                 PropertyString);
  SourceLocation EndLoc = Setter->getDeclaratorEndLoc();
  // Get location past ';'
  EndLoc = EndLoc.getLocWithOffset(1);
  commit.remove(CharSourceRange::getCharRange(Setter->getLocStart(), EndLoc));
  return true;
}
Пример #20
0
    bool VisitFunctionDecl(FunctionDecl *f) {
        // Only function definitions (with bodies), not declarations.
            Stmt *FuncBody = f->getBody();
            // Type name as string
            QualType QT = f->getResultType();
            string TypeStr = QT.getAsString();
            // Function name
            DeclarationName DeclName = f->getNameInfo().getName();
            string FuncName = DeclName.getAsString();
            func_info fi;
            fi.name = FuncName;
            fi.return_type = TypeStr;
            unsigned nbp = f->getNumParams();
            for (int i = 0; i < nbp; ++i) {
                //getTypeSourceInfo()->getType() and getOriginalType() is the final type. e.g. for size_t, the result may be unsigned int, but we need only size_t
                //fi.argv.push_back(f->getParamDecl(i)->getTypeSourceInfo()->getType().getAsString());//->getOriginalType().getAsString());
/*
                TypeLoc tl = f->getParamDecl(i)->getTypeSourceInfo()->getTypeLoc();
                SourceLocation sl0 = tl.getBeginLoc();
                SourceLocation sl1 = tl.getEndLoc();
                const char* ptr0 = TheRewriter.getSourceMgr().getCharacterData(sl0);
                const char* ptr1 = TheRewriter.getSourceMgr().getCharacterData(sl1);
*/
                fi.argv.push_back(trim(decl2str_without_var(f->getParamDecl(i), &TheRewriter.getSourceMgr())));
            }
            mFuncInfo.push_back(fi);
#if 0
            if (f->hasBody()) {
                // Add comment before
                stringstream SSBefore;
                SSBefore << "// Begin function " << FuncName << " returning "
                         << TypeStr << "\n";
                SourceLocation ST = f->getSourceRange().getBegin();
                TheRewriter.InsertText(ST, SSBefore.str(), true, true);

                // And after
                stringstream SSAfter;
                SSAfter << "\n// End function " << FuncName << "\n";
                ST = FuncBody->getLocEnd().getLocWithOffset(1);
                TheRewriter.InsertText(ST, SSAfter.str(), true, true);
            }
#endif
        return true;
    }
Пример #21
0
/// \brief If the new variable name conflicts with any type used in the loop,
/// then we mark that variable name as taken.
bool DeclFinderASTVisitor::VisitTypeLoc(TypeLoc TL) {
  QualType QType = TL.getType();

  // Check if our name conflicts with a type, to handle for typedefs.
  if (QType.getAsString() == Name) {
    Found = true;
    return false;
  }
  // Check for base type conflicts. For example, when a struct is being
  // referenced in the body of the loop, the above getAsString() will return the
  // whole type (ex. "struct s"), but will be caught here.
  if (const IdentifierInfo *Ident = QType.getBaseTypeIdentifier()) {
    if (Ident->getName() == Name) {
      Found = true;
      return false;
    }
  }
  return true;
}
Пример #22
0
  bool VisitVarDecl(const VarDecl *D) {
    // Bail out early if this location should not be checked.
    if (doIgnore(D->getLocation())) {
      return true;
    }

    const QualType qualType = D->getType();
    // Bail out if this type is either an enum or does not look like a real
    // value.
    if (qualType->isEnumeralType() || qualType->isBooleanType() ||
        qualType->isArithmeticType() == false) {
      return true;
    }

    const Type *t = qualType.getTypePtrOrNull();
    assert(t && "Type of arithmetic types has to be available.");
    const std::string typeName = qualType.getAsString();
    // If it is of the same type as "size_t" and does have "size_t" somewhere in
    // its name we can go with it.
    // Please note: This also allows a typedef for "unsigned long" to be named
    // e.g. "size_type" without any size indicator - which may or may not be a
    // good thing.
    if (context->hasSameUnqualifiedType(qualType, context->getSizeType()) &&
        typeName.find("size_t") != std::string::npos) {
      return true;
    }

    // char_t and wchar_t are not subject to this rule.
    const std::string needle = "char_t";
    if (std::equal(needle.rbegin(), needle.rend(), typeName.rbegin())) {
      return true;
    }

    const uint64_t typeSize = context->getTypeSize(t);
    const std::string sizeStr = llvm::utostr(typeSize);
    // For all remaining types, the number of occupied bits must be embedded in
    // the typename.
    if (typeName.rfind(sizeStr) == std::string::npos) {
      reportError(D->getLocation());
    }

    return true;
  }
Пример #23
0
  void printType_Default(llvm::raw_ostream& o, const Value& V) {
    using namespace clang;
    QualType QT = V.getType().getNonReferenceType();
    std::string ValueTyStr;
    if (const TypedefType* TDTy = dyn_cast<TypedefType>(QT))
      ValueTyStr = TDTy->getDecl()->getQualifiedNameAsString();
    else if (const TagType* TTy = dyn_cast<TagType>(QT))
      ValueTyStr = TTy->getDecl()->getQualifiedNameAsString();

    if (ValueTyStr.empty())
      ValueTyStr = QT.getAsString();
    else if (QT.hasQualifiers())
      ValueTyStr = QT.getQualifiers().getAsString() + " " + ValueTyStr;

    o << "(";
    o << ValueTyStr;
    if (V.getType()->isReferenceType())
      o << " &";
    o << ") ";
  }
void ReplaceArrayAccessWithIndex::doRewrite(void)
{
  ArraySubscriptExpr const *ASE = ASEs[TransformationCounter - 1];
  Expr const *Idx = ASE->getIdx();

  TransAssert(Idx && "Bad Idx!");

  std::string IdxStr;
  RewriteHelper->getExprString(Idx, IdxStr);

  QualType ASEType = ASE->getType().getCanonicalType();
  QualType IdxType = Idx->getType().getCanonicalType();

  if (ASEType != IdxType) {
    IdxStr = std::string("(") + ASEType.getAsString() + std::string(")")+
      std::string("(") + IdxStr + std::string(")");
  }

  RewriteHelper->replaceExpr(ASE, IdxStr);
}
Пример #25
0
bool FindModule::VisitCXXRecordDecl (CXXRecordDecl * d)
{

	if (_decl->getNumBases () <= 0)
		{
			return true;
		}

	for (CXXRecordDecl::base_class_iterator bi = _decl->bases_begin (), be =
			 _decl->bases_end (); bi != be; ++bi)
		{
			QualType
				q = bi->getType ();

			string
				baseName = q.getAsString ();

			if (baseName == "::sc_core::sc_module"
					|| baseName == "sc_core::sc_module"
					|| baseName == "class sc_core::sc_module")
				{

					_isSystemCModule = true;
					IdentifierInfo *
						info = _decl->getIdentifier ();

					if (info != NULL)
						{
							_moduleName = info->getNameStart ();
						}
				}
		}

	if (_isSystemCModule == false)
		{
			return true;
		}

	return false;
}
Пример #26
0
void ASTLocation::print(raw_ostream &OS) const {
  if (isInvalid()) {
    OS << "<< Invalid ASTLocation >>\n";
    return;
  }
  
  ASTContext &Ctx = getParentDecl()->getASTContext();

  switch (getKind()) {
  case N_Decl:
    OS << "[Decl: " << AsDecl()->getDeclKindName() << " ";
    if (const NamedDecl *ND = dyn_cast<NamedDecl>(AsDecl()))
      OS << ND;
    break;

  case N_Stmt:
    OS << "[Stmt: " << AsStmt()->getStmtClassName() << " ";
    AsStmt()->printPretty(OS, Ctx, 0, PrintingPolicy(Ctx.getLangOptions()));
    break;
    
  case N_NamedRef:
    OS << "[NamedRef: " << AsNamedRef().ND->getDeclKindName() << " ";
    OS << AsNamedRef().ND;
    break;
    
  case N_Type: {
    QualType T = AsTypeLoc().getType();
    OS << "[Type: " << T->getTypeClassName() << " " << T.getAsString();
  }
  }

  OS << "] <";

  SourceRange Range = getSourceRange();
  SourceManager &SourceMgr = Ctx.getSourceManager();
  Range.getBegin().print(OS, SourceMgr);
  OS << ", ";
  Range.getEnd().print(OS, SourceMgr);
  OS << ">\n";
}
void StaticAccessedThroughInstanceCheck::check(
    const MatchFinder::MatchResult &Result) {
  const auto *MemberExpression =
      Result.Nodes.getNodeAs<MemberExpr>("memberExpression");

  if (MemberExpression->getBeginLoc().isMacroID())
    return;

  const Expr *BaseExpr = MemberExpression->getBase();

  // Do not warn for overlaoded -> operators.
  if (isa<CXXOperatorCallExpr>(BaseExpr))
    return;

  QualType BaseType =
      BaseExpr->getType()->isPointerType()
          ? BaseExpr->getType()->getPointeeType().getUnqualifiedType()
          : BaseExpr->getType().getUnqualifiedType();

  const ASTContext *AstContext = Result.Context;
  PrintingPolicy PrintingPolicyWithSupressedTag(AstContext->getLangOpts());
  PrintingPolicyWithSupressedTag.SuppressTagKeyword = true;
  PrintingPolicyWithSupressedTag.SuppressUnwrittenScope = true;
  std::string BaseTypeName =
      BaseType.getAsString(PrintingPolicyWithSupressedTag);

  SourceLocation MemberExprStartLoc = MemberExpression->getBeginLoc();
  auto Diag =
      diag(MemberExprStartLoc, "static member accessed through instance");

  if (BaseExpr->HasSideEffects(*AstContext) ||
      getNameSpecifierNestingLevel(BaseType) > NameSpecifierNestingThreshold)
    return;

  Diag << FixItHint::CreateReplacement(
      CharSourceRange::getCharRange(MemberExprStartLoc,
                                    MemberExpression->getMemberLoc()),
      BaseTypeName + "::");
}
Пример #28
0
 virtual bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
   if (E->getReceiverKind() == ObjCMessageExpr::Class) {
     QualType ReceiverType = E->getClassReceiver();
     Selector Sel = E->getSelector();
     string TypeName = ReceiverType.getAsString();
     string SelName = Sel.getAsString();
     if (TypeName == "Observer" && SelName == "observerWithTarget:action:") {
       Expr *Receiver = E->getArg(0)->IgnoreParenCasts();
       ObjCSelectorExpr* SelExpr = cast<ObjCSelectorExpr>(E->getArg(1)->IgnoreParenCasts());
       Selector Sel = SelExpr->getSelector();
       if (const ObjCObjectPointerType *OT = Receiver->getType()->getAs<ObjCObjectPointerType>()) {
         ObjCInterfaceDecl *decl = OT->getInterfaceDecl();
         if (! decl->lookupInstanceMethod(Sel)) {
           errs() << "Warning: class " << TypeName << " does not implement selector " << Sel.getAsString() << "\n";
           SourceLocation Loc = E->getExprLoc();
           PresumedLoc PLoc = astContext->getSourceManager().getPresumedLoc(Loc);
           errs() << "in " << PLoc.getFilename() << " <" << PLoc.getLine() << ":" << PLoc.getColumn() << ">\n";
         }
       }
     }
   }
   return true;
 }
Пример #29
0
  void Value::print(llvm::raw_ostream& Out) const {
    // Try to find user defined printing functions:
    // cling::printType(const void* const p, TY* const u, const Value& V) and
    // cling::printValue(const void* const p, TY* const u, const Value& V)

    using namespace clang;
    Sema& SemaR = m_Interpreter->getSema();
    ASTContext& C = SemaR.getASTContext();
    NamespaceDecl* ClingNSD = utils::Lookup::Namespace(&SemaR, "cling");
    SourceLocation noLoc;
    LookupResult R(SemaR, &C.Idents.get("printType"), noLoc,
                   Sema::LookupOrdinaryName, Sema::ForRedeclaration);
    assert(ClingNSD && "There must be a valid namespace.");

    {
      // Could trigger deserialization of decls.
      cling::Interpreter::PushTransactionRAII RAII(m_Interpreter);
      SemaR.LookupQualifiedName(R, ClingNSD);
      // We commit here because the possibly deserialized decls from the lookup
      // will be needed by evaluate.
    }
    QualType ValueTy = this->getType().getNonReferenceType();
    bool ValidAddress = true;
    if (!ValueTy->isPointerType())
      ValueTy = C.getPointerType(ValueTy);
    else
       ValidAddress = isAddressValid(this->getPtr());
    ValueTy = utils::TypeName::GetFullyQualifiedType(ValueTy, getASTContext());
    PrintingPolicy Policy(m_Interpreter->getCI()->getLangOpts());
    std::string ValueTyStr = ValueTy.getAsString(Policy);
    std::string typeStr;
    std::string valueStr;

    if (ValidAddress && hasViableCandidateToCall(R, *this)) {
      // There is such a routine call, it:
      std::stringstream printTypeSS;
      printTypeSS << "cling::printType(";
      printTypeSS << '(' << ValueTyStr << ')' << this->getPtr() << ',';
      printTypeSS << '(' << ValueTyStr << ')' << this->getPtr() << ',';
      printTypeSS <<"(*(cling::Value*)" << this << "));";
      Value printTypeV;
      m_Interpreter->evaluate(printTypeSS.str(), printTypeV);
      assert(printTypeV.isValid() && "Must return valid value.");
      typeStr = *(std::string*)printTypeV.getPtr();
      // CXXScopeSpec CSS;
      // Expr* UnresolvedLookup
      //   = m_Sema->BuildDeclarationNameExpr(CSS, R, /*ADL*/ false).take();
      // // Build Arg1: const void* const p
      // QualType ConstVoidPtrTy = C.VoidPtrTy.withConst();
      // Expr* Arg1
      //   = utils::Synthesize::CStyleCastPtrExpr(SemaR, ConstVoidPtrTy,
      //                                          (uint64_t)this->getPtr());

      // // Build Arg2: TY* const u
      // Expr* Arg2
      //   = utils::Synthesize::CStyleCastPtrExpr(SemaR, ValueTy,
      //                                          (uint64_t)this->getPtr());

      // // Build Arg3: const Value&
      // RecordDecl* ClingValueDecl
      //   = dyn_cast<RecordDecl>(utils::Lookup::Named(SemaR, "Value",ClingNSD));
      // assert(ClingValueDecl && "Declaration must be found!");
      // QualType ClingValueTy = m_Context->getTypeDeclType(ClingValueDecl);
      // Expr* Arg3
      //   = utils::Synthesize::CStyleCastPtrExpr(m_Sema, ClingValueTy,
      //                                          (uint64_t)this);
      // llvm::SmallVector<Expr*, 4> CallArgs;
      // CallArgs.push_back(Arg1);
      // CallArgs.push_back(Arg2);
      // CallArgs.push_back(Arg3);
      // Expr* Call = m_Sema->ActOnCallExpr(/*Scope*/0, UnresolvedLookup, noLoc,
      //                                    CallArgs, noLoc).take();
    }
    else {
      llvm::raw_string_ostream o(typeStr);
      cling::valuePrinterInternal::printType_Default(o, *this);
    }
    R.clear();
    R.setLookupName(&C.Idents.get("printValue"));
    {
      // Could trigger deserialization of decls.
      cling::Interpreter::PushTransactionRAII RAII(m_Interpreter);
      SemaR.LookupQualifiedName(R, ClingNSD);
      // We commit here because the possibly deserialized decls from the lookup
      // will be needed by evaluate.
    }

    if (ValidAddress && hasViableCandidateToCall(R, *this)) {
      // There is such a routine call it:
      std::stringstream printValueSS;
      printValueSS << "cling::printValue(";
      printValueSS << '(' << ValueTyStr << ')' << this->getPtr() << ',';
      printValueSS << '(' << ValueTyStr << ')' << this->getPtr() << ',';
      printValueSS <<"(*(cling::Value*)" << this << "));";
      Value printValueV;
      m_Interpreter->evaluate(printValueSS.str(), printValueV);
      assert(printValueV.isValid() && "Must return valid value.");
      valueStr = *(std::string*)printValueV.getPtr();
    }
    else {
      llvm::raw_string_ostream o(valueStr);
      cling::valuePrinterInternal::printValue_Default(o, *this);
    }

    // print the type and the value:
    Out << typeStr + valueStr << "\n";
  }
Пример #30
0
 bool GetType(QualType T, Obj * tt) {
     
     T = Context->getCanonicalType(T);
     const Type *Ty = T.getTypePtr();
     
     switch (Ty->getTypeClass()) {
       case Type::Record: {
         const RecordType *RT = dyn_cast<RecordType>(Ty);
         RecordDecl * rd = RT->getDecl();
         return GetRecordTypeFromDecl(rd, tt);
       }  break; //TODO
       case Type::Builtin:
         switch (cast<BuiltinType>(Ty)->getKind()) {
         case BuiltinType::Void:
           InitType("opaque",tt);
             return true;
         case BuiltinType::Bool:
             InitType("bool",tt);
             return true;
         case BuiltinType::Char_S:
         case BuiltinType::Char_U:
         case BuiltinType::SChar:
         case BuiltinType::UChar:
         case BuiltinType::Short:
         case BuiltinType::UShort:
         case BuiltinType::Int:
         case BuiltinType::UInt:
         case BuiltinType::Long:
         case BuiltinType::ULong:
         case BuiltinType::LongLong:
         case BuiltinType::ULongLong:
         case BuiltinType::WChar_S:
         case BuiltinType::WChar_U:
         case BuiltinType::Char16:
         case BuiltinType::Char32: {
             std::stringstream ss;
             if (Ty->isUnsignedIntegerType())
                 ss << "u";
             ss << "int";
             int sz = Context->getTypeSize(T);
             ss << sz;
             InitType(ss.str().c_str(),tt);
             return true;
         }
         case BuiltinType::Half:
             break;
         case BuiltinType::Float:
             InitType("float",tt);
             return true;
         case BuiltinType::Double:
             InitType("double",tt);
             return true;
         case BuiltinType::LongDouble:
         case BuiltinType::NullPtr:
         case BuiltinType::UInt128:
         default:
             break;
         }
       case Type::Complex:
       case Type::LValueReference:
       case Type::RValueReference:
         break;
       case Type::Pointer: {
         const PointerType *PTy = cast<PointerType>(Ty);
         QualType ETy = PTy->getPointeeType();
         Obj t2;
         if(!GetType(ETy,&t2)) {
             return false;
         }
         PushTypeField("pointer");
         t2.push();
         lua_call(L,1,1);
         tt->initFromStack(L, ref_table);
         return true;
       }
       
       case Type::VariableArray:
       case Type::IncompleteArray:
         break;
       case Type::ConstantArray: {
         Obj at;
         const ConstantArrayType *ATy = cast<ConstantArrayType>(Ty);
         int sz = ATy->getSize().getZExtValue();
         if(GetType(ATy->getElementType(),&at)) {
             PushTypeField("array");
             at.push();
             lua_pushinteger(L, sz);
             lua_call(L,2,1);
             tt->initFromStack(L,ref_table);
             return true;
         } else {
             return false;
         }
       } break;
       case Type::ExtVector:
       case Type::Vector: {
             //printf("making a vector!\n");
             const VectorType *VT = cast<VectorType>(T);
             Obj at;
             if(GetType(VT->getElementType(),&at)) {
                 int n = VT->getNumElements();
                 PushTypeField("vector");
                 at.push();
                 lua_pushinteger(L,n);
                 lua_call(L,2,1);
                 tt->initFromStack(L, ref_table);
                 return true;
             } else {
                 return false;
             }
       } break;
       case Type::FunctionNoProto:
             break;
       case Type::FunctionProto: {
             const FunctionProtoType *FT = cast<FunctionProtoType>(Ty);
             //call functype... getNumArgs();
             if(FT && GetFuncType(FT,tt))
                 return true;
             else
                 return false;
             break;
       }
       case Type::ObjCObject:
       case Type::ObjCInterface:
       case Type::ObjCObjectPointer:
       case Type::Enum:
         InitType("uint32",tt);
         return true;
       case Type::BlockPointer:
       case Type::MemberPointer:
       case Type::Atomic:
       default:
         break;
     }
     std::stringstream ss;
     ss << "type not understood: " << T.getAsString().c_str() << " " << Ty->getTypeClass();
     return ImportError(ss.str().c_str());
 }