[llvm-branch-commits] [clang] 8c1f2d1 - Following up on PR48517, fix handling of template arguments that refer
Richard Smith via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Dec 17 23:59:46 PST 2020
Author: Richard Smith
Date: 2020-12-17T23:54:37-08:00
New Revision: 8c1f2d15b826591cdf6bd6b468b8a7d23377b29e
URL: https://github.com/llvm/llvm-project/commit/8c1f2d15b826591cdf6bd6b468b8a7d23377b29e
DIFF: https://github.com/llvm/llvm-project/commit/8c1f2d15b826591cdf6bd6b468b8a7d23377b29e.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.
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 c8d87ec48a3f..e1c3b6944142 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 7967f8a91214..abf873a7ee40 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 6b81494e8eff..2c781eb88415 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3353,7 +3353,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 50beeb5cabb1..0426b20a33a9 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 56181bbe1166..231a8c3bc8bd 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 b6af655deff0..44d52c56ffbb 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 64259767d98a..7ebd9be831ad 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 39ea9e06e7b1..cbf4fb1de465 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 at +1 {{integral constant expression}} expected-note at +1 0+{{constant expression}}
+ // expected-error at +1 1+{{integral constant expression}} expected-note at +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 at +1 {{integral constant expression}} expected-note at +1 0+{{constant expression}}
+// expected-error at +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 at +1 {{integral constant expression}} expected-note at +1 0+{{constant expression}}
+ // expected-error at +1 1+{{integral constant expression}} expected-note at +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>();
+}
More information about the llvm-branch-commits
mailing list