зеркало из https://github.com/microsoft/clang-1.git
Resolve a source location that is inside a type declarator.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83098 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
eb66759e9a
Коммит
ef6cd6712c
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "clang/Index/Utils.h"
|
||||
#include "clang/Index/ASTLocation.h"
|
||||
#include "clang/AST/TypeLoc.h"
|
||||
#include "clang/AST/DeclVisitor.h"
|
||||
#include "clang/AST/StmtVisitor.h"
|
||||
#include "clang/Lex/Lexer.h"
|
||||
|
@ -29,6 +30,8 @@ class VISIBILITY_HIDDEN LocResolverBase {
|
|||
protected:
|
||||
ASTContext &Ctx;
|
||||
SourceLocation Loc;
|
||||
|
||||
ASTLocation ResolveInDeclarator(Decl *D, Stmt *Stm, DeclaratorInfo *DInfo);
|
||||
|
||||
enum RangePos {
|
||||
BeforeLoc,
|
||||
|
@ -37,21 +40,29 @@ protected:
|
|||
};
|
||||
|
||||
RangePos CheckRange(SourceRange Range);
|
||||
RangePos CheckRange(Decl *D) { return CheckRange(D->getSourceRange()); }
|
||||
RangePos CheckRange(DeclaratorInfo *DInfo);
|
||||
RangePos CheckRange(Decl *D) {
|
||||
if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D))
|
||||
if (ContainsLocation(DD->getDeclaratorInfo()))
|
||||
return ContainsLoc;
|
||||
|
||||
return CheckRange(D->getSourceRange());
|
||||
}
|
||||
RangePos CheckRange(Stmt *Node) { return CheckRange(Node->getSourceRange()); }
|
||||
RangePos CheckRange(TypeLoc TL) { return CheckRange(TL.getSourceRange()); }
|
||||
|
||||
template <typename T>
|
||||
bool isBeforeLocation(T *Node) {
|
||||
bool isBeforeLocation(T Node) {
|
||||
return CheckRange(Node) == BeforeLoc;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool ContainsLocation(T *Node) {
|
||||
bool ContainsLocation(T Node) {
|
||||
return CheckRange(Node) == ContainsLoc;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool isAfterLocation(T *Node) {
|
||||
bool isAfterLocation(T Node) {
|
||||
return CheckRange(Node) == AfterLoc;
|
||||
}
|
||||
|
||||
|
@ -94,12 +105,29 @@ public:
|
|||
|
||||
ASTLocation VisitDeclContext(DeclContext *DC);
|
||||
ASTLocation VisitTranslationUnitDecl(TranslationUnitDecl *TU);
|
||||
ASTLocation VisitDeclaratorDecl(DeclaratorDecl *D);
|
||||
ASTLocation VisitVarDecl(VarDecl *D);
|
||||
ASTLocation VisitFunctionDecl(FunctionDecl *D);
|
||||
ASTLocation VisitObjCMethodDecl(ObjCMethodDecl *D);
|
||||
ASTLocation VisitDecl(Decl *D);
|
||||
};
|
||||
|
||||
class TypeLocResolver : public LocResolverBase,
|
||||
public TypeLocVisitor<TypeLocResolver, ASTLocation> {
|
||||
Decl * const ParentDecl;
|
||||
|
||||
public:
|
||||
TypeLocResolver(ASTContext &ctx, SourceLocation loc, Decl *pd)
|
||||
: LocResolverBase(ctx, loc), ParentDecl(pd) { }
|
||||
|
||||
ASTLocation VisitTypedefLoc(TypedefLoc TL);
|
||||
ASTLocation VisitFunctionLoc(FunctionLoc TL);
|
||||
ASTLocation VisitArrayLoc(ArrayLoc TL);
|
||||
ASTLocation VisitObjCInterfaceLoc(ObjCInterfaceLoc TL);
|
||||
ASTLocation VisitObjCProtocolListLoc(ObjCProtocolListLoc TL);
|
||||
ASTLocation VisitTypeLoc(TypeLoc TL);
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
ASTLocation
|
||||
|
@ -237,6 +265,15 @@ ASTLocation DeclLocResolver::VisitFunctionDecl(FunctionDecl *D) {
|
|||
return StmtLocResolver(Ctx, Loc, D).Visit(Body);
|
||||
}
|
||||
|
||||
ASTLocation DeclLocResolver::VisitDeclaratorDecl(DeclaratorDecl *D) {
|
||||
assert(ContainsLocation(D) &&
|
||||
"Should visit only after verifying that loc is in range");
|
||||
if (ContainsLocation(D->getDeclaratorInfo()))
|
||||
return ResolveInDeclarator(D, /*Stmt=*/0, D->getDeclaratorInfo());
|
||||
|
||||
return ASTLocation(D);
|
||||
}
|
||||
|
||||
ASTLocation DeclLocResolver::VisitVarDecl(VarDecl *D) {
|
||||
assert(ContainsLocation(D) &&
|
||||
"Should visit only after verifying that loc is in range");
|
||||
|
@ -245,6 +282,9 @@ ASTLocation DeclLocResolver::VisitVarDecl(VarDecl *D) {
|
|||
Expr *Init = D->getInit();
|
||||
if (Init && ContainsLocation(Init))
|
||||
return StmtLocResolver(Ctx, Loc, D).Visit(Init);
|
||||
|
||||
if (ContainsLocation(D->getDeclaratorInfo()))
|
||||
return ResolveInDeclarator(D, 0, D->getDeclaratorInfo());
|
||||
|
||||
return ASTLocation(D);
|
||||
}
|
||||
|
@ -306,6 +346,96 @@ ASTLocation DeclLocResolver::VisitDecl(Decl *D) {
|
|||
return ASTLocation(D);
|
||||
}
|
||||
|
||||
ASTLocation TypeLocResolver::VisitTypedefLoc(TypedefLoc TL) {
|
||||
assert(ContainsLocation(TL) &&
|
||||
"Should visit only after verifying that loc is in range");
|
||||
if (ContainsLocation(TL.getNameLoc()))
|
||||
return ASTLocation(ParentDecl, TL.getTypedefDecl(), TL.getNameLoc());
|
||||
return ASTLocation(ParentDecl, TL);
|
||||
}
|
||||
|
||||
ASTLocation TypeLocResolver::VisitFunctionLoc(FunctionLoc TL) {
|
||||
assert(ContainsLocation(TL) &&
|
||||
"Should visit only after verifying that loc is in range");
|
||||
|
||||
for (unsigned i = 0; i != TL.getNumArgs(); ++i) {
|
||||
ParmVarDecl *Parm = TL.getArg(i);
|
||||
RangePos RP = CheckRange(Parm);
|
||||
if (RP == AfterLoc)
|
||||
break;
|
||||
if (RP == ContainsLoc)
|
||||
return DeclLocResolver(Ctx, Loc).Visit(Parm);
|
||||
}
|
||||
|
||||
return ASTLocation(ParentDecl, TL);
|
||||
}
|
||||
|
||||
ASTLocation TypeLocResolver::VisitArrayLoc(ArrayLoc TL) {
|
||||
assert(ContainsLocation(TL) &&
|
||||
"Should visit only after verifying that loc is in range");
|
||||
|
||||
Expr *E = TL.getSizeExpr();
|
||||
if (E && ContainsLocation(E))
|
||||
return StmtLocResolver(Ctx, Loc, ParentDecl).Visit(E);
|
||||
|
||||
return ASTLocation(ParentDecl, TL);
|
||||
}
|
||||
|
||||
ASTLocation TypeLocResolver::VisitObjCInterfaceLoc(ObjCInterfaceLoc TL) {
|
||||
assert(ContainsLocation(TL) &&
|
||||
"Should visit only after verifying that loc is in range");
|
||||
if (ContainsLocation(TL.getNameLoc()))
|
||||
return ASTLocation(ParentDecl, TL.getIFaceDecl(), TL.getNameLoc());
|
||||
return ASTLocation(ParentDecl, TL);
|
||||
}
|
||||
|
||||
ASTLocation TypeLocResolver::VisitObjCProtocolListLoc(ObjCProtocolListLoc TL) {
|
||||
assert(ContainsLocation(TL) &&
|
||||
"Should visit only after verifying that loc is in range");
|
||||
|
||||
for (unsigned i = 0; i != TL.getNumProtocols(); ++i) {
|
||||
SourceLocation L = TL.getProtocolLoc(i);
|
||||
RangePos RP = CheckRange(L);
|
||||
if (RP == AfterLoc)
|
||||
break;
|
||||
if (RP == ContainsLoc)
|
||||
return ASTLocation(ParentDecl, TL.getProtocol(i), L);
|
||||
}
|
||||
|
||||
return ASTLocation(ParentDecl, TL);
|
||||
}
|
||||
|
||||
ASTLocation TypeLocResolver::VisitTypeLoc(TypeLoc TL) {
|
||||
assert(ContainsLocation(TL) &&
|
||||
"Should visit only after verifying that loc is in range");
|
||||
return ASTLocation(ParentDecl, TL);
|
||||
}
|
||||
|
||||
ASTLocation LocResolverBase::ResolveInDeclarator(Decl *D, Stmt *Stm,
|
||||
DeclaratorInfo *DInfo) {
|
||||
assert(ContainsLocation(DInfo) &&
|
||||
"Should visit only after verifying that loc is in range");
|
||||
|
||||
TypeLocResolver(Ctx, Loc, D);
|
||||
for (TypeLoc TL = DInfo->getTypeLoc(); TL; TL = TL.getNextTypeLoc())
|
||||
if (ContainsLocation(TL))
|
||||
return TypeLocResolver(Ctx, Loc, D).Visit(TL);
|
||||
|
||||
assert(0 && "Should have found the loc in a typeloc");
|
||||
return ASTLocation(D, Stm);
|
||||
}
|
||||
|
||||
LocResolverBase::RangePos LocResolverBase::CheckRange(DeclaratorInfo *DInfo) {
|
||||
if (!DInfo)
|
||||
return BeforeLoc; // Keep looking.
|
||||
|
||||
for (TypeLoc TL = DInfo->getTypeLoc(); TL; TL = TL.getNextTypeLoc())
|
||||
if (ContainsLocation(TL))
|
||||
return ContainsLoc;
|
||||
|
||||
return BeforeLoc; // Keep looking.
|
||||
}
|
||||
|
||||
LocResolverBase::RangePos LocResolverBase::CheckRange(SourceRange Range) {
|
||||
if (!Range.isValid())
|
||||
return BeforeLoc; // Keep looking.
|
||||
|
|
Загрузка…
Ссылка в новой задаче