sepavloff marked 2 inline comments as done.
sepavloff added a comment.

In https://reviews.llvm.org/D30170#761342, @rsmith wrote:
> 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?


It requires 3 additional changes besides update of `isDefined`. All of them 
implement current behavior of the function and look like:

  @@ -3749,7 +3750,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation 
PointOfInstantiation,
                                            bool Recursive,
                                            bool DefinitionRequired,
                                            bool AtEndOfTU) {
  -  if (Function->isInvalidDecl() || Function->isDefined())
  +  const FunctionDecl *Def;
  +  if (Function->isInvalidDecl() || (Function->isDefined(Def) && 
Def->isThisDeclarationADefinition()))
       return;
  
     // Never instantiate an explicit specialization except if it is a class 
scope

It make sense to replace this weird expression `Function->isDefined(Def) && 
Def->isThisDeclarationADefinition()` with a call to a new function, something 
like `isActuallyDefined`. So we anyway have to add a new function for checking 
function definition. In the case of `IsOdrDefinition` the new function is used 
in one place only, modified version of `isDefined` requires changes in 
unrelated code places.

Use of a special variant of `isDefined` dedicated to redefinition checks looks 
less invasive and more robust. If however there are reasons to use modified 
`isDefined`, it also can be implemented, there is nothing wrong with such 
solution.



================
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.
+  ///
----------------
rsmith wrote:
> 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.
Fixed also some comments according to this note.


================
Comment at: include/clang/AST/Decl.h:1848
+      return true;
+    if (FunctionDecl *Original = getInstantiatedFromMemberFunction())
+      return Original->isOdrDefined();
----------------
rsmith wrote:
> 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.
Although this function is not called in this case, its name must agree with its 
functionality, so changed implementation as you recommend.


================
Comment at: lib/AST/Decl.cpp:2538
+    if (I->isThisDeclarationADefinition()) {
+      Definition = I->IsDeleted ? I->getCanonicalDecl() : I;
+      return true;
----------------
rsmith wrote:
> 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()`.)
Indeed, if a declaration was selected to be a definition, it is strange if 
`isThisDeclarationADefinition` returns false for it.


================
Comment at: lib/Sema/SemaDecl.cpp:11882
+
+  if (FD == Definition)
+    return;
----------------
rsmith wrote:
> 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`.
`CheckForFunctionRedefinition` is called after the declaration is put to 
redeclaration chain. At this point the declaration does not have a body, so 
problem may arise only if the provided declaration is an instantiation. It 
happens when the method is called from `PerformPendingInstantiations` -> 
`InstantiateFunctionDefinition` -> `ActOnStartOfFunctionDef` -> 
`CheckForFunctionRedefinition`. In this case function body is generated for 
declaration that is already in redeclaration chain. If the chain is in valid 
state, it does not have duplicate definitions and call to 
`CheckForFunctionRedefinition` is redundant and this check makes shortcut 
return.


https://reviews.llvm.org/D30170



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to