Revert r219977, "Re-commit r217995 and follow-up patches (r217997, r218011, r218053...
authorNAKAMURA Takumi <geek4civic@gmail.com>
Fri, 17 Oct 2014 12:48:37 +0000 (12:48 +0000)
committerNAKAMURA Takumi <geek4civic@gmail.com>
Fri, 17 Oct 2014 12:48:37 +0000 (12:48 +0000)
It broke some builders. I guess it'd be reproducible with --vg.

  Failing Tests (3):
      Clang :: CXX/except/except.spec/p1.cpp
      Clang :: SemaTemplate/instantiate-exception-spec-cxx11.cpp
      Clang :: SemaTemplate/instantiate-exception-spec.cpp

llvm-svn: 220038

15 files changed:
clang/include/clang/AST/DataRecursiveASTVisitor.h
clang/include/clang/AST/Expr.h
clang/include/clang/AST/RecursiveASTVisitor.h
clang/include/clang/AST/Type.h
clang/include/clang/Sema/Sema.h
clang/lib/AST/Type.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Sema/SemaExceptionSpec.cpp
clang/lib/Sema/SemaTemplateInstantiate.cpp
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/lib/Sema/SemaType.cpp
clang/lib/Sema/TreeTransform.h
clang/test/CXX/except/except.spec/p1.cpp
clang/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
clang/test/SemaTemplate/instantiate-exception-spec.cpp

index f7c811e..6d9ac94 100644 (file)
@@ -878,9 +878,6 @@ DEF_TRAVERSE_TYPE(FunctionProtoType, {
   for (const auto &E : T->exceptions()) {
     TRY_TO(TraverseType(E));
   }
-
-  if (Expr *NE = T->getNoexceptExpr())
-    TRY_TO(TraverseStmt(NE));
 })
 
 DEF_TRAVERSE_TYPE(UnresolvedUsingType, {})
@@ -1089,9 +1086,6 @@ DEF_TRAVERSE_TYPELOC(FunctionProtoType, {
   for (const auto &E : T->exceptions()) {
     TRY_TO(TraverseType(E));
   }
-
-  if (Expr *NE = T->getNoexceptExpr())
-    TRY_TO(TraverseStmt(NE));
 })
 
 DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {})
@@ -2131,29 +2125,21 @@ bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
     TRY_TO(TraverseLambdaCapture(S, C));
   }
 
-  TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
-  FunctionProtoTypeLoc Proto = TL.castAs<FunctionProtoTypeLoc>();
-
-  if (S->hasExplicitParameters() && S->hasExplicitResultType()) {
-    // Visit the whole type.
-    TRY_TO(TraverseTypeLoc(TL));
-  } else {
-    if (S->hasExplicitParameters()) {
-      // Visit parameters.
-      for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) {
-        TRY_TO(TraverseDecl(Proto.getParam(I)));
+  if (S->hasExplicitParameters() || S->hasExplicitResultType()) {
+    TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
+    if (S->hasExplicitParameters() && S->hasExplicitResultType()) {
+      // Visit the whole type.
+      TRY_TO(TraverseTypeLoc(TL));
+    } else if (FunctionProtoTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) {
+      if (S->hasExplicitParameters()) {
+        // Visit parameters.
+        for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) {
+          TRY_TO(TraverseDecl(Proto.getParam(I)));
+        }
+      } else {
+        TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));
       }
-    } else if (S->hasExplicitResultType()) {
-      TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));
     }
-
-    auto *T = Proto.getTypePtr();
-    for (const auto &E : T->exceptions()) {
-      TRY_TO(TraverseType(E));
-    }
-
-    if (Expr *NE = T->getNoexceptExpr())
-      TRY_TO(TraverseStmt(NE));
   }
 
   TRY_TO(TraverseLambdaBody(S));
index afe4b0c..2b2adc8 100644 (file)
@@ -2678,23 +2678,20 @@ private:
   }
 
 protected:
-  CastExpr(StmtClass SC, QualType ty, ExprValueKind VK, const CastKind kind,
-           Expr *op, unsigned BasePathSize)
-      : Expr(SC, ty, VK, OK_Ordinary,
-             // Cast expressions are type-dependent if the type is
-             // dependent (C++ [temp.dep.expr]p3).
-             ty->isDependentType(),
-             // Cast expressions are value-dependent if the type is
-             // dependent or if the subexpression is value-dependent.
-             ty->isDependentType() || (op && op->isValueDependent()),
-             (ty->isInstantiationDependentType() ||
-              (op && op->isInstantiationDependent())),
-             // An implicit cast expression doesn't (lexically) contain an
-             // unexpanded pack, even if its target type does.
-             ((SC != ImplicitCastExprClass &&
-               ty->containsUnexpandedParameterPack()) ||
-              (op && op->containsUnexpandedParameterPack()))),
-        Op(op) {
+  CastExpr(StmtClass SC, QualType ty, ExprValueKind VK,
+           const CastKind kind, Expr *op, unsigned BasePathSize) :
+    Expr(SC, ty, VK, OK_Ordinary,
+         // Cast expressions are type-dependent if the type is
+         // dependent (C++ [temp.dep.expr]p3).
+         ty->isDependentType(),
+         // Cast expressions are value-dependent if the type is
+         // dependent or if the subexpression is value-dependent.
+         ty->isDependentType() || (op && op->isValueDependent()),
+         (ty->isInstantiationDependentType() ||
+          (op && op->isInstantiationDependent())),
+         (ty->containsUnexpandedParameterPack() ||
+          (op && op->containsUnexpandedParameterPack()))),
+    Op(op) {
     assert(kind != CK_Invalid && "creating cast with invalid cast kind");
     CastExprBits.Kind = kind;
     setBasePathSize(BasePathSize);
index 6ae788d..2f26801 100644 (file)
@@ -943,9 +943,6 @@ DEF_TRAVERSE_TYPE(FunctionProtoType, {
   for (const auto &E : T->exceptions()) {
     TRY_TO(TraverseType(E));
   }
-
-  if (Expr *NE = T->getNoexceptExpr())
-    TRY_TO(TraverseStmt(NE));
 })
 
 DEF_TRAVERSE_TYPE(UnresolvedUsingType, {})
@@ -1154,9 +1151,6 @@ DEF_TRAVERSE_TYPELOC(FunctionProtoType, {
   for (const auto &E : T->exceptions()) {
     TRY_TO(TraverseType(E));
   }
-
-  if (Expr *NE = T->getNoexceptExpr())
-    TRY_TO(TraverseStmt(NE));
 })
 
 DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {})
@@ -2153,29 +2147,21 @@ bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
     TRY_TO(TraverseLambdaCapture(S, C));
   }
 
-  TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
-  FunctionProtoTypeLoc Proto = TL.castAs<FunctionProtoTypeLoc>();
-
-  if (S->hasExplicitParameters() && S->hasExplicitResultType()) {
-    // Visit the whole type.
-    TRY_TO(TraverseTypeLoc(TL));
-  } else {
-    if (S->hasExplicitParameters()) {
-      // Visit parameters.
-      for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) {
-        TRY_TO(TraverseDecl(Proto.getParam(I)));
+  if (S->hasExplicitParameters() || S->hasExplicitResultType()) {
+    TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
+    if (S->hasExplicitParameters() && S->hasExplicitResultType()) {
+      // Visit the whole type.
+      TRY_TO(TraverseTypeLoc(TL));
+    } else if (FunctionProtoTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) {
+      if (S->hasExplicitParameters()) {
+        // Visit parameters.
+        for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) {
+          TRY_TO(TraverseDecl(Proto.getParam(I)));
+        }
+      } else {
+        TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));
       }
-    } else if (S->hasExplicitResultType()) {
-      TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));
-    }
-
-    auto *T = Proto.getTypePtr();
-    for (const auto &E : T->exceptions()) {
-      TRY_TO(TraverseType(E));
     }
-
-    if (Expr *NE = T->getNoexceptExpr())
-      TRY_TO(TraverseStmt(NE));
   }
 
   TRY_TO(TraverseLambdaBody(S));
index 2a6ac2d..1391586 100644 (file)
@@ -3012,8 +3012,6 @@ public:
   bool hasNoexceptExceptionSpec() const {
     return isNoexceptExceptionSpec(getExceptionSpecType());
   }
-  /// \brief Return whether this function has a dependent exception spec.
-  bool hasDependentExceptionSpec() const;
   /// \brief Result type of getNoexceptSpec().
   enum NoexceptResult {
     NR_NoNoexcept,  ///< There is no noexcept specifier.
@@ -5249,8 +5247,8 @@ template <typename T> const T *Type::castAs() const {
   ArrayType_cannot_be_used_with_getAs<T> at;
   (void) at;
 
-  if (const T *ty = dyn_cast<T>(this)) return ty;
   assert(isa<T>(CanonicalType));
+  if (const T *ty = dyn_cast<T>(this)) return ty;
   return cast<T>(getUnqualifiedDesugaredType());
 }
 
index 7c8535c..3723654 100644 (file)
@@ -4036,8 +4036,7 @@ public:
 
   /// \brief Check the given exception-specification and update the
   /// exception specification information with the results.
-  void checkExceptionSpecification(bool IsTopLevel,
-                                   ExceptionSpecificationType EST,
+  void checkExceptionSpecification(ExceptionSpecificationType EST,
                                    ArrayRef<ParsedType> DynamicExceptions,
                                    ArrayRef<SourceRange> DynamicExceptionRanges,
                                    Expr *NoexceptExpr,
@@ -6676,8 +6675,6 @@ public:
                                         DeclarationName Entity,
                                         CXXRecordDecl *ThisContext,
                                         unsigned ThisTypeQuals);
-  void SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,
-                          const MultiLevelTemplateArgumentList &Args);
   ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D,
                             const MultiLevelTemplateArgumentList &TemplateArgs,
                                 int indexAdjustment,
index 726db92..3c5e80e 100644 (file)
@@ -1624,9 +1624,9 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
     QualType *exnSlot = argSlot + NumParams;
     unsigned I = 0;
     for (QualType ExceptionType : epi.ExceptionSpec.Exceptions) {
-      // Note that a dependent exception specification does *not* make
-      // a type dependent; it's not even part of the C++ type system.
-      if (ExceptionType->isInstantiationDependentType())
+      if (ExceptionType->isDependentType())
+        setDependent();
+      else if (ExceptionType->isInstantiationDependentType())
         setInstantiationDependent();
 
       if (ExceptionType->containsUnexpandedParameterPack())
@@ -1640,12 +1640,11 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
     *noexSlot = epi.ExceptionSpec.NoexceptExpr;
 
     if (epi.ExceptionSpec.NoexceptExpr) {
-      if (epi.ExceptionSpec.NoexceptExpr->isValueDependent() ||
-          epi.ExceptionSpec.NoexceptExpr->isInstantiationDependent())
+      if (epi.ExceptionSpec.NoexceptExpr->isValueDependent() 
+          || epi.ExceptionSpec.NoexceptExpr->isTypeDependent())
+        setDependent();
+      else if (epi.ExceptionSpec.NoexceptExpr->isInstantiationDependent())
         setInstantiationDependent();
-
-      if (epi.ExceptionSpec.NoexceptExpr->containsUnexpandedParameterPack())
-        setContainsUnexpandedParameterPack();
     }
   } else if (getExceptionSpecType() == EST_Uninstantiated) {
     // Store the function decl from which we will resolve our
@@ -1671,18 +1670,6 @@ FunctionProtoType::FunctionProtoType(QualType result, ArrayRef<QualType> params,
   }
 }
 
-bool FunctionProtoType::hasDependentExceptionSpec() const {
-  if (Expr *NE = getNoexceptExpr())
-    return NE->isValueDependent();
-  for (QualType ET : exceptions())
-    // A pack expansion with a non-dependent pattern is still dependent,
-    // because we don't know whether the pattern is in the exception spec
-    // or not (that depends on whether the pack has 0 expansions).
-    if (ET->isDependentType() || ET->getAs<PackExpansionType>())
-      return true;
-  return false;
-}
-
 FunctionProtoType::NoexceptResult
 FunctionProtoType::getNoexceptSpec(const ASTContext &ctx) const {
   ExceptionSpecificationType est = getExceptionSpecType();
index d1f337f..ed15012 100644 (file)
@@ -13168,12 +13168,13 @@ bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) {
   return false;
 }
 
-void Sema::checkExceptionSpecification(
-    bool IsTopLevel, ExceptionSpecificationType EST,
-    ArrayRef<ParsedType> DynamicExceptions,
-    ArrayRef<SourceRange> DynamicExceptionRanges, Expr *NoexceptExpr,
-    SmallVectorImpl<QualType> &Exceptions,
-    FunctionProtoType::ExceptionSpecInfo &ESI) {
+void
+Sema::checkExceptionSpecification(ExceptionSpecificationType EST,
+                                  ArrayRef<ParsedType> DynamicExceptions,
+                                  ArrayRef<SourceRange> DynamicExceptionRanges,
+                                  Expr *NoexceptExpr,
+                                  SmallVectorImpl<QualType> &Exceptions,
+                                  FunctionProtoType::ExceptionSpecInfo &ESI) {
   Exceptions.clear();
   ESI.Type = EST;
   if (EST == EST_Dynamic) {
@@ -13182,15 +13183,13 @@ void Sema::checkExceptionSpecification(
       // FIXME: Preserve type source info.
       QualType ET = GetTypeFromParser(DynamicExceptions[ei]);
 
-      if (IsTopLevel) {
-        SmallVector<UnexpandedParameterPack, 2> Unexpanded;
-        collectUnexpandedParameterPacks(ET, Unexpanded);
-        if (!Unexpanded.empty()) {
-          DiagnoseUnexpandedParameterPacks(
-              DynamicExceptionRanges[ei].getBegin(), UPPC_ExceptionType,
-              Unexpanded);
-          continue;
-        }
+      SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+      collectUnexpandedParameterPacks(ET, Unexpanded);
+      if (!Unexpanded.empty()) {
+        DiagnoseUnexpandedParameterPacks(DynamicExceptionRanges[ei].getBegin(),
+                                         UPPC_ExceptionType,
+                                         Unexpanded);
+        continue;
       }
 
       // Check that the type is valid for an exception spec, and
@@ -13209,8 +13208,7 @@ void Sema::checkExceptionSpecification(
               NoexceptExpr->getType()->getCanonicalTypeUnqualified() ==
               Context.BoolTy) &&
              "Parser should have made sure that the expression is boolean");
-      if (IsTopLevel && NoexceptExpr &&
-          DiagnoseUnexpandedParameterPack(NoexceptExpr)) {
+      if (NoexceptExpr && DiagnoseUnexpandedParameterPack(NoexceptExpr)) {
         ESI.Type = EST_BasicNoexcept;
         return;
       }
index 4e4de5a..e4963b1 100644 (file)
@@ -720,11 +720,10 @@ static bool CheckSpecForTypesEquivalent(Sema &S,
 /// assignment and override compatibility check. We do not check the parameters
 /// of parameter function pointers recursively, as no sane programmer would
 /// even be able to write such a function type.
-bool Sema::CheckParamExceptionSpec(const PartialDiagnostic &NoteID,
-                                   const FunctionProtoType *Target,
-                                   SourceLocation TargetLoc,
-                                   const FunctionProtoType *Source,
-                                   SourceLocation SourceLoc) {
+bool Sema::CheckParamExceptionSpec(const PartialDiagnostic & NoteID,
+    const FunctionProtoType *Target, SourceLocation TargetLoc,
+    const FunctionProtoType *Source, SourceLocation SourceLoc)
+{
   if (CheckSpecForTypesEquivalent(
           *this, PDiag(diag::err_deep_exception_specs_differ) << 0, PDiag(),
           Target->getReturnType(), TargetLoc, Source->getReturnType(),
@@ -745,30 +744,23 @@ bool Sema::CheckParamExceptionSpec(const PartialDiagnostic &NoteID,
   return false;
 }
 
-bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) {
+bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType)
+{
   // First we check for applicability.
   // Target type must be a function, function pointer or function reference.
   const FunctionProtoType *ToFunc = GetUnderlyingFunction(ToType);
-  if (!ToFunc || ToFunc->hasDependentExceptionSpec())
+  if (!ToFunc)
     return false;
 
   // SourceType must be a function or function pointer.
   const FunctionProtoType *FromFunc = GetUnderlyingFunction(From->getType());
-  if (!FromFunc || FromFunc->hasDependentExceptionSpec())
+  if (!FromFunc)
     return false;
 
   // Now we've got the correct types on both sides, check their compatibility.
   // This means that the source of the conversion can only throw a subset of
   // the exceptions of the target, and any exception specs on arguments or
   // return types must be equivalent.
-  //
-  // FIXME: If there is a nested dependent exception specification, we should
-  // not be checking it here. This is fine:
-  //   template<typename T> void f() {
-  //     void (*p)(void (*) throw(T));
-  //     void (*q)(void (*) throw(int)) = p;
-  //   }
-  // ... because it might be instantiated with T=int.
   return CheckExceptionSpecSubset(PDiag(diag::err_incompatible_exception_specs),
                                   PDiag(), ToFunc, 
                                   From->getSourceRange().getBegin(),
index a9aae00..9c1ffb0 100644 (file)
@@ -791,17 +791,11 @@ namespace {
     ExprResult TransformFunctionParmPackExpr(FunctionParmPackExpr *E);
 
     QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
-                                        FunctionProtoTypeLoc TL) {
-      // Call the base version; it will forward to our overridden version below.
-      return inherited::TransformFunctionProtoType(TLB, TL);
-    }
-
-    template<typename Fn>
+                                        FunctionProtoTypeLoc TL);
     QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
                                         FunctionProtoTypeLoc TL,
                                         CXXRecordDecl *ThisContext,
-                                        unsigned ThisTypeQuals,
-                                        Fn TransformExceptionSpec);
+                                        unsigned ThisTypeQuals);
 
     ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
                                             int indexAdjustment,
@@ -1333,16 +1327,21 @@ ExprResult TemplateInstantiator::TransformCXXDefaultArgExpr(
                                         E->getParam());
 }
 
-template<typename Fn>
+QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
+                                                      FunctionProtoTypeLoc TL) {
+  // We need a local instantiation scope for this function prototype.
+  LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
+  return inherited::TransformFunctionProtoType(TLB, TL);
+}
+
 QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
                                  FunctionProtoTypeLoc TL,
                                  CXXRecordDecl *ThisContext,
-                                 unsigned ThisTypeQuals,
-                                 Fn TransformExceptionSpec) {
+                                 unsigned ThisTypeQuals) {
   // We need a local instantiation scope for this function prototype.
   LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
-  return inherited::TransformFunctionProtoType(
-      TLB, TL, ThisContext, ThisTypeQuals, TransformExceptionSpec);
+  return inherited::TransformFunctionProtoType(TLB, TL, ThisContext, 
+                                               ThisTypeQuals);  
 }
 
 ParmVarDecl *
@@ -1577,8 +1576,7 @@ static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) {
 
 /// A form of SubstType intended specifically for instantiating the
 /// type of a FunctionDecl.  Its purpose is solely to force the
-/// instantiation of default-argument expressions and to avoid
-/// instantiating an exception-specification.
+/// instantiation of default-argument expressions.
 TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
                                 const MultiLevelTemplateArgumentList &Args,
                                 SourceLocation Loc,
@@ -1601,17 +1599,9 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
 
   QualType Result;
 
-  if (FunctionProtoTypeLoc Proto =
-          TL.IgnoreParens().getAs<FunctionProtoTypeLoc>()) {
-    // Instantiate the type, other than its exception specification. The
-    // exception specification is instantiated in InitFunctionInstantiation
-    // once we've built the FunctionDecl.
-    // FIXME: Set the exception specification to EST_Uninstantiated here,
-    // instead of rebuilding the function type again later.
-    Result = Instantiator.TransformFunctionProtoType(
-        TLB, Proto, ThisContext, ThisTypeQuals,
-        [](FunctionProtoType::ExceptionSpecInfo &ESI,
-           bool &Changed) { return false; });
+  if (FunctionProtoTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) {
+    Result = Instantiator.TransformFunctionProtoType(TLB, Proto, ThisContext,
+                                                     ThisTypeQuals);
   } else {
     Result = Instantiator.TransformType(TLB, TL);
   }
@@ -1621,26 +1611,6 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
   return TLB.getTypeSourceInfo(Context, Result);
 }
 
-void Sema::SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,
-                              const MultiLevelTemplateArgumentList &Args) {
-  FunctionProtoType::ExceptionSpecInfo ESI =
-      Proto->getExtProtoInfo().ExceptionSpec;
-  assert(ESI.Type != EST_Uninstantiated);
-
-  TemplateInstantiator Instantiator(*this, Args, New->getLocation(),
-                                    New->getDeclName());
-
-  SmallVector<QualType, 4> ExceptionStorage;
-  bool Changed = false;
-  if (Instantiator.TransformExceptionSpec(
-          New->getTypeSourceInfo()->getTypeLoc().getLocEnd(), ESI,
-          ExceptionStorage, Changed))
-    // On error, recover by dropping the exception specification.
-    ESI.Type = EST_None;
-
-  UpdateExceptionSpec(New, ESI);
-}
-
 ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, 
                             const MultiLevelTemplateArgumentList &TemplateArgs,
                                     int indexAdjustment,
index cc2460c..ec8c08d 100644 (file)
@@ -3056,7 +3056,7 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
 /// Introduce the instantiated function parameters into the local
 /// instantiation scope, and set the parameter names to those used
 /// in the template.
-static bool addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,
+static void addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,
                                              const FunctionDecl *PatternDecl,
                                              LocalInstantiationScope &Scope,
                            const MultiLevelTemplateArgumentList &TemplateArgs) {
@@ -3067,22 +3067,15 @@ static bool addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,
       // Simple case: not a parameter pack.
       assert(FParamIdx < Function->getNumParams());
       ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
-      FunctionParam->setDeclName(PatternParam->getDeclName());
       // If the parameter's type is not dependent, update it to match the type
       // in the pattern. They can differ in top-level cv-qualifiers, and we want
       // the pattern's type here. If the type is dependent, they can't differ,
-      // per core issue 1668. Substitute into the type from the pattern, in case
-      // it's instantiation-dependent.
+      // per core issue 1668.
       // FIXME: Updating the type to work around this is at best fragile.
-      if (!PatternDecl->getType()->isDependentType()) {
-        QualType T = S.SubstType(PatternParam->getType(), TemplateArgs,
-                                 FunctionParam->getLocation(),
-                                 FunctionParam->getDeclName());
-        if (T.isNull())
-          return true;
-        FunctionParam->setType(T);
-      }
+      if (!PatternDecl->getType()->isDependentType())
+        FunctionParam->setType(PatternParam->getType());
 
+      FunctionParam->setDeclName(PatternParam->getDeclName());
       Scope.InstantiatedLocal(PatternParam, FunctionParam);
       ++FParamIdx;
       continue;
@@ -3094,27 +3087,136 @@ static bool addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,
       = S.getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs);
     assert(NumArgumentsInExpansion &&
            "should only be called when all template arguments are known");
-    QualType PatternType =
-        PatternParam->getType()->castAs<PackExpansionType>()->getPattern();
     for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) {
       ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
+      if (!PatternDecl->getType()->isDependentType())
+        FunctionParam->setType(PatternParam->getType());
+
       FunctionParam->setDeclName(PatternParam->getDeclName());
-      if (!PatternDecl->getType()->isDependentType()) {
-        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, Arg);
-        QualType T = S.SubstType(PatternType, TemplateArgs,
-                                 FunctionParam->getLocation(),
-                                 FunctionParam->getDeclName());
+      Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
+      ++FParamIdx;
+    }
+  }
+}
+
+static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New,
+                                     const FunctionProtoType *Proto,
+                           const MultiLevelTemplateArgumentList &TemplateArgs) {
+  assert(Proto->getExceptionSpecType() != EST_Uninstantiated);
+
+  // C++11 [expr.prim.general]p3:
+  //   If a declaration declares a member function or member function 
+  //   template of a class X, the expression this is a prvalue of type 
+  //   "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
+  //   and the end of the function-definition, member-declarator, or 
+  //   declarator.    
+  CXXRecordDecl *ThisContext = nullptr;
+  unsigned ThisTypeQuals = 0;
+  if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(New)) {
+    ThisContext = Method->getParent();
+    ThisTypeQuals = Method->getTypeQualifiers();
+  }
+  Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, ThisTypeQuals,
+                                   SemaRef.getLangOpts().CPlusPlus11);
+
+  // The function has an exception specification or a "noreturn"
+  // attribute. Substitute into each of the exception types.
+  SmallVector<QualType, 4> Exceptions;
+  for (unsigned I = 0, N = Proto->getNumExceptions(); I != N; ++I) {
+    // FIXME: Poor location information!
+    if (const PackExpansionType *PackExpansion
+          = Proto->getExceptionType(I)->getAs<PackExpansionType>()) {
+      // We have a pack expansion. Instantiate it.
+      SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+      SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(),
+                                              Unexpanded);
+      assert(!Unexpanded.empty() &&
+             "Pack expansion without parameter packs?");
+
+      bool Expand = false;
+      bool RetainExpansion = false;
+      Optional<unsigned> NumExpansions = PackExpansion->getNumExpansions();
+      if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(),
+                                                  SourceRange(),
+                                                  Unexpanded,
+                                                  TemplateArgs,
+                                                  Expand,
+                                                  RetainExpansion,
+                                                  NumExpansions))
+        break;
+
+      if (!Expand) {
+        // We can't expand this pack expansion into separate arguments yet;
+        // just substitute into the pattern and create a new pack expansion
+        // type.
+        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);
+        QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
+                                       TemplateArgs,
+                                     New->getLocation(), New->getDeclName());
         if (T.isNull())
-          return true;
-        FunctionParam->setType(T);
+          break;
+
+        T = SemaRef.Context.getPackExpansionType(T, NumExpansions);
+        Exceptions.push_back(T);
+        continue;
       }
 
-      Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
-      ++FParamIdx;
+      // Substitute into the pack expansion pattern for each template
+      bool Invalid = false;
+      for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) {
+        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, ArgIdx);
+
+        QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
+                                       TemplateArgs,
+                                     New->getLocation(), New->getDeclName());
+        if (T.isNull()) {
+          Invalid = true;
+          break;
+        }
+
+        Exceptions.push_back(T);
+      }
+
+      if (Invalid)
+        break;
+
+      continue;
+    }
+
+    QualType T
+      = SemaRef.SubstType(Proto->getExceptionType(I), TemplateArgs,
+                          New->getLocation(), New->getDeclName());
+    if (T.isNull() ||
+        SemaRef.CheckSpecifiedExceptionType(T, New->getLocation()))
+      continue;
+
+    Exceptions.push_back(T);
+  }
+  Expr *NoexceptExpr = nullptr;
+  if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) {
+    EnterExpressionEvaluationContext Unevaluated(SemaRef,
+                                                 Sema::ConstantEvaluated);
+    ExprResult E = SemaRef.SubstExpr(OldNoexceptExpr, TemplateArgs);
+    if (E.isUsable())
+      E = SemaRef.CheckBooleanCondition(E.get(), E.get()->getLocStart());
+
+    if (E.isUsable()) {
+      NoexceptExpr = E.get();
+      if (!NoexceptExpr->isTypeDependent() &&
+          !NoexceptExpr->isValueDependent())
+        NoexceptExpr
+          = SemaRef.VerifyIntegerConstantExpression(NoexceptExpr,
+              nullptr, diag::err_noexcept_needs_constant_expression,
+              /*AllowFold*/ false).get();
     }
   }
 
-  return false;
+  FunctionProtoType::ExceptionSpecInfo ESI;
+  ESI.Type = Proto->getExceptionSpecType();
+  ESI.Exceptions = Exceptions;
+  ESI.NoexceptExpr = NoexceptExpr;
+
+  SemaRef.UpdateExceptionSpec(New, ESI);
 }
 
 void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
@@ -3141,14 +3243,11 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
     getTemplateInstantiationArgs(Decl, nullptr, /*RelativeToPrimary*/true);
 
   FunctionDecl *Template = Proto->getExceptionSpecTemplate();
-  if (addInstantiatedParametersToScope(*this, Decl, Template, Scope,
-                                       TemplateArgs)) {
-    UpdateExceptionSpec(Decl, EST_None);
-    return;
-  }
+  addInstantiatedParametersToScope(*this, Decl, Template, Scope, TemplateArgs);
 
-  SubstExceptionSpec(Decl, Template->getType()->castAs<FunctionProtoType>(),
-                     TemplateArgs);
+  ::InstantiateExceptionSpec(*this, Decl,
+                             Template->getType()->castAs<FunctionProtoType>(),
+                             TemplateArgs);
 }
 
 /// \brief Initializes the common fields of an instantiation function
@@ -3217,7 +3316,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
       New->setType(SemaRef.Context.getFunctionType(
           NewProto->getReturnType(), NewProto->getParamTypes(), EPI));
     } else {
-      SemaRef.SubstExceptionSpec(New, Proto, TemplateArgs);
+      ::InstantiateExceptionSpec(SemaRef, New, Proto, TemplateArgs);
     }
   }
 
@@ -3407,9 +3506,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
     MultiLevelTemplateArgumentList TemplateArgs =
       getTemplateInstantiationArgs(Function, nullptr, false, PatternDecl);
 
-    if (addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope,
-                                         TemplateArgs))
-      return;
+    addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope,
+                                     TemplateArgs);
 
     // If this is a constructor, instantiate the member initializers.
     if (const CXXConstructorDecl *Ctor =
index f395e10..3ce9489 100644 (file)
@@ -2989,8 +2989,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
           NoexceptExpr = FTI.NoexceptExpr;
         }
 
-        S.checkExceptionSpecification(D.isFunctionDeclarationContext(),
-                                      FTI.getExceptionSpecType(),
+        S.checkExceptionSpecification(FTI.getExceptionSpecType(),
                                       DynamicExceptions,
                                       DynamicExceptionRanges,
                                       NoexceptExpr,
index 75783f2..28890f5 100644 (file)
@@ -563,17 +563,10 @@ public:
   QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T);
 #include "clang/AST/TypeLocNodes.def"
 
-  template<typename Fn>
   QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
                                       FunctionProtoTypeLoc TL,
                                       CXXRecordDecl *ThisContext,
-                                      unsigned ThisTypeQuals,
-                                      Fn TransformExceptionSpec);
-
-  bool TransformExceptionSpec(SourceLocation Loc,
-                              FunctionProtoType::ExceptionSpecInfo &ESI,
-                              SmallVectorImpl<QualType> &Exceptions,
-                              bool &Changed);
+                                      unsigned ThisTypeQuals);
 
   StmtResult TransformSEHHandler(Stmt *Handler);
 
@@ -4557,19 +4550,15 @@ template<typename Derived>
 QualType
 TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
                                                    FunctionProtoTypeLoc TL) {
-  SmallVector<QualType, 4> ExceptionStorage;
-  return getDerived().TransformFunctionProtoType(
-      TLB, TL, nullptr, 0,
-      [&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {
-        return TransformExceptionSpec(TL.getBeginLoc(), ESI, ExceptionStorage,
-                                      Changed);
-      });
-}
-
-template<typename Derived> template<typename Fn>
-QualType TreeTransform<Derived>::TransformFunctionProtoType(
-    TypeLocBuilder &TLB, FunctionProtoTypeLoc TL, CXXRecordDecl *ThisContext,
-    unsigned ThisTypeQuals, Fn TransformExceptionSpec) {
+  return getDerived().TransformFunctionProtoType(TLB, TL, nullptr, 0);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
+                                                   FunctionProtoTypeLoc TL,
+                                                   CXXRecordDecl *ThisContext,
+                                                   unsigned ThisTypeQuals) {
   // Transform the parameters and return type.
   //
   // We are required to instantiate the params and return type in source order.
@@ -4614,21 +4603,15 @@ QualType TreeTransform<Derived>::TransformFunctionProtoType(
       return QualType();
   }
 
-  FunctionProtoType::ExtProtoInfo EPI = T->getExtProtoInfo();
-
-  bool EPIChanged = false;
-  if (TransformExceptionSpec(EPI.ExceptionSpec, EPIChanged))
-    return QualType();
-
-  // FIXME: Need to transform ConsumedParameters for variadic template
-  // expansion.
+  // FIXME: Need to transform the exception-specification too.
 
   QualType Result = TL.getType();
   if (getDerived().AlwaysRebuild() || ResultType != T->getReturnType() ||
       T->getNumParams() != ParamTypes.size() ||
       !std::equal(T->param_type_begin(), T->param_type_end(),
-                  ParamTypes.begin()) || EPIChanged) {
-    Result = getDerived().RebuildFunctionProtoType(ResultType, ParamTypes, EPI);
+                  ParamTypes.begin())) {
+    Result = getDerived().RebuildFunctionProtoType(ResultType, ParamTypes,
+                                                   T->getExtProtoInfo());
     if (Result.isNull())
       return QualType();
   }
@@ -4645,107 +4628,6 @@ QualType TreeTransform<Derived>::TransformFunctionProtoType(
 }
 
 template<typename Derived>
-bool TreeTransform<Derived>::TransformExceptionSpec(
-    SourceLocation Loc, FunctionProtoType::ExceptionSpecInfo &ESI,
-    SmallVectorImpl<QualType> &Exceptions, bool &Changed) {
-  assert(ESI.Type != EST_Uninstantiated && ESI.Type != EST_Unevaluated);
-
-  // Instantiate a dynamic noexcept expression, if any.
-  if (ESI.Type == EST_ComputedNoexcept) {
-    EnterExpressionEvaluationContext Unevaluated(getSema(),
-                                                 Sema::ConstantEvaluated);
-    ExprResult NoexceptExpr = getDerived().TransformExpr(ESI.NoexceptExpr);
-    if (NoexceptExpr.isInvalid())
-      return true;
-
-    NoexceptExpr = getSema().CheckBooleanCondition(
-        NoexceptExpr.get(), NoexceptExpr.get()->getLocStart());
-    if (NoexceptExpr.isInvalid())
-      return true;
-
-    if (!NoexceptExpr.get()->isValueDependent()) {
-      NoexceptExpr = getSema().VerifyIntegerConstantExpression(
-          NoexceptExpr.get(), nullptr,
-          diag::err_noexcept_needs_constant_expression,
-          /*AllowFold*/false);
-      if (NoexceptExpr.isInvalid())
-        return true;
-    }
-
-    if (ESI.NoexceptExpr != NoexceptExpr.get())
-      Changed = true;
-    ESI.NoexceptExpr = NoexceptExpr.get();
-  }
-
-  if (ESI.Type != EST_Dynamic)
-    return false;
-
-  // Instantiate a dynamic exception specification's type.
-  for (QualType T : ESI.Exceptions) {
-    if (const PackExpansionType *PackExpansion =
-            T->getAs<PackExpansionType>()) {
-      Changed = true;
-
-      // We have a pack expansion. Instantiate it.
-      SmallVector<UnexpandedParameterPack, 2> Unexpanded;
-      SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(),
-                                              Unexpanded);
-      assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
-
-      // Determine whether the set of unexpanded parameter packs can and
-      // should
-      // be expanded.
-      bool Expand = false;
-      bool RetainExpansion = false;
-      Optional<unsigned> NumExpansions = PackExpansion->getNumExpansions();
-      // FIXME: Track the location of the ellipsis (and track source location
-      // information for the types in the exception specification in general).
-      if (getDerived().TryExpandParameterPacks(
-              Loc, SourceRange(), Unexpanded, Expand,
-              RetainExpansion, NumExpansions))
-        return true;
-
-      if (!Expand) {
-        // We can't expand this pack expansion into separate arguments yet;
-        // just substitute into the pattern and create a new pack expansion
-        // type.
-        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
-        QualType U = getDerived().TransformType(PackExpansion->getPattern());
-        if (U.isNull())
-          return true;
-
-        U = SemaRef.Context.getPackExpansionType(U, NumExpansions);
-        Exceptions.push_back(U);
-        continue;
-      }
-
-      // Substitute into the pack expansion pattern for each slice of the
-      // pack.
-      for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) {
-        Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), ArgIdx);
-
-        QualType U = getDerived().TransformType(PackExpansion->getPattern());
-        if (U.isNull() || SemaRef.CheckSpecifiedExceptionType(U, Loc))
-          return true;
-
-        Exceptions.push_back(U);
-      }
-    } else {
-      QualType U = getDerived().TransformType(T);
-      if (U.isNull() || SemaRef.CheckSpecifiedExceptionType(U, Loc))
-        return true;
-      if (T != U)
-        Changed = true;
-
-      Exceptions.push_back(U);
-    }
-  }
-
-  ESI.Exceptions = Exceptions;
-  return false;
-}
-
-template<typename Derived>
 QualType TreeTransform<Derived>::TransformFunctionNoProtoType(
                                                  TypeLocBuilder &TLB,
                                                  FunctionNoProtoTypeLoc TL) {
@@ -9123,13 +9005,9 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
     // transformed parameters.
 
     TypeLocBuilder NewCallOpTLBuilder;
-    SmallVector<QualType, 4> ExceptionStorage;
-    QualType NewCallOpType = TransformFunctionProtoType(
-        NewCallOpTLBuilder, OldCallOpFPTL, nullptr, 0,
-        [&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {
-          return TransformExceptionSpec(OldCallOpFPTL.getBeginLoc(), ESI,
-                                        ExceptionStorage, Changed);
-        });
+    QualType NewCallOpType = TransformFunctionProtoType(NewCallOpTLBuilder, 
+                                                        OldCallOpFPTL, 
+                                                        nullptr, 0);
     NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context,
                                                         NewCallOpType);
   }
index fa53c9f..a32f37d 100644 (file)
@@ -77,12 +77,5 @@ namespace PR11084 {
     static int f() noexcept(1/X) { return 10; }  // expected-error{{argument to noexcept specifier must be a constant expression}} expected-note{{division by zero}}
   };
 
-  template<int X> void f() {
-    int (*p)() noexcept(1/X); // expected-error{{argument to noexcept specifier must be a constant expression}} expected-note{{division by zero}}
-  };
-
-  void g() {
-    A<0>::f(); // expected-note{{in instantiation of exception specification for 'f'}}
-    f<0>(); // expected-note{{in instantiation of function template specialization}}
-  }
+  void g() { A<0>::f(); } // expected-note{{in instantiation of exception specification for 'f' requested here}}
 }
index f62ef61..a376f0e 100644 (file)
@@ -58,13 +58,6 @@ namespace dr1330_example {
     S().f<S>(); // ok
     S().f<int>(); // expected-note {{instantiation of exception spec}}
   }
-
-  template<typename T>
-  struct U {
-    void f() noexcept(T::error);
-    void (g)() noexcept(T::error);
-  };
-  U<int> uint; // ok
 }
 
 namespace core_19754_example {
@@ -144,37 +137,3 @@ namespace PR12763 {
   };
   void X::g() {} // expected-note {{in instantiation of}}
 }
-
-namespace Variadic {
-  template<bool B> void check() { static_assert(B, ""); }
-  template<bool B, bool B2, bool ...Bs> void check() { static_assert(B, ""); check<B2, Bs...>(); }
-
-  template<typename ...T> void consume(T...);
-
-  template<typename ...T> void f(void (*...p)() throw (T)) {
-    void (*q[])() = { p... };
-    consume((p(),0)...);
-  }
-  template<bool ...B> void g(void (*...p)() noexcept (B)) {
-    consume((p(),0)...);
-    check<noexcept(p()) == B ...>();
-  }
-  template<typename ...T> void i() {
-    consume([]() throw(T) {} ...);
-    consume([]() noexcept(sizeof(T) == 4) {} ...);
-  }
-  template<bool ...B> void j() {
-    consume([](void (*p)() noexcept(B)) {
-      void (*q)() noexcept = p; // expected-error {{not superset of source}}
-    } ...);
-  }
-
-  void z() {
-    f<int, char, double>(nullptr, nullptr, nullptr);
-    g<true, false, true>(nullptr, nullptr, nullptr);
-    i<int, long, short>();
-    j<true, true>();
-    j<true, false>(); // expected-note {{in instantiation of}}
-  }
-
-}
index d341172..993ee8d 100644 (file)
@@ -1,7 +1,5 @@
-// RUN: %clang_cc1 -fexceptions -fcxx-exceptions -verify %s -DERRORS
-// RUN: %clang_cc1 -fexceptions -fcxx-exceptions -emit-llvm-only %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s
 
-#ifdef ERRORS
 template<typename T> void f1(T*) throw(T); // expected-error{{incomplete type 'Incomplete' is not allowed in exception specification}}
 struct Incomplete; // expected-note{{forward}}
 
@@ -9,20 +7,3 @@ void test_f1(Incomplete *incomplete_p, int *int_p) {
   f1(int_p);
   f1(incomplete_p); // expected-note{{instantiation of}}
 }
-#endif
-
-template<typename T> void f(void (*p)() throw(T)) {
-#ifdef ERRORS
-  void (*q)() throw(char) = p; // expected-error {{target exception spec}}
-
-  extern void (*p2)() throw(T);
-  void (*q2)() throw(char) = p2; // expected-error {{target exception spec}}
-
-  extern void (*p3)() throw(char);
-  void (*q3)() throw(T) = p3; // expected-error {{target exception spec}}
-
-  void (*q4)() throw(T) = p2; // ok
-#endif
-  p();
-}
-void g() { f<int>(0); } // expected-note {{instantiation of}}