-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[clang] Include explicit object methods in overload suggestions #154041
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -413,6 +413,37 @@ class ResultBuilder { | |
bool IsImpossibleToSatisfy(const NamedDecl *ND) const; | ||
//@} | ||
}; | ||
|
||
void AddFunctionTypeQuals(CodeCompletionBuilder &Result, | ||
|
||
const Qualifiers Quals) { | ||
// FIXME: Add ref-qualifier! | ||
|
||
// Handle single qualifiers without copying | ||
if (Quals.hasOnlyConst()) { | ||
Result.AddInformativeChunk(" const"); | ||
return; | ||
} | ||
|
||
if (Quals.hasOnlyVolatile()) { | ||
Result.AddInformativeChunk(" volatile"); | ||
return; | ||
} | ||
|
||
if (Quals.hasOnlyRestrict()) { | ||
Result.AddInformativeChunk(" restrict"); | ||
return; | ||
} | ||
|
||
// Handle multiple qualifiers. | ||
std::string QualsStr; | ||
if (Quals.hasConst()) | ||
QualsStr += " const"; | ||
if (Quals.hasVolatile()) | ||
QualsStr += " volatile"; | ||
if (Quals.hasRestrict()) | ||
QualsStr += " restrict"; | ||
Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr)); | ||
} | ||
} // namespace | ||
|
||
void PreferredTypeBuilder::enterReturn(Sema &S, SourceLocation Tok) { | ||
|
@@ -1435,6 +1466,14 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, | |
|
||
AdjustResultPriorityForDecl(R); | ||
|
||
// Account for explicit object parameter | ||
const auto GetQualifiers = [&](const CXXMethodDecl *MethodDecl) { | ||
if (MethodDecl->isExplicitObjectMemberFunction()) | ||
return MethodDecl->getFunctionObjectParameterType().getQualifiers(); | ||
else | ||
return MethodDecl->getMethodQualifiers(); | ||
}; | ||
|
||
if (IsExplicitObjectMemberFunction && | ||
R.Kind == CodeCompletionResult::RK_Declaration && | ||
(isa<CXXMethodDecl>(R.Declaration) || isa<FieldDecl>(R.Declaration))) { | ||
|
@@ -1447,7 +1486,7 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, | |
if (HasObjectTypeQualifiers) | ||
if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration)) | ||
if (Method->isInstance()) { | ||
Qualifiers MethodQuals = Method->getMethodQualifiers(); | ||
Qualifiers MethodQuals = GetQualifiers(Method); | ||
if (ObjectTypeQualifiers == MethodQuals) | ||
R.Priority += CCD_ObjectQualifierMatch; | ||
else if (ObjectTypeQualifiers - MethodQuals) { | ||
|
@@ -3426,40 +3465,36 @@ static void AddQualifierToCompletionString(CodeCompletionBuilder &Result, | |
Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS)); | ||
} | ||
|
||
static void | ||
AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result, | ||
const FunctionDecl *Function) { | ||
const auto *Proto = Function->getType()->getAs<FunctionProtoType>(); | ||
if (!Proto || !Proto->getMethodQuals()) | ||
return; | ||
// Sets the function qualifiers completion string by inspecting the explicit | ||
// object | ||
static void AddCXXExplicitObjectFunctionTypeQualsToCompletionString( | ||
|
||
CodeCompletionBuilder &Result, const CXXMethodDecl *Function) { | ||
assert(isa<CXXMethodDecl>(Function) && | ||
Function->hasCXXExplicitFunctionObjectParameter() && | ||
"Valid only on CXX explicit object methods"); | ||
|
||
// FIXME: Add ref-qualifier! | ||
|
||
// Handle single qualifiers without copying | ||
if (Proto->getMethodQuals().hasOnlyConst()) { | ||
Result.AddInformativeChunk(" const"); | ||
const auto Quals = Function->getFunctionObjectParameterType(); | ||
if (!Quals.hasQualifiers()) | ||
return; | ||
} | ||
|
||
if (Proto->getMethodQuals().hasOnlyVolatile()) { | ||
Result.AddInformativeChunk(" volatile"); | ||
return; | ||
} | ||
AddFunctionTypeQuals(Result, Quals.getQualifiers()); | ||
} | ||
|
||
if (Proto->getMethodQuals().hasOnlyRestrict()) { | ||
Result.AddInformativeChunk(" restrict"); | ||
return; | ||
} | ||
static void | ||
AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result, | ||
const FunctionDecl *Function) { | ||
if (auto *CxxMethodDecl = llvm::dyn_cast_if_present<CXXMethodDecl>(Function); | ||
CxxMethodDecl && CxxMethodDecl->hasCXXExplicitFunctionObjectParameter()) { | ||
// if explicit object method, infer quals from the object parameter | ||
AddCXXExplicitObjectFunctionTypeQualsToCompletionString(Result, | ||
CxxMethodDecl); | ||
} else { | ||
const auto *Proto = Function->getType()->getAs<FunctionProtoType>(); | ||
if (!Proto || !Proto->getMethodQuals()) | ||
return; | ||
|
||
// Handle multiple qualifiers. | ||
std::string QualsStr; | ||
if (Proto->isConst()) | ||
QualsStr += " const"; | ||
if (Proto->isVolatile()) | ||
QualsStr += " volatile"; | ||
if (Proto->isRestrict()) | ||
QualsStr += " restrict"; | ||
Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr)); | ||
AddFunctionTypeQuals(Result, Proto->getMethodQuals()); | ||
} | ||
} | ||
|
||
static void | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test slightly modified from example that @zwuis originally shared in the ticket.
Happy to change or update!