Fix for PR47544. Clang is crashing after generating the right
authorZahira Ammarguellat <zahira.ammarguellat@intel.com>
Tue, 27 Oct 2020 12:51:02 +0000 (05:51 -0700)
committerZahira Ammarguellat <zahira.ammarguellat@intel.com>
Tue, 27 Oct 2020 12:57:39 +0000 (05:57 -0700)
diagnostic for a re-declaration of a friend method.d
https://reviews.llvm.org/D88112

clang/lib/Parse/ParseCXXInlineMethods.cpp
clang/test/SemaCXX/invalid-decl.cpp [new file with mode: 0644]

index d05332b5ac5a70788c28d6856fd4894028e4c759..12941f214cbc6c9c81ad7232a7c88178324541fc 100644 (file)
@@ -405,14 +405,21 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
         ConsumeAnyToken();
     } else if (HasUnparsed) {
       assert(Param->hasInheritedDefaultArg());
-      FunctionDecl *Old = cast<FunctionDecl>(LM.Method)->getPreviousDecl();
-      ParmVarDecl *OldParam = Old->getParamDecl(I);
-      assert (!OldParam->hasUnparsedDefaultArg());
-      if (OldParam->hasUninstantiatedDefaultArg())
-        Param->setUninstantiatedDefaultArg(
-            OldParam->getUninstantiatedDefaultArg());
+      const FunctionDecl *Old;
+      if (const auto *FunTmpl = dyn_cast<FunctionTemplateDecl>(LM.Method))
+        Old =
+            cast<FunctionDecl>(FunTmpl->getTemplatedDecl())->getPreviousDecl();
       else
-        Param->setDefaultArg(OldParam->getInit());
+        Old = cast<FunctionDecl>(LM.Method)->getPreviousDecl();
+      if (Old) {
+        ParmVarDecl *OldParam = const_cast<ParmVarDecl*>(Old->getParamDecl(I));
+        assert(!OldParam->hasUnparsedDefaultArg());
+        if (OldParam->hasUninstantiatedDefaultArg())
+          Param->setUninstantiatedDefaultArg(
+              OldParam->getUninstantiatedDefaultArg());
+        else
+          Param->setDefaultArg(OldParam->getInit());
+      }
     }
   }
 
diff --git a/clang/test/SemaCXX/invalid-decl.cpp b/clang/test/SemaCXX/invalid-decl.cpp
new file mode 100644 (file)
index 0000000..0cb8b00
--- /dev/null
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+class test1 {
+  template <typename> friend int bar(bool = true) {} // expected-note {{previous declaration is here}}
+  template <typename> friend int bar(bool);          // expected-error {{friend declaration specifying a default argument must be the only declaration}}
+};
+
+class test2 {
+  friend int bar(bool = true) {} // expected-note {{previous declaration is here}}
+  friend int bar(bool);          // expected-error{{friend declaration specifying a default argument must be the only declaration}}
+};