diff options
Diffstat (limited to 'clang/lib/Sema/SemaStmt.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 127 | 
1 files changed, 74 insertions, 53 deletions
| diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index d6c3af9e84c8..73f3183c163f 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -334,6 +334,11 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {      }    } else if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {      const Expr *Source = POE->getSyntacticForm(); +    // Handle the actually selected call of an OpenMP specialized call. +    if (LangOpts.OpenMP && isa<CallExpr>(Source) && +        POE->getNumSemanticExprs() == 1 && +        isa<CallExpr>(POE->getSemanticExpr(0))) +      return DiagnoseUnusedExprResult(POE->getSemanticExpr(0));      if (isa<ObjCSubscriptRefExpr>(Source))        DiagID = diag::warn_unused_container_subscript_expr;      else @@ -365,7 +370,10 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {      }    } -  if (E->isGLValue() && E->getType().isVolatileQualified()) { +  // Tell the user to assign it into a variable to force a volatile load if this +  // isn't an array. +  if (E->isGLValue() && E->getType().isVolatileQualified() && +      !E->getType()->isArrayType()) {      Diag(Loc, diag::warn_unused_volatile) << R1 << R2;      return;    } @@ -389,6 +397,11 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R,                                     ArrayRef<Stmt *> Elts, bool isStmtExpr) {    const unsigned NumElts = Elts.size(); +  // Mark the current function as usng floating point constrained intrinsics +  if (getCurFPFeatures().isFPConstrained()) +    if (FunctionDecl *F = dyn_cast<FunctionDecl>(CurContext)) +      F->setUsesFPIntrin(true); +    // If we're in C89 mode, check that we don't have any decls after stmts.  If    // so, emit an extension diagnostic.    if (!getLangOpts().C99 && !getLangOpts().CPlusPlus) { @@ -464,7 +477,9 @@ Sema::ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val) {      return ER;    }; -  ExprResult Converted = CorrectDelayedTyposInExpr(Val, CheckAndFinish); +  ExprResult Converted = CorrectDelayedTyposInExpr( +      Val, /*InitDecl=*/nullptr, /*RecoverUncorrectedTypos=*/false, +      CheckAndFinish);    if (Converted.get() == Val.get())      Converted = CheckAndFinish(Val.get());    return Converted; @@ -730,11 +745,11 @@ StmtResult Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,    if (CondExpr && !CondExpr->isTypeDependent()) {      // We have already converted the expression to an integral or enumeration -    // type, when we parsed the switch condition. If we don't have an -    // appropriate type now, enter the switch scope but remember that it's -    // invalid. -    assert(CondExpr->getType()->isIntegralOrEnumerationType() && -           "invalid condition type"); +    // type, when we parsed the switch condition. There are cases where we don't +    // have an appropriate type, e.g. a typo-expr Cond was corrected to an +    // inappropriate-type expr, we just return an error. +    if (!CondExpr->getType()->isIntegralOrEnumerationType()) +      return StmtError();      if (CondExpr->isKnownToHaveBooleanValue()) {        // switch(bool_expr) {...} is often a programmer error, e.g.        //   switch(n && mask) { ... }  // Doh - should be "n & mask". @@ -1313,8 +1328,9 @@ Sema::DiagnoseAssignmentEnum(QualType DstType, QualType SrcType,      }  } -StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond, -                                Stmt *Body) { +StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc, +                                SourceLocation LParenLoc, ConditionResult Cond, +                                SourceLocation RParenLoc, Stmt *Body) {    if (Cond.isInvalid())      return StmtError(); @@ -1329,7 +1345,7 @@ StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond,      getCurCompoundScope().setHasEmptyLoopBodies();    return WhileStmt::Create(Context, CondVal.first, CondVal.second, Body, -                           WhileLoc); +                           WhileLoc, LParenLoc, RParenLoc);  }  StmtResult @@ -1387,10 +1403,9 @@ namespace {        Simple = false;      } -    // Any Stmt not whitelisted will cause the condition to be marked complex. -    void VisitStmt(Stmt *S) { -      Simple = false; -    } +    // Any Stmt not explicitly listed will cause the condition to be marked +    // complex. +    void VisitStmt(Stmt *S) { Simple = false; }      void VisitBinaryOperator(BinaryOperator *E) {        Visit(E->getLHS()); @@ -2114,18 +2129,22 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,      return StmtError();    } +  // This function is responsible for attaching an initializer to LoopVar. We +  // must call ActOnInitializerError if we fail to do so.    Decl *LoopVar = DS->getSingleDecl();    if (LoopVar->isInvalidDecl() || !Range ||        DiagnoseUnexpandedParameterPack(Range, UPPC_Expression)) { -    LoopVar->setInvalidDecl(); +    ActOnInitializerError(LoopVar);      return StmtError();    }    // Build the coroutine state immediately and not later during template    // instantiation    if (!CoawaitLoc.isInvalid()) { -    if (!ActOnCoroutineBodyStart(S, CoawaitLoc, "co_await")) +    if (!ActOnCoroutineBodyStart(S, CoawaitLoc, "co_await")) { +      ActOnInitializerError(LoopVar);        return StmtError(); +    }    }    // Build  auto && __range = range-init @@ -2137,7 +2156,7 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,                                             std::string("__range") + DepthStr);    if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc,                              diag::err_for_range_deduction_failure)) { -    LoopVar->setInvalidDecl(); +    ActOnInitializerError(LoopVar);      return StmtError();    } @@ -2146,14 +2165,20 @@ StmtResult Sema::ActOnCXXForRangeStmt(Scope *S, SourceLocation ForLoc,        BuildDeclaratorGroup(MutableArrayRef<Decl *>((Decl **)&RangeVar, 1));    StmtResult RangeDecl = ActOnDeclStmt(RangeGroup, RangeLoc, RangeLoc);    if (RangeDecl.isInvalid()) { -    LoopVar->setInvalidDecl(); +    ActOnInitializerError(LoopVar);      return StmtError();    } -  return BuildCXXForRangeStmt( +  StmtResult R = BuildCXXForRangeStmt(        ForLoc, CoawaitLoc, InitStmt, ColonLoc, RangeDecl.get(),        /*BeginStmt=*/nullptr, /*EndStmt=*/nullptr,        /*Cond=*/nullptr, /*Inc=*/nullptr, DS, RParenLoc, Kind); +  if (R.isInvalid()) { +    ActOnInitializerError(LoopVar); +    return StmtError(); +  } + +  return R;  }  /// Create the initialization, compare, and increment steps for @@ -2336,22 +2361,6 @@ static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S,        AdjustedRange.get(), RParenLoc, Sema::BFRK_Rebuild);  } -namespace { -/// RAII object to automatically invalidate a declaration if an error occurs. -struct InvalidateOnErrorScope { -  InvalidateOnErrorScope(Sema &SemaRef, Decl *D, bool Enabled) -      : Trap(SemaRef.Diags), D(D), Enabled(Enabled) {} -  ~InvalidateOnErrorScope() { -    if (Enabled && Trap.hasErrorOccurred()) -      D->setInvalidDecl(); -  } - -  DiagnosticErrorTrap Trap; -  Decl *D; -  bool Enabled; -}; -} -  /// BuildCXXForRangeStmt - Build or instantiate a C++11 for-range statement.  StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc,                                        SourceLocation CoawaitLoc, Stmt *InitStmt, @@ -2378,11 +2387,6 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc,    DeclStmt *LoopVarDS = cast<DeclStmt>(LoopVarDecl);    VarDecl *LoopVar = cast<VarDecl>(LoopVarDS->getSingleDecl()); -  // If we hit any errors, mark the loop variable as invalid if its type -  // contains 'auto'. -  InvalidateOnErrorScope Invalidate(*this, LoopVar, -                                    LoopVar->getType()->isUndeducedType()); -    StmtResult BeginDeclStmt = Begin;    StmtResult EndDeclStmt = End;    ExprResult NotEqExpr = Cond, IncrExpr = Inc; @@ -2664,7 +2668,8 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc,      // trying to determine whether this would be a valid range.      if (!LoopVar->isInvalidDecl() && Kind != BFRK_Check) {        AddInitializerToDecl(LoopVar, DerefExpr.get(), /*DirectInit=*/false); -      if (LoopVar->isInvalidDecl()) +      if (LoopVar->isInvalidDecl() || +          (LoopVar->getInit() && LoopVar->getInit()->containsErrors()))          NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin);      }    } @@ -2741,22 +2746,24 @@ static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef,      E = E->IgnoreImpCasts();    } -  bool ReturnsReference = false; +  QualType ReferenceReturnType;    if (isa<UnaryOperator>(E)) { -    ReturnsReference = true; +    ReferenceReturnType = SemaRef.Context.getLValueReferenceType(E->getType());    } else {      const CXXOperatorCallExpr *Call = cast<CXXOperatorCallExpr>(E);      const FunctionDecl *FD = Call->getDirectCallee();      QualType ReturnType = FD->getReturnType(); -    ReturnsReference = ReturnType->isReferenceType(); +    if (ReturnType->isReferenceType()) +      ReferenceReturnType = ReturnType;    } -  if (ReturnsReference) { +  if (!ReferenceReturnType.isNull()) {      // Loop variable creates a temporary.  Suggest either to go with      // non-reference loop variable to indicate a copy is made, or -    // the correct time to bind a const reference. -    SemaRef.Diag(VD->getLocation(), diag::warn_for_range_const_reference_copy) -        << VD << VariableType << E->getType(); +    // the correct type to bind a const reference. +    SemaRef.Diag(VD->getLocation(), +                 diag::warn_for_range_const_ref_binds_temp_built_from_ref) +        << VD << VariableType << ReferenceReturnType;      QualType NonReferenceType = VariableType.getNonReferenceType();      NonReferenceType.removeLocalConst();      QualType NewReferenceType = @@ -2769,7 +2776,7 @@ static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef,      // Suggest removing the reference from the loop variable.      // If the type is a rvalue reference do not warn since that changes the      // semantic of the code. -    SemaRef.Diag(VD->getLocation(), diag::warn_for_range_variable_always_copy) +    SemaRef.Diag(VD->getLocation(), diag::warn_for_range_ref_binds_ret_temp)          << VD << RangeInitType;      QualType NonReferenceType = VariableType.getNonReferenceType();      NonReferenceType.removeLocalConst(); @@ -2821,7 +2828,7 @@ static void DiagnoseForRangeConstVariableCopies(Sema &SemaRef,    // Suggest changing from a const variable to a const reference variable    // if doing so will prevent a copy.    SemaRef.Diag(VD->getLocation(), diag::warn_for_range_copy) -      << VD << VariableType << InitExpr->getType(); +      << VD << VariableType;    SemaRef.Diag(VD->getBeginLoc(), diag::note_use_reference_type)        << SemaRef.Context.getLValueReferenceType(VariableType)        << VD->getSourceRange() @@ -2838,9 +2845,13 @@ static void DiagnoseForRangeConstVariableCopies(Sema &SemaRef,  ///    Suggest "const foo &x" to prevent the copy.  static void DiagnoseForRangeVariableCopies(Sema &SemaRef,                                             const CXXForRangeStmt *ForStmt) { -  if (SemaRef.Diags.isIgnored(diag::warn_for_range_const_reference_copy, -                              ForStmt->getBeginLoc()) && -      SemaRef.Diags.isIgnored(diag::warn_for_range_variable_always_copy, +  if (SemaRef.inTemplateInstantiation()) +    return; + +  if (SemaRef.Diags.isIgnored( +          diag::warn_for_range_const_ref_binds_temp_built_from_ref, +          ForStmt->getBeginLoc()) && +      SemaRef.Diags.isIgnored(diag::warn_for_range_ref_binds_ret_temp,                                ForStmt->getBeginLoc()) &&        SemaRef.Diags.isIgnored(diag::warn_for_range_copy,                                ForStmt->getBeginLoc())) { @@ -2860,6 +2871,9 @@ static void DiagnoseForRangeVariableCopies(Sema &SemaRef,    if (!InitExpr)      return; +  if (InitExpr->getExprLoc().isMacroID()) +    return; +    if (VariableType->isReferenceType()) {      DiagnoseForRangeReferenceVariableCopies(SemaRef, VD,                                              ForStmt->getRangeInit()->getType()); @@ -3286,6 +3300,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {      assert(AT && "lost auto type from lambda return type");      if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) {        FD->setInvalidDecl(); +      // FIXME: preserve the ill-formed return expression.        return StmtError();      }      CurCap->ReturnType = FnRetType = FD->getReturnType(); @@ -3616,6 +3631,12 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {        if (isa<CXXBoolLiteralExpr>(RetValExp))          Diag(ReturnLoc, diag::warn_main_returns_bool_literal)            << RetValExp->getSourceRange(); +    if (FD->hasAttr<CmseNSEntryAttr>() && RetValExp) { +      if (const auto *RT = dyn_cast<RecordType>(FnRetType.getCanonicalType())) { +        if (RT->getDecl()->isOrContainsUnion()) +          Diag(RetValExp->getBeginLoc(), diag::warn_cmse_nonsecure_union) << 1; +      } +    }    } else if (ObjCMethodDecl *MD = getCurMethodDecl()) {      FnRetType = MD->getReturnType();      isObjCMethod = true; | 
