[prev in list] [next in list] [prev in thread] [next in thread]
List: cfe-commits
Subject: Re: [PATCH] D10732: [OPENMP 4.0] Initial support for array sections.
From: Alexey Bataev <a.bataev () hotmail ! com>
Date: 2015-07-14 13:18:02
Message-ID: 676bedfea04ae89e2da08eb16605674f () localhost ! localdomain
[Download RAW message or body]
ABataev updated this revision to Diff 29671.
ABataev added a comment.
Fixed processing of array sections without specified length.
http://reviews.llvm.org/D10732
Files:
include/clang-c/Index.h
include/clang/AST/DataRecursiveASTVisitor.h
include/clang/AST/Expr.h
include/clang/AST/RecursiveASTVisitor.h
include/clang/AST/Type.h
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Basic/StmtNodes.td
include/clang/Parse/Parser.h
include/clang/Sema/Sema.h
include/clang/Serialization/ASTBitCodes.h
lib/AST/ASTDumper.cpp
lib/AST/Expr.cpp
lib/AST/ExprClassification.cpp
lib/AST/ExprConstant.cpp
lib/AST/ItaniumMangle.cpp
lib/AST/StmtPrinter.cpp
lib/AST/StmtProfile.cpp
lib/Parse/ParseExpr.cpp
lib/Parse/ParseOpenMP.cpp
lib/Parse/Parser.cpp
lib/Parse/RAIIObjectsForParser.h
lib/Sema/SemaChecking.cpp
lib/Sema/SemaExceptionSpec.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaOpenMP.cpp
lib/Sema/SemaOverload.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReaderStmt.cpp
lib/Serialization/ASTWriterStmt.cpp
lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
lib/StaticAnalyzer/Core/ExprEngine.cpp
test/OpenMP/task_ast_print.cpp
test/OpenMP/task_depend_messages.cpp
tools/libclang/CIndex.cpp
tools/libclang/CXCursor.cpp
["D10732.29671.patch" (text/x-patch)]
Index: lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- lib/Serialization/ASTWriterStmt.cpp
+++ lib/Serialization/ASTWriterStmt.cpp
@@ -511,6 +511,16 @@
Code = serialization::EXPR_ARRAY_SUBSCRIPT;
}
+void ASTStmtWriter::VisitArraySectionExpr(ArraySectionExpr *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_ARRAY_SECTION;
+}
+
void ASTStmtWriter::VisitCallExpr(CallExpr *E) {
VisitExpr(E);
Record.push_back(E->getNumArgs());
Index: lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- lib/Serialization/ASTReaderStmt.cpp
+++ lib/Serialization/ASTReaderStmt.cpp
@@ -589,6 +589,15 @@
E->setRBracketLoc(ReadSourceLocation(Record, Idx));
}
+void ASTStmtReader::VisitArraySectionExpr(ArraySectionExpr *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++]);
@@ -2493,6 +2502,10 @@
S = new (Context) ArraySubscriptExpr(Empty);
break;
+ case EXPR_ARRAY_SECTION:
+ S = new (Context) ArraySectionExpr(Empty);
+ break;
+
case EXPR_CALL:
S = new (Context) CallExpr(Context, Stmt::CallExprClass, Empty);
break;
Index: lib/Parse/Parser.cpp
===================================================================
--- lib/Parse/Parser.cpp
+++ lib/Parse/Parser.cpp
@@ -69,10 +69,10 @@
}
Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies)
- : PP(pp), Actions(actions), Diags(PP.getDiagnostics()),
- GreaterThanIsOperator(true), ColonIsSacred(false),
- InMessageExpression(false), TemplateParameterDepth(0),
- ParsingInObjCContainer(false) {
+ : PP(pp), Actions(actions), Diags(PP.getDiagnostics()),
+ GreaterThanIsOperator(true), ColonIsSacred(false),
+ ArraySectionAllowed(false), InMessageExpression(false),
+ TemplateParameterDepth(0), ParsingInObjCContainer(false) {
SkipFunctionBodies = pp.isCodeCompletionEnabled() || skipFunctionBodies;
Tok.startToken();
Tok.setKind(tok::eof);
Index: lib/Parse/ParseOpenMP.cpp
===================================================================
--- lib/Parse/ParseOpenMP.cpp
+++ lib/Parse/ParseOpenMP.cpp
@@ -764,7 +764,9 @@
const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
Tok.isNot(tok::annot_pragma_openmp_end))) {
- ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
+ ArraySectionExpressionRAIIObject RAII(*this, Kind == OMPC_depend);
+ ColonProtectionRAIIObject ColonRAII(*this,
+ Kind == OMPC_depend || MayHaveTail);
// Parse variable
ExprResult VarExpr =
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
Index: lib/Parse/RAIIObjectsForParser.h
===================================================================
--- lib/Parse/RAIIObjectsForParser.h
+++ lib/Parse/RAIIObjectsForParser.h
@@ -286,7 +286,27 @@
restore();
}
};
-
+
+ /// \brief This sets the Parser::ArraySectionAllowed bool and
+ /// restores it when destroyed. It it also manages Parser::ColonIsSacred for
+ /// correct parsing of array sections.
+ class ArraySectionExpressionRAIIObject {
+ Parser &P;
+ bool OldVal;
+
+ public:
+ ArraySectionExpressionRAIIObject(Parser &p, bool Value = true)
+ : P(p), OldVal(P.ArraySectionAllowed) {
+ P.ArraySectionAllowed = Value;
+ }
+
+ /// restore - This can be used to restore the state early, before the dtor
+ /// is run.
+ void restore() { P.ArraySectionAllowed = OldVal; }
+
+ ~ArraySectionExpressionRAIIObject() { restore(); }
+ };
+
/// \brief RAII object that makes '>' behave either as an operator
/// or as the closing angle bracket for a template argument list.
class GreaterThanIsOperatorScope {
Index: lib/Parse/ParseExpr.cpp
===================================================================
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -1396,21 +1396,46 @@
BalancedDelimiterTracker T(*this, tok::l_square);
T.consumeOpen();
Loc = T.getOpenLocation();
- ExprResult Idx;
+ ExprResult Idx, Length;
+ bool ArraySectionIsFound = false;
+ SourceLocation ColonLoc;
if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
Idx = ParseBraceInitializer();
- } else
- Idx = ParseExpression();
+ } else {
+ bool MayArraySection = ArraySectionAllowed;
+ ArraySectionExpressionRAIIObject RAII(*this, /*Value=*/false);
+ // Parse [: or [ expr or [ expr :
+ if (!MayArraySection || !Tok.is(tok::colon)) {
+ // [ expr
+ Idx = ParseExpression();
+ }
+ if (MayArraySection && Tok.is(tok::colon)) {
+ // Consume ':'
+ ArraySectionIsFound = true;
+ ColonLoc = ConsumeToken();
+ if (Tok.isNot(tok::r_square)) {
+ Length = 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 (ArraySectionIsFound) {
+ LHS = Actions.ActOnArraySectionExpr(getCurScope(), 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();
}
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -901,7 +901,8 @@
case Stmt::ObjCStringLiteralClass:
case Stmt::CXXPseudoDestructorExprClass:
case Stmt::SubstNonTypeTemplateParmExprClass:
- case Stmt::CXXNullPtrLiteralExprClass: {
+ case Stmt::CXXNullPtrLiteralExprClass:
+ case Stmt::ArraySectionExprClass: {
Bldr.takeNodes(Pred);
ExplodedNodeSet preVisit;
getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);
Index: lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
+++ lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
@@ -332,6 +332,7 @@
return false;
case Stmt::CallExprClass:
case Stmt::ArraySubscriptExprClass:
+ case Stmt::ArraySectionExprClass:
case Stmt::ImplicitCastExprClass:
case Stmt::ParenExprClass:
case Stmt::BreakStmtClass:
Index: lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
+++ lib/StaticAnalyzer/Checkers/DereferenceChecker.cpp
@@ -130,6 +130,14 @@
os << " results in a null pointer dereference";
break;
}
+ case Stmt::ArraySectionExprClass: {
+ os << "Array access";
+ const ArraySectionExpr *AE = cast<ArraySectionExpr>(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);
Index: lib/AST/ExprClassification.cpp
===================================================================
--- lib/AST/ExprClassification.cpp
+++ lib/AST/ExprClassification.cpp
@@ -136,6 +136,7 @@
case Expr::ObjCIvarRefExprClass:
case Expr::FunctionParmPackExprClass:
case Expr::MSPropertyRefExprClass:
+ case Expr::ArraySectionExprClass:
return Cl::CL_LValue;
// C99 6.5.2.5p5 says that compound literals are lvalues.
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp
+++ lib/AST/Expr.cpp
@@ -3012,6 +3012,7 @@
case ParenExprClass:
case ArraySubscriptExprClass:
+ case ArraySectionExprClass:
case MemberExprClass:
case ConditionalOperatorClass:
case BinaryConditionalOperatorClass:
Index: lib/AST/StmtProfile.cpp
===================================================================
--- lib/AST/StmtProfile.cpp
+++ lib/AST/StmtProfile.cpp
@@ -646,6 +646,10 @@
VisitExpr(S);
}
+void StmtProfiler::VisitArraySectionExpr(const ArraySectionExpr *S) {
+ VisitExpr(S);
+}
+
void StmtProfiler::VisitCallExpr(const CallExpr *S) {
VisitExpr(S);
}
Index: lib/AST/ASTDumper.cpp
===================================================================
--- lib/AST/ASTDumper.cpp
+++ lib/AST/ASTDumper.cpp
@@ -270,6 +270,7 @@
case ArrayType::Normal: break;
case ArrayType::Static: OS << " static"; break;
case ArrayType::Star: OS << " *"; break;
+ case ArrayType::ArraySection: OS << " array section"; break;
}
OS << " " << T->getIndexTypeQualifiers().getAsString();
dumpTypeAsChild(T->getElementType());
Index: lib/AST/StmtPrinter.cpp
===================================================================
--- lib/AST/StmtPrinter.cpp
+++ lib/AST/StmtPrinter.cpp
@@ -1266,6 +1266,17 @@
OS << "]";
}
+void StmtPrinter::VisitArraySectionExpr(ArraySectionExpr *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))) {
Index: lib/AST/ItaniumMangle.cpp
===================================================================
--- lib/AST/ItaniumMangle.cpp
+++ lib/AST/ItaniumMangle.cpp
@@ -2700,6 +2700,7 @@
case Expr::LambdaExprClass:
case Expr::MSPropertyRefExprClass:
case Expr::TypoExprClass: // This should no longer exist in the AST by now.
+ case Expr::ArraySectionExprClass:
llvm_unreachable("unexpected statement kind");
// FIXME: invent manglings for all these.
Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -8677,6 +8677,7 @@
case Expr::ImaginaryLiteralClass:
case Expr::StringLiteralClass:
case Expr::ArraySubscriptExprClass:
+ case Expr::ArraySectionExprClass:
case Expr::MemberExprClass:
case Expr::CompoundAssignOperatorClass:
case Expr::CompoundLiteralExprClass:
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -492,6 +492,17 @@
// Standard Promotions and Conversions
//===----------------------------------------------------------------------===//
+static QualType getNonArraySectionType(QualType Ty) {
+ if (!Ty.isNull() && Ty->isArrayType()) {
+ while (!Ty.isNull() && Ty->isArrayType() &&
+ Ty->getAsArrayTypeUnsafe()->getSizeModifier() ==
+ ArrayType::ArraySection) {
+ Ty = Ty->getAsArrayTypeUnsafe()->getElementType();
+ }
+ }
+ return Ty;
+}
+
/// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
ExprResult Sema::DefaultFunctionArrayConversion(Expr *E) {
// Handle any placeholder expressions which made it here.
@@ -504,6 +515,7 @@
QualType Ty = E->getType();
assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type");
+ Ty = getNonArraySectionType(Ty);
if (Ty->isFunctionType()) {
// If we are here, we are not calling a function but taking
// its address (which is not allowed in OpenCL v1.0 s6.8.a.3).
@@ -3991,6 +4003,177 @@
return CreateBuiltinArraySubscriptExpr(base, lbLoc, idx, rbLoc);
}
+ExprResult Sema::ActOnArraySectionExpr(Scope *S, Expr *Base,
+ SourceLocation LBLoc, Expr *LowerBound,
+ SourceLocation ColonLoc, Expr *Length,
+ SourceLocation RBLoc) {
+ // Since this might be a postfix expression, get rid of ParenListExprs.
+ if (isa<ParenListExpr>(Base)) {
+ ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base);
+ if (Result.isInvalid())
+ return ExprError();
+ Base = Result.get();
+ }
+
+ // Handle any non-overload placeholder types in the base and index
+ // expressions. We can't handle overloads here because the other
+ // operand might be an overloadable type, in which case the overload
+ // resolution for the operator overload should get the first crack
+ // at the overload.
+ if (Base->getType()->isNonOverloadPlaceholderType()) {
+ 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()) ||
+ (Length && Length->isTypeDependent())) {
+ return new (Context)
+ ArraySectionExpr(Base, LowerBound, Length, Context.DependentTy,
+ VK_LValue, OK_Ordinary, ColonLoc, RBLoc);
+ }
+
+ // Perform default conversions.
+ QualType OriginalTy = getNonArraySectionType(Base->getType());
+ ExprResult Result = DefaultFunctionArrayLvalueConversion(Base);
+ if (Result.isInvalid())
+ return ExprError();
+ Base = Result.get();
+
+ QualType ResultType;
+ QualType BaseTy = getNonArraySectionType(Base->getType());
+ if (const PointerType *PTy = BaseTy->getAs<PointerType>()) {
+ ResultType = PTy->getPointeeType();
+ } else if (BaseTy->isArrayType()) {
+ // If we see an array that wasn't promoted by
+ // DefaultFunctionArrayLvalueConversion, it must be an array that wasn't
+ // promoted because of the C90 rule that doesn't allow promoting non-lvalue
+ // arrays. Warn, then force the promotion here.
+ Diag(Base->getLocStart(), diag::ext_subscript_non_lvalue)
+ << Base->getSourceRange();
+ Base = ImpCastExprToType(Base, Context.getArrayDecayedType(BaseTy),
+ CK_ArrayToPointerDecay)
+ .get();
+ ResultType = BaseTy->getAs<PointerType>()->getPointeeType();
+ } else {
+ return ExprError(Diag(Base->getExprLoc(), diag::err_typecheck_section_value)
+ << Base->getSourceRange());
+ }
+ // C99 6.5.2.1p1
+ if (LowerBound) {
+ if (!LowerBound->getType()->isIntegerType())
+ return ExprError(Diag(LowerBound->getExprLoc(),
+ diag::err_typecheck_section_not_integer)
+ << 0 << LowerBound->getSourceRange());
+
+ if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
+ LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
+ Diag(LowerBound->getExprLoc(), diag::warn_section_is_char)
+ << 0 << LowerBound->getSourceRange();
+ }
+ if (Length) {
+ if (!Length->getType()->isIntegerType())
+ return ExprError(
+ Diag(Length->getExprLoc(), diag::err_typecheck_section_not_integer)
+ << 1 << Length->getSourceRange());
+
+ if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
+ Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
+ Diag(Length->getExprLoc(), diag::warn_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 (ResultType->isFunctionType()) {
+ Diag(Base->getExprLoc(), diag::err_section_function_type)
+ << ResultType << Base->getSourceRange();
+ return ExprError();
+ }
+
+ if (RequireCompleteType(Base->getExprLoc(), ResultType,
+ diag::err_section_incomplete_type, Base))
+ return ExprError();
+
+ if (LowerBound) {
+ llvm::APSInt LowerBoundValue;
+ if (LowerBound->EvaluateAsInt(LowerBoundValue, Context,
+ Expr::SE_AllowSideEffects)) {
+ // 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_section_negative)
+ << 0 << LowerBound->getSourceRange();
+ return ExprError();
+ }
+ }
+ }
+
+ if (Length) {
+ llvm::APSInt LengthValue;
+ if (Length->EvaluateAsInt(LengthValue, Context,
+ Expr::SE_AllowSideEffects)) {
+ // 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_section_negative)
+ << 1 << Length->getSourceRange();
+ return ExprError();
+ }
+ }
+ } else {
+ // OpenMP 4.0, [2.4 Array Sections]
+ // When the size of the array dimension is not known, the length must be
+ // specified explicitly.
+ if (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
+ !OriginalTy->isVariableArrayType())) {
+ Diag(ColonLoc, diag::err_section_length_undefined);
+ return ExprError();
+ }
+ }
+
+ Expr *LengthExpr = Length;
+ if (!LengthExpr) {
+ if (auto *CAT =
+ dyn_cast<ConstantArrayType>(OriginalTy->getAsArrayTypeUnsafe())) {
+ llvm::APInt SizeVal = CAT->getSize();
+ LengthExpr = IntegerLiteral::Create(Context, SizeVal,
+ Context.getIntPtrType(), RBLoc);
+ } else {
+ auto *VAT = cast<VariableArrayType>(OriginalTy->getAsArrayTypeUnsafe());
+ LengthExpr = VAT->getSizeExpr();
+ }
+ if (LowerBound) {
+ LengthExpr = BuildBinOp(S, RBLoc, BO_Sub, LengthExpr, LowerBound).get();
+ if (!LengthExpr)
+ return ExprError();
+ }
+ }
+ ResultType = Context.getVariableArrayType(
+ ResultType, LengthExpr, ArrayType::ArraySection, /*IndexTypeQuals=*/0,
+ SourceRange(LBLoc, RBLoc));
+ return new (Context)
+ ArraySectionExpr(Base, LowerBound, Length, ResultType, VK_LValue,
+ OK_Ordinary, ColonLoc, RBLoc);
+}
+
ExprResult
Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
Expr *Idx, SourceLocation RLoc) {
@@ -4019,6 +4202,8 @@
// and index from the expression types.
Expr *BaseExpr, *IndexExpr;
QualType ResultType;
+ LHSTy = getNonArraySectionType(LHSTy);
+ RHSTy = getNonArraySectionType(RHSTy);
if (LHSTy->isDependentType() || RHSTy->isDependentType()) {
BaseExpr = LHSExp;
IndexExpr = RHSExp;
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -5750,6 +5750,10 @@
return EvalAddr(cast<ArraySubscriptExpr>(E)->getBase(), refVars,ParentDecl);
}
+ case Stmt::ArraySectionExprClass: {
+ return EvalAddr(cast<ArraySectionExpr>(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 +8466,13 @@
AllowOnePastEnd > 0);
return;
}
+ case Stmt::ArraySectionExprClass: {
+ const ArraySectionExpr *ASE = cast<ArraySectionExpr>(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);
Index: lib/Sema/SemaExceptionSpec.cpp
===================================================================
--- lib/Sema/SemaExceptionSpec.cpp
+++ lib/Sema/SemaExceptionSpec.cpp
@@ -1059,6 +1059,7 @@
// Some might be dependent for other reasons.
case Expr::ArraySubscriptExprClass:
+ case Expr::ArraySectionExprClass:
case Expr::BinaryOperatorClass:
case Expr::CompoundAssignOperatorClass:
case Expr::CStyleCastExprClass:
Index: lib/Sema/SemaOverload.cpp
===================================================================
--- lib/Sema/SemaOverload.cpp
+++ lib/Sema/SemaOverload.cpp
@@ -1388,6 +1388,17 @@
StandardConversionSequence &SCS,
bool CStyle);
+static QualType getNonArraySectionType(QualType Ty) {
+ if (!Ty.isNull() && Ty->isArrayType()) {
+ while (!Ty.isNull() && Ty->isArrayType() &&
+ Ty->getAsArrayTypeUnsafe()->getSizeModifier() ==
+ ArrayType::ArraySection) {
+ Ty = Ty->getAsArrayTypeUnsafe()->getElementType();
+ }
+ }
+ return Ty;
+}
+
/// IsStandardConversion - Determines whether there is a standard
/// conversion sequence (C++ [conv], C++ [over.ics.scs]) from the
/// expression From to the type ToType. Standard conversion sequences
@@ -1478,6 +1489,7 @@
// A glvalue (3.10) of a non-function, non-array type T can
// be converted to a prvalue.
bool argIsLValue = From->isGLValue();
+ FromType = getNonArraySectionType(FromType);
if (argIsLValue &&
!FromType->isFunctionType() && !FromType->isArrayType() &&
S.Context.getCanonicalType(FromType) != S.Context.OverloadTy) {
Index: lib/Sema/SemaOpenMP.cpp
===================================================================
--- lib/Sema/SemaOpenMP.cpp
+++ lib/Sema/SemaOpenMP.cpp
@@ -6536,10 +6536,11 @@
// 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 *ASecE = dyn_cast<ArraySectionExpr>(SimpleExpr);
+ if (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
+ (!ASE && !DE && !ASecE) || (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)
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -1857,6 +1857,18 @@
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 RebuildArraySectionExpr(Expr *Base, SourceLocation LBracketLoc,
+ Expr *LowerBound, SourceLocation ColonLoc,
+ Expr *Length, SourceLocation RBracketLoc) {
+ return getSema().ActOnArraySectionExpr(/*Scope=*/nullptr, Base, LBracketLoc,
+ LowerBound, ColonLoc, Length,
+ RBracketLoc);
+ }
+
/// \brief Build a new call expression.
///
/// By default, performs semantic analysis to build the new expression.
@@ -7829,6 +7841,36 @@
E->getRBracketLoc());
}
+template <typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformArraySectionExpr(ArraySectionExpr *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().RebuildArraySectionExpr(
+ Base.get(), E->getBase()->getLocEnd(), LowerBound.get(), E->getColonLoc(),
+ Length.get(), E->getRBracketLoc());
+}
+
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformCallExpr(CallExpr *E) {
Index: tools/libclang/CIndex.cpp
===================================================================
--- tools/libclang/CIndex.cpp
+++ tools/libclang/CIndex.cpp
@@ -4056,6 +4056,8 @@
return cxstring::createRef("UnaryOperator");
case CXCursor_ArraySubscriptExpr:
return cxstring::createRef("ArraySubscriptExpr");
+ case CXCursor_ArraySectionExpr:
+ return cxstring::createRef("ArraySectionExpr");
case CXCursor_BinaryOperator:
return cxstring::createRef("BinaryOperator");
case CXCursor_CompoundAssignOperator:
Index: tools/libclang/CXCursor.cpp
===================================================================
--- tools/libclang/CXCursor.cpp
+++ tools/libclang/CXCursor.cpp
@@ -328,6 +328,10 @@
K = CXCursor_ArraySubscriptExpr;
break;
+ case Stmt::ArraySectionExprClass:
+ K = CXCursor_ArraySectionExpr;
+ break;
+
case Stmt::BinaryOperatorClass:
K = CXCursor_BinaryOperator;
break;
Index: include/clang-c/Index.h
===================================================================
--- include/clang-c/Index.h
+++ include/clang-c/Index.h
@@ -1982,7 +1982,11 @@
*/
CXCursor_ObjCSelfExpr = 146,
- CXCursor_LastExpr = CXCursor_ObjCSelfExpr,
+ /** \brief OpenMP 4.0 [2.4, Array Section].
+ */
+ CXCursor_ArraySectionExpr = 147,
+
+ CXCursor_LastExpr = CXCursor_ArraySectionExpr,
/* Statements */
CXCursor_FirstStmt = 200,
Index: include/clang/Serialization/ASTBitCodes.h
===================================================================
--- include/clang/Serialization/ASTBitCodes.h
+++ include/clang/Serialization/ASTBitCodes.h
@@ -1401,6 +1401,7 @@
STMT_OMP_TASKGROUP_DIRECTIVE,
STMT_OMP_CANCELLATION_POINT_DIRECTIVE,
STMT_OMP_CANCEL_DIRECTIVE,
+ EXPR_ARRAY_SECTION,
// ARC
EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -57,6 +57,7 @@
friend class ColonProtectionRAIIObject;
friend class InMessageExpressionRAIIObject;
friend class PoisonSEHIdentifiersRAIIObject;
+ friend class ArraySectionExpressionRAIIObject;
friend class ObjCDeclContextSwitch;
friend class ParenBraceBracketBalancer;
friend class BalancedDelimiterTracker;
@@ -181,6 +182,11 @@
/// ColonProtectionRAIIObject RAII object.
bool ColonIsSacred;
+ /// \brief If true, parsing of array sections is supported. Otherwise, only
+ /// array subscripts are allowed. This is managed by the
+ /// ArraySectionExpressionRAIIObject RAII object.
+ bool ArraySectionAllowed;
+
/// \brief When true, we are directly inside an Objective-C message
/// send expression.
///
Index: include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- include/clang/AST/RecursiveASTVisitor.h
+++ include/clang/AST/RecursiveASTVisitor.h
@@ -2232,6 +2232,7 @@
// over the children.
DEF_TRAVERSE_STMT(AddrLabelExpr, {})
DEF_TRAVERSE_STMT(ArraySubscriptExpr, {})
+DEF_TRAVERSE_STMT(ArraySectionExpr, {})
DEF_TRAVERSE_STMT(BlockExpr, {
TRY_TO(TraverseDecl(S->getBlockDecl()));
return true; // no child statements to loop through.
Index: include/clang/AST/DataRecursiveASTVisitor.h
===================================================================
--- include/clang/AST/DataRecursiveASTVisitor.h
+++ include/clang/AST/DataRecursiveASTVisitor.h
@@ -2200,6 +2200,7 @@
// over the children.
DEF_TRAVERSE_STMT(AddrLabelExpr, {})
DEF_TRAVERSE_STMT(ArraySubscriptExpr, {})
+DEF_TRAVERSE_STMT(ArraySectionExpr, {})
DEF_TRAVERSE_STMT(BlockExpr, {
TRY_TO(TraverseDecl(S->getBlockDecl()));
return true; // no child statements to loop through.
Index: include/clang/AST/Type.h
===================================================================
--- include/clang/AST/Type.h
+++ include/clang/AST/Type.h
@@ -2400,7 +2400,7 @@
/// with a star size (e.g. int X[*]).
/// 'static' is only allowed on function parameters.
enum ArraySizeModifier {
- Normal, Static, Star
+ Normal, Static, Star, ArraySection
};
private:
/// ElementType - The element type of the array.
Index: include/clang/AST/Expr.h
===================================================================
--- include/clang/AST/Expr.h
+++ include/clang/AST/Expr.h
@@ -2142,6 +2142,110 @@
}
};
+/// \brief OpenMP 4.0 [2.4, Array Sections].
+/// To specify an array section in an OpenMP construct, array subscript
+/// expressions are extended with the following syntax:
+/// \code
+/// [ lower-bound : length ]
+/// [ lower-bound : ]
+/// [ : length ]
+/// [ : ]
+/// \endcode
+/// The array section must be a subset of the original array.
+/// Array sections are allowed on multidimensional arrays. Base language array
+/// subscript expressions can be used to specify length-one dimensions of
+/// multidimensional array sections.
+/// The lower-bound and length are integral type expressions. When evaluated
+/// they represent a set of integer values as follows:
+/// \code
+/// { lower-bound, lower-bound + 1, lower-bound + 2,... , lower-bound + length -
+/// 1 }
+/// \endcode
+/// The lower-bound and length must evaluate to non-negative integers.
+/// When the size of the array dimension is not known, the length must be
+/// specified explicitly.
+/// When the length is absent, it defaults to the size of the array dimension
+/// minus the lower-bound.
+/// When the lower-bound is absent it defaults to 0.
+class ArraySectionExpr : public Expr {
+ enum { BASE, LOWER_BOUND, LENGTH, END_EXPR };
+ Stmt *SubExprs[END_EXPR];
+ SourceLocation ColonLoc;
+ SourceLocation RBracketLoc;
+
+public:
+ ArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, QualType Type,
+ ExprValueKind VK, ExprObjectKind OK, SourceLocation ColonLoc,
+ SourceLocation RBracketLoc)
+ : Expr(
+ ArraySectionExprClass, Type, VK, OK,
+ Base->isTypeDependent() ||
+ (LowerBound && LowerBound->isTypeDependent()) ||
+ (Length && Length->isTypeDependent()),
+ Base->isValueDependent() ||
+ (LowerBound && LowerBound->isValueDependent()) ||
+ (Length && Length->isValueDependent()),
+ Base->isInstantiationDependent() ||
+ (LowerBound && LowerBound->isInstantiationDependent()) ||
+ (Length && Length->isInstantiationDependent()),
+ Base->containsUnexpandedParameterPack() ||
+ (LowerBound && LowerBound->containsUnexpandedParameterPack()) ||
+ (Length && Length->containsUnexpandedParameterPack())),
+ ColonLoc(ColonLoc), RBracketLoc(RBracketLoc) {
+ SubExprs[BASE] = Base;
+ SubExprs[LOWER_BOUND] = LowerBound;
+ SubExprs[LENGTH] = Length;
+ }
+
+ /// \brief Create an empty array section expression.
+ explicit ArraySectionExpr(EmptyShell Shell)
+ : Expr(ArraySectionExprClass, Shell) {}
+
+ /// An array section can be written only as Base[LowerBound:Length].
+
+ /// \brief Get base of the array section.
+ Expr *getBase() { return cast<Expr>(SubExprs[BASE]); }
+ const Expr *getBase() const { return cast<Expr>(SubExprs[BASE]); }
+ /// \brief Set base of the array section.
+ void setBase(Expr *E) { SubExprs[BASE] = E; }
+
+ /// \brief Get lower bound of array section.
+ Expr *getLowerBound() { return cast_or_null<Expr>(SubExprs[LOWER_BOUND]); }
+ const Expr *getLowerBound() const {
+ return cast_or_null<Expr>(SubExprs[LOWER_BOUND]);
+ }
+ /// \brief Set lower bound of the array section.
+ void setLowerBound(Expr *E) { SubExprs[LOWER_BOUND] = E; }
+
+ /// \brief Get length of array section.
+ Expr *getLength() { return cast_or_null<Expr>(SubExprs[LENGTH]); }
+ const Expr *getLength() const { return cast_or_null<Expr>(SubExprs[LENGTH]); }
+ /// \brief Set length of the array section.
+ void setLength(Expr *E) { SubExprs[LENGTH] = E; }
+
+ SourceLocation getLocStart() const LLVM_READONLY {
+ return getBase()->getLocStart();
+ }
+ SourceLocation getLocEnd() const LLVM_READONLY { return RBracketLoc; }
+
+ SourceLocation getColonLoc() const { return ColonLoc; }
+ void setColonLoc(SourceLocation L) { ColonLoc = L; }
+
+ SourceLocation getRBracketLoc() const { return RBracketLoc; }
+ void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
+
+ SourceLocation getExprLoc() const LLVM_READONLY {
+ return getBase()->getExprLoc();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ArraySectionExprClass;
+ }
+
+ child_range children() {
+ return child_range(&SubExprs[BASE], &SubExprs[END_EXPR]);
+ }
+};
/// CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
/// CallExpr itself represents a normal function call, e.g., "f(x, 2)",
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -3787,6 +3787,9 @@
Expr *Idx, SourceLocation RLoc);
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
Expr *Idx, SourceLocation RLoc);
+ ExprResult ActOnArraySectionExpr(Scope *S, Expr *Base, SourceLocation LBLoc,
+ Expr *LowerBound, SourceLocation ColonLoc,
+ Expr *Length, SourceLocation RBLoc);
// This struct is for use by ActOnMemberAccess to allow
// BuildMemberReferenceExpr to be able to reinvoke ActOnMemberAccess after
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -4892,6 +4892,21 @@
def warn_subscript_is_char : Warning<"array subscript is of type 'char'">,
InGroup<CharSubscript>, DefaultIgnore;
+def err_typecheck_section_value : Error<
+ "subscripted value is not an array or pointer">;
+def err_typecheck_section_not_integer : Error<
+ "array section %select{lower bound|length}0 is not an integer">;
+def err_section_function_type : Error<
+ "section of pointer to function type %0">;
+def warn_section_is_char : Warning<"array section %select{lower bound|length}0 is of \
type 'char'">, + InGroup<CharSubscript>, DefaultIgnore;
+def err_section_incomplete_type : Error<
+ "section of pointer to incomplete type %0">;
+def err_section_negative : Error<
+ "section %select{lower bound|length}0 is evaluated to a negative value">;
+def err_section_length_undefined : Error<
+ "section length is undefined, but subscripted value is not a sized array">;
+
def err_typecheck_incomplete_tag : Error<"incomplete definition of type %0">;
def err_no_member : Error<"no member named %0 in %1">;
def err_no_member_overloaded_arrow : Error<
Index: include/clang/Basic/StmtNodes.td
===================================================================
--- include/clang/Basic/StmtNodes.td
+++ include/clang/Basic/StmtNodes.td
@@ -62,6 +62,7 @@
def OffsetOfExpr : DStmt<Expr>;
def UnaryExprOrTypeTraitExpr : DStmt<Expr>;
def ArraySubscriptExpr : DStmt<Expr>;
+def ArraySectionExpr : DStmt<Expr>;
def CallExpr : DStmt<Expr>;
def MemberExpr : DStmt<Expr>;
def CastExpr : DStmt<Expr, 1>;
Index: test/OpenMP/task_ast_print.cpp
===================================================================
--- test/OpenMP/task_ast_print.cpp
+++ test/OpenMP/task_ast_print.cpp
@@ -33,7 +33,8 @@
T b = argc, c, d, e, f, g;
static T a;
S<T> s;
-#pragma omp task untied depend(in : argc)
+ T arr[argc];
+#pragma omp task untied depend(in : argc, argv[b:argc], arr[:])
a = 2;
#pragma omp task default(none), private(argc, b) firstprivate(argv) shared(d) if \
(argc > 0) final(S<T>::TS > 0) foo();
@@ -46,7 +47,8 @@
// CHECK-NEXT: int b = argc, c, d, e, f, g;
// CHECK-NEXT: static int a;
// CHECK-NEXT: S<int> s;
-// CHECK-NEXT: #pragma omp task untied depend(in : argc)
+// CHECK-NEXT: int arr[argc];
+// CHECK-NEXT: #pragma omp task untied depend(in : argc,argv[b:argc],arr[:])
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) \
shared(d) if(argc > 0) final(S<int>::TS > 0) // CHECK-NEXT: foo()
@@ -56,7 +58,8 @@
// CHECK-NEXT: long b = argc, c, d, e, f, g;
// CHECK-NEXT: static long a;
// CHECK-NEXT: S<long> s;
-// CHECK-NEXT: #pragma omp task untied depend(in : argc)
+// CHECK-NEXT: long arr[argc];
+// CHECK-NEXT: #pragma omp task untied depend(in : argc,argv[b:argc],arr[:])
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) \
shared(d) if(argc > 0) final(S<long>::TS > 0) // CHECK-NEXT: foo()
@@ -66,7 +69,8 @@
// CHECK-NEXT: T b = argc, c, d, e, f, g;
// CHECK-NEXT: static T a;
// CHECK-NEXT: S<T> s;
-// CHECK-NEXT: #pragma omp task untied depend(in : argc)
+// CHECK-NEXT: T arr[argc];
+// CHECK-NEXT: #pragma omp task untied depend(in : argc,argv[b:argc],arr[:])
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) \
shared(d) if(argc > 0) final(S<T>::TS > 0) // CHECK-NEXT: foo()
@@ -79,15 +83,16 @@
long x;
int b = argc, c, d, e, f, g;
static int a;
+ int arr[10];
#pragma omp threadprivate(a)
Enum ee;
// CHECK: Enum ee;
-#pragma omp task untied mergeable depend(out:argv[1])
- // CHECK-NEXT: #pragma omp task untied mergeable depend(out : argv[1])
+#pragma omp task untied mergeable depend(out:argv[1], arr[0:])
+ // CHECK-NEXT: #pragma omp task untied mergeable depend(out : argv[1],arr[0:])
a = 2;
// CHECK-NEXT: a = 2;
-#pragma omp task default(none), private(argc, b) firstprivate(argv) if (argc > 0) \
final(a > 0) depend(inout : a)
- // CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) \
if(argc > 0) final(a > 0) depend(inout : a) +#pragma omp task default(none), \
private(argc, b) firstprivate(argv) if (argc > 0) final(a > 0) depend(inout : a, \
argv[:argc],arr[:a]) + // CHECK-NEXT: #pragma omp task default(none) private(argc,b) \
firstprivate(argv) if(argc > 0) final(a > 0) depend(inout : a,argv[:argc],arr[:a]) \
foo(); // CHECK-NEXT: foo();
return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x);
Index: test/OpenMP/task_depend_messages.cpp
===================================================================
--- test/OpenMP/task_depend_messages.cpp
+++ test/OpenMP/task_depend_messages.cpp
@@ -33,6 +33,20 @@
#pragma omp task depend (in : ) // expected-error {{expected expression}}
#pragma omp task depend (in : main) // expected-error {{expected variable name, \
array element or array section}} #pragma omp task depend(in : a[0]) // \
expected-error{{expected variable name, array element or array section}} + #pragma \
omp task depend (in : vec[1:2]) // expected-error {{ value is not an array or \
pointer}} + #pragma omp task depend (in : argv[ // expected-error {{expected \
expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} \
expected-note {{to match this '['}} expected-note {{to match this '('}} + #pragma \
omp task depend (in : argv[: // expected-error {{expected expression}} expected-error \
{{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} \
expected-note {{to match this '('}} + #pragma omp task depend (in : argv[:] // \
expected-error {{section length is undefined, but subscripted value is not a sized \
array}} expected-error {{expected ')'}} expected-note {{to match this '('}} + \
#pragma omp task depend (in : argv[argc: // expected-error {{expected expression}} \
expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to \
match this '['}} expected-note {{to match this '('}} + #pragma omp task depend (in : \
argv[argc:argc] // expected-error {{expected ')'}} expected-note {{to match this \
'('}} + #pragma omp task depend (in : argv[0:-1]) // expected-error {{section length \
is evaluated to a negative value}} + #pragma omp task depend (in : argv[-1:0]) // \
expected-error {{section lower bound is evaluated to a negative value}} + #pragma \
omp task depend (in : argv[:]) // expected-error {{section length is undefined, but \
subscripted value is not a sized array}} + #pragma omp task depend (in : \
argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}} + \
#pragma omp task depend(in:a[0:1]) // expected-error {{subscripted value is not an \
array or pointer}} + #pragma omp task depend(in:argv[argv[:]:1]) // expected-error \
{{expected expression}} expected-error {{expected ']'}} expected-note {{to match this \
'['}} + #pragma omp task depend(in:argv[0:][:]) // expected-error {{section length \
is undefined, but subscripted value is not a sized array}} + #pragma omp task \
depend(in : argv[ : argc][1 : argc - 1]) foo();
return 0;
_______________________________________________
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic