PathDiagnosticLocation now also wraps Decls.

llvm-svn: 68470
This commit is contained in:
Ted Kremenek 2009-04-06 22:33:35 +00:00
parent 1df12baca9
commit 92820d2d3d
2 changed files with 52 additions and 21 deletions

View File

@ -31,6 +31,7 @@ namespace clang {
class PathDiagnostic;
class Stmt;
class Decl;
class PathDiagnosticClient : public DiagnosticClient {
public:
@ -54,35 +55,40 @@ public:
class PathDiagnosticLocation {
private:
enum Kind { Range, SingleLoc, Statement } K;
enum Kind { RangeK, SingleLocK, StmtK, DeclK } K;
SourceRange R;
const Stmt *S;
const Decl *D;
const SourceManager *SM;
public:
PathDiagnosticLocation()
: K(SingleLoc), S(0), SM(0) {}
: K(SingleLocK), S(0), D(0), SM(0) {}
PathDiagnosticLocation(FullSourceLoc L)
: K(SingleLoc), R(L, L), S(0), SM(&L.getManager()) {}
: K(SingleLocK), R(L, L), S(0), D(0), SM(&L.getManager()) {}
PathDiagnosticLocation(const Stmt *s, const SourceManager &sm)
: K(Statement), S(s), SM(&sm) {}
: K(StmtK), S(s), D(0), SM(&sm) {}
PathDiagnosticLocation(SourceRange r, const SourceManager &sm)
: K(Range), R(r), S(0), SM(&sm) {}
: K(RangeK), R(r), S(0), D(0), SM(&sm) {}
PathDiagnosticLocation(const Decl *d, const SourceManager &sm)
: K(DeclK), S(0), D(d), SM(&sm) {}
bool operator==(const PathDiagnosticLocation &X) const {
return K == X.K && R == X.R && S == X.S;
return K == X.K && R == X.R && S == X.S && D == X.D;
}
bool operator!=(const PathDiagnosticLocation &X) const {
return K != X.K || R != X.R || S != X.S;
return K != X.K || R != X.R || S != X.S || D != X.D;;
}
PathDiagnosticLocation& operator=(const PathDiagnosticLocation &X) {
K = X.K;
R = X.R;
S = X.S;
D = X.D;
SM = X.SM;
return *this;
}
@ -94,20 +100,15 @@ public:
FullSourceLoc asLocation() const;
SourceRange asRange() const;
const Stmt *asStmt() const { assert(isValid()); return S; }
const Decl *asDecl() const { assert(isValid()); return D; }
bool hasRange() const { return K == Statement || K == Range; }
bool hasRange() const { return K == StmtK || K == RangeK || K == DeclK; }
void invalidate() {
*this = PathDiagnosticLocation();
}
void flatten() {
if (K == Statement) {
R = asRange();
K = Range;
S = 0;
}
}
void flatten();
const SourceManager& getManager() const { assert(isValid()); return *SM; }
};

View File

@ -13,6 +13,8 @@
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/Casting.h"
#include <sstream>
@ -144,11 +146,13 @@ FullSourceLoc PathDiagnosticLocation::asLocation() const {
// Note that we want a 'switch' here so that the compiler can warn us in
// case we add more cases.
switch (K) {
case SingleLoc:
case Range:
case SingleLocK:
case RangeK:
break;
case Statement:
case StmtK:
return FullSourceLoc(S->getLocStart(), const_cast<SourceManager&>(*SM));
case DeclK:
return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
}
return FullSourceLoc(R.getBegin(), const_cast<SourceManager&>(*SM));
@ -159,13 +163,39 @@ SourceRange PathDiagnosticLocation::asRange() const {
// Note that we want a 'switch' here so that the compiler can warn us in
// case we add more cases.
switch (K) {
case SingleLoc:
case Range:
case SingleLocK:
case RangeK:
break;
case Statement:
case StmtK:
return S->getSourceRange();
case DeclK:
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
return MD->getSourceRange();
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
return FD->getBody()->getSourceRange();
else {
SourceLocation L = D->getLocation();
return SourceRange(L, L);
}
}
return R;
}
void PathDiagnosticLocation::flatten() {
if (K == StmtK) {
R = asRange();
K = RangeK;
S = 0;
D = 0;
}
else if (K == DeclK) {
SourceLocation L = D->getLocation();
R = SourceRange(L, L);
K = SingleLocK;
S = 0;
D = 0;
}
}