コード例 #1
0
ファイル: JumpDiagnostics.cpp プロジェクト: boostpro/clang
/// VerifyJumps - Verify each element of the Jumps array to see if they are
/// valid, emitting diagnostics if not.
void JumpScopeChecker::VerifyJumps() {
  while (!Jumps.empty()) {
    Stmt *Jump = Jumps.pop_back_val();

    // With a goto,
    if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) {
      CheckJump(GS, GS->getLabel()->getStmt(), GS->getGotoLoc(),
                diag::err_goto_into_protected_scope,
                diag::warn_goto_into_protected_scope,
                diag::warn_cxx98_compat_goto_into_protected_scope);
      continue;
    }

    // We only get indirect gotos here when they have a constant target.
    if (IndirectGotoStmt *IGS = dyn_cast<IndirectGotoStmt>(Jump)) {
      LabelDecl *Target = IGS->getConstantTarget();
      CheckJump(IGS, Target->getStmt(), IGS->getGotoLoc(),
                diag::err_goto_into_protected_scope,
                diag::warn_goto_into_protected_scope,
                diag::warn_cxx98_compat_goto_into_protected_scope);
      continue;
    }

    SwitchStmt *SS = cast<SwitchStmt>(Jump);
    for (SwitchCase *SC = SS->getSwitchCaseList(); SC;
         SC = SC->getNextSwitchCase()) {
      assert(LabelAndGotoScopes.count(SC) && "Case not visited?");
      CheckJump(SS, SC, SC->getLocStart(),
                diag::err_switch_into_protected_scope, 0,
                diag::warn_cxx98_compat_switch_into_protected_scope);
    }
  }
}
コード例 #2
0
StringRef ClangAsmParserCallback::LookupInlineAsmLabel(StringRef Identifier,
                                                       llvm::SourceMgr &LSM,
                                                       llvm::SMLoc Location,
                                                       bool Create) {
  SourceLocation Loc = translateLocation(LSM, Location);
  LabelDecl *Label =
      TheParser.getActions().GetOrCreateMSAsmLabel(Identifier, Loc, Create);
  return Label->getMSAsmLabel();
}
コード例 #3
0
/// VerifyJumps - Verify each element of the Jumps array to see if they are
/// valid, emitting diagnostics if not.
void JumpScopeChecker::VerifyJumps() {
  while (!Jumps.empty()) {
    Stmt *Jump = Jumps.pop_back_val();

    // With a goto,
    if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) {
      // The label may not have a statement if it's coming from inline MS ASM.
      if (GS->getLabel()->getStmt()) {
        CheckJump(GS, GS->getLabel()->getStmt(), GS->getGotoLoc(),
                  diag::err_goto_into_protected_scope,
                  diag::ext_goto_into_protected_scope,
                  diag::warn_cxx98_compat_goto_into_protected_scope);
      }
      CheckGotoStmt(GS);
      continue;
    }

    // We only get indirect gotos here when they have a constant target.
    if (IndirectGotoStmt *IGS = dyn_cast<IndirectGotoStmt>(Jump)) {
      LabelDecl *Target = IGS->getConstantTarget();
      CheckJump(IGS, Target->getStmt(), IGS->getGotoLoc(),
                diag::err_goto_into_protected_scope,
                diag::ext_goto_into_protected_scope,
                diag::warn_cxx98_compat_goto_into_protected_scope);
      continue;
    }

    SwitchStmt *SS = cast<SwitchStmt>(Jump);
    for (SwitchCase *SC = SS->getSwitchCaseList(); SC;
         SC = SC->getNextSwitchCase()) {
      if (CHECK_PERMISSIVE(!LabelAndGotoScopes.count(SC)))
        continue;
      SourceLocation Loc;
      if (CaseStmt *CS = dyn_cast<CaseStmt>(SC))
        Loc = CS->getLocStart();
      else if (DefaultStmt *DS = dyn_cast<DefaultStmt>(SC))
        Loc = DS->getLocStart();
      else
        Loc = SC->getLocStart();
      CheckJump(SS, SC, Loc, diag::err_switch_into_protected_scope, 0,
                diag::warn_cxx98_compat_switch_into_protected_scope);
    }
  }
}
コード例 #4
0
ファイル: SemaStmtAsm.cpp プロジェクト: hanm/clang
LabelDecl *Sema::GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
                                       SourceLocation Location,
                                       bool AlwaysCreate) {
  LabelDecl* Label = LookupOrCreateLabel(PP.getIdentifierInfo(ExternalLabelName),
                                         Location);

  if (Label->isMSAsmLabel()) {
    // If we have previously created this label implicitly, mark it as used.
    Label->markUsed(Context);
  } else {
    // Otherwise, insert it, but only resolve it if we have seen the label itself.
    std::string InternalName;
    llvm::raw_string_ostream OS(InternalName);
    // Create an internal name for the label.  The name should not be a valid mangled
    // name, and should be unique.  We use a dot to make the name an invalid mangled
    // name.
    OS << "__MSASMLABEL_." << MSAsmLabelNameCounter++ << "__" << ExternalLabelName;
    Label->setMSAsmLabel(OS.str());
  }
  if (AlwaysCreate) {
    // The label might have been created implicitly from a previously encountered
    // goto statement.  So, for both newly created and looked up labels, we mark
    // them as resolved.
    Label->setMSAsmLabelResolved();
  }
  // Adjust their location for being able to generate accurate diagnostics.
  Label->setLocation(Location);

  return Label;
}
コード例 #5
0
LabelDecl *Sema::GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
                                       SourceLocation Location,
                                       bool AlwaysCreate) {
  LabelDecl* Label = LookupOrCreateLabel(PP.getIdentifierInfo(ExternalLabelName),
                                         Location);

  if (Label->isMSAsmLabel()) {
    // If we have previously created this label implicitly, mark it as used.
    Label->markUsed(Context);
  } else {
    // Otherwise, insert it, but only resolve it if we have seen the label itself.
    std::string InternalName;
    llvm::raw_string_ostream OS(InternalName);
    // Create an internal name for the label.  The name should not be a valid
    // mangled name, and should be unique.  We use a dot to make the name an
    // invalid mangled name. We use LLVM's inline asm ${:uid} escape so that a
    // unique label is generated each time this blob is emitted, even after
    // inlining or LTO.
    OS << "__MSASMLABEL_.${:uid}__";
    for (char C : ExternalLabelName) {
      OS << C;
      // We escape '$' in asm strings by replacing it with "$$"
      if (C == '$')
        OS << '$';
    }
    Label->setMSAsmLabel(OS.str());
  }
  if (AlwaysCreate) {
    // The label might have been created implicitly from a previously encountered
    // goto statement.  So, for both newly created and looked up labels, we mark
    // them as resolved.
    Label->setMSAsmLabelResolved();
  }
  // Adjust their location for being able to generate accurate diagnostics.
  Label->setLocation(Location);

  return Label;
}
コード例 #6
0
ファイル: JumpDiagnostics.cpp プロジェクト: boostpro/clang
/// VerifyIndirectJumps - Verify whether any possible indirect jump
/// might cross a protection boundary.  Unlike direct jumps, indirect
/// jumps count cleanups as protection boundaries:  since there's no
/// way to know where the jump is going, we can't implicitly run the
/// right cleanups the way we can with direct jumps.
///
/// Thus, an indirect jump is "trivial" if it bypasses no
/// initializations and no teardowns.  More formally, an indirect jump
/// from A to B is trivial if the path out from A to DCA(A,B) is
/// trivial and the path in from DCA(A,B) to B is trivial, where
/// DCA(A,B) is the deepest common ancestor of A and B.
/// Jump-triviality is transitive but asymmetric.
///
/// A path in is trivial if none of the entered scopes have an InDiag.
/// A path out is trivial is none of the exited scopes have an OutDiag.
///
/// Under these definitions, this function checks that the indirect
/// jump between A and B is trivial for every indirect goto statement A
/// and every label B whose address was taken in the function.
void JumpScopeChecker::VerifyIndirectJumps() {
  if (IndirectJumps.empty()) return;

  // If there aren't any address-of-label expressions in this function,
  // complain about the first indirect goto.
  if (IndirectJumpTargets.empty()) {
    S.Diag(IndirectJumps[0]->getGotoLoc(),
           diag::err_indirect_goto_without_addrlabel);
    return;
  }

  // Collect a single representative of every scope containing an
  // indirect goto.  For most code bases, this substantially cuts
  // down on the number of jump sites we'll have to consider later.
  typedef std::pair<unsigned, IndirectGotoStmt*> JumpScope;
  SmallVector<JumpScope, 32> JumpScopes;
  {
    llvm::DenseMap<unsigned, IndirectGotoStmt*> JumpScopesMap;
    for (SmallVectorImpl<IndirectGotoStmt*>::iterator
           I = IndirectJumps.begin(), E = IndirectJumps.end(); I != E; ++I) {
      IndirectGotoStmt *IG = *I;
      assert(LabelAndGotoScopes.count(IG) &&
             "indirect jump didn't get added to scopes?");
      unsigned IGScope = LabelAndGotoScopes[IG];
      IndirectGotoStmt *&Entry = JumpScopesMap[IGScope];
      if (!Entry) Entry = IG;
    }
    JumpScopes.reserve(JumpScopesMap.size());
    for (llvm::DenseMap<unsigned, IndirectGotoStmt*>::iterator
           I = JumpScopesMap.begin(), E = JumpScopesMap.end(); I != E; ++I)
      JumpScopes.push_back(*I);
  }

  // Collect a single representative of every scope containing a
  // label whose address was taken somewhere in the function.
  // For most code bases, there will be only one such scope.
  llvm::DenseMap<unsigned, LabelDecl*> TargetScopes;
  for (SmallVectorImpl<LabelDecl*>::iterator
         I = IndirectJumpTargets.begin(), E = IndirectJumpTargets.end();
       I != E; ++I) {
    LabelDecl *TheLabel = *I;
    assert(LabelAndGotoScopes.count(TheLabel->getStmt()) &&
           "Referenced label didn't get added to scopes?");
    unsigned LabelScope = LabelAndGotoScopes[TheLabel->getStmt()];
    LabelDecl *&Target = TargetScopes[LabelScope];
    if (!Target) Target = TheLabel;
  }

  // For each target scope, make sure it's trivially reachable from
  // every scope containing a jump site.
  //
  // A path between scopes always consists of exitting zero or more
  // scopes, then entering zero or more scopes.  We build a set of
  // of scopes S from which the target scope can be trivially
  // entered, then verify that every jump scope can be trivially
  // exitted to reach a scope in S.
  llvm::BitVector Reachable(Scopes.size(), false);
  for (llvm::DenseMap<unsigned,LabelDecl*>::iterator
         TI = TargetScopes.begin(), TE = TargetScopes.end(); TI != TE; ++TI) {
    unsigned TargetScope = TI->first;
    LabelDecl *TargetLabel = TI->second;

    Reachable.reset();

    // Mark all the enclosing scopes from which you can safely jump
    // into the target scope.  'Min' will end up being the index of
    // the shallowest such scope.
    unsigned Min = TargetScope;
    while (true) {
      Reachable.set(Min);

      // Don't go beyond the outermost scope.
      if (Min == 0) break;

      // Stop if we can't trivially enter the current scope.
      if (Scopes[Min].InDiag) break;

      Min = Scopes[Min].ParentScope;
    }

    // Walk through all the jump sites, checking that they can trivially
    // reach this label scope.
    for (SmallVectorImpl<JumpScope>::iterator
           I = JumpScopes.begin(), E = JumpScopes.end(); I != E; ++I) {
      unsigned Scope = I->first;

      // Walk out the "scope chain" for this scope, looking for a scope
      // we've marked reachable.  For well-formed code this amortizes
      // to O(JumpScopes.size() / Scopes.size()):  we only iterate
      // when we see something unmarked, and in well-formed code we
      // mark everything we iterate past.
      bool IsReachable = false;
      while (true) {
        if (Reachable.test(Scope)) {
          // If we find something reachable, mark all the scopes we just
          // walked through as reachable.
          for (unsigned S = I->first; S != Scope; S = Scopes[S].ParentScope)
            Reachable.set(S);
          IsReachable = true;
          break;
        }

        // Don't walk out if we've reached the top-level scope or we've
        // gotten shallower than the shallowest reachable scope.
        if (Scope == 0 || Scope < Min) break;

        // Don't walk out through an out-diagnostic.
        if (Scopes[Scope].OutDiag) break;

        Scope = Scopes[Scope].ParentScope;
      }

      // Only diagnose if we didn't find something.
      if (IsReachable) continue;

      DiagnoseIndirectJump(I->second, I->first, TargetLabel, TargetScope);
    }
  }
}