r259428 - Always build a new TypeSourceInfo for function templates with parameters

Nico Weber via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 1 14:31:51 PST 2016


Author: nico
Date: Mon Feb  1 16:31:51 2016
New Revision: 259428

URL: http://llvm.org/viewvc/llvm-project?rev=259428&view=rev
Log:
Always build a new TypeSourceInfo for function templates with parameters

RecursiveASTVisitor::TraverseFunctionHelper() traverses a function's
ParmVarDecls by going to the function's getTypeSourceInfo if it exists, and
`DEF_TRAVERSE_TYPELOC(FunctionProtoType` then goes to the function's
ParmVarDecls.

For a function template that doesn't have parameters that explicitly depend on
the template parameter, we used to be clever and not build a new
TypeSourceInfo. That meant that when an instantiation of such a template is
visited, its TypeSourceInfo would point to the ParmVarDecls of the template,
not of the instantiation, which then confused clients of RecursiveASTVisitor.

So don't be clever for function templates that have parameters, even if none of
the parameters depend on the type.

Fixes PR26257.
http://reviews.llvm.org/D16478

Modified:
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=259428&r1=259427&r2=259428&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Mon Feb  1 16:31:51 2016
@@ -1512,7 +1512,7 @@ QualType Sema::SubstType(QualType T,
 }
 
 static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) {
-  if (T->getType()->isInstantiationDependentType() || 
+  if (T->getType()->isInstantiationDependentType() ||
       T->getType()->isVariablyModifiedType())
     return true;
 
@@ -1521,23 +1521,13 @@ static bool NeedsInstantiationAsFunction
     return false;
 
   FunctionProtoTypeLoc FP = TL.castAs<FunctionProtoTypeLoc>();
-  for (unsigned I = 0, E = FP.getNumParams(); I != E; ++I) {
-    ParmVarDecl *P = FP.getParam(I);
-
+  for (ParmVarDecl *P : FP.getParams()) {
     // This must be synthesized from a typedef.
     if (!P) continue;
 
-    // The parameter's type as written might be dependent even if the
-    // decayed type was not dependent.
-    if (TypeSourceInfo *TSInfo = P->getTypeSourceInfo())
-      if (TSInfo->getType()->isInstantiationDependentType())
-        return true;
-
-    // TODO: currently we always rebuild expressions.  When we
-    // properly get lazier about this, we should use the same
-    // logic to avoid rebuilding prototypes here.
-    if (P->hasDefaultArg())
-      return true;
+    // If there are any parameters, a new TypeSourceInfo that refers to the
+    // instantiated parameters must be built.
+    return true;
   }
 
   return false;
@@ -1556,7 +1546,7 @@ TypeSourceInfo *Sema::SubstFunctionDeclT
   assert(!ActiveTemplateInstantiations.empty() &&
          "Cannot perform an instantiation without some context on the "
          "instantiation stack");
-  
+
   if (!NeedsInstantiationAsFunctionType(T))
     return T;
 

Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp?rev=259428&r1=259427&r2=259428&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp Mon Feb  1 16:31:51 2016
@@ -4276,6 +4276,17 @@ TEST(HasAncestor, AnonymousUnionMemberEx
                       declRefExpr(to(decl(hasAncestor(decl()))))));
 }
 
+TEST(HasAncestor, NonParmDependentTemplateParmVarDeclRefExpr) {
+  EXPECT_TRUE(matches("struct PartitionAllocator {\n"
+                      "  template<typename T>\n"
+                      "  static int quantizedSize(int count) {\n"
+                      "    return count;\n"
+                      "  }\n"
+                      "  void f() { quantizedSize<int>(10); }\n"
+                      "};",
+                      declRefExpr(to(decl(hasAncestor(decl()))))));
+}
+
 TEST(HasParent, MatchesAllParents) {
   EXPECT_TRUE(matches(
       "template <typename T> struct C { static void f() { 42; } };"




More information about the cfe-commits mailing list