Revert "Following up on PR48517, fix handling of template arguments that refer"
authorArthur Eubanks <aeubanks@google.com>
Tue, 22 Dec 2020 18:12:40 +0000 (10:12 -0800)
committerArthur Eubanks <aeubanks@google.com>
Tue, 22 Dec 2020 18:18:08 +0000 (10:18 -0800)
This reverts commit 8c1f2d15b826591cdf6bd6b468b8a7d23377b29e.

This is part of 5 commits being reverted due to https://crbug.com/1161059. See bug for repro.

33 files changed:
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_cxx17.cpp [deleted file]
clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp [new file with mode: 0644]
clang/test/SemaTemplate/temp_arg_nontype_cxx20.cpp

index e1c3b694414209b8edf6e45c8fb7feec2e8b416f..c8d87ec48a3f0cece3ab71d9f9d42ae55d8980c9 100644 (file)
@@ -578,12 +578,12 @@ public:
   struct EvalStatus {
     /// Whether the evaluated expression has side effects.
     /// For example, (f() && 0) can be folded, but it still has side effects.
-    bool HasSideEffects = false;
+    bool HasSideEffects;
 
     /// 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 = false;
+    bool HasUndefinedBehavior;
 
     /// 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,7 +592,10 @@ public:
     /// 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 = nullptr;
+    SmallVectorImpl<PartialDiagnosticAt> *Diag;
+
+    EvalStatus()
+        : HasSideEffects(false), HasUndefinedBehavior(false), Diag(nullptr) {}
 
     // hasSideEffects - Return true if the evaluated expression has
     // side effects.
@@ -603,11 +606,8 @@ public:
 
   /// EvalResult is a struct with detailed info about an evaluated expression.
   struct EvalResult : EvalStatus {
-    /// This is the value the expression can be folded to.
+    /// Val - 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.
index abf873a7ee40fb5170f655eaf89755dc398bde76..7967f8a91214d71bd64a52136b4485a53a057bdd 100644 (file)
@@ -252,12 +252,6 @@ public:
   /// 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
@@ -680,6 +674,13 @@ 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,
index 2c781eb88415f990fbd64f3a53c541233c470acf..6b81494e8eff0a264c38934b7169d99d27dbbf90 100644 (file)
@@ -3353,8 +3353,7 @@ public:
                                               llvm::APSInt &Value, CCEKind CCE);
   ExprResult CheckConvertedConstantExpression(Expr *From, QualType T,
                                               APValue &Value, CCEKind CCE,
-                                              NamedDecl *Dest = nullptr,
-                                              bool *ValueDependent = nullptr);
+                                              NamedDecl *Dest = nullptr);
 
   /// Abstract base class used to perform a contextual implicit
   /// conversion from an expression to any type passing a filter.
index 5262e3cbe233b58776740413728ccf4780b6cd5c..4026fdc76fd6fcef13fbeea2dcf358479320bc59 100644 (file)
@@ -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::ValueInstantiation;
+          Dep |= ExprDependence::Value;
       }
     }
   }
@@ -443,21 +443,12 @@ 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() &
-                               ~TemplateArgumentDependence::Dependent);
+      Deps |= toExprDependence(Arg->getArgument().getDependence());
   }
 
   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;
index dafa7136ecb4e00fe434368717a21f4113d92916..a274bf37a407aa6445ecd8edb293c6687b0e5f33 100644 (file)
@@ -416,9 +416,12 @@ DeclRefExpr::DeclRefExpr(const ASTContext &Ctx,
       RefersToEnclosingVariableOrCapture;
   DeclRefExprBits.NonOdrUseReason = NOUR;
   if (TemplateArgs) {
+    auto Deps = TemplateArgumentDependence::None;
     getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
-        TemplateKWLoc, *TemplateArgs,
-        getTrailingObjects<TemplateArgumentLoc>());
+        TemplateKWLoc, *TemplateArgs, getTrailingObjects<TemplateArgumentLoc>(),
+        Deps);
+    assert(!(Deps & TemplateArgumentDependence::Dependent) &&
+           "built a DeclRefExpr with dependent template args");
   } else if (TemplateKWLoc.isValid()) {
     getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
         TemplateKWLoc);
@@ -1521,8 +1524,16 @@ MemberExpr *MemberExpr::Create(
   MemberExpr *E = new (Mem) MemberExpr(Base, IsArrow, OperatorLoc, MemberDecl,
                                        NameInfo, T, VK, OK, NOUR);
 
-  // FIXME: Move this into the constructor.
+  // FIXME: remove remaining dependence computation to computeDependence().
+  auto Deps = E->getDependence();
   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 =
@@ -1535,26 +1546,16 @@ MemberExpr *MemberExpr::Create(
       TemplateArgs || TemplateKWLoc.isValid();
 
   if (TemplateArgs) {
+    auto TemplateArgDeps = TemplateArgumentDependence::None;
     E->getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
         TemplateKWLoc, *TemplateArgs,
-        E->getTrailingObjects<TemplateArgumentLoc>());
+        E->getTrailingObjects<TemplateArgumentLoc>(), TemplateArgDeps);
+    if (TemplateArgDeps & TemplateArgumentDependence::Instantiation)
+      Deps |= ExprDependence::Instantiation;
   } 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;
index e1f658923519a8961d22beb95fafc0ac61f9e4f7..8dc9d4296e149d96080725502143498b4603c445 100644 (file)
@@ -433,8 +433,9 @@ OverloadExpr::OverloadExpr(StmtClass SC, const ASTContext &Context,
   }
 
   if (TemplateArgs) {
+    auto Deps = TemplateArgumentDependence::None;
     getTrailingASTTemplateKWAndArgsInfo()->initializeFrom(
-        TemplateKWLoc, *TemplateArgs, getTrailingTemplateArgumentLoc());
+        TemplateKWLoc, *TemplateArgs, getTrailingTemplateArgumentLoc(), Deps);
   } else if (TemplateKWLoc.isValid()) {
     getTrailingASTTemplateKWAndArgsInfo()->initializeFrom(TemplateKWLoc);
   }
@@ -463,8 +464,9 @@ DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(
   DependentScopeDeclRefExprBits.HasTemplateKWAndArgsInfo =
       (Args != nullptr) || TemplateKWLoc.isValid();
   if (Args) {
+    auto Deps = TemplateArgumentDependence::None;
     getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
-        TemplateKWLoc, *Args, getTrailingObjects<TemplateArgumentLoc>());
+        TemplateKWLoc, *Args, getTrailingObjects<TemplateArgumentLoc>(), Deps);
   } else if (TemplateKWLoc.isValid()) {
     getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
         TemplateKWLoc);
@@ -1374,9 +1376,10 @@ CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
   CXXDependentScopeMemberExprBits.OperatorLoc = OperatorLoc;
 
   if (TemplateArgs) {
+    auto Deps = TemplateArgumentDependence::None;
     getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
-        TemplateKWLoc, *TemplateArgs,
-        getTrailingObjects<TemplateArgumentLoc>());
+        TemplateKWLoc, *TemplateArgs, getTrailingObjects<TemplateArgumentLoc>(),
+        Deps);
   } else if (TemplateKWLoc.isValid()) {
     getTrailingObjects<ASTTemplateKWAndArgsInfo>()->initializeFrom(
         TemplateKWLoc);
index 231a8c3bc8bd1c93680b59bd23b5f5094a8b722f..56181bbe116684941fcc51d24c6e57ecd95f44fe 100644 (file)
@@ -1819,8 +1819,7 @@ 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,
-                             bool &Dependent);
+static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result);
 
 /// Evaluate an integer or fixed point expression into an APResult.
 static bool EvaluateFixedPointOrInteger(const Expr *E, APFixedPoint &Result,
@@ -2108,8 +2107,7 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK,
                                   QualType Type, const APValue &Value,
                                   ConstantExprKind Kind,
                                   SourceLocation SubobjectLoc,
-                                  CheckedTemporaries &CheckedTemps,
-                                  bool &Dependent);
+                                  CheckedTemporaries &CheckedTemps);
 
 /// Check that this reference or pointer core constant expression is a valid
 /// value for an address or reference constant expression. Return true if we
@@ -2117,8 +2115,7 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK,
 static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
                                           QualType Type, const LValue &LVal,
                                           ConstantExprKind Kind,
-                                          CheckedTemporaries &CheckedTemps,
-                                          bool &Dependent) {
+                                          CheckedTemporaries &CheckedTemps) {
   bool IsReferenceType = Type->isReferenceType();
 
   APValue::LValueBase Base = LVal.getLValueBase();
@@ -2203,8 +2200,6 @@ 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())
@@ -2235,9 +2230,6 @@ 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()) {
@@ -2250,8 +2242,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, Dependent))
+                                 Info, MTE->getExprLoc(), TempType, *V,
+                                 Kind, SourceLocation(), CheckedTemps))
         return false;
     }
   }
@@ -2280,15 +2272,13 @@ 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, bool &Dependent) {
+static bool CheckMemberPointerConstantExpression(EvalInfo &Info,
+                                                 SourceLocation Loc,
+                                                 QualType Type,
+                                                 const APValue &Value,
+                                                 ConstantExprKind Kind) {
   const ValueDecl *Member = Value.getMemberPointerDecl();
-  if (!Member)
-    return true;
-  Dependent |= Member->isTemplated();
-  const auto *FD = dyn_cast<CXXMethodDecl>(Member);
+  const auto *FD = dyn_cast_or_null<CXXMethodDecl>(Member);
   if (!FD)
     return true;
   if (FD->isConsteval()) {
@@ -2337,8 +2327,7 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK,
                                   QualType Type, const APValue &Value,
                                   ConstantExprKind Kind,
                                   SourceLocation SubobjectLoc,
-                                  CheckedTemporaries &CheckedTemps,
-                                  bool &Dependent) {
+                                  CheckedTemporaries &CheckedTemps) {
   if (!Value.hasValue()) {
     Info.FFDiag(DiagLoc, diag::note_constexpr_uninitialized)
       << true << Type;
@@ -2360,20 +2349,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, Dependent))
+                                 SubobjectLoc, CheckedTemps))
         return false;
     }
     if (!Value.hasArrayFiller())
       return true;
     return CheckEvaluationResult(CERK, Info, DiagLoc, EltTy,
                                  Value.getArrayFiller(), Kind, SubobjectLoc,
-                                 CheckedTemps, Dependent);
+                                 CheckedTemps);
   }
   if (Value.isUnion() && Value.getUnionField()) {
     return CheckEvaluationResult(
         CERK, Info, DiagLoc, Value.getUnionField()->getType(),
         Value.getUnionValue(), Kind, Value.getUnionField()->getLocation(),
-        CheckedTemps, Dependent);
+        CheckedTemps);
   }
   if (Value.isStruct()) {
     RecordDecl *RD = Type->castAs<RecordType>()->getDecl();
@@ -2382,7 +2371,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, Dependent))
+                                   BS.getBeginLoc(), CheckedTemps))
           return false;
         ++BaseIndex;
       }
@@ -2392,8 +2381,8 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK,
         continue;
 
       if (!CheckEvaluationResult(CERK, Info, DiagLoc, I->getType(),
-                                 Value.getStructField(I->getFieldIndex()), Kind,
-                                 I->getLocation(), CheckedTemps, Dependent))
+                                 Value.getStructField(I->getFieldIndex()),
+                                 Kind, I->getLocation(), CheckedTemps))
         return false;
     }
   }
@@ -2403,13 +2392,12 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK,
     LValue LVal;
     LVal.setFrom(Info.Ctx, Value);
     return CheckLValueConstantExpression(Info, DiagLoc, Type, LVal, Kind,
-                                         CheckedTemps, Dependent);
+                                         CheckedTemps);
   }
 
   if (Value.isMemberPointer() &&
       CERK == CheckEvaluationResultKind::ConstantExpression)
-    return CheckMemberPointerConstantExpression(Info, DiagLoc, Type, Value,
-                                                Kind, Dependent);
+    return CheckMemberPointerConstantExpression(Info, DiagLoc, Type, Value, Kind);
 
   // Everything else is fine.
   return true;
@@ -2420,7 +2408,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, bool &Dependent) {
+                                    ConstantExprKind Kind) {
   // Nothing to check for a constant expression of type 'cv void'.
   if (Type->isVoidType())
     return true;
@@ -2428,18 +2416,17 @@ static bool CheckConstantExpression(EvalInfo &Info, SourceLocation DiagLoc,
   CheckedTemporaries CheckedTemps;
   return CheckEvaluationResult(CheckEvaluationResultKind::ConstantExpression,
                                Info, DiagLoc, Type, Value, Kind,
-                               SourceLocation(), CheckedTemps, Dependent);
+                               SourceLocation(), CheckedTemps);
 }
 
 /// 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, Dependent);
+      ConstantExprKind::Normal, SourceLocation(), CheckedTemps);
 }
 
 /// Enforce C++2a [expr.const]/4.17, which disallows new-expressions unless
@@ -11111,9 +11098,7 @@ static bool EvaluateBuiltinConstantP(EvalInfo &Info, const Expr *Arg) {
       ArgType->isAnyComplexType() || ArgType->isPointerType() ||
       ArgType->isNullPtrType()) {
     APValue V;
-    bool Dependent = false;
-    if (!::EvaluateAsRValue(Info, Arg, V, Dependent) ||
-        Info.EvalStatus.HasSideEffects) {
+    if (!::EvaluateAsRValue(Info, Arg, V) || Info.EvalStatus.HasSideEffects) {
       Fold.keepDiagnostics();
       return false;
     }
@@ -11415,8 +11400,7 @@ 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;
-      bool Dependent = false;
-      if (!EvaluateAsRValue(Info, E, RVal, Dependent))
+      if (!EvaluateAsRValue(Info, E, RVal))
         return false;
       LVal.setFrom(Info.Ctx, RVal);
     } else if (!EvaluatePointer(ignorePointerCastsAndParens(E), LVal, Info,
@@ -12845,9 +12829,8 @@ 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, Dependent);
+                                   ConstantExprKind::Normal);
   };
   return EvaluateComparisonBinaryOperator(Info, E, OnSuccess, [&]() {
     return ExprEvaluatorBaseTy::VisitBinCmp(E);
@@ -14611,8 +14594,7 @@ 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,
-                             bool &Dependent) {
+static bool EvaluateAsRValue(EvalInfo &Info, const Expr *E, APValue &Result) {
   assert(!E->isValueDependent());
   if (Info.EnableNewConstInterp) {
     if (!Info.Ctx.getInterpContext().evaluateAsRValue(Info, E, Result))
@@ -14637,7 +14619,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, Dependent) &&
+                                 ConstantExprKind::Normal) &&
          CheckMemoryLeaks(Info);
 }
 
@@ -14683,7 +14665,7 @@ static bool EvaluateAsRValue(const Expr *E, Expr::EvalResult &Result,
   if (FastEvaluateAsRValue(E, Result, Ctx, IsConst))
     return IsConst;
 
-  return EvaluateAsRValue(Info, E, Result.Val, Result.Dependent);
+  return EvaluateAsRValue(Info, E, Result.Val);
 }
 
 static bool EvaluateAsInt(const Expr *E, Expr::EvalResult &ExprResult,
@@ -14793,9 +14775,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, Result.Dependent))
+      !CheckLValueConstantExpression(Info, getExprLoc(),
+                                     Ctx.getLValueReferenceType(getType()), LV,
+                                     ConstantExprKind::Normal, CheckedTemps))
     return false;
 
   LV.moveInto(Result.Val);
@@ -14854,7 +14836,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.Dependent))
+                               Result.Val, Kind))
     return false;
   if (!CheckMemoryLeaks(Info))
     return false;
@@ -14918,9 +14900,8 @@ 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, Dependent) &&
+                                 ConstantExprKind::Normal) &&
          CheckMemoryLeaks(Info);
 }
 
@@ -14987,7 +14968,7 @@ APSInt Expr::EvaluateKnownConstIntCheckOverflow(
   Info.InConstantContext = true;
   Info.CheckingForUndefinedBehavior = true;
 
-  bool Result = ::EvaluateAsRValue(this, EVResult, Ctx, Info);
+  bool Result = ::EvaluateAsRValue(Info, this, EVResult.Val);
   (void)Result;
   assert(Result && "Could not evaluate expression");
   assert(EVResult.Val.isInt() && "Expression did not evaluate to integer");
@@ -14999,10 +14980,13 @@ void Expr::EvaluateForOverflow(const ASTContext &Ctx) const {
   assert(!isValueDependent() &&
          "Expression evaluator can't be called on a dependent expression.");
 
+  bool IsConst;
   EvalResult EVResult;
-  EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects);
-  Info.CheckingForUndefinedBehavior = true;
-  (void)::EvaluateAsRValue(this, EVResult, Ctx, Info);
+  if (!FastEvaluateAsRValue(this, EVResult, Ctx, IsConst)) {
+    EvalInfo Info(Ctx, EVResult, EvalInfo::EM_IgnoreSideEffects);
+    Info.CheckingForUndefinedBehavior = true;
+    (void)::EvaluateAsRValue(Info, this, EVResult.Val);
+  }
 }
 
 bool Expr::EvalResult::isGlobalLValue() const {
@@ -15552,9 +15536,8 @@ 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, Dependent) &&
+      ::EvaluateAsRValue(Info, this, Result ? *Result : Scratch) &&
       // 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;
index 44d52c56ffbbc51fa01e340a6fdc937e903f51d5..b6af655deff04598c82b235921ea7f599dcd4444 100644 (file)
@@ -131,17 +131,25 @@ 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());
-    // Instantiation-dependent expression arguments are considered dependent
-    // until they're resolved to another form.
-    if (Deps & TemplateArgumentDependence::Instantiation)
-      Deps |= TemplateArgumentDependence::Dependent;
+    if (isa<PackExpansionExpr>(getAsExpr()))
+      Deps |= TemplateArgumentDependence::Dependent |
+              TemplateArgumentDependence::Instantiation;
     return Deps;
 
   case Pack:
@@ -536,8 +544,8 @@ ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
   NumTemplateArgs = Info.size();
 
   TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>();
-  std::uninitialized_copy(Info.arguments().begin(), Info.arguments().end(),
-                          ArgBuffer);
+  for (unsigned i = 0; i != NumTemplateArgs; ++i)
+    new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
 }
 
 void ASTTemplateKWAndArgsInfo::initializeFrom(
@@ -547,8 +555,9 @@ void ASTTemplateKWAndArgsInfo::initializeFrom(
   LAngleLoc = Info.getLAngleLoc();
   RAngleLoc = Info.getRAngleLoc();
   NumTemplateArgs = Info.size();
-  std::uninitialized_copy(Info.arguments().begin(), Info.arguments().end(),
-                          OutArgArray);
+
+  for (unsigned i = 0; i != NumTemplateArgs; ++i)
+    new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
 }
 
 void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
@@ -559,6 +568,21 @@ 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);
index ac52612ea3b0cb669db3971c214a98aa591a9abd..13d2125d1a28d0e7edd6882bbe8fb2d350e27831 100644 (file)
@@ -5619,8 +5619,7 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
                                                    QualType T, APValue &Value,
                                                    Sema::CCEKind CCE,
                                                    bool RequireInt,
-                                                   NamedDecl *Dest,
-                                                   bool *ValueDependent) {
+                                                   NamedDecl *Dest) {
   assert(S.getLangOpts().CPlusPlus11 &&
          "converted constant expression outside C++11");
 
@@ -5744,8 +5743,6 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
 
   if (Result.get()->isValueDependent()) {
     Value = APValue();
-    if (ValueDependent)
-      *ValueDependent = true;
     return Result;
   }
 
@@ -5769,8 +5766,6 @@ 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.
@@ -5801,10 +5796,9 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From,
 
 ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
                                                   APValue &Value, CCEKind CCE,
-                                                  NamedDecl *Dest,
-                                                  bool *ValueDependent) {
+                                                  NamedDecl *Dest) {
   return ::CheckConvertedConstantExpression(*this, From, T, Value, CCE, false,
-                                            Dest, ValueDependent);
+                                            Dest);
 }
 
 ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
@@ -5814,8 +5808,7 @@ ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T,
 
   APValue V;
   auto R = ::CheckConvertedConstantExpression(*this, From, T, V, CCE, true,
-                                              /*Dest=*/nullptr,
-                                              /*ValueDependent=*/nullptr);
+                                              /*Dest=*/nullptr);
   if (!R.isInvalid() && !R.get()->isValueDependent())
     Value = V.getInt();
   return R;
index 7ebd9be831ad52bee851bb74d48a7fbc56e77c17..64259767d98a68fd152c4b612ba233c3dbdce984 100644 (file)
@@ -6620,12 +6620,6 @@ 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));
@@ -6640,6 +6634,8 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
                                                  QualType ParamType,
                                                  Expr *&ResultArg,
                                                  TemplateArgument &Converted) {
+  bool Invalid = false;
+
   Expr *Arg = ResultArg;
   bool ObjCLifetimeConversion;
 
@@ -6655,7 +6651,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 (!ExtraParens) {
+    if (!Invalid && !ExtraParens) {
       S.Diag(Arg->getBeginLoc(),
              S.getLangOpts().CPlusPlus11
                  ? diag::warn_cxx98_compat_template_arg_extra_parens
@@ -6684,8 +6680,13 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
     ValueDecl *VD = DRE->getDecl();
     if (VD->getType()->isMemberPointerType()) {
       if (isa<NonTypeTemplateParmDecl>(VD)) {
-        Converted = TemplateArgument(Arg);
-        return false;
+        if (Arg->isTypeDependent() || Arg->isValueDependent()) {
+          Converted = TemplateArgument(Arg);
+        } else {
+          VD = cast<ValueDecl>(VD->getCanonicalDecl());
+          Converted = TemplateArgument(VD, ParamType);
+        }
+        return Invalid;
       }
     }
 
@@ -6744,7 +6745,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
       ValueDecl *D = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl());
       Converted = TemplateArgument(D, S.Context.getCanonicalType(ParamType));
     }
-    return false;
+    return Invalid;
   }
 
   // We found something else, but we don't know specifically what it is.
@@ -6921,17 +6922,14 @@ 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, &ValueDependent);
+        Arg, ParamType, Value, CCEK_TemplateArg, Param);
     if (ArgResult.isInvalid())
       return ExprError();
 
     // For a value-dependent argument, CheckConvertedConstantExpression is
-    // 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) {
+    // permitted (and expected) to be unable to determine a value.
+    if (ArgResult.get()->isValueDependent()) {
       Converted = TemplateArgument(ArgResult.get());
       return ArgResult;
     }
index cbf4fb1de46566d3a5d245e23a4c605a1171d0c5..39ea9e06e7b1ffdd4bee00ed1f4a0c99c48f29a7 100644 (file)
@@ -3227,8 +3227,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
       if (FunctionDecl *Pattern =
               Function->getInstantiatedFromMemberFunction()) {
 
-        if (TSK != TSK_ImplicitInstantiation &&
-            Function->hasAttr<ExcludeFromExplicitInstantiationAttr>())
+        if (Function->hasAttr<ExcludeFromExplicitInstantiationAttr>())
           continue;
 
         MemberSpecializationInfo *MSInfo =
@@ -3273,8 +3272,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
         continue;
 
       if (Var->isStaticDataMember()) {
-        if (TSK != TSK_ImplicitInstantiation &&
-            Var->hasAttr<ExcludeFromExplicitInstantiationAttr>())
+        if (Var->hasAttr<ExcludeFromExplicitInstantiationAttr>())
           continue;
 
         MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
@@ -3291,7 +3289,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
             SuppressNew)
           continue;
 
-        if (TSK != TSK_ExplicitInstantiationDeclaration) {
+        if (TSK == TSK_ExplicitInstantiationDefinition) {
           // C++0x [temp.explicit]p8:
           //   An explicit instantiation definition that names a class template
           //   specialization explicitly instantiates the class template
index 0f7b2172f5a545cd96d365c827a93c743b14d2e8..cd232f40feb43416ae59a44ba4d4d5e8bb8b5626 100644 (file)
@@ -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-error 2{{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{{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
   return T();
 }
index 18dcac555f740a842cdc19d881115266a8d82edf..07e7704dffded694783ae8d27efe67805ada0bce 100644 (file)
@@ -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-error 2{{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{{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
   return T();
 }
index 63f8cfe917cd466ebc72d97079208b79d20e6187..ed7b19111dee8a7b14441620eac4082d13f7eaa8 100644 (file)
@@ -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-error 2{{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{{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
   return T();
 }
index a6593cfbe0d3ddc4ba1d255d0315f24beef82d73..794681c02646c11adbadb19c5a45ec02b51e73f9 100644 (file)
@@ -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-error 2{{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{{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
   return T();
 }
index f829874864daa43f546cade6e201a00115d98f6e..7acb2587f976f11e9fc940928bba0f216f8e7d6b 100644 (file)
@@ -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 1+{{integral constant expression}} expected-note@+1 0+{{constant expression}}
+  // expected-error@+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)
index 972aa5753e3630d414ee471a0878705ff4ec1ed5..8dd7f68c25fd887c79a28094f141208487557e43 100644 (file)
@@ -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 {{'ordered' clause with a parameter can not be specified in '#pragma omp target parallel for simd' directive}}
+// expected-error@+1 {{integral constant expression}} expected-note@+1 0+{{constant expression}}
 #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];
index d8b0a91f97d7b889ba5cc3fe114dd40aafd61b4c..00fa3c85279f22f4a45a4e86b34a744827bd9319 100644 (file)
@@ -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 1+{{integral constant expression}} expected-note@+1 0+{{constant expression}}
+  // expected-error@+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)
index e31df97ba31c9365571db3cafb4d97294f3b4db6..69c1e55eeaa3b857b4b9458b2ef49472c0ba6fa7 100644 (file)
@@ -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-error 2{{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{{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
 
   return T();
index 4f3c5812544697e1cd1ecd260700d2561cb750ce..a0efad18668e9259be7afec2495b6147e0580e80 100644 (file)
@@ -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-error 2{{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{{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
 
   return T();
index 8b272d4358f60af40b7eac3767a9c804736c21aa..ec634c8ac01c9ca4d8eaadec784efa5e56e89280 100644 (file)
@@ -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-error 2{{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{{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
 
   return T();
index b583c14831e70bd4b8aec4e9874bb98e5cfcb146..507ddabd2fc2074703328deef9da65fdb536281d 100644 (file)
@@ -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-error 2{{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{{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
 
   return T();
index 42ecc2814e1257adcf2bebed7432b536f34d6474..3dc377c4ca4cedaf109527b44315839e07f9dd8d 100644 (file)
@@ -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 2{{bit fields cannot be used to specify storage in a 'from' clause}}
+#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.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)
   {
index 941c781119e6efb47e2799204d7f7f9b457831d4..fca4e21304fce91a7074d620f4b61f96a7093c4d 100644 (file)
@@ -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 2{{bit fields cannot be used to specify storage in a 'to' clause}}
+#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.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)
   {
index 2f9ee9a44402e2dbc93f0912daf5ccf86884d443..13cbfb6c45693163073f5bb78c78b76cfce2bc56 100644 (file)
@@ -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}}
+#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(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'}}
+#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) 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'}}
index bd1aaa5c6289667cf48de566d7f80a09e5b791a0..22d2408d3f1784d0efbd4ba198b8d69991cac3c6 100644 (file)
@@ -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-error 2{{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{{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
 
   return T();
index a70d80ad1251ed3c1204374e491c570613e811fc..27ff4125daf7f7be05d5dc59591cbd92f8d695b3 100644 (file)
@@ -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-error 2{{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{{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
 
   return T();
index b87301fa98d8a5cd41ec1bf765557be458b09126..cbd4ec4ce9793fabf7c2eefb0ae671588748c8ff 100644 (file)
@@ -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-error 2{{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{{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
 
   return T();
index 6e653fae08c81cdb00647e3c37baf9f009725eeb..424797576837f40dcea5bd2411a8f16f8eedf2cb 100644 (file)
@@ -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-error 2{{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{{expression must have integral or unscoped enumeration type, not 'char *'}}
   for (int i = 0; i < 10; ++i) foo();
 
   return T();
index 764a4a42a0846b603ffcc4bb639043ac961c49e6..52ec390b0bba65e21dddb3723643d756b7f97151 100644 (file)
@@ -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 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_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_cxx17.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx17.cpp
deleted file mode 100644 (file)
index 52cf517..0000000
+++ /dev/null
@@ -1,515 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s
-
-template<typename T, T val> struct A {};
-
-template<typename T, typename U> constexpr bool is_same = false; // expected-note +{{here}}
-template<typename T> constexpr bool is_same<T, T> = true;
-
-namespace String {
-  A<const char*, "test"> a; // expected-error {{pointer to subobject of string literal}}
-  A<const char (&)[5], "test"> b; // expected-error {{reference to string literal}}
-}
-
-namespace Array {
-  char arr[3];
-  char x;
-  A<const char*, arr> a;
-  A<const char(&)[3], arr> b;
-  A<const char*, &arr[0]> c;
-  A<const char*, &arr[1]> d; // expected-error {{refers to subobject '&arr[1]'}}
-  A<const char*, (&arr)[0]> e;
-  A<const char*, &x> f;
-  A<const char*, &(&x)[0]> g;
-  A<const char*, &(&x)[1]> h; // expected-error {{refers to subobject '&x + 1'}}
-  A<const char*, 0> i; // expected-error {{not allowed in a converted constant}}
-  A<const char*, nullptr> j;
-
-  extern char aub[];
-  A<char[], aub> k;
-}
-
-namespace Function {
-  void f();
-  void g() noexcept;
-  void h();
-  void h(int);
-  template<typename...T> void i(T...);
-  typedef A<void (*)(), f> a;
-  typedef A<void (*)(), &f> a;
-  typedef A<void (*)(), g> b;
-  typedef A<void (*)(), &g> b;
-  typedef A<void (*)(), h> c;
-  typedef A<void (*)(), &h> c;
-  typedef A<void (*)(), i> d;
-  typedef A<void (*)(), &i> d;
-  typedef A<void (*)(), i<>> d;
-  typedef A<void (*)(), i<int>> e; // expected-error {{is not implicitly convertible}}
-
-  typedef A<void (*)(), 0> x; // expected-error {{not allowed in a converted constant}}
-  typedef A<void (*)(), nullptr> y;
-}
-
-void Func() {
-  A<const char*, __func__> a; // expected-error {{pointer to subobject of predefined '__func__' variable}}
-}
-
-namespace LabelAddrDiff {
-  void f() {
-    a: b: A<int, __builtin_constant_p(true) ? (__INTPTR_TYPE__)&&b - (__INTPTR_TYPE__)&&a : 0> s; // expected-error {{label address difference}}
-  };
-}
-
-namespace Temp {
-  struct S { int n; };
-  constexpr S &addr(S &&s) { return s; }
-  A<S &, addr({})> a; // expected-error {{reference to temporary object}}
-  A<S *, &addr({})> b; // expected-error {{pointer to temporary object}}
-  A<int &, addr({}).n> c; // expected-error {{reference to subobject of temporary object}}
-  A<int *, &addr({}).n> d; // expected-error {{pointer to subobject of temporary object}}
-}
-
-namespace std { struct type_info; }
-
-namespace RTTI {
-  A<const std::type_info&, typeid(int)> a; // expected-error {{reference to type_info object}}
-  A<const std::type_info*, &typeid(int)> b; // expected-error {{pointer to type_info object}}
-}
-
-namespace PtrMem {
-  struct B { int b; };
-  struct C : B {};
-  struct D : B {};
-  struct E : C, D { int e; };
-
-  constexpr int B::*b = &B::b;
-  constexpr int C::*cb = b;
-  constexpr int D::*db = b;
-  constexpr int E::*ecb = cb; // expected-note +{{here}}
-  constexpr int E::*edb = db; // expected-note +{{here}}
-
-  constexpr int E::*e = &E::e;
-  constexpr int D::*de = (int D::*)e;
-  constexpr int C::*ce = (int C::*)e;
-  constexpr int B::*bde = (int B::*)de; // expected-note +{{here}}
-  constexpr int B::*bce = (int B::*)ce; // expected-note +{{here}}
-
-  // FIXME: This should all be accepted, but we don't yet have a representation
-  // nor mangling for this form of template argument.
-  using Ab = A<int B::*, b>;
-  using Ab = A<int B::*, &B::b>;
-  using Abce = A<int B::*, bce>; // expected-error {{not supported}}
-  using Abde = A<int B::*, bde>; // expected-error {{not supported}}
-  static_assert(!is_same<Ab, Abce>, ""); // expected-error {{undeclared}} expected-error {{must be a type}}
-  static_assert(!is_same<Ab, Abde>, ""); // expected-error {{undeclared}} expected-error {{must be a type}}
-  static_assert(!is_same<Abce, Abde>, ""); // expected-error 2{{undeclared}} expected-error {{must be a type}}
-  static_assert(is_same<Abce, A<int B::*, (int B::*)(int C::*)&E::e>>, ""); // expected-error {{undeclared}} expected-error {{not supported}}
-
-  using Ae = A<int E::*, e>;
-  using Ae = A<int E::*, &E::e>;
-  using Aecb = A<int E::*, ecb>; // expected-error {{not supported}}
-  using Aedb = A<int E::*, edb>; // expected-error {{not supported}}
-  static_assert(!is_same<Ae, Aecb>, ""); // expected-error {{undeclared}} expected-error {{must be a type}}
-  static_assert(!is_same<Ae, Aedb>, ""); // expected-error {{undeclared}} expected-error {{must be a type}}
-  static_assert(!is_same<Aecb, Aedb>, ""); // expected-error 2{{undeclared}} expected-error {{must be a type}}
-  static_assert(is_same<Aecb, A<int E::*, (int E::*)(int C::*)&B::b>>, ""); // expected-error {{undeclared}} expected-error {{not supported}}
-
-  using An = A<int E::*, nullptr>;
-  using A0 = A<int E::*, (int E::*)0>;
-  static_assert(is_same<An, A0>);
-}
-
-namespace DeduceDifferentType {
-  template<int N> struct A {};
-  template<long N> int a(A<N>); // expected-note {{does not have the same type}}
-  int a_imp = a(A<3>()); // expected-error {{no matching function}}
-  int a_exp = a<3>(A<3>());
-
-  template<decltype(nullptr)> struct B {};
-  template<int *P> int b(B<P>); // expected-error {{value of type 'int *' is not implicitly convertible to 'decltype(nullptr)'}}
-  int b_imp = b(B<nullptr>()); // expected-error {{no matching function}}
-  int b_exp = b<nullptr>(B<nullptr>()); // expected-error {{no matching function}}
-
-  struct X { constexpr operator int() { return 0; } } x;
-  template<X &> struct C {};
-  template<int N> int c(C<N>); // expected-error {{value of type 'int' is not implicitly convertible to 'DeduceDifferentType::X &'}}
-  int c_imp = c(C<x>()); // expected-error {{no matching function}}
-  int c_exp = c<x>(C<x>()); // expected-error {{no matching function}}
-
-  struct Z;
-  struct Y { constexpr operator Z&(); } y;
-  struct Z { constexpr operator Y&() { return y; } } z;
-  constexpr Y::operator Z&() { return z; }
-  template<Y &> struct D {};
-  template<Z &z> int d(D<z>); // expected-note {{couldn't infer template argument 'z'}}
-  int d_imp = d(D<y>()); // expected-error {{no matching function}}
-  int d_exp = d<y>(D<y>());
-}
-
-namespace DeclMatch {
-  template<typename T, T> int f();
-  template<typename T> class X { friend int f<T, 0>(); static int n; };
-  template<typename T, T> int f() { return X<T>::n; }
-  int k = f<int, 0>(); // ok, friend
-}
-
-namespace PR24921 {
-  enum E { e };
-  template<E> void f();
-  template<int> void f(int);
-  template<> void f<e>() {}
-}
-
-namespace Auto {
-  namespace Basic {
-    // simple auto
-    template<auto x> constexpr auto constant = x; // expected-note {{declared here}}
-
-    auto v1 = constant<5>;
-    auto v2 = constant<true>;
-    auto v3 = constant<'a'>;
-    auto v4 = constant<2.5>;  // expected-error {{cannot have type 'double'}}
-
-    using T1 = decltype(v1);
-    using T1 = int;
-    using T2 = decltype(v2);
-    using T2 = bool;
-    using T3 = decltype(v3);
-    using T3 = char;
-
-    // pointers
-    template<auto v>    class B { };
-    template<auto* p>   class B<p> { }; // expected-note {{matches}}
-    template<auto** pp> class B<pp> { };
-    template<auto* p0>   int &f(B<p0> b); // expected-note {{candidate}}
-    template<auto** pp0> float &f(B<pp0> b); // expected-note {{candidate}}
-
-    int a, *b = &a;
-    int &r = f(B<&a>());
-    float &s = f(B<&b>());
-
-    void type_affects_identity(B<&a>) {}
-    void type_affects_identity(B<(const int*)&a>) {}
-    void type_affects_identity(B<(void*)&a>) {}
-    void type_affects_identity(B<(const void*)&a>) {}
-
-    // pointers to members
-    template<typename T, auto *T::*p> struct B<p> {};
-    template<typename T, auto **T::*p> struct B<p> {};
-    template<typename T, auto *T::*p0>   char &f(B<p0> b); // expected-note {{candidate}}
-    template<typename T, auto **T::*pp0> short &f(B<pp0> b); // expected-note {{candidate}}
-
-    struct X { int n; int *p; int **pp; typedef int a, b; };
-    auto t = f(B<&X::n>()); // expected-error {{no match}}
-    char &u = f(B<&X::p>());
-    short &v = f(B<&X::pp>());
-
-    struct Y : X {};
-    void type_affects_identity(B<&X::n>) {}
-    void type_affects_identity(B<(int Y::*)&X::n>) {} // FIXME: expected-error {{sorry}}
-    void type_affects_identity(B<(const int X::*)&X::n>) {}
-    void type_affects_identity(B<(const int Y::*)&X::n>) {} // FIXME: expected-error {{sorry}}
-
-    // A case where we need to do auto-deduction, and check whether the
-    // resulting dependent types match during partial ordering. These
-    // templates are not ordered due to the mismatching function parameter.
-    template<typename T, auto *(*f)(T, typename T::a)> struct B<f> {}; // expected-note {{matches}}
-    template<typename T, auto **(*f)(T, typename T::b)> struct B<f> {}; // expected-note {{matches}}
-    int **g(X, int);
-    B<&g> bg; // expected-error {{ambiguous}}
-  }
-
-  namespace Chained {
-    // chained template argument deduction
-    template<long n> struct C { };
-    template<class T> struct D;
-    template<class T, T n> struct D<C<n>>
-    {
-        using Q = T;
-    };
-    using DQ = long;
-    using DQ = D<C<short(2)>>::Q;
-
-    // chained template argument deduction from an array bound
-    template<typename T> struct E;
-    template<typename T, T n> struct E<int[n]> {
-        using Q = T;
-    };
-    using EQ = E<int[short(42)]>::Q;
-    using EQ = decltype(sizeof 0);
-
-    template<int N> struct F;
-    template<typename T, T N> int foo(F<N> *) = delete;  // expected-note {{explicitly deleted}}
-    void foo(void *); // expected-note {{candidate function}}
-    void bar(F<0> *p) {
-        foo(p); // expected-error {{deleted function}}
-    }
-  }
-
-  namespace ArrayToPointer {
-    constexpr char s[] = "test";
-    template<const auto* p> struct S { };
-    S<s> p;
-
-    template<typename R, typename P, R F(P)> struct A {};
-    template<typename R, typename P, R F(P)> void x(A<R, P, F> a);
-    void g(int) { x(A<void, int, &g>()); }
-  }
-
-  namespace DecltypeAuto {
-    template<auto v> struct A { };
-    template<decltype(auto) v> struct DA { };
-    template<auto&> struct R { };
-
-    auto n = 0; // expected-note + {{declared here}}
-    A<n> a; // expected-error {{not a constant}} expected-note {{non-const variable 'n'}}
-    DA<n> da1;  // expected-error {{not a constant}} expected-note {{non-const variable 'n'}}
-    DA<(n)> da2;
-    R<n> r;
-  }
-
-  namespace Decomposition {
-    // Types of deduced non-type template arguments must match exactly, so
-    // partial ordering fails in both directions here.
-    template<auto> struct Any;
-    template<int N> struct Any<N> { typedef int Int; }; // expected-note 3{{match}}
-    template<short N> struct Any<N> { typedef int Short; }; // expected-note 3{{match}}
-    Any<0>::Int is_int; // expected-error {{ambiguous}}
-    Any<(short)0>::Short is_short; // expected-error {{ambiguous}}
-    Any<(char)0>::Short is_char; // expected-error {{ambiguous}}
-
-    template<int, auto> struct NestedAny;
-    template<auto N> struct NestedAny<0, N>; // expected-note 3{{match}}
-    template<int N> struct NestedAny<0, N> { typedef int Int; }; // expected-note 3{{match}}
-    template<short N> struct NestedAny<0, N> { typedef int Short; }; // expected-note 3{{match}}
-    NestedAny<0, 0>::Int nested_int; // expected-error {{ambiguous}}
-    NestedAny<0, (short)0>::Short nested_short; // expected-error {{ambiguous}}
-    NestedAny<0, (char)0>::Short nested_char; // expected-error {{ambiguous}}
-
-    double foo(int, bool);
-    template<auto& f> struct fn_result_type;
-
-    template<class R, class... Args, R (& f)(Args...)>
-    struct fn_result_type<f>
-    {
-        using type = R;
-    };
-
-    using R1 = fn_result_type<foo>::type;
-    using R1 = double;
-
-    template<int, auto &f> struct fn_result_type_partial_order;
-    template<auto &f> struct fn_result_type_partial_order<0, f>;
-    template<class R, class... Args, R (& f)(Args...)>
-    struct fn_result_type_partial_order<0, f> {};
-    fn_result_type_partial_order<0, foo> frtpo;
-  }
-
-  namespace Variadic {
-    template<auto... vs> struct value_list { };
-
-    using size_t = decltype(sizeof 0);
-    template<size_t n, class List> struct nth_element;
-    template<size_t n, class List> constexpr auto nth_element_v = nth_element<n, List>::value;
-
-    template<size_t n, auto v0, auto... vs>
-    struct nth_element<n, value_list<v0, vs...>>
-    {
-        static constexpr auto value = nth_element<n - 1, value_list<vs...>>::value;
-    };
-    template<auto v0, auto... vs>
-    struct nth_element<0, value_list<v0, vs...>>
-    {
-        static constexpr auto value = v0;
-    };
-
-    static_assert(nth_element_v<2, value_list<'a', 27U, false>> == false, "value mismatch");
-  }
-}
-
-namespace Nested {
-  template<typename T> struct A {
-    template<auto X> struct B;
-    template<auto *P> struct B<P>;
-    template<auto **P> struct B<P> { using pointee = decltype(+**P); };
-    template<auto (*P)(T)> struct B<P> { using param = T; };
-    template<typename U, auto (*P)(T, U)> struct B<P> { using param2 = U; };
-  };
-
-  using Int = int;
-
-  int *n;
-  using Int = A<int>::B<&n>::pointee;
-
-  void f(int);
-  using Int = A<int>::B<&f>::param;
-
-  void g(int, int);
-  using Int = A<int>::B<&g>::param2;
-}
-
-namespace rdar41852459 {
-template <auto V> struct G {};
-
-template <class T> struct S {
-  template <auto V> void f() {
-    G<V> x;
-  }
-  template <auto *PV> void f2() {
-    G<PV> x;
-  }
-  template <decltype(auto) V> void f3() {
-    G<V> x;
-  }
-};
-
-template <auto *PV> struct I {};
-
-template <class T> struct K {
-  template <auto *PV> void f() {
-    I<PV> x;
-  }
-  template <auto V> void f2() {
-    I<V> x;
-  }
-  template <decltype(auto) V> void f3() {
-    I<V> x;
-  }
-};
-
-template <decltype(auto)> struct L {};
-template <class T> struct M {
-  template <auto *PV> void f() {
-    L<PV> x;
-  }
-  template <auto V> void f() {
-    L<V> x;
-  }
-  template <decltype(auto) V> void f() {
-    L<V> x;
-  }
-};
-}
-
-namespace PR42362 {
-  template<auto ...A> struct X { struct Y; void f(int...[A]); };
-  template<auto ...A> struct X<A...>::Y {};
-  template<auto ...A> void X<A...>::f(int...[A]) {}
-  void f() { X<1, 2>::Y y; X<1, 2>().f(0, 0); }
-
-  template<typename, auto...> struct Y;
-  template<auto ...A> struct Y<int, A...> {};
-  Y<int, 1, 2, 3> y;
-
-  template<auto (&...F)()> struct Z { struct Q; };
-  template<auto (&...F)()> struct Z<F...>::Q {};
-  Z<f, f, f>::Q q;
-}
-
-namespace QualConv {
-  int *X;
-  template<const int *const *P> void f() {
-    using T = decltype(P);
-    using T = const int* const*;
-  }
-  template void f<&X>();
-
-  template<const int *const &R> void g() {
-    using T = decltype(R);
-    using T = const int *const &;
-  }
-  template void g<(const int *const&)X>();
-}
-
-namespace FunctionConversion {
-  struct a { void c(char *) noexcept; };
-  template<void (a::*f)(char*)> void g() {
-    using T = decltype(f);
-    using T = void (a::*)(char*); // (not 'noexcept')
-  }
-  template void g<&a::c>();
-
-  void c() noexcept;
-  template<void (*p)()> void h() {
-    using T = decltype(p);
-    using T = void (*)(); // (not 'noexcept')
-  }
-  template void h<&c>();
-}
-
-namespace VoidPtr {
-  // Note, this is an extension in C++17 but valid in C++20.
-  template<void *P> void f() {
-    using T = decltype(P);
-    using T = void*;
-  }
-  int n;
-  template void f<(void*)&n>();
-}
-
-namespace PR42108 {
-  struct R {};
-  struct S { constexpr S() {} constexpr S(R) {} };
-  struct T { constexpr operator S() { return {}; } };
-  template <const S &> struct A {};
-  void f() {
-    A<R{}>(); // expected-error {{would bind reference to a temporary}}
-    A<S{}>(); // expected-error {{reference to temporary object}}
-    A<T{}>(); // expected-error {{reference to temporary object}}
-  }
-}
-
-namespace PR46637 {
-  template<auto (*f)() -> auto> struct X { // expected-note {{here}}
-    auto call() { return f(); }
-  };
-  X<nullptr> x; // expected-error {{incompatible initializer}}
-
-  void *f();
-  X<f> y;
-  int n = y.call(); // expected-error {{cannot initialize a variable of type 'int' with an rvalue of type 'void *'}}
-}
-
-namespace PR48517 {
-  template<const int *P> struct A { static constexpr const int *p = P; };
-  template<typename T> auto make_nonconst() {
-    static int n;
-    return A<&n>();
-  };
-  using T = decltype(make_nonconst<int>()); // expected-note {{previous}}
-  using U = decltype(make_nonconst<float>());
-  static_assert(T::p != U::p);
-  using T = U; // expected-error {{different types}}
-
-  template<typename T> auto make_const() {
-    static constexpr int n = 42;
-    return A<&n>();
-  };
-  using V = decltype(make_const<int>()); // expected-note {{previous}}
-  using W = decltype(make_const<float>());
-  static_assert(*V::p == *W::p);
-  static_assert(V::p != W::p);
-  using V = W; // expected-error {{different types}}
-
-  template<auto V> struct Q {
-    using X = int;
-    static_assert(V == "primary template should not be instantiated");
-  };
-  template<typename T> struct R {
-    int n;
-    constexpr int f() {
-      return Q<&R::n>::X;
-    }
-  };
-  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_cxx1z.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
new file mode 100644 (file)
index 0000000..675f957
--- /dev/null
@@ -0,0 +1,505 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z %s
+
+template<typename T, T val> struct A {};
+
+template<typename T, typename U> constexpr bool is_same = false; // expected-note +{{here}}
+template<typename T> constexpr bool is_same<T, T> = true;
+
+namespace String {
+  A<const char*, "test"> a; // expected-error {{pointer to subobject of string literal}}
+  A<const char (&)[5], "test"> b; // expected-error {{reference to string literal}}
+}
+
+namespace Array {
+  char arr[3];
+  char x;
+  A<const char*, arr> a;
+  A<const char(&)[3], arr> b;
+  A<const char*, &arr[0]> c;
+  A<const char*, &arr[1]> d; // expected-error {{refers to subobject '&arr[1]'}}
+  A<const char*, (&arr)[0]> e;
+  A<const char*, &x> f;
+  A<const char*, &(&x)[0]> g;
+  A<const char*, &(&x)[1]> h; // expected-error {{refers to subobject '&x + 1'}}
+  A<const char*, 0> i; // expected-error {{not allowed in a converted constant}}
+  A<const char*, nullptr> j;
+
+  extern char aub[];
+  A<char[], aub> k;
+}
+
+namespace Function {
+  void f();
+  void g() noexcept;
+  void h();
+  void h(int);
+  template<typename...T> void i(T...);
+  typedef A<void (*)(), f> a;
+  typedef A<void (*)(), &f> a;
+  typedef A<void (*)(), g> b;
+  typedef A<void (*)(), &g> b;
+  typedef A<void (*)(), h> c;
+  typedef A<void (*)(), &h> c;
+  typedef A<void (*)(), i> d;
+  typedef A<void (*)(), &i> d;
+  typedef A<void (*)(), i<>> d;
+  typedef A<void (*)(), i<int>> e; // expected-error {{is not implicitly convertible}}
+
+  typedef A<void (*)(), 0> x; // expected-error {{not allowed in a converted constant}}
+  typedef A<void (*)(), nullptr> y;
+}
+
+void Func() {
+  A<const char*, __func__> a; // expected-error {{pointer to subobject of predefined '__func__' variable}}
+}
+
+namespace LabelAddrDiff {
+  void f() {
+    a: b: A<int, __builtin_constant_p(true) ? (__INTPTR_TYPE__)&&b - (__INTPTR_TYPE__)&&a : 0> s; // expected-error {{label address difference}}
+  };
+}
+
+namespace Temp {
+  struct S { int n; };
+  constexpr S &addr(S &&s) { return s; }
+  A<S &, addr({})> a; // expected-error {{reference to temporary object}}
+  A<S *, &addr({})> b; // expected-error {{pointer to temporary object}}
+  A<int &, addr({}).n> c; // expected-error {{reference to subobject of temporary object}}
+  A<int *, &addr({}).n> d; // expected-error {{pointer to subobject of temporary object}}
+}
+
+namespace std { struct type_info; }
+
+namespace RTTI {
+  A<const std::type_info&, typeid(int)> a; // expected-error {{reference to type_info object}}
+  A<const std::type_info*, &typeid(int)> b; // expected-error {{pointer to type_info object}}
+}
+
+namespace PtrMem {
+  struct B { int b; };
+  struct C : B {};
+  struct D : B {};
+  struct E : C, D { int e; };
+
+  constexpr int B::*b = &B::b;
+  constexpr int C::*cb = b;
+  constexpr int D::*db = b;
+  constexpr int E::*ecb = cb; // expected-note +{{here}}
+  constexpr int E::*edb = db; // expected-note +{{here}}
+
+  constexpr int E::*e = &E::e;
+  constexpr int D::*de = (int D::*)e;
+  constexpr int C::*ce = (int C::*)e;
+  constexpr int B::*bde = (int B::*)de; // expected-note +{{here}}
+  constexpr int B::*bce = (int B::*)ce; // expected-note +{{here}}
+
+  // FIXME: This should all be accepted, but we don't yet have a representation
+  // nor mangling for this form of template argument.
+  using Ab = A<int B::*, b>;
+  using Ab = A<int B::*, &B::b>;
+  using Abce = A<int B::*, bce>; // expected-error {{not supported}}
+  using Abde = A<int B::*, bde>; // expected-error {{not supported}}
+  static_assert(!is_same<Ab, Abce>, ""); // expected-error {{undeclared}} expected-error {{must be a type}}
+  static_assert(!is_same<Ab, Abde>, ""); // expected-error {{undeclared}} expected-error {{must be a type}}
+  static_assert(!is_same<Abce, Abde>, ""); // expected-error 2{{undeclared}} expected-error {{must be a type}}
+  static_assert(is_same<Abce, A<int B::*, (int B::*)(int C::*)&E::e>>, ""); // expected-error {{undeclared}} expected-error {{not supported}}
+
+  using Ae = A<int E::*, e>;
+  using Ae = A<int E::*, &E::e>;
+  using Aecb = A<int E::*, ecb>; // expected-error {{not supported}}
+  using Aedb = A<int E::*, edb>; // expected-error {{not supported}}
+  static_assert(!is_same<Ae, Aecb>, ""); // expected-error {{undeclared}} expected-error {{must be a type}}
+  static_assert(!is_same<Ae, Aedb>, ""); // expected-error {{undeclared}} expected-error {{must be a type}}
+  static_assert(!is_same<Aecb, Aedb>, ""); // expected-error 2{{undeclared}} expected-error {{must be a type}}
+  static_assert(is_same<Aecb, A<int E::*, (int E::*)(int C::*)&B::b>>, ""); // expected-error {{undeclared}} expected-error {{not supported}}
+
+  using An = A<int E::*, nullptr>;
+  using A0 = A<int E::*, (int E::*)0>;
+  static_assert(is_same<An, A0>);
+}
+
+namespace DeduceDifferentType {
+  template<int N> struct A {};
+  template<long N> int a(A<N>); // expected-note {{does not have the same type}}
+  int a_imp = a(A<3>()); // expected-error {{no matching function}}
+  int a_exp = a<3>(A<3>());
+
+  template<decltype(nullptr)> struct B {};
+  template<int *P> int b(B<P>); // expected-error {{value of type 'int *' is not implicitly convertible to 'decltype(nullptr)'}}
+  int b_imp = b(B<nullptr>()); // expected-error {{no matching function}}
+  int b_exp = b<nullptr>(B<nullptr>()); // expected-error {{no matching function}}
+
+  struct X { constexpr operator int() { return 0; } } x;
+  template<X &> struct C {};
+  template<int N> int c(C<N>); // expected-error {{value of type 'int' is not implicitly convertible to 'DeduceDifferentType::X &'}}
+  int c_imp = c(C<x>()); // expected-error {{no matching function}}
+  int c_exp = c<x>(C<x>()); // expected-error {{no matching function}}
+
+  struct Z;
+  struct Y { constexpr operator Z&(); } y;
+  struct Z { constexpr operator Y&() { return y; } } z;
+  constexpr Y::operator Z&() { return z; }
+  template<Y &> struct D {};
+  template<Z &z> int d(D<z>); // expected-note {{couldn't infer template argument 'z'}}
+  int d_imp = d(D<y>()); // expected-error {{no matching function}}
+  int d_exp = d<y>(D<y>());
+}
+
+namespace DeclMatch {
+  template<typename T, T> int f();
+  template<typename T> class X { friend int f<T, 0>(); static int n; };
+  template<typename T, T> int f() { return X<T>::n; }
+  int k = f<int, 0>(); // ok, friend
+}
+
+namespace PR24921 {
+  enum E { e };
+  template<E> void f();
+  template<int> void f(int);
+  template<> void f<e>() {}
+}
+
+namespace Auto {
+  namespace Basic {
+    // simple auto
+    template<auto x> constexpr auto constant = x; // expected-note {{declared here}}
+
+    auto v1 = constant<5>;
+    auto v2 = constant<true>;
+    auto v3 = constant<'a'>;
+    auto v4 = constant<2.5>;  // expected-error {{cannot have type 'double'}}
+
+    using T1 = decltype(v1);
+    using T1 = int;
+    using T2 = decltype(v2);
+    using T2 = bool;
+    using T3 = decltype(v3);
+    using T3 = char;
+
+    // pointers
+    template<auto v>    class B { };
+    template<auto* p>   class B<p> { }; // expected-note {{matches}}
+    template<auto** pp> class B<pp> { };
+    template<auto* p0>   int &f(B<p0> b); // expected-note {{candidate}}
+    template<auto** pp0> float &f(B<pp0> b); // expected-note {{candidate}}
+
+    int a, *b = &a;
+    int &r = f(B<&a>());
+    float &s = f(B<&b>());
+
+    void type_affects_identity(B<&a>) {}
+    void type_affects_identity(B<(const int*)&a>) {}
+    void type_affects_identity(B<(void*)&a>) {}
+    void type_affects_identity(B<(const void*)&a>) {}
+
+    // pointers to members
+    template<typename T, auto *T::*p> struct B<p> {};
+    template<typename T, auto **T::*p> struct B<p> {};
+    template<typename T, auto *T::*p0>   char &f(B<p0> b); // expected-note {{candidate}}
+    template<typename T, auto **T::*pp0> short &f(B<pp0> b); // expected-note {{candidate}}
+
+    struct X { int n; int *p; int **pp; typedef int a, b; };
+    auto t = f(B<&X::n>()); // expected-error {{no match}}
+    char &u = f(B<&X::p>());
+    short &v = f(B<&X::pp>());
+
+    struct Y : X {};
+    void type_affects_identity(B<&X::n>) {}
+    void type_affects_identity(B<(int Y::*)&X::n>) {} // FIXME: expected-error {{sorry}}
+    void type_affects_identity(B<(const int X::*)&X::n>) {}
+    void type_affects_identity(B<(const int Y::*)&X::n>) {} // FIXME: expected-error {{sorry}}
+
+    // A case where we need to do auto-deduction, and check whether the
+    // resulting dependent types match during partial ordering. These
+    // templates are not ordered due to the mismatching function parameter.
+    template<typename T, auto *(*f)(T, typename T::a)> struct B<f> {}; // expected-note {{matches}}
+    template<typename T, auto **(*f)(T, typename T::b)> struct B<f> {}; // expected-note {{matches}}
+    int **g(X, int);
+    B<&g> bg; // expected-error {{ambiguous}}
+  }
+
+  namespace Chained {
+    // chained template argument deduction
+    template<long n> struct C { };
+    template<class T> struct D;
+    template<class T, T n> struct D<C<n>>
+    {
+        using Q = T;
+    };
+    using DQ = long;
+    using DQ = D<C<short(2)>>::Q;
+
+    // chained template argument deduction from an array bound
+    template<typename T> struct E;
+    template<typename T, T n> struct E<int[n]> {
+        using Q = T;
+    };
+    using EQ = E<int[short(42)]>::Q;
+    using EQ = decltype(sizeof 0);
+
+    template<int N> struct F;
+    template<typename T, T N> int foo(F<N> *) = delete;  // expected-note {{explicitly deleted}}
+    void foo(void *); // expected-note {{candidate function}}
+    void bar(F<0> *p) {
+        foo(p); // expected-error {{deleted function}}
+    }
+  }
+
+  namespace ArrayToPointer {
+    constexpr char s[] = "test";
+    template<const auto* p> struct S { };
+    S<s> p;
+
+    template<typename R, typename P, R F(P)> struct A {};
+    template<typename R, typename P, R F(P)> void x(A<R, P, F> a);
+    void g(int) { x(A<void, int, &g>()); }
+  }
+
+  namespace DecltypeAuto {
+    template<auto v> struct A { };
+    template<decltype(auto) v> struct DA { };
+    template<auto&> struct R { };
+
+    auto n = 0; // expected-note + {{declared here}}
+    A<n> a; // expected-error {{not a constant}} expected-note {{non-const variable 'n'}}
+    DA<n> da1;  // expected-error {{not a constant}} expected-note {{non-const variable 'n'}}
+    DA<(n)> da2;
+    R<n> r;
+  }
+
+  namespace Decomposition {
+    // Types of deduced non-type template arguments must match exactly, so
+    // partial ordering fails in both directions here.
+    template<auto> struct Any;
+    template<int N> struct Any<N> { typedef int Int; }; // expected-note 3{{match}}
+    template<short N> struct Any<N> { typedef int Short; }; // expected-note 3{{match}}
+    Any<0>::Int is_int; // expected-error {{ambiguous}}
+    Any<(short)0>::Short is_short; // expected-error {{ambiguous}}
+    Any<(char)0>::Short is_char; // expected-error {{ambiguous}}
+
+    template<int, auto> struct NestedAny;
+    template<auto N> struct NestedAny<0, N>; // expected-note 3{{match}}
+    template<int N> struct NestedAny<0, N> { typedef int Int; }; // expected-note 3{{match}}
+    template<short N> struct NestedAny<0, N> { typedef int Short; }; // expected-note 3{{match}}
+    NestedAny<0, 0>::Int nested_int; // expected-error {{ambiguous}}
+    NestedAny<0, (short)0>::Short nested_short; // expected-error {{ambiguous}}
+    NestedAny<0, (char)0>::Short nested_char; // expected-error {{ambiguous}}
+
+    double foo(int, bool);
+    template<auto& f> struct fn_result_type;
+
+    template<class R, class... Args, R (& f)(Args...)>
+    struct fn_result_type<f>
+    {
+        using type = R;
+    };
+
+    using R1 = fn_result_type<foo>::type;
+    using R1 = double;
+
+    template<int, auto &f> struct fn_result_type_partial_order;
+    template<auto &f> struct fn_result_type_partial_order<0, f>;
+    template<class R, class... Args, R (& f)(Args...)>
+    struct fn_result_type_partial_order<0, f> {};
+    fn_result_type_partial_order<0, foo> frtpo;
+  }
+
+  namespace Variadic {
+    template<auto... vs> struct value_list { };
+
+    using size_t = decltype(sizeof 0);
+    template<size_t n, class List> struct nth_element;
+    template<size_t n, class List> constexpr auto nth_element_v = nth_element<n, List>::value;
+
+    template<size_t n, auto v0, auto... vs>
+    struct nth_element<n, value_list<v0, vs...>>
+    {
+        static constexpr auto value = nth_element<n - 1, value_list<vs...>>::value;
+    };
+    template<auto v0, auto... vs>
+    struct nth_element<0, value_list<v0, vs...>>
+    {
+        static constexpr auto value = v0;
+    };
+
+    static_assert(nth_element_v<2, value_list<'a', 27U, false>> == false, "value mismatch");
+  }
+}
+
+namespace Nested {
+  template<typename T> struct A {
+    template<auto X> struct B;
+    template<auto *P> struct B<P>;
+    template<auto **P> struct B<P> { using pointee = decltype(+**P); };
+    template<auto (*P)(T)> struct B<P> { using param = T; };
+    template<typename U, auto (*P)(T, U)> struct B<P> { using param2 = U; };
+  };
+
+  using Int = int;
+
+  int *n;
+  using Int = A<int>::B<&n>::pointee;
+
+  void f(int);
+  using Int = A<int>::B<&f>::param;
+
+  void g(int, int);
+  using Int = A<int>::B<&g>::param2;
+}
+
+namespace rdar41852459 {
+template <auto V> struct G {};
+
+template <class T> struct S {
+  template <auto V> void f() {
+    G<V> x;
+  }
+  template <auto *PV> void f2() {
+    G<PV> x;
+  }
+  template <decltype(auto) V> void f3() {
+    G<V> x;
+  }
+};
+
+template <auto *PV> struct I {};
+
+template <class T> struct K {
+  template <auto *PV> void f() {
+    I<PV> x;
+  }
+  template <auto V> void f2() {
+    I<V> x;
+  }
+  template <decltype(auto) V> void f3() {
+    I<V> x;
+  }
+};
+
+template <decltype(auto)> struct L {};
+template <class T> struct M {
+  template <auto *PV> void f() {
+    L<PV> x;
+  }
+  template <auto V> void f() {
+    L<V> x;
+  }
+  template <decltype(auto) V> void f() {
+    L<V> x;
+  }
+};
+}
+
+namespace PR42362 {
+  template<auto ...A> struct X { struct Y; void f(int...[A]); };
+  template<auto ...A> struct X<A...>::Y {};
+  template<auto ...A> void X<A...>::f(int...[A]) {}
+  void f() { X<1, 2>::Y y; X<1, 2>().f(0, 0); }
+
+  template<typename, auto...> struct Y;
+  template<auto ...A> struct Y<int, A...> {};
+  Y<int, 1, 2, 3> y;
+
+  template<auto (&...F)()> struct Z { struct Q; };
+  template<auto (&...F)()> struct Z<F...>::Q {};
+  Z<f, f, f>::Q q;
+}
+
+namespace QualConv {
+  int *X;
+  template<const int *const *P> void f() {
+    using T = decltype(P);
+    using T = const int* const*;
+  }
+  template void f<&X>();
+
+  template<const int *const &R> void g() {
+    using T = decltype(R);
+    using T = const int *const &;
+  }
+  template void g<(const int *const&)X>();
+}
+
+namespace FunctionConversion {
+  struct a { void c(char *) noexcept; };
+  template<void (a::*f)(char*)> void g() {
+    using T = decltype(f);
+    using T = void (a::*)(char*); // (not 'noexcept')
+  }
+  template void g<&a::c>();
+
+  void c() noexcept;
+  template<void (*p)()> void h() {
+    using T = decltype(p);
+    using T = void (*)(); // (not 'noexcept')
+  }
+  template void h<&c>();
+}
+
+namespace VoidPtr {
+  // Note, this is an extension in C++17 but valid in C++20.
+  template<void *P> void f() {
+    using T = decltype(P);
+    using T = void*;
+  }
+  int n;
+  template void f<(void*)&n>();
+}
+
+namespace PR42108 {
+  struct R {};
+  struct S { constexpr S() {} constexpr S(R) {} };
+  struct T { constexpr operator S() { return {}; } };
+  template <const S &> struct A {};
+  void f() {
+    A<R{}>(); // expected-error {{would bind reference to a temporary}}
+    A<S{}>(); // expected-error {{reference to temporary object}}
+    A<T{}>(); // expected-error {{reference to temporary object}}
+  }
+}
+
+namespace PR46637 {
+  template<auto (*f)() -> auto> struct X { // expected-note {{here}}
+    auto call() { return f(); }
+  };
+  X<nullptr> x; // expected-error {{incompatible initializer}}
+
+  void *f();
+  X<f> y;
+  int n = y.call(); // expected-error {{cannot initialize a variable of type 'int' with an rvalue of type 'void *'}}
+}
+
+namespace PR48517 {
+  template<const int *P> struct A { static constexpr const int *p = P; };
+  template<typename T> auto make_nonconst() {
+    static int n;
+    return A<&n>();
+  };
+  using T = decltype(make_nonconst<int>()); // expected-note {{previous}}
+  using U = decltype(make_nonconst<float>());
+  static_assert(T::p != U::p);
+  using T = U; // expected-error {{different types}}
+
+  template<typename T> auto make_const() {
+    static constexpr int n = 42;
+    return A<&n>();
+  };
+  using V = decltype(make_const<int>()); // expected-note {{previous}}
+  using W = decltype(make_const<float>());
+  static_assert(*V::p == *W::p);
+  static_assert(V::p != W::p);
+  using V = W; // expected-error {{different types}}
+
+  template<auto V> struct Q {
+    using X = int;
+    static_assert(V == "primary template should not be instantiated");
+  };
+  template<typename T> struct R {
+    int n;
+    constexpr int f() {
+      return Q<&R::n>::X;
+    }
+  };
+  template<> struct Q<&R<int>::n> { static constexpr int X = 1; };
+  static_assert(R<int>().f() == 1);
+}
index d514465f7d677f487bd76239a658d178317d3388..c42fda7804305dd5249bf6c8c8cf820039d38079 100644 (file)
@@ -292,47 +292,3 @@ 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>();
-}