[PATCH] D30170: Function definition may have uninstantiated body

Richard Smith via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon May 22 13:27:06 PDT 2017


rsmith added a comment.

Do we really need two different notions of "definition" and "odr definition" here? What goes wrong if we always treat the "instantiation of a friend function definition" case as being a definition?



================
Comment at: include/clang/AST/Decl.h:1789
+  //     function is not used yet, but the declaration is considered a
+  //     definition, it does not allow other definition of this function.
+  //   - it does not have a user specified body, but it does not allow
----------------
it -> and


================
Comment at: include/clang/AST/Decl.h:1829-1830
 
+  /// Returns true if the function is defined and other definitions are not
+  /// allowed in the redeclaration chain.
+  ///
----------------
This will not be true in the presence of modules: we will ensure that at most one declaration has a body, but multiple declarations can be instantiated from a defined member function of a class template, for instance. So I think the constraint is that you're not allowed to add *more* such definitions.


================
Comment at: include/clang/AST/Decl.h:1842
+
+  /// Returns true if this declaration is a definition is the sense of ODR
+  /// checks.
----------------
is the sense -> in the sense


================
Comment at: include/clang/AST/Decl.h:1848
+      return true;
+    if (FunctionDecl *Original = getInstantiatedFromMemberFunction())
+      return Original->isOdrDefined();
----------------
I think this will do the wrong thing for an explicit specialization of a member of a class template:

```
template<typename T> struct A { void f() {}; };
template<> void A<int>::f();
```

Here, `A<int>::f()` is "instantiated from a member function" but it's not a definition, not even in the ODR sense. I think it would suffice to also check whether `Original` is a friend declaration here.


================
Comment at: lib/AST/Decl.cpp:2538
+    if (I->isThisDeclarationADefinition()) {
+      Definition = I->IsDeleted ? I->getCanonicalDecl() : I;
+      return true;
----------------
It seems incorrect to me for `isThisDeclarationADefinition()` to return `true` on a redeclaration of a deleted function: only the first declaration should be considered to be a definition in that case. (This special case should be in `isThisDeclarationADefinition()`, not in `isDefined()`.)


================
Comment at: lib/Sema/SemaDecl.cpp:11882
+
+  if (FD == Definition)
+    return;
----------------
This looks wrong to me: `CheckForFunctionRedefinition` is intended to be called *before* marking the function in question as a definition. If you call it afterwards, then the `isOdrDefined` call won't work properly because it will always check to see whether `FD` is a definition before checking any other declaration. So any case that reaches here with `FD` being a definition seems like a bug. I expect we're only getting here in that case due to the missing check for friend in `isThisDeclarationAnOdrDefinition`.


https://reviews.llvm.org/D30170





More information about the cfe-commits mailing list