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
This commit is contained in:
Erik Verbruggen 2011-10-06 07:27:49 +00:00
Родитель aed123ec3c
Коммит d12059673d
10 изменённых файлов: 154 добавлений и 14 удалений

Просмотреть файл

@ -115,7 +115,12 @@ enum CXAvailabilityKind {
/**
* \brief The entity is not available; any use of it will be an error.
*/
CXAvailability_NotAvailable
CXAvailability_NotAvailable,
/**
* \brief The entity is available, but not accessible; any use of it will be
* an error.
*/
CXAvailability_NotAccessible
};
/**

Просмотреть файл

@ -632,14 +632,15 @@ public:
/// \brief Build a result that refers to a declaration.
CodeCompletionResult(NamedDecl *Declaration,
NestedNameSpecifier *Qualifier = 0,
bool QualifierIsInformative = false)
bool QualifierIsInformative = false,
bool Accessible = true)
: Kind(RK_Declaration), Declaration(Declaration),
Priority(getPriorityFromDecl(Declaration)),
Availability(CXAvailability_Available), StartParameter(0),
Hidden(false), QualifierIsInformative(QualifierIsInformative),
StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
DeclaringEntity(false), Qualifier(Qualifier) {
computeCursorKindAndAvailability();
computeCursorKindAndAvailability(Accessible);
}
/// \brief Build a result that refers to a keyword or symbol.
@ -701,7 +702,7 @@ public:
static unsigned getPriorityFromDecl(NamedDecl *ND);
private:
void computeCursorKindAndAvailability();
void computeCursorKindAndAvailability(bool Accessible = true);
};
bool operator<(const CodeCompletionResult &X, const CodeCompletionResult &Y);

Просмотреть файл

@ -636,9 +636,11 @@ private:
/// \param Hiding a declaration that hides the declaration \p ND,
/// or NULL if no such declaration exists.
///
/// \param Ctx the original context from which the lookup started.
///
/// \param InBaseClass whether this declaration was found in base
/// class of the context we searched.
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
bool InBaseClass) = 0;
};

Просмотреть файл

@ -3693,6 +3693,7 @@ public:
bool ForceCheck = false,
bool ForceUnprivileged = false);
void CheckLookupAccess(const LookupResult &R);
bool IsSimplyAccessible(NamedDecl *decl, CXXRecordDecl *Class);
void HandleDependentAccessCheck(const DependentDiagnostic &DD,
const MultiLevelTemplateArgumentList &TemplateArgs);

Просмотреть файл

@ -376,7 +376,7 @@ PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
}
}
void CodeCompletionResult::computeCursorKindAndAvailability() {
void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) {
switch (Kind) {
case RK_Declaration:
// Set the availability based on attributes.
@ -418,6 +418,9 @@ void CodeCompletionResult::computeCursorKindAndAvailability() {
// Do nothing: Patterns can come with cursor kinds!
break;
}
if (!Accessible)
Availability = CXAvailability_NotAccessible;
}
/// \brief Retrieve the name that should be used to order a result.

Просмотреть файл

@ -1641,6 +1641,27 @@ void Sema::CheckLookupAccess(const LookupResult &R) {
}
}
/// Checks access to Decl from the given class. The check will take access
/// specifiers into account, but no member access expressions and such.
///
/// \param Decl the declaration to check if it can be accessed
/// \param Class the class/context from which to start the search
/// \return true if the Decl is accessible from the Class, false otherwise.
bool Sema::IsSimplyAccessible(NamedDecl *Decl, CXXRecordDecl *Class) {
if (!Class)
return true;
QualType qType = Class->getTypeForDecl()->getCanonicalTypeInternal();
AccessTarget Entity(Context, AccessedEntity::Member, Class,
DeclAccessPair::make(Decl, Decl->getAccess()),
qType);
if (Entity.getAccess() == AS_public)
return true;
EffectiveContext EC(CurContext);
return ::IsAccessible(*this, EC, Entity) != ::AR_inaccessible;
}
void Sema::ActOnStartSuppressingAccessChecks() {
assert(!SuppressAccessChecking &&
"Tried to start access check suppression when already started.");

Просмотреть файл

@ -1186,8 +1186,16 @@ namespace {
CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
: Results(Results), CurContext(CurContext) { }
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool InBaseClass) {
Results.AddResult(ND, CurContext, Hiding, InBaseClass);
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
bool InBaseClass) {
bool Accessible = true;
if (Ctx) {
if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx))
Accessible = Results.getSema().IsSimplyAccessible(ND, Class);
// FIXME: ObjC access checks are missing.
}
ResultBuilder::Result Result(ND, 0, false, Accessible);
Results.AddResult(Result, CurContext, Hiding, InBaseClass);
}
};
}

Просмотреть файл

@ -2701,7 +2701,7 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
D != DEnd; ++D) {
if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) {
if (Result.isAcceptableDecl(ND)) {
Consumer.FoundDecl(ND, Visited.checkHidden(ND), InBaseClass);
Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
Visited.add(ND);
}
} else if (ObjCForwardProtocolDecl *ForwardProto
@ -2712,14 +2712,15 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
P != PEnd;
++P) {
if (Result.isAcceptableDecl(*P)) {
Consumer.FoundDecl(*P, Visited.checkHidden(*P), InBaseClass);
Consumer.FoundDecl(*P, Visited.checkHidden(*P), Ctx, InBaseClass);
Visited.add(*P);
}
}
} else if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*D)) {
ObjCInterfaceDecl *IFace = Class->getForwardInterfaceDecl();
if (Result.isAcceptableDecl(IFace)) {
Consumer.FoundDecl(IFace, Visited.checkHidden(IFace), InBaseClass);
Consumer.FoundDecl(IFace, Visited.checkHidden(IFace), Ctx,
InBaseClass);
Visited.add(IFace);
}
}
@ -2861,7 +2862,7 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result,
D != DEnd; ++D) {
if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
if (Result.isAcceptableDecl(ND)) {
Consumer.FoundDecl(ND, Visited.checkHidden(ND), false);
Consumer.FoundDecl(ND, Visited.checkHidden(ND), 0, false);
Visited.add(ND);
}
}
@ -3043,7 +3044,8 @@ public:
delete I->second;
}
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool InBaseClass);
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
bool InBaseClass);
void FoundName(StringRef Name);
void addKeywordResult(StringRef Keyword);
void addName(StringRef Name, NamedDecl *ND, unsigned Distance,
@ -3074,7 +3076,7 @@ public:
}
void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
bool InBaseClass) {
DeclContext *Ctx, bool InBaseClass) {
// Don't consider hidden names for typo correction.
if (Hiding)
return;

Просмотреть файл

@ -0,0 +1,89 @@
struct X {
int member1;
void func1();
protected:
int member2;
void func2();
private:
int member3;
void func3();
};
struct Y: protected X {
void doSomething();
};
class Z {
public:
int member1;
void func1();
protected:
int member2;
void func2();
private:
int member3;
void func3();
};
void Y::doSomething() {
// RUN: c-index-test -code-completion-at=%s:30:9 %s | FileCheck -check-prefix=CHECK-SUPER-ACCESS %s
this->;
Z that;
// RUN: c-index-test -code-completion-at=%s:34:8 %s | FileCheck -check-prefix=CHECK-ACCESS %s
that.
}
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{TypedText doSomething}{LeftParen (}{RightParen )} (34)
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{Informative X::}{TypedText func1}{LeftParen (}{RightParen )} (36)
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{Informative X::}{TypedText func2}{LeftParen (}{RightParen )} (36) (inaccessible)
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType void}{Informative X::}{TypedText func3}{LeftParen (}{RightParen )} (36) (inaccessible)
// CHECK-SUPER-ACCESS: FieldDecl:{ResultType int}{Informative X::}{TypedText member1} (37)
// CHECK-SUPER-ACCESS: FieldDecl:{ResultType int}{Informative X::}{TypedText member2} (37) (inaccessible)
// CHECK-SUPER-ACCESS: FieldDecl:{ResultType int}{Informative X::}{TypedText member3} (37) (inaccessible)
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType Y &}{TypedText operator=}{LeftParen (}{Placeholder const Y &}{RightParen )} (34)
// CHECK-SUPER-ACCESS: CXXMethod:{ResultType X &}{Text X::}{TypedText operator=}{LeftParen (}{Placeholder const X &}{RightParen )} (36)
// CHECK-SUPER-ACCESS: StructDecl:{TypedText X}{Text ::} (77)
// CHECK-SUPER-ACCESS: StructDecl:{TypedText Y}{Text ::} (75)
// CHECK-SUPER-ACCESS: CXXDestructor:{ResultType void}{Informative X::}{TypedText ~X}{LeftParen (}{RightParen )} (36)
// CHECK-SUPER-ACCESS: CXXDestructor:{ResultType void}{TypedText ~Y}{LeftParen (}{RightParen )} (34)
// CHECK-ACCESS: CXXMethod:{ResultType void}{TypedText func1}{LeftParen (}{RightParen )} (34)
// CHECK-ACCESS: CXXMethod:{ResultType void}{TypedText func2}{LeftParen (}{RightParen )} (34) (inaccessible)
// CHECK-ACCESS: CXXMethod:{ResultType void}{TypedText func3}{LeftParen (}{RightParen )} (34) (inaccessible)
// CHECK-ACCESS: FieldDecl:{ResultType int}{TypedText member1} (35)
// CHECK-ACCESS: FieldDecl:{ResultType int}{TypedText member2} (35) (inaccessible)
// CHECK-ACCESS: FieldDecl:{ResultType int}{TypedText member3} (35) (inaccessible)
// CHECK-ACCESS: CXXMethod:{ResultType Z &}{TypedText operator=}{LeftParen (}{Placeholder const Z &}{RightParen )} (34)
// CHECK-ACCESS: ClassDecl:{TypedText Z}{Text ::} (75)
// CHECK-ACCESS: CXXDestructor:{ResultType void}{TypedText ~Z}{LeftParen (}{RightParen )} (34)
class P {
protected:
int member;
};
class Q : public P {
public:
using P::member;
};
void f(P x, Q y) {
// RUN: c-index-test -code-completion-at=%s:73:5 %s | FileCheck -check-prefix=CHECK-USING-INACCESSIBLE %s
x.; // member is inaccessible
// RUN: c-index-test -code-completion-at=%s:75:5 %s | FileCheck -check-prefix=CHECK-USING-ACCESSIBLE %s
y.; // member is accessible
}
// CHECK-USING-INACCESSIBLE: FieldDecl:{ResultType int}{TypedText member} (35) (inaccessible)
// CHECK-USING-INACCESSIBLE: CXXMethod:{ResultType P &}{TypedText operator=}{LeftParen (}{Placeholder const P &}{RightParen )} (34)
// CHECK-USING-INACCESSIBLE: ClassDecl:{TypedText P}{Text ::} (75)
// CHECK-USING-INACCESSIBLE: CXXDestructor:{ResultType void}{TypedText ~P}{LeftParen (}{RightParen )} (34)
// CHECK-USING-ACCESSIBLE: FieldDecl:{ResultType int}{TypedText member} (35)
// CHECK-USING-ACCESSIBLE: CXXMethod:{ResultType Q &}{TypedText operator=}{LeftParen (}{Placeholder const Q &}{RightParen )} (34)
// CHECK-USING-ACCESSIBLE: CXXMethod:{ResultType P &}{Text P::}{TypedText operator=}{LeftParen (}{Placeholder const P &}{RightParen )} (36)
// CHECK-USING-ACCESSIBLE: ClassDecl:{TypedText P}{Text ::} (77)
// CHECK-USING-ACCESSIBLE: ClassDecl:{TypedText Q}{Text ::} (75)
// CHECK-USING-ACCESSIBLE: CXXDestructor:{ResultType void}{Informative P::}{TypedText ~P}{LeftParen (}{RightParen )} (36)
// CHECK-USING-ACCESSIBLE: CXXDestructor:{ResultType void}{TypedText ~Q}{LeftParen (}{RightParen )} (34)

Просмотреть файл

@ -238,6 +238,10 @@ static void PrintCursor(CXCursor Cursor) {
case CXAvailability_NotAvailable:
printf(" (unavailable)");
break;
case CXAvailability_NotAccessible:
printf(" (inaccessible)");
break;
}
if (clang_CXXMethod_isStatic(Cursor))
@ -1051,6 +1055,10 @@ void print_completion_result(CXCompletionResult *completion_result,
case CXAvailability_NotAvailable:
fprintf(file, " (unavailable)");
break;
case CXAvailability_NotAccessible:
fprintf(file, " (inaccessible)");
break;
}
fprintf(file, "\n");
}