Adds support for default arguments in the internal representation and reads these values from the source. Implements writing these values to YAML but does not implement this for the HTML or markdown outputs.
Reviewed By: paulkirth
Differential Revision: https://reviews.llvm.org/D133732
switch (ID) {
case FIELD_TYPE_NAME:
return decodeRecord(R, I->Name, Blob);
+ case FIELD_DEFAULT_VALUE:
+ return decodeRecord(R, I->DefaultValue, Blob);
default:
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"invalid field for TypeInfo");
{COMMENT_ATTRVAL, {"AttrVal", &StringAbbrev}},
{COMMENT_ARG, {"Arg", &StringAbbrev}},
{FIELD_TYPE_NAME, {"Name", &StringAbbrev}},
+ {FIELD_DEFAULT_VALUE, {"DefaultValue", &StringAbbrev}},
{MEMBER_TYPE_NAME, {"Name", &StringAbbrev}},
{MEMBER_TYPE_ACCESS, {"Access", &IntAbbrev}},
{NAMESPACE_USR, {"USR", &SymbolIDAbbrev}},
// Type Block
{BI_TYPE_BLOCK_ID, {}},
// FieldType Block
- {BI_FIELD_TYPE_BLOCK_ID, {FIELD_TYPE_NAME}},
+ {BI_FIELD_TYPE_BLOCK_ID, {FIELD_TYPE_NAME, FIELD_DEFAULT_VALUE}},
// MemberType Block
{BI_MEMBER_TYPE_BLOCK_ID, {MEMBER_TYPE_NAME, MEMBER_TYPE_ACCESS}},
// Enum Block
StreamSubBlockGuard Block(Stream, BI_FIELD_TYPE_BLOCK_ID);
emitBlock(T.Type, FieldId::F_type);
emitRecord(T.Name, FIELD_TYPE_NAME);
+ emitRecord(T.DefaultValue, FIELD_DEFAULT_VALUE);
}
void ClangDocBitcodeWriter::emitBlock(const MemberTypeInfo &T) {
COMMENT_ATTRVAL,
COMMENT_ARG,
FIELD_TYPE_NAME,
+ FIELD_DEFAULT_VALUE,
MEMBER_TYPE_NAME,
MEMBER_TYPE_ACCESS,
NAMESPACE_USR,
: TypeInfo(RefName, Path), Name(Name) {}
bool operator==(const FieldTypeInfo &Other) const {
- return std::tie(Type, Name) == std::tie(Other.Type, Other.Name);
+ return std::tie(Type, Name, DefaultValue) ==
+ std::tie(Other.Type, Other.Name, Other.DefaultValue);
}
SmallString<16> Name; // Name associated with this info.
+
+ // When used for function parameters, contains the string representing the
+ // expression of the default value, if any.
+ SmallString<16> DefaultValue;
};
// Info for member types.
#include "BitcodeWriter.h"
#include "clang/AST/Comment.h"
#include "clang/Index/USRGeneration.h"
+#include "clang/Lex/Lexer.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/SHA1.h"
static void parseParameters(FunctionInfo &I, const FunctionDecl *D) {
for (const ParmVarDecl *P : D->parameters()) {
+ FieldTypeInfo *FieldInfo = nullptr;
if (const auto *T = getDeclForType(P->getOriginalType())) {
if (const auto *N = dyn_cast<EnumDecl>(T)) {
- I.Params.emplace_back(getUSRForDecl(N), N->getNameAsString(),
- InfoType::IT_enum, getInfoRelativePath(N),
- P->getNameAsString());
- continue;
+ FieldInfo = &I.Params.emplace_back(
+ getUSRForDecl(N), N->getNameAsString(), InfoType::IT_enum,
+ getInfoRelativePath(N), P->getNameAsString());
} else if (const auto *N = dyn_cast<RecordDecl>(T)) {
- I.Params.emplace_back(getUSRForDecl(N), N->getNameAsString(),
- InfoType::IT_record, getInfoRelativePath(N),
- P->getNameAsString());
- continue;
+ FieldInfo = &I.Params.emplace_back(
+ getUSRForDecl(N), N->getNameAsString(), InfoType::IT_record,
+ getInfoRelativePath(N), P->getNameAsString());
}
+ // Otherwise fall through to the default case below.
+ }
+
+ if (!FieldInfo) {
+ FieldInfo = &I.Params.emplace_back(P->getOriginalType().getAsString(),
+ P->getNameAsString());
+ }
+
+ if (const Expr *DefaultArg = P->getDefaultArg()) {
+ FieldInfo->DefaultValue = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(DefaultArg->getSourceRange()),
+ D->getASTContext().getSourceManager(),
+ D->getASTContext().getLangOpts());
}
- I.Params.emplace_back(P->getOriginalType().getAsString(),
- P->getNameAsString());
}
}
static void FieldTypeInfoMapping(IO &IO, FieldTypeInfo &I) {
TypeInfoMapping(IO, I);
IO.mapOptional("Name", I.Name, SmallString<16>());
+ IO.mapOptional("DefaultValue", I.DefaultValue, SmallString<16>());
}
static void InfoMapping(IO &IO, Info &I) {
static void mapping(IO &IO, FieldTypeInfo &I) {
TypeInfoMapping(IO, I);
IO.mapOptional("Name", I.Name, SmallString<16>());
+ IO.mapOptional("DefaultValue", I.DefaultValue, SmallString<16>());
}
};
std::vector<std::string> Args;
Args.push_back("-fmodules-ts");
ExtractInfosFromCodeWithArgs(R"raw(export module M;
-int moduleFunction(int x);
+int moduleFunction(int x, double d = 3.2 - 1.0);
static int staticModuleFunction(int x);
export double exportedModuleFunction(double y);)raw",
2, /*Public=*/true, Infos, Args);
F.ReturnType = TypeInfo(EmptySID, "int", InfoType::IT_default);
F.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
F.Params.emplace_back("int", "x");
+ F.Params.emplace_back("double", "d");
+ F.Params.back().DefaultValue = "3.2 - 1.0";
F.Access = AccessSpecifier::AS_none;
ExpectedBWithFunction.ChildFunctions.emplace_back(std::move(F));
CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
I.ReturnType =
TypeInfo(EmptySID, "void", InfoType::IT_default, "path/to/void");
I.Params.emplace_back("int", "path/to/int", "P");
+ I.Params.emplace_back("double", "path/to/double", "D");
+ I.Params.back().DefaultValue = "2.0 * M_PI";
I.IsMethod = true;
I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
Name: 'int'
Path: 'path/to/int'
Name: 'P'
+ - Type:
+ Name: 'double'
+ Path: 'path/to/double'
+ Name: 'D'
+ DefaultValue: '2.0 * M_PI'
ReturnType:
Type:
Name: 'void'