================ @@ -168,16 +168,95 @@ bool Sema::IsStringInit(Expr *Init, const ArrayType *AT) { return ::IsStringInit(Init, AT, Context) == SIF_None; } +static StringLiteral *CloneStringLiteral(const StringLiteral *SL, + ASTContext &C) { + SourceLocation *SLocs = new (C) SourceLocation[SL->getNumConcatenated()]; + std::copy(SL->tokloc_begin(), SL->tokloc_end(), SLocs); + return StringLiteral::Create( + C, SL->getBytes(), SL->getKind(), SL->isPascal(), SL->getType(), + ArrayRef<SourceLocation>(SLocs, SL->getNumConcatenated())); +} + +// Exactly follow `IgnoreParensSingleStep` (`AST/IgnoreExpr.h`) +// We only clone those subexpressions which `IgnoreParensSingleStep` drills down +// to. +static Expr *CloneDrilled(Expr *E, ASTContext &C) { + if (auto *SL = dyn_cast<StringLiteral>(E)) { + return CloneStringLiteral(SL, C); + } + + if (auto *PE = dyn_cast<ParenExpr>(E)) { + return new (C) ParenExpr(PE->getBeginLoc(), PE->getEndLoc(), + CloneDrilled(PE->getSubExpr(), C)); + } + + if (auto *UO = dyn_cast<UnaryOperator>(E)) { + if (UO->getOpcode() == UO_Extension) { + return UnaryOperator::Create( + C, CloneDrilled(UO->getSubExpr(), C), UO_Extension, UO->getType(), + UO->getValueKind(), UO->getObjectKind(), UO->getBeginLoc(), + UO->canOverflow(), UO->getFPOptionsOverride()); + } + } + + else if (auto *GSE = dyn_cast<GenericSelectionExpr>(E)) { + if (!GSE->isResultDependent()) { + ArrayRef<Expr *> GSEAEs = GSE->getAssocExprs(); + Expr **NewGSEAEs = new (C) Expr *[GSEAEs.size()]; + std::copy(GSEAEs.begin(), GSEAEs.end(), NewGSEAEs); + NewGSEAEs[GSE->getResultIndex()] = CloneDrilled(GSE->getResultExpr(), C); + +#define CREATE_GSE(ctrl) \ + GenericSelectionExpr::Create( \ + C, GSE->getGenericLoc(), ctrl, GSE->getAssocTypeSourceInfos(), \ + ArrayRef<Expr *>(NewGSEAEs, GSEAEs.size()), GSE->getDefaultLoc(), \ + GSE->getRParenLoc(), GSE->containsUnexpandedParameterPack(), \ + GSE->getResultIndex()) + + return GSE->isExprPredicate() ? CREATE_GSE(GSE->getControllingExpr()) + : CREATE_GSE(GSE->getControllingType()); +#undef CREATE_GSE + } + } + + else if (auto *CE = dyn_cast<ChooseExpr>(E)) { + if (!CE->isConditionDependent()) { + // Drills to `CE->getChosenSubExpr()` + const bool isCondTrue = CE->isConditionTrue(); + return new (C) + ChooseExpr(CE->getBeginLoc(), CE->getCond(), + isCondTrue ? CloneDrilled(CE->getLHS(), C) : CE->getLHS(), + isCondTrue ? CE->getRHS() : CloneDrilled(CE->getRHS(), C), + CE->getType(), CE->getValueKind(), CE->getObjectKind(), + CE->getRParenLoc(), CE->isConditionTrue()); + } + } + + else if (auto *PE = dyn_cast<PredefinedExpr>(E)) { + if (PE->isTransparent() && PE->getFunctionName()) { + return PredefinedExpr::Create( + C, PE->getLocation(), PE->getType(), PE->getIdentKind(), + PE->isTransparent(), CloneStringLiteral(PE->getFunctionName(), C)); + } + } + + return E; +} + /// Update the type of a string literal, including any surrounding parentheses, /// to match the type of the object which it is initializing. -static void updateStringLiteralType(Expr *E, QualType Ty) { +static Expr *updateStringLiteralType(Expr *E, QualType Ty, Sema &S) { + Expr *ENew = CloneDrilled(E, S.Context); + E = ENew; + while (true) { E->setType(Ty); E->setValueKind(VK_PRValue); if (isa<StringLiteral>(E) || isa<ObjCEncodeExpr>(E)) break; E = IgnoreParensSingleStep(E); } + return ENew; ---------------- awson wrote:
Nope. We need to keep `ENew` for return. `E` drills down to innermost string literal. https://github.com/llvm/llvm-project/pull/156846 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits