bool LToGASTVisitor::makeLocalAsGlobalVar(FunctionDecl *FD, VarDecl *LV) { std::string GlobalVarStr; std::string NewName = ConsumerInstance->getNewName(); QualType T = LV->getType(); T.getAsStringInternal(NewName, ConsumerInstance->Context->getPrintingPolicy()); GlobalVarStr = NewName; if (LV->hasInit()) { const Expr *InitExpr = LV->getInit(); std::string InitStr(""); ConsumerInstance->RewriteHelper->getExprString(InitExpr, InitStr); GlobalVarStr += " = "; GlobalVarStr += InitStr; } GlobalVarStr += ";\n"; return ConsumerInstance->RewriteHelper-> insertStringBeforeFunc(FD, GlobalVarStr); }
void CallExprToValue::replaceCallExpr(void) { std::string CommaStr = ""; QualType RVQualType = TheCallExpr->getType(); const Type *RVType = RVQualType.getTypePtr(); if (RVType->isVoidType()) { // Nothing to do } else if (RVType->isUnionType() || RVType->isStructureType()) { std::string RVStr(""); RewriteHelper->getTmpTransName(NamePostfix, RVStr); NamePostfix++; CommaStr = RVStr; RVQualType.getAsStringInternal(RVStr, Context->getPrintingPolicy()); RVStr += ";\n"; RewriteHelper->insertStringBeforeFunc(CurrentFD, RVStr); } else { CommaStr = "0"; } RewriteHelper->replaceExpr(TheCallExpr, CommaStr); }
bool InstantiateTemplateParam::getTypeString( const QualType &QT, std::string &Str, std::string &ForwardStr) { const Type *Ty = QT.getTypePtr(); Type::TypeClass TC = Ty->getTypeClass(); switch (TC) { case Type::Elaborated: { const ElaboratedType *ETy = dyn_cast<ElaboratedType>(Ty); return getTypeString(ETy->getNamedType(), Str, ForwardStr); } case Type::Typedef: { const TypedefType *TdefTy = dyn_cast<TypedefType>(Ty); const TypedefNameDecl *TdefD = TdefTy->getDecl(); return getTypeString(TdefD->getUnderlyingType(), Str, ForwardStr); } case Type::Record: { RecordDeclSet TempAvailableRecordDecls; getForwardDeclStr(Ty, ForwardStr, TempAvailableRecordDecls); QT.getAsStringInternal(Str, Context->getPrintingPolicy()); return true; } case Type::Builtin: { QT.getAsStringInternal(Str, Context->getPrintingPolicy()); return true; } default: return false; } TransAssert(0 && "Unreachable code!"); return false; }
bool BinOpSimplification::addNewTmpVariable(void) { QualType QT = TheBinOp->getType(); std::string VarStr; std::stringstream SS; unsigned int NamePostfix = NameQueryWrap->getMaxNamePostfix(); SS << RewriteHelper->getTmpVarNamePrefix() << (NamePostfix + 1); VarStr = SS.str(); setTmpVarName(VarStr); QT.getAsStringInternal(VarStr, Context->getPrintingPolicy()); VarStr += ";"; return RewriteHelper->addLocalVarToFunc(VarStr, TheFuncDecl); }
void SimplifyCallExpr::replaceCallExpr(void) { std::string CommaStr(""); unsigned int NumArg = TheCallExpr->getNumArgs(); if (NumArg == 0) { RewriteHelper->replaceExpr(TheCallExpr, CommaStr); return; } const Expr *Arg = TheCallExpr->getArg(0); std::string ArgStr; handleOneArgStr(Arg, ArgStr); CommaStr += ("(" + ArgStr); for (unsigned int I = 1; I < NumArg; ++I) { Arg = TheCallExpr->getArg(I); handleOneArgStr(Arg, ArgStr); CommaStr += ("," + ArgStr); } QualType RVQualType = TheCallExpr->getType(); const Type *RVType = RVQualType.getTypePtr(); if (RVType->isVoidType()) { // Nothing to do } else if (RVType->isUnionType() || RVType->isStructureType()) { std::string RVStr(""); RewriteHelper->getTmpTransName(NamePostfix, RVStr); NamePostfix++; CommaStr += ("," + RVStr); RVQualType.getAsStringInternal(RVStr, Context->getPrintingPolicy()); RVStr += ";\n"; RewriteHelper->insertStringBeforeFunc(CurrentFD, RVStr); } else { CommaStr += ",0"; } CommaStr += ")"; RewriteHelper->replaceExpr(TheCallExpr, CommaStr); }
bool AggregateToScalar::addTmpVar(const Expr *RefE, const std::string &VarName, const std::string *InitStr) { std::string VarStr(VarName); QualType QT = RefE->getType(); QT.getAsStringInternal(VarStr, Context->getPrintingPolicy()); if (InitStr) { VarStr += " = "; VarStr += (*InitStr); } VarStr += ";"; if (TheVarDecl->getStorageClass() == SC_Static) VarStr = "static " + VarStr; TransAssert(!dyn_cast<ParmVarDecl>(TheVarDecl) && "We don't handle ParmVarDecl!"); if (TheVarDecl->isLocalVarDecl()) { DeclStmt *TheDeclStmt = VarDeclToDeclStmtMap[TheVarDecl]; TransAssert(TheDeclStmt && "NULL TheDeclStmt"); return RewriteHelper->addStringAfterStmt(TheDeclStmt, VarStr); } else { llvm::DenseMap<const VarDecl *, DeclGroupRef>::iterator DI = VarDeclToDeclGroupMap.find(TheVarDecl); TransAssert((DI != VarDeclToDeclGroupMap.end()) && "Cannot find VarDeclGroup!"); VarDecl *LastVD = NULL; DeclGroupRef DR = (*DI).second; for (DeclGroupRef::iterator I = DR.begin(), E = DR.end(); I != E; ++I) { LastVD = dyn_cast<VarDecl>(*I); } TransAssert(LastVD && "Bad LastVD!"); return RewriteHelper->addStringAfterVarDecl(LastVD, VarStr); } }
ASTNodeInfo EvaluateTSynthesizer::VisitDeclStmt(DeclStmt* Node) { // Visit all the children, which are the contents of the DeclGroupRef for (Stmt::child_iterator I = Node->child_begin(), E = Node->child_end(); I != E; ++I) { if (*I) { Expr* E = cast_or_null<Expr>(*I); if (!E || !IsArtificiallyDependent(E)) continue; //FIXME: don't assume there is only one decl. assert(Node->isSingleDecl() && "There is more that one decl in stmt"); VarDecl* CuredDecl = cast_or_null<VarDecl>(Node->getSingleDecl()); assert(CuredDecl && "Not a variable declaration!"); QualType CuredDeclTy = CuredDecl->getType(); // check if the case is sometype * somevar = init; // or some_builtin_type somevar = init; if (CuredDecl->hasInit() && (CuredDeclTy->isAnyPointerType() || !CuredDeclTy->isRecordType())) { *I = SubstituteUnknownSymbol(CuredDeclTy, CuredDecl->getInit()); continue; } // 1. Check whether this is the case of MyClass A(dep->symbol()) // 2. Insert the RuntimeUniverse's LifetimeHandler instance // 3. Change the A's initializer to *(MyClass*)instance.getMemory() // 4. Make A reference (&A) // 5. Set the new initializer of A if (CuredDeclTy->isLValueReferenceType()) continue; // Set Sema's Current DeclContext to the one we need DeclContext* OldDC = m_Sema->CurContext; m_Sema->CurContext = CuredDecl->getDeclContext(); ASTNodeInfo NewNode; // 2.1 Get unique name for the LifetimeHandler instance and // initialize it std::string UniqueName; createUniqueName(UniqueName); IdentifierInfo& II = m_Context->Idents.get(UniqueName); // Prepare the initialization Exprs. // We want to call LifetimeHandler(DynamicExprInfo* ExprInfo, // DeclContext DC, // const char* type) // Interpreter* interp) llvm::SmallVector<Expr*, 4> Inits; // Add MyClass in LifetimeHandler unique(DynamicExprInfo* ExprInfo // DC, // "MyClass" // Interpreter* Interp) // Build Arg0 DynamicExprInfo Inits.push_back(BuildDynamicExprInfo(E)); // Build Arg1 DeclContext* DC QualType DCTy = m_Context->getTypeDeclType(m_DeclContextDecl); Inits.push_back(utils::Synthesize::CStyleCastPtrExpr(m_Sema, DCTy, (uint64_t)m_CurDeclContext) ); // Build Arg2 llvm::StringRef // Get the type of the type without specifiers PrintingPolicy Policy(m_Context->getLangOpts()); Policy.SuppressTagKeyword = 1; std::string Res; CuredDeclTy.getAsStringInternal(Res, Policy); Inits.push_back(ConstructConstCharPtrExpr(Res.c_str())); // Build Arg3 cling::Interpreter CXXScopeSpec CXXSS; DeclarationNameInfo NameInfo(m_gCling->getDeclName(), m_gCling->getLocStart()); Expr* gClingDRE = m_Sema->BuildDeclarationNameExpr(CXXSS, NameInfo ,m_gCling).take(); Inits.push_back(gClingDRE); // 2.3 Create a variable from LifetimeHandler. QualType HandlerTy = m_Context->getTypeDeclType(m_LifetimeHandlerDecl); TypeSourceInfo* TSI = m_Context->getTrivialTypeSourceInfo(HandlerTy, m_NoSLoc); VarDecl* HandlerInstance = VarDecl::Create(*m_Context, CuredDecl->getDeclContext(), m_NoSLoc, m_NoSLoc, &II, HandlerTy, TSI, SC_None); // 2.4 Call the best-match constructor. The method does overload // resolution of the constructors and then initializes the new // variable with it ExprResult InitExprResult = m_Sema->ActOnParenListExpr(m_NoSLoc, m_NoELoc, Inits); m_Sema->AddInitializerToDecl(HandlerInstance, InitExprResult.take(), /*DirectInit*/ true, /*TypeMayContainAuto*/ false); // 2.5 Register the instance in the enclosing context CuredDecl->getDeclContext()->addDecl(HandlerInstance); NewNode.addNode(new (m_Context) DeclStmt(DeclGroupRef(HandlerInstance), m_NoSLoc, m_NoELoc) ); // 3.1 Build a DeclRefExpr, which holds the object DeclRefExpr* MemberExprBase = m_Sema->BuildDeclRefExpr(HandlerInstance, HandlerTy, VK_LValue, m_NoSLoc ).takeAs<DeclRefExpr>(); // 3.2 Create a MemberExpr to getMemory from its declaration. CXXScopeSpec SS; LookupResult MemberLookup(*m_Sema, m_LHgetMemoryDecl->getDeclName(), m_NoSLoc, Sema::LookupMemberName); // Add the declaration as if doesn't exist. // TODO: Check whether this is the most appropriate variant MemberLookup.addDecl(m_LHgetMemoryDecl, AS_public); MemberLookup.resolveKind(); Expr* MemberExpr = m_Sema->BuildMemberReferenceExpr(MemberExprBase, HandlerTy, m_NoSLoc, /*IsArrow=*/false, SS, m_NoSLoc, /*FirstQualifierInScope=*/0, MemberLookup, /*TemplateArgs=*/0 ).take(); // 3.3 Build the actual call Scope* S = m_Sema->getScopeForContext(m_Sema->CurContext); Expr* theCall = m_Sema->ActOnCallExpr(S, MemberExpr, m_NoSLoc, MultiExprArg(), m_NoELoc).take(); // Cast to the type LHS type Expr* Result = utils::Synthesize::CStyleCastPtrExpr(m_Sema, CuredDeclTy, theCall); // Cast once more (dereference the cstyle cast) Result = m_Sema->BuildUnaryOp(S, m_NoSLoc, UO_Deref, Result).take(); // 4. CuredDecl->setType(m_Context->getLValueReferenceType(CuredDeclTy)); // 5. CuredDecl->setInit(Result); NewNode.addNode(Node); // Restore Sema's original DeclContext m_Sema->CurContext = OldDC; return NewNode; } } return ASTNodeInfo(Node, 0); }
void RemoveNestedFunction::getNewTmpVariableStr(ASTContext &ASTCtx, std::string &VarStr) { std::stringstream SS; unsigned int NamePostfix = NameQueryWrap->getMaxNamePostfix(); SS << RewriteHelper->getTmpVarNamePrefix() << (NamePostfix + 1); VarStr = SS.str(); setTmpVarName(VarStr); QualType QT; const Expr *E = TheCallExpr->getCallee(); if (const UnresolvedLookupExpr *UE = dyn_cast<UnresolvedLookupExpr>(E)) { // clang doesn't always resolve CallExpr's callee. For example: // template<typename T> int foo1(int p) {return p;} // template<typename T> int foo2(int p) {return p;} // template<typename T> // void bar(void) { foo1<T>(foo2<T>(1)); } // foo2<T>(1) has BuiltinType and hence // TheCallExpr->getCallReturnType() will segfault. // In this case, we have to lookup a corresponding function decl DeclarationName DName = UE->getName(); TransAssert(((DName.getNameKind() == DeclarationName::Identifier) || (DName.getNameKind() == DeclarationName::CXXOperatorName)) && "Not an indentifier!"); const FunctionDecl *FD = NULL; if (const NestedNameSpecifier *NNS = UE->getQualifier()) { if (const DeclContext *Ctx = getDeclContextFromSpecifier(NNS)) { DeclContextSet VisitedCtxs; FD = lookupFunctionDecl(DName, Ctx, VisitedCtxs); } } if (!FD) { DeclContextSet VisitedCtxs; FD = lookupFunctionDecl(DName, TheFuncDecl->getLookupParent(), VisitedCtxs); } // give up and generate a tmp var of int type, e.g.: // template <class T> struct S { // T x; // template <class A> void foo(A &a0) { x(y(a0)); } // }; if (!FD) return getNewIntTmpVariable(VarStr); QT = FD->getReturnType(); //FIXME: This is actually not quite correct, we should get the instantiated // type here. return getNewTmpVariable(QT, VarStr); } if (const UnresolvedMemberExpr *UM = dyn_cast<UnresolvedMemberExpr>(E)) { DeclarationName DName = UM->getMemberName(); CXXRecordDecl *CXXRD = UM->getNamingClass(); DeclContextSet VisitedCtxs; const FunctionDecl *FD = lookupFunctionDecl(DName, CXXRD, VisitedCtxs); // FIXME: try to resolve FD here if (FD) QT = FD->getReturnType(); return getNewTmpVariable(QT, VarStr); } if (const CXXTemporaryObjectExpr *CXXTE = dyn_cast<CXXTemporaryObjectExpr>(E)) { const CXXConstructorDecl *CXXCtor = CXXTE->getConstructor(); QT = CXXCtor->getThisType(ASTCtx); return getNewTmpVariable(QT, VarStr); } if (const CXXTemporaryObjectExpr *CXXTE = dyn_cast<CXXTemporaryObjectExpr>(E)) { const CXXConstructorDecl *CXXCtor = CXXTE->getConstructor(); QT = CXXCtor->getThisType(ASTCtx); return getNewTmpVariable(QT, VarStr); } if (const CXXDependentScopeMemberExpr *ME = dyn_cast<CXXDependentScopeMemberExpr>(E)) { if (ME->isImplicitAccess()) return; DeclarationName DName = ME->getMember(); TransAssert((DName.getNameKind() == DeclarationName::Identifier) && "Not an indentifier!"); const Expr *E = ME->getBase(); TransAssert(E && "NULL Base Expr!"); const Expr *BaseE = E->IgnoreParens(); // handle cases where base expr or member name is dependent, e.g., // template<typename T> // class S { // int f1(int p1) { return p1; }; // int f2(int p2) { return p2; }; // void f3(void); // }; // template<typename T> // void S<T>::f3(void) // { // f1(this->f2(1)); // } // where this->f2(1) is a CXXDependentScopeMemberExpr if (dyn_cast<CXXThisExpr>(BaseE)) { const DeclContext *Ctx = TheFuncDecl->getLookupParent(); TransAssert(Ctx && "Bad DeclContext!"); DeclContextSet VisitedCtxs; const FunctionDecl *FD = lookupFunctionDecl(DName, Ctx, VisitedCtxs); TransAssert(FD && "Cannot resolve DName!"); QT = FD->getReturnType(); return getNewTmpVariable(QT, VarStr); } // handle other cases where lookupDeclContext is different from // the current CXXRecord, e.g., const Type *Ty = ME->getBaseType().getTypePtr(); if (const DeclContext *Ctx = getBaseDeclFromType(Ty)) { DeclContextSet VisitedCtxs; const FunctionDecl *FD = lookupFunctionDecl(DName, Ctx, VisitedCtxs); if (!FD) { return getNewTmpVariable(QT, VarStr); } QT = FD->getReturnType(); const Type *RVTy = QT.getTypePtr(); if (RVTy->getAs<InjectedClassNameType>()) { // handle cases like: // template <typename> struct D { // D f(); // }; // template <typename T> void foo(D<T>); // template <typename T > void bar () { // D<T> G; // foo(G.f()); // } // in this case, seems it's hard to retrieve the instantiated type // of f's return type, because `D<T> G' is dependent. I tried // findSpecialization from ClassTemplateDecl, but it didn't work. // So use a really ugly way, i.e., manipulating strings... const TemplateSpecializationType *TST = Ty->getAs<TemplateSpecializationType>(); TransAssert(TST && "Invalid TemplateSpecialization Type!"); QT.getAsStringInternal(VarStr, Context->getPrintingPolicy()); return getVarStrForTemplateSpecialization(VarStr, TST); } else { // other cases: // template <typename> struct D { // int f(); // }; // void foo(int); // template <typename T > void bar () { // D<T> G; // foo(G.f()); // } return getNewTmpVariable(QT, VarStr); } } else { // template <typename> struct D { // D f(); // D operator[] (int); // }; // template <typename T> void foo(D<T>); // template <typename T > void bar () { // D<T> G; // foo(G[0].f()); // } // In this case, G[0] is of BuiltinType. // But why does clang represent a dependent type as BuiltinType here? TransAssert((Ty->getAs<BuiltinType>() || Ty->getAs<TemplateTypeParmType>() || Ty->getAs<TypedefType>() || Ty->getAs<DependentNameType>()) && "Uncaught Type"); // FIXME: This is incorrect! // a couple of questions // - how can we find a correct DeclContext where we could lookup f? // - can we obtain the dependent template argument from BuiltinType? // Probably we cannot do these? Comments from lib/AST/ASTContext.cpp: // // Placeholder type for type-dependent expressions whose type is // completely unknown. No code should ever check a type against // DependentTy and users should never see it; however, it is here to // help diagnose failures to properly check for type-dependent // expressions. return getNewIntTmpVariable(VarStr); } } const Type *CalleeType = E->getType().getTypePtr(); // template <class T1, class T2> struct S { // T1 x; T2 y; // template <class A> void foo(A &a0) { x(y(a0)); } // }; if (const TemplateTypeParmType *PT = dyn_cast<TemplateTypeParmType>(CalleeType)) { const TemplateTypeParmDecl *PD = PT->getDecl(); std::string DStr = PD->getNameAsString(); VarStr = DStr + " " + VarStr; return; } QT = TheCallExpr->getCallReturnType(ASTCtx); getNewTmpVariable( QT.getTypePtr()->getUnqualifiedDesugaredType()->getCanonicalTypeInternal(), VarStr); }
void RemoveNestedFunction::getNewTmpVariable(const QualType &QT, std::string &VarStr) { QT.getAsStringInternal(VarStr, Context->getPrintingPolicy()); }