Combined with da986511fb9da1a46a0ca4dba2e49e2426036303 this broke Chromium's build. See https://bugs.chromium.org/p/chromium/issues/detail?id=1168494#c1 for a repro.
I've reverted this change and the changes that depended on it in 8ba442bc2136c9ab91c74826db7195e406b94fb7 in the meantime. On Tue, Jan 19, 2021 at 6:06 AM Richard Smith via cfe-commits <cfe-commits@lists.llvm.org> wrote: > > > Author: Richard Smith > Date: 2021-01-18T21:05:01-08:00 > New Revision: 5a391d38ac6c561ba908334d427f26124ed9132e > > URL: > https://github.com/llvm/llvm-project/commit/5a391d38ac6c561ba908334d427f26124ed9132e > DIFF: > https://github.com/llvm/llvm-project/commit/5a391d38ac6c561ba908334d427f26124ed9132e.diff > > LOG: Following up on PR48517, fix handling of template arguments that refer > to dependent declarations. > > Treat an id-expression that names a local variable in a templated > function as being instantiation-dependent. > > This addresses a language defect whereby a reference to a dependent > declaration can be formed without any construct being value-dependent. > Fixing that through value-dependence turns out to be problematic, so > instead this patch takes the approach (proposed on the core reflector) > of allowing the use of pointers or references to (but not values of) > dependent declarations inside value-dependent expressions, and instead > treating template arguments as dependent if they evaluate to a constant > involving such dependent declarations. > > This ends up affecting a bunch of OpenMP tests, due to OpenMP > imprecisely handling instantiation-dependent constructs, bailing out > early instead of processing dependent constructs to the extent possible > when handling the template. > > Previously committed as 8c1f2d15b826591cdf6bd6b468b8a7d23377b29e, and > reverted because a dependency commit was reverted. > > Added: > clang/test/SemaTemplate/temp_arg_nontype_cxx17.cpp > > Modified: > clang/include/clang/AST/Expr.h > clang/include/clang/AST/TemplateBase.h > clang/include/clang/Sema/Sema.h > clang/lib/AST/ComputeDependence.cpp > clang/lib/AST/Expr.cpp > clang/lib/AST/ExprCXX.cpp > clang/lib/AST/ExprConstant.cpp > clang/lib/AST/TemplateBase.cpp > clang/lib/Sema/SemaOverload.cpp > clang/lib/Sema/SemaTemplate.cpp > clang/lib/Sema/SemaTemplateInstantiate.cpp > clang/test/OpenMP/distribute_dist_schedule_messages.cpp > clang/test/OpenMP/distribute_parallel_for_dist_schedule_messages.cpp > clang/test/OpenMP/distribute_parallel_for_simd_dist_schedule_messages.cpp > clang/test/OpenMP/distribute_simd_dist_schedule_messages.cpp > clang/test/OpenMP/target_parallel_for_simd_collapse_messages.cpp > clang/test/OpenMP/target_parallel_for_simd_ordered_messages.cpp > clang/test/OpenMP/target_simd_collapse_messages.cpp > clang/test/OpenMP/target_teams_distribute_dist_schedule_messages.cpp > > clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_messages.cpp > > clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_messages.cpp > clang/test/OpenMP/target_teams_distribute_simd_dist_schedule_messages.cpp > clang/test/OpenMP/target_update_from_messages.cpp > clang/test/OpenMP/target_update_to_messages.cpp > clang/test/OpenMP/task_messages.cpp > clang/test/OpenMP/teams_distribute_dist_schedule_messages.cpp > clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_messages.cpp > > clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_messages.cpp > clang/test/OpenMP/teams_distribute_simd_dist_schedule_messages.cpp > clang/test/SemaCXX/warn-unused-lambda-capture.cpp > clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp > > Removed: > clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp > > > ################################################################################ > diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h > index a44d06967431..c963be98d3cb 100644 > --- a/clang/include/clang/AST/Expr.h > +++ b/clang/include/clang/AST/Expr.h > @@ -578,12 +578,12 @@ class Expr : public ValueStmt { > struct EvalStatus { > /// Whether the evaluated expression has side effects. > /// For example, (f() && 0) can be folded, but it still has side effects. > - bool HasSideEffects; > + bool HasSideEffects = false; > > /// Whether the evaluation hit undefined behavior. > /// For example, 1.0 / 0.0 can be folded to Inf, but has undefined > behavior. > /// Likewise, INT_MAX + 1 can be folded to INT_MIN, but has UB. > - bool HasUndefinedBehavior; > + bool HasUndefinedBehavior = false; > > /// Diag - If this is non-null, it will be filled in with a stack of > notes > /// indicating why evaluation failed (or why it failed to produce a > constant > @@ -592,10 +592,7 @@ class Expr : public ValueStmt { > /// foldable. If the expression is foldable, but not a constant > expression, > /// the notes will describes why it isn't a constant expression. If the > /// expression *is* a constant expression, no notes will be produced. > - SmallVectorImpl<PartialDiagnosticAt> *Diag; > - > - EvalStatus() > - : HasSideEffects(false), HasUndefinedBehavior(false), Diag(nullptr) > {} > + SmallVectorImpl<PartialDiagnosticAt> *Diag = nullptr; > > // hasSideEffects - Return true if the evaluated expression has > // side effects. > @@ -606,8 +603,11 @@ class Expr : public ValueStmt { > > /// EvalResult is a struct with detailed info about an evaluated > expression. > struct EvalResult : EvalStatus { > - /// Val - This is the value the expression can be folded to. > + /// This is the value the expression can be folded to. > APValue Val; > + /// Indicates whether Val contains a pointer or reference or pointer to > + /// member naming a templated entity, and thus the value is dependent. > + bool Dependent = false; > > // isGlobalLValue - Return true if the evaluated lvalue expression > // is global. > > diff --git a/clang/include/clang/AST/TemplateBase.h > b/clang/include/clang/AST/TemplateBase.h > index 1671637521e2..5fbb25c315cf 100644 > --- a/clang/include/clang/AST/TemplateBase.h > +++ b/clang/include/clang/AST/TemplateBase.h > @@ -252,6 +252,12 @@ class TemplateArgument { > /// Whether this template argument is dependent on a template > /// parameter such that its result can change from one instantiation to > /// another. > + /// > + /// It's not always meaningful to ask whether a template argument is > + /// dependent before it's been converted to match a template parameter; > + /// whether a non-type template argument is dependent depends on the > + /// corresponding parameter. For an unconverted template argument, this > + /// returns true if the argument *might* be dependent. > bool isDependent() const; > > /// Whether this template argument is dependent on a template > @@ -674,13 +680,6 @@ struct alignas(void *) ASTTemplateKWAndArgsInfo { > void initializeFrom(SourceLocation TemplateKWLoc, > const TemplateArgumentListInfo &List, > TemplateArgumentLoc *OutArgArray); > - // FIXME: The parameter Deps is the result populated by this method, the > - // caller doesn't need it since it is populated by computeDependence. > remove > - // it. > - void initializeFrom(SourceLocation TemplateKWLoc, > - const TemplateArgumentListInfo &List, > - TemplateArgumentLoc *OutArgArray, > - TemplateArgumentDependence &Deps); > void initializeFrom(SourceLocation TemplateKWLoc); > > void copyInto(const TemplateArgumentLoc *ArgArray, > > diff --git a/clang/include/clang/Sema/Sema.h > b/clang/include/clang/Sema/Sema.h > index 7f7c84eb1b1d..7cdfe24a3a3f 100644 > --- a/clang/include/clang/Sema/Sema.h > +++ b/clang/include/clang/Sema/Sema.h > @@ -3465,7 +3465,8 @@ class Sema final { > llvm::APSInt &Value, CCEKind > CCE); > ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, > APValue &Value, CCEKind CCE, > - NamedDecl *Dest = nullptr); > + NamedDecl *Dest = nullptr, > + bool *ValueDependent = > nullptr); > > /// Abstract base class used to perform a contextual implicit > /// conversion from an expression to any type passing a filter. > > diff --git a/clang/lib/AST/ComputeDependence.cpp > b/clang/lib/AST/ComputeDependence.cpp > index 4026fdc76fd6..5262e3cbe233 100644 > --- a/clang/lib/AST/ComputeDependence.cpp > +++ b/clang/lib/AST/ComputeDependence.cpp > @@ -64,7 +64,7 @@ ExprDependence clang::computeDependence(UnaryOperator *E, > if (VD && VD->isTemplated()) { > auto *VarD = dyn_cast<VarDecl>(VD); > if (!VarD || !VarD->hasLocalStorage()) > - Dep |= ExprDependence::Value; > + Dep |= ExprDependence::ValueInstantiation; > } > } > } > @@ -443,12 +443,21 @@ ExprDependence clang::computeDependence(DeclRefExpr *E, > const ASTContext &Ctx) { > if (auto *FirstArg = E->getTemplateArgs()) { > unsigned NumArgs = E->getNumTemplateArgs(); > for (auto *Arg = FirstArg, *End = FirstArg + NumArgs; Arg < End; ++Arg) > - Deps |= toExprDependence(Arg->getArgument().getDependence()); > + Deps |= toExprDependence(Arg->getArgument().getDependence() & > + ~TemplateArgumentDependence::Dependent); > } > > auto *Decl = E->getDecl(); > + auto *Found = E->getFoundDecl(); > auto Type = E->getType(); > > + // FIXME: For a ParmVarDecl referenced in a function signature, we don't > know > + // its dependence yet! > + if (!isa<ParmVarDecl>(Decl)) { > + if (Decl->getDeclContext()->isDependentContext() || > + (Found && Found->getDeclContext()->isDependentContext())) > + Deps |= ExprDependence::Instantiation; > + } > if (Decl->isParameterPack()) > Deps |= ExprDependence::UnexpandedPack; > Deps |= toExprDependence(Type->getDependence()) & ExprDependence::Error; > > diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp > index 5d7066cc2699..6e12b3be01b2 100644 > --- a/clang/lib/AST/Expr.cpp > +++ b/clang/lib/AST/Expr.cpp > @@ -416,12 +416,9 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx, > RefersToEnclosingVariableOrCapture; > DeclRefExprBits.NonOdrUseReason = NOUR; > if (TemplateArgs) { > - auto Deps = TemplateArgumentDependence::None; > getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( > - TemplateKWLoc, *TemplateArgs, > getTrailingObjects<TemplateArgumentLoc>(), > - Deps); > - assert(!(Deps & TemplateArgumentDependence::Dependent) && > - "built a DeclRefExpr with dependent template args"); > + TemplateKWLoc, *TemplateArgs, > + getTrailingObjects<TemplateArgumentLoc>()); > } else if (TemplateKWLoc.isValid()) { > getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( > TemplateKWLoc); > @@ -1524,16 +1521,8 @@ MemberExpr *MemberExpr::Create( > MemberExpr *E = new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, > MemberDecl, > NameInfo, T, VK, OK, NOUR); > > - // FIXME: remove remaining dependence computation to computeDependence(). > - auto Deps = E->getDependence(); > + // FIXME: Move this into the constructor. > if (HasQualOrFound) { > - // FIXME: Wrong. We should be looking at the member declaration we found. > - if (QualifierLoc && QualifierLoc.getNestedNameSpecifier()->isDependent()) > - Deps |= ExprDependence::TypeValueInstantiation; > - else if (QualifierLoc && > - > QualifierLoc.getNestedNameSpecifier()->isInstantiationDependent()) > - Deps |= ExprDependence::Instantiation; > - > E->MemberExprBits.HasQualifierOrFoundDecl = true; > > MemberExprNameQualifier *NQ = > @@ -1546,16 +1535,26 @@ MemberExpr *MemberExpr::Create( > TemplateArgs || TemplateKWLoc.isValid(); > > if (TemplateArgs) { > - auto TemplateArgDeps = TemplateArgumentDependence::None; > E->getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( > TemplateKWLoc, *TemplateArgs, > - E->getTrailingObjects<TemplateArgumentLoc>(), TemplateArgDeps); > - if (TemplateArgDeps & TemplateArgumentDependence::Instantiation) > - Deps |= ExprDependence::Instantiation; > + E->getTrailingObjects<TemplateArgumentLoc>()); > } else if (TemplateKWLoc.isValid()) { > E->getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( > TemplateKWLoc); > } > + > + // FIXME: remove remaining dependence computation to computeDependence(). > + auto Deps = E->getDependence(); > + if (NestedNameSpecifier *Qual = E->getQualifier()) { > + // FIXME: Wrong. We should be looking at the member declaration we found. > + if (Qual->isDependent()) > + Deps |= ExprDependence::TypeValueInstantiation; > + else if (Qual->isInstantiationDependent()) > + Deps |= ExprDependence::Instantiation; > + } > + if (TemplateSpecializationType::anyInstantiationDependentTemplateArguments( > + E->template_arguments())) > + Deps |= ExprDependence::Instantiation; > E->setDependence(Deps); > > return E; > > diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp > index 8dc9d4296e14..e1f658923519 100644 > --- a/clang/lib/AST/ExprCXX.cpp > +++ b/clang/lib/AST/ExprCXX.cpp > @@ -433,9 +433,8 @@ OverloadExpr::OverloadExpr(StmtClass SC, const ASTContext > &Context, > } > > if (TemplateArgs) { > - auto Deps = TemplateArgumentDependence::None; > getTrailingASTTemplateKWAndArgsInfo()->initializeFrom( > - TemplateKWLoc, *TemplateArgs, getTrailingTemplateArgumentLoc(), > Deps); > + TemplateKWLoc, *TemplateArgs, getTrailingTemplateArgumentLoc()); > } else if (TemplateKWLoc.isValid()) { > getTrailingASTTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc); > } > @@ -464,9 +463,8 @@ DependentScopeDeclRefExpr::DependentScopeDeclRefExpr( > DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo = > (Args != nullptr) || TemplateKWLoc.isValid(); > if (Args) { > - auto Deps = TemplateArgumentDependence::None; > getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( > - TemplateKWLoc, *Args, getTrailingObjects<TemplateArgumentLoc>(), > Deps); > + TemplateKWLoc, *Args, getTrailingObjects<TemplateArgumentLoc>()); > } else if (TemplateKWLoc.isValid()) { > getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( > TemplateKWLoc); > @@ -1376,10 +1374,9 @@ > CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr( > CXXDependentScopeMemberExprBits.OperatorLoc = OperatorLoc; > > if (TemplateArgs) { > - auto Deps = TemplateArgumentDependence::None; > getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( > - TemplateKWLoc, *TemplateArgs, > getTrailingObjects<TemplateArgumentLoc>(), > - Deps); > + TemplateKWLoc, *TemplateArgs, > + getTrailingObjects<TemplateArgumentLoc>()); > } else if (TemplateKWLoc.isValid()) { > getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom( > TemplateKWLoc); > > diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp > index b153e22259f7..6ec6df09c83f 100644 > --- a/clang/lib/AST/ExprConstant.cpp > +++ b/clang/lib/AST/ExprConstant.cpp > @@ -1819,7 +1819,8 @@ static bool EvaluateFloat(const Expr *E, APFloat > &Result, EvalInfo &Info); > static bool EvaluateComplex(const Expr *E, ComplexValue &Res, EvalInfo > &Info); > static bool EvaluateAtomic(const Expr *E, const LValue *This, APValue > &Result, > EvalInfo &Info); > -static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result); > +static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result, > + bool &Dependent); > > /// Evaluate an integer or fixed point expression into an APResult. > static bool EvaluateFixedPointOrInteger(const Expr *E, APFixedPoint &Result, > @@ -2107,7 +2108,8 @@ static bool > CheckEvaluationResult(CheckEvaluationResultKind CERK, > QualType Type, const APValue &Value, > ConstantExprKind Kind, > SourceLocation SubobjectLoc, > - CheckedTemporaries &CheckedTemps); > + CheckedTemporaries &CheckedTemps, > + bool &Dependent); > > /// Check that this reference or pointer core constant expression is a valid > /// value for an address or reference constant expression. Return true if we > @@ -2115,7 +2117,8 @@ static bool > CheckEvaluationResult(CheckEvaluationResultKind CERK, > static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc, > QualType Type, const LValue &LVal, > ConstantExprKind Kind, > - CheckedTemporaries &CheckedTemps) { > + CheckedTemporaries &CheckedTemps, > + bool &Dependent) { > bool IsReferenceType = Type->isReferenceType(); > > APValue::LValueBase Base = LVal.getLValueBase(); > @@ -2200,6 +2203,8 @@ static bool CheckLValueConstantExpression(EvalInfo > &Info, SourceLocation Loc, > } > > if (BaseVD) { > + Dependent |= BaseVD->isTemplated(); > + > if (const VarDecl *Var = dyn_cast<const VarDecl>(BaseVD)) { > // Check if this is a thread-local variable. > if (Var->getTLSKind()) > @@ -2230,6 +2235,9 @@ static bool CheckLValueConstantExpression(EvalInfo > &Info, SourceLocation Loc, > } > } else if (const auto *MTE = > dyn_cast_or_null<MaterializeTemporaryExpr>(BaseE)) { > + if (auto *Extending = MTE->getExtendingDecl()) > + Dependent |= Extending->isTemplated(); > + > if (CheckedTemps.insert(MTE).second) { > QualType TempType = getType(Base); > if (TempType.isDestructedType()) { > @@ -2242,8 +2250,8 @@ static bool CheckLValueConstantExpression(EvalInfo > &Info, SourceLocation Loc, > APValue *V = MTE->getOrCreateValue(false); > assert(V && "evasluation result refers to uninitialised temporary"); > if > (!CheckEvaluationResult(CheckEvaluationResultKind::ConstantExpression, > - Info, MTE->getExprLoc(), TempType, *V, > - Kind, SourceLocation(), CheckedTemps)) > + Info, MTE->getExprLoc(), TempType, *V, Kind, > + SourceLocation(), CheckedTemps, Dependent)) > return false; > } > } > @@ -2272,13 +2280,15 @@ static bool CheckLValueConstantExpression(EvalInfo > &Info, SourceLocation Loc, > > /// Member pointers are constant expressions unless they point to a > /// non-virtual dllimport member function. > -static bool CheckMemberPointerConstantExpression(EvalInfo &Info, > - SourceLocation Loc, > - QualType Type, > - const APValue &Value, > - ConstantExprKind Kind) { > +static bool > +CheckMemberPointerConstantExpression(EvalInfo &Info, SourceLocation Loc, > + QualType Type, const APValue &Value, > + ConstantExprKind Kind, bool &Dependent) > { > const ValueDecl *Member = Value.getMemberPointerDecl(); > - const auto *FD = dyn_cast_or_null<CXXMethodDecl>(Member); > + if (!Member) > + return true; > + Dependent |= Member->isTemplated(); > + const auto *FD = dyn_cast<CXXMethodDecl>(Member); > if (!FD) > return true; > if (FD->isConsteval()) { > @@ -2327,7 +2337,8 @@ static bool > CheckEvaluationResult(CheckEvaluationResultKind CERK, > QualType Type, const APValue &Value, > ConstantExprKind Kind, > SourceLocation SubobjectLoc, > - CheckedTemporaries &CheckedTemps) { > + CheckedTemporaries &CheckedTemps, > + bool &Dependent) { > if (!Value.hasValue()) { > Info.FFDiag(DiagLoc, diag::note_constexpr_uninitialized) > << true << Type; > @@ -2349,20 +2360,20 @@ static bool > CheckEvaluationResult(CheckEvaluationResultKind CERK, > for (unsigned I = 0, N = Value.getArrayInitializedElts(); I != N; ++I) { > if (!CheckEvaluationResult(CERK, Info, DiagLoc, EltTy, > Value.getArrayInitializedElt(I), Kind, > - SubobjectLoc, CheckedTemps)) > + SubobjectLoc, CheckedTemps, Dependent)) > return false; > } > if (!Value.hasArrayFiller()) > return true; > return CheckEvaluationResult(CERK, Info, DiagLoc, EltTy, > Value.getArrayFiller(), Kind, SubobjectLoc, > - CheckedTemps); > + CheckedTemps, Dependent); > } > if (Value.isUnion() && Value.getUnionField()) { > return CheckEvaluationResult( > CERK, Info, DiagLoc, Value.getUnionField()->getType(), > Value.getUnionValue(), Kind, Value.getUnionField()->getLocation(), > - CheckedTemps); > + CheckedTemps, Dependent); > } > if (Value.isStruct()) { > RecordDecl *RD = Type->castAs<RecordType>()->getDecl(); > @@ -2371,7 +2382,7 @@ static bool > CheckEvaluationResult(CheckEvaluationResultKind CERK, > for (const CXXBaseSpecifier &BS : CD->bases()) { > if (!CheckEvaluationResult(CERK, Info, DiagLoc, BS.getType(), > Value.getStructBase(BaseIndex), Kind, > - BS.getBeginLoc(), CheckedTemps)) > + BS.getBeginLoc(), CheckedTemps, > Dependent)) > return false; > ++BaseIndex; > } > @@ -2381,8 +2392,8 @@ static bool > CheckEvaluationResult(CheckEvaluationResultKind CERK, > continue; > > if (!CheckEvaluationResult(CERK, Info, DiagLoc, I->getType(), > - Value.getStructField(I->getFieldIndex()), > - Kind, I->getLocation(), CheckedTemps)) > + Value.getStructField(I->getFieldIndex()), > Kind, > + I->getLocation(), CheckedTemps, Dependent)) > return false; > } > } > @@ -2392,12 +2403,13 @@ static bool > CheckEvaluationResult(CheckEvaluationResultKind CERK, > LValue LVal; > LVal.setFrom(Info.Ctx, Value); > return CheckLValueConstantExpression(Info, DiagLoc, Type, LVal, Kind, > - CheckedTemps); > + CheckedTemps, Dependent); > } > > if (Value.isMemberPointer() && > CERK == CheckEvaluationResultKind::ConstantExpression) > - return CheckMemberPointerConstantExpression(Info, DiagLoc, Type, Value, > Kind); > + return CheckMemberPointerConstantExpression(Info, DiagLoc, Type, Value, > + Kind, Dependent); > > // Everything else is fine. > return true; > @@ -2408,7 +2420,7 @@ static bool > CheckEvaluationResult(CheckEvaluationResultKind CERK, > /// check that the expression is of literal type. > static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc, > QualType Type, const APValue &Value, > - ConstantExprKind Kind) { > + ConstantExprKind Kind, bool &Dependent) { > // Nothing to check for a constant expression of type 'cv void'. > if (Type->isVoidType()) > return true; > @@ -2416,17 +2428,18 @@ static bool CheckConstantExpression(EvalInfo &Info, > SourceLocation DiagLoc, > CheckedTemporaries CheckedTemps; > return CheckEvaluationResult(CheckEvaluationResultKind::ConstantExpression, > Info, DiagLoc, Type, Value, Kind, > - SourceLocation(), CheckedTemps); > + SourceLocation(), CheckedTemps, Dependent); > } > > /// Check that this evaluated value is fully-initialized and can be loaded by > /// an lvalue-to-rvalue conversion. > static bool CheckFullyInitialized(EvalInfo &Info, SourceLocation DiagLoc, > QualType Type, const APValue &Value) { > + bool Dependent = false; > CheckedTemporaries CheckedTemps; > return CheckEvaluationResult( > CheckEvaluationResultKind::FullyInitialized, Info, DiagLoc, Type, > Value, > - ConstantExprKind::Normal, SourceLocation(), CheckedTemps); > + ConstantExprKind::Normal, SourceLocation(), CheckedTemps, Dependent); > } > > /// Enforce C++2a [expr.const]/4.17, which disallows new-expressions unless > @@ -11098,7 +11111,9 @@ static bool EvaluateBuiltinConstantP(EvalInfo &Info, > const Expr *Arg) { > ArgType->isAnyComplexType() || ArgType->isPointerType() || > ArgType->isNullPtrType()) { > APValue V; > - if (!::EvaluateAsRValue(Info, Arg, V) || Info.EvalStatus.HasSideEffects) > { > + bool Dependent = false; > + if (!::EvaluateAsRValue(Info, Arg, V, Dependent) || > + Info.EvalStatus.HasSideEffects) { > Fold.keepDiagnostics(); > return false; > } > @@ -11400,7 +11415,8 @@ static bool tryEvaluateBuiltinObjectSize(const Expr > *E, unsigned Type, > // It's possible for us to be given GLValues if we're called via > // Expr::tryEvaluateObjectSize. > APValue RVal; > - if (!EvaluateAsRValue(Info, E, RVal)) > + bool Dependent = false; > + if (!EvaluateAsRValue(Info, E, RVal, Dependent)) > return false; > LVal.setFrom(Info.Ctx, RVal); > } else if (!EvaluatePointer(ignorePointerCastsAndParens(E), LVal, Info, > @@ -12829,8 +12845,9 @@ bool RecordExprEvaluator::VisitBinCmp(const > BinaryOperator *E) { > LV.set(VD); > if (!handleLValueToRValueConversion(Info, E, E->getType(), LV, Result)) > return false; > + bool Dependent = false; > return CheckConstantExpression(Info, E->getExprLoc(), E->getType(), > Result, > - ConstantExprKind::Normal); > + ConstantExprKind::Normal, Dependent); > }; > return EvaluateComparisonBinaryOperator(Info, E, OnSuccess, [&]() { > return ExprEvaluatorBaseTy::VisitBinCmp(E); > @@ -14594,7 +14611,8 @@ static bool EvaluateInPlace(APValue &Result, EvalInfo > &Info, const LValue &This, > > /// EvaluateAsRValue - Try to evaluate this expression, performing an > implicit > /// lvalue-to-rvalue cast if it is an lvalue. > -static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) > { > +static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result, > + bool &Dependent) { > assert(!E->isValueDependent()); > if (Info.EnableNewConstInterp) { > if (!Info.Ctx.getInterpContext().evaluateAsRValue(Info, E, Result)) > @@ -14619,7 +14637,7 @@ static bool EvaluateAsRValue(EvalInfo &Info, const > Expr *E, APValue &Result) { > > // Check this core constant expression is a constant expression. > return CheckConstantExpression(Info, E->getExprLoc(), E->getType(), Result, > - ConstantExprKind::Normal) && > + ConstantExprKind::Normal, Dependent) && > CheckMemoryLeaks(Info); > } > > @@ -14665,7 +14683,7 @@ static bool EvaluateAsRValue(const Expr *E, > Expr::EvalResult &Result, > if (FastEvaluateAsRValue(E, Result, Ctx, IsConst)) > return IsConst; > > - return EvaluateAsRValue(Info, E, Result.Val); > + return EvaluateAsRValue(Info, E, Result.Val, Result.Dependent); > } > > static bool EvaluateAsInt(const Expr *E, Expr::EvalResult &ExprResult, > @@ -14775,9 +14793,9 @@ bool Expr::EvaluateAsLValue(EvalResult &Result, const > ASTContext &Ctx, > CheckedTemporaries CheckedTemps; > if (!EvaluateLValue(this, LV, Info) || !Info.discardCleanups() || > Result.HasSideEffects || > - !CheckLValueConstantExpression(Info, getExprLoc(), > - Ctx.getLValueReferenceType(getType()), > LV, > - ConstantExprKind::Normal, CheckedTemps)) > + !CheckLValueConstantExpression( > + Info, getExprLoc(), Ctx.getLValueReferenceType(getType()), LV, > + ConstantExprKind::Normal, CheckedTemps, Result.Dependent)) > return false; > > LV.moveInto(Result.Val); > @@ -14836,7 +14854,7 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, > const ASTContext &Ctx, > llvm_unreachable("Unhandled cleanup; missing full expression marker?"); > > if (!CheckConstantExpression(Info, getExprLoc(), getStorageType(Ctx, this), > - Result.Val, Kind)) > + Result.Val, Kind, Result.Dependent)) > return false; > if (!CheckMemoryLeaks(Info)) > return false; > @@ -14900,8 +14918,9 @@ bool Expr::EvaluateAsInitializer(APValue &Value, > const ASTContext &Ctx, > if (!Info.discardCleanups()) > llvm_unreachable("Unhandled cleanup; missing full expression marker?"); > } > + bool Dependent = false; > return CheckConstantExpression(Info, DeclLoc, DeclTy, Value, > - ConstantExprKind::Normal) && > + ConstantExprKind::Normal, Dependent) && > CheckMemoryLeaks(Info); > } > > @@ -14968,7 +14987,7 @@ APSInt Expr::EvaluateKnownConstIntCheckOverflow( > Info.InConstantContext = true; > Info.CheckingForUndefinedBehavior = true; > > - bool Result = ::EvaluateAsRValue(Info, this, EVResult.Val); > + bool Result = ::EvaluateAsRValue(this, EVResult, Ctx, Info); > (void)Result; > assert(Result && "Could not evaluate expression"); > assert(EVResult.Val.isInt() && "Expression did not evaluate to integer"); > @@ -14980,13 +14999,10 @@ void Expr::EvaluateForOverflow(const ASTContext > &Ctx) const { > assert(!isValueDependent() && > "Expression evaluator can't be called on a dependent expression."); > > - bool IsConst; > EvalResult EVResult; > - if (!FastEvaluateAsRValue(this, EVResult, Ctx, IsConst)) { > - EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects); > - Info.CheckingForUndefinedBehavior = true; > - (void)::EvaluateAsRValue(Info, this, EVResult.Val); > - } > + EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects); > + Info.CheckingForUndefinedBehavior = true; > + (void)::EvaluateAsRValue(this, EVResult, Ctx, Info); > } > > bool Expr::EvalResult::isGlobalLValue() const { > @@ -15536,8 +15552,9 @@ bool Expr::isCXX11ConstantExpr(const ASTContext &Ctx, > APValue *Result, > EvalInfo Info(Ctx, Status, EvalInfo::EM_ConstantExpression); > > APValue Scratch; > + bool Dependent = false; > bool IsConstExpr = > - ::EvaluateAsRValue(Info, this, Result ? *Result : Scratch) && > + ::EvaluateAsRValue(Info, this, Result ? *Result : Scratch, Dependent) > && > // FIXME: We don't produce a diagnostic for this, but the callers that > // call us on arbitrary full-expressions should generally not care. > Info.discardCleanups() && !Status.HasSideEffects; > > diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp > index baf62bd115a8..8cbb595b5bd1 100644 > --- a/clang/lib/AST/TemplateBase.cpp > +++ b/clang/lib/AST/TemplateBase.cpp > @@ -131,25 +131,17 @@ TemplateArgumentDependence > TemplateArgument::getDependence() const { > return TemplateArgumentDependence::Dependent | > TemplateArgumentDependence::Instantiation; > > - case Declaration: { > - auto *DC = dyn_cast<DeclContext>(getAsDecl()); > - if (!DC) > - DC = getAsDecl()->getDeclContext(); > - if (DC->isDependentContext()) > - Deps = TemplateArgumentDependence::Dependent | > - TemplateArgumentDependence::Instantiation; > - return Deps; > - } > - > case NullPtr: > case Integral: > + case Declaration: > return TemplateArgumentDependence::None; > > case Expression: > Deps = toTemplateArgumentDependence(getAsExpr()->getDependence()); > - if (isa<PackExpansionExpr>(getAsExpr())) > - Deps |= TemplateArgumentDependence::Dependent | > - TemplateArgumentDependence::Instantiation; > + // Instantiation-dependent expression arguments are considered dependent > + // until they're resolved to another form. > + if (Deps & TemplateArgumentDependence::Instantiation) > + Deps |= TemplateArgumentDependence::Dependent; > return Deps; > > case Pack: > @@ -544,8 +536,8 @@ ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo( > NumTemplateArgs = Info.size(); > > TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>(); > - for (unsigned i = 0; i != NumTemplateArgs; ++i) > - new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); > + std::uninitialized_copy(Info.arguments().begin(), Info.arguments().end(), > + ArgBuffer); > } > > void ASTTemplateKWAndArgsInfo::initializeFrom( > @@ -555,9 +547,8 @@ void ASTTemplateKWAndArgsInfo::initializeFrom( > LAngleLoc = Info.getLAngleLoc(); > RAngleLoc = Info.getRAngleLoc(); > NumTemplateArgs = Info.size(); > - > - for (unsigned i = 0; i != NumTemplateArgs; ++i) > - new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]); > + std::uninitialized_copy(Info.arguments().begin(), Info.arguments().end(), > + OutArgArray); > } > > void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) { > @@ -568,21 +559,6 @@ void > ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) { > NumTemplateArgs = 0; > } > > -void ASTTemplateKWAndArgsInfo::initializeFrom( > - SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info, > - TemplateArgumentLoc *OutArgArray, TemplateArgumentDependence &Deps) { > - this->TemplateKWLoc = TemplateKWLoc; > - LAngleLoc = Info.getLAngleLoc(); > - RAngleLoc = Info.getRAngleLoc(); > - NumTemplateArgs = Info.size(); > - > - for (unsigned i = 0; i != NumTemplateArgs; ++i) { > - Deps |= Info[i].getArgument().getDependence(); > - > - new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]); > - } > -} > - > void ASTTemplateKWAndArgsInfo::copyInto(const TemplateArgumentLoc *ArgArray, > TemplateArgumentListInfo &Info) > const { > Info.setLAngleLoc(LAngleLoc); > > diff --git a/clang/lib/Sema/SemaOverload.cpp > b/clang/lib/Sema/SemaOverload.cpp > index 13d2125d1a28..ac52612ea3b0 100644 > --- a/clang/lib/Sema/SemaOverload.cpp > +++ b/clang/lib/Sema/SemaOverload.cpp > @@ -5619,7 +5619,8 @@ static ExprResult CheckConvertedConstantExpression(Sema > &S, Expr *From, > QualType T, APValue > &Value, > Sema::CCEKind CCE, > bool RequireInt, > - NamedDecl *Dest) { > + NamedDecl *Dest, > + bool *ValueDependent) { > assert(S.getLangOpts().CPlusPlus11 && > "converted constant expression outside C++11"); > > @@ -5743,6 +5744,8 @@ static ExprResult CheckConvertedConstantExpression(Sema > &S, Expr *From, > > if (Result.get()->isValueDependent()) { > Value = APValue(); > + if (ValueDependent) > + *ValueDependent = true; > return Result; > } > > @@ -5766,6 +5769,8 @@ static ExprResult CheckConvertedConstantExpression(Sema > &S, Expr *From, > Result = ExprError(); > } else { > Value = Eval.Val; > + if (ValueDependent) > + *ValueDependent = Eval.Dependent; > > if (Notes.empty()) { > // It's a constant expression. > @@ -5796,9 +5801,10 @@ static ExprResult > CheckConvertedConstantExpression(Sema &S, Expr *From, > > ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T, > APValue &Value, CCEKind > CCE, > - NamedDecl *Dest) { > + NamedDecl *Dest, > + bool *ValueDependent) { > return ::CheckConvertedConstantExpression(*this, From, T, Value, CCE, > false, > - Dest); > + Dest, ValueDependent); > } > > ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T, > @@ -5808,7 +5814,8 @@ ExprResult Sema::CheckConvertedConstantExpression(Expr > *From, QualType T, > > APValue V; > auto R = ::CheckConvertedConstantExpression(*this, From, T, V, CCE, true, > - /*Dest=*/nullptr); > + /*Dest=*/nullptr, > + /*ValueDependent=*/nullptr); > if (!R.isInvalid() && !R.get()->isValueDependent()) > Value = V.getInt(); > return R; > > diff --git a/clang/lib/Sema/SemaTemplate.cpp > b/clang/lib/Sema/SemaTemplate.cpp > index 12880b95b9c6..9f314685faf0 100644 > --- a/clang/lib/Sema/SemaTemplate.cpp > +++ b/clang/lib/Sema/SemaTemplate.cpp > @@ -6620,6 +6620,12 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, > Arg, ArgType)) > return true; > > + // Don't build a resolved template argument naming a dependent declaration. > + if (Entity->isTemplated()) { > + Converted = TemplateArgument(ArgIn); > + return false; > + } > + > // Create the template argument. > Converted = TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()), > S.Context.getCanonicalType(ParamType)); > @@ -6634,8 +6640,6 @@ static bool CheckTemplateArgumentPointerToMember(Sema > &S, > QualType ParamType, > Expr *&ResultArg, > TemplateArgument > &Converted) { > - bool Invalid = false; > - > Expr *Arg = ResultArg; > bool ObjCLifetimeConversion; > > @@ -6651,7 +6655,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema > &S, > // See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773 > bool ExtraParens = false; > while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) { > - if (!Invalid && !ExtraParens) { > + if (!ExtraParens) { > S.Diag(Arg->getBeginLoc(), > S.getLangOpts().CPlusPlus11 > ? diag::warn_cxx98_compat_template_arg_extra_parens > @@ -6680,13 +6684,8 @@ static bool CheckTemplateArgumentPointerToMember(Sema > &S, > ValueDecl *VD = DRE->getDecl(); > if (VD->getType()->isMemberPointerType()) { > if (isa<NonTypeTemplateParmDecl>(VD)) { > - if (Arg->isTypeDependent() || Arg->isValueDependent()) { > - Converted = TemplateArgument(Arg); > - } else { > - VD = cast<ValueDecl>(VD->getCanonicalDecl()); > - Converted = TemplateArgument(VD, ParamType); > - } > - return Invalid; > + Converted = TemplateArgument(Arg); > + return false; > } > } > > @@ -6745,7 +6744,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema > &S, > ValueDecl *D = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl()); > Converted = TemplateArgument(D, S.Context.getCanonicalType(ParamType)); > } > - return Invalid; > + return false; > } > > // We found something else, but we don't know specifically what it is. > @@ -6922,14 +6921,17 @@ ExprResult > Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, > // A template-argument for a non-type template parameter shall be > // a converted constant expression of the type of the > template-parameter. > APValue Value; > + bool ValueDependent = false; > ExprResult ArgResult = CheckConvertedConstantExpression( > - Arg, ParamType, Value, CCEK_TemplateArg, Param); > + Arg, ParamType, Value, CCEK_TemplateArg, Param, &ValueDependent); > if (ArgResult.isInvalid()) > return ExprError(); > > // For a value-dependent argument, CheckConvertedConstantExpression is > - // permitted (and expected) to be unable to determine a value. > - if (ArgResult.get()->isValueDependent()) { > + // permitted (and expected) to be unable to determine a value. We might > find > + // the evaluated result refers to a dependent declaration even though the > + // template argument is not a value-dependent expression. > + if (ValueDependent) { > Converted = TemplateArgument(ArgResult.get()); > return ArgResult; > } > > diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp > b/clang/lib/Sema/SemaTemplateInstantiate.cpp > index 7e0cc2da2f58..49ff7cd33fab 100644 > --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp > +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp > @@ -3227,7 +3227,8 @@ Sema::InstantiateClassMembers(SourceLocation > PointOfInstantiation, > if (FunctionDecl *Pattern = > Function->getInstantiatedFromMemberFunction()) { > > - if (Function->hasAttr<ExcludeFromExplicitInstantiationAttr>()) > + if (TSK != TSK_ImplicitInstantiation && > + Function->hasAttr<ExcludeFromExplicitInstantiationAttr>()) > continue; > > MemberSpecializationInfo *MSInfo = > @@ -3272,7 +3273,8 @@ Sema::InstantiateClassMembers(SourceLocation > PointOfInstantiation, > continue; > > if (Var->isStaticDataMember()) { > - if (Var->hasAttr<ExcludeFromExplicitInstantiationAttr>()) > + if (TSK != TSK_ImplicitInstantiation && > + Var->hasAttr<ExcludeFromExplicitInstantiationAttr>()) > continue; > > MemberSpecializationInfo *MSInfo = > Var->getMemberSpecializationInfo(); > @@ -3289,7 +3291,7 @@ Sema::InstantiateClassMembers(SourceLocation > PointOfInstantiation, > SuppressNew) > continue; > > - if (TSK == TSK_ExplicitInstantiationDefinition) { > + if (TSK != TSK_ExplicitInstantiationDeclaration) { > // C++0x [temp.explicit]p8: > // An explicit instantiation definition that names a class > template > // specialization explicitly instantiates the class template > > diff --git a/clang/test/OpenMP/distribute_dist_schedule_messages.cpp > b/clang/test/OpenMP/distribute_dist_schedule_messages.cpp > index cd232f40feb4..0f7b2172f5a5 100644 > --- a/clang/test/OpenMP/distribute_dist_schedule_messages.cpp > +++ b/clang/test/OpenMP/distribute_dist_schedule_messages.cpp > @@ -35,7 +35,7 @@ T tmain(T argc) { > for (int i = 0; i < 10; ++i) foo(); > #pragma omp distribute dist_schedule (static, S1) // expected-error {{'S1' > does not refer to a value}} > for (int i = 0; i < 10; ++i) foo(); > - #pragma omp distribute dist_schedule (static, argv[1]=2) // expected-error > {{expected ')'}} expected-note {{to match this '('}} expected-error3 > {{expression must have integral or unscoped enumeration type, not 'char *'}} > + #pragma omp distribute dist_schedule (static, argv[1]=2) // expected-error > {{expected ')'}} expected-note {{to match this '('}} expected-error > 2{{expression must have integral or unscoped enumeration type, not 'char *'}} > for (int i = 0; i < 10; ++i) foo(); > return T(); > } > > diff --git > a/clang/test/OpenMP/distribute_parallel_for_dist_schedule_messages.cpp > b/clang/test/OpenMP/distribute_parallel_for_dist_schedule_messages.cpp > index 07e7704dffde..18dcac555f74 100644 > --- a/clang/test/OpenMP/distribute_parallel_for_dist_schedule_messages.cpp > +++ b/clang/test/OpenMP/distribute_parallel_for_dist_schedule_messages.cpp > @@ -54,7 +54,7 @@ T tmain(T argc) { > for (int i = 0; i < 10; ++i) foo(); > #pragma omp target > #pragma omp teams > -#pragma omp distribute parallel for dist_schedule (static, argv[1]=2) // > expected-error {{expected ')'}} expected-note {{to match this '('}} > expected-error3 {{expression must have integral or unscoped enumeration type, > not 'char *'}} > +#pragma omp distribute parallel for dist_schedule (static, argv[1]=2) // > expected-error {{expected ')'}} expected-note {{to match this '('}} > expected-error 2{{expression must have integral or unscoped enumeration type, > not 'char *'}} > for (int i = 0; i < 10; ++i) foo(); > return T(); > } > > diff --git > a/clang/test/OpenMP/distribute_parallel_for_simd_dist_schedule_messages.cpp > b/clang/test/OpenMP/distribute_parallel_for_simd_dist_schedule_messages.cpp > index ed7b19111dee..63f8cfe917cd 100644 > --- > a/clang/test/OpenMP/distribute_parallel_for_simd_dist_schedule_messages.cpp > +++ > b/clang/test/OpenMP/distribute_parallel_for_simd_dist_schedule_messages.cpp > @@ -55,7 +55,7 @@ T tmain(T argc) { > for (int i = 0; i < 10; ++i) foo(); > #pragma omp target > #pragma omp teams > -#pragma omp distribute parallel for simd dist_schedule (static, argv[1]=2) > // expected-error {{expected ')'}} expected-note {{to match this '('}} > expected-error3 {{expression must have integral or unscoped enumeration type, > not 'char *'}} > +#pragma omp distribute parallel for simd dist_schedule (static, argv[1]=2) > // expected-error {{expected ')'}} expected-note {{to match this '('}} > expected-error 2{{expression must have integral or unscoped enumeration type, > not 'char *'}} > for (int i = 0; i < 10; ++i) foo(); > return T(); > } > > diff --git a/clang/test/OpenMP/distribute_simd_dist_schedule_messages.cpp > b/clang/test/OpenMP/distribute_simd_dist_schedule_messages.cpp > index 794681c02646..a6593cfbe0d3 100644 > --- a/clang/test/OpenMP/distribute_simd_dist_schedule_messages.cpp > +++ b/clang/test/OpenMP/distribute_simd_dist_schedule_messages.cpp > @@ -63,7 +63,7 @@ T tmain(T argc) { > for (int i = 0; i < 10; ++i) foo(); > #pragma omp target > #pragma omp teams > -#pragma omp distribute simd dist_schedule (static, argv[1]=2) // > expected-error {{expected ')'}} expected-note {{to match this '('}} > expected-error3 {{expression must have integral or unscoped enumeration type, > not 'char *'}} > +#pragma omp distribute simd dist_schedule (static, argv[1]=2) // > expected-error {{expected ')'}} expected-note {{to match this '('}} > expected-error 2{{expression must have integral or unscoped enumeration type, > not 'char *'}} > for (int i = 0; i < 10; ++i) foo(); > return T(); > } > > diff --git > a/clang/test/OpenMP/target_parallel_for_simd_collapse_messages.cpp > b/clang/test/OpenMP/target_parallel_for_simd_collapse_messages.cpp > index 7acb2587f976..f829874864da 100644 > --- a/clang/test/OpenMP/target_parallel_for_simd_collapse_messages.cpp > +++ b/clang/test/OpenMP/target_parallel_for_simd_collapse_messages.cpp > @@ -46,7 +46,7 @@ T tmain(T argc, S **argv) { > #pragma omp target parallel for simd collapse (S) // expected-error {{'S' > does not refer to a value}} > for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; > > - // expected-error@+1 {{integral constant expression}} expected-note@+1 > 0+{{constant expression}} > + // expected-error@+1 1+{{integral constant expression}} expected-note@+1 > 0+{{constant expression}} > #pragma omp target parallel for simd collapse (j=2) // expected-error > {{expected ')'}} expected-note {{to match this '('}} > for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; > #pragma omp target parallel for simd collapse (1) > > diff --git a/clang/test/OpenMP/target_parallel_for_simd_ordered_messages.cpp > b/clang/test/OpenMP/target_parallel_for_simd_ordered_messages.cpp > index 8dd7f68c25fd..972aa5753e36 100644 > --- a/clang/test/OpenMP/target_parallel_for_simd_ordered_messages.cpp > +++ b/clang/test/OpenMP/target_parallel_for_simd_ordered_messages.cpp > @@ -56,7 +56,7 @@ T tmain(T argc, S **argv) { > for (int i = ST; i < N; i++) > argv[0][i] = argv[0][i] - argv[0][i - ST]; > > -// expected-error@+1 {{integral constant expression}} expected-note@+1 > 0+{{constant expression}} > +// expected-error@+1 {{'ordered' clause with a parameter can not be > specified in '#pragma omp target parallel for simd' directive}} > #pragma omp target parallel for simd ordered(j = 2) // expected-error > {{expected ')'}} expected-note {{to match this '('}} > for (int i = ST; i < N; i++) > argv[0][i] = argv[0][i] - argv[0][i - ST]; > > diff --git a/clang/test/OpenMP/target_simd_collapse_messages.cpp > b/clang/test/OpenMP/target_simd_collapse_messages.cpp > index 00fa3c85279f..d8b0a91f97d7 100644 > --- a/clang/test/OpenMP/target_simd_collapse_messages.cpp > +++ b/clang/test/OpenMP/target_simd_collapse_messages.cpp > @@ -44,7 +44,7 @@ T tmain(T argc, S **argv) { > #pragma omp target simd collapse (S) // expected-error {{'S' does not > refer to a value}} > for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; > > - // expected-error@+1 {{integral constant expression}} expected-note@+1 > 0+{{constant expression}} > + // expected-error@+1 1+{{integral constant expression}} expected-note@+1 > 0+{{constant expression}} > #pragma omp target simd collapse (j=2) // expected-error {{expected ')'}} > expected-note {{to match this '('}} > for (int i = ST; i < N; i++) argv[0][i] = argv[0][i] - argv[0][i-ST]; > #pragma omp target simd collapse (1) > > diff --git > a/clang/test/OpenMP/target_teams_distribute_dist_schedule_messages.cpp > b/clang/test/OpenMP/target_teams_distribute_dist_schedule_messages.cpp > index 69c1e55eeaa3..e31df97ba31c 100644 > --- a/clang/test/OpenMP/target_teams_distribute_dist_schedule_messages.cpp > +++ b/clang/test/OpenMP/target_teams_distribute_dist_schedule_messages.cpp > @@ -45,7 +45,7 @@ T tmain(T argc) { > #pragma omp target teams distribute dist_schedule (static, S1) // > expected-error {{'S1' does not refer to a value}} > for (int i = 0; i < 10; ++i) foo(); > > -#pragma omp target teams distribute dist_schedule (static, argv[1]=2) // > expected-error {{expected ')'}} expected-note {{to match this '('}} > expected-error3 {{expression must have integral or unscoped enumeration type, > not 'char *'}} > +#pragma omp target teams distribute dist_schedule (static, argv[1]=2) // > expected-error {{expected ')'}} expected-note {{to match this '('}} > expected-error 2{{expression must have integral or unscoped enumeration type, > not 'char *'}} > for (int i = 0; i < 10; ++i) foo(); > > return T(); > > diff --git > a/clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_messages.cpp > > b/clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_messages.cpp > index a0efad18668e..4f3c58125446 100644 > --- > a/clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_messages.cpp > +++ > b/clang/test/OpenMP/target_teams_distribute_parallel_for_dist_schedule_messages.cpp > @@ -45,7 +45,7 @@ T tmain(T argc) { > #pragma omp target teams distribute parallel for dist_schedule (static, S1) > // expected-error {{'S1' does not refer to a value}} > for (int i = 0; i < 10; ++i) foo(); > > -#pragma omp target teams distribute parallel for dist_schedule (static, > argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this > '('}} expected-error3 {{expression must have integral or unscoped enumeration > type, not 'char *'}} > +#pragma omp target teams distribute parallel for dist_schedule (static, > argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this > '('}} expected-error 2{{expression must have integral or unscoped enumeration > type, not 'char *'}} > for (int i = 0; i < 10; ++i) foo(); > > return T(); > > diff --git > a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_messages.cpp > > b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_messages.cpp > index ec634c8ac01c..8b272d4358f6 100644 > --- > a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_messages.cpp > +++ > b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_dist_schedule_messages.cpp > @@ -45,7 +45,7 @@ T tmain(T argc) { > #pragma omp target teams distribute parallel for simd dist_schedule (static, > S1) // expected-error {{'S1' does not refer to a value}} > for (int i = 0; i < 10; ++i) foo(); > > -#pragma omp target teams distribute parallel for simd dist_schedule (static, > argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this > '('}} expected-error3 {{expression must have integral or unscoped enumeration > type, not 'char *'}} > +#pragma omp target teams distribute parallel for simd dist_schedule (static, > argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this > '('}} expected-error 2{{expression must have integral or unscoped enumeration > type, not 'char *'}} > for (int i = 0; i < 10; ++i) foo(); > > return T(); > > diff --git > a/clang/test/OpenMP/target_teams_distribute_simd_dist_schedule_messages.cpp > b/clang/test/OpenMP/target_teams_distribute_simd_dist_schedule_messages.cpp > index 507ddabd2fc2..b583c14831e7 100644 > --- > a/clang/test/OpenMP/target_teams_distribute_simd_dist_schedule_messages.cpp > +++ > b/clang/test/OpenMP/target_teams_distribute_simd_dist_schedule_messages.cpp > @@ -45,7 +45,7 @@ T tmain(T argc) { > #pragma omp target teams distribute simd dist_schedule (static, S1) // > expected-error {{'S1' does not refer to a value}} > for (int i = 0; i < 10; ++i) foo(); > > -#pragma omp target teams distribute simd dist_schedule (static, argv[1]=2) > // expected-error {{expected ')'}} expected-note {{to match this '('}} > expected-error3 {{expression must have integral or unscoped enumeration type, > not 'char *'}} > +#pragma omp target teams distribute simd dist_schedule (static, argv[1]=2) > // expected-error {{expected ')'}} expected-note {{to match this '('}} > expected-error 2{{expression must have integral or unscoped enumeration type, > not 'char *'}} > for (int i = 0; i < 10; ++i) foo(); > > return T(); > > diff --git a/clang/test/OpenMP/target_update_from_messages.cpp > b/clang/test/OpenMP/target_update_from_messages.cpp > index 3dc377c4ca4c..42ecc2814e12 100644 > --- a/clang/test/OpenMP/target_update_from_messages.cpp > +++ b/clang/test/OpenMP/target_update_from_messages.cpp > @@ -131,7 +131,7 @@ T tmain(T argc) { > #pragma omp target update from(x, s7.s6[:5].aa[6]) // expected-error > {{OpenMP array section is not allowed here}} > #pragma omp target update from(x, s7.s6[:5].aa[:6]) // expected-error > {{OpenMP array section is not allowed here}} > #pragma omp target update from(s7.p[:10]) > -#pragma omp target update from(x, s7.bfa) // expected-error {{bit fields > cannot be used to specify storage in a 'from' clause}} > +#pragma omp target update from(x, s7.bfa) // expected-error 2{{bit fields > cannot be used to specify storage in a 'from' clause}} > #pragma omp target update from(x, s7.p[:]) // expected-error {{section > length is unspecified and cannot be inferred because subscripted value is not > an array}} > #pragma omp target data map(to: s7.i) > { > > diff --git a/clang/test/OpenMP/target_update_to_messages.cpp > b/clang/test/OpenMP/target_update_to_messages.cpp > index fca4e21304fc..941c781119e6 100644 > --- a/clang/test/OpenMP/target_update_to_messages.cpp > +++ b/clang/test/OpenMP/target_update_to_messages.cpp > @@ -138,7 +138,7 @@ T tmain(T argc) { > #pragma omp target update to(x, s7.s6[:5].aa[6]) // expected-error {{OpenMP > array section is not allowed here}} > #pragma omp target update to(x, s7.s6[:5].aa[:6]) // expected-error {{OpenMP > array section is not allowed here}} > #pragma omp target update to(s7.p[:10]) > -#pragma omp target update to(x, s7.bfa) // expected-error {{bit fields > cannot be used to specify storage in a 'to' clause}} > +#pragma omp target update to(x, s7.bfa) // expected-error 2{{bit fields > cannot be used to specify storage in a 'to' clause}} > #pragma omp target update to(x, s7.p[:]) // expected-error {{section length > is unspecified and cannot be inferred because subscripted value is not an > array}} > #pragma omp target data map(to: s7.i) > { > > diff --git a/clang/test/OpenMP/task_messages.cpp > b/clang/test/OpenMP/task_messages.cpp > index 13cbfb6c4569..2f9ee9a44402 100644 > --- a/clang/test/OpenMP/task_messages.cpp > +++ b/clang/test/OpenMP/task_messages.cpp > @@ -156,11 +156,11 @@ int foo() { > #pragma omp task detach(a) // omp45-error {{unexpected OpenMP clause > 'detach' in directive '#pragma omp task'}} omp50-error {{expected variable of > the 'omp_event_handle_t' type, not 'int'}} omp50-error {{expected variable of > the 'omp_event_handle_t' type, not 'S'}} > ; > #pragma omp task detach(evt) detach(evt) // omp45-error 2 {{unexpected > OpenMP clause 'detach' in directive '#pragma omp task'}} expected-error > {{directive '#pragma omp task' cannot contain more than one 'detach' clause}} > -#pragma omp task detach(cevt) detach(revt) // omp45-error 2 {{unexpected > OpenMP clause 'detach' in directive '#pragma omp task'}} expected-error > {{directive '#pragma omp task' cannot contain more than one 'detach' clause}} > omp50-error {{expected variable of the 'omp_event_handle_t' type, not 'const > omp_event_handle_t' (aka 'const unsigned long')}} omp50-error {{expected > variable of the 'omp_event_handle_t' type, not 'omp_event_handle_t &' (aka > 'unsigned long &')}} > +#pragma omp task detach(cevt) detach(revt) // omp45-error 2 {{unexpected > OpenMP clause 'detach' in directive '#pragma omp task'}} expected-error > {{directive '#pragma omp task' cannot contain more than one 'detach' clause}} > #pragma omp task detach(evt) mergeable // omp45-error {{unexpected OpenMP > clause 'detach' in directive '#pragma omp task'}} omp50-error {{'mergeable' > and 'detach' clause are mutually exclusive and may not appear on the same > directive}} omp50-note {{'detach' clause is specified here}} > ; > #pragma omp task mergeable detach(evt) // omp45-error {{unexpected OpenMP > clause 'detach' in directive '#pragma omp task'}} omp50-error {{'detach' and > 'mergeable' clause are mutually exclusive and may not appear on the same > directive}} omp50-note {{'mergeable' clause is specified here}} > -#pragma omp task detach(-evt) // omp45-error {{unexpected OpenMP clause > 'detach' in directive '#pragma omp task'}} omp50-error {{expected variable of > the 'omp_event_handle_t' type}} > +#pragma omp task detach(-evt) // omp45-error {{unexpected OpenMP clause > 'detach' in directive '#pragma omp task'}} > ; > #pragma omp task detach(evt) shared(evt) // omp45-error {{unexpected OpenMP > clause 'detach' in directive '#pragma omp task'}} > #pragma omp task detach(evt) firstprivate(evt) // omp45-error {{unexpected > OpenMP clause 'detach' in directive '#pragma omp task'}} > > diff --git a/clang/test/OpenMP/teams_distribute_dist_schedule_messages.cpp > b/clang/test/OpenMP/teams_distribute_dist_schedule_messages.cpp > index 22d2408d3f17..bd1aaa5c6289 100644 > --- a/clang/test/OpenMP/teams_distribute_dist_schedule_messages.cpp > +++ b/clang/test/OpenMP/teams_distribute_dist_schedule_messages.cpp > @@ -55,7 +55,7 @@ T tmain(T argc) { > for (int i = 0; i < 10; ++i) foo(); > > #pragma omp target > -#pragma omp teams distribute dist_schedule (static, argv[1]=2) // > expected-error {{expected ')'}} expected-note {{to match this '('}} > expected-error3 {{expression must have integral or unscoped enumeration type, > not 'char *'}} > +#pragma omp teams distribute dist_schedule (static, argv[1]=2) // > expected-error {{expected ')'}} expected-note {{to match this '('}} > expected-error 2{{expression must have integral or unscoped enumeration type, > not 'char *'}} > for (int i = 0; i < 10; ++i) foo(); > > return T(); > > diff --git > a/clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_messages.cpp > b/clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_messages.cpp > index 27ff4125daf7..a70d80ad1251 100644 > --- > a/clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_messages.cpp > +++ > b/clang/test/OpenMP/teams_distribute_parallel_for_dist_schedule_messages.cpp > @@ -55,7 +55,7 @@ T tmain(T argc) { > for (int i = 0; i < 10; ++i) foo(); > > #pragma omp target > -#pragma omp teams distribute parallel for dist_schedule (static, argv[1]=2) > // expected-error {{expected ')'}} expected-note {{to match this '('}} > expected-error3 {{expression must have integral or unscoped enumeration type, > not 'char *'}} > +#pragma omp teams distribute parallel for dist_schedule (static, argv[1]=2) > // expected-error {{expected ')'}} expected-note {{to match this '('}} > expected-error 2{{expression must have integral or unscoped enumeration type, > not 'char *'}} > for (int i = 0; i < 10; ++i) foo(); > > return T(); > > diff --git > a/clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_messages.cpp > > b/clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_messages.cpp > index cbd4ec4ce979..b87301fa98d8 100644 > --- > a/clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_messages.cpp > +++ > b/clang/test/OpenMP/teams_distribute_parallel_for_simd_dist_schedule_messages.cpp > @@ -55,7 +55,7 @@ T tmain(T argc) { > for (int i = 0; i < 10; ++i) foo(); > > #pragma omp target > -#pragma omp teams distribute parallel for simd dist_schedule (static, > argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this > '('}} expected-error3 {{expression must have integral or unscoped enumeration > type, not 'char *'}} > +#pragma omp teams distribute parallel for simd dist_schedule (static, > argv[1]=2) // expected-error {{expected ')'}} expected-note {{to match this > '('}} expected-error 2{{expression must have integral or unscoped enumeration > type, not 'char *'}} > for (int i = 0; i < 10; ++i) foo(); > > return T(); > > diff --git > a/clang/test/OpenMP/teams_distribute_simd_dist_schedule_messages.cpp > b/clang/test/OpenMP/teams_distribute_simd_dist_schedule_messages.cpp > index 424797576837..6e653fae08c8 100644 > --- a/clang/test/OpenMP/teams_distribute_simd_dist_schedule_messages.cpp > +++ b/clang/test/OpenMP/teams_distribute_simd_dist_schedule_messages.cpp > @@ -55,7 +55,7 @@ T tmain(T argc) { > for (int i = 0; i < 10; ++i) foo(); > > #pragma omp target > -#pragma omp teams distribute simd dist_schedule (static, argv[1]=2) // > expected-error {{expected ')'}} expected-note {{to match this '('}} > expected-error3 {{expression must have integral or unscoped enumeration type, > not 'char *'}} > +#pragma omp teams distribute simd dist_schedule (static, argv[1]=2) // > expected-error {{expected ')'}} expected-note {{to match this '('}} > expected-error 2{{expression must have integral or unscoped enumeration type, > not 'char *'}} > for (int i = 0; i < 10; ++i) foo(); > > return T(); > > diff --git a/clang/test/SemaCXX/warn-unused-lambda-capture.cpp > b/clang/test/SemaCXX/warn-unused-lambda-capture.cpp > index 52ec390b0bba..764a4a42a084 100644 > --- a/clang/test/SemaCXX/warn-unused-lambda-capture.cpp > +++ b/clang/test/SemaCXX/warn-unused-lambda-capture.cpp > @@ -147,7 +147,7 @@ void test_templated() { > > auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda > capture 'i' is not used}} > auto explicit_by_value_unused_sizeof = [i] { return sizeof(i); }; // > expected-warning{{lambda capture 'i' is not required to be captured for this > use}} > - auto explicit_by_value_unused_decltype = [i] { decltype(i) j = 0; }; // > expected-warning{{lambda capture 'i' is not used}} > + auto explicit_by_value_unused_decltype = [i] { decltype(i) j = 0; }; // > expected-warning{{lambda capture 'i' is not required to be captured for this > use}} > auto explicit_by_value_unused_const = [k] { return k + 1; }; // > expected-warning{{lambda capture 'k' is not required to be captured for this > use}} > auto explicit_by_value_unused_const_generic = [k](auto c) { return k + 1; > }; // expected-warning{{lambda capture 'k' is not required to be captured for > this use}} > > > diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp > b/clang/test/SemaTemplate/temp_arg_nontype_cxx17.cpp > similarity index 98% > rename from clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp > rename to clang/test/SemaTemplate/temp_arg_nontype_cxx17.cpp > index 675f957ef6fa..52cf51719f05 100644 > --- a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp > +++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx17.cpp > @@ -503,3 +503,13 @@ namespace PR48517 { > template<> struct Q<&R<int>::n> { static constexpr int X = 1; }; > static_assert(R<int>().f() == 1); > } > + > +namespace dependent_reference { > + template<int &r> struct S { int *q = &r; }; > + template<int> auto f() { static int n; return S<n>(); } > + auto v = f<0>(); > + auto w = f<1>(); > + static_assert(!is_same<decltype(v), decltype(w)>); > + // Ensure that we can instantiate the definition of S<...>. > + int n = *v.q + *w.q; > +} > > diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp > b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp > index c42fda780430..d514465f7d67 100644 > --- a/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp > +++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp > @@ -292,3 +292,47 @@ namespace Predefined { > Y<B{__func__[0]}>(); // expected-error {{reference to subobject of > predefined '__func__' variable}} > } > } > + > +namespace dependent { > + template<auto &V> struct R { static inline auto &v = V; }; > + template<auto &V, auto &W> constexpr bool operator==(R<V>, R<W>) { return > &V == &W; } > + template<auto *V> struct S { static inline auto *v = V; }; > + template<auto *V, auto *W> constexpr bool operator==(S<V>, S<W>) { return > V == W; } > + template<auto V> struct T { static inline const auto &v = V; }; > + template<auto V, auto W> constexpr bool operator==(T<V>, T<W>) { return &V > == &W; } > + template<typename T> struct V { T v; }; > + template<int N> auto f() { > + static int n; > + static V<int> vn; > + if constexpr (N < 10) > + return R<n>(); > + else if constexpr (N < 20) > + return R<vn.v>(); // FIXME: expected-error 2{{refers to subobject}} > + else if constexpr (N < 30) > + return S<&n>(); > + else if constexpr (N < 40) > + return S<&vn.v>(); // FIXME: expected-error 2{{refers to subobject}} > + else if constexpr (N < 50) > + return T<V<int&>{n}>(); > + else if constexpr (N < 60) > + return T<V<int*>{&n}>(); > + else if constexpr (N < 70) > + return T<V<int&>{vn.v}>(); > + else if constexpr (N < 80) > + return T<V<int*>{&vn.v}>(); > + } > + template<int Base> void check() { > + auto v = f<Base + 0>(); // FIXME: expected-note 2{{instantiation of}} > + auto w = f<Base + 1>(); // FIXME: expected-note 2{{instantiation of}} > + static_assert(!__is_same(decltype(v), decltype(w))); > + static_assert(v != w); > + } > + template void check<0>(); > + template void check<10>(); // FIXME: expected-note 2{{instantiation of}} > + template void check<20>(); > + template void check<30>(); // FIXME: expected-note 2{{instantiation of}} > + template void check<40>(); > + template void check<50>(); > + template void check<60>(); > + template void check<70>(); > +} > > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits