r335805 - [modules] Ensure that an in-class function definition is attached to the
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 27 18:07:28 PDT 2018
Author: rsmith
Date: Wed Jun 27 18:07:28 2018
New Revision: 335805
URL: http://llvm.org/viewvc/llvm-project?rev=335805&view=rev
Log:
[modules] Ensure that an in-class function definition is attached to the
declaration of the function that ends up in the primary definition of
the class.
... at least for class templates. This is necessary for us to be able to
track when an inline friend function has a definition that needs to be
(lazily) instantiated.
Added:
cfe/trunk/test/Modules/friend-definition-2.cpp
Modified:
cfe/trunk/lib/Serialization/ASTReader.cpp
Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=335805&r1=335804&r2=335805&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Wed Jun 27 18:07:28 2018
@@ -9356,6 +9356,19 @@ void ASTReader::finishPendingActions() {
PBEnd = PendingBodies.end();
PB != PBEnd; ++PB) {
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(PB->first)) {
+ // For a function defined inline within a class template, force the
+ // canonical definition to be the one inside the canonical definition of
+ // the template. This ensures that we instantiate from a correct view
+ // of the template.
+ //
+ // Sadly we can't do this more generally: we can't be sure that all
+ // copies of an arbitrary class definition will have the same members
+ // defined (eg, some member functions may not be instantiated, and some
+ // special members may or may not have been implicitly defined).
+ if (auto *RD = dyn_cast<CXXRecordDecl>(FD->getLexicalParent()))
+ if (RD->isDependentContext() && !RD->isThisDeclarationADefinition())
+ continue;
+
// FIXME: Check for =delete/=default?
// FIXME: Complain about ODR violations here?
const FunctionDecl *Defn = nullptr;
Added: cfe/trunk/test/Modules/friend-definition-2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/friend-definition-2.cpp?rev=335805&view=auto
==============================================================================
--- cfe/trunk/test/Modules/friend-definition-2.cpp (added)
+++ cfe/trunk/test/Modules/friend-definition-2.cpp Wed Jun 27 18:07:28 2018
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -fmodules %s -verify
+// expected-no-diagnostics
+#pragma clang module build A
+module A {}
+#pragma clang module contents
+#pragma clang module begin A
+template<typename T> struct ct { friend auto operator-(ct, ct) { struct X {}; return X(); } void x(); };
+#pragma clang module end
+#pragma clang module endbuild
+
+#pragma clang module build B
+module B {}
+#pragma clang module contents
+#pragma clang module begin B
+template<typename T> struct ct { friend auto operator-(ct, ct) { struct X{}; return X(); } void x(); };
+inline auto f() { return ct<float>() - ct<float>(); }
+#pragma clang module end
+#pragma clang module endbuild
+
+// Force the definition of ct in module A to be the primary definition.
+#pragma clang module import A
+template<typename T> void ct<T>::x() {}
+
+// Attempt to cause the definition of operator- in the ct primary template in
+// module B to be the primary definition of that function. If that happens,
+// we'll be left with a class template ct that appears to not contain a
+// definition of the inline friend function.
+#pragma clang module import B
+auto v = f();
+
+ct<int> make();
+void h() {
+ make() - make();
+}
More information about the cfe-commits
mailing list