class ParentMap {
void* Impl;
+ bool IsSemantic;
public:
- ParentMap(Stmt* ASTRoot);
+ ParentMap(Stmt* ASTRoot, bool isSemantic = false);
~ParentMap();
/// \brief Adds and/or updates the parent/child-relations of the complete
bool builtCFG, builtCompleteCFG;
OwningPtr<ParentMap> PM;
+ OwningPtr<ParentMap> SemanticPM;
OwningPtr<PseudoConstantAnalysis> PCA;
OwningPtr<CFGReverseBlockReachabilityAnalysis> CFA;
bool isCFGBuilt() const { return builtCFG; }
ParentMap &getParentMap();
+
+ ParentMap &getSemanticParentMap();
+
PseudoConstantAnalysis *getPseudoConstantAnalysis();
typedef const VarDecl * const * referenced_decls_iterator;
return getAnalysisDeclContext()->getParentMap();
}
+ ParentMap &getSemanticParentMap() const {
+ return getAnalysisDeclContext()->getSemanticParentMap();
+ }
+
const ImplicitParamDecl *getSelfDecl() const {
return Ctx->getSelfDecl();
}
OV_Opaque
};
-static void BuildParentMap(MapTy& M, Stmt* S,
+static void BuildParentMap(MapTy& M, Stmt* S, bool isSemantic,
OpaqueValueMode OVMode = OV_Transparent) {
switch (S->getStmtClass()) {
assert(OVMode == OV_Transparent && "Should not appear alongside OVEs");
PseudoObjectExpr *POE = cast<PseudoObjectExpr>(S);
- M[POE->getSyntacticForm()] = S;
- BuildParentMap(M, POE->getSyntacticForm(), OV_Transparent);
+ if (!isSemantic) {
+ M[POE->getSyntacticForm()] = S;
+ BuildParentMap(M, POE->getSyntacticForm(), OV_Transparent);
+ }
for (PseudoObjectExpr::semantics_iterator I = POE->semantics_begin(),
E = POE->semantics_end();
I != E; ++I) {
M[*I] = S;
- BuildParentMap(M, *I, OV_Opaque);
+ BuildParentMap(M, *I, isSemantic,
+ isSemantic ? OV_Transparent : OV_Opaque);
}
break;
}
BinaryConditionalOperator *BCO = cast<BinaryConditionalOperator>(S);
M[BCO->getCommon()] = S;
- BuildParentMap(M, BCO->getCommon(), OV_Transparent);
+ BuildParentMap(M, BCO->getCommon(), isSemantic, OV_Transparent);
M[BCO->getCond()] = S;
- BuildParentMap(M, BCO->getCond(), OV_Opaque);
+ BuildParentMap(M, BCO->getCond(), isSemantic, OV_Opaque);
M[BCO->getTrueExpr()] = S;
- BuildParentMap(M, BCO->getTrueExpr(), OV_Opaque);
+ BuildParentMap(M, BCO->getTrueExpr(), isSemantic, OV_Opaque);
M[BCO->getFalseExpr()] = S;
- BuildParentMap(M, BCO->getFalseExpr(), OV_Transparent);
+ BuildParentMap(M, BCO->getFalseExpr(), isSemantic, OV_Transparent);
break;
}
if (OVMode == OV_Transparent) {
OpaqueValueExpr *OVE = cast<OpaqueValueExpr>(S);
M[OVE->getSourceExpr()] = S;
- BuildParentMap(M, OVE->getSourceExpr(), OV_Transparent);
+ BuildParentMap(M, OVE->getSourceExpr(), isSemantic, OV_Transparent);
}
break;
default:
for (Stmt::child_range I = S->children(); I; ++I) {
if (*I) {
M[*I] = S;
- BuildParentMap(M, *I, OVMode);
+ BuildParentMap(M, *I, isSemantic, OVMode);
}
}
break;
}
}
-ParentMap::ParentMap(Stmt* S) : Impl(0) {
+ParentMap::ParentMap(Stmt* S, bool isSemantic) : Impl(0),
+ IsSemantic(isSemantic) {
if (S) {
MapTy *M = new MapTy();
- BuildParentMap(*M, S);
+ BuildParentMap(*M, S, isSemantic);
Impl = M;
}
}
void ParentMap::addStmt(Stmt* S) {
if (S) {
- BuildParentMap(*(MapTy*) Impl, S);
+ BuildParentMap(*(MapTy*) Impl, S, IsSemantic);
}
}
getCFG()->dump(getASTContext().getLangOpts(), ShowColors);
}
+static ParentMap *constructParentMap(bool isSemantic,
+ Stmt *Body,
+ const Decl *D) {
+ ParentMap *PM = new ParentMap(Body, isSemantic);
+ if (const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(D)) {
+ for (CXXConstructorDecl::init_const_iterator I = C->init_begin(),
+ E = C->init_end();
+ I != E; ++I) {
+ PM->addStmt((*I)->getInit());
+ }
+ }
+ return PM;
+}
+
ParentMap &AnalysisDeclContext::getParentMap() {
if (!PM) {
- PM.reset(new ParentMap(getBody()));
- if (const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(getDecl())) {
- for (CXXConstructorDecl::init_const_iterator I = C->init_begin(),
- E = C->init_end();
- I != E; ++I) {
- PM->addStmt((*I)->getInit());
- }
- }
+ PM.reset(constructParentMap(false, getBody(), getDecl()));
}
return *PM;
}
+ParentMap &AnalysisDeclContext::getSemanticParentMap() {
+ if (!SemanticPM) {
+ SemanticPM.reset(constructParentMap(true, getBody(), getDecl()));
+ }
+ return *SemanticPM;
+}
+
PseudoConstantAnalysis *AnalysisDeclContext::getPseudoConstantAnalysis() {
if (!PCA)
PCA.reset(new PseudoConstantAnalysis(getBody()));
typedef llvm::DenseSet<const PathDiagnosticCallPiece *>
OptimizedCallsSet;
+typedef llvm::DenseMap<const Stmt *,
+ Optional<const PseudoObjectExpr *> >
+ PseudoObjectExprMap;
+
+/// Return the PseudoObjectExpr that contains this statement (if any).
+static const PseudoObjectExpr *
+getContainingPseudoObjectExpr(PseudoObjectExprMap &PEM,
+ ParentMap &PM,
+ const Stmt *S) {
+ if (!S)
+ return 0;
+
+ Optional<const PseudoObjectExpr *> &Entry = PEM[S];
+ if (!Entry.hasValue()) {
+ const Stmt *Parent = PM.getParentIgnoreParens(S);
+ if (const PseudoObjectExpr *PE = dyn_cast_or_null<PseudoObjectExpr>(Parent))
+ Entry = PE;
+ else
+ Entry = getContainingPseudoObjectExpr(PEM, PM, Parent);
+ }
+ return Entry.getValue();
+}
+
+#if 0
+static void printPath(PathPieces &path, ParentMap &PM) {
+ unsigned index = 0;
+ for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ++I ) {
+ llvm::errs() << "[" << index++ << "]\n";
+ if (isa<PathDiagnosticCallPiece>(*I)) {
+ llvm::errs() << " CALL\n";
+ continue;
+ }
+ if (isa<PathDiagnosticEventPiece>(*I)) {
+ llvm::errs() << " EVENT\n";
+ continue;
+ }
+ if (const PathDiagnosticControlFlowPiece *CP = dyn_cast<PathDiagnosticControlFlowPiece>(*I)) {
+ llvm::errs() << " CONTROL\n";
+ const Stmt *s1Start = getLocStmt(CP->getStartLocation());
+ const Stmt *s1End = getLocStmt(CP->getEndLocation());
+ if (s1Start) {
+ s1Start->dump();
+ llvm::errs() << "PARENT: \n";
+ const Stmt *Parent = getStmtParent(s1Start, PM);
+ if (Parent) {
+ Parent->dump();
+ }
+ }
+ else {
+ llvm::errs() << "NULL\n";
+ }
+ llvm::errs() << " --------- ===== ----- \n";
+ if (s1End) {
+ s1End->dump();
+ llvm::errs() << "PARENT: \n";
+ const Stmt *Parent = getStmtParent(s1End, PM);
+ if (Parent) {
+ Parent->dump();
+ }
+ }
+ else {
+ llvm::errs() << "NULL\n";
+ }
+ }
+ }
+}
+#endif
+
static bool optimizeEdges(PathPieces &path, SourceManager &SM,
OptimizedCallsSet &OCS,
- LocationContextMap &LCM) {
+ LocationContextMap &LCM,
+ PseudoObjectExprMap &PEM) {
bool hasChanges = false;
const LocationContext *LC = LCM[&path];
assert(LC);
// Record the fact that a call has been optimized so we only do the
// effort once.
if (!OCS.count(CallI)) {
- while (optimizeEdges(CallI->path, SM, OCS, LCM)) {}
+ while (optimizeEdges(CallI->path, SM, OCS, LCM, PEM)) {}
OCS.insert(CallI);
}
++I;
continue;
}
- ParentMap &PM = LC->getParentMap();
+ ParentMap &PM = LC->getSemanticParentMap();
const Stmt *s1Start = getLocStmt(PieceI->getStartLocation());
const Stmt *s1End = getLocStmt(PieceI->getEndLocation());
const Stmt *level1 = getStmtParent(s1Start, PM);
}
}
+ // Prune out edges for pseudo object expressions.
+ //
+ // Case 1: incoming into a pseudo expr.
+ //
+ // An edge into a subexpression of a pseudo object expression
+ // should be replaced with an edge to the pseudo object expression
+ // itself.
+ const PseudoObjectExpr *PE = getContainingPseudoObjectExpr(PEM, PM, s1End);
+ if (PE) {
+ PathDiagnosticLocation L(PE, SM, LC);
+ PieceI->setEndLocation(L);
+ // Do not increment the iterator. It is possible we will match again.
+ hasChanges = true;
+ continue;
+ }
+
+ // Prune out edges for pseudo object expressions.
+ //
+ // Case 2: outgoing from a pseudo expr.
+ //
+ // An edge into a subexpression of a pseudo object expression
+ // should be replaced with an edge to the pseudo object expression
+ // itself.
+ PE = getContainingPseudoObjectExpr(PEM, PM, s1Start);
+ if (PE) {
+ PathDiagnosticLocation L(PE, SM, LC);
+ PieceI->setStartLocation(L);
+ // Do not increment the iterator. It is possible we will match again.
+ hasChanges = true;
+ continue;
+ }
+
+ // Pattern match on two edges after this point.
PathPieces::iterator NextI = I; ++NextI;
if (NextI == E)
break;
// to an aesthetically pleasing subset that conveys the
// necessary information.
OptimizedCallsSet OCS;
- while (optimizeEdges(PD.getMutablePieces(), SM, OCS, LCM)) {}
+ PseudoObjectExprMap PEM;
+ while (optimizeEdges(PD.getMutablePieces(), SM, OCS, LCM, PEM)) {}
// Adjust edges into loop conditions to make them more uniform
// and aesthetically pleasing.