[clang] 45538b5 - [Concepts] Fix bug when referencing function parameters in instantiated function template requires clause

Saar Raz via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 22 01:25:37 PST 2020


Author: Saar Raz
Date: 2020-01-22T11:25:27+02:00
New Revision: 45538b5fb280e5b2903f7924fd4fa5b07a6dd3ea

URL: https://github.com/llvm/llvm-project/commit/45538b5fb280e5b2903f7924fd4fa5b07a6dd3ea
DIFF: https://github.com/llvm/llvm-project/commit/45538b5fb280e5b2903f7924fd4fa5b07a6dd3ea.diff

LOG: [Concepts] Fix bug when referencing function parameters in instantiated function template requires clause

Fixes bug #44613 - instantiated parameters were not being added when instantiating the requires clauses.

Added: 
    

Modified: 
    clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
    clang/test/SemaTemplate/instantiate-requires-clause.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index a470cfc87440..bdea54de2414 100755
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1766,6 +1766,70 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
   return Record;
 }
 
+/// 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,
+                                             const FunctionDecl *PatternDecl,
+                                             LocalInstantiationScope &Scope,
+                           const MultiLevelTemplateArgumentList &TemplateArgs) {
+  unsigned FParamIdx = 0;
+  for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) {
+    const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I);
+    if (!PatternParam->isParameterPack()) {
+      // 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 
diff er in top-level cv-qualifiers, and we want
+      // the pattern's type here. If the type is dependent, they can't 
diff er,
+      // per core issue 1668. Substitute into the type from the pattern, in case
+      // it's instantiation-dependent.
+      // 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);
+      }
+
+      Scope.InstantiatedLocal(PatternParam, FunctionParam);
+      ++FParamIdx;
+      continue;
+    }
+
+    // Expand the parameter pack.
+    Scope.MakeInstantiatedLocalArgPack(PatternParam);
+    Optional<unsigned> NumArgumentsInExpansion
+      = S.getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs);
+    if (NumArgumentsInExpansion) {
+      QualType PatternType =
+          PatternParam->getType()->castAs<PackExpansionType>()->getPattern();
+      for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) {
+        ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
+        FunctionParam->setDeclName(PatternParam->getDeclName());
+        if (!PatternDecl->getType()->isDependentType()) {
+          Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, Arg);
+          QualType T = S.SubstType(PatternType, TemplateArgs,
+                                   FunctionParam->getLocation(),
+                                   FunctionParam->getDeclName());
+          if (T.isNull())
+            return true;
+          FunctionParam->setType(T);
+        }
+
+        Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
+        ++FParamIdx;
+      }
+    }
+  }
+
+  return false;
+}
+
 /// Adjust the given function type for an instantiation of the
 /// given declaration, to cope with modifications to the function's type that
 /// aren't reflected in the type-source information.
@@ -1848,6 +1912,11 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
   // FIXME: Concepts: Do not substitute into constraint expressions
   Expr *TrailingRequiresClause = D->getTrailingRequiresClause();
   if (TrailingRequiresClause) {
+    if (D->isTemplateInstantiation() &&
+        addInstantiatedParametersToScope(
+            SemaRef, D, D->getTemplateInstantiationPattern(), Scope,
+            TemplateArgs))
+      return nullptr;
     ExprResult SubstRC = SemaRef.SubstExpr(TrailingRequiresClause,
                                            TemplateArgs);
     if (SubstRC.isInvalid())
@@ -4105,70 +4174,6 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
   return NewTInfo;
 }
 
-/// 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,
-                                             const FunctionDecl *PatternDecl,
-                                             LocalInstantiationScope &Scope,
-                           const MultiLevelTemplateArgumentList &TemplateArgs) {
-  unsigned FParamIdx = 0;
-  for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) {
-    const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I);
-    if (!PatternParam->isParameterPack()) {
-      // 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 
diff er in top-level cv-qualifiers, and we want
-      // the pattern's type here. If the type is dependent, they can't 
diff er,
-      // per core issue 1668. Substitute into the type from the pattern, in case
-      // it's instantiation-dependent.
-      // 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);
-      }
-
-      Scope.InstantiatedLocal(PatternParam, FunctionParam);
-      ++FParamIdx;
-      continue;
-    }
-
-    // Expand the parameter pack.
-    Scope.MakeInstantiatedLocalArgPack(PatternParam);
-    Optional<unsigned> NumArgumentsInExpansion
-      = S.getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs);
-    if (NumArgumentsInExpansion) {
-      QualType PatternType =
-          PatternParam->getType()->castAs<PackExpansionType>()->getPattern();
-      for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) {
-        ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
-        FunctionParam->setDeclName(PatternParam->getDeclName());
-        if (!PatternDecl->getType()->isDependentType()) {
-          Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, Arg);
-          QualType T = S.SubstType(PatternType, TemplateArgs,
-                                   FunctionParam->getLocation(),
-                                   FunctionParam->getDeclName());
-          if (T.isNull())
-            return true;
-          FunctionParam->setType(T);
-        }
-
-        Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
-        ++FParamIdx;
-      }
-    }
-  }
-
-  return false;
-}
-
 void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
                                     FunctionDecl *Decl) {
   const FunctionProtoType *Proto = Decl->getType()->castAs<FunctionProtoType>();

diff  --git a/clang/test/SemaTemplate/instantiate-requires-clause.cpp b/clang/test/SemaTemplate/instantiate-requires-clause.cpp
index f36396b98db7..04b595717e6d 100644
--- a/clang/test/SemaTemplate/instantiate-requires-clause.cpp
+++ b/clang/test/SemaTemplate/instantiate-requires-clause.cpp
@@ -29,3 +29,13 @@ using f31 = decltype(f3('a'));
 using f32 = decltype(f3(1, 'b'));
 using f33 = decltype(f3(1, 'b', 2));
 // expected-error at -1 {{no matching function for call to 'f3'}}
+
+template<typename T>
+struct S {
+	template<typename U>
+	static constexpr auto f(U const index) requires(index, true) {
+		return true;
+	}
+};
+
+static_assert(S<void>::f(1));


        


More information about the cfe-commits mailing list