diff options
Diffstat (limited to 'clang/lib')
24 files changed, 324 insertions, 9 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index f679377b845..0a99575f406 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1047,6 +1047,10 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) { // Placeholder type for builtin functions. InitBuiltinType(BuiltinFnTy, BuiltinType::BuiltinFn); + // Placeholder type for OMP array sections. + if (LangOpts.OpenMP) + InitBuiltinType(OMPArraySectionTy, BuiltinType::OMPArraySection); + // C99 6.2.5p11. FloatComplexTy = getComplexType(FloatTy); DoubleComplexTy = getComplexType(DoubleTy); diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 3327fb3ef1d..1fc4ccbd102 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -3017,6 +3017,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case ParenExprClass: case ArraySubscriptExprClass: + case OMPArraySectionExprClass: case MemberExprClass: case ConditionalOperatorClass: case BinaryConditionalOperatorClass: diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp index 9cc612eae9b..882c786c357 100644 --- a/clang/lib/AST/ExprClassification.cpp +++ b/clang/lib/AST/ExprClassification.cpp @@ -136,6 +136,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::ObjCIvarRefExprClass: case Expr::FunctionParmPackExprClass: case Expr::MSPropertyRefExprClass: + case Expr::OMPArraySectionExprClass: return Cl::CL_LValue; // C99 6.5.2.5p5 says that compound literals are lvalues. diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 7b4277b287d..4f6666dfa40 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -8728,6 +8728,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::ImaginaryLiteralClass: case Expr::StringLiteralClass: case Expr::ArraySubscriptExprClass: + case Expr::OMPArraySectionExprClass: case Expr::MemberExprClass: case Expr::CompoundAssignOperatorClass: case Expr::CompoundLiteralExprClass: diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 1e777a51d9f..3f40743d9b4 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -2712,6 +2712,7 @@ recurse: case Expr::LambdaExprClass: case Expr::MSPropertyRefExprClass: case Expr::TypoExprClass: // This should no longer exist in the AST by now. + case Expr::OMPArraySectionExprClass: llvm_unreachable("unexpected statement kind"); // FIXME: invent manglings for all these. diff --git a/clang/lib/AST/NSAPI.cpp b/clang/lib/AST/NSAPI.cpp index c9264d59aae..17d5beb1424 100644 --- a/clang/lib/AST/NSAPI.cpp +++ b/clang/lib/AST/NSAPI.cpp @@ -461,6 +461,7 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const { case BuiltinType::Half: case BuiltinType::PseudoObject: case BuiltinType::BuiltinFn: + case BuiltinType::OMPArraySection: break; } diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index e8a02eee7f8..22b557dadc6 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -15,6 +15,7 @@ #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprOpenMP.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 6f6c10daebf..8470a0c5a14 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -19,6 +19,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprOpenMP.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/CharInfo.h" @@ -1292,6 +1293,17 @@ void StmtPrinter::VisitArraySubscriptExpr(ArraySubscriptExpr *Node) { OS << "]"; } +void StmtPrinter::VisitOMPArraySectionExpr(OMPArraySectionExpr *Node) { + PrintExpr(Node->getBase()); + OS << "["; + if (Node->getLowerBound()) + PrintExpr(Node->getLowerBound()); + OS << ":"; + if (Node->getLength()) + PrintExpr(Node->getLength()); + OS << "]"; +} + void StmtPrinter::PrintCallArgs(CallExpr *Call) { for (unsigned i = 0, e = Call->getNumArgs(); i != e; ++i) { if (isa<CXXDefaultArgExpr>(Call->getArg(i))) { diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 2e5f2479aff..231f450c9b4 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -18,6 +18,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprOpenMP.h" #include "clang/AST/StmtVisitor.h" #include "llvm/ADT/FoldingSet.h" using namespace clang; @@ -664,6 +665,10 @@ void StmtProfiler::VisitArraySubscriptExpr(const ArraySubscriptExpr *S) { VisitExpr(S); } +void StmtProfiler::VisitOMPArraySectionExpr(const OMPArraySectionExpr *S) { + VisitExpr(S); +} + void StmtProfiler::VisitCallExpr(const CallExpr *S) { VisitExpr(S); } diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index cddb46e9d1e..1f4ed4647eb 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2510,6 +2510,7 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const { case OCLImage3d: return "image3d_t"; case OCLSampler: return "sampler_t"; case OCLEvent: return "event_t"; + case OMPArraySection: return "<OpenMP array section type>"; } llvm_unreachable("Invalid builtin type."); @@ -3415,6 +3416,7 @@ bool Type::canHaveNullability() const { case BuiltinType::OCLEvent: case BuiltinType::BuiltinFn: case BuiltinType::NullPtr: + case BuiltinType::OMPArraySection: return false; } diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp index 85bda6a06d9..2dbad7edcfd 100644 --- a/clang/lib/AST/TypeLoc.cpp +++ b/clang/lib/AST/TypeLoc.cpp @@ -342,6 +342,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const { case BuiltinType::OCLSampler: case BuiltinType::OCLEvent: case BuiltinType::BuiltinFn: + case BuiltinType::OMPArraySection: return TST_unspecified; } diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index b866798a1c6..ed8073a80c4 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1396,21 +1396,42 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { BalancedDelimiterTracker T(*this, tok::l_square); T.consumeOpen(); Loc = T.getOpenLocation(); - ExprResult Idx; + ExprResult Idx, Length; + SourceLocation ColonLoc; if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); Idx = ParseBraceInitializer(); + } else if (getLangOpts().OpenMP) { + ColonProtectionRAIIObject RAII(*this); + // Parse [: or [ expr or [ expr : + if (!Tok.is(tok::colon)) { + // [ expr + Idx = ParseExpression(); + } + if (Tok.is(tok::colon)) { + // Consume ':' + ColonLoc = ConsumeToken(); + if (Tok.isNot(tok::r_square)) + Length = ParseExpression(); + } } else Idx = ParseExpression(); SourceLocation RLoc = Tok.getLocation(); - if (!LHS.isInvalid() && !Idx.isInvalid() && Tok.is(tok::r_square)) { - LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), LHS.get(), Loc, - Idx.get(), RLoc); + if (!LHS.isInvalid() && !Idx.isInvalid() && !Length.isInvalid() && + Tok.is(tok::r_square)) { + if (ColonLoc.isValid()) { + LHS = Actions.ActOnOMPArraySectionExpr(LHS.get(), Loc, Idx.get(), + ColonLoc, Length.get(), RLoc); + } else { + LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), LHS.get(), Loc, + Idx.get(), RLoc); + } } else { (void)Actions.CorrectDelayedTyposInExpr(LHS); (void)Actions.CorrectDelayedTyposInExpr(Idx); + (void)Actions.CorrectDelayedTyposInExpr(Length); LHS = ExprError(); Idx = ExprError(); } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index a8a7009ccf5..92c94560d57 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -21,6 +21,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprOpenMP.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/Analysis/Analyses/FormatString.h" @@ -5750,6 +5751,11 @@ do { return EvalAddr(cast<ArraySubscriptExpr>(E)->getBase(), refVars,ParentDecl); } + case Stmt::OMPArraySectionExprClass: { + return EvalAddr(cast<OMPArraySectionExpr>(E)->getBase(), refVars, + ParentDecl); + } + case Stmt::ConditionalOperatorClass: { // For conditional operators we need to see if either the LHS or RHS are // non-NULL Expr's. If one is non-NULL, we return it. @@ -8462,6 +8468,13 @@ void Sema::CheckArrayAccess(const Expr *expr) { AllowOnePastEnd > 0); return; } + case Stmt::OMPArraySectionExprClass: { + const OMPArraySectionExpr *ASE = cast<OMPArraySectionExpr>(expr); + if (ASE->getLowerBound()) + CheckArrayAccess(ASE->getBase(), ASE->getLowerBound(), + /*ASE=*/nullptr, AllowOnePastEnd > 0); + return; + } case Stmt::UnaryOperatorClass: { // Only unwrap the * and & unary operators const UnaryOperator *UO = cast<UnaryOperator>(expr); diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index 7d03ac4b249..6182ad934e8 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -1065,6 +1065,7 @@ CanThrowResult Sema::canThrow(const Expr *E) { // Some might be dependent for other reasons. case Expr::ArraySubscriptExprClass: + case Expr::OMPArraySectionExprClass: case Expr::BinaryOperatorClass: case Expr::CompoundAssignOperatorClass: case Expr::CStyleCastExprClass: diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index f7fa5d38a21..e1430e3a2ac 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -24,6 +24,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprOpenMP.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/PartialDiagnostic.h" @@ -3931,6 +3932,10 @@ static bool checkArithmeticOnObjCPointer(Sema &S, ExprResult Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc, Expr *idx, SourceLocation rbLoc) { + if (base->getType()->isSpecificPlaceholderType(BuiltinType::OMPArraySection)) + return ActOnOMPArraySectionExpr(base, lbLoc, idx, SourceLocation(), + /*Length=*/nullptr, rbLoc); + // Since this might be a postfix expression, get rid of ParenListExprs. if (isa<ParenListExpr>(base)) { ExprResult result = MaybeConvertParenListExprToParenExpr(S, base); @@ -3979,6 +3984,161 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc, return CreateBuiltinArraySubscriptExpr(base, lbLoc, idx, rbLoc); } +static QualType getNonOMPArraySectionType(Expr *Base) { + unsigned ArraySectionCount = 0; + while (auto *OASE = dyn_cast<OMPArraySectionExpr>(Base->IgnoreParens())) { + Base = OASE->getBase(); + ++ArraySectionCount; + } + auto OriginalTy = Base->getType(); + if (auto *DRE = dyn_cast<DeclRefExpr>(Base)) + if (auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) + OriginalTy = PVD->getOriginalType().getNonReferenceType(); + + for (unsigned Cnt = 0; Cnt < ArraySectionCount; ++Cnt) { + if (OriginalTy->isAnyPointerType()) + OriginalTy = OriginalTy->getPointeeType(); + else { + assert (OriginalTy->isArrayType()); + OriginalTy = OriginalTy->castAsArrayTypeUnsafe()->getElementType(); + } + } + return OriginalTy; +} + +ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, + Expr *LowerBound, + SourceLocation ColonLoc, Expr *Length, + SourceLocation RBLoc) { + if (Base->getType()->isPlaceholderType() && + !Base->getType()->isSpecificPlaceholderType( + BuiltinType::OMPArraySection)) { + ExprResult Result = CheckPlaceholderExpr(Base); + if (Result.isInvalid()) + return ExprError(); + Base = Result.get(); + } + if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) { + ExprResult Result = CheckPlaceholderExpr(LowerBound); + if (Result.isInvalid()) + return ExprError(); + LowerBound = Result.get(); + } + if (Length && Length->getType()->isNonOverloadPlaceholderType()) { + ExprResult Result = CheckPlaceholderExpr(Length); + if (Result.isInvalid()) + return ExprError(); + Length = Result.get(); + } + + // Build an unanalyzed expression if either operand is type-dependent. + if (Base->isTypeDependent() || + (LowerBound && + (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) || + (Length && (Length->isTypeDependent() || Length->isValueDependent()))) { + return new (Context) + OMPArraySectionExpr(Base, LowerBound, Length, Context.DependentTy, + VK_LValue, OK_Ordinary, ColonLoc, RBLoc); + } + + // Perform default conversions. + QualType OriginalTy = getNonOMPArraySectionType(Base); + QualType ResultTy; + if (OriginalTy->isAnyPointerType()) { + ResultTy = OriginalTy->getPointeeType(); + } else if (OriginalTy->isArrayType()) { + ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType(); + } else { + return ExprError( + Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value) + << Base->getSourceRange()); + } + // C99 6.5.2.1p1 + if (LowerBound) { + auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(), + LowerBound); + if (Res.isInvalid()) + return ExprError(Diag(LowerBound->getExprLoc(), + diag::err_omp_typecheck_section_not_integer) + << 0 << LowerBound->getSourceRange()); + LowerBound = Res.get(); + + if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) || + LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U)) + Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char) + << 0 << LowerBound->getSourceRange(); + } + if (Length) { + auto Res = + PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length); + if (Res.isInvalid()) + return ExprError(Diag(Length->getExprLoc(), + diag::err_omp_typecheck_section_not_integer) + << 1 << Length->getSourceRange()); + Length = Res.get(); + + if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) || + Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U)) + Diag(Length->getExprLoc(), diag::warn_omp_section_is_char) + << 1 << Length->getSourceRange(); + } + + // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly, + // C++ [expr.sub]p1: The type "T" shall be a completely-defined object + // type. Note that functions are not objects, and that (in C99 parlance) + // incomplete types are not object types. + if (ResultTy->isFunctionType()) { + Diag(Base->getExprLoc(), diag::err_omp_section_function_type) + << ResultTy << Base->getSourceRange(); + return ExprError(); + } + + if (RequireCompleteType(Base->getExprLoc(), ResultTy, + diag::err_omp_section_incomplete_type, Base)) + return ExprError(); + + if (LowerBound) { + llvm::APSInt LowerBoundValue; + if (LowerBound->EvaluateAsInt(LowerBoundValue, Context)) { + // OpenMP 4.0, [2.4 Array Sections] + // The lower-bound and length must evaluate to non-negative integers. + if (LowerBoundValue.isNegative()) { + Diag(LowerBound->getExprLoc(), diag::err_omp_section_negative) + << 0 << LowerBoundValue.toString(/*Radix=*/10, /*Signed=*/true) + << LowerBound->getSourceRange(); + return ExprError(); + } + } + } + + if (Length) { + llvm::APSInt LengthValue; + if (Length->EvaluateAsInt(LengthValue, Context)) { + // OpenMP 4.0, [2.4 Array Sections] + // The lower-bound and length must evaluate to non-negative integers. + if (LengthValue.isNegative()) { + Diag(Length->getExprLoc(), diag::err_omp_section_negative) + << 1 << LengthValue.toString(/*Radix=*/10, /*Signed=*/true) + << Length->getSourceRange(); + return ExprError(); + } + } + } else if (ColonLoc.isValid() && + (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() && + !OriginalTy->isVariableArrayType()))) { + // OpenMP 4.0, [2.4 Array Sections] + // When the size of the array dimension is not known, the length must be + // specified explicitly. + Diag(ColonLoc, diag::err_omp_section_length_undefined) + << (!OriginalTy.isNull() && OriginalTy->isArrayType()); + return ExprError(); + } + + return new (Context) + OMPArraySectionExpr(Base, LowerBound, Length, Context.OMPArraySectionTy, + VK_LValue, OK_Ordinary, ColonLoc, RBLoc); +} + ExprResult Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc) { @@ -4611,7 +4771,9 @@ static bool isPlaceholderToRemoveAsArg(QualType type) { // These are always invalid as call arguments and should be reported. case BuiltinType::BoundMember: case BuiltinType::BuiltinFn: + case BuiltinType::OMPArraySection: return true; + } llvm_unreachable("bad builtin type kind"); } @@ -14301,6 +14463,11 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { return ExprError(); } + // Expressions of unknown type. + case BuiltinType::OMPArraySection: + Diag(E->getLocStart(), diag::err_omp_array_section_use); + return ExprError(); + // Everything else should be impossible. #define BUILTIN_TYPE(Id, SingletonId) \ case BuiltinType::Id: diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 77d8c2f662b..6b092a80de9 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -6973,10 +6973,11 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, // structure) but is not an array element or an array section cannot appear // in a depend clause. auto *SimpleExpr = RefExpr->IgnoreParenCasts(); - DeclRefExpr *DE = dyn_cast<DeclRefExpr>(SimpleExpr); - ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr); - if (!RefExpr->IgnoreParenImpCasts()->isLValue() || (!ASE && !DE) || - (DE && !isa<VarDecl>(DE->getDecl())) || + auto *DE = dyn_cast<DeclRefExpr>(SimpleExpr); + auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr); + auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr); + if (!RefExpr->IgnoreParenImpCasts()->isLValue() || + (!ASE && !DE && !OASE) || (DE && !isa<VarDecl>(DE->getDecl())) || (ASE && !ASE->getBase()->getType()->isAnyPointerType() && !ASE->getBase()->getType()->isArrayType())) { Diag(ELoc, diag::err_omp_expected_var_name_or_array_item) diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 7c2c2a587a6..799127e50be 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -21,6 +21,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprOpenMP.h" #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" @@ -1891,6 +1892,18 @@ public: RBracketLoc); } + /// \brief Build a new array section expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildOMPArraySectionExpr(Expr *Base, SourceLocation LBracketLoc, + Expr *LowerBound, + SourceLocation ColonLoc, Expr *Length, + SourceLocation RBracketLoc) { + return getSema().ActOnOMPArraySectionExpr(Base, LBracketLoc, LowerBound, + ColonLoc, Length, RBracketLoc); + } + /// \brief Build a new call expression. /// /// By default, performs semantic analysis to build the new expression. @@ -7896,6 +7909,36 @@ TreeTransform<Derived>::TransformArraySubscriptExpr(ArraySubscriptExpr *E) { E->getRBracketLoc()); } +template <typename Derived> +ExprResult +TreeTransform<Derived>::TransformOMPArraySectionExpr(OMPArraySectionExpr *E) { + ExprResult Base = getDerived().TransformExpr(E->getBase()); + if (Base.isInvalid()) + return ExprError(); + + ExprResult LowerBound; + if (E->getLowerBound()) { + LowerBound = getDerived().TransformExpr(E->getLowerBound()); + if (LowerBound.isInvalid()) + return ExprError(); + } + + ExprResult Length; + if (E->getLength()) { + Length = getDerived().TransformExpr(E->getLength()); + if (Length.isInvalid()) + return ExprError(); + } + + if (!getDerived().AlwaysRebuild() && Base.get() == E->getBase() && + LowerBound.get() == E->getLowerBound() && Length.get() == E->getLength()) + return E; + + return getDerived().RebuildOMPArraySectionExpr( + Base.get(), E->getBase()->getLocEnd(), LowerBound.get(), E->getColonLoc(), + Length.get(), E->getRBracketLoc()); +} + template<typename Derived> ExprResult TreeTransform<Derived>::TransformCallExpr(CallExpr *E) { diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp index b1bf4a6bff8..0159c1648c0 100644 --- a/clang/lib/Serialization/ASTCommon.cpp +++ b/clang/lib/Serialization/ASTCommon.cpp @@ -72,6 +72,7 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) { case BuiltinType::OCLEvent: ID = PREDEF_TYPE_EVENT_ID; break; case BuiltinType::BuiltinFn: ID = PREDEF_TYPE_BUILTIN_FN; break; + case BuiltinType::OMPArraySection: ID = PREDEF_TYPE_OMP_ARRAY_SECTION; break; } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 7c94ca435de..f9522aeaa36 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -5826,6 +5826,10 @@ QualType ASTReader::GetType(TypeID ID) { case PREDEF_TYPE_BUILTIN_FN: T = Context.BuiltinFnTy; break; + + case PREDEF_TYPE_OMP_ARRAY_SECTION: + T = Context.OMPArraySectionTy; + break; } assert(!T.isNull() && "Unknown predefined type"); diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 4a76ca0bc7d..2d6f5e0db7f 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -589,6 +589,15 @@ void ASTStmtReader::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { E->setRBracketLoc(ReadSourceLocation(Record, Idx)); } +void ASTStmtReader::VisitOMPArraySectionExpr(OMPArraySectionExpr *E) { + VisitExpr(E); + E->setBase(Reader.ReadSubExpr()); + E->setLowerBound(Reader.ReadSubExpr()); + E->setLength(Reader.ReadSubExpr()); + E->setColonLoc(ReadSourceLocation(Record, Idx)); + E->setRBracketLoc(ReadSourceLocation(Record, Idx)); +} + void ASTStmtReader::VisitCallExpr(CallExpr *E) { VisitExpr(E); E->setNumArgs(Reader.getContext(), Record[Idx++]); @@ -2532,6 +2541,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = new (Context) ArraySubscriptExpr(Empty); break; + case EXPR_OMP_ARRAY_SECTION: + S = new (Context) OMPArraySectionExpr(Empty); + break; + case EXPR_CALL: S = new (Context) CallExpr(Context, Stmt::CallExprClass, Empty); break; diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 6bf5b7d3057..2695f67f057 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -511,6 +511,16 @@ void ASTStmtWriter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { Code = serialization::EXPR_ARRAY_SUBSCRIPT; } +void ASTStmtWriter::VisitOMPArraySectionExpr(OMPArraySectionExpr *E) { + VisitExpr(E); + Writer.AddStmt(E->getBase()); + Writer.AddStmt(E->getLowerBound()); + Writer.AddStmt(E->getLength()); + Writer.AddSourceLocation(E->getColonLoc(), Record); + Writer.AddSourceLocation(E->getRBracketLoc(), Record); + Code = serialization::EXPR_OMP_ARRAY_SECTION; +} + void ASTStmtWriter::VisitCallExpr(CallExpr *E) { VisitExpr(E); Record.push_back(E->getNumArgs()); diff --git a/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp index 3f27c3954fa..cf9d9f74385 100644 --- a/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp @@ -14,6 +14,7 @@ #include "ClangSACheckers.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprOpenMP.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" #include "clang/StaticAnalyzer/Core/Checker.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" @@ -130,6 +131,14 @@ void DereferenceChecker::reportBug(ProgramStateRef State, const Stmt *S, os << " results in a null pointer dereference"; break; } + case Stmt::OMPArraySectionExprClass: { + os << "Array access"; + const OMPArraySectionExpr *AE = cast<OMPArraySectionExpr>(S); + AddDerefSource(os, Ranges, AE->getBase()->IgnoreParenCasts(), + State.get(), N->getLocationContext()); + os << " results in a null pointer dereference"; + break; + } case Stmt::UnaryOperatorClass: { os << "Dereference of null pointer"; const UnaryOperator *U = cast<UnaryOperator>(S); diff --git a/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp index 23fa2d11a7e..3e50d2e3345 100644 --- a/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp @@ -350,6 +350,7 @@ static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1, return false; case Stmt::CallExprClass: case Stmt::ArraySubscriptExprClass: + case Stmt::OMPArraySectionExprClass: case Stmt::ImplicitCastExprClass: case Stmt::ParenExprClass: case Stmt::BreakStmtClass: diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 335ba5afa53..67c7b9365b2 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -902,7 +902,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::ObjCStringLiteralClass: case Stmt::CXXPseudoDestructorExprClass: case Stmt::SubstNonTypeTemplateParmExprClass: - case Stmt::CXXNullPtrLiteralExprClass: { + case Stmt::CXXNullPtrLiteralExprClass: + case Stmt::OMPArraySectionExprClass: { Bldr.takeNodes(Pred); ExplodedNodeSet preVisit; getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this); |