1 //===--- AST.h - Utility AST functions -------------------------*- 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 // 9 // Various code that examines C++ source code using AST. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_AST_H 14 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_AST_H 15 16 #include "Headers.h" 17 #include "index/Symbol.h" 18 #include "index/SymbolID.h" 19 #include "clang/AST/Decl.h" 20 #include "clang/AST/DeclObjC.h" 21 #include "clang/AST/NestedNameSpecifier.h" 22 #include "clang/AST/TypeLoc.h" 23 #include "clang/Basic/SourceLocation.h" 24 #include "clang/Lex/MacroInfo.h" 25 #include "llvm/ADT/StringRef.h" 26 #include <optional> 27 #include <string> 28 #include <vector> 29 30 namespace clang { 31 class SourceManager; 32 class Decl; 33 class DynTypedNode; 34 35 namespace clangd { 36 37 /// Returns true if the declaration is considered implementation detail based on 38 /// heuristics. For example, a declaration whose name is not explicitly spelled 39 /// in code is considered implementation detail. 40 bool isImplementationDetail(const Decl *D); 41 42 /// Find the source location of the identifier for \p D. 43 /// Transforms macro locations to locations spelled inside files. All code 44 /// that needs locations of declaration names (e.g. the index) should go through 45 /// this function. 46 SourceLocation nameLocation(const clang::Decl &D, const SourceManager &SM); 47 48 /// Returns the qualified name of ND. The scope doesn't contain unwritten scopes 49 /// like inline namespaces. 50 std::string printQualifiedName(const NamedDecl &ND); 51 52 /// Returns the first enclosing namespace scope starting from \p DC. 53 std::string printNamespaceScope(const DeclContext &DC); 54 55 /// Returns the name of the namespace inside the 'using namespace' directive, as 56 /// written in the code. E.g., passing 'using namespace ::std' will result in 57 /// '::std'. 58 std::string printUsingNamespaceName(const ASTContext &Ctx, 59 const UsingDirectiveDecl &D); 60 61 /// Prints unqualified name of the decl for the purpose of displaying it to the 62 /// user. Anonymous decls return names of the form "(anonymous {kind})", e.g. 63 /// "(anonymous struct)" or "(anonymous namespace)". 64 std::string printName(const ASTContext &Ctx, const NamedDecl &ND); 65 66 /// Prints template arguments of a decl as written in the source code, including 67 /// enclosing '<' and '>', e.g for a partial specialization like: template 68 /// <typename U> struct Foo<int, U> will return '<int, U>'. Returns an empty 69 /// string if decl is not a template specialization. 70 std::string printTemplateSpecializationArgs(const NamedDecl &ND); 71 72 /// Print the Objective-C method name, including the full container name, e.g. 73 /// `-[MyClass(Category) method:]` 74 std::string printObjCMethod(const ObjCMethodDecl &Method); 75 76 /// Print the Objective-C container name including categories, e.g. `MyClass`, 77 // `MyClass()`, `MyClass(Category)`, and `MyProtocol`. 78 std::string printObjCContainer(const ObjCContainerDecl &C); 79 80 /// Returns true if this is a NamedDecl with a reserved name. 81 bool hasReservedName(const Decl &); 82 /// Returns true if this scope would be written with a reserved name. 83 /// This does not include unwritten scope elements like __1 in std::__1::vector. 84 bool hasReservedScope(const DeclContext &); 85 86 /// Gets the symbol ID for a declaration. Returned SymbolID might be null. 87 SymbolID getSymbolID(const Decl *D); 88 89 /// Gets the symbol ID for a macro. Returned SymbolID might be null. 90 /// Currently, this is an encoded USR of the macro, which incorporates macro 91 /// locations (e.g. file name, offset in file). 92 /// FIXME: the USR semantics might not be stable enough as the ID for index 93 /// macro (e.g. a change in definition offset can result in a different USR). We 94 /// could change these semantics in the future by reimplementing this funcure 95 /// (e.g. avoid USR for macros). 96 SymbolID getSymbolID(const llvm::StringRef MacroName, const MacroInfo *MI, 97 const SourceManager &SM); 98 99 /// Return the corresponding implementation/definition for the given ObjC 100 /// container if it has one, otherwise, return nullptr. 101 /// 102 /// Objective-C classes can have three types of declarations: 103 /// 104 /// - forward declaration: "@class MyClass;" 105 /// - true declaration (interface definition): "@interface MyClass ... @end" 106 /// - true definition (implementation): "@implementation MyClass ... @end" 107 /// 108 /// Objective-C categories are extensions on classes: 109 /// 110 /// - declaration: "@interface MyClass (Ext) ... @end" 111 /// - definition: "@implementation MyClass (Ext) ... @end" 112 /// 113 /// With one special case, a class extension, which is normally used to keep 114 /// some declarations internal to a file without exposing them in a header. 115 /// 116 /// - class extension declaration: "@interface MyClass () ... @end" 117 /// - which really links to class definition: "@implementation MyClass ... @end" 118 /// 119 /// For Objective-C protocols, e.g. "@protocol MyProtocol ... @end" this will 120 /// return nullptr as protocols don't have an implementation. 121 const ObjCImplDecl *getCorrespondingObjCImpl(const ObjCContainerDecl *D); 122 123 /// Infer the include directive to use for the given \p FileName. It aims for 124 /// #import for ObjC files and #include for the rest. 125 /// 126 /// - For source files we use LangOpts directly to infer ObjC-ness. 127 /// - For header files we also check for symbols declared by the file and 128 /// existing include directives, as the language can be set to ObjC++ as a 129 /// fallback in the absence of compile flags. 130 Symbol::IncludeDirective 131 preferredIncludeDirective(llvm::StringRef FileName, const LangOptions &LangOpts, 132 ArrayRef<Inclusion> MainFileIncludes, 133 ArrayRef<const Decl *> TopLevelDecls); 134 135 /// Returns a QualType as string. The result doesn't contain unwritten scopes 136 /// like anonymous/inline namespace. 137 std::string printType(const QualType QT, const DeclContext &CurContext, 138 llvm::StringRef Placeholder = ""); 139 140 /// Indicates if \p D is a template instantiation implicitly generated by the 141 /// compiler, e.g. 142 /// template <class T> struct vector {}; 143 /// vector<int> v; // 'vector<int>' is an implicit instantiation 144 bool isImplicitTemplateInstantiation(const NamedDecl *D); 145 /// Indicates if \p D is an explicit template specialization, e.g. 146 /// template <class T> struct vector {}; 147 /// template <> struct vector<bool> {}; // <-- explicit specialization 148 /// 149 /// Note that explicit instantiations are NOT explicit specializations, albeit 150 /// they look similar. 151 /// template struct vector<bool>; // <-- explicit instantiation, NOT an 152 /// explicit specialization. 153 bool isExplicitTemplateSpecialization(const NamedDecl *D); 154 155 /// Returns a nested name specifier loc of \p ND if it was present in the 156 /// source, e.g. 157 /// void ns::something::foo() -> returns 'ns::something' 158 /// void foo() -> returns null 159 NestedNameSpecifierLoc getQualifierLoc(const NamedDecl &ND); 160 161 // Returns a type corresponding to a declaration of that type. 162 // Unlike the method on ASTContext, attempts to preserve the type as-written 163 // (i.e. vector<T*> rather than vector<type-parameter-0-0 *>. 164 QualType declaredType(const TypeDecl *D); 165 166 /// Retrieves the deduced type at a given location (auto, decltype). 167 /// It will return the underlying type. 168 /// If the type is an undeduced auto, returns the type itself. 169 std::optional<QualType> getDeducedType(ASTContext &, SourceLocation Loc); 170 171 // Find the abbreviated-function-template `auto` within a type, or returns null. 172 // Similar to getContainedAutoTypeLoc, but these `auto`s are 173 // TemplateTypeParmTypes for implicit TTPs, instead of AutoTypes. 174 // Also we don't look very hard, just stripping const, references, pointers. 175 // FIXME: handle more type patterns. 176 TemplateTypeParmTypeLoc getContainedAutoParamType(TypeLoc TL); 177 178 // If TemplatedDecl is the generic body of a template, and the template has 179 // exactly one visible instantiation, return the instantiated body. 180 NamedDecl *getOnlyInstantiation(NamedDecl *TemplatedDecl); 181 182 /// Return attributes attached directly to a node. 183 std::vector<const Attr *> getAttributes(const DynTypedNode &); 184 185 /// Gets the nested name specifier necessary for spelling \p ND in \p 186 /// DestContext, at \p InsertionPoint. It selects the shortest suffix of \p ND 187 /// such that it is visible in \p DestContext. 188 /// Returns an empty string if no qualification is necessary. For example, if 189 /// you want to qualify clang::clangd::bar::foo in clang::clangd::x, this 190 /// function will return bar. Note that the result might be sub-optimal for 191 /// classes, e.g. when the \p ND is a member of the base class. 192 /// 193 /// This version considers all the using namespace directives before \p 194 /// InsertionPoint. i.e, if you have `using namespace 195 /// clang::clangd::bar`, this function will return an empty string for the 196 /// example above since no qualification is necessary in that case. 197 /// FIXME: Also take using directives and namespace aliases inside function body 198 /// into account. 199 std::string getQualification(ASTContext &Context, 200 const DeclContext *DestContext, 201 SourceLocation InsertionPoint, 202 const NamedDecl *ND); 203 204 /// This function uses the \p VisibleNamespaces to figure out if a shorter 205 /// qualification is sufficient for \p ND, and ignores any using namespace 206 /// directives. It can be useful if there's no AST for the DestContext, but some 207 /// pseudo-parsing is done. i.e. if \p ND is ns1::ns2::X and \p DestContext is 208 /// ns1::, users can provide `ns2::` as visible to change the result to be 209 /// empty. 210 /// Elements in VisibleNamespaces should be in the form: `ns::`, with trailing 211 /// "::". 212 /// Note that this is just textual and might be incorrect. e.g. when there are 213 /// two namespaces ns1::a and ns2::a, the function will early exit if "a::" is 214 /// present in \p VisibleNamespaces, no matter whether it is from ns1:: or ns2:: 215 std::string getQualification(ASTContext &Context, 216 const DeclContext *DestContext, 217 const NamedDecl *ND, 218 llvm::ArrayRef<std::string> VisibleNamespaces); 219 220 /// Whether we must avoid computing linkage for D during code completion. 221 /// Clang aggressively caches linkage computation, which is stable after the AST 222 /// is built. Unfortunately the AST is incomplete during code completion, so 223 /// linkage may still change. 224 /// 225 /// Example: `auto x = []{^}` at file scope. 226 /// During code completion, the initializer for x hasn't been parsed yet. 227 /// x has type `undeduced auto`, and external linkage. 228 /// If we compute linkage at this point, the external linkage will be cached. 229 /// 230 /// After code completion the initializer is attached, and x has a lambda type. 231 /// This means x has "unique external" linkage. If we computed linkage above, 232 /// the cached value is incorrect. (clang catches this with an assertion). 233 bool hasUnstableLinkage(const Decl *D); 234 235 /// Checks whether \p D is more than \p MaxDepth away from translation unit 236 /// scope. 237 /// This is useful for limiting traversals to keep operation latencies 238 /// reasonable. 239 bool isDeeplyNested(const Decl *D, unsigned MaxDepth = 10); 240 241 /// Recursively resolves the parameters of a FunctionDecl that forwards its 242 /// parameters to another function via variadic template parameters. This can 243 /// for example be used to retrieve the constructor parameter ParmVarDecl for a 244 /// make_unique or emplace_back call. 245 llvm::SmallVector<const ParmVarDecl *> 246 resolveForwardingParameters(const FunctionDecl *D, unsigned MaxDepth = 10); 247 248 /// Checks whether D is instantiated from a function parameter pack 249 /// whose type is a bare type parameter pack (e.g. `Args...`), or a 250 /// reference to one (e.g. `Args&...` or `Args&&...`). 251 bool isExpandedFromParameterPack(const ParmVarDecl *D); 252 253 } // namespace clangd 254 } // namespace clang 255 256 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_AST_H 257