aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/ExtractAPI/DeclarationFragments.cpp
diff options
context:
space:
mode:
authorErick Velez <erickvelez7@gmail.com>2023-06-01 10:22:19 -0700
committerErick Velez <erickvelez7@gmail.com>2023-08-02 10:19:05 -0700
commit8b76b44e46ac5b4efbf8cb3702f09d353af2a112 (patch)
tree8b98f65fb35d222a4db0f6d32925ca5038b8ceda /clang/lib/ExtractAPI/DeclarationFragments.cpp
parentb711d11c83aeed3b7266ea09532f64229e81bfd6 (diff)
downloadllvm-8b76b44e46ac5b4efbf8cb3702f09d353af2a112.zip
llvm-8b76b44e46ac5b4efbf8cb3702f09d353af2a112.tar.gz
llvm-8b76b44e46ac5b4efbf8cb3702f09d353af2a112.tar.bz2
[clang][ExtractAPI] Add support for C++ classes
Add ExtractAPI support C++ classes, fields, methods, and various qualifiers and specifiers Differential Revision: https://reviews.llvm.org/D153557
Diffstat (limited to 'clang/lib/ExtractAPI/DeclarationFragments.cpp')
-rw-r--r--clang/lib/ExtractAPI/DeclarationFragments.cpp257
1 files changed, 236 insertions, 21 deletions
diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp
index 2033576..ea72835 100644
--- a/clang/lib/ExtractAPI/DeclarationFragments.cpp
+++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp
@@ -12,8 +12,12 @@
//===----------------------------------------------------------------------===//
#include "clang/ExtractAPI/DeclarationFragments.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/Basic/OperatorKinds.h"
#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
#include "clang/Index/USRGeneration.h"
+#include "clang/Parse/Parser.h"
#include "llvm/ADT/StringSwitch.h"
using namespace clang::extractapi;
@@ -84,6 +88,59 @@ DeclarationFragments::parseFragmentKindFromString(StringRef S) {
.Default(DeclarationFragments::FragmentKind::None);
}
+DeclarationFragments DeclarationFragments::getExceptionSpecificationString(
+ ExceptionSpecificationType ExceptionSpec) {
+ DeclarationFragments Fragments;
+ switch (ExceptionSpec) {
+ case ExceptionSpecificationType::EST_None:
+ return Fragments;
+ case ExceptionSpecificationType::EST_DynamicNone:
+ return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
+ .append("throw", DeclarationFragments::FragmentKind::Keyword)
+ .append("(", DeclarationFragments::FragmentKind::Text)
+ .append(")", DeclarationFragments::FragmentKind::Text);
+ case ExceptionSpecificationType::EST_Dynamic:
+ // FIXME: throw(int), get types of inner expression
+ return Fragments;
+ case ExceptionSpecificationType::EST_BasicNoexcept:
+
+ return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
+ .append("noexcept", DeclarationFragments::FragmentKind::Keyword);
+ case ExceptionSpecificationType::EST_DependentNoexcept:
+ // FIXME: throw(conditional-expression), get expression
+ break;
+ case ExceptionSpecificationType::EST_NoexceptFalse:
+ return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
+ .append("noexcept", DeclarationFragments::FragmentKind::Keyword)
+ .append("(", DeclarationFragments::FragmentKind::Text)
+ .append("false", DeclarationFragments::FragmentKind::Keyword)
+ .append(")", DeclarationFragments::FragmentKind::Text);
+ case ExceptionSpecificationType::EST_NoexceptTrue:
+ return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
+ .append("noexcept", DeclarationFragments::FragmentKind::Keyword)
+ .append("(", DeclarationFragments::FragmentKind::Text)
+ .append("true", DeclarationFragments::FragmentKind::Keyword)
+ .append(")", DeclarationFragments::FragmentKind::Text);
+ default:
+ return Fragments;
+ }
+
+ llvm_unreachable("Unhandled exception specification");
+}
+
+DeclarationFragments
+DeclarationFragments::getStructureTypeFragment(const RecordDecl *Record) {
+ DeclarationFragments Fragments;
+ if (Record->isStruct())
+ Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);
+ else if (Record->isUnion())
+ Fragments.append("union", DeclarationFragments::FragmentKind::Keyword);
+ else
+ Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);
+
+ return Fragments;
+}
+
// NNS stores C++ nested name specifiers, which are prefixes to qualified names.
// Build declaration fragments for NNS recursively so that we have the USR for
// every part in a qualified name, and also leaves the actual underlying type
@@ -369,6 +426,9 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {
DeclarationFragments Fragments;
+ if (Var->isConstexpr())
+ Fragments.append("constexpr ", DeclarationFragments::FragmentKind::Keyword);
+
StorageClass SC = Var->getStorageClass();
if (SC != SC_None)
Fragments
@@ -438,7 +498,10 @@ DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
case SC_Register:
llvm_unreachable("invalid for functions");
}
- // FIXME: Handle C++ function specifiers: constexpr, consteval, explicit, etc.
+ if (Func->isConsteval()) // if consteval, it is also constexpr
+ Fragments.append("consteval ", DeclarationFragments::FragmentKind::Keyword);
+ else if (Func->isConstexpr())
+ Fragments.append("constexpr ", DeclarationFragments::FragmentKind::Keyword);
// FIXME: Is `after` actually needed here?
DeclarationFragments After;
@@ -457,6 +520,9 @@ DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
}
Fragments.append(")", DeclarationFragments::FragmentKind::Text);
+ Fragments.append(DeclarationFragments::getExceptionSpecificationString(
+ Func->getExceptionSpecType()));
+
// FIXME: Handle exception specifiers: throw, noexcept
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
@@ -493,7 +559,13 @@ DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {
DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) {
DeclarationFragments After;
- return getFragmentsForType(Field->getType(), Field->getASTContext(), After)
+ DeclarationFragments Fragments;
+ if (Field->isMutable())
+ Fragments.append("mutable", DeclarationFragments::FragmentKind::Keyword)
+ .appendSpace();
+ return Fragments
+ .append(
+ getFragmentsForType(Field->getType(), Field->getASTContext(), After))
.appendSpace()
.append(Field->getName(), DeclarationFragments::FragmentKind::Identifier)
.append(std::move(After))
@@ -515,6 +587,156 @@ DeclarationFragmentsBuilder::getFragmentsForStruct(const RecordDecl *Record) {
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
+DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
+ const CXXRecordDecl *Record) {
+ if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
+ return getFragmentsForTypedef(TypedefNameDecl);
+
+ DeclarationFragments Fragments;
+ Fragments.append(DeclarationFragments::getStructureTypeFragment(Record));
+
+ if (!Record->getName().empty())
+ Fragments.appendSpace().append(
+ Record->getName(), DeclarationFragments::FragmentKind::Identifier);
+
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+}
+
+DeclarationFragments
+DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(
+ const CXXMethodDecl *Method) {
+ DeclarationFragments Fragments;
+ StringRef Name;
+ if (isa<CXXConstructorDecl>(Method)) {
+ auto *Constructor = dyn_cast<CXXConstructorDecl>(Method);
+ Name = cast<CXXRecordDecl>(Constructor->getDeclContext())->getName();
+ if (Constructor->isExplicit())
+ Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)
+ .appendSpace();
+ } else if (isa<CXXDestructorDecl>(Method))
+ Name = StringRef(Method->getNameAsString());
+
+ DeclarationFragments After;
+ Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier)
+ .append(std::move(After));
+ Fragments.append("(", DeclarationFragments::FragmentKind::Text);
+ for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
+ if (i)
+ Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
+ Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
+ }
+ Fragments.append(")", DeclarationFragments::FragmentKind::Text);
+
+ Fragments.append(DeclarationFragments::getExceptionSpecificationString(
+ Method->getExceptionSpecType()));
+
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+}
+
+DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
+ const CXXMethodDecl *Method) {
+ DeclarationFragments Fragments;
+ StringRef Name;
+ Name = Method->getName();
+ if (Method->isStatic())
+ Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
+ .appendSpace();
+ if (Method->isConstexpr())
+ Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
+ .appendSpace();
+ if (Method->isVolatile())
+ Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword)
+ .appendSpace();
+
+ // Build return type
+ DeclarationFragments After;
+ Fragments
+ .append(getFragmentsForType(Method->getReturnType(),
+ Method->getASTContext(), After))
+ .appendSpace()
+ .append(Name, DeclarationFragments::FragmentKind::Identifier)
+ .append(std::move(After));
+ Fragments.append("(", DeclarationFragments::FragmentKind::Text);
+ for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
+ if (i)
+ Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
+ Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
+ }
+ Fragments.append(")", DeclarationFragments::FragmentKind::Text);
+
+ if (Method->isConst())
+ Fragments.appendSpace().append("const",
+ DeclarationFragments::FragmentKind::Keyword);
+
+ Fragments.append(DeclarationFragments::getExceptionSpecificationString(
+ Method->getExceptionSpecType()));
+
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+}
+
+DeclarationFragments
+DeclarationFragmentsBuilder::getFragmentsForConversionFunction(
+ const CXXConversionDecl *ConversionFunction) {
+ DeclarationFragments Fragments;
+
+ if (ConversionFunction->isExplicit())
+ Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)
+ .appendSpace();
+
+ Fragments.append("operator", DeclarationFragments::FragmentKind::Keyword)
+ .appendSpace();
+
+ Fragments
+ .append(ConversionFunction->getConversionType().getAsString(),
+ DeclarationFragments::FragmentKind::TypeIdentifier)
+ .append("(", DeclarationFragments::FragmentKind::Text);
+ for (unsigned i = 0, end = ConversionFunction->getNumParams(); i != end;
+ ++i) {
+ if (i)
+ Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
+ Fragments.append(getFragmentsForParam(ConversionFunction->getParamDecl(i)));
+ }
+ Fragments.append(")", DeclarationFragments::FragmentKind::Text);
+
+ if (ConversionFunction->isConst())
+ Fragments.appendSpace().append("const",
+ DeclarationFragments::FragmentKind::Keyword);
+
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+}
+
+DeclarationFragments
+DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(
+ const CXXMethodDecl *Method) {
+ DeclarationFragments Fragments;
+
+ // Build return type
+ DeclarationFragments After;
+ Fragments
+ .append(getFragmentsForType(Method->getReturnType(),
+ Method->getASTContext(), After))
+ .appendSpace()
+ .append(Method->getNameAsString(),
+ DeclarationFragments::FragmentKind::Identifier)
+ .append(std::move(After));
+ Fragments.append("(", DeclarationFragments::FragmentKind::Text);
+ for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
+ if (i)
+ Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
+ Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
+ }
+ Fragments.append(")", DeclarationFragments::FragmentKind::Text);
+
+ if (Method->isConst())
+ Fragments.appendSpace().append("const",
+ DeclarationFragments::FragmentKind::Keyword);
+
+ Fragments.append(DeclarationFragments::getExceptionSpecificationString(
+ Method->getExceptionSpecType()));
+
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
+}
+
DeclarationFragments
DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name,
const MacroDirective *MD) {
@@ -765,24 +987,6 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef(
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
-template <typename FunctionT>
-FunctionSignature
-DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) {
- FunctionSignature Signature;
-
- DeclarationFragments ReturnType, After;
- ReturnType
- .append(getFragmentsForType(Function->getReturnType(),
- Function->getASTContext(), After))
- .append(std::move(After));
- Signature.setReturnType(ReturnType);
-
- for (const auto *Param : Function->parameters())
- Signature.addParameter(Param->getName(), getFragmentsForParam(Param));
-
- return Signature;
-}
-
// Instantiate template for FunctionDecl.
template FunctionSignature
DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *);
@@ -795,7 +999,18 @@ DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *);
DeclarationFragments
DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) {
DeclarationFragments Fragments;
- if (!Decl->getName().empty())
+ if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl))
+ Fragments.append(cast<CXXRecordDecl>(Decl->getDeclContext())->getName(),
+ DeclarationFragments::FragmentKind::Identifier);
+ else if (isa<CXXConversionDecl>(Decl)) {
+ Fragments.append(
+ cast<CXXConversionDecl>(Decl)->getConversionType().getAsString(),
+ DeclarationFragments::FragmentKind::Identifier);
+ } else if (isa<CXXMethodDecl>(Decl) &&
+ cast<CXXMethodDecl>(Decl)->isOverloadedOperator()) {
+ Fragments.append(Decl->getNameAsString(),
+ DeclarationFragments::FragmentKind::Identifier);
+ } else if (!Decl->getName().empty())
Fragments.append(Decl->getName(),
DeclarationFragments::FragmentKind::Identifier);
return Fragments;