v1nh1shungry created this revision. Herald added subscribers: kadircet, arphaman. Herald added a project: All. v1nh1shungry requested review of this revision. Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov. Herald added a project: clang-tools-extra.
Enable the existing code action `ExpandAutoType` to expand `decltype(expr)`, e.g. decltype(0) i; will expand to int i; Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D141226 Files: clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp
Index: clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp +++ clang-tools-extra/clangd/unittests/tweaks/ExpandAutoTypeTests.cpp @@ -50,7 +50,10 @@ StartsWith("fail: Could not deduce type for 'auto' type")); // function pointers should not be replaced EXPECT_THAT(apply("au^to x = &ns::Func;"), - StartsWith("fail: Could not expand type of function pointer")); + StartsWith("fail: Could not expand type of function")); + // function references should not be replaced + EXPECT_THAT(apply("au^to &x = ns::Func;"), + StartsWith("fail: Could not expand type of function")); // lambda types are not replaced EXPECT_UNAVAILABLE("au^to x = []{};"); // inline namespaces @@ -78,6 +81,17 @@ EXPECT_THAT(apply("template <typename T> void x() { ^auto y = T::z(); }"), StartsWith("fail: Could not deduce type for 'auto' type")); + EXPECT_EQ(apply("decl^type(0) i;"), "int i;"); + EXPECT_THAT(apply("void f(); decl^type(f) g;"), + StartsWith("fail: Could not expand type of function")); + EXPECT_EQ(apply("decl^type(0) f();"), "int f();"); + EXPECT_EQ(apply("auto f() -> decl^type(0) { return 0; }"), + "auto f() -> int { return 0; }"); + EXPECT_EQ(apply("template <class = decl^type(0)> class Foo {};"), + "template <class = int> class Foo {};"); + EXPECT_EQ(apply("template <class> class Bar {}; Bar<decl^type(0)> b;"), + "template <class> class Bar {}; Bar<int> b;"); + ExtraArgs.push_back("-std=c++20"); EXPECT_UNAVAILABLE("template <au^to X> class Y;"); @@ -90,6 +104,9 @@ // FIXME: should work on constrained auto params, once SourceRange is fixed. EXPECT_UNAVAILABLE("template<class> concept C = true;" "auto X = [](C ^auto *){return 0;};"); + + EXPECT_UNAVAILABLE("auto f = [](){}; decl^type(f) g;"); + EXPECT_UNAVAILABLE("decl^type([]{}) f;"); } } // namespace Index: clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp =================================================================== --- clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp +++ clang-tools-extra/clangd/refactor/tweaks/ExpandAutoType.cpp @@ -29,7 +29,6 @@ /// After: /// MyClass x = Something(); /// ^^^^^^^ -/// FIXME: Handle decltype as well class ExpandAutoType : public Tweak { public: const char *id() const final; @@ -41,12 +40,15 @@ std::string title() const override; private: - SourceRange AutoRange; + SourceRange Range; + bool IsAutoType; }; REGISTER_TWEAK(ExpandAutoType) -std::string ExpandAutoType::title() const { return "Expand auto type"; } +std::string ExpandAutoType::title() const { + return IsAutoType ? "Expand auto type" : "Expand decltype"; +} // Structured bindings must use auto, e.g. `const auto& [a,b,c] = ...;`. // Return whether N (an AutoTypeLoc) is such an auto that must not be expanded. @@ -93,7 +95,7 @@ if (!isStructuredBindingType(Node) && !isDeducedAsLambda(Node, Result.getBeginLoc()) && !isTemplateParam(Node)) - AutoRange = Result.getSourceRange(); + Range = Result.getSourceRange(); } if (auto TTPAuto = TypeNode->getAs<TemplateTypeParmTypeLoc>()) { // We exclude concept constraints for now, as the SourceRange is wrong. @@ -102,41 +104,43 @@ // TTPAuto->getSourceRange only covers "auto", not "C auto". if (TTPAuto.getDecl()->isImplicit() && !TTPAuto.getDecl()->hasTypeConstraint()) - AutoRange = TTPAuto.getSourceRange(); + Range = TTPAuto.getSourceRange(); + } + IsAutoType = true; + + if (auto DTTL = TypeNode->getAs<DecltypeTypeLoc>()) { + if (!isDeducedAsLambda(Node, DTTL.getBeginLoc())) + Range = DTTL.getSourceRange(); + IsAutoType = false; } } } - return AutoRange.isValid(); + return Range.isValid(); } -Expected<Tweak::Effect> ExpandAutoType::apply(const Selection& Inputs) { +Expected<Tweak::Effect> ExpandAutoType::apply(const Selection &Inputs) { auto &SrcMgr = Inputs.AST->getSourceManager(); std::optional<clang::QualType> DeducedType = - getDeducedType(Inputs.AST->getASTContext(), AutoRange.getBegin()); + getDeducedType(Inputs.AST->getASTContext(), Range.getBegin()); // if we can't resolve the type, return an error message if (DeducedType == std::nullopt || (*DeducedType)->isUndeducedAutoType()) return error("Could not deduce type for 'auto' type"); - // if it's a lambda expression, return an error message - if (isa<RecordType>(*DeducedType) && - cast<RecordType>(*DeducedType)->getDecl()->isLambda()) { - return error("Could not expand type of lambda expression"); - } - // if it's a function expression, return an error message // naively replacing 'auto' with the type will break declarations. // FIXME: there are other types that have similar problems - if (DeducedType->getTypePtr()->isFunctionPointerType()) { - return error("Could not expand type of function pointer"); + if (const Type *T = DeducedType->getTypePtr(); + T->isFunctionType() || T->isFunctionPointerType()) { + return error("Could not expand type of function"); } - std::string PrettyTypeName = printType(*DeducedType, - Inputs.ASTSelection.commonAncestor()->getDeclContext()); + std::string PrettyTypeName = printType( + *DeducedType, Inputs.ASTSelection.commonAncestor()->getDeclContext()); - tooling::Replacement Expansion(SrcMgr, CharSourceRange(AutoRange, true), + tooling::Replacement Expansion(SrcMgr, CharSourceRange(Range, true), PrettyTypeName); return Effect::mainFileEdit(SrcMgr, tooling::Replacements(Expansion));
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits