clang-tools 10.0.0

ExpandAutoType.cpp
Go to the documentation of this file.
1 //===--- ExpandAutoType.cpp --------------------------------------*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 #include "refactor/Tweak.h"
9
10 #include "Logger.h"
11 #include "clang/AST/Type.h"
12 #include "clang/AST/TypeLoc.h"
13 #include "clang/Basic/LLVM.h"
14 #include "llvm/ADT/None.h"
15 #include "llvm/ADT/Optional.h"
16 #include "llvm/Support/Debug.h"
17 #include "llvm/Support/Error.h"
18 #include <climits>
19 #include <memory>
20 #include <string>
21 #include <AST.h>
22 #include "XRefs.h"
23 #include "llvm/ADT/StringExtras.h"
24
25 namespace clang {
26 namespace clangd {
27 namespace {
28
29 /// Expand the "auto" type to the derived type
30 /// Before:
31 /// auto x = Something();
32 /// ^^^^
33 /// After:
34 /// MyClass x = Something();
35 /// ^^^^^^^
36 /// FIXME: Handle decltype as well
37 class ExpandAutoType : public Tweak {
38 public:
39 const char *id() const final;
40 Intent intent() const override { return Intent::Refactor;}
41 bool prepare(const Selection &Inputs) override;
42 Expected<Effect> apply(const Selection &Inputs) override;
43 std::string title() const override;
44
45 private:
46 /// Cache the AutoTypeLoc, so that we do not need to search twice.
47 llvm::Optional<clang::AutoTypeLoc> CachedLocation;
48
49 /// Create an error message with filename and line number in it
50 llvm::Error createErrorMessage(const std::string& Message,
51 const Selection &Inputs);
52
53 };
54
55 REGISTER_TWEAK(ExpandAutoType)
56
57 std::string ExpandAutoType::title() const { return "Expand auto type"; }
58
59 bool ExpandAutoType::prepare(const Selection& Inputs) {
60 CachedLocation = llvm::None;
61 if (auto *Node = Inputs.ASTSelection.commonAncestor()) {
62 if (auto *TypeNode = Node->ASTNode.get<TypeLoc>()) {
63 if (const AutoTypeLoc Result = TypeNode->getAs<AutoTypeLoc>()) {
64 // Code in apply() does handle 'decltype(auto)' yet.
65 if (!Result.getTypePtr()->isDecltypeAuto())
66 CachedLocation = Result;
67 }
68 }
69 }
70 return (bool) CachedLocation;
71 }
72
73 Expected<Tweak::Effect> ExpandAutoType::apply(const Selection& Inputs) {
74 auto &SrcMgr = Inputs.AST->getSourceManager();
75
76 llvm::Optional<clang::QualType> DeducedType = getDeducedType(
77 Inputs.AST->getASTContext(), CachedLocation->getBeginLoc());
78
79 // if we can't resolve the type, return an error message
80 if (DeducedType == llvm::None)
81 return createErrorMessage("Could not deduce type for 'auto' type", Inputs);
82
83 // if it's a lambda expression, return an error message
84 if (isa<RecordType>(*DeducedType) &&
85 dyn_cast<RecordType>(*DeducedType)->getDecl()->isLambda()) {
86 return createErrorMessage("Could not expand type of lambda expression",
87 Inputs);
88 }
89
90 // if it's a function expression, return an error message
91 // naively replacing 'auto' with the type will break declarations.
92 // FIXME: there are other types that have similar problems
93 if (DeducedType->getTypePtr()->isFunctionPointerType()) {
94 return createErrorMessage("Could not expand type of function pointer",
95 Inputs);
96 }
97
98 std::string PrettyTypeName = printType(*DeducedType,
99 Inputs.ASTSelection.commonAncestor()->getDeclContext());
100
101 tooling::Replacement
102 Expansion(SrcMgr, CharSourceRange(CachedLocation->getSourceRange(), true),
103 PrettyTypeName);
104
105 return Effect::mainFileEdit(SrcMgr, tooling::Replacements(Expansion));
106 }
107
108 llvm::Error ExpandAutoType::createErrorMessage(const std::string& Message,
109 const Selection& Inputs) {
110 auto &SrcMgr = Inputs.AST->getSourceManager();
111 std::string ErrorMessage =
112 Message + ": " +
113 SrcMgr.getFilename(Inputs.Cursor).str() + " Line " +
114 std::to_string(SrcMgr.getExpansionLineNumber(Inputs.Cursor));
115
116 return llvm::createStringError(llvm::inconvertibleErrorCode(),
117 ErrorMessage.c_str());
118 }
119
120 } // namespace
121 } // namespace clangd
122 } // namespace clang
DeducedType
QualType DeducedType
Definition: AST.cpp:414
AST.h
clang::clangd::getDeducedType
llvm::Optional< QualType > getDeducedType(ASTContext &ASTCtx, SourceLocation Loc)
Retrieves the deduced type at a given location (auto, decltype).
Definition: AST.cpp:418
clang::clangd::MessageType::Error
An error message.
clang::tidy::modernize::Message
constexpr llvm::StringLiteral Message
Definition: UseTrailingReturnTypeCheck.cpp:101
REGISTER_TWEAK
#define REGISTER_TWEAK(Subclass)
Definition: Tweak.h:129
clang::clangd::TextDocumentSyncKind::None
Documents should not be synced at all.
clang::clangd::printType
std::string printType(const QualType QT, const DeclContext &CurContext)
Returns a QualType as string.
Definition: AST.cpp:305
Tweak.h
Logger.h
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
XRefs.h