Skip to content

Commit 8924617

Browse files
committed
[clangd][Sema] add noexcept to override functions during code completion
1 parent ce747a1 commit 8924617

File tree

2 files changed

+64
-27
lines changed

2 files changed

+64
-27
lines changed

clang/lib/Sema/SemaCodeComplete.cpp

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "clang/AST/Type.h"
2727
#include "clang/Basic/AttributeCommonInfo.h"
2828
#include "clang/Basic/CharInfo.h"
29+
#include "clang/Basic/ExceptionSpecificationType.h"
2930
#include "clang/Basic/OperatorKinds.h"
3031
#include "clang/Basic/Specifiers.h"
3132
#include "clang/Lex/HeaderSearch.h"
@@ -184,7 +185,7 @@ class ResultBuilder {
184185

185186
/// Overloaded C++ member functions found by SemaLookup.
186187
/// Used to determine when one overload is dominated by another.
187-
llvm::DenseMap<std::pair<DeclContext *, /*Name*/uintptr_t>, ShadowMapEntry>
188+
llvm::DenseMap<std::pair<DeclContext *, /*Name=*/uintptr_t>, ShadowMapEntry>
188189
OverloadMap;
189190

190191
/// If we're potentially referring to a C++ member function, the set
@@ -1432,16 +1433,16 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
14321433
}
14331434
// Detect cases where a ref-qualified method cannot be invoked.
14341435
switch (Method->getRefQualifier()) {
1435-
case RQ_LValue:
1436-
if (ObjectKind != VK_LValue && !MethodQuals.hasConst())
1437-
return;
1438-
break;
1439-
case RQ_RValue:
1440-
if (ObjectKind == VK_LValue)
1441-
return;
1442-
break;
1443-
case RQ_None:
1444-
break;
1436+
case RQ_LValue:
1437+
if (ObjectKind != VK_LValue && !MethodQuals.hasConst())
1438+
return;
1439+
break;
1440+
case RQ_RValue:
1441+
if (ObjectKind == VK_LValue)
1442+
return;
1443+
break;
1444+
case RQ_None:
1445+
break;
14451446
}
14461447

14471448
/// Check whether this dominates another overloaded method, which should
@@ -1490,9 +1491,7 @@ void ResultBuilder::AddResult(Result R) {
14901491
void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
14911492

14921493
/// Exit from the current scope.
1493-
void ResultBuilder::ExitScope() {
1494-
ShadowMaps.pop_back();
1495-
}
1494+
void ResultBuilder::ExitScope() { ShadowMaps.pop_back(); }
14961495

14971496
/// Determines whether this given declaration will be found by
14981497
/// ordinary name lookup.
@@ -2557,7 +2556,8 @@ AddOrdinaryNameResults(SemaCodeCompletion::ParserCompletionContext CCC,
25572556
ReturnType = Method->getReturnType();
25582557
else if (SemaRef.getCurBlock() &&
25592558
!SemaRef.getCurBlock()->ReturnType.isNull())
2560-
ReturnType = SemaRef.getCurBlock()->ReturnType;;
2559+
ReturnType = SemaRef.getCurBlock()->ReturnType;
2560+
;
25612561
if (ReturnType.isNull() || ReturnType->isVoidType()) {
25622562
Builder.AddTypedTextChunk("return");
25632563
Builder.AddChunk(CodeCompletionString::CK_SemiColon);
@@ -3427,6 +3427,25 @@ AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
34273427
Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
34283428
}
34293429

3430+
static void
3431+
AddFunctionExceptSpecToCompletionString(std::string &NameAndSignature,
3432+
const FunctionDecl *Function) {
3433+
const auto *Proto = Function->getType()->getAs<FunctionProtoType>();
3434+
if (!Proto)
3435+
return;
3436+
3437+
auto ExceptInfo = Proto->getExceptionSpecInfo();
3438+
switch (ExceptInfo.Type) {
3439+
case EST_BasicNoexcept:
3440+
case EST_NoexceptTrue:
3441+
NameAndSignature += " noexcept";
3442+
break;
3443+
3444+
default:
3445+
break;
3446+
}
3447+
}
3448+
34303449
/// Add the name of the given declaration
34313450
static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
34323451
const NamedDecl *ND,
@@ -3642,6 +3661,13 @@ CodeCompletionResult::createCodeCompletionStringForOverride(
36423661
std::string NameAndSignature;
36433662
// For overrides all chunks go into the result, none are informative.
36443663
printOverrideString(*CCS, BeforeName, NameAndSignature);
3664+
3665+
// If the virtual function is declared with "noexcept", add it in the result
3666+
// code completion string.
3667+
const auto *VirtualFunc = dyn_cast<FunctionDecl>(Declaration);
3668+
assert(VirtualFunc && "overridden decl must be a function");
3669+
AddFunctionExceptSpecToCompletionString(NameAndSignature, VirtualFunc);
3670+
36453671
NameAndSignature += " override";
36463672

36473673
Result.AddTextChunk(Result.getAllocator().CopyString(BeforeName));
@@ -4886,7 +4912,8 @@ static void AddEnumerators(ResultBuilder &Results, ASTContext &Context,
48864912
EnumDecl *Enum, DeclContext *CurContext,
48874913
const CoveredEnumerators &Enumerators) {
48884914
NestedNameSpecifier *Qualifier = Enumerators.SuggestedQualifier;
4889-
if (Context.getLangOpts().CPlusPlus && !Qualifier && Enumerators.Seen.empty()) {
4915+
if (Context.getLangOpts().CPlusPlus && !Qualifier &&
4916+
Enumerators.Seen.empty()) {
48904917
// If there are no prior enumerators in C++, check whether we have to
48914918
// qualify the names of the enumerators that we suggest, because they
48924919
// may not be visible in this scope.
@@ -5292,8 +5319,7 @@ AddObjCProperties(const CodeCompletionContext &CCContext,
52925319
AllowNullaryMethods, CurContext, AddedProperties,
52935320
Results, IsBaseExprStatement, IsClassProperty,
52945321
/*InOriginalClass*/ false);
5295-
} else if (const auto *Category =
5296-
dyn_cast<ObjCCategoryDecl>(Container)) {
5322+
} else if (const auto *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
52975323
// Look through protocols.
52985324
for (auto *P : Category->protocols())
52995325
AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
@@ -6159,8 +6185,7 @@ void SemaCodeCompletion::CodeCompleteCase(Scope *S) {
61596185

61606186
Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
61616187
if (auto *DRE = dyn_cast<DeclRefExpr>(CaseVal))
6162-
if (auto *Enumerator =
6163-
dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
6188+
if (auto *Enumerator = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
61646189
// We look into the AST of the case statement to determine which
61656190
// enumerator was named. Alternatively, we could compute the value of
61666191
// the integral constant expression, then compare it against the
@@ -8480,11 +8505,10 @@ void SemaCodeCompletion::CodeCompleteObjCInstanceMessage(
84808505
return;
84818506
RecExpr = Conv.get();
84828507
}
8483-
QualType ReceiverType = RecExpr
8484-
? RecExpr->getType()
8485-
: Super ? Context.getObjCObjectPointerType(
8486-
Context.getObjCInterfaceType(Super))
8487-
: Context.getObjCIdType();
8508+
QualType ReceiverType = RecExpr ? RecExpr->getType()
8509+
: Super ? Context.getObjCObjectPointerType(
8510+
Context.getObjCInterfaceType(Super))
8511+
: Context.getObjCIdType();
84888512

84898513
// If we're messaging an expression with type "id" or "Class", check
84908514
// whether we know something special about the receiver that allows
@@ -10356,8 +10380,7 @@ void SemaCodeCompletion::CodeCompleteIncludedFile(llvm::StringRef Dir,
1035610380
};
1035710381

1035810382
// Helper: scans IncludeDir for nice files, and adds results for each.
10359-
auto AddFilesFromIncludeDir = [&](StringRef IncludeDir,
10360-
bool IsSystem,
10383+
auto AddFilesFromIncludeDir = [&](StringRef IncludeDir, bool IsSystem,
1036110384
DirectoryLookup::LookupType_t LookupType) {
1036210385
llvm::SmallString<128> Dir = IncludeDir;
1036310386
if (!NativeRelDir.empty()) {

clang/test/CodeCompletion/overrides.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,17 @@ void func() {
4141
// Runs completion at empty line on line 37.
4242
// RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-5):1 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s
4343
// CHECK-CC4: COMPLETION: Pattern : void vfunc(bool param, int p) override{{$}}
44+
45+
class NoexceptBase {
46+
public:
47+
virtual void method() noexcept;
48+
};
49+
50+
class NoexceptDerived : public NoexceptBase {
51+
public:
52+
met;
53+
};
54+
55+
// Runs completion at met^ on line 52.
56+
// RUN: not %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-4):6 %s -o - | FileCheck -check-prefix=CHECK-CC5 %s
57+
// CHECK-CC5: COMPLETION: Pattern : void method() noexcept override{{$}}

0 commit comments

Comments
 (0)