Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit d120596

Browse files
committed
Added CXAvailability_NotAccessible to indicate that a declaration is available, but not accessible from the current code completion context.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141278 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent aed123e commit d120596

File tree

10 files changed

+154
-14
lines changed

10 files changed

+154
-14
lines changed

Diff for: include/clang-c/Index.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,12 @@ enum CXAvailabilityKind {
115115
/**
116116
* \brief The entity is not available; any use of it will be an error.
117117
*/
118-
CXAvailability_NotAvailable
118+
CXAvailability_NotAvailable,
119+
/**
120+
* \brief The entity is available, but not accessible; any use of it will be
121+
* an error.
122+
*/
123+
CXAvailability_NotAccessible
119124
};
120125

121126
/**

Diff for: include/clang/Sema/CodeCompleteConsumer.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -632,14 +632,15 @@ class CodeCompletionResult {
632632
/// \brief Build a result that refers to a declaration.
633633
CodeCompletionResult(NamedDecl *Declaration,
634634
NestedNameSpecifier *Qualifier = 0,
635-
bool QualifierIsInformative = false)
635+
bool QualifierIsInformative = false,
636+
bool Accessible = true)
636637
: Kind(RK_Declaration), Declaration(Declaration),
637638
Priority(getPriorityFromDecl(Declaration)),
638639
Availability(CXAvailability_Available), StartParameter(0),
639640
Hidden(false), QualifierIsInformative(QualifierIsInformative),
640641
StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
641642
DeclaringEntity(false), Qualifier(Qualifier) {
642-
computeCursorKindAndAvailability();
643+
computeCursorKindAndAvailability(Accessible);
643644
}
644645

645646
/// \brief Build a result that refers to a keyword or symbol.
@@ -701,7 +702,7 @@ class CodeCompletionResult {
701702
static unsigned getPriorityFromDecl(NamedDecl *ND);
702703

703704
private:
704-
void computeCursorKindAndAvailability();
705+
void computeCursorKindAndAvailability(bool Accessible = true);
705706
};
706707

707708
bool operator<(const CodeCompletionResult &X, const CodeCompletionResult &Y);

Diff for: include/clang/Sema/Lookup.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -636,9 +636,11 @@ class LookupResult {
636636
/// \param Hiding a declaration that hides the declaration \p ND,
637637
/// or NULL if no such declaration exists.
638638
///
639+
/// \param Ctx the original context from which the lookup started.
640+
///
639641
/// \param InBaseClass whether this declaration was found in base
640642
/// class of the context we searched.
641-
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
643+
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
642644
bool InBaseClass) = 0;
643645
};
644646

Diff for: include/clang/Sema/Sema.h

+1
Original file line numberDiff line numberDiff line change
@@ -3693,6 +3693,7 @@ class Sema {
36933693
bool ForceCheck = false,
36943694
bool ForceUnprivileged = false);
36953695
void CheckLookupAccess(const LookupResult &R);
3696+
bool IsSimplyAccessible(NamedDecl *decl, CXXRecordDecl *Class);
36963697

36973698
void HandleDependentAccessCheck(const DependentDiagnostic &DD,
36983699
const MultiLevelTemplateArgumentList &TemplateArgs);

Diff for: lib/Sema/CodeCompleteConsumer.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
376376
}
377377
}
378378

379-
void CodeCompletionResult::computeCursorKindAndAvailability() {
379+
void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) {
380380
switch (Kind) {
381381
case RK_Declaration:
382382
// Set the availability based on attributes.
@@ -418,6 +418,9 @@ void CodeCompletionResult::computeCursorKindAndAvailability() {
418418
// Do nothing: Patterns can come with cursor kinds!
419419
break;
420420
}
421+
422+
if (!Accessible)
423+
Availability = CXAvailability_NotAccessible;
421424
}
422425

423426
/// \brief Retrieve the name that should be used to order a result.

Diff for: lib/Sema/SemaAccess.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -1641,6 +1641,27 @@ void Sema::CheckLookupAccess(const LookupResult &R) {
16411641
}
16421642
}
16431643

1644+
/// Checks access to Decl from the given class. The check will take access
1645+
/// specifiers into account, but no member access expressions and such.
1646+
///
1647+
/// \param Decl the declaration to check if it can be accessed
1648+
/// \param Class the class/context from which to start the search
1649+
/// \return true if the Decl is accessible from the Class, false otherwise.
1650+
bool Sema::IsSimplyAccessible(NamedDecl *Decl, CXXRecordDecl *Class) {
1651+
if (!Class)
1652+
return true;
1653+
1654+
QualType qType = Class->getTypeForDecl()->getCanonicalTypeInternal();
1655+
AccessTarget Entity(Context, AccessedEntity::Member, Class,
1656+
DeclAccessPair::make(Decl, Decl->getAccess()),
1657+
qType);
1658+
if (Entity.getAccess() == AS_public)
1659+
return true;
1660+
1661+
EffectiveContext EC(CurContext);
1662+
return ::IsAccessible(*this, EC, Entity) != ::AR_inaccessible;
1663+
}
1664+
16441665
void Sema::ActOnStartSuppressingAccessChecks() {
16451666
assert(!SuppressAccessChecking &&
16461667
"Tried to start access check suppression when already started.");

Diff for: lib/Sema/SemaCodeComplete.cpp

+10-2
Original file line numberDiff line numberDiff line change
@@ -1186,8 +1186,16 @@ namespace {
11861186
CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
11871187
: Results(Results), CurContext(CurContext) { }
11881188

1189-
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool InBaseClass) {
1190-
Results.AddResult(ND, CurContext, Hiding, InBaseClass);
1189+
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1190+
bool InBaseClass) {
1191+
bool Accessible = true;
1192+
if (Ctx) {
1193+
if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx))
1194+
Accessible = Results.getSema().IsSimplyAccessible(ND, Class);
1195+
// FIXME: ObjC access checks are missing.
1196+
}
1197+
ResultBuilder::Result Result(ND, 0, false, Accessible);
1198+
Results.AddResult(Result, CurContext, Hiding, InBaseClass);
11911199
}
11921200
};
11931201
}

Diff for: lib/Sema/SemaLookup.cpp

+8-6
Original file line numberDiff line numberDiff line change
@@ -2701,7 +2701,7 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
27012701
D != DEnd; ++D) {
27022702
if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) {
27032703
if (Result.isAcceptableDecl(ND)) {
2704-
Consumer.FoundDecl(ND, Visited.checkHidden(ND), InBaseClass);
2704+
Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
27052705
Visited.add(ND);
27062706
}
27072707
} else if (ObjCForwardProtocolDecl *ForwardProto
@@ -2712,14 +2712,15 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
27122712
P != PEnd;
27132713
++P) {
27142714
if (Result.isAcceptableDecl(*P)) {
2715-
Consumer.FoundDecl(*P, Visited.checkHidden(*P), InBaseClass);
2715+
Consumer.FoundDecl(*P, Visited.checkHidden(*P), Ctx, InBaseClass);
27162716
Visited.add(*P);
27172717
}
27182718
}
27192719
} else if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*D)) {
27202720
ObjCInterfaceDecl *IFace = Class->getForwardInterfaceDecl();
27212721
if (Result.isAcceptableDecl(IFace)) {
2722-
Consumer.FoundDecl(IFace, Visited.checkHidden(IFace), InBaseClass);
2722+
Consumer.FoundDecl(IFace, Visited.checkHidden(IFace), Ctx,
2723+
InBaseClass);
27232724
Visited.add(IFace);
27242725
}
27252726
}
@@ -2861,7 +2862,7 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
28612862
D != DEnd; ++D) {
28622863
if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
28632864
if (Result.isAcceptableDecl(ND)) {
2864-
Consumer.FoundDecl(ND, Visited.checkHidden(ND), false);
2865+
Consumer.FoundDecl(ND, Visited.checkHidden(ND), 0, false);
28652866
Visited.add(ND);
28662867
}
28672868
}
@@ -3043,7 +3044,8 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer {
30433044
delete I->second;
30443045
}
30453046

3046-
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool InBaseClass);
3047+
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
3048+
bool InBaseClass);
30473049
void FoundName(StringRef Name);
30483050
void addKeywordResult(StringRef Keyword);
30493051
void addName(StringRef Name, NamedDecl *ND, unsigned Distance,
@@ -3074,7 +3076,7 @@ class TypoCorrectionConsumer : public VisibleDeclConsumer {
30743076
}
30753077

30763078
void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
3077-
bool InBaseClass) {
3079+
DeclContext *Ctx, bool InBaseClass) {
30783080
// Don't consider hidden names for typo correction.
30793081
if (Hiding)
30803082
return;

Diff for: test/Index/complete-access-checks.cpp

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
struct X {
2+
int member1;
3+
void func1();
4+
protected:
5+
int member2;
6+
void func2();
7+
private:
8+
int member3;
9+
void func3();
10+
};
11+
12+
struct Y: protected X {
13+
void doSomething();
14+
};
15+
16+
class Z {
17+
public:
18+
int member1;
19+
void func1();
20+
protected:
21+
int member2;
22+
void func2();
23+
private:
24+
int member3;
25+
void func3();
26+
};
27+
28+
void Y::doSomething() {
29+
// RUN: c-index-test -code-completion-at=%s:30:9 %s | FileCheck -check-prefix=CHECK-SUPER-ACCESS %s
30+
this->;
31+
32+
Z that;
33+
// RUN: c-index-test -code-completion-at=%s:34:8 %s | FileCheck -check-prefix=CHECK-ACCESS %s
34+
that.
35+
}
36+
37+
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34)
38+
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{Informative X::}{TypedText func1}{LeftParen (}{RightParen )} (36)
39+
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{Informative X::}{TypedText func2}{LeftParen (}{RightParen )} (36) (inaccessible)
40+
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{Informative X::}{TypedText func3}{LeftParen (}{RightParen )} (36) (inaccessible)
41+
// CHECK-SUPER-ACCESS: FieldDecl:{ResultType int}{Informative X::}{TypedText member1} (37)
42+
// CHECK-SUPER-ACCESS: FieldDecl:{ResultType int}{Informative X::}{TypedText member2} (37) (inaccessible)
43+
// CHECK-SUPER-ACCESS: FieldDecl:{ResultType int}{Informative X::}{TypedText member3} (37) (inaccessible)
44+
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType Y &}{TypedText operator=}{LeftParen (}{Placeholder const Y &}{RightParen )} (34)
45+
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType X &}{Text X::}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (36)
46+
// CHECK-SUPER-ACCESS: StructDecl:{TypedText X}{Text ::} (77)
47+
// CHECK-SUPER-ACCESS: StructDecl:{TypedText Y}{Text ::} (75)
48+
// CHECK-SUPER-ACCESS: CXXDestructor:{ResultType void}{Informative X::}{TypedText ~X}{LeftParen (}{RightParen )} (36)
49+
// CHECK-SUPER-ACCESS: CXXDestructor:{ResultType void}{TypedText ~Y}{LeftParen (}{RightParen )} (34)
50+
51+
// CHECK-ACCESS: CXXMethod:{ResultType void}{TypedText func1}{LeftParen (}{RightParen )} (34)
52+
// CHECK-ACCESS: CXXMethod:{ResultType void}{TypedText func2}{LeftParen (}{RightParen )} (34) (inaccessible)
53+
// CHECK-ACCESS: CXXMethod:{ResultType void}{TypedText func3}{LeftParen (}{RightParen )} (34) (inaccessible)
54+
// CHECK-ACCESS: FieldDecl:{ResultType int}{TypedText member1} (35)
55+
// CHECK-ACCESS: FieldDecl:{ResultType int}{TypedText member2} (35) (inaccessible)
56+
// CHECK-ACCESS: FieldDecl:{ResultType int}{TypedText member3} (35) (inaccessible)
57+
// CHECK-ACCESS: CXXMethod:{ResultType Z &}{TypedText operator=}{LeftParen (}{Placeholder const Z &}{RightParen )} (34)
58+
// CHECK-ACCESS: ClassDecl:{TypedText Z}{Text ::} (75)
59+
// CHECK-ACCESS: CXXDestructor:{ResultType void}{TypedText ~Z}{LeftParen (}{RightParen )} (34)
60+
61+
class P {
62+
protected:
63+
int member;
64+
};
65+
66+
class Q : public P {
67+
public:
68+
using P::member;
69+
};
70+
71+
void f(P x, Q y) {
72+
// RUN: c-index-test -code-completion-at=%s:73:5 %s | FileCheck -check-prefix=CHECK-USING-INACCESSIBLE %s
73+
x.; // member is inaccessible
74+
// RUN: c-index-test -code-completion-at=%s:75:5 %s | FileCheck -check-prefix=CHECK-USING-ACCESSIBLE %s
75+
y.; // member is accessible
76+
}
77+
78+
// CHECK-USING-INACCESSIBLE: FieldDecl:{ResultType int}{TypedText member} (35) (inaccessible)
79+
// CHECK-USING-INACCESSIBLE: CXXMethod:{ResultType P &}{TypedText operator=}{LeftParen (}{Placeholder const P &}{RightParen )} (34)
80+
// CHECK-USING-INACCESSIBLE: ClassDecl:{TypedText P}{Text ::} (75)
81+
// CHECK-USING-INACCESSIBLE: CXXDestructor:{ResultType void}{TypedText ~P}{LeftParen (}{RightParen )} (34)
82+
83+
// CHECK-USING-ACCESSIBLE: FieldDecl:{ResultType int}{TypedText member} (35)
84+
// CHECK-USING-ACCESSIBLE: CXXMethod:{ResultType Q &}{TypedText operator=}{LeftParen (}{Placeholder const Q &}{RightParen )} (34)
85+
// CHECK-USING-ACCESSIBLE: CXXMethod:{ResultType P &}{Text P::}{TypedText operator=}{LeftParen (}{Placeholder const P &}{RightParen )} (36)
86+
// CHECK-USING-ACCESSIBLE: ClassDecl:{TypedText P}{Text ::} (77)
87+
// CHECK-USING-ACCESSIBLE: ClassDecl:{TypedText Q}{Text ::} (75)
88+
// CHECK-USING-ACCESSIBLE: CXXDestructor:{ResultType void}{Informative P::}{TypedText ~P}{LeftParen (}{RightParen )} (36)
89+
// CHECK-USING-ACCESSIBLE: CXXDestructor:{ResultType void}{TypedText ~Q}{LeftParen (}{RightParen )} (34)

Diff for: tools/c-index-test/c-index-test.c

+8
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,10 @@ static void PrintCursor(CXCursor Cursor) {
238238
case CXAvailability_NotAvailable:
239239
printf(" (unavailable)");
240240
break;
241+
242+
case CXAvailability_NotAccessible:
243+
printf(" (inaccessible)");
244+
break;
241245
}
242246

243247
if (clang_CXXMethod_isStatic(Cursor))
@@ -1051,6 +1055,10 @@ void print_completion_result(CXCompletionResult *completion_result,
10511055
case CXAvailability_NotAvailable:
10521056
fprintf(file, " (unavailable)");
10531057
break;
1058+
1059+
case CXAvailability_NotAccessible:
1060+
fprintf(file, " (inaccessible)");
1061+
break;
10541062
}
10551063
fprintf(file, "\n");
10561064
}

0 commit comments

Comments
 (0)