Comment AST: add DeclInfo to store information about the declaration. Sema was

already extracting most of this, but discarding at the end of semantic analysis.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161140 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dmitri Gribenko 2012-08-01 23:08:09 +00:00
Родитель 2ff84b514e
Коммит 1ca7ecc885
4 изменённых файлов: 155 добавлений и 101 удалений

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

@ -19,6 +19,10 @@
#include "llvm/ADT/StringRef.h"
namespace clang {
class Decl;
class ParmVarDecl;
class TemplateParameterList;
namespace comments {
/// Any part of the comment.
@ -906,14 +910,61 @@ public:
}
};
/// Information about the declaration, useful to clients of FullComment.
struct DeclInfo {
/// Declaration the comment is attached to. Should not be NULL.
const Decl *ThisDecl;
/// Parameters that can be referenced by \\param if \c ThisDecl is something
/// that we consider a "function".
ArrayRef<const ParmVarDecl *> ParamVars;
/// Template parameters that can be referenced by \\tparam if \c ThisDecl is
/// a template.
const TemplateParameterList *TemplateParameters;
/// If false, only \c ThisDecl is valid.
unsigned IsFilled : 1;
/// Is \c ThisDecl something that we consider a "function".
unsigned IsFunctionDecl : 1;
/// Is \c ThisDecl something that we consider a "class".
unsigned IsClassDecl : 1;
/// Is \c ThisDecl a template declaration.
unsigned IsTemplateDecl : 1;
/// Is \c ThisDecl a template specialization.
unsigned IsTemplateSpecialization : 1;
/// Is \c ThisDecl a template partial specialization.
/// Never true if \c IsFunctionDecl is true.
unsigned IsTemplatePartialSpecialization : 1;
/// Is \c ThisDecl a non-static member function of C++ class or
/// instance method of ObjC class.
/// Can be true only if \c IsFunctionDecl is true.
unsigned IsInstanceMethod : 1;
/// Is \c ThisDecl a static member function of C++ class or
/// class method of ObjC class.
/// Can be true only if \c IsFunctionDecl is true.
unsigned IsClassMethod : 1;
void fill();
};
/// A full comment attached to a declaration, contains block content.
class FullComment : public Comment {
llvm::ArrayRef<BlockContentComment *> Blocks;
DeclInfo *ThisDeclInfo;
public:
FullComment(llvm::ArrayRef<BlockContentComment *> Blocks) :
FullComment(llvm::ArrayRef<BlockContentComment *> Blocks, DeclInfo *D) :
Comment(FullCommentKind, SourceLocation(), SourceLocation()),
Blocks(Blocks) {
Blocks(Blocks), ThisDeclInfo(D) {
if (Blocks.empty())
return;
@ -935,6 +986,16 @@ public:
child_iterator child_end() const {
return reinterpret_cast<child_iterator>(Blocks.end());
}
const Decl *getDecl() const LLVM_READONLY {
return ThisDeclInfo->ThisDecl;
}
const DeclInfo *getDeclInfo() const LLVM_READONLY {
if (!ThisDeclInfo->IsFilled)
ThisDeclInfo->fill();
return ThisDeclInfo;
}
};
} // end namespace comments

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

@ -24,9 +24,6 @@
namespace clang {
class Decl;
class FunctionDecl;
class ParmVarDecl;
class TemplateParameterList;
class SourceMgr;
namespace comments {
@ -43,45 +40,22 @@ class Sema {
DiagnosticsEngine &Diags;
/// Declaration this comment is attached to.
const Decl *ThisDecl;
/// Parameters that can be referenced by \\param if \c ThisDecl is something
/// that we consider a "function".
/// Contains a valid value if \c IsThisDeclInspected is true.
ArrayRef<const ParmVarDecl *> ParamVars;
/// Information about the declaration this comment is attached to.
DeclInfo *ThisDeclInfo;
/// Comment AST nodes that correspond to \c ParamVars for which we have
/// found a \\param command or NULL if no documentation was found so far.
///
/// Has correct size and contains valid values if \c IsThisDeclInspected is
/// Has correct size and contains valid values if \c DeclInfo->IsFilled is
/// true.
llvm::SmallVector<ParamCommandComment *, 8> ParamVarDocs;
/// Template parameters that can be referenced by \\tparam if \c ThisDecl is
/// a template.
///
/// Contains a valid value if \c IsThisDeclInspected is true.
const TemplateParameterList *TemplateParameters;
/// Comment AST nodes that correspond to parameter names in
/// \c TemplateParameters.
///
/// Contains a valid value if \c IsThisDeclInspected is true.
/// Contains a valid value if \c DeclInfo->IsFilled is true.
llvm::StringMap<TParamCommandComment *> TemplateParameterDocs;
/// True if we extracted all important information from \c ThisDecl into
/// \c Sema members.
unsigned IsThisDeclInspected : 1;
/// Is \c ThisDecl something that we consider a "function".
/// Contains a valid value if \c IsThisDeclInspected is true.
unsigned IsFunctionDecl : 1;
/// Is \c ThisDecl a template declaration.
/// Contains a valid value if \c IsThisDeclInspected is true.
unsigned IsTemplateDecl : 1;
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
return Diags.Report(Loc, DiagID);
}
@ -212,8 +186,8 @@ public:
ArrayRef<const ParmVarDecl *> getParamVars();
/// Extract all important semantic information from \c ThisDecl into
/// \c Sema members.
/// Extract all important semantic information from
/// \c ThisDeclInfo->ThisDecl into \c ThisDeclInfo members.
void inspectThisDecl();
/// Returns index of a function parameter with a given name.

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

@ -8,6 +8,9 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/Comment.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@ -134,5 +137,66 @@ const char *ParamCommandComment::getDirectionAsString(PassDirection D) {
llvm_unreachable("unknown PassDirection");
}
void DeclInfo::fill() {
assert(!IsFilled);
// Set defaults.
IsFunctionDecl = false;
IsTemplateDecl = false;
IsTemplateSpecialization = false;
IsTemplatePartialSpecialization = false;
IsInstanceMethod = false;
IsClassMethod = false;
ParamVars = ArrayRef<const ParmVarDecl *>();
TemplateParameters = NULL;
if (!ThisDecl) {
// Defaults are OK.
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ThisDecl)) {
IsFunctionDecl = true;
ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(),
FD->getNumParams());
unsigned NumLists = FD->getNumTemplateParameterLists();
if (NumLists != 0) {
IsTemplateDecl = true;
IsTemplateSpecialization = true;
TemplateParameters =
FD->getTemplateParameterList(NumLists - 1);
}
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {
IsInstanceMethod = MD->isInstance();
IsClassMethod = !IsInstanceMethod;
}
} else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ThisDecl)) {
IsFunctionDecl = true;
ParamVars = ArrayRef<const ParmVarDecl *>(MD->param_begin(),
MD->param_size());
IsInstanceMethod = MD->isInstanceMethod();
IsClassMethod = !IsInstanceMethod;
} else if (const FunctionTemplateDecl *FTD =
dyn_cast<FunctionTemplateDecl>(ThisDecl)) {
IsFunctionDecl = true;
IsTemplateDecl = true;
const FunctionDecl *FD = FTD->getTemplatedDecl();
ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(),
FD->getNumParams());
TemplateParameters = FTD->getTemplateParameters();
} else if (const ClassTemplateDecl *CTD =
dyn_cast<ClassTemplateDecl>(ThisDecl)) {
IsTemplateDecl = true;
TemplateParameters = CTD->getTemplateParameters();
} else if (const ClassTemplatePartialSpecializationDecl *CTPSD =
dyn_cast<ClassTemplatePartialSpecializationDecl>(ThisDecl)) {
IsTemplateDecl = true;
IsTemplatePartialSpecialization = true;
TemplateParameters = CTPSD->getTemplateParameters();
} else if (isa<ClassTemplateSpecializationDecl>(ThisDecl)) {
IsTemplateDecl = true;
IsTemplateSpecialization = true;
}
IsFilled = true;
}
} // end namespace comments
} // end namespace clang

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

@ -10,7 +10,6 @@
#include "clang/AST/CommentSema.h"
#include "clang/AST/CommentDiagnostic.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/StringSwitch.h"
@ -20,12 +19,16 @@ namespace comments {
Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr,
DiagnosticsEngine &Diags) :
Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), ThisDecl(NULL),
IsThisDeclInspected(false) {
Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags),
ThisDeclInfo(NULL) {
}
void Sema::setDecl(const Decl *D) {
ThisDecl = D;
if (!D)
return;
ThisDeclInfo = new (Allocator) DeclInfo;
ThisDeclInfo->ThisDecl = D;
}
ParagraphComment *Sema::actOnParagraphComment(
@ -234,6 +237,8 @@ TParamCommandComment *Sema::actOnTParamCommandParamNameArg(
return Command;
}
const TemplateParameterList *TemplateParameters =
ThisDeclInfo->TemplateParameters;
SmallVector<unsigned, 2> Position;
if (resolveTParamReference(Arg, TemplateParameters, &Position)) {
Command->setPosition(copyArray(llvm::makeArrayRef(Position)));
@ -449,7 +454,7 @@ HTMLEndTagComment *Sema::actOnHTMLEndTag(SourceLocation LocBegin,
FullComment *Sema::actOnFullComment(
ArrayRef<BlockContentComment *> Blocks) {
return new (Allocator) FullComment(Blocks);
return new (Allocator) FullComment(Blocks, ThisDeclInfo);
}
void Sema::checkBlockCommandEmptyParagraph(BlockCommandComment *Command) {
@ -467,80 +472,30 @@ void Sema::checkBlockCommandEmptyParagraph(BlockCommandComment *Command) {
}
bool Sema::isFunctionDecl() {
if (!IsThisDeclInspected)
if (!ThisDeclInfo)
return false;
if (!ThisDeclInfo->IsFilled)
inspectThisDecl();
return IsFunctionDecl;
return ThisDeclInfo->IsFunctionDecl;
}
bool Sema::isTemplateDecl() {
if (!IsThisDeclInspected)
if (!ThisDeclInfo)
return false;
if (!ThisDeclInfo->IsFilled)
inspectThisDecl();
return IsTemplateDecl;
return ThisDeclInfo->IsTemplateDecl;
}
ArrayRef<const ParmVarDecl *> Sema::getParamVars() {
if (!IsThisDeclInspected)
if (!ThisDeclInfo->IsFilled)
inspectThisDecl();
return ParamVars;
return ThisDeclInfo->ParamVars;
}
void Sema::inspectThisDecl() {
assert(!IsThisDeclInspected);
if (!ThisDecl) {
IsFunctionDecl = false;
IsTemplateDecl = false;
ParamVars = ArrayRef<const ParmVarDecl *>();
TemplateParameters = NULL;
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ThisDecl)) {
IsFunctionDecl = true;
IsTemplateDecl = false;
ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(),
FD->getNumParams());
TemplateParameters = NULL;
unsigned NumLists = FD->getNumTemplateParameterLists();
if (NumLists != 0) {
IsTemplateDecl = true;
TemplateParameters = FD->getTemplateParameterList(NumLists - 1);
}
} else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ThisDecl)) {
IsFunctionDecl = true;
IsTemplateDecl = false;
ParamVars = ArrayRef<const ParmVarDecl *>(MD->param_begin(),
MD->param_size());
TemplateParameters = NULL;
} else if (const FunctionTemplateDecl *FTD =
dyn_cast<FunctionTemplateDecl>(ThisDecl)) {
IsFunctionDecl = true;
IsTemplateDecl = true;
const FunctionDecl *FD = FTD->getTemplatedDecl();
ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(),
FD->getNumParams());
TemplateParameters = FTD->getTemplateParameters();
} else if (const ClassTemplateDecl *CTD =
dyn_cast<ClassTemplateDecl>(ThisDecl)) {
IsFunctionDecl = false;
IsTemplateDecl = true;
ParamVars = ArrayRef<const ParmVarDecl *>();
TemplateParameters = CTD->getTemplateParameters();
} else if (const ClassTemplatePartialSpecializationDecl *CTPSD =
dyn_cast<ClassTemplatePartialSpecializationDecl>(ThisDecl)) {
IsFunctionDecl = false;
IsTemplateDecl = true;
ParamVars = ArrayRef<const ParmVarDecl *>();
TemplateParameters = CTPSD->getTemplateParameters();
} else if (isa<ClassTemplateSpecializationDecl>(ThisDecl)) {
IsFunctionDecl = false;
IsTemplateDecl = true;
ParamVars = ArrayRef<const ParmVarDecl *>();
TemplateParameters = NULL;
} else {
IsFunctionDecl = false;
IsTemplateDecl = false;
ParamVars = ArrayRef<const ParmVarDecl *>();
TemplateParameters = NULL;
}
ParamVarDocs.resize(ParamVars.size(), NULL);
IsThisDeclInspected = true;
ThisDeclInfo->fill();
ParamVarDocs.resize(ThisDeclInfo->ParamVars.size(), NULL);
}
unsigned Sema::resolveParmVarReference(StringRef Name,