[cfe-commits] r171828 - in /cfe/trunk: lib/ARCMigrate/TransProtectedScope.cpp test/ARCMT/checking.m test/ARCMT/protected-scope.m test/ARCMT/protected-scope.m.result

Aaron Ballman aaron at aaronballman.com
Tue Mar 12 10:48:56 PDT 2013


Have you had the chance to look into this?  It's still unresolved for
me, and causes the MSVC 11 debug builds to fail.

Thanks!

~Aaron

On Mon, Feb 18, 2013 at 10:26 PM, Argyrios Kyrtzidis <akyrtzi at gmail.com> wrote:
> Thanks for letting me know Aaron, I'll look into it.
>
> -Argyrios
>
> On Feb 18, 2013, at 5:59 PM, Aaron Ballman <aaron at aaronballman.com> wrote:
>
>> Sorry about the incredible "lateness" of this review, but the error
>> has been bugging me for a while.
>>
>> On Mon, Jan 7, 2013 at 7:58 PM, Argyrios Kyrtzidis <akyrtzi at gmail.com> wrote:
>>> Author: akirtzidis
>>> Date: Mon Jan  7 18:58:25 2013
>>> New Revision: 171828
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=171828&view=rev
>>> Log:
>>> [arcmt] Follow-up for r171484; make sure when adding brackets enclosing case statements,
>>> that the case does not "contain" a declaration that is referenced "outside" of it,
>>> otherwise we will emit un-compilable code.
>>>
>>> Modified:
>>>    cfe/trunk/lib/ARCMigrate/TransProtectedScope.cpp
>>>    cfe/trunk/test/ARCMT/checking.m
>>>    cfe/trunk/test/ARCMT/protected-scope.m
>>>    cfe/trunk/test/ARCMT/protected-scope.m.result
>>>
>>> Modified: cfe/trunk/lib/ARCMigrate/TransProtectedScope.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/TransProtectedScope.cpp?rev=171828&r1=171827&r2=171828&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/lib/ARCMigrate/TransProtectedScope.cpp (original)
>>> +++ cfe/trunk/lib/ARCMigrate/TransProtectedScope.cpp Mon Jan  7 18:58:25 2013
>>> @@ -15,6 +15,7 @@
>>> #include "Transforms.h"
>>> #include "Internals.h"
>>> #include "clang/Sema/SemaDiagnostic.h"
>>> +#include "clang/AST/ASTContext.h"
>>>
>>> using namespace clang;
>>> using namespace arcmt;
>>> @@ -22,26 +23,58 @@
>>>
>>> namespace {
>>>
>>> +class LocalRefsCollector : public RecursiveASTVisitor<LocalRefsCollector> {
>>> +  SmallVectorImpl<DeclRefExpr *> &Refs;
>>> +
>>> +public:
>>> +  LocalRefsCollector(SmallVectorImpl<DeclRefExpr *> &refs)
>>> +    : Refs(refs) { }
>>> +
>>> +  bool VisitDeclRefExpr(DeclRefExpr *E) {
>>> +    if (ValueDecl *D = E->getDecl())
>>> +      if (D->getDeclContext()->getRedeclContext()->isFunctionOrMethod())
>>> +        Refs.push_back(E);
>>> +    return true;
>>> +  }
>>> +};
>>> +
>>> struct CaseInfo {
>>>   SwitchCase *SC;
>>>   SourceRange Range;
>>> -  bool FixedBypass;
>>> +  enum {
>>> +    St_Unchecked,
>>> +    St_CannotFix,
>>> +    St_Fixed
>>> +  } State;
>>>
>>> -  CaseInfo() : SC(0), FixedBypass(false) {}
>>> +  CaseInfo() : SC(0), State(St_Unchecked) {}
>>>   CaseInfo(SwitchCase *S, SourceRange Range)
>>> -    : SC(S), Range(Range), FixedBypass(false) {}
>>> +    : SC(S), Range(Range), State(St_Unchecked) {}
>>> };
>>>
>>> class CaseCollector : public RecursiveASTVisitor<CaseCollector> {
>>> +  ParentMap &PMap;
>>>   llvm::SmallVectorImpl<CaseInfo> &Cases;
>>>
>>> public:
>>> -  CaseCollector(llvm::SmallVectorImpl<CaseInfo> &Cases)
>>> -    : Cases(Cases) { }
>>> +  CaseCollector(ParentMap &PMap, llvm::SmallVectorImpl<CaseInfo> &Cases)
>>> +    : PMap(PMap), Cases(Cases) { }
>>>
>>>   bool VisitSwitchStmt(SwitchStmt *S) {
>>> -    SourceLocation NextLoc = S->getLocEnd();
>>>     SwitchCase *Curr = S->getSwitchCaseList();
>>> +    if (!Curr)
>>> +      return true;
>>> +    Stmt *Parent = getCaseParent(Curr);
>>> +    Curr = Curr->getNextSwitchCase();
>>> +    // Make sure all case statements are in the same scope.
>>> +    while (Curr) {
>>> +      if (getCaseParent(Curr) != Parent)
>>> +        return true;
>>> +      Curr = Curr->getNextSwitchCase();
>>> +    }
>>> +
>>> +    SourceLocation NextLoc = S->getLocEnd();
>>> +    Curr = S->getSwitchCaseList();
>>>     // We iterate over case statements in reverse source-order.
>>>     while (Curr) {
>>>       Cases.push_back(CaseInfo(Curr,SourceRange(Curr->getLocStart(), NextLoc)));
>>> @@ -50,69 +83,114 @@
>>>     }
>>>     return true;
>>>   }
>>> -};
>>>
>>> -} // anonymous namespace
>>> +  Stmt *getCaseParent(SwitchCase *S) {
>>> +    Stmt *Parent = PMap.getParent(S);
>>> +    while (Parent && (isa<SwitchCase>(Parent) || isa<LabelStmt>(Parent)))
>>> +      Parent = PMap.getParent(Parent);
>>> +    return Parent;
>>> +  }
>>> +};
>>>
>>> -static bool isInRange(FullSourceLoc Loc, SourceRange R) {
>>> -  return !Loc.isBeforeInTranslationUnitThan(R.getBegin()) &&
>>> -          Loc.isBeforeInTranslationUnitThan(R.getEnd());
>>> -}
>>> +class ProtectedScopeFixer {
>>> +  MigrationPass &Pass;
>>> +  SourceManager &SM;
>>> +  SmallVector<CaseInfo, 16> Cases;
>>> +  SmallVector<DeclRefExpr *, 16> LocalRefs;
>>>
>>> -static bool handleProtectedNote(const StoredDiagnostic &Diag,
>>> -                                llvm::SmallVectorImpl<CaseInfo> &Cases,
>>> -                                TransformActions &TA) {
>>> -  assert(Diag.getLevel() == DiagnosticsEngine::Note);
>>> -
>>> -  for (unsigned i = 0; i != Cases.size(); i++) {
>>> -    CaseInfo &info = Cases[i];
>>> -    if (isInRange(Diag.getLocation(), info.Range)) {
>>> -      TA.clearDiagnostic(Diag.getID(), Diag.getLocation());
>>> -      if (!info.FixedBypass) {
>>> -        TA.insertAfterToken(info.SC->getColonLoc(), " {");
>>> -        TA.insert(info.Range.getEnd(), "}\n");
>>> -        info.FixedBypass = true;
>>> +public:
>>> +  ProtectedScopeFixer(BodyContext &BodyCtx)
>>> +    : Pass(BodyCtx.getMigrationContext().Pass),
>>> +      SM(Pass.Ctx.getSourceManager()) {
>>> +
>>> +    CaseCollector(BodyCtx.getParentMap(), Cases)
>>> +        .TraverseStmt(BodyCtx.getTopStmt());
>>> +    LocalRefsCollector(LocalRefs).TraverseStmt(BodyCtx.getTopStmt());
>>> +
>>> +    SourceRange BodyRange = BodyCtx.getTopStmt()->getSourceRange();
>>> +    const CapturedDiagList &DiagList = Pass.getDiags();
>>> +    CapturedDiagList::iterator I = DiagList.begin(), E = DiagList.end();
>>> +    while (I != E) {
>>> +      if (I->getID() == diag::err_switch_into_protected_scope &&
>>> +          isInRange(I->getLocation(), BodyRange)) {
>>> +        handleProtectedScopeError(I, E);
>>> +        continue;
>>
>> The use of iterators here is problematic because
>> handleProtectedScopeError can invalidate the iterators.  This is
>> causing a failed assertion in debug build of MSVC11 where there are
>> checked iterators involved.
>>
>> From what I am seeing, handleProtectedScopeError has a Transaction
>> object, which on destruction winds up calling
>> CapturedDiagList::clearDiagnostic, and that calls erase on the list,
>> which invalidates the iterators.  Attempting to perform the comparison
>> then fires the assert.
>>
>> I'm not entirely certain of the best way to solve this issue, but I
>> figured I would mention that it causes problems.  We have a test case
>> already demonstrating the issue with test\ARCMT\protected-scope.m
>>
>> ~Aaron
>



More information about the cfe-commits mailing list