[DeclPrinter] Allow printing fully qualified name of function declaration

When requesting a tooltip for a function call in an IDE, the fully
qualified name helps to remove ambiguity in the function signature.

Patch by Nikolai Kosjar!

Differential Revision: https://reviews.llvm.org/D40013

llvm-svn: 318896
This commit is contained in:
Serge Pavlov 2017-11-23 05:38:20 +00:00
parent c5b8e8b97f
commit 842022a0f1
3 changed files with 64 additions and 10 deletions

View File

@ -51,7 +51,8 @@ struct PrintingPolicy {
TerseOutput(false), PolishForDeclaration(false),
Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar),
IncludeNewlines(true), MSVCFormatting(false),
ConstantsAsWritten(false), SuppressImplicitBase(false) { }
ConstantsAsWritten(false), SuppressImplicitBase(false),
FullyQualifiedName(false) { }
/// Adjust this printing policy for cases where it's known that we're
/// printing C++ code (for instance, if AST dumping reaches a C++-only
@ -220,6 +221,10 @@ struct PrintingPolicy {
/// When true, don't print the implicit 'self' or 'this' expressions.
bool SuppressImplicitBase : 1;
/// When true, print the fully qualified name of function declarations.
/// This is the opposite of SuppressScope and thus overrules it.
bool FullyQualifiedName : 1;
};
} // end namespace clang

View File

@ -580,13 +580,19 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
PrintingPolicy SubPolicy(Policy);
SubPolicy.SuppressSpecifiers = false;
std::string Proto;
if (!Policy.SuppressScope) {
if (const NestedNameSpecifier *NS = D->getQualifier()) {
llvm::raw_string_ostream OS(Proto);
NS->print(OS, Policy);
if (Policy.FullyQualifiedName) {
Proto += D->getQualifiedNameAsString();
} else {
if (!Policy.SuppressScope) {
if (const NestedNameSpecifier *NS = D->getQualifier()) {
llvm::raw_string_ostream OS(Proto);
NS->print(OS, Policy);
}
}
Proto += D->getNameInfo().getAsString();
}
Proto += D->getNameInfo().getAsString();
if (GuideDecl)
Proto = GuideDecl->getDeducedTemplate()->getDeclName().getAsString();
if (const TemplateArgumentList *TArgs = D->getTemplateSpecializationArgs()) {

View File

@ -104,15 +104,17 @@ PrintedDeclMatches(StringRef Code, const std::vector<std::string> &Args,
return ::testing::AssertionSuccess();
}
::testing::AssertionResult PrintedDeclCXX98Matches(StringRef Code,
StringRef DeclName,
StringRef ExpectedPrinted) {
::testing::AssertionResult
PrintedDeclCXX98Matches(StringRef Code, StringRef DeclName,
StringRef ExpectedPrinted,
PrintingPolicyModifier PolicyModifier = nullptr) {
std::vector<std::string> Args(1, "-std=c++98");
return PrintedDeclMatches(Code,
Args,
namedDecl(hasName(DeclName)).bind("id"),
ExpectedPrinted,
"input.cc");
"input.cc",
PolicyModifier);
}
::testing::AssertionResult
@ -350,6 +352,47 @@ TEST(DeclPrinter, TestFunctionDecl1) {
"void A()"));
}
TEST(DeclPrinter, TestFreeFunctionDecl_FullyQualifiedName) {
ASSERT_TRUE(PrintedDeclCXX98Matches(
"void A();",
"A",
"void A()",
[](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; }));
}
TEST(DeclPrinter, TestFreeFunctionDeclInNamespace_FullyQualifiedName) {
ASSERT_TRUE(PrintedDeclCXX98Matches(
"namespace X { void A(); };",
"A",
"void X::A()",
[](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; }));
}
TEST(DeclPrinter, TestMemberFunction_FullyQualifiedName) {
ASSERT_TRUE(PrintedDeclCXX98Matches(
"struct X { void A(); };",
"A",
"void X::A()",
[](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; }));
}
TEST(DeclPrinter, TestMemberFunctionInNamespace_FullyQualifiedName) {
ASSERT_TRUE(PrintedDeclCXX98Matches(
"namespace Z { struct X { void A(); }; }",
"A",
"void Z::X::A()",
[](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; }));
}
TEST(DeclPrinter, TestMemberFunctionOutside_FullyQualifiedName) {
ASSERT_TRUE(PrintedDeclCXX98Matches(
"struct X { void A(); };"
"void X::A() {}",
functionDecl(hasName("A"), isDefinition()).bind("id"),
"void X::A()",
[](PrintingPolicy &Policy){ Policy.FullyQualifiedName = true; }));
}
TEST(DeclPrinter, TestFunctionDecl2) {
ASSERT_TRUE(PrintedDeclCXX98Matches(
"void A() {}",