]> granicus.if.org Git - clang/commitdiff
Make ParentMap work with explicit specializations of function templates.
authorNico Weber <nicolasweber@gmx.de>
Mon, 8 Feb 2016 22:23:09 +0000 (22:23 +0000)
committerNico Weber <nicolasweber@gmx.de>
Mon, 8 Feb 2016 22:23:09 +0000 (22:23 +0000)
For an explicit specialization, we first build a FunctionDecl, and then
we call SubstDecl() on it to build a second FunctionDecl, which has the
first FunctionDecl as canonical decl.

The address of an explicit specialization of function template used to be the
canonical decl of the FunctionDecl.  This is different from all the other
DeduceTemplateArguments() calls in SemaOverload, and since the canonical decl
isn't visited by ParentMap while the redecl is, it also made ParentMap assert
when computing the parent of a address-of-explicit-specialization-fun-template.

To fix, remove the getCanonicalDecl() call.  No behavior difference for clang,
but it fixes an assert in ParentMap (which is e.g. used by libTooling).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@260159 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaOverload.cpp
unittests/ASTMatchers/ASTMatchersTest.cpp

index eaac06162f73049ea4596f3f6f80e7fa2732cdd6..d71b307d15b7588f0298f48895439070d8bd4d50 100644 (file)
@@ -10339,7 +10339,6 @@ private:
     // Template argument deduction ensures that we have an exact match or
     // compatible pointer-to-function arguments that would be adjusted by ICS.
     // This function template specicalization works.
-    Specialization = cast<FunctionDecl>(Specialization->getCanonicalDecl());
     assert(S.isSameOrCompatibleFunctionType(
               Context.getCanonicalType(Specialization->getType()),
               Context.getCanonicalType(TargetFunctionType)));
index 2aaa92c35b8df340dd4b6afd6ad251f85f231ed1..5578e066a22293f7d7d8c02dddce73ff47dd204f 100644 (file)
@@ -4333,6 +4333,13 @@ TEST(HasAncestor, NonParmDependentTemplateParmVarDeclRefExpr) {
                       declRefExpr(to(decl(hasAncestor(decl()))))));
 }
 
+TEST(HasAncestor, AddressOfExplicitSpecializationFunction) {
+  EXPECT_TRUE(matches("template <class T> void f();\n"
+                      "template <> void f<int>();\n"
+                      "void (*get_f())() { return f<int>; }\n",
+                      declRefExpr(to(decl(hasAncestor(decl()))))));
+}
+
 TEST(HasParent, MatchesAllParents) {
   EXPECT_TRUE(matches(
       "template <typename T> struct C { static void f() { 42; } };"